You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by gi...@apache.org on 2018/05/15 14:49:44 UTC

[01/50] hbase-site git commit: Published site at 26babcf013de696b899d76a3c39434b794440d8d.

Repository: hbase-site
Updated Branches:
  refs/heads/asf-site 58454ffaa -> da4482ac2


http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowKeyFilter.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowKeyFilter.html b/testdevapidocs/src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowKeyFilter.html
new file mode 100644
index 0000000..6f38b3f
--- /dev/null
+++ b/testdevapidocs/src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowKeyFilter.html
@@ -0,0 +1,334 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html lang="en">
+<head>
+<title>Source code</title>
+<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
+</head>
+<body>
+<div class="sourceContainer">
+<pre><span class="sourceLineNo">001</span>/**<a name="line.1"></a>
+<span class="sourceLineNo">002</span> * Licensed to the Apache Software Foundation (ASF) under one<a name="line.2"></a>
+<span class="sourceLineNo">003</span> * or more contributor license agreements.  See the NOTICE file<a name="line.3"></a>
+<span class="sourceLineNo">004</span> * distributed with this work for additional information<a name="line.4"></a>
+<span class="sourceLineNo">005</span> * regarding copyright ownership.  The ASF licenses this file<a name="line.5"></a>
+<span class="sourceLineNo">006</span> * to you under the Apache License, Version 2.0 (the<a name="line.6"></a>
+<span class="sourceLineNo">007</span> * "License"); you may not use this file except in compliance<a name="line.7"></a>
+<span class="sourceLineNo">008</span> * with the License.  You may obtain a copy of the License at<a name="line.8"></a>
+<span class="sourceLineNo">009</span> *<a name="line.9"></a>
+<span class="sourceLineNo">010</span> *     http://www.apache.org/licenses/LICENSE-2.0<a name="line.10"></a>
+<span class="sourceLineNo">011</span> *<a name="line.11"></a>
+<span class="sourceLineNo">012</span> * Unless required by applicable law or agreed to in writing, software<a name="line.12"></a>
+<span class="sourceLineNo">013</span> * distributed under the License is distributed on an "AS IS" BASIS,<a name="line.13"></a>
+<span class="sourceLineNo">014</span> * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.<a name="line.14"></a>
+<span class="sourceLineNo">015</span> * See the License for the specific language governing permissions and<a name="line.15"></a>
+<span class="sourceLineNo">016</span> * limitations under the License.<a name="line.16"></a>
+<span class="sourceLineNo">017</span> */<a name="line.17"></a>
+<span class="sourceLineNo">018</span>package org.apache.hadoop.hbase.regionserver;<a name="line.18"></a>
+<span class="sourceLineNo">019</span><a name="line.19"></a>
+<span class="sourceLineNo">020</span>import static org.junit.Assert.assertEquals;<a name="line.20"></a>
+<span class="sourceLineNo">021</span>import static org.junit.Assert.assertFalse;<a name="line.21"></a>
+<span class="sourceLineNo">022</span>import static org.junit.Assert.assertTrue;<a name="line.22"></a>
+<span class="sourceLineNo">023</span><a name="line.23"></a>
+<span class="sourceLineNo">024</span>import java.io.IOException;<a name="line.24"></a>
+<span class="sourceLineNo">025</span>import java.util.ArrayList;<a name="line.25"></a>
+<span class="sourceLineNo">026</span>import java.util.List;<a name="line.26"></a>
+<span class="sourceLineNo">027</span>import java.util.concurrent.ThreadLocalRandom;<a name="line.27"></a>
+<span class="sourceLineNo">028</span>import org.apache.hadoop.hbase.Cell;<a name="line.28"></a>
+<span class="sourceLineNo">029</span>import org.apache.hadoop.hbase.HBaseClassTestRule;<a name="line.29"></a>
+<span class="sourceLineNo">030</span>import org.apache.hadoop.hbase.HBaseTestingUtility;<a name="line.30"></a>
+<span class="sourceLineNo">031</span>import org.apache.hadoop.hbase.TableName;<a name="line.31"></a>
+<span class="sourceLineNo">032</span>import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder;<a name="line.32"></a>
+<span class="sourceLineNo">033</span>import org.apache.hadoop.hbase.client.Put;<a name="line.33"></a>
+<span class="sourceLineNo">034</span>import org.apache.hadoop.hbase.client.Result;<a name="line.34"></a>
+<span class="sourceLineNo">035</span>import org.apache.hadoop.hbase.client.Scan;<a name="line.35"></a>
+<span class="sourceLineNo">036</span>import org.apache.hadoop.hbase.client.TableDescriptorBuilder;<a name="line.36"></a>
+<span class="sourceLineNo">037</span>import org.apache.hadoop.hbase.filter.Filter;<a name="line.37"></a>
+<span class="sourceLineNo">038</span>import org.apache.hadoop.hbase.filter.FilterBase;<a name="line.38"></a>
+<span class="sourceLineNo">039</span>import org.apache.hadoop.hbase.regionserver.HRegion.RegionScannerImpl;<a name="line.39"></a>
+<span class="sourceLineNo">040</span>import org.apache.hadoop.hbase.regionserver.ScannerContext.LimitScope;<a name="line.40"></a>
+<span class="sourceLineNo">041</span>import org.apache.hadoop.hbase.testclassification.MediumTests;<a name="line.41"></a>
+<span class="sourceLineNo">042</span>import org.apache.hadoop.hbase.testclassification.RegionServerTests;<a name="line.42"></a>
+<span class="sourceLineNo">043</span>import org.apache.hadoop.hbase.util.Bytes;<a name="line.43"></a>
+<span class="sourceLineNo">044</span>import org.junit.AfterClass;<a name="line.44"></a>
+<span class="sourceLineNo">045</span>import org.junit.BeforeClass;<a name="line.45"></a>
+<span class="sourceLineNo">046</span>import org.junit.ClassRule;<a name="line.46"></a>
+<span class="sourceLineNo">047</span>import org.junit.Ignore;<a name="line.47"></a>
+<span class="sourceLineNo">048</span>import org.junit.Test;<a name="line.48"></a>
+<span class="sourceLineNo">049</span>import org.junit.experimental.categories.Category;<a name="line.49"></a>
+<span class="sourceLineNo">050</span><a name="line.50"></a>
+<span class="sourceLineNo">051</span>@Category({ RegionServerTests.class, MediumTests.class })<a name="line.51"></a>
+<span class="sourceLineNo">052</span>public class TestSwitchToStreamRead {<a name="line.52"></a>
+<span class="sourceLineNo">053</span><a name="line.53"></a>
+<span class="sourceLineNo">054</span>  @ClassRule<a name="line.54"></a>
+<span class="sourceLineNo">055</span>  public static final HBaseClassTestRule CLASS_RULE =<a name="line.55"></a>
+<span class="sourceLineNo">056</span>    HBaseClassTestRule.forClass(TestSwitchToStreamRead.class);<a name="line.56"></a>
+<span class="sourceLineNo">057</span><a name="line.57"></a>
+<span class="sourceLineNo">058</span>  private static final HBaseTestingUtility UTIL = new HBaseTestingUtility();<a name="line.58"></a>
+<span class="sourceLineNo">059</span><a name="line.59"></a>
+<span class="sourceLineNo">060</span>  private static TableName TABLE_NAME = TableName.valueOf("stream");<a name="line.60"></a>
+<span class="sourceLineNo">061</span><a name="line.61"></a>
+<span class="sourceLineNo">062</span>  private static byte[] FAMILY = Bytes.toBytes("cf");<a name="line.62"></a>
+<span class="sourceLineNo">063</span><a name="line.63"></a>
+<span class="sourceLineNo">064</span>  private static byte[] QUAL = Bytes.toBytes("cq");<a name="line.64"></a>
+<span class="sourceLineNo">065</span><a name="line.65"></a>
+<span class="sourceLineNo">066</span>  private static String VALUE_PREFIX;<a name="line.66"></a>
+<span class="sourceLineNo">067</span><a name="line.67"></a>
+<span class="sourceLineNo">068</span>  private static HRegion REGION;<a name="line.68"></a>
+<span class="sourceLineNo">069</span><a name="line.69"></a>
+<span class="sourceLineNo">070</span>  @BeforeClass<a name="line.70"></a>
+<span class="sourceLineNo">071</span>  public static void setUp() throws IOException {<a name="line.71"></a>
+<span class="sourceLineNo">072</span>    UTIL.getConfiguration().setLong(StoreScanner.STORESCANNER_PREAD_MAX_BYTES, 2048);<a name="line.72"></a>
+<span class="sourceLineNo">073</span>    StringBuilder sb = new StringBuilder(256);<a name="line.73"></a>
+<span class="sourceLineNo">074</span>    for (int i = 0; i &lt; 255; i++) {<a name="line.74"></a>
+<span class="sourceLineNo">075</span>      sb.append((char) ThreadLocalRandom.current().nextInt('A', 'z' + 1));<a name="line.75"></a>
+<span class="sourceLineNo">076</span>    }<a name="line.76"></a>
+<span class="sourceLineNo">077</span>    VALUE_PREFIX = sb.append("-").toString();<a name="line.77"></a>
+<span class="sourceLineNo">078</span>    REGION = UTIL.createLocalHRegion(<a name="line.78"></a>
+<span class="sourceLineNo">079</span>      TableDescriptorBuilder.newBuilder(TABLE_NAME)<a name="line.79"></a>
+<span class="sourceLineNo">080</span>        .setColumnFamily(<a name="line.80"></a>
+<span class="sourceLineNo">081</span>          ColumnFamilyDescriptorBuilder.newBuilder(FAMILY).setBlocksize(1024).build())<a name="line.81"></a>
+<span class="sourceLineNo">082</span>        .build(),<a name="line.82"></a>
+<span class="sourceLineNo">083</span>      null, null);<a name="line.83"></a>
+<span class="sourceLineNo">084</span>    for (int i = 0; i &lt; 900; i++) {<a name="line.84"></a>
+<span class="sourceLineNo">085</span>      REGION<a name="line.85"></a>
+<span class="sourceLineNo">086</span>        .put(new Put(Bytes.toBytes(i)).addColumn(FAMILY, QUAL, Bytes.toBytes(VALUE_PREFIX + i)));<a name="line.86"></a>
+<span class="sourceLineNo">087</span>    }<a name="line.87"></a>
+<span class="sourceLineNo">088</span>    REGION.flush(true);<a name="line.88"></a>
+<span class="sourceLineNo">089</span>    for (int i = 900; i &lt; 1000; i++) {<a name="line.89"></a>
+<span class="sourceLineNo">090</span>      REGION<a name="line.90"></a>
+<span class="sourceLineNo">091</span>        .put(new Put(Bytes.toBytes(i)).addColumn(FAMILY, QUAL, Bytes.toBytes(VALUE_PREFIX + i)));<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>  @AfterClass<a name="line.95"></a>
+<span class="sourceLineNo">096</span>  public static void tearDown() throws IOException {<a name="line.96"></a>
+<span class="sourceLineNo">097</span>    REGION.close(true);<a name="line.97"></a>
+<span class="sourceLineNo">098</span>    UTIL.cleanupTestDir();<a name="line.98"></a>
+<span class="sourceLineNo">099</span>  }<a name="line.99"></a>
+<span class="sourceLineNo">100</span><a name="line.100"></a>
+<span class="sourceLineNo">101</span>  @Test<a name="line.101"></a>
+<span class="sourceLineNo">102</span>  public void test() throws IOException {<a name="line.102"></a>
+<span class="sourceLineNo">103</span>    try (RegionScannerImpl scanner = REGION.getScanner(new Scan())) {<a name="line.103"></a>
+<span class="sourceLineNo">104</span>      StoreScanner storeScanner =<a name="line.104"></a>
+<span class="sourceLineNo">105</span>        (StoreScanner) (scanner).getStoreHeapForTesting().getCurrentForTesting();<a name="line.105"></a>
+<span class="sourceLineNo">106</span>      for (KeyValueScanner kvs : storeScanner.getAllScannersForTesting()) {<a name="line.106"></a>
+<span class="sourceLineNo">107</span>        if (kvs instanceof StoreFileScanner) {<a name="line.107"></a>
+<span class="sourceLineNo">108</span>          StoreFileScanner sfScanner = (StoreFileScanner) kvs;<a name="line.108"></a>
+<span class="sourceLineNo">109</span>          // starting from pread so we use shared reader here.<a name="line.109"></a>
+<span class="sourceLineNo">110</span>          assertTrue(sfScanner.getReader().shared);<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>      List&lt;Cell&gt; cells = new ArrayList&lt;&gt;();<a name="line.113"></a>
+<span class="sourceLineNo">114</span>      for (int i = 0; i &lt; 500; i++) {<a name="line.114"></a>
+<span class="sourceLineNo">115</span>        assertTrue(scanner.next(cells));<a name="line.115"></a>
+<span class="sourceLineNo">116</span>        Result result = Result.create(cells);<a name="line.116"></a>
+<span class="sourceLineNo">117</span>        assertEquals(VALUE_PREFIX + i, Bytes.toString(result.getValue(FAMILY, QUAL)));<a name="line.117"></a>
+<span class="sourceLineNo">118</span>        cells.clear();<a name="line.118"></a>
+<span class="sourceLineNo">119</span>        scanner.shipped();<a name="line.119"></a>
+<span class="sourceLineNo">120</span>      }<a name="line.120"></a>
+<span class="sourceLineNo">121</span>      for (KeyValueScanner kvs : storeScanner.getAllScannersForTesting()) {<a name="line.121"></a>
+<span class="sourceLineNo">122</span>        if (kvs instanceof StoreFileScanner) {<a name="line.122"></a>
+<span class="sourceLineNo">123</span>          StoreFileScanner sfScanner = (StoreFileScanner) kvs;<a name="line.123"></a>
+<span class="sourceLineNo">124</span>          // we should have convert to use stream read now.<a name="line.124"></a>
+<span class="sourceLineNo">125</span>          assertFalse(sfScanner.getReader().shared);<a name="line.125"></a>
+<span class="sourceLineNo">126</span>        }<a name="line.126"></a>
+<span class="sourceLineNo">127</span>      }<a name="line.127"></a>
+<span class="sourceLineNo">128</span>      for (int i = 500; i &lt; 1000; i++) {<a name="line.128"></a>
+<span class="sourceLineNo">129</span>        assertEquals(i != 999, scanner.next(cells));<a name="line.129"></a>
+<span class="sourceLineNo">130</span>        Result result = Result.create(cells);<a name="line.130"></a>
+<span class="sourceLineNo">131</span>        assertEquals(VALUE_PREFIX + i, Bytes.toString(result.getValue(FAMILY, QUAL)));<a name="line.131"></a>
+<span class="sourceLineNo">132</span>        cells.clear();<a name="line.132"></a>
+<span class="sourceLineNo">133</span>        scanner.shipped();<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>    // make sure all scanners are closed.<a name="line.136"></a>
+<span class="sourceLineNo">137</span>    for (HStoreFile sf : REGION.getStore(FAMILY).getStorefiles()) {<a name="line.137"></a>
+<span class="sourceLineNo">138</span>      assertFalse(sf.isReferencedInReads());<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>  public static final class MatchLastRowKeyFilter extends FilterBase {<a name="line.142"></a>
+<span class="sourceLineNo">143</span><a name="line.143"></a>
+<span class="sourceLineNo">144</span>    @Override<a name="line.144"></a>
+<span class="sourceLineNo">145</span>    public boolean filterRowKey(Cell cell) throws IOException {<a name="line.145"></a>
+<span class="sourceLineNo">146</span>      return Bytes.toInt(cell.getRowArray(), cell.getRowOffset()) != 999;<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>  private void testFilter(Filter filter) throws IOException {<a name="line.150"></a>
+<span class="sourceLineNo">151</span>    try (RegionScannerImpl scanner = REGION.getScanner(new Scan().setFilter(filter))) {<a name="line.151"></a>
+<span class="sourceLineNo">152</span>      StoreScanner storeScanner =<a name="line.152"></a>
+<span class="sourceLineNo">153</span>        (StoreScanner) (scanner).getStoreHeapForTesting().getCurrentForTesting();<a name="line.153"></a>
+<span class="sourceLineNo">154</span>      for (KeyValueScanner kvs : storeScanner.getAllScannersForTesting()) {<a name="line.154"></a>
+<span class="sourceLineNo">155</span>        if (kvs instanceof StoreFileScanner) {<a name="line.155"></a>
+<span class="sourceLineNo">156</span>          StoreFileScanner sfScanner = (StoreFileScanner) kvs;<a name="line.156"></a>
+<span class="sourceLineNo">157</span>          // starting from pread so we use shared reader here.<a name="line.157"></a>
+<span class="sourceLineNo">158</span>          assertTrue(sfScanner.getReader().shared);<a name="line.158"></a>
+<span class="sourceLineNo">159</span>        }<a name="line.159"></a>
+<span class="sourceLineNo">160</span>      }<a name="line.160"></a>
+<span class="sourceLineNo">161</span>      List&lt;Cell&gt; cells = new ArrayList&lt;&gt;();<a name="line.161"></a>
+<span class="sourceLineNo">162</span>      // should return before finishing the scan as we want to switch from pread to stream<a name="line.162"></a>
+<span class="sourceLineNo">163</span>      assertTrue(scanner.next(cells,<a name="line.163"></a>
+<span class="sourceLineNo">164</span>        ScannerContext.newBuilder().setTimeLimit(LimitScope.BETWEEN_CELLS, -1).build()));<a name="line.164"></a>
+<span class="sourceLineNo">165</span>      assertTrue(cells.isEmpty());<a name="line.165"></a>
+<span class="sourceLineNo">166</span>      scanner.shipped();<a name="line.166"></a>
+<span class="sourceLineNo">167</span><a name="line.167"></a>
+<span class="sourceLineNo">168</span>      for (KeyValueScanner kvs : storeScanner.getAllScannersForTesting()) {<a name="line.168"></a>
+<span class="sourceLineNo">169</span>        if (kvs instanceof StoreFileScanner) {<a name="line.169"></a>
+<span class="sourceLineNo">170</span>          StoreFileScanner sfScanner = (StoreFileScanner) kvs;<a name="line.170"></a>
+<span class="sourceLineNo">171</span>          // we should have convert to use stream read now.<a name="line.171"></a>
+<span class="sourceLineNo">172</span>          assertFalse(sfScanner.getReader().shared);<a name="line.172"></a>
+<span class="sourceLineNo">173</span>        }<a name="line.173"></a>
+<span class="sourceLineNo">174</span>      }<a name="line.174"></a>
+<span class="sourceLineNo">175</span>      assertFalse(scanner.next(cells,<a name="line.175"></a>
+<span class="sourceLineNo">176</span>        ScannerContext.newBuilder().setTimeLimit(LimitScope.BETWEEN_CELLS, -1).build()));<a name="line.176"></a>
+<span class="sourceLineNo">177</span>      Result result = Result.create(cells);<a name="line.177"></a>
+<span class="sourceLineNo">178</span>      assertEquals(VALUE_PREFIX + 999, Bytes.toString(result.getValue(FAMILY, QUAL)));<a name="line.178"></a>
+<span class="sourceLineNo">179</span>      cells.clear();<a name="line.179"></a>
+<span class="sourceLineNo">180</span>      scanner.shipped();<a name="line.180"></a>
+<span class="sourceLineNo">181</span>    }<a name="line.181"></a>
+<span class="sourceLineNo">182</span>    // make sure all scanners are closed.<a name="line.182"></a>
+<span class="sourceLineNo">183</span>    for (HStoreFile sf : REGION.getStore(FAMILY).getStorefiles()) {<a name="line.183"></a>
+<span class="sourceLineNo">184</span>      assertFalse(sf.isReferencedInReads());<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>  // We use a different logic to implement filterRowKey, where we will keep calling kvHeap.next<a name="line.188"></a>
+<span class="sourceLineNo">189</span>  // until the row key is changed. And there we can only use NoLimitScannerContext so we can not<a name="line.189"></a>
+<span class="sourceLineNo">190</span>  // make the upper layer return immediately. Simply do not use NoLimitScannerContext will lead to<a name="line.190"></a>
+<span class="sourceLineNo">191</span>  // an infinite loop. Need to dig more, the code are way too complicated...<a name="line.191"></a>
+<span class="sourceLineNo">192</span>  @Ignore<a name="line.192"></a>
+<span class="sourceLineNo">193</span>  @Test<a name="line.193"></a>
+<span class="sourceLineNo">194</span>  public void testFilterRowKey() throws IOException {<a name="line.194"></a>
+<span class="sourceLineNo">195</span>    testFilter(new MatchLastRowKeyFilter());<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>  public static final class MatchLastRowCellNextColFilter extends FilterBase {<a name="line.198"></a>
+<span class="sourceLineNo">199</span><a name="line.199"></a>
+<span class="sourceLineNo">200</span>    @Override<a name="line.200"></a>
+<span class="sourceLineNo">201</span>    public ReturnCode filterCell(Cell c) throws IOException {<a name="line.201"></a>
+<span class="sourceLineNo">202</span>      if (Bytes.toInt(c.getRowArray(), c.getRowOffset()) == 999) {<a name="line.202"></a>
+<span class="sourceLineNo">203</span>        return ReturnCode.INCLUDE;<a name="line.203"></a>
+<span class="sourceLineNo">204</span>      } else {<a name="line.204"></a>
+<span class="sourceLineNo">205</span>        return ReturnCode.NEXT_COL;<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>  }<a name="line.208"></a>
+<span class="sourceLineNo">209</span><a name="line.209"></a>
+<span class="sourceLineNo">210</span>  @Test<a name="line.210"></a>
+<span class="sourceLineNo">211</span>  public void testFilterCellNextCol() throws IOException {<a name="line.211"></a>
+<span class="sourceLineNo">212</span>    testFilter(new MatchLastRowCellNextColFilter());<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>  public static final class MatchLastRowCellNextRowFilter extends FilterBase {<a name="line.215"></a>
+<span class="sourceLineNo">216</span><a name="line.216"></a>
+<span class="sourceLineNo">217</span>    @Override<a name="line.217"></a>
+<span class="sourceLineNo">218</span>    public ReturnCode filterCell(Cell c) throws IOException {<a name="line.218"></a>
+<span class="sourceLineNo">219</span>      if (Bytes.toInt(c.getRowArray(), c.getRowOffset()) == 999) {<a name="line.219"></a>
+<span class="sourceLineNo">220</span>        return ReturnCode.INCLUDE;<a name="line.220"></a>
+<span class="sourceLineNo">221</span>      } else {<a name="line.221"></a>
+<span class="sourceLineNo">222</span>        return ReturnCode.NEXT_ROW;<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>  }<a name="line.225"></a>
+<span class="sourceLineNo">226</span><a name="line.226"></a>
+<span class="sourceLineNo">227</span>  @Test<a name="line.227"></a>
+<span class="sourceLineNo">228</span>  public void testFilterCellNextRow() throws IOException {<a name="line.228"></a>
+<span class="sourceLineNo">229</span>    testFilter(new MatchLastRowCellNextRowFilter());<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>  public static final class MatchLastRowFilterRowFilter extends FilterBase {<a name="line.232"></a>
+<span class="sourceLineNo">233</span><a name="line.233"></a>
+<span class="sourceLineNo">234</span>    private boolean exclude;<a name="line.234"></a>
+<span class="sourceLineNo">235</span><a name="line.235"></a>
+<span class="sourceLineNo">236</span>    @Override<a name="line.236"></a>
+<span class="sourceLineNo">237</span>    public void filterRowCells(List&lt;Cell&gt; kvs) throws IOException {<a name="line.237"></a>
+<span class="sourceLineNo">238</span>      Cell c = kvs.get(0);<a name="line.238"></a>
+<span class="sourceLineNo">239</span>      exclude = Bytes.toInt(c.getRowArray(), c.getRowOffset()) != 999;<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>    @Override<a name="line.242"></a>
+<span class="sourceLineNo">243</span>    public void reset() throws IOException {<a name="line.243"></a>
+<span class="sourceLineNo">244</span>      exclude = false;<a name="line.244"></a>
+<span class="sourceLineNo">245</span>    }<a name="line.245"></a>
+<span class="sourceLineNo">246</span><a name="line.246"></a>
+<span class="sourceLineNo">247</span>    @Override<a name="line.247"></a>
+<span class="sourceLineNo">248</span>    public boolean filterRow() throws IOException {<a name="line.248"></a>
+<span class="sourceLineNo">249</span>      return exclude;<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>    @Override<a name="line.252"></a>
+<span class="sourceLineNo">253</span>    public boolean hasFilterRow() {<a name="line.253"></a>
+<span class="sourceLineNo">254</span>      return true;<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>  @Test<a name="line.258"></a>
+<span class="sourceLineNo">259</span>  public void testFilterRow() throws IOException {<a name="line.259"></a>
+<span class="sourceLineNo">260</span>    testFilter(new MatchLastRowFilterRowFilter());<a name="line.260"></a>
+<span class="sourceLineNo">261</span>  }<a name="line.261"></a>
+<span class="sourceLineNo">262</span>}<a name="line.262"></a>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</div>
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html b/testdevapidocs/src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html
index 10b89d4..6f38b3f 100644
--- a/testdevapidocs/src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html
+++ b/testdevapidocs/src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html
@@ -42,107 +42,232 @@
 <span class="sourceLineNo">034</span>import org.apache.hadoop.hbase.client.Result;<a name="line.34"></a>
 <span class="sourceLineNo">035</span>import org.apache.hadoop.hbase.client.Scan;<a name="line.35"></a>
 <span class="sourceLineNo">036</span>import org.apache.hadoop.hbase.client.TableDescriptorBuilder;<a name="line.36"></a>
-<span class="sourceLineNo">037</span>import org.apache.hadoop.hbase.regionserver.HRegion.RegionScannerImpl;<a name="line.37"></a>
-<span class="sourceLineNo">038</span>import org.apache.hadoop.hbase.testclassification.MediumTests;<a name="line.38"></a>
-<span class="sourceLineNo">039</span>import org.apache.hadoop.hbase.testclassification.RegionServerTests;<a name="line.39"></a>
-<span class="sourceLineNo">040</span>import org.apache.hadoop.hbase.util.Bytes;<a name="line.40"></a>
-<span class="sourceLineNo">041</span>import org.junit.AfterClass;<a name="line.41"></a>
-<span class="sourceLineNo">042</span>import org.junit.BeforeClass;<a name="line.42"></a>
-<span class="sourceLineNo">043</span>import org.junit.ClassRule;<a name="line.43"></a>
-<span class="sourceLineNo">044</span>import org.junit.Test;<a name="line.44"></a>
-<span class="sourceLineNo">045</span>import org.junit.experimental.categories.Category;<a name="line.45"></a>
-<span class="sourceLineNo">046</span><a name="line.46"></a>
-<span class="sourceLineNo">047</span>@Category({ RegionServerTests.class, MediumTests.class })<a name="line.47"></a>
-<span class="sourceLineNo">048</span>public class TestSwitchToStreamRead {<a name="line.48"></a>
-<span class="sourceLineNo">049</span><a name="line.49"></a>
-<span class="sourceLineNo">050</span>  @ClassRule<a name="line.50"></a>
-<span class="sourceLineNo">051</span>  public static final HBaseClassTestRule CLASS_RULE =<a name="line.51"></a>
-<span class="sourceLineNo">052</span>      HBaseClassTestRule.forClass(TestSwitchToStreamRead.class);<a name="line.52"></a>
+<span class="sourceLineNo">037</span>import org.apache.hadoop.hbase.filter.Filter;<a name="line.37"></a>
+<span class="sourceLineNo">038</span>import org.apache.hadoop.hbase.filter.FilterBase;<a name="line.38"></a>
+<span class="sourceLineNo">039</span>import org.apache.hadoop.hbase.regionserver.HRegion.RegionScannerImpl;<a name="line.39"></a>
+<span class="sourceLineNo">040</span>import org.apache.hadoop.hbase.regionserver.ScannerContext.LimitScope;<a name="line.40"></a>
+<span class="sourceLineNo">041</span>import org.apache.hadoop.hbase.testclassification.MediumTests;<a name="line.41"></a>
+<span class="sourceLineNo">042</span>import org.apache.hadoop.hbase.testclassification.RegionServerTests;<a name="line.42"></a>
+<span class="sourceLineNo">043</span>import org.apache.hadoop.hbase.util.Bytes;<a name="line.43"></a>
+<span class="sourceLineNo">044</span>import org.junit.AfterClass;<a name="line.44"></a>
+<span class="sourceLineNo">045</span>import org.junit.BeforeClass;<a name="line.45"></a>
+<span class="sourceLineNo">046</span>import org.junit.ClassRule;<a name="line.46"></a>
+<span class="sourceLineNo">047</span>import org.junit.Ignore;<a name="line.47"></a>
+<span class="sourceLineNo">048</span>import org.junit.Test;<a name="line.48"></a>
+<span class="sourceLineNo">049</span>import org.junit.experimental.categories.Category;<a name="line.49"></a>
+<span class="sourceLineNo">050</span><a name="line.50"></a>
+<span class="sourceLineNo">051</span>@Category({ RegionServerTests.class, MediumTests.class })<a name="line.51"></a>
+<span class="sourceLineNo">052</span>public class TestSwitchToStreamRead {<a name="line.52"></a>
 <span class="sourceLineNo">053</span><a name="line.53"></a>
-<span class="sourceLineNo">054</span>  private static final HBaseTestingUtility UTIL = new HBaseTestingUtility();<a name="line.54"></a>
-<span class="sourceLineNo">055</span><a name="line.55"></a>
-<span class="sourceLineNo">056</span>  private static TableName TABLE_NAME = TableName.valueOf("stream");<a name="line.56"></a>
+<span class="sourceLineNo">054</span>  @ClassRule<a name="line.54"></a>
+<span class="sourceLineNo">055</span>  public static final HBaseClassTestRule CLASS_RULE =<a name="line.55"></a>
+<span class="sourceLineNo">056</span>    HBaseClassTestRule.forClass(TestSwitchToStreamRead.class);<a name="line.56"></a>
 <span class="sourceLineNo">057</span><a name="line.57"></a>
-<span class="sourceLineNo">058</span>  private static byte[] FAMILY = Bytes.toBytes("cf");<a name="line.58"></a>
+<span class="sourceLineNo">058</span>  private static final HBaseTestingUtility UTIL = new HBaseTestingUtility();<a name="line.58"></a>
 <span class="sourceLineNo">059</span><a name="line.59"></a>
-<span class="sourceLineNo">060</span>  private static byte[] QUAL = Bytes.toBytes("cq");<a name="line.60"></a>
+<span class="sourceLineNo">060</span>  private static TableName TABLE_NAME = TableName.valueOf("stream");<a name="line.60"></a>
 <span class="sourceLineNo">061</span><a name="line.61"></a>
-<span class="sourceLineNo">062</span>  private static String VALUE_PREFIX;<a name="line.62"></a>
+<span class="sourceLineNo">062</span>  private static byte[] FAMILY = Bytes.toBytes("cf");<a name="line.62"></a>
 <span class="sourceLineNo">063</span><a name="line.63"></a>
-<span class="sourceLineNo">064</span>  private static HRegion REGION;<a name="line.64"></a>
+<span class="sourceLineNo">064</span>  private static byte[] QUAL = Bytes.toBytes("cq");<a name="line.64"></a>
 <span class="sourceLineNo">065</span><a name="line.65"></a>
-<span class="sourceLineNo">066</span>  @BeforeClass<a name="line.66"></a>
-<span class="sourceLineNo">067</span>  public static void setUp() throws IOException {<a name="line.67"></a>
-<span class="sourceLineNo">068</span>    UTIL.getConfiguration().setLong(StoreScanner.STORESCANNER_PREAD_MAX_BYTES, 2048);<a name="line.68"></a>
-<span class="sourceLineNo">069</span>    StringBuilder sb = new StringBuilder(256);<a name="line.69"></a>
-<span class="sourceLineNo">070</span>    for (int i = 0; i &lt; 255; i++) {<a name="line.70"></a>
-<span class="sourceLineNo">071</span>      sb.append((char) ThreadLocalRandom.current().nextInt('A', 'z' + 1));<a name="line.71"></a>
-<span class="sourceLineNo">072</span>    }<a name="line.72"></a>
-<span class="sourceLineNo">073</span>    VALUE_PREFIX = sb.append("-").toString();<a name="line.73"></a>
-<span class="sourceLineNo">074</span>    REGION = UTIL.createLocalHRegion(<a name="line.74"></a>
-<span class="sourceLineNo">075</span>      TableDescriptorBuilder.newBuilder(TABLE_NAME)<a name="line.75"></a>
-<span class="sourceLineNo">076</span>          .setColumnFamily(<a name="line.76"></a>
-<span class="sourceLineNo">077</span>            ColumnFamilyDescriptorBuilder.newBuilder(FAMILY).setBlocksize(1024).build())<a name="line.77"></a>
-<span class="sourceLineNo">078</span>          .build(),<a name="line.78"></a>
-<span class="sourceLineNo">079</span>      null, null);<a name="line.79"></a>
-<span class="sourceLineNo">080</span>    for (int i = 0; i &lt; 900; i++) {<a name="line.80"></a>
-<span class="sourceLineNo">081</span>      REGION<a name="line.81"></a>
-<span class="sourceLineNo">082</span>          .put(new Put(Bytes.toBytes(i)).addColumn(FAMILY, QUAL, Bytes.toBytes(VALUE_PREFIX + i)));<a name="line.82"></a>
-<span class="sourceLineNo">083</span>    }<a name="line.83"></a>
-<span class="sourceLineNo">084</span>    REGION.flush(true);<a name="line.84"></a>
-<span class="sourceLineNo">085</span>    for (int i = 900; i &lt; 1000; i++) {<a name="line.85"></a>
-<span class="sourceLineNo">086</span>      REGION<a name="line.86"></a>
-<span class="sourceLineNo">087</span>          .put(new Put(Bytes.toBytes(i)).addColumn(FAMILY, QUAL, Bytes.toBytes(VALUE_PREFIX + i)));<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><a name="line.90"></a>
-<span class="sourceLineNo">091</span>  @AfterClass<a name="line.91"></a>
-<span class="sourceLineNo">092</span>  public static void tearDown() throws IOException {<a name="line.92"></a>
-<span class="sourceLineNo">093</span>    REGION.close(true);<a name="line.93"></a>
-<span class="sourceLineNo">094</span>    UTIL.cleanupTestDir();<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>  @Test<a name="line.97"></a>
-<span class="sourceLineNo">098</span>  public void test() throws IOException {<a name="line.98"></a>
-<span class="sourceLineNo">099</span>    try (RegionScannerImpl scanner = REGION.getScanner(new Scan())) {<a name="line.99"></a>
-<span class="sourceLineNo">100</span>      StoreScanner storeScanner = (StoreScanner) (scanner)<a name="line.100"></a>
-<span class="sourceLineNo">101</span>          .getStoreHeapForTesting().getCurrentForTesting();<a name="line.101"></a>
-<span class="sourceLineNo">102</span>      for (KeyValueScanner kvs : storeScanner.getAllScannersForTesting()) {<a name="line.102"></a>
-<span class="sourceLineNo">103</span>        if (kvs instanceof StoreFileScanner) {<a name="line.103"></a>
-<span class="sourceLineNo">104</span>          StoreFileScanner sfScanner = (StoreFileScanner) kvs;<a name="line.104"></a>
-<span class="sourceLineNo">105</span>          // starting from pread so we use shared reader here.<a name="line.105"></a>
-<span class="sourceLineNo">106</span>          assertTrue(sfScanner.getReader().shared);<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>      List&lt;Cell&gt; cells = new ArrayList&lt;&gt;();<a name="line.109"></a>
-<span class="sourceLineNo">110</span>      for (int i = 0; i &lt; 500; i++) {<a name="line.110"></a>
-<span class="sourceLineNo">111</span>        assertTrue(scanner.next(cells));<a name="line.111"></a>
-<span class="sourceLineNo">112</span>        Result result = Result.create(cells);<a name="line.112"></a>
-<span class="sourceLineNo">113</span>        assertEquals(VALUE_PREFIX + i, Bytes.toString(result.getValue(FAMILY, QUAL)));<a name="line.113"></a>
-<span class="sourceLineNo">114</span>        cells.clear();<a name="line.114"></a>
-<span class="sourceLineNo">115</span>        scanner.shipped();<a name="line.115"></a>
-<span class="sourceLineNo">116</span>      }<a name="line.116"></a>
-<span class="sourceLineNo">117</span>      for (KeyValueScanner kvs : storeScanner.getAllScannersForTesting()) {<a name="line.117"></a>
-<span class="sourceLineNo">118</span>        if (kvs instanceof StoreFileScanner) {<a name="line.118"></a>
-<span class="sourceLineNo">119</span>          StoreFileScanner sfScanner = (StoreFileScanner) kvs;<a name="line.119"></a>
-<span class="sourceLineNo">120</span>          // we should have convert to use stream read now.<a name="line.120"></a>
-<span class="sourceLineNo">121</span>          assertFalse(sfScanner.getReader().shared);<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>      for (int i = 500; i &lt; 1000; i++) {<a name="line.124"></a>
-<span class="sourceLineNo">125</span>        assertEquals(i != 999, scanner.next(cells));<a name="line.125"></a>
-<span class="sourceLineNo">126</span>        Result result = Result.create(cells);<a name="line.126"></a>
-<span class="sourceLineNo">127</span>        assertEquals(VALUE_PREFIX + i, Bytes.toString(result.getValue(FAMILY, QUAL)));<a name="line.127"></a>
-<span class="sourceLineNo">128</span>        cells.clear();<a name="line.128"></a>
-<span class="sourceLineNo">129</span>        scanner.shipped();<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>    // make sure all scanners are closed.<a name="line.132"></a>
-<span class="sourceLineNo">133</span>    for (HStoreFile sf : REGION.getStore(FAMILY).getStorefiles()) {<a name="line.133"></a>
-<span class="sourceLineNo">134</span>      assertFalse(sf.isReferencedInReads());<a name="line.134"></a>
+<span class="sourceLineNo">066</span>  private static String VALUE_PREFIX;<a name="line.66"></a>
+<span class="sourceLineNo">067</span><a name="line.67"></a>
+<span class="sourceLineNo">068</span>  private static HRegion REGION;<a name="line.68"></a>
+<span class="sourceLineNo">069</span><a name="line.69"></a>
+<span class="sourceLineNo">070</span>  @BeforeClass<a name="line.70"></a>
+<span class="sourceLineNo">071</span>  public static void setUp() throws IOException {<a name="line.71"></a>
+<span class="sourceLineNo">072</span>    UTIL.getConfiguration().setLong(StoreScanner.STORESCANNER_PREAD_MAX_BYTES, 2048);<a name="line.72"></a>
+<span class="sourceLineNo">073</span>    StringBuilder sb = new StringBuilder(256);<a name="line.73"></a>
+<span class="sourceLineNo">074</span>    for (int i = 0; i &lt; 255; i++) {<a name="line.74"></a>
+<span class="sourceLineNo">075</span>      sb.append((char) ThreadLocalRandom.current().nextInt('A', 'z' + 1));<a name="line.75"></a>
+<span class="sourceLineNo">076</span>    }<a name="line.76"></a>
+<span class="sourceLineNo">077</span>    VALUE_PREFIX = sb.append("-").toString();<a name="line.77"></a>
+<span class="sourceLineNo">078</span>    REGION = UTIL.createLocalHRegion(<a name="line.78"></a>
+<span class="sourceLineNo">079</span>      TableDescriptorBuilder.newBuilder(TABLE_NAME)<a name="line.79"></a>
+<span class="sourceLineNo">080</span>        .setColumnFamily(<a name="line.80"></a>
+<span class="sourceLineNo">081</span>          ColumnFamilyDescriptorBuilder.newBuilder(FAMILY).setBlocksize(1024).build())<a name="line.81"></a>
+<span class="sourceLineNo">082</span>        .build(),<a name="line.82"></a>
+<span class="sourceLineNo">083</span>      null, null);<a name="line.83"></a>
+<span class="sourceLineNo">084</span>    for (int i = 0; i &lt; 900; i++) {<a name="line.84"></a>
+<span class="sourceLineNo">085</span>      REGION<a name="line.85"></a>
+<span class="sourceLineNo">086</span>        .put(new Put(Bytes.toBytes(i)).addColumn(FAMILY, QUAL, Bytes.toBytes(VALUE_PREFIX + i)));<a name="line.86"></a>
+<span class="sourceLineNo">087</span>    }<a name="line.87"></a>
+<span class="sourceLineNo">088</span>    REGION.flush(true);<a name="line.88"></a>
+<span class="sourceLineNo">089</span>    for (int i = 900; i &lt; 1000; i++) {<a name="line.89"></a>
+<span class="sourceLineNo">090</span>      REGION<a name="line.90"></a>
+<span class="sourceLineNo">091</span>        .put(new Put(Bytes.toBytes(i)).addColumn(FAMILY, QUAL, Bytes.toBytes(VALUE_PREFIX + i)));<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>  @AfterClass<a name="line.95"></a>
+<span class="sourceLineNo">096</span>  public static void tearDown() throws IOException {<a name="line.96"></a>
+<span class="sourceLineNo">097</span>    REGION.close(true);<a name="line.97"></a>
+<span class="sourceLineNo">098</span>    UTIL.cleanupTestDir();<a name="line.98"></a>
+<span class="sourceLineNo">099</span>  }<a name="line.99"></a>
+<span class="sourceLineNo">100</span><a name="line.100"></a>
+<span class="sourceLineNo">101</span>  @Test<a name="line.101"></a>
+<span class="sourceLineNo">102</span>  public void test() throws IOException {<a name="line.102"></a>
+<span class="sourceLineNo">103</span>    try (RegionScannerImpl scanner = REGION.getScanner(new Scan())) {<a name="line.103"></a>
+<span class="sourceLineNo">104</span>      StoreScanner storeScanner =<a name="line.104"></a>
+<span class="sourceLineNo">105</span>        (StoreScanner) (scanner).getStoreHeapForTesting().getCurrentForTesting();<a name="line.105"></a>
+<span class="sourceLineNo">106</span>      for (KeyValueScanner kvs : storeScanner.getAllScannersForTesting()) {<a name="line.106"></a>
+<span class="sourceLineNo">107</span>        if (kvs instanceof StoreFileScanner) {<a name="line.107"></a>
+<span class="sourceLineNo">108</span>          StoreFileScanner sfScanner = (StoreFileScanner) kvs;<a name="line.108"></a>
+<span class="sourceLineNo">109</span>          // starting from pread so we use shared reader here.<a name="line.109"></a>
+<span class="sourceLineNo">110</span>          assertTrue(sfScanner.getReader().shared);<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>      List&lt;Cell&gt; cells = new ArrayList&lt;&gt;();<a name="line.113"></a>
+<span class="sourceLineNo">114</span>      for (int i = 0; i &lt; 500; i++) {<a name="line.114"></a>
+<span class="sourceLineNo">115</span>        assertTrue(scanner.next(cells));<a name="line.115"></a>
+<span class="sourceLineNo">116</span>        Result result = Result.create(cells);<a name="line.116"></a>
+<span class="sourceLineNo">117</span>        assertEquals(VALUE_PREFIX + i, Bytes.toString(result.getValue(FAMILY, QUAL)));<a name="line.117"></a>
+<span class="sourceLineNo">118</span>        cells.clear();<a name="line.118"></a>
+<span class="sourceLineNo">119</span>        scanner.shipped();<a name="line.119"></a>
+<span class="sourceLineNo">120</span>      }<a name="line.120"></a>
+<span class="sourceLineNo">121</span>      for (KeyValueScanner kvs : storeScanner.getAllScannersForTesting()) {<a name="line.121"></a>
+<span class="sourceLineNo">122</span>        if (kvs instanceof StoreFileScanner) {<a name="line.122"></a>
+<span class="sourceLineNo">123</span>          StoreFileScanner sfScanner = (StoreFileScanner) kvs;<a name="line.123"></a>
+<span class="sourceLineNo">124</span>          // we should have convert to use stream read now.<a name="line.124"></a>
+<span class="sourceLineNo">125</span>          assertFalse(sfScanner.getReader().shared);<a name="line.125"></a>
+<span class="sourceLineNo">126</span>        }<a name="line.126"></a>
+<span class="sourceLineNo">127</span>      }<a name="line.127"></a>
+<span class="sourceLineNo">128</span>      for (int i = 500; i &lt; 1000; i++) {<a name="line.128"></a>
+<span class="sourceLineNo">129</span>        assertEquals(i != 999, scanner.next(cells));<a name="line.129"></a>
+<span class="sourceLineNo">130</span>        Result result = Result.create(cells);<a name="line.130"></a>
+<span class="sourceLineNo">131</span>        assertEquals(VALUE_PREFIX + i, Bytes.toString(result.getValue(FAMILY, QUAL)));<a name="line.131"></a>
+<span class="sourceLineNo">132</span>        cells.clear();<a name="line.132"></a>
+<span class="sourceLineNo">133</span>        scanner.shipped();<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>}<a name="line.137"></a>
+<span class="sourceLineNo">136</span>    // make sure all scanners are closed.<a name="line.136"></a>
+<span class="sourceLineNo">137</span>    for (HStoreFile sf : REGION.getStore(FAMILY).getStorefiles()) {<a name="line.137"></a>
+<span class="sourceLineNo">138</span>      assertFalse(sf.isReferencedInReads());<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>  public static final class MatchLastRowKeyFilter extends FilterBase {<a name="line.142"></a>
+<span class="sourceLineNo">143</span><a name="line.143"></a>
+<span class="sourceLineNo">144</span>    @Override<a name="line.144"></a>
+<span class="sourceLineNo">145</span>    public boolean filterRowKey(Cell cell) throws IOException {<a name="line.145"></a>
+<span class="sourceLineNo">146</span>      return Bytes.toInt(cell.getRowArray(), cell.getRowOffset()) != 999;<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>  private void testFilter(Filter filter) throws IOException {<a name="line.150"></a>
+<span class="sourceLineNo">151</span>    try (RegionScannerImpl scanner = REGION.getScanner(new Scan().setFilter(filter))) {<a name="line.151"></a>
+<span class="sourceLineNo">152</span>      StoreScanner storeScanner =<a name="line.152"></a>
+<span class="sourceLineNo">153</span>        (StoreScanner) (scanner).getStoreHeapForTesting().getCurrentForTesting();<a name="line.153"></a>
+<span class="sourceLineNo">154</span>      for (KeyValueScanner kvs : storeScanner.getAllScannersForTesting()) {<a name="line.154"></a>
+<span class="sourceLineNo">155</span>        if (kvs instanceof StoreFileScanner) {<a name="line.155"></a>
+<span class="sourceLineNo">156</span>          StoreFileScanner sfScanner = (StoreFileScanner) kvs;<a name="line.156"></a>
+<span class="sourceLineNo">157</span>          // starting from pread so we use shared reader here.<a name="line.157"></a>
+<span class="sourceLineNo">158</span>          assertTrue(sfScanner.getReader().shared);<a name="line.158"></a>
+<span class="sourceLineNo">159</span>        }<a name="line.159"></a>
+<span class="sourceLineNo">160</span>      }<a name="line.160"></a>
+<span class="sourceLineNo">161</span>      List&lt;Cell&gt; cells = new ArrayList&lt;&gt;();<a name="line.161"></a>
+<span class="sourceLineNo">162</span>      // should return before finishing the scan as we want to switch from pread to stream<a name="line.162"></a>
+<span class="sourceLineNo">163</span>      assertTrue(scanner.next(cells,<a name="line.163"></a>
+<span class="sourceLineNo">164</span>        ScannerContext.newBuilder().setTimeLimit(LimitScope.BETWEEN_CELLS, -1).build()));<a name="line.164"></a>
+<span class="sourceLineNo">165</span>      assertTrue(cells.isEmpty());<a name="line.165"></a>
+<span class="sourceLineNo">166</span>      scanner.shipped();<a name="line.166"></a>
+<span class="sourceLineNo">167</span><a name="line.167"></a>
+<span class="sourceLineNo">168</span>      for (KeyValueScanner kvs : storeScanner.getAllScannersForTesting()) {<a name="line.168"></a>
+<span class="sourceLineNo">169</span>        if (kvs instanceof StoreFileScanner) {<a name="line.169"></a>
+<span class="sourceLineNo">170</span>          StoreFileScanner sfScanner = (StoreFileScanner) kvs;<a name="line.170"></a>
+<span class="sourceLineNo">171</span>          // we should have convert to use stream read now.<a name="line.171"></a>
+<span class="sourceLineNo">172</span>          assertFalse(sfScanner.getReader().shared);<a name="line.172"></a>
+<span class="sourceLineNo">173</span>        }<a name="line.173"></a>
+<span class="sourceLineNo">174</span>      }<a name="line.174"></a>
+<span class="sourceLineNo">175</span>      assertFalse(scanner.next(cells,<a name="line.175"></a>
+<span class="sourceLineNo">176</span>        ScannerContext.newBuilder().setTimeLimit(LimitScope.BETWEEN_CELLS, -1).build()));<a name="line.176"></a>
+<span class="sourceLineNo">177</span>      Result result = Result.create(cells);<a name="line.177"></a>
+<span class="sourceLineNo">178</span>      assertEquals(VALUE_PREFIX + 999, Bytes.toString(result.getValue(FAMILY, QUAL)));<a name="line.178"></a>
+<span class="sourceLineNo">179</span>      cells.clear();<a name="line.179"></a>
+<span class="sourceLineNo">180</span>      scanner.shipped();<a name="line.180"></a>
+<span class="sourceLineNo">181</span>    }<a name="line.181"></a>
+<span class="sourceLineNo">182</span>    // make sure all scanners are closed.<a name="line.182"></a>
+<span class="sourceLineNo">183</span>    for (HStoreFile sf : REGION.getStore(FAMILY).getStorefiles()) {<a name="line.183"></a>
+<span class="sourceLineNo">184</span>      assertFalse(sf.isReferencedInReads());<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>  // We use a different logic to implement filterRowKey, where we will keep calling kvHeap.next<a name="line.188"></a>
+<span class="sourceLineNo">189</span>  // until the row key is changed. And there we can only use NoLimitScannerContext so we can not<a name="line.189"></a>
+<span class="sourceLineNo">190</span>  // make the upper layer return immediately. Simply do not use NoLimitScannerContext will lead to<a name="line.190"></a>
+<span class="sourceLineNo">191</span>  // an infinite loop. Need to dig more, the code are way too complicated...<a name="line.191"></a>
+<span class="sourceLineNo">192</span>  @Ignore<a name="line.192"></a>
+<span class="sourceLineNo">193</span>  @Test<a name="line.193"></a>
+<span class="sourceLineNo">194</span>  public void testFilterRowKey() throws IOException {<a name="line.194"></a>
+<span class="sourceLineNo">195</span>    testFilter(new MatchLastRowKeyFilter());<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>  public static final class MatchLastRowCellNextColFilter extends FilterBase {<a name="line.198"></a>
+<span class="sourceLineNo">199</span><a name="line.199"></a>
+<span class="sourceLineNo">200</span>    @Override<a name="line.200"></a>
+<span class="sourceLineNo">201</span>    public ReturnCode filterCell(Cell c) throws IOException {<a name="line.201"></a>
+<span class="sourceLineNo">202</span>      if (Bytes.toInt(c.getRowArray(), c.getRowOffset()) == 999) {<a name="line.202"></a>
+<span class="sourceLineNo">203</span>        return ReturnCode.INCLUDE;<a name="line.203"></a>
+<span class="sourceLineNo">204</span>      } else {<a name="line.204"></a>
+<span class="sourceLineNo">205</span>        return ReturnCode.NEXT_COL;<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>  }<a name="line.208"></a>
+<span class="sourceLineNo">209</span><a name="line.209"></a>
+<span class="sourceLineNo">210</span>  @Test<a name="line.210"></a>
+<span class="sourceLineNo">211</span>  public void testFilterCellNextCol() throws IOException {<a name="line.211"></a>
+<span class="sourceLineNo">212</span>    testFilter(new MatchLastRowCellNextColFilter());<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>  public static final class MatchLastRowCellNextRowFilter extends FilterBase {<a name="line.215"></a>
+<span class="sourceLineNo">216</span><a name="line.216"></a>
+<span class="sourceLineNo">217</span>    @Override<a name="line.217"></a>
+<span class="sourceLineNo">218</span>    public ReturnCode filterCell(Cell c) throws IOException {<a name="line.218"></a>
+<span class="sourceLineNo">219</span>      if (Bytes.toInt(c.getRowArray(), c.getRowOffset()) == 999) {<a name="line.219"></a>
+<span class="sourceLineNo">220</span>        return ReturnCode.INCLUDE;<a name="line.220"></a>
+<span class="sourceLineNo">221</span>      } else {<a name="line.221"></a>
+<span class="sourceLineNo">222</span>        return ReturnCode.NEXT_ROW;<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>  }<a name="line.225"></a>
+<span class="sourceLineNo">226</span><a name="line.226"></a>
+<span class="sourceLineNo">227</span>  @Test<a name="line.227"></a>
+<span class="sourceLineNo">228</span>  public void testFilterCellNextRow() throws IOException {<a name="line.228"></a>
+<span class="sourceLineNo">229</span>    testFilter(new MatchLastRowCellNextRowFilter());<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>  public static final class MatchLastRowFilterRowFilter extends FilterBase {<a name="line.232"></a>
+<span class="sourceLineNo">233</span><a name="line.233"></a>
+<span class="sourceLineNo">234</span>    private boolean exclude;<a name="line.234"></a>
+<span class="sourceLineNo">235</span><a name="line.235"></a>
+<span class="sourceLineNo">236</span>    @Override<a name="line.236"></a>
+<span class="sourceLineNo">237</span>    public void filterRowCells(List&lt;Cell&gt; kvs) throws IOException {<a name="line.237"></a>
+<span class="sourceLineNo">238</span>      Cell c = kvs.get(0);<a name="line.238"></a>
+<span class="sourceLineNo">239</span>      exclude = Bytes.toInt(c.getRowArray(), c.getRowOffset()) != 999;<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>    @Override<a name="line.242"></a>
+<span class="sourceLineNo">243</span>    public void reset() throws IOException {<a name="line.243"></a>
+<span class="sourceLineNo">244</span>      exclude = false;<a name="line.244"></a>
+<span class="sourceLineNo">245</span>    }<a name="line.245"></a>
+<span class="sourceLineNo">246</span><a name="line.246"></a>
+<span class="sourceLineNo">247</span>    @Override<a name="line.247"></a>
+<span class="sourceLineNo">248</span>    public boolean filterRow() throws IOException {<a name="line.248"></a>
+<span class="sourceLineNo">249</span>      return exclude;<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>    @Override<a name="line.252"></a>
+<span class="sourceLineNo">253</span>    public boolean hasFilterRow() {<a name="line.253"></a>
+<span class="sourceLineNo">254</span>      return true;<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>  @Test<a name="line.258"></a>
+<span class="sourceLineNo">259</span>  public void testFilterRow() throws IOException {<a name="line.259"></a>
+<span class="sourceLineNo">260</span>    testFilter(new MatchLastRowFilterRowFilter());<a name="line.260"></a>
+<span class="sourceLineNo">261</span>  }<a name="line.261"></a>
+<span class="sourceLineNo">262</span>}<a name="line.262"></a>
 
 
 

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/src-html/org/apache/hadoop/hbase/rsgroup/TestEnableRSGroup.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/src-html/org/apache/hadoop/hbase/rsgroup/TestEnableRSGroup.html b/testdevapidocs/src-html/org/apache/hadoop/hbase/rsgroup/TestEnableRSGroup.html
index 68328a9..e5cc360 100644
--- a/testdevapidocs/src-html/org/apache/hadoop/hbase/rsgroup/TestEnableRSGroup.html
+++ b/testdevapidocs/src-html/org/apache/hadoop/hbase/rsgroup/TestEnableRSGroup.html
@@ -77,7 +77,7 @@
 <span class="sourceLineNo">069</span>    TEST_UTIL.getMiniHBaseCluster().waitOnMaster(0);<a name="line.69"></a>
 <span class="sourceLineNo">070</span><a name="line.70"></a>
 <span class="sourceLineNo">071</span>    LOG.info("stopped master...");<a name="line.71"></a>
-<span class="sourceLineNo">072</span>    final Configuration conf = TEST_UTIL.getConfiguration();<a name="line.72"></a>
+<span class="sourceLineNo">072</span>    final Configuration conf = TEST_UTIL.getMiniHBaseCluster().getConfiguration();<a name="line.72"></a>
 <span class="sourceLineNo">073</span>    conf.set(CoprocessorHost.MASTER_COPROCESSOR_CONF_KEY, RSGroupAdminEndpoint.class.getName());<a name="line.73"></a>
 <span class="sourceLineNo">074</span>    conf.set(HConstants.HBASE_MASTER_LOADBALANCER_CLASS, RSGroupBasedLoadBalancer.class.getName());<a name="line.74"></a>
 <span class="sourceLineNo">075</span><a name="line.75"></a>


[04/50] hbase-site git commit: Published site at 26babcf013de696b899d76a3c39434b794440d8d.

Posted by gi...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.MockedBucketCache.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.MockedBucketCache.html b/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.MockedBucketCache.html
index dd58cd9..01157c1 100644
--- a/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.MockedBucketCache.html
+++ b/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.MockedBucketCache.html
@@ -27,394 +27,433 @@
 <span class="sourceLineNo">019</span><a name="line.19"></a>
 <span class="sourceLineNo">020</span>import static org.junit.Assert.assertEquals;<a name="line.20"></a>
 <span class="sourceLineNo">021</span>import static org.junit.Assert.assertFalse;<a name="line.21"></a>
-<span class="sourceLineNo">022</span>import static org.junit.Assert.assertTrue;<a name="line.22"></a>
-<span class="sourceLineNo">023</span><a name="line.23"></a>
-<span class="sourceLineNo">024</span>import java.io.FileNotFoundException;<a name="line.24"></a>
-<span class="sourceLineNo">025</span>import java.io.IOException;<a name="line.25"></a>
-<span class="sourceLineNo">026</span>import java.util.ArrayList;<a name="line.26"></a>
-<span class="sourceLineNo">027</span>import java.util.Arrays;<a name="line.27"></a>
-<span class="sourceLineNo">028</span>import java.util.List;<a name="line.28"></a>
-<span class="sourceLineNo">029</span>import java.util.Map;<a name="line.29"></a>
-<span class="sourceLineNo">030</span>import java.util.Random;<a name="line.30"></a>
-<span class="sourceLineNo">031</span>import java.util.Set;<a name="line.31"></a>
-<span class="sourceLineNo">032</span>import java.util.concurrent.locks.ReentrantReadWriteLock;<a name="line.32"></a>
-<span class="sourceLineNo">033</span>import org.apache.hadoop.conf.Configuration;<a name="line.33"></a>
-<span class="sourceLineNo">034</span>import org.apache.hadoop.fs.Path;<a name="line.34"></a>
-<span class="sourceLineNo">035</span>import org.apache.hadoop.hbase.HBaseClassTestRule;<a name="line.35"></a>
-<span class="sourceLineNo">036</span>import org.apache.hadoop.hbase.HBaseConfiguration;<a name="line.36"></a>
-<span class="sourceLineNo">037</span>import org.apache.hadoop.hbase.HBaseTestingUtility;<a name="line.37"></a>
-<span class="sourceLineNo">038</span>import org.apache.hadoop.hbase.io.hfile.BlockCacheKey;<a name="line.38"></a>
-<span class="sourceLineNo">039</span>import org.apache.hadoop.hbase.io.hfile.CacheTestUtils;<a name="line.39"></a>
-<span class="sourceLineNo">040</span>import org.apache.hadoop.hbase.io.hfile.CacheTestUtils.HFileBlockPair;<a name="line.40"></a>
-<span class="sourceLineNo">041</span>import org.apache.hadoop.hbase.io.hfile.Cacheable;<a name="line.41"></a>
-<span class="sourceLineNo">042</span>import org.apache.hadoop.hbase.io.hfile.bucket.BucketAllocator.BucketSizeInfo;<a name="line.42"></a>
-<span class="sourceLineNo">043</span>import org.apache.hadoop.hbase.io.hfile.bucket.BucketAllocator.IndexStatistics;<a name="line.43"></a>
-<span class="sourceLineNo">044</span>import org.apache.hadoop.hbase.testclassification.IOTests;<a name="line.44"></a>
-<span class="sourceLineNo">045</span>import org.apache.hadoop.hbase.testclassification.MediumTests;<a name="line.45"></a>
-<span class="sourceLineNo">046</span>import org.junit.After;<a name="line.46"></a>
-<span class="sourceLineNo">047</span>import org.junit.Before;<a name="line.47"></a>
-<span class="sourceLineNo">048</span>import org.junit.ClassRule;<a name="line.48"></a>
-<span class="sourceLineNo">049</span>import org.junit.Test;<a name="line.49"></a>
-<span class="sourceLineNo">050</span>import org.junit.experimental.categories.Category;<a name="line.50"></a>
-<span class="sourceLineNo">051</span>import org.junit.runner.RunWith;<a name="line.51"></a>
-<span class="sourceLineNo">052</span>import org.junit.runners.Parameterized;<a name="line.52"></a>
-<span class="sourceLineNo">053</span><a name="line.53"></a>
-<span class="sourceLineNo">054</span>import org.apache.hbase.thirdparty.com.google.common.collect.ImmutableMap;<a name="line.54"></a>
-<span class="sourceLineNo">055</span><a name="line.55"></a>
-<span class="sourceLineNo">056</span>/**<a name="line.56"></a>
-<span class="sourceLineNo">057</span> * Basic test of BucketCache.Puts and gets.<a name="line.57"></a>
-<span class="sourceLineNo">058</span> * &lt;p&gt;<a name="line.58"></a>
-<span class="sourceLineNo">059</span> * Tests will ensure that blocks' data correctness under several threads concurrency<a name="line.59"></a>
-<span class="sourceLineNo">060</span> */<a name="line.60"></a>
-<span class="sourceLineNo">061</span>@RunWith(Parameterized.class)<a name="line.61"></a>
-<span class="sourceLineNo">062</span>@Category({ IOTests.class, MediumTests.class })<a name="line.62"></a>
-<span class="sourceLineNo">063</span>public class TestBucketCache {<a name="line.63"></a>
-<span class="sourceLineNo">064</span><a name="line.64"></a>
-<span class="sourceLineNo">065</span>  @ClassRule<a name="line.65"></a>
-<span class="sourceLineNo">066</span>  public static final HBaseClassTestRule CLASS_RULE =<a name="line.66"></a>
-<span class="sourceLineNo">067</span>      HBaseClassTestRule.forClass(TestBucketCache.class);<a name="line.67"></a>
-<span class="sourceLineNo">068</span><a name="line.68"></a>
-<span class="sourceLineNo">069</span>  private static final Random RAND = new Random();<a name="line.69"></a>
-<span class="sourceLineNo">070</span><a name="line.70"></a>
-<span class="sourceLineNo">071</span>  @Parameterized.Parameters(name = "{index}: blockSize={0}, bucketSizes={1}")<a name="line.71"></a>
-<span class="sourceLineNo">072</span>  public static Iterable&lt;Object[]&gt; data() {<a name="line.72"></a>
-<span class="sourceLineNo">073</span>    return Arrays.asList(new Object[][] {<a name="line.73"></a>
-<span class="sourceLineNo">074</span>        { 8192, null }, // TODO: why is 8k the default blocksize for these tests?<a name="line.74"></a>
-<span class="sourceLineNo">075</span>        {<a name="line.75"></a>
-<span class="sourceLineNo">076</span>            16 * 1024,<a name="line.76"></a>
-<span class="sourceLineNo">077</span>            new int[] { 2 * 1024 + 1024, 4 * 1024 + 1024, 8 * 1024 + 1024, 16 * 1024 + 1024,<a name="line.77"></a>
-<span class="sourceLineNo">078</span>                28 * 1024 + 1024, 32 * 1024 + 1024, 64 * 1024 + 1024, 96 * 1024 + 1024,<a name="line.78"></a>
-<span class="sourceLineNo">079</span>                128 * 1024 + 1024 } } });<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>  @Parameterized.Parameter(0)<a name="line.82"></a>
-<span class="sourceLineNo">083</span>  public int constructedBlockSize;<a name="line.83"></a>
-<span class="sourceLineNo">084</span><a name="line.84"></a>
-<span class="sourceLineNo">085</span>  @Parameterized.Parameter(1)<a name="line.85"></a>
-<span class="sourceLineNo">086</span>  public int[] constructedBlockSizes;<a name="line.86"></a>
-<span class="sourceLineNo">087</span><a name="line.87"></a>
-<span class="sourceLineNo">088</span>  BucketCache cache;<a name="line.88"></a>
-<span class="sourceLineNo">089</span>  final int CACHE_SIZE = 1000000;<a name="line.89"></a>
-<span class="sourceLineNo">090</span>  final int NUM_BLOCKS = 100;<a name="line.90"></a>
-<span class="sourceLineNo">091</span>  final int BLOCK_SIZE = CACHE_SIZE / NUM_BLOCKS;<a name="line.91"></a>
-<span class="sourceLineNo">092</span>  final int NUM_THREADS = 100;<a name="line.92"></a>
-<span class="sourceLineNo">093</span>  final int NUM_QUERIES = 10000;<a name="line.93"></a>
+<span class="sourceLineNo">022</span>import static org.junit.Assert.assertNull;<a name="line.22"></a>
+<span class="sourceLineNo">023</span>import static org.junit.Assert.assertTrue;<a name="line.23"></a>
+<span class="sourceLineNo">024</span><a name="line.24"></a>
+<span class="sourceLineNo">025</span>import java.io.FileNotFoundException;<a name="line.25"></a>
+<span class="sourceLineNo">026</span>import java.io.IOException;<a name="line.26"></a>
+<span class="sourceLineNo">027</span>import java.nio.ByteBuffer;<a name="line.27"></a>
+<span class="sourceLineNo">028</span>import java.util.ArrayList;<a name="line.28"></a>
+<span class="sourceLineNo">029</span>import java.util.Arrays;<a name="line.29"></a>
+<span class="sourceLineNo">030</span>import java.util.List;<a name="line.30"></a>
+<span class="sourceLineNo">031</span>import java.util.Map;<a name="line.31"></a>
+<span class="sourceLineNo">032</span>import java.util.Random;<a name="line.32"></a>
+<span class="sourceLineNo">033</span>import java.util.Set;<a name="line.33"></a>
+<span class="sourceLineNo">034</span>import java.util.concurrent.locks.ReentrantReadWriteLock;<a name="line.34"></a>
+<span class="sourceLineNo">035</span>import org.apache.hadoop.conf.Configuration;<a name="line.35"></a>
+<span class="sourceLineNo">036</span>import org.apache.hadoop.fs.Path;<a name="line.36"></a>
+<span class="sourceLineNo">037</span>import org.apache.hadoop.hbase.HBaseClassTestRule;<a name="line.37"></a>
+<span class="sourceLineNo">038</span>import org.apache.hadoop.hbase.HBaseConfiguration;<a name="line.38"></a>
+<span class="sourceLineNo">039</span>import org.apache.hadoop.hbase.HBaseTestingUtility;<a name="line.39"></a>
+<span class="sourceLineNo">040</span>import org.apache.hadoop.hbase.HConstants;<a name="line.40"></a>
+<span class="sourceLineNo">041</span>import org.apache.hadoop.hbase.io.hfile.BlockCacheKey;<a name="line.41"></a>
+<span class="sourceLineNo">042</span>import org.apache.hadoop.hbase.io.hfile.BlockType;<a name="line.42"></a>
+<span class="sourceLineNo">043</span>import org.apache.hadoop.hbase.io.hfile.CacheTestUtils;<a name="line.43"></a>
+<span class="sourceLineNo">044</span>import org.apache.hadoop.hbase.io.hfile.CacheTestUtils.HFileBlockPair;<a name="line.44"></a>
+<span class="sourceLineNo">045</span>import org.apache.hadoop.hbase.io.hfile.Cacheable;<a name="line.45"></a>
+<span class="sourceLineNo">046</span>import org.apache.hadoop.hbase.io.hfile.HFileBlock;<a name="line.46"></a>
+<span class="sourceLineNo">047</span>import org.apache.hadoop.hbase.io.hfile.HFileContext;<a name="line.47"></a>
+<span class="sourceLineNo">048</span>import org.apache.hadoop.hbase.io.hfile.HFileContextBuilder;<a name="line.48"></a>
+<span class="sourceLineNo">049</span>import org.apache.hadoop.hbase.io.hfile.bucket.BucketAllocator.BucketSizeInfo;<a name="line.49"></a>
+<span class="sourceLineNo">050</span>import org.apache.hadoop.hbase.io.hfile.bucket.BucketAllocator.IndexStatistics;<a name="line.50"></a>
+<span class="sourceLineNo">051</span>import org.apache.hadoop.hbase.testclassification.IOTests;<a name="line.51"></a>
+<span class="sourceLineNo">052</span>import org.apache.hadoop.hbase.testclassification.MediumTests;<a name="line.52"></a>
+<span class="sourceLineNo">053</span>import org.junit.After;<a name="line.53"></a>
+<span class="sourceLineNo">054</span>import org.junit.Before;<a name="line.54"></a>
+<span class="sourceLineNo">055</span>import org.junit.ClassRule;<a name="line.55"></a>
+<span class="sourceLineNo">056</span>import org.junit.Test;<a name="line.56"></a>
+<span class="sourceLineNo">057</span>import org.junit.experimental.categories.Category;<a name="line.57"></a>
+<span class="sourceLineNo">058</span>import org.junit.runner.RunWith;<a name="line.58"></a>
+<span class="sourceLineNo">059</span>import org.junit.runners.Parameterized;<a name="line.59"></a>
+<span class="sourceLineNo">060</span><a name="line.60"></a>
+<span class="sourceLineNo">061</span>import org.apache.hbase.thirdparty.com.google.common.collect.ImmutableMap;<a name="line.61"></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> * Basic test of BucketCache.Puts and gets.<a name="line.64"></a>
+<span class="sourceLineNo">065</span> * &lt;p&gt;<a name="line.65"></a>
+<span class="sourceLineNo">066</span> * Tests will ensure that blocks' data correctness under several threads concurrency<a name="line.66"></a>
+<span class="sourceLineNo">067</span> */<a name="line.67"></a>
+<span class="sourceLineNo">068</span>@RunWith(Parameterized.class)<a name="line.68"></a>
+<span class="sourceLineNo">069</span>@Category({ IOTests.class, MediumTests.class })<a name="line.69"></a>
+<span class="sourceLineNo">070</span>public class TestBucketCache {<a name="line.70"></a>
+<span class="sourceLineNo">071</span><a name="line.71"></a>
+<span class="sourceLineNo">072</span>  @ClassRule<a name="line.72"></a>
+<span class="sourceLineNo">073</span>  public static final HBaseClassTestRule CLASS_RULE =<a name="line.73"></a>
+<span class="sourceLineNo">074</span>      HBaseClassTestRule.forClass(TestBucketCache.class);<a name="line.74"></a>
+<span class="sourceLineNo">075</span><a name="line.75"></a>
+<span class="sourceLineNo">076</span>  private static final Random RAND = new Random();<a name="line.76"></a>
+<span class="sourceLineNo">077</span><a name="line.77"></a>
+<span class="sourceLineNo">078</span>  @Parameterized.Parameters(name = "{index}: blockSize={0}, bucketSizes={1}")<a name="line.78"></a>
+<span class="sourceLineNo">079</span>  public static Iterable&lt;Object[]&gt; data() {<a name="line.79"></a>
+<span class="sourceLineNo">080</span>    return Arrays.asList(new Object[][] {<a name="line.80"></a>
+<span class="sourceLineNo">081</span>        { 8192, null }, // TODO: why is 8k the default blocksize for these tests?<a name="line.81"></a>
+<span class="sourceLineNo">082</span>        {<a name="line.82"></a>
+<span class="sourceLineNo">083</span>            16 * 1024,<a name="line.83"></a>
+<span class="sourceLineNo">084</span>            new int[] { 2 * 1024 + 1024, 4 * 1024 + 1024, 8 * 1024 + 1024, 16 * 1024 + 1024,<a name="line.84"></a>
+<span class="sourceLineNo">085</span>                28 * 1024 + 1024, 32 * 1024 + 1024, 64 * 1024 + 1024, 96 * 1024 + 1024,<a name="line.85"></a>
+<span class="sourceLineNo">086</span>                128 * 1024 + 1024 } } });<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>  @Parameterized.Parameter(0)<a name="line.89"></a>
+<span class="sourceLineNo">090</span>  public int constructedBlockSize;<a name="line.90"></a>
+<span class="sourceLineNo">091</span><a name="line.91"></a>
+<span class="sourceLineNo">092</span>  @Parameterized.Parameter(1)<a name="line.92"></a>
+<span class="sourceLineNo">093</span>  public int[] constructedBlockSizes;<a name="line.93"></a>
 <span class="sourceLineNo">094</span><a name="line.94"></a>
-<span class="sourceLineNo">095</span>  final long capacitySize = 32 * 1024 * 1024;<a name="line.95"></a>
-<span class="sourceLineNo">096</span>  final int writeThreads = BucketCache.DEFAULT_WRITER_THREADS;<a name="line.96"></a>
-<span class="sourceLineNo">097</span>  final int writerQLen = BucketCache.DEFAULT_WRITER_QUEUE_ITEMS;<a name="line.97"></a>
-<span class="sourceLineNo">098</span>  String ioEngineName = "offheap";<a name="line.98"></a>
-<span class="sourceLineNo">099</span>  String persistencePath = null;<a name="line.99"></a>
-<span class="sourceLineNo">100</span><a name="line.100"></a>
-<span class="sourceLineNo">101</span>  private static class MockedBucketCache extends BucketCache {<a name="line.101"></a>
-<span class="sourceLineNo">102</span><a name="line.102"></a>
-<span class="sourceLineNo">103</span>    public MockedBucketCache(String ioEngineName, long capacity, int blockSize, int[] bucketSizes,<a name="line.103"></a>
-<span class="sourceLineNo">104</span>        int writerThreads, int writerQLen, String persistencePath) throws FileNotFoundException,<a name="line.104"></a>
-<span class="sourceLineNo">105</span>        IOException {<a name="line.105"></a>
-<span class="sourceLineNo">106</span>      super(ioEngineName, capacity, blockSize, bucketSizes, writerThreads, writerQLen,<a name="line.106"></a>
-<span class="sourceLineNo">107</span>          persistencePath);<a name="line.107"></a>
-<span class="sourceLineNo">108</span>      super.wait_when_cache = true;<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>    @Override<a name="line.111"></a>
-<span class="sourceLineNo">112</span>    public void cacheBlock(BlockCacheKey cacheKey, Cacheable buf, boolean inMemory) {<a name="line.112"></a>
-<span class="sourceLineNo">113</span>      if (super.getBlock(cacheKey, true, false, true) != null) {<a name="line.113"></a>
-<span class="sourceLineNo">114</span>        throw new RuntimeException("Cached an already cached block");<a name="line.114"></a>
-<span class="sourceLineNo">115</span>      }<a name="line.115"></a>
-<span class="sourceLineNo">116</span>      super.cacheBlock(cacheKey, buf, inMemory);<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>    @Override<a name="line.119"></a>
-<span class="sourceLineNo">120</span>    public void cacheBlock(BlockCacheKey cacheKey, Cacheable buf) {<a name="line.120"></a>
-<span class="sourceLineNo">121</span>      if (super.getBlock(cacheKey, true, false, true) != null) {<a name="line.121"></a>
-<span class="sourceLineNo">122</span>        throw new RuntimeException("Cached an already cached block");<a name="line.122"></a>
-<span class="sourceLineNo">123</span>      }<a name="line.123"></a>
-<span class="sourceLineNo">124</span>      super.cacheBlock(cacheKey, buf);<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><a name="line.127"></a>
-<span class="sourceLineNo">128</span>  @Before<a name="line.128"></a>
-<span class="sourceLineNo">129</span>  public void setup() throws FileNotFoundException, IOException {<a name="line.129"></a>
-<span class="sourceLineNo">130</span>    cache =<a name="line.130"></a>
-<span class="sourceLineNo">131</span>        new MockedBucketCache(ioEngineName, capacitySize, constructedBlockSize,<a name="line.131"></a>
-<span class="sourceLineNo">132</span>            constructedBlockSizes, writeThreads, writerQLen, persistencePath);<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>  @After<a name="line.135"></a>
-<span class="sourceLineNo">136</span>  public void tearDown() {<a name="line.136"></a>
-<span class="sourceLineNo">137</span>    cache.shutdown();<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>   * Return a random element from {@code a}.<a name="line.141"></a>
-<span class="sourceLineNo">142</span>   */<a name="line.142"></a>
-<span class="sourceLineNo">143</span>  private static &lt;T&gt; T randFrom(List&lt;T&gt; a) {<a name="line.143"></a>
-<span class="sourceLineNo">144</span>    return a.get(RAND.nextInt(a.size()));<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>  @Test<a name="line.147"></a>
-<span class="sourceLineNo">148</span>  public void testBucketAllocator() throws BucketAllocatorException {<a name="line.148"></a>
-<span class="sourceLineNo">149</span>    BucketAllocator mAllocator = cache.getAllocator();<a name="line.149"></a>
-<span class="sourceLineNo">150</span>    /*<a name="line.150"></a>
-<span class="sourceLineNo">151</span>     * Test the allocator first<a name="line.151"></a>
-<span class="sourceLineNo">152</span>     */<a name="line.152"></a>
-<span class="sourceLineNo">153</span>    final List&lt;Integer&gt; BLOCKSIZES = Arrays.asList(4 * 1024, 8 * 1024, 64 * 1024, 96 * 1024);<a name="line.153"></a>
-<span class="sourceLineNo">154</span><a name="line.154"></a>
-<span class="sourceLineNo">155</span>    boolean full = false;<a name="line.155"></a>
-<span class="sourceLineNo">156</span>    ArrayList&lt;Long&gt; allocations = new ArrayList&lt;&gt;();<a name="line.156"></a>
-<span class="sourceLineNo">157</span>    // Fill the allocated extents by choosing a random blocksize. Continues selecting blocks until<a name="line.157"></a>
-<span class="sourceLineNo">158</span>    // the cache is completely filled.<a name="line.158"></a>
-<span class="sourceLineNo">159</span>    List&lt;Integer&gt; tmp = new ArrayList&lt;&gt;(BLOCKSIZES);<a name="line.159"></a>
-<span class="sourceLineNo">160</span>    while (!full) {<a name="line.160"></a>
-<span class="sourceLineNo">161</span>      Integer blockSize = null;<a name="line.161"></a>
-<span class="sourceLineNo">162</span>      try {<a name="line.162"></a>
-<span class="sourceLineNo">163</span>        blockSize = randFrom(tmp);<a name="line.163"></a>
-<span class="sourceLineNo">164</span>        allocations.add(mAllocator.allocateBlock(blockSize));<a name="line.164"></a>
-<span class="sourceLineNo">165</span>      } catch (CacheFullException cfe) {<a name="line.165"></a>
-<span class="sourceLineNo">166</span>        tmp.remove(blockSize);<a name="line.166"></a>
-<span class="sourceLineNo">167</span>        if (tmp.isEmpty()) full = true;<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>    for (Integer blockSize : BLOCKSIZES) {<a name="line.171"></a>
-<span class="sourceLineNo">172</span>      BucketSizeInfo bucketSizeInfo = mAllocator.roundUpToBucketSizeInfo(blockSize);<a name="line.172"></a>
-<span class="sourceLineNo">173</span>      IndexStatistics indexStatistics = bucketSizeInfo.statistics();<a name="line.173"></a>
-<span class="sourceLineNo">174</span>      assertEquals("unexpected freeCount for " + bucketSizeInfo, 0, indexStatistics.freeCount());<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>    for (long offset : allocations) {<a name="line.177"></a>
-<span class="sourceLineNo">178</span>      assertEquals(mAllocator.sizeOfAllocation(offset), mAllocator.freeBlock(offset));<a name="line.178"></a>
-<span class="sourceLineNo">179</span>    }<a name="line.179"></a>
-<span class="sourceLineNo">180</span>    assertEquals(0, mAllocator.getUsedSize());<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>  @Test<a name="line.183"></a>
-<span class="sourceLineNo">184</span>  public void testCacheSimple() throws Exception {<a name="line.184"></a>
-<span class="sourceLineNo">185</span>    CacheTestUtils.testCacheSimple(cache, BLOCK_SIZE, NUM_QUERIES);<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>  @Test<a name="line.188"></a>
-<span class="sourceLineNo">189</span>  public void testCacheMultiThreadedSingleKey() throws Exception {<a name="line.189"></a>
-<span class="sourceLineNo">190</span>    CacheTestUtils.hammerSingleKey(cache, BLOCK_SIZE, 2 * NUM_THREADS, 2 * NUM_QUERIES);<a name="line.190"></a>
-<span class="sourceLineNo">191</span>  }<a name="line.191"></a>
-<span class="sourceLineNo">192</span><a name="line.192"></a>
-<span class="sourceLineNo">193</span>  @Test<a name="line.193"></a>
-<span class="sourceLineNo">194</span>  public void testHeapSizeChanges() throws Exception {<a name="line.194"></a>
-<span class="sourceLineNo">195</span>    cache.stopWriterThreads();<a name="line.195"></a>
-<span class="sourceLineNo">196</span>    CacheTestUtils.testHeapSizeChanges(cache, BLOCK_SIZE);<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>  // BucketCache.cacheBlock is async, it first adds block to ramCache and writeQueue, then writer<a name="line.199"></a>
-<span class="sourceLineNo">200</span>  // threads will flush it to the bucket and put reference entry in backingMap.<a name="line.200"></a>
-<span class="sourceLineNo">201</span>  private void cacheAndWaitUntilFlushedToBucket(BucketCache cache, BlockCacheKey cacheKey,<a name="line.201"></a>
-<span class="sourceLineNo">202</span>      Cacheable block) throws InterruptedException {<a name="line.202"></a>
-<span class="sourceLineNo">203</span>    cache.cacheBlock(cacheKey, block);<a name="line.203"></a>
-<span class="sourceLineNo">204</span>    while (!cache.backingMap.containsKey(cacheKey)) {<a name="line.204"></a>
-<span class="sourceLineNo">205</span>      Thread.sleep(100);<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><a name="line.208"></a>
-<span class="sourceLineNo">209</span>  @Test<a name="line.209"></a>
-<span class="sourceLineNo">210</span>  public void testMemoryLeak() throws Exception {<a name="line.210"></a>
-<span class="sourceLineNo">211</span>    final BlockCacheKey cacheKey = new BlockCacheKey("dummy", 1L);<a name="line.211"></a>
-<span class="sourceLineNo">212</span>    cacheAndWaitUntilFlushedToBucket(cache, cacheKey, new CacheTestUtils.ByteArrayCacheable(<a name="line.212"></a>
-<span class="sourceLineNo">213</span>        new byte[10]));<a name="line.213"></a>
-<span class="sourceLineNo">214</span>    long lockId = cache.backingMap.get(cacheKey).offset();<a name="line.214"></a>
-<span class="sourceLineNo">215</span>    ReentrantReadWriteLock lock = cache.offsetLock.getLock(lockId);<a name="line.215"></a>
-<span class="sourceLineNo">216</span>    lock.writeLock().lock();<a name="line.216"></a>
-<span class="sourceLineNo">217</span>    Thread evictThread = new Thread("evict-block") {<a name="line.217"></a>
-<span class="sourceLineNo">218</span><a name="line.218"></a>
-<span class="sourceLineNo">219</span>      @Override<a name="line.219"></a>
-<span class="sourceLineNo">220</span>      public void run() {<a name="line.220"></a>
-<span class="sourceLineNo">221</span>        cache.evictBlock(cacheKey);<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>    };<a name="line.224"></a>
-<span class="sourceLineNo">225</span>    evictThread.start();<a name="line.225"></a>
-<span class="sourceLineNo">226</span>    cache.offsetLock.waitForWaiters(lockId, 1);<a name="line.226"></a>
-<span class="sourceLineNo">227</span>    cache.blockEvicted(cacheKey, cache.backingMap.remove(cacheKey), true);<a name="line.227"></a>
-<span class="sourceLineNo">228</span>    cacheAndWaitUntilFlushedToBucket(cache, cacheKey, new CacheTestUtils.ByteArrayCacheable(<a name="line.228"></a>
-<span class="sourceLineNo">229</span>        new byte[10]));<a name="line.229"></a>
-<span class="sourceLineNo">230</span>    lock.writeLock().unlock();<a name="line.230"></a>
-<span class="sourceLineNo">231</span>    evictThread.join();<a name="line.231"></a>
-<span class="sourceLineNo">232</span>    assertEquals(1L, cache.getBlockCount());<a name="line.232"></a>
-<span class="sourceLineNo">233</span>    assertTrue(cache.getCurrentSize() &gt; 0L);<a name="line.233"></a>
-<span class="sourceLineNo">234</span>    assertTrue("We should have a block!", cache.iterator().hasNext());<a name="line.234"></a>
-<span class="sourceLineNo">235</span>  }<a name="line.235"></a>
-<span class="sourceLineNo">236</span><a name="line.236"></a>
-<span class="sourceLineNo">237</span>  @Test<a name="line.237"></a>
-<span class="sourceLineNo">238</span>  public void testRetrieveFromFile() throws Exception {<a name="line.238"></a>
-<span class="sourceLineNo">239</span>    HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();<a name="line.239"></a>
-<span class="sourceLineNo">240</span>    Path testDir = TEST_UTIL.getDataTestDir();<a name="line.240"></a>
-<span class="sourceLineNo">241</span>    TEST_UTIL.getTestFileSystem().mkdirs(testDir);<a name="line.241"></a>
-<span class="sourceLineNo">242</span><a name="line.242"></a>
-<span class="sourceLineNo">243</span>    BucketCache bucketCache = new BucketCache("file:" + testDir + "/bucket.cache", capacitySize,<a name="line.243"></a>
-<span class="sourceLineNo">244</span>        constructedBlockSize, constructedBlockSizes, writeThreads, writerQLen, testDir<a name="line.244"></a>
-<span class="sourceLineNo">245</span>            + "/bucket.persistence");<a name="line.245"></a>
-<span class="sourceLineNo">246</span>    long usedSize = bucketCache.getAllocator().getUsedSize();<a name="line.246"></a>
-<span class="sourceLineNo">247</span>    assertTrue(usedSize == 0);<a name="line.247"></a>
-<span class="sourceLineNo">248</span><a name="line.248"></a>
-<span class="sourceLineNo">249</span>    HFileBlockPair[] blocks = CacheTestUtils.generateHFileBlocks(constructedBlockSize, 1);<a name="line.249"></a>
-<span class="sourceLineNo">250</span>    // Add blocks<a name="line.250"></a>
-<span class="sourceLineNo">251</span>    for (HFileBlockPair block : blocks) {<a name="line.251"></a>
-<span class="sourceLineNo">252</span>      bucketCache.cacheBlock(block.getBlockName(), block.getBlock());<a name="line.252"></a>
-<span class="sourceLineNo">253</span>    }<a name="line.253"></a>
-<span class="sourceLineNo">254</span>    for (HFileBlockPair block : blocks) {<a name="line.254"></a>
-<span class="sourceLineNo">255</span>      cacheAndWaitUntilFlushedToBucket(bucketCache, block.getBlockName(), block.getBlock());<a name="line.255"></a>
-<span class="sourceLineNo">256</span>    }<a name="line.256"></a>
-<span class="sourceLineNo">257</span>    usedSize = bucketCache.getAllocator().getUsedSize();<a name="line.257"></a>
-<span class="sourceLineNo">258</span>    assertTrue(usedSize != 0);<a name="line.258"></a>
-<span class="sourceLineNo">259</span>    // persist cache to file<a name="line.259"></a>
-<span class="sourceLineNo">260</span>    bucketCache.shutdown();<a name="line.260"></a>
-<span class="sourceLineNo">261</span><a name="line.261"></a>
-<span class="sourceLineNo">262</span>    // restore cache from file<a name="line.262"></a>
-<span class="sourceLineNo">263</span>    bucketCache = new BucketCache("file:" + testDir + "/bucket.cache", capacitySize,<a name="line.263"></a>
-<span class="sourceLineNo">264</span>        constructedBlockSize, constructedBlockSizes, writeThreads, writerQLen, testDir<a name="line.264"></a>
-<span class="sourceLineNo">265</span>            + "/bucket.persistence");<a name="line.265"></a>
-<span class="sourceLineNo">266</span>    assertEquals(usedSize, bucketCache.getAllocator().getUsedSize());<a name="line.266"></a>
-<span class="sourceLineNo">267</span>    // persist cache to file<a name="line.267"></a>
-<span class="sourceLineNo">268</span>    bucketCache.shutdown();<a name="line.268"></a>
-<span class="sourceLineNo">269</span><a name="line.269"></a>
-<span class="sourceLineNo">270</span>    // reconfig buckets sizes, the biggest bucket is small than constructedBlockSize (8k or 16k)<a name="line.270"></a>
-<span class="sourceLineNo">271</span>    // so it can't restore cache from file<a name="line.271"></a>
-<span class="sourceLineNo">272</span>    int[] smallBucketSizes = new int[] { 2 * 1024 + 1024, 4 * 1024 + 1024 };<a name="line.272"></a>
-<span class="sourceLineNo">273</span>    bucketCache = new BucketCache("file:" + testDir + "/bucket.cache", capacitySize,<a name="line.273"></a>
-<span class="sourceLineNo">274</span>        constructedBlockSize, smallBucketSizes, writeThreads,<a name="line.274"></a>
-<span class="sourceLineNo">275</span>        writerQLen, testDir + "/bucket.persistence");<a name="line.275"></a>
-<span class="sourceLineNo">276</span>    assertEquals(0, bucketCache.getAllocator().getUsedSize());<a name="line.276"></a>
-<span class="sourceLineNo">277</span>    assertEquals(0, bucketCache.backingMap.size());<a name="line.277"></a>
-<span class="sourceLineNo">278</span><a name="line.278"></a>
-<span class="sourceLineNo">279</span>    TEST_UTIL.cleanupTestDir();<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>  @Test<a name="line.282"></a>
-<span class="sourceLineNo">283</span>  public void testBucketAllocatorLargeBuckets() throws BucketAllocatorException {<a name="line.283"></a>
-<span class="sourceLineNo">284</span>    long availableSpace = 20 * 1024L * 1024 * 1024;<a name="line.284"></a>
-<span class="sourceLineNo">285</span>    int[] bucketSizes = new int[]{1024, 1024 * 1024, 1024 * 1024 * 1024};<a name="line.285"></a>
-<span class="sourceLineNo">286</span>    BucketAllocator allocator = new BucketAllocator(availableSpace, bucketSizes);<a name="line.286"></a>
-<span class="sourceLineNo">287</span>    assertTrue(allocator.getBuckets().length &gt; 0);<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>  @Test<a name="line.290"></a>
-<span class="sourceLineNo">291</span>  public void testGetPartitionSize() throws IOException {<a name="line.291"></a>
-<span class="sourceLineNo">292</span>    //Test default values<a name="line.292"></a>
-<span class="sourceLineNo">293</span>    validateGetPartitionSize(cache, BucketCache.DEFAULT_SINGLE_FACTOR, BucketCache.DEFAULT_MIN_FACTOR);<a name="line.293"></a>
-<span class="sourceLineNo">294</span><a name="line.294"></a>
-<span class="sourceLineNo">295</span>    Configuration conf = HBaseConfiguration.create();<a name="line.295"></a>
-<span class="sourceLineNo">296</span>    conf.setFloat(BucketCache.MIN_FACTOR_CONFIG_NAME, 0.5f);<a name="line.296"></a>
-<span class="sourceLineNo">297</span>    conf.setFloat(BucketCache.SINGLE_FACTOR_CONFIG_NAME, 0.1f);<a name="line.297"></a>
-<span class="sourceLineNo">298</span>    conf.setFloat(BucketCache.MULTI_FACTOR_CONFIG_NAME, 0.7f);<a name="line.298"></a>
-<span class="sourceLineNo">299</span>    conf.setFloat(BucketCache.MEMORY_FACTOR_CONFIG_NAME, 0.2f);<a name="line.299"></a>
-<span class="sourceLineNo">300</span><a name="line.300"></a>
-<span class="sourceLineNo">301</span>    BucketCache cache = new BucketCache(ioEngineName, capacitySize, constructedBlockSize,<a name="line.301"></a>
-<span class="sourceLineNo">302</span>        constructedBlockSizes, writeThreads, writerQLen, persistencePath, 100, conf);<a name="line.302"></a>
-<span class="sourceLineNo">303</span><a name="line.303"></a>
-<span class="sourceLineNo">304</span>    validateGetPartitionSize(cache, 0.1f, 0.5f);<a name="line.304"></a>
-<span class="sourceLineNo">305</span>    validateGetPartitionSize(cache, 0.7f, 0.5f);<a name="line.305"></a>
-<span class="sourceLineNo">306</span>    validateGetPartitionSize(cache, 0.2f, 0.5f);<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>  @Test<a name="line.309"></a>
-<span class="sourceLineNo">310</span>  public void testValidBucketCacheConfigs() throws IOException {<a name="line.310"></a>
-<span class="sourceLineNo">311</span>    Configuration conf = HBaseConfiguration.create();<a name="line.311"></a>
-<span class="sourceLineNo">312</span>    conf.setFloat(BucketCache.ACCEPT_FACTOR_CONFIG_NAME, 0.9f);<a name="line.312"></a>
-<span class="sourceLineNo">313</span>    conf.setFloat(BucketCache.MIN_FACTOR_CONFIG_NAME, 0.5f);<a name="line.313"></a>
-<span class="sourceLineNo">314</span>    conf.setFloat(BucketCache.EXTRA_FREE_FACTOR_CONFIG_NAME, 0.5f);<a name="line.314"></a>
-<span class="sourceLineNo">315</span>    conf.setFloat(BucketCache.SINGLE_FACTOR_CONFIG_NAME, 0.1f);<a name="line.315"></a>
-<span class="sourceLineNo">316</span>    conf.setFloat(BucketCache.MULTI_FACTOR_CONFIG_NAME, 0.7f);<a name="line.316"></a>
-<span class="sourceLineNo">317</span>    conf.setFloat(BucketCache.MEMORY_FACTOR_CONFIG_NAME, 0.2f);<a name="line.317"></a>
-<span class="sourceLineNo">318</span><a name="line.318"></a>
-<span class="sourceLineNo">319</span>    BucketCache cache = new BucketCache(ioEngineName, capacitySize, constructedBlockSize,<a name="line.319"></a>
-<span class="sourceLineNo">320</span>        constructedBlockSizes, writeThreads, writerQLen, persistencePath, 100, conf);<a name="line.320"></a>
-<span class="sourceLineNo">321</span><a name="line.321"></a>
-<span class="sourceLineNo">322</span>    assertEquals(BucketCache.ACCEPT_FACTOR_CONFIG_NAME + " failed to propagate.", 0.9f,<a name="line.322"></a>
-<span class="sourceLineNo">323</span>        cache.getAcceptableFactor(), 0);<a name="line.323"></a>
-<span class="sourceLineNo">324</span>    assertEquals(BucketCache.MIN_FACTOR_CONFIG_NAME + " failed to propagate.", 0.5f,<a name="line.324"></a>
-<span class="sourceLineNo">325</span>        cache.getMinFactor(), 0);<a name="line.325"></a>
-<span class="sourceLineNo">326</span>    assertEquals(BucketCache.EXTRA_FREE_FACTOR_CONFIG_NAME + " failed to propagate.", 0.5f,<a name="line.326"></a>
-<span class="sourceLineNo">327</span>        cache.getExtraFreeFactor(), 0);<a name="line.327"></a>
-<span class="sourceLineNo">328</span>    assertEquals(BucketCache.SINGLE_FACTOR_CONFIG_NAME + " failed to propagate.", 0.1f,<a name="line.328"></a>
-<span class="sourceLineNo">329</span>        cache.getSingleFactor(), 0);<a name="line.329"></a>
-<span class="sourceLineNo">330</span>    assertEquals(BucketCache.MULTI_FACTOR_CONFIG_NAME + " failed to propagate.", 0.7f,<a name="line.330"></a>
-<span class="sourceLineNo">331</span>        cache.getMultiFactor(), 0);<a name="line.331"></a>
-<span class="sourceLineNo">332</span>    assertEquals(BucketCache.MEMORY_FACTOR_CONFIG_NAME + " failed to propagate.", 0.2f,<a name="line.332"></a>
-<span class="sourceLineNo">333</span>        cache.getMemoryFactor(), 0);<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>  @Test<a name="line.336"></a>
-<span class="sourceLineNo">337</span>  public void testInvalidAcceptFactorConfig() throws IOException {<a name="line.337"></a>
-<span class="sourceLineNo">338</span>    float[] configValues = {-1f, 0.2f, 0.86f, 1.05f};<a name="line.338"></a>
-<span class="sourceLineNo">339</span>    boolean[] expectedOutcomes = {false, false, true, false};<a name="line.339"></a>
-<span class="sourceLineNo">340</span>    Map&lt;String, float[]&gt; configMappings = ImmutableMap.of(BucketCache.ACCEPT_FACTOR_CONFIG_NAME, configValues);<a name="line.340"></a>
-<span class="sourceLineNo">341</span>    Configuration conf = HBaseConfiguration.create();<a name="line.341"></a>
-<span class="sourceLineNo">342</span>    checkConfigValues(conf, configMappings, expectedOutcomes);<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>  @Test<a name="line.345"></a>
-<span class="sourceLineNo">346</span>  public void testInvalidMinFactorConfig() throws IOException {<a name="line.346"></a>
-<span class="sourceLineNo">347</span>    float[] configValues = {-1f, 0f, 0.96f, 1.05f};<a name="line.347"></a>
-<span class="sourceLineNo">348</span>    //throws due to &lt;0, in expected range, minFactor &gt; acceptableFactor, &gt; 1.0<a name="line.348"></a>
-<span class="sourceLineNo">349</span>    boolean[] expectedOutcomes = {false, true, false, false};<a name="line.349"></a>
-<span class="sourceLineNo">350</span>    Map&lt;String, float[]&gt; configMappings = ImmutableMap<a name="line.350"></a>
-<span class="sourceLineNo">351</span>      .of(BucketCache.MIN_FACTOR_CONFIG_NAME, configValues);<a name="line.351"></a>
-<span class="sourceLineNo">352</span>    Configuration conf = HBaseConfiguration.create();<a name="line.352"></a>
-<span class="sourceLineNo">353</span>    checkConfigValues(conf, configMappings, expectedOutcomes);<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>  @Test<a name="line.356"></a>
-<span class="sourceLineNo">357</span>  public void testInvalidExtraFreeFactorConfig() throws IOException {<a name="line.357"></a>
-<span class="sourceLineNo">358</span>    float[] configValues = {-1f, 0f, 0.2f, 1.05f};<a name="line.358"></a>
-<span class="sourceLineNo">359</span>    //throws due to &lt;0, in expected range, in expected range, config can be &gt; 1.0<a name="line.359"></a>
-<span class="sourceLineNo">360</span>    boolean[] expectedOutcomes = {false, true, true, true};<a name="line.360"></a>
-<span class="sourceLineNo">361</span>    Map&lt;String, float[]&gt; configMappings = ImmutableMap.of(BucketCache.EXTRA_FREE_FACTOR_CONFIG_NAME, configValues);<a name="line.361"></a>
-<span class="sourceLineNo">362</span>    Configuration conf = HBaseConfiguration.create();<a name="line.362"></a>
-<span class="sourceLineNo">363</span>    checkConfigValues(conf, configMappings, expectedOutcomes);<a name="line.363"></a>
-<span class="sourceLineNo">364</span>  }<a name="line.364"></a>
-<span class="sourceLineNo">365</span><a name="line.365"></a>
-<span class="sourceLineNo">366</span>  @Test<a name="line.366"></a>
-<span class="sourceLineNo">367</span>  public void testInvalidCacheSplitFactorConfig() throws IOException {<a name="line.367"></a>
-<span class="sourceLineNo">368</span>    float[] singleFactorConfigValues = {0.2f, 0f, -0.2f, 1f};<a name="line.368"></a>
-<span class="sourceLineNo">369</span>    float[] multiFactorConfigValues = {0.4f, 0f, 1f, .05f};<a name="line.369"></a>
-<span class="sourceLineNo">370</span>    float[] memoryFactorConfigValues = {0.4f, 0f, 0.2f, .5f};<a name="line.370"></a>
-<span class="sourceLineNo">371</span>    // All configs add up to 1.0 and are between 0 and 1.0, configs don't add to 1.0, configs can't be negative, configs don't add to 1.0<a name="line.371"></a>
-<span class="sourceLineNo">372</span>    boolean[] expectedOutcomes = {true, false, false, false};<a name="line.372"></a>
-<span class="sourceLineNo">373</span>    Map&lt;String, float[]&gt; configMappings = ImmutableMap.of(BucketCache.SINGLE_FACTOR_CONFIG_NAME,<a name="line.373"></a>
-<span class="sourceLineNo">374</span>        singleFactorConfigValues, BucketCache.MULTI_FACTOR_CONFIG_NAME, multiFactorConfigValues,<a name="line.374"></a>
-<span class="sourceLineNo">375</span>        BucketCache.MEMORY_FACTOR_CONFIG_NAME, memoryFactorConfigValues);<a name="line.375"></a>
-<span class="sourceLineNo">376</span>    Configuration conf = HBaseConfiguration.create();<a name="line.376"></a>
-<span class="sourceLineNo">377</span>    checkConfigValues(conf, configMappings, expectedOutcomes);<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>  private void checkConfigValues(Configuration conf, Map&lt;String, float[]&gt; configMap, boolean[] expectSuccess) throws IOException {<a name="line.380"></a>
-<span class="sourceLineNo">381</span>    Set&lt;String&gt; configNames = configMap.keySet();<a name="line.381"></a>
-<span class="sourceLineNo">382</span>    for (int i = 0; i &lt; expectSuccess.length; i++) {<a name="line.382"></a>
-<span class="sourceLineNo">383</span>      try {<a name="line.383"></a>
-<span class="sourceLineNo">384</span>        for (String configName : configNames) {<a name="line.384"></a>
-<span class="sourceLineNo">385</span>          conf.setFloat(configName, configMap.get(configName)[i]);<a name="line.385"></a>
-<span class="sourceLineNo">386</span>        }<a name="line.386"></a>
-<span class="sourceLineNo">387</span>        BucketCache cache = new BucketCache(ioEngineName, capacitySize, constructedBlockSize,<a name="line.387"></a>
-<span class="sourceLineNo">388</span>            constructedBlockSizes, writeThreads, writerQLen, persistencePath, 100, conf);<a name="line.388"></a>
-<span class="sourceLineNo">389</span>        assertTrue("Created BucketCache and expected it to succeed: " + expectSuccess[i] + ", but it actually was: " + !expectSuccess[i], expectSuccess[i]);<a name="line.389"></a>
-<span class="sourceLineNo">390</span>      } catch (IllegalArgumentException e) {<a name="line.390"></a>
-<span class="sourceLineNo">391</span>        assertFalse("Created BucketCache and expected it to succeed: " + expectSuccess[i] + ", but it actually was: " + !expectSuccess[i], expectSuccess[i]);<a name="line.391"></a>
-<span class="sourceLineNo">392</span>      }<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>  private void validateGetPartitionSize(BucketCache bucketCache, float partitionFactor, float minFactor) {<a name="line.396"></a>
-<span class="sourceLineNo">397</span>    long expectedOutput = (long) Math.floor(bucketCache.getAllocator().getTotalSize() * partitionFactor * minFactor);<a name="line.397"></a>
-<span class="sourceLineNo">398</span>    assertEquals(expectedOutput, bucketCache.getPartitionSize(partitionFactor));<a name="line.398"></a>
-<span class="sourceLineNo">399</span>  }<a name="line.399"></a>
-<span class="sourceLineNo">400</span><a name="line.400"></a>
-<span class="sourceLineNo">401</span>  @Test<a name="line.401"></a>
-<span class="sourceLineNo">402</span>  public void testOffsetProducesPositiveOutput() {<a name="line.402"></a>
-<span class="sourceLineNo">403</span>    //This number is picked because it produces negative output if the values isn't ensured to be positive.<a name="line.403"></a>
-<span class="sourceLineNo">404</span>    //See HBASE-18757 for more information.<a name="line.404"></a>
-<span class="sourceLineNo">405</span>    long testValue = 549888460800L;<a name="line.405"></a>
-<span class="sourceLineNo">406</span>    BucketCache.BucketEntry bucketEntry = new BucketCache.BucketEntry(testValue, 10, 10L, true);<a name="line.406"></a>
-<span class="sourceLineNo">407</span>    assertEquals(testValue, bucketEntry.offset());<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">095</span>  BucketCache cache;<a name="line.95"></a>
+<span class="sourceLineNo">096</span>  final int CACHE_SIZE = 1000000;<a name="line.96"></a>
+<span class="sourceLineNo">097</span>  final int NUM_BLOCKS = 100;<a name="line.97"></a>
+<span class="sourceLineNo">098</span>  final int BLOCK_SIZE = CACHE_SIZE / NUM_BLOCKS;<a name="line.98"></a>
+<span class="sourceLineNo">099</span>  final int NUM_THREADS = 100;<a name="line.99"></a>
+<span class="sourceLineNo">100</span>  final int NUM_QUERIES = 10000;<a name="line.100"></a>
+<span class="sourceLineNo">101</span><a name="line.101"></a>
+<span class="sourceLineNo">102</span>  final long capacitySize = 32 * 1024 * 1024;<a name="line.102"></a>
+<span class="sourceLineNo">103</span>  final int writeThreads = BucketCache.DEFAULT_WRITER_THREADS;<a name="line.103"></a>
+<span class="sourceLineNo">104</span>  final int writerQLen = BucketCache.DEFAULT_WRITER_QUEUE_ITEMS;<a name="line.104"></a>
+<span class="sourceLineNo">105</span>  String ioEngineName = "offheap";<a name="line.105"></a>
+<span class="sourceLineNo">106</span>  String persistencePath = null;<a name="line.106"></a>
+<span class="sourceLineNo">107</span><a name="line.107"></a>
+<span class="sourceLineNo">108</span>  private static class MockedBucketCache extends BucketCache {<a name="line.108"></a>
+<span class="sourceLineNo">109</span><a name="line.109"></a>
+<span class="sourceLineNo">110</span>    public MockedBucketCache(String ioEngineName, long capacity, int blockSize, int[] bucketSizes,<a name="line.110"></a>
+<span class="sourceLineNo">111</span>        int writerThreads, int writerQLen, String persistencePath) throws FileNotFoundException,<a name="line.111"></a>
+<span class="sourceLineNo">112</span>        IOException {<a name="line.112"></a>
+<span class="sourceLineNo">113</span>      super(ioEngineName, capacity, blockSize, bucketSizes, writerThreads, writerQLen,<a name="line.113"></a>
+<span class="sourceLineNo">114</span>          persistencePath);<a name="line.114"></a>
+<span class="sourceLineNo">115</span>      super.wait_when_cache = true;<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>    @Override<a name="line.118"></a>
+<span class="sourceLineNo">119</span>    public void cacheBlock(BlockCacheKey cacheKey, Cacheable buf, boolean inMemory) {<a name="line.119"></a>
+<span class="sourceLineNo">120</span>      super.cacheBlock(cacheKey, buf, inMemory);<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>    @Override<a name="line.123"></a>
+<span class="sourceLineNo">124</span>    public void cacheBlock(BlockCacheKey cacheKey, Cacheable buf) {<a name="line.124"></a>
+<span class="sourceLineNo">125</span>      super.cacheBlock(cacheKey, buf);<a name="line.125"></a>
+<span class="sourceLineNo">126</span>    }<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>  @Before<a name="line.129"></a>
+<span class="sourceLineNo">130</span>  public void setup() throws FileNotFoundException, IOException {<a name="line.130"></a>
+<span class="sourceLineNo">131</span>    cache =<a name="line.131"></a>
+<span class="sourceLineNo">132</span>        new MockedBucketCache(ioEngineName, capacitySize, constructedBlockSize,<a name="line.132"></a>
+<span class="sourceLineNo">133</span>            constructedBlockSizes, writeThreads, writerQLen, persistencePath);<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>  @After<a name="line.136"></a>
+<span class="sourceLineNo">137</span>  public void tearDown() {<a name="line.137"></a>
+<span class="sourceLineNo">138</span>    cache.shutdown();<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>   * Return a random element from {@code a}.<a name="line.142"></a>
+<span class="sourceLineNo">143</span>   */<a name="line.143"></a>
+<span class="sourceLineNo">144</span>  private static &lt;T&gt; T randFrom(List&lt;T&gt; a) {<a name="line.144"></a>
+<span class="sourceLineNo">145</span>    return a.get(RAND.nextInt(a.size()));<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>  @Test<a name="line.148"></a>
+<span class="sourceLineNo">149</span>  public void testBucketAllocator() throws BucketAllocatorException {<a name="line.149"></a>
+<span class="sourceLineNo">150</span>    BucketAllocator mAllocator = cache.getAllocator();<a name="line.150"></a>
+<span class="sourceLineNo">151</span>    /*<a name="line.151"></a>
+<span class="sourceLineNo">152</span>     * Test the allocator first<a name="line.152"></a>
+<span class="sourceLineNo">153</span>     */<a name="line.153"></a>
+<span class="sourceLineNo">154</span>    final List&lt;Integer&gt; BLOCKSIZES = Arrays.asList(4 * 1024, 8 * 1024, 64 * 1024, 96 * 1024);<a name="line.154"></a>
+<span class="sourceLineNo">155</span><a name="line.155"></a>
+<span class="sourceLineNo">156</span>    boolean full = false;<a name="line.156"></a>
+<span class="sourceLineNo">157</span>    ArrayList&lt;Long&gt; allocations = new ArrayList&lt;&gt;();<a name="line.157"></a>
+<span class="sourceLineNo">158</span>    // Fill the allocated extents by choosing a random blocksize. Continues selecting blocks until<a name="line.158"></a>
+<span class="sourceLineNo">159</span>    // the cache is completely filled.<a name="line.159"></a>
+<span class="sourceLineNo">160</span>    List&lt;Integer&gt; tmp = new ArrayList&lt;&gt;(BLOCKSIZES);<a name="line.160"></a>
+<span class="sourceLineNo">161</span>    while (!full) {<a name="line.161"></a>
+<span class="sourceLineNo">162</span>      Integer blockSize = null;<a name="line.162"></a>
+<span class="sourceLineNo">163</span>      try {<a name="line.163"></a>
+<span class="sourceLineNo">164</span>        blockSize = randFrom(tmp);<a name="line.164"></a>
+<span class="sourceLineNo">165</span>        allocations.add(mAllocator.allocateBlock(blockSize));<a name="line.165"></a>
+<span class="sourceLineNo">166</span>      } catch (CacheFullException cfe) {<a name="line.166"></a>
+<span class="sourceLineNo">167</span>        tmp.remove(blockSize);<a name="line.167"></a>
+<span class="sourceLineNo">168</span>        if (tmp.isEmpty()) full = true;<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>    for (Integer blockSize : BLOCKSIZES) {<a name="line.172"></a>
+<span class="sourceLineNo">173</span>      BucketSizeInfo bucketSizeInfo = mAllocator.roundUpToBucketSizeInfo(blockSize);<a name="line.173"></a>
+<span class="sourceLineNo">174</span>      IndexStatistics indexStatistics = bucketSizeInfo.statistics();<a name="line.174"></a>
+<span class="sourceLineNo">175</span>      assertEquals("unexpected freeCount for " + bucketSizeInfo, 0, indexStatistics.freeCount());<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>    for (long offset : allocations) {<a name="line.178"></a>
+<span class="sourceLineNo">179</span>      assertEquals(mAllocator.sizeOfAllocation(offset), mAllocator.freeBlock(offset));<a name="line.179"></a>
+<span class="sourceLineNo">180</span>    }<a name="line.180"></a>
+<span class="sourceLineNo">181</span>    assertEquals(0, mAllocator.getUsedSize());<a name="line.181"></a>
+<span class="sourceLineNo">182</span>  }<a name="line.182"></a>
+<span class="sourceLineNo">183</span><a name="line.183"></a>
+<span class="sourceLineNo">184</span>  @Test<a name="line.184"></a>
+<span class="sourceLineNo">185</span>  public void testCacheSimple() throws Exception {<a name="line.185"></a>
+<span class="sourceLineNo">186</span>    CacheTestUtils.testCacheSimple(cache, BLOCK_SIZE, NUM_QUERIES);<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>  @Test<a name="line.189"></a>
+<span class="sourceLineNo">190</span>  public void testCacheMultiThreadedSingleKey() throws Exception {<a name="line.190"></a>
+<span class="sourceLineNo">191</span>    CacheTestUtils.hammerSingleKey(cache, BLOCK_SIZE, 2 * NUM_THREADS, 2 * NUM_QUERIES);<a name="line.191"></a>
+<span class="sourceLineNo">192</span>  }<a name="line.192"></a>
+<span class="sourceLineNo">193</span><a name="line.193"></a>
+<span class="sourceLineNo">194</span>  @Test<a name="line.194"></a>
+<span class="sourceLineNo">195</span>  public void testHeapSizeChanges() throws Exception {<a name="line.195"></a>
+<span class="sourceLineNo">196</span>    cache.stopWriterThreads();<a name="line.196"></a>
+<span class="sourceLineNo">197</span>    CacheTestUtils.testHeapSizeChanges(cache, BLOCK_SIZE);<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>  // BucketCache.cacheBlock is async, it first adds block to ramCache and writeQueue, then writer<a name="line.200"></a>
+<span class="sourceLineNo">201</span>  // threads will flush it to the bucket and put reference entry in backingMap.<a name="line.201"></a>
+<span class="sourceLineNo">202</span>  private void cacheAndWaitUntilFlushedToBucket(BucketCache cache, BlockCacheKey cacheKey,<a name="line.202"></a>
+<span class="sourceLineNo">203</span>      Cacheable block) throws InterruptedException {<a name="line.203"></a>
+<span class="sourceLineNo">204</span>    cache.cacheBlock(cacheKey, block);<a name="line.204"></a>
+<span class="sourceLineNo">205</span>    while (!cache.backingMap.containsKey(cacheKey)) {<a name="line.205"></a>
+<span class="sourceLineNo">206</span>      Thread.sleep(100);<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><a name="line.209"></a>
+<span class="sourceLineNo">210</span>  @Test<a name="line.210"></a>
+<span class="sourceLineNo">211</span>  public void testMemoryLeak() throws Exception {<a name="line.211"></a>
+<span class="sourceLineNo">212</span>    final BlockCacheKey cacheKey = new BlockCacheKey("dummy", 1L);<a name="line.212"></a>
+<span class="sourceLineNo">213</span>    cacheAndWaitUntilFlushedToBucket(cache, cacheKey, new CacheTestUtils.ByteArrayCacheable(<a name="line.213"></a>
+<span class="sourceLineNo">214</span>        new byte[10]));<a name="line.214"></a>
+<span class="sourceLineNo">215</span>    long lockId = cache.backingMap.get(cacheKey).offset();<a name="line.215"></a>
+<span class="sourceLineNo">216</span>    ReentrantReadWriteLock lock = cache.offsetLock.getLock(lockId);<a name="line.216"></a>
+<span class="sourceLineNo">217</span>    lock.writeLock().lock();<a name="line.217"></a>
+<span class="sourceLineNo">218</span>    Thread evictThread = new Thread("evict-block") {<a name="line.218"></a>
+<span class="sourceLineNo">219</span><a name="line.219"></a>
+<span class="sourceLineNo">220</span>      @Override<a name="line.220"></a>
+<span class="sourceLineNo">221</span>      public void run() {<a name="line.221"></a>
+<span class="sourceLineNo">222</span>        cache.evictBlock(cacheKey);<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>    };<a name="line.225"></a>
+<span class="sourceLineNo">226</span>    evictThread.start();<a name="line.226"></a>
+<span class="sourceLineNo">227</span>    cache.offsetLock.waitForWaiters(lockId, 1);<a name="line.227"></a>
+<span class="sourceLineNo">228</span>    cache.blockEvicted(cacheKey, cache.backingMap.remove(cacheKey), true);<a name="line.228"></a>
+<span class="sourceLineNo">229</span>    cacheAndWaitUntilFlushedToBucket(cache, cacheKey, new CacheTestUtils.ByteArrayCacheable(<a name="line.229"></a>
+<span class="sourceLineNo">230</span>        new byte[10]));<a name="line.230"></a>
+<span class="sourceLineNo">231</span>    lock.writeLock().unlock();<a name="line.231"></a>
+<span class="sourceLineNo">232</span>    evictThread.join();<a name="line.232"></a>
+<span class="sourceLineNo">233</span>    assertEquals(1L, cache.getBlockCount());<a name="line.233"></a>
+<span class="sourceLineNo">234</span>    assertTrue(cache.getCurrentSize() &gt; 0L);<a name="line.234"></a>
+<span class="sourceLineNo">235</span>    assertTrue("We should have a block!", cache.iterator().hasNext());<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>  @Test<a name="line.238"></a>
+<span class="sourceLineNo">239</span>  public void testRetrieveFromFile() throws Exception {<a name="line.239"></a>
+<span class="sourceLineNo">240</span>    HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();<a name="line.240"></a>
+<span class="sourceLineNo">241</span>    Path testDir = TEST_UTIL.getDataTestDir();<a name="line.241"></a>
+<span class="sourceLineNo">242</span>    TEST_UTIL.getTestFileSystem().mkdirs(testDir);<a name="line.242"></a>
+<span class="sourceLineNo">243</span><a name="line.243"></a>
+<span class="sourceLineNo">244</span>    BucketCache bucketCache = new BucketCache("file:" + testDir + "/bucket.cache", capacitySize,<a name="line.244"></a>
+<span class="sourceLineNo">245</span>        constructedBlockSize, constructedBlockSizes, writeThreads, writerQLen, testDir<a name="line.245"></a>
+<span class="sourceLineNo">246</span>            + "/bucket.persistence");<a name="line.246"></a>
+<span class="sourceLineNo">247</span>    long usedSize = bucketCache.getAllocator().getUsedSize();<a name="line.247"></a>
+<span class="sourceLineNo">248</span>    assertTrue(usedSize == 0);<a name="line.248"></a>
+<span class="sourceLineNo">249</span><a name="line.249"></a>
+<span class="sourceLineNo">250</span>    HFileBlockPair[] blocks = CacheTestUtils.generateHFileBlocks(constructedBlockSize, 1);<a name="line.250"></a>
+<span class="sourceLineNo">251</span>    // Add blocks<a name="line.251"></a>
+<span class="sourceLineNo">252</span>    for (HFileBlockPair block : blocks) {<a name="line.252"></a>
+<span class="sourceLineNo">253</span>      bucketCache.cacheBlock(block.getBlockName(), block.getBlock());<a name="line.253"></a>
+<span class="sourceLineNo">254</span>    }<a name="line.254"></a>
+<span class="sourceLineNo">255</span>    for (HFileBlockPair block : blocks) {<a name="line.255"></a>
+<span class="sourceLineNo">256</span>      cacheAndWaitUntilFlushedToBucket(bucketCache, block.getBlockName(), block.getBlock());<a name="line.256"></a>
+<span class="sourceLineNo">257</span>    }<a name="line.257"></a>
+<span class="sourceLineNo">258</span>    usedSize = bucketCache.getAllocator().getUsedSize();<a name="line.258"></a>
+<span class="sourceLineNo">259</span>    assertTrue(usedSize != 0);<a name="line.259"></a>
+<span class="sourceLineNo">260</span>    // persist cache to file<a name="line.260"></a>
+<span class="sourceLineNo">261</span>    bucketCache.shutdown();<a name="line.261"></a>
+<span class="sourceLineNo">262</span><a name="line.262"></a>
+<span class="sourceLineNo">263</span>    // restore cache from file<a name="line.263"></a>
+<span class="sourceLineNo">264</span>    bucketCache = new BucketCache("file:" + testDir + "/bucket.cache", capacitySize,<a name="line.264"></a>
+<span class="sourceLineNo">265</span>        constructedBlockSize, constructedBlockSizes, writeThreads, writerQLen, testDir<a name="line.265"></a>
+<span class="sourceLineNo">266</span>            + "/bucket.persistence");<a name="line.266"></a>
+<span class="sourceLineNo">267</span>    assertEquals(usedSize, bucketCache.getAllocator().getUsedSize());<a name="line.267"></a>
+<span class="sourceLineNo">268</span>    // persist cache to file<a name="line.268"></a>
+<span class="sourceLineNo">269</span>    bucketCache.shutdown();<a name="line.269"></a>
+<span class="sourceLineNo">270</span><a name="line.270"></a>
+<span class="sourceLineNo">271</span>    // reconfig buckets sizes, the biggest bucket is small than constructedBlockSize (8k or 16k)<a name="line.271"></a>
+<span class="sourceLineNo">272</span>    // so it can't restore cache from file<a name="line.272"></a>
+<span class="sourceLineNo">273</span>    int[] smallBucketSizes = new int[] { 2 * 1024 + 1024, 4 * 1024 + 1024 };<a name="line.273"></a>
+<span class="sourceLineNo">274</span>    bucketCache = new BucketCache("file:" + testDir + "/bucket.cache", capacitySize,<a name="line.274"></a>
+<span class="sourceLineNo">275</span>        constructedBlockSize, smallBucketSizes, writeThreads,<a name="line.275"></a>
+<span class="sourceLineNo">276</span>        writerQLen, testDir + "/bucket.persistence");<a name="line.276"></a>
+<span class="sourceLineNo">277</span>    assertEquals(0, bucketCache.getAllocator().getUsedSize());<a name="line.277"></a>
+<span class="sourceLineNo">278</span>    assertEquals(0, bucketCache.backingMap.size());<a name="line.278"></a>
+<span class="sourceLineNo">279</span><a name="line.279"></a>
+<span class="sourceLineNo">280</span>    TEST_UTIL.cleanupTestDir();<a name="line.280"></a>
+<span class="sourceLineNo">281</span>  }<a name="line.281"></a>
+<span class="sourceLineNo">282</span><a name="line.282"></a>
+<span class="sourceLineNo">283</span>  @Test<a name="line.283"></a>
+<span class="sourceLineNo">284</span>  public void testBucketAllocatorLargeBuckets() throws BucketAllocatorException {<a name="line.284"></a>
+<span class="sourceLineNo">285</span>    long availableSpace = 20 * 1024L * 1024 * 1024;<a name="line.285"></a>
+<span class="sourceLineNo">286</span>    int[] bucketSizes = new int[]{1024, 1024 * 1024, 1024 * 1024 * 1024};<a name="line.286"></a>
+<span class="sourceLineNo">287</span>    BucketAllocator allocator = new BucketAllocator(availableSpace, bucketSizes);<a name="line.287"></a>
+<span class="sourceLineNo">288</span>    assertTrue(allocator.getBuckets().length &gt; 0);<a name="line.288"></a>
+<span class="sourceLineNo">289</span>  }<a name="line.289"></a>
+<span class="sourceLineNo">290</span><a name="line.290"></a>
+<span class="sourceLineNo">291</span>  @Test<a name="line.291"></a>
+<span class="sourceLineNo">292</span>  public void testGetPartitionSize() throws IOException {<a name="line.292"></a>
+<span class="sourceLineNo">293</span>    //Test default values<a name="line.293"></a>
+<span class="sourceLineNo">294</span>    validateGetPartitionSize(cache, BucketCache.DEFAULT_SINGLE_FACTOR, BucketCache.DEFAULT_MIN_FACTOR);<a name="line.294"></a>
+<span class="sourceLineNo">295</span><a name="line.295"></a>
+<span class="sourceLineNo">296</span>    Configuration conf = HBaseConfiguration.create();<a name="line.296"></a>
+<span class="sourceLineNo">297</span>    conf.setFloat(BucketCache.MIN_FACTOR_CONFIG_NAME, 0.5f);<a name="line.297"></a>
+<span class="sourceLineNo">298</span>    conf.setFloat(BucketCache.SINGLE_FACTOR_CONFIG_NAME, 0.1f);<a name="line.298"></a>
+<span class="sourceLineNo">299</span>    conf.setFloat(BucketCache.MULTI_FACTOR_CONFIG_NAME, 0.7f);<a name="line.299"></a>
+<span class="sourceLineNo">300</span>    conf.setFloat(BucketCache.MEMORY_FACTOR_CONFIG_NAME, 0.2f);<a name="line.300"></a>
+<span class="sourceLineNo">301</span><a name="line.301"></a>
+<span class="sourceLineNo">302</span>    BucketCache cache = new BucketCache(ioEngineName, capacitySize, constructedBlockSize,<a name="line.302"></a>
+<span class="sourceLineNo">303</span>        constructedBlockSizes, writeThreads, writerQLen, persistencePath, 100, conf);<a name="line.303"></a>
+<span class="sourceLineNo">304</span><a name="line.304"></a>
+<span class="sourceLineNo">305</span>    validateGetPartitionSize(cache, 0.1f, 0.5f);<a name="line.305"></a>
+<span class="sourceLineNo">306</span>    validateGetPartitionSize(cache, 0.7f, 0.5f);<a name="line.306"></a>
+<span class="sourceLineNo">307</span>    validateGetPartitionSize(cache, 0.2f, 0.5f);<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>  @Test<a name="line.310"></a>
+<span class="sourceLineNo">311</span>  public void testValidBucketCacheConfigs() throws IOException {<a name="line.311"></a>
+<span class="sourceLineNo">312</span>    Configuration conf = HBaseConfiguration.create();<a name="line.312"></a>
+<span class="sourceLineNo">313</span>    conf.setFloat(BucketCache.ACCEPT_FACTOR_CONFIG_NAME, 0.9f);<a name="line.313"></a>
+<span class="sourceLineNo">314</span>    conf.setFloat(BucketCache.MIN_FACTOR_CONFIG_NAME, 0.5f);<a name="line.314"></a>
+<span class="sourceLineNo">315</span>    conf.setFloat(BucketCache.EXTRA_FREE_FACTOR_CONFIG_NAME, 0.5f);<a name="line.315"></a>
+<span class="sourceLineNo">316</span>    conf.setFloat(BucketCache.SINGLE_FACTOR_CONFIG_NAME, 0.1f);<a name="line.316"></a>
+<span class="sourceLineNo">317</span>    conf.setFloat(BucketCache.MULTI_FACTOR_CONFIG_NAME, 0.7f);<a name="line.317"></a>
+<span class="sourceLineNo">318</span>    conf.setFloat(BucketCache.MEMORY_FACTOR_CONFIG_NAME, 0.2f);<a name="line.318"></a>
+<span class="sourceLineNo">319</span><a name="line.319"></a>
+<span class="sourceLineNo">320</span>    BucketCache cache = new BucketCache(ioEngineName, capacitySize, constructedBlockSize,<a name="line.320"></a>
+<span class="sourceLineNo">321</span>        constructedBlockSizes, writeThreads, writerQLen, persistencePath, 100, conf);<a name="line.321"></a>
+<span class="sourceLineNo">322</span><a name="line.322"></a>
+<span class="sourceLineNo">323</span>    assertEquals(BucketCache.ACCEPT_FACTOR_CONFIG_NAME + " failed to propagate.", 0.9f,<a name="line.323"></a>
+<span class="sourceLineNo">324</span>        cache.getAcceptableFactor(), 0);<a name="line.324"></a>
+<span class="sourceLineNo">325</span>    assertEquals(BucketCache.MIN_FACTOR_CONFIG_NAME + " failed to propagate.", 0.5f,<a name="line.325"></a>
+<span class="sourceLineNo">326</span>        cache.getMinFactor(), 0);<a name="line.326"></a>
+<span class="sourceLineNo">327</span>    assertEquals(BucketCache.EXTRA_FREE_FACTOR_CONFIG_NAME + " failed to propagate.", 0.5f,<a name="line.327"></a>
+<span class="sourceLineNo">328</span>        cache.getExtraFreeFactor(), 0);<a name="line.328"></a>
+<span class="sourceLineNo">329</span>    assertEquals(BucketCache.SINGLE_FACTOR_CONFIG_NAME + " failed to propagate.", 0.1f,<a name="line.329"></a>
+<span class="sourceLineNo">330</span>        cache.getSingleFactor(), 0);<a name="line.330"></a>
+<span class="sourceLineNo">331</span>    assertEquals(BucketCache.MULTI_FACTOR_CONFIG_NAME + " failed to propagate.", 0.7f,<a name="line.331"></a>
+<span class="sourceLineNo">332</span>        cache.getMultiFactor(), 0);<a name="line.332"></a>
+<span class="sourceLineNo">333</span>    assertEquals(BucketCache.MEMORY_FACTOR_CONFIG_NAME + " failed to propagate.", 0.2f,<a name="line.333"></a>
+<span class="sourceLineNo">334</span>        cache.getMemoryFactor(), 0);<a name="line.334"></a>
+<span class="sourceLineNo">335</span>  }<a name="line.335"></a>
+<span class="sourceLineNo">336</span><a name="line.336"></a>
+<span class="sourceLineNo">337</span>  @Test<a name="line.337"></a>
+<span class="sourceLineNo">338</span>  public void testInvalidAcceptFactorConfig() throws IOException {<a name="line.338"></a>
+<span class="sourceLineNo">339</span>    float[] configValues = {-1f, 0.2f, 0.86f, 1.05f};<a name="line.339"></a>
+<span class="sourceLineNo">340</span>    boolean[] expectedOutcomes = {false, false, true, false};<a name="line.340"></a>
+<span class="sourceLineNo">341</span>    Map&lt;String, float[]&gt; configMappings = ImmutableMap.of(BucketCache.ACCEPT_FACTOR_CONFIG_NAME, configValues);<a name="line.341"></a>
+<span class="sourceLineNo">342</span>    Configuration conf = HBaseConfiguration.create();<a name="line.342"></a>
+<span class="sourceLineNo">343</span>    checkConfigValues(conf, configMappings, expectedOutcomes);<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>  @Test<a name="line.346"></a>
+<span class="sourceLineNo">347</span>  public void testInvalidMinFactorConfig() throws IOException {<a name="line.347"></a>
+<span class="sourceLineNo">348</span>    float[] configValues = {-1f, 0f, 0.96f, 1.05f};<a name="line.348"></a>
+<span class="sourceLineNo">349</span>    //throws due to &lt;0, in expected range, minFactor &gt; acceptableFactor, &gt; 1.0<a name="line.349"></a>
+<span class="sourceLineNo">350</span>    boolean[] expectedOutcomes = {false, true, false, false};<a name="line.350"></a>
+<span class="sourceLineNo">351</span>    Map&lt;String, float[]&gt; configMappings = ImmutableMap<a name="line.351"></a>
+<span class="sourceLineNo">352</span>      .of(BucketCache.MIN_FACTOR_CONFIG_NAME, configValues);<a name="line.352"></a>
+<span class="sourceLineNo">353</span>    Configuration conf = HBaseConfiguration.create();<a name="line.353"></a>
+<span class="sourceLineNo">354</span>    checkConfigValues(conf, configMappings, expectedOutcomes);<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">357</span>  @Test<a name="line.357"></a>
+<span class="sourceLineNo">358</span>  public void testInvalidExtraFreeFactorConfig() throws IOException {<a name="line.358"></a>
+<span class="sourceLineNo">359</span>    float[] configValues = {-1f, 0f, 0.2f, 1.05f};<a name="line.359"></a>
+<span class="sourceLineNo">360</span>    //throws due to &lt;0, in expected range, in expected range, config can be &gt; 1.0<a name="line.360"></a>
+<span class="sourceLineNo">361</span>    boolean[] expectedOutcomes = {false, true, true, true};<a name="line.361"></a>
+<span class="sourceLineNo">362</span>    Map&lt;String, float[]&gt; configMappings = ImmutableMap.of(BucketCache.EXTRA_FREE_FACTOR_CONFIG_NAME, configValues);<a name="line.362"></a>
+<span class="sourceLineNo">363</span>    Configuration conf = HBaseConfiguration.create();<a name="line.363"></a>
+<span class="sourceLineNo">364</span>    checkConfigValues(conf, configMappings, expectedOutcomes);<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>  @Test<a name="line.367"></a>
+<span class="sourceLineNo">368</span>  public void testInvalidCacheSplitFactorConfig() throws IOException {<a name="line.368"></a>
+<span class="sourceLineNo">369</span>    float[] singleFactorConfigValues = {0.2f, 0f, -0.2f, 1f};<a name="line.369"></a>
+<span class="sourceLineNo">370</span>    float[] multiFactorConfigValues = {0.4f, 0f, 1f, .05f};<a name="line.370"></a>
+<span class="sourceLineNo">371</span>    float[] memoryFactorConfigValues = {0.4f, 0f, 0.2f, .5f};<a name="line.371"></a>
+<span class="sourceLineNo">372</span>    // All configs add up to 1.0 and are between 0 and 1.0, configs don't add to 1.0, configs can't be negative, configs don't add to 1.0<a name="line.372"></a>
+<span class="sourceLineNo">373</span>    boolean[] expectedOutcomes = {true, false, false, false};<a name="line.373"></a>
+<span class="sourceLineNo">374</span>    Map&lt;String, float[]&gt; configMappings = ImmutableMap.of(BucketCache.SINGLE_FACTOR_CONFIG_NAME,<a name="line.374"></a>
+<span class="sourceLineNo">375</span>        singleFactorConfigValues, BucketCache.MULTI_FACTOR_CONFIG_NAME, multiFactorConfigValues,<a name="line.375"></a>
+<span class="sourceLineNo">376</span>        BucketCache.MEMORY_FACTOR_CONFIG_NAME, memoryFactorConfigValues);<a name="line.376"></a>
+<span class="sourceLineNo">377</span>    Configuration conf = HBaseConfiguration.create();<a name="line.377"></a>
+<span class="sourceLineNo">378</span>    checkConfigValues(conf, configMappings, expectedOutcomes);<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>  private void checkConfigValues(Configuration conf, Map&lt;String, float[]&gt; configMap, boolean[] expectSuccess) throws IOException {<a name="line.381"></a>
+<span class="sourceLineNo">382</span>    Set&lt;String&gt; configNames = configMap.keySet();<a name="line.382"></a>
+<span class="sourceLineNo">383</span>    for (int i = 0; i &lt; expectSuccess.length; i++) {<a name="line.383"></a>
+<span class="sourceLineNo">384</span>      try {<a name="line.384"></a>
+<span class="sourceLineNo">385</span>        for (String configName : configNames) {<a name="line.385"></a>
+<span class="sourceLineNo">386</span>          conf.setFloat(configName, configMap.get(configName)[i]);<a name="line.386"></a>
+<span class="sourceLineNo">387</span>        }<a name="line.387"></a>
+<span class="sourceLineNo">388</span>        BucketCache cache = new BucketCache(ioEngineName, capacitySize, constructedBlockSize,<a name="line.388"></a>
+<span class="sourceLineNo">389</span>            constructedBlockSizes, writeThreads, writerQLen, persistencePath, 100, conf);<a name="line.389"></a>
+<span class="sourceLineNo">390</span>        assertTrue("Created BucketCache and expected it to succeed: " + expectSuccess[i] + ", but it actually was: " + !expectSuccess[i], expectSuccess[i]);<a name="line.390"></a>
+<span class="sourceLineNo">391</span>      } catch (IllegalArgumentException e) {<a name="line.391"></a>
+<span class="sourceLineNo">392</span>        assertFalse("Created BucketCache and expected it to succeed: " + expectSuccess[i] + ", but it actually was: " + !expectSuccess[i], expectSuccess[i]);<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><a name="line.396"></a>
+<span class="sourceLineNo">397</span>  private void validateGetPartitionSize(BucketCache bucketCache, float partitionFactor, float minFactor) {<a name="line.397"></a>
+<span class="sourceLineNo">398</span>    long expectedOutput = (long) Math.floor(bucketCache.getAllocator().getTotalSize() * partitionFactor * minFactor);<a name="line.398"></a>
+<span class="sourceLineNo">399</span>    assertEquals(expectedOutput, bucketCache.getPartitionSize(partitionFactor));<a name="line.399"></a>
+<span class="sourceLineNo">400</span>  }<a name="line.400"></a>
+<span class="sourceLineNo">401</span><a name="line.401"></a>
+<span class="sourceLineNo">402</span>  @Test<a name="line.402"></a>
+<span class="sourceLineNo">403</span>  public void testOffsetProducesPositiveOutput() {<a name="line.403"></a>
+<span class="sourceLineNo">404</span>    //This number is picked because it produces negative output if the values isn't ensured to be positive.<a name="line.404"></a>
+<span class="sourceLineNo">405</span>    //See HBASE-18757 for more information.<a name="line.405"></a>
+<span class="sourceLineNo">406</span>    long testValue = 549888460800L;<a name="line.406"></a>
+<span class="sourceLineNo">407</span>    BucketCache.BucketEntry bucketEntry = new BucketCache.BucketEntry(testValue, 10, 10L, true);<a name="line.407"></a>
+<span class="sourceLineNo">408</span>    assertEquals(testValue, bucketEntry.offset());<a name="line.408"></a>
+<span class="sourceLineNo">409</span>  }<a name="line.409"></a>
+<span class="sourceLineNo">410</span><a name="line.410"></a>
+<span class="sourceLineNo">411</span>  @Test<a name="line.411"></a>
+<span class="sourceLineNo">412</span>  public void testCacheBlockNextBlockMetadataMissing() {<a name="line.412"></a>
+<span class="sourceLineNo">413</span>    int size = 100;<a name="line.413"></a>
+<span class="sourceLineNo">414</span>    int length = HConstants.HFILEBLOCK_HEADER_SIZE + size;<a name="line.414"></a>
+<span class="sourceLineNo">415</span>    byte[] byteArr = new byte[length];<a name="line.415"></a>
+<span class="sourceLineNo">416</span>    ByteBuffer buf = ByteBuffer.wrap(byteArr, 0, size);<a name="line.416"></a>
+<span class="sourceLineNo">417</span>    HFileContext meta = new HFileContextBuilder().build();<a name="line.417"></a>
+<span class="sourceLineNo">418</span>    HFileBlock blockWithNextBlockMetadata = new HFileBlock(BlockType.DATA, size, size, -1, buf,<a name="line.418"></a>
+<span class="sourceLineNo">419</span>        HFileBlock.FILL_HEADER, -1, 52, -1, meta);<a name="line.419"></a>
+<span class="sourceLineNo">420</span>    HFileBlock blockWithoutNextBlockMetadata = new HFileBlock(BlockType.DATA, size, size, -1, buf,<a name="line.420"></a>
+<span class="sourceLineNo">421</span>        HFileBlock.FILL_HEADER, -1, -1, -1, meta);<a name="line.421"></a>
+<span class="sourceLineNo">422</span><a name="line.422"></a>
+<span class="sourceLineNo">423</span>    BlockCacheKey key = new BlockCacheKey("key1", 0);<a name="line.423"></a>
+<span class="sourceLineNo">424</span>    ByteBuffer actualBuffer = ByteBuffer.allocate(length);<a name="line.424"></a>
+<span class="sourceLineNo">425</span>    ByteBuffer block1Buffer = ByteBuffer.allocate(length);<a name="line.425"></a>
+<span class="sourceLineNo">426</span>    ByteBuffer block2Buffer = ByteBuffer.allocate(length);<a name="line.426"></a>
+<span class="sourceLineNo">427</span>    blockWithNextBlockMetadata.serialize(block1Buffer, true);<a name="line.427"></a>
+<span class="sourceLineNo">428</span>    blockWithoutNextBlockMetadata.serialize(block2Buffer, true);<a name="line.428"></a>
+<span class="sourceLineNo">429</span><a name="line.429"></a>
+<span class="sourceLineNo">430</span>    //Add blockWithNextBlockMetadata, expect blockWithNextBlockMetadata back.<a name="line.430"></a>
+<span class="sourceLineNo">431</span>    CacheTestUtils.getBlockAndAssertEquals(cache, key, blockWithNextBlockMetadata, actualBuffer,<a name="line.431"></a>
+<span class="sourceLineNo">432</span>        block1Buffer);<a name="line.432"></a>
+<span class="sourceLineNo">433</span><a name="line.433"></a>
+<span class="sourceLineNo">434</span>    //Add blockWithoutNextBlockMetada, expect blockWithNextBlockMetadata back.<a name="line.434"></a>
+<span class="sourceLineNo">435</span>    CacheTestUtils.getBlockAndAssertEquals(cache, key, blockWithoutNextBlockMetadata, actualBuffer,<a name="line.435"></a>
+<span class="sourceLineNo">436</span>        block1Buffer);<a name="line.436"></a>
+<span class="sourceLineNo">437</span><a name="line.437"></a>
+<span class="sourceLineNo">438</span>    //Clear and add blockWithoutNextBlockMetadata<a name="line.438"></a>
+<span class="sourceLineNo">439</span>    cache.evictBlock(key);<a name="line.439"></a>
+<span class="sourceLineNo">440</span>    assertNull(cache.getBlock(key, false, false, false));<a name="line.440"></a>
+<span class="sourceLineNo">441</span>    CacheTestUtils.getBlockAndAssertEquals(cache, key, blockWithoutNextBlockMetadata, actualBuffer,<a name="line.441"></a>
+<span class="sourceLineNo">442</span>        block2Buffer);<a name="line.442"></a>
+<span class="sourceLineNo">443</span><a name="line.443"></a>
+<span class="sourceLineNo">444</span>    //Add blockWithNextBlockMetadata, expect blockWithNextBlockMetadata to replace.<a name="line.444"></a>
+<span class="sourceLineNo">445</span>    CacheTestUtils.getBlockAndAssertEquals(cache, key, blockWithNextBlockMetadata, actualBuffer,<a name="line.445"></a>
+<span class="sourceLineNo">446</span>        block1Buffer);<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>
 
 
 


[10/50] hbase-site git commit: Published site at 26babcf013de696b899d76a3c39434b794440d8d.

Posted by gi...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.CachedItem.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.CachedItem.html b/testdevapidocs/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.CachedItem.html
index 5cc06e0..3061419 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.CachedItem.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.CachedItem.html
@@ -117,7 +117,7 @@ var activeTableTab = "activeTableTab";
 </dl>
 <hr>
 <br>
-<pre>private static class <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#line.852">TestLruBlockCache.CachedItem</a>
+<pre>private static class <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#line.906">TestLruBlockCache.CachedItem</a>
 extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true" title="class or interface in java.lang">Object</a>
 implements org.apache.hadoop.hbase.io.hfile.Cacheable</pre>
 </li>
@@ -229,7 +229,8 @@ implements org.apache.hadoop.hbase.io.hfile.Cacheable</pre>
 </tr>
 <tr id="i6" class="altColor">
 <td class="colFirst"><code>void</code></td>
-<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.CachedItem.html#serialize-java.nio.ByteBuffer-">serialize</a></span>(<a href="https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html?is-external=true" title="class or interface in java.nio">ByteBuffer</a>&nbsp;destination)</code>&nbsp;</td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.CachedItem.html#serialize-java.nio.ByteBuffer-boolean-">serialize</a></span>(<a href="https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html?is-external=true" title="class or interface in java.nio">ByteBuffer</a>&nbsp;destination,
+         boolean&nbsp;includeNextBlockMetadata)</code>&nbsp;</td>
 </tr>
 </table>
 <ul class="blockList">
@@ -259,7 +260,7 @@ implements org.apache.hadoop.hbase.io.hfile.Cacheable</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>cacheKey</h4>
-<pre>org.apache.hadoop.hbase.io.hfile.BlockCacheKey <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.CachedItem.html#line.853">cacheKey</a></pre>
+<pre>org.apache.hadoop.hbase.io.hfile.BlockCacheKey <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.CachedItem.html#line.907">cacheKey</a></pre>
 </li>
 </ul>
 <a name="size">
@@ -268,7 +269,7 @@ implements org.apache.hadoop.hbase.io.hfile.Cacheable</pre>
 <ul class="blockListLast">
 <li class="blockList">
 <h4>size</h4>
-<pre>int <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.CachedItem.html#line.854">size</a></pre>
+<pre>int <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.CachedItem.html#line.908">size</a></pre>
 </li>
 </ul>
 </li>
@@ -285,7 +286,7 @@ implements org.apache.hadoop.hbase.io.hfile.Cacheable</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>CachedItem</h4>
-<pre><a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.CachedItem.html#line.856">CachedItem</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;blockName,
+<pre><a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.CachedItem.html#line.910">CachedItem</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;blockName,
            int&nbsp;size,
            int&nbsp;offset)</pre>
 </li>
@@ -296,7 +297,7 @@ implements org.apache.hadoop.hbase.io.hfile.Cacheable</pre>
 <ul class="blockListLast">
 <li class="blockList">
 <h4>CachedItem</h4>
-<pre><a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.CachedItem.html#line.861">CachedItem</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;blockName,
+<pre><a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.CachedItem.html#line.915">CachedItem</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;blockName,
            int&nbsp;size)</pre>
 </li>
 </ul>
@@ -314,7 +315,7 @@ implements org.apache.hadoop.hbase.io.hfile.Cacheable</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>heapSize</h4>
-<pre>public&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.CachedItem.html#line.868">heapSize</a>()</pre>
+<pre>public&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.CachedItem.html#line.922">heapSize</a>()</pre>
 <div class="block">The size of this item reported to the block cache layer</div>
 <dl>
 <dt><span class="overrideSpecifyLabel">Specified by:</span></dt>
@@ -328,7 +329,7 @@ implements org.apache.hadoop.hbase.io.hfile.Cacheable</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>cacheBlockHeapSize</h4>
-<pre>public&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.CachedItem.html#line.873">cacheBlockHeapSize</a>()</pre>
+<pre>public&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.CachedItem.html#line.927">cacheBlockHeapSize</a>()</pre>
 <div class="block">Size of the cache block holding this item. Used for verification.</div>
 </li>
 </ul>
@@ -338,7 +339,7 @@ implements org.apache.hadoop.hbase.io.hfile.Cacheable</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>getSerializedLength</h4>
-<pre>public&nbsp;int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.CachedItem.html#line.880">getSerializedLength</a>()</pre>
+<pre>public&nbsp;int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.CachedItem.html#line.934">getSerializedLength</a>()</pre>
 <dl>
 <dt><span class="overrideSpecifyLabel">Specified by:</span></dt>
 <dd><code>getSerializedLength</code>&nbsp;in interface&nbsp;<code>org.apache.hadoop.hbase.io.hfile.Cacheable</code></dd>
@@ -351,20 +352,21 @@ implements org.apache.hadoop.hbase.io.hfile.Cacheable</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>getDeserializer</h4>
-<pre>public&nbsp;org.apache.hadoop.hbase.io.hfile.CacheableDeserializer&lt;org.apache.hadoop.hbase.io.hfile.Cacheable&gt;&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.CachedItem.html#line.885">getDeserializer</a>()</pre>
+<pre>public&nbsp;org.apache.hadoop.hbase.io.hfile.CacheableDeserializer&lt;org.apache.hadoop.hbase.io.hfile.Cacheable&gt;&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.CachedItem.html#line.939">getDeserializer</a>()</pre>
 <dl>
 <dt><span class="overrideSpecifyLabel">Specified by:</span></dt>
 <dd><code>getDeserializer</code>&nbsp;in interface&nbsp;<code>org.apache.hadoop.hbase.io.hfile.Cacheable</code></dd>
 </dl>
 </li>
 </ul>
-<a name="serialize-java.nio.ByteBuffer-">
+<a name="serialize-java.nio.ByteBuffer-boolean-">
 <!--   -->
 </a>
 <ul class="blockList">
 <li class="blockList">
 <h4>serialize</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.CachedItem.html#line.890">serialize</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html?is-external=true" title="class or interface in java.nio">ByteBuffer</a>&nbsp;destination)</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.CachedItem.html#line.944">serialize</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html?is-external=true" title="class or interface in java.nio">ByteBuffer</a>&nbsp;destination,
+                      boolean&nbsp;includeNextBlockMetadata)</pre>
 <dl>
 <dt><span class="overrideSpecifyLabel">Specified by:</span></dt>
 <dd><code>serialize</code>&nbsp;in interface&nbsp;<code>org.apache.hadoop.hbase.io.hfile.Cacheable</code></dd>
@@ -377,7 +379,7 @@ implements org.apache.hadoop.hbase.io.hfile.Cacheable</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>getBlockType</h4>
-<pre>public&nbsp;org.apache.hadoop.hbase.io.hfile.BlockType&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.CachedItem.html#line.894">getBlockType</a>()</pre>
+<pre>public&nbsp;org.apache.hadoop.hbase.io.hfile.BlockType&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.CachedItem.html#line.948">getBlockType</a>()</pre>
 <dl>
 <dt><span class="overrideSpecifyLabel">Specified by:</span></dt>
 <dd><code>getBlockType</code>&nbsp;in interface&nbsp;<code>org.apache.hadoop.hbase.io.hfile.Cacheable</code></dd>
@@ -390,7 +392,7 @@ implements org.apache.hadoop.hbase.io.hfile.Cacheable</pre>
 <ul class="blockListLast">
 <li class="blockList">
 <h4>getMemoryType</h4>
-<pre>public&nbsp;org.apache.hadoop.hbase.io.hfile.Cacheable.MemoryType&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.CachedItem.html#line.899">getMemoryType</a>()</pre>
+<pre>public&nbsp;org.apache.hadoop.hbase.io.hfile.Cacheable.MemoryType&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.CachedItem.html#line.953">getMemoryType</a>()</pre>
 <dl>
 <dt><span class="overrideSpecifyLabel">Specified by:</span></dt>
 <dd><code>getMemoryType</code>&nbsp;in interface&nbsp;<code>org.apache.hadoop.hbase.io.hfile.Cacheable</code></dd>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html b/testdevapidocs/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html
index 5045d39..5222f12 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html
@@ -18,7 +18,7 @@
     catch(err) {
     }
 //-->
-var methods = {"i0":10,"i1":10,"i2":10,"i3":10,"i4":10,"i5":10,"i6":10,"i7":10,"i8":10,"i9":10,"i10":10,"i11":10,"i12":10,"i13":10,"i14":10,"i15":10};
+var methods = {"i0":10,"i1":10,"i2":10,"i3":10,"i4":10,"i5":10,"i6":10,"i7":10,"i8":10,"i9":10,"i10":10,"i11":10,"i12":10,"i13":10,"i14":10,"i15":10,"i16":10};
 var tabs = {65535:["t0","All Methods"],2:["t2","Instance Methods"],8:["t4","Concrete Methods"]};
 var altColor = "altColor";
 var rowColor = "rowColor";
@@ -109,7 +109,7 @@ var activeTableTab = "activeTableTab";
 <li class="blockList">
 <hr>
 <br>
-<pre>public class <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#line.53">TestLruBlockCache</a>
+<pre>public class <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#line.54">TestLruBlockCache</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">Tests the concurrent LruBlockCache.<p>
 
@@ -222,42 +222,46 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 </tr>
 <tr id="i6" class="altColor">
 <td class="colFirst"><code>void</code></td>
-<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#testCacheEvictionInMemoryForceMode--">testCacheEvictionInMemoryForceMode</a></span>()</code>&nbsp;</td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#testCacheBlockNextBlockMetadataMissing--">testCacheBlockNextBlockMetadataMissing</a></span>()</code>&nbsp;</td>
 </tr>
 <tr id="i7" class="rowColor">
 <td class="colFirst"><code>void</code></td>
-<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#testCacheEvictionSimple--">testCacheEvictionSimple</a></span>()</code>&nbsp;</td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#testCacheEvictionInMemoryForceMode--">testCacheEvictionInMemoryForceMode</a></span>()</code>&nbsp;</td>
 </tr>
 <tr id="i8" class="altColor">
 <td class="colFirst"><code>void</code></td>
-<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#testCacheEvictionThreadSafe--">testCacheEvictionThreadSafe</a></span>()</code>&nbsp;</td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#testCacheEvictionSimple--">testCacheEvictionSimple</a></span>()</code>&nbsp;</td>
 </tr>
 <tr id="i9" class="rowColor">
 <td class="colFirst"><code>void</code></td>
-<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#testCacheEvictionThreePriorities--">testCacheEvictionThreePriorities</a></span>()</code>&nbsp;</td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#testCacheEvictionThreadSafe--">testCacheEvictionThreadSafe</a></span>()</code>&nbsp;</td>
 </tr>
 <tr id="i10" class="altColor">
 <td class="colFirst"><code>void</code></td>
-<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#testCacheEvictionTwoPriorities--">testCacheEvictionTwoPriorities</a></span>()</code>&nbsp;</td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#testCacheEvictionThreePriorities--">testCacheEvictionThreePriorities</a></span>()</code>&nbsp;</td>
 </tr>
 <tr id="i11" class="rowColor">
 <td class="colFirst"><code>void</code></td>
-<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#testCacheSimple--">testCacheSimple</a></span>()</code>&nbsp;</td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#testCacheEvictionTwoPriorities--">testCacheEvictionTwoPriorities</a></span>()</code>&nbsp;</td>
 </tr>
 <tr id="i12" class="altColor">
 <td class="colFirst"><code>void</code></td>
-<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#testMaxBlockSize--">testMaxBlockSize</a></span>()</code>&nbsp;</td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#testCacheSimple--">testCacheSimple</a></span>()</code>&nbsp;</td>
 </tr>
 <tr id="i13" class="rowColor">
 <td class="colFirst"><code>void</code></td>
-<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#testPastNPeriodsMetrics--">testPastNPeriodsMetrics</a></span>()</code>&nbsp;</td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#testMaxBlockSize--">testMaxBlockSize</a></span>()</code>&nbsp;</td>
 </tr>
 <tr id="i14" class="altColor">
 <td class="colFirst"><code>void</code></td>
-<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#testResizeBlockCache--">testResizeBlockCache</a></span>()</code>&nbsp;</td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#testPastNPeriodsMetrics--">testPastNPeriodsMetrics</a></span>()</code>&nbsp;</td>
 </tr>
 <tr id="i15" class="rowColor">
 <td class="colFirst"><code>void</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#testResizeBlockCache--">testResizeBlockCache</a></span>()</code>&nbsp;</td>
+</tr>
+<tr id="i16" class="altColor">
+<td class="colFirst"><code>void</code></td>
 <td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#testScanResistance--">testScanResistance</a></span>()</code>&nbsp;</td>
 </tr>
 </table>
@@ -288,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>CLASS_RULE</h4>
-<pre>public static final&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/HBaseClassTestRule.html" title="class in org.apache.hadoop.hbase">HBaseClassTestRule</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#line.56">CLASS_RULE</a></pre>
+<pre>public static final&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/HBaseClassTestRule.html" title="class in org.apache.hadoop.hbase">HBaseClassTestRule</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#line.57">CLASS_RULE</a></pre>
 </li>
 </ul>
 </li>
@@ -305,7 +309,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>TestLruBlockCache</h4>
-<pre>public&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#line.53">TestLruBlockCache</a>()</pre>
+<pre>public&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#line.54">TestLruBlockCache</a>()</pre>
 </li>
 </ul>
 </li>
@@ -322,7 +326,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>testCacheEvictionThreadSafe</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#line.60">testCacheEvictionThreadSafe</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#line.61">testCacheEvictionThreadSafe</a>()
                                  throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
 <dl>
 <dt><span class="throwsLabel">Throws:</span></dt>
@@ -336,7 +340,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>testBackgroundEvictionThread</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#line.112">testBackgroundEvictionThread</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#line.113">testBackgroundEvictionThread</a>()
                                   throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
 <dl>
 <dt><span class="throwsLabel">Throws:</span></dt>
@@ -350,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>testCacheSimple</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#line.162">testCacheSimple</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#line.163">testCacheSimple</a>()
                      throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
 <dl>
 <dt><span class="throwsLabel">Throws:</span></dt>
@@ -364,7 +368,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>testCacheEvictionSimple</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#line.221">testCacheEvictionSimple</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#line.222">testCacheEvictionSimple</a>()
                              throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
 <dl>
 <dt><span class="throwsLabel">Throws:</span></dt>
@@ -378,7 +382,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>testCacheEvictionTwoPriorities</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#line.261">testCacheEvictionTwoPriorities</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#line.262">testCacheEvictionTwoPriorities</a>()
                                     throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
 <dl>
 <dt><span class="throwsLabel">Throws:</span></dt>
@@ -392,7 +396,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>testCacheEvictionThreePriorities</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#line.320">testCacheEvictionThreePriorities</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#line.321">testCacheEvictionThreePriorities</a>()
                                       throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
 <dl>
 <dt><span class="throwsLabel">Throws:</span></dt>
@@ -406,7 +410,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>testCacheEvictionInMemoryForceMode</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#line.443">testCacheEvictionInMemoryForceMode</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#line.444">testCacheEvictionInMemoryForceMode</a>()
                                         throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
 <dl>
 <dt><span class="throwsLabel">Throws:</span></dt>
@@ -420,7 +424,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>testScanResistance</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#line.549">testScanResistance</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#line.550">testScanResistance</a>()
                         throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
 <dl>
 <dt><span class="throwsLabel">Throws:</span></dt>
@@ -434,7 +438,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>testMaxBlockSize</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#line.614">testMaxBlockSize</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#line.615">testMaxBlockSize</a>()
                       throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
 <dl>
 <dt><span class="throwsLabel">Throws:</span></dt>
@@ -448,7 +452,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>testResizeBlockCache</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#line.653">testResizeBlockCache</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#line.654">testResizeBlockCache</a>()
                           throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
 <dl>
 <dt><span class="throwsLabel">Throws:</span></dt>
@@ -462,7 +466,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>testPastNPeriodsMetrics</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#line.718">testPastNPeriodsMetrics</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#line.719">testPastNPeriodsMetrics</a>()
                              throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
 <dl>
 <dt><span class="throwsLabel">Throws:</span></dt>
@@ -470,13 +474,22 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 </dl>
 </li>
 </ul>
+<a name="testCacheBlockNextBlockMetadataMissing--">
+<!--   -->
+</a>
+<ul class="blockList">
+<li class="blockList">
+<h4>testCacheBlockNextBlockMetadataMissing</h4>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#line.808">testCacheBlockNextBlockMetadataMissing</a>()</pre>
+</li>
+</ul>
 <a name="generateFixedBlocks-int-int-java.lang.String-">
 <!--   -->
 </a>
 <ul class="blockList">
 <li class="blockList">
 <h4>generateFixedBlocks</h4>
-<pre>private&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.CachedItem.html" title="class in org.apache.hadoop.hbase.io.hfile">TestLruBlockCache.CachedItem</a>[]&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#line.806">generateFixedBlocks</a>(int&nbsp;numBlocks,
+<pre>private&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.CachedItem.html" title="class in org.apache.hadoop.hbase.io.hfile">TestLruBlockCache.CachedItem</a>[]&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#line.860">generateFixedBlocks</a>(int&nbsp;numBlocks,
                                                            int&nbsp;size,
                                                            <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;pfx)</pre>
 </li>
@@ -487,7 +500,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>generateFixedBlocks</h4>
-<pre>private&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.CachedItem.html" title="class in org.apache.hadoop.hbase.io.hfile">TestLruBlockCache.CachedItem</a>[]&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#line.814">generateFixedBlocks</a>(int&nbsp;numBlocks,
+<pre>private&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.CachedItem.html" title="class in org.apache.hadoop.hbase.io.hfile">TestLruBlockCache.CachedItem</a>[]&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#line.868">generateFixedBlocks</a>(int&nbsp;numBlocks,
                                                            long&nbsp;size,
                                                            <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;pfx)</pre>
 </li>
@@ -498,7 +511,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>generateRandomBlocks</h4>
-<pre>private&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.CachedItem.html" title="class in org.apache.hadoop.hbase.io.hfile">TestLruBlockCache.CachedItem</a>[]&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#line.818">generateRandomBlocks</a>(int&nbsp;numBlocks,
+<pre>private&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.CachedItem.html" title="class in org.apache.hadoop.hbase.io.hfile">TestLruBlockCache.CachedItem</a>[]&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#line.872">generateRandomBlocks</a>(int&nbsp;numBlocks,
                                                             long&nbsp;maxSize)</pre>
 </li>
 </ul>
@@ -508,7 +521,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>calculateBlockSize</h4>
-<pre>private&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#line.827">calculateBlockSize</a>(long&nbsp;maxSize,
+<pre>private&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#line.881">calculateBlockSize</a>(long&nbsp;maxSize,
                                 int&nbsp;numBlocks)</pre>
 </li>
 </ul>
@@ -518,7 +531,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>calculateBlockSizeDefault</h4>
-<pre>private&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#line.839">calculateBlockSizeDefault</a>(long&nbsp;maxSize,
+<pre>private&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#line.893">calculateBlockSizeDefault</a>(long&nbsp;maxSize,
                                        int&nbsp;numBlocks)</pre>
 </li>
 </ul>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.MockedBucketCache.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.MockedBucketCache.html b/testdevapidocs/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.MockedBucketCache.html
index e3c4d0c..6b830cd 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.MockedBucketCache.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.MockedBucketCache.html
@@ -122,7 +122,7 @@ var activeTableTab = "activeTableTab";
 </dl>
 <hr>
 <br>
-<pre>private static class <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.101">TestBucketCache.MockedBucketCache</a>
+<pre>private static class <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.108">TestBucketCache.MockedBucketCache</a>
 extends org.apache.hadoop.hbase.io.hfile.bucket.BucketCache</pre>
 </li>
 </ul>
@@ -248,7 +248,7 @@ extends org.apache.hadoop.hbase.io.hfile.bucket.BucketCache</pre>
 <ul class="blockListLast">
 <li class="blockList">
 <h4>MockedBucketCache</h4>
-<pre>public&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.MockedBucketCache.html#line.103">MockedBucketCache</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;ioEngineName,
+<pre>public&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.MockedBucketCache.html#line.110">MockedBucketCache</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;ioEngineName,
                          long&nbsp;capacity,
                          int&nbsp;blockSize,
                          int[]&nbsp;bucketSizes,
@@ -278,7 +278,7 @@ extends org.apache.hadoop.hbase.io.hfile.bucket.BucketCache</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>cacheBlock</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.MockedBucketCache.html#line.112">cacheBlock</a>(org.apache.hadoop.hbase.io.hfile.BlockCacheKey&nbsp;cacheKey,
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.MockedBucketCache.html#line.119">cacheBlock</a>(org.apache.hadoop.hbase.io.hfile.BlockCacheKey&nbsp;cacheKey,
                        org.apache.hadoop.hbase.io.hfile.Cacheable&nbsp;buf,
                        boolean&nbsp;inMemory)</pre>
 <dl>
@@ -295,7 +295,7 @@ extends org.apache.hadoop.hbase.io.hfile.bucket.BucketCache</pre>
 <ul class="blockListLast">
 <li class="blockList">
 <h4>cacheBlock</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.MockedBucketCache.html#line.120">cacheBlock</a>(org.apache.hadoop.hbase.io.hfile.BlockCacheKey&nbsp;cacheKey,
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.MockedBucketCache.html#line.124">cacheBlock</a>(org.apache.hadoop.hbase.io.hfile.BlockCacheKey&nbsp;cacheKey,
                        org.apache.hadoop.hbase.io.hfile.Cacheable&nbsp;buf)</pre>
 <dl>
 <dt><span class="overrideSpecifyLabel">Specified by:</span></dt>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html b/testdevapidocs/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html
index add8b14..c9a25ad 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html
@@ -18,7 +18,7 @@
     catch(err) {
     }
 //-->
-var methods = {"i0":10,"i1":10,"i2":9,"i3":9,"i4":10,"i5":10,"i6":10,"i7":10,"i8":10,"i9":10,"i10":10,"i11":10,"i12":10,"i13":10,"i14":10,"i15":10,"i16":10,"i17":10,"i18":10,"i19":10,"i20":10};
+var methods = {"i0":10,"i1":10,"i2":9,"i3":9,"i4":10,"i5":10,"i6":10,"i7":10,"i8":10,"i9":10,"i10":10,"i11":10,"i12":10,"i13":10,"i14":10,"i15":10,"i16":10,"i17":10,"i18":10,"i19":10,"i20":10,"i21":10};
 var tabs = {65535:["t0","All Methods"],1:["t1","Static Methods"],2:["t2","Instance Methods"],8:["t4","Concrete Methods"]};
 var altColor = "altColor";
 var rowColor = "rowColor";
@@ -109,7 +109,7 @@ var activeTableTab = "activeTableTab";
 <li class="blockList">
 <hr>
 <br>
-<pre>public class <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.63">TestBucketCache</a>
+<pre>public class <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.70">TestBucketCache</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">Basic test of BucketCache.Puts and gets.
  <p>
@@ -283,53 +283,57 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 </tr>
 <tr id="i8" class="altColor">
 <td class="colFirst"><code>void</code></td>
-<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#testCacheMultiThreadedSingleKey--">testCacheMultiThreadedSingleKey</a></span>()</code>&nbsp;</td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#testCacheBlockNextBlockMetadataMissing--">testCacheBlockNextBlockMetadataMissing</a></span>()</code>&nbsp;</td>
 </tr>
 <tr id="i9" class="rowColor">
 <td class="colFirst"><code>void</code></td>
-<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#testCacheSimple--">testCacheSimple</a></span>()</code>&nbsp;</td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#testCacheMultiThreadedSingleKey--">testCacheMultiThreadedSingleKey</a></span>()</code>&nbsp;</td>
 </tr>
 <tr id="i10" class="altColor">
 <td class="colFirst"><code>void</code></td>
-<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#testGetPartitionSize--">testGetPartitionSize</a></span>()</code>&nbsp;</td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#testCacheSimple--">testCacheSimple</a></span>()</code>&nbsp;</td>
 </tr>
 <tr id="i11" class="rowColor">
 <td class="colFirst"><code>void</code></td>
-<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#testHeapSizeChanges--">testHeapSizeChanges</a></span>()</code>&nbsp;</td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#testGetPartitionSize--">testGetPartitionSize</a></span>()</code>&nbsp;</td>
 </tr>
 <tr id="i12" class="altColor">
 <td class="colFirst"><code>void</code></td>
-<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#testInvalidAcceptFactorConfig--">testInvalidAcceptFactorConfig</a></span>()</code>&nbsp;</td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#testHeapSizeChanges--">testHeapSizeChanges</a></span>()</code>&nbsp;</td>
 </tr>
 <tr id="i13" class="rowColor">
 <td class="colFirst"><code>void</code></td>
-<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#testInvalidCacheSplitFactorConfig--">testInvalidCacheSplitFactorConfig</a></span>()</code>&nbsp;</td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#testInvalidAcceptFactorConfig--">testInvalidAcceptFactorConfig</a></span>()</code>&nbsp;</td>
 </tr>
 <tr id="i14" class="altColor">
 <td class="colFirst"><code>void</code></td>
-<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#testInvalidExtraFreeFactorConfig--">testInvalidExtraFreeFactorConfig</a></span>()</code>&nbsp;</td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#testInvalidCacheSplitFactorConfig--">testInvalidCacheSplitFactorConfig</a></span>()</code>&nbsp;</td>
 </tr>
 <tr id="i15" class="rowColor">
 <td class="colFirst"><code>void</code></td>
-<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#testInvalidMinFactorConfig--">testInvalidMinFactorConfig</a></span>()</code>&nbsp;</td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#testInvalidExtraFreeFactorConfig--">testInvalidExtraFreeFactorConfig</a></span>()</code>&nbsp;</td>
 </tr>
 <tr id="i16" class="altColor">
 <td class="colFirst"><code>void</code></td>
-<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#testMemoryLeak--">testMemoryLeak</a></span>()</code>&nbsp;</td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#testInvalidMinFactorConfig--">testInvalidMinFactorConfig</a></span>()</code>&nbsp;</td>
 </tr>
 <tr id="i17" class="rowColor">
 <td class="colFirst"><code>void</code></td>
-<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#testOffsetProducesPositiveOutput--">testOffsetProducesPositiveOutput</a></span>()</code>&nbsp;</td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#testMemoryLeak--">testMemoryLeak</a></span>()</code>&nbsp;</td>
 </tr>
 <tr id="i18" class="altColor">
 <td class="colFirst"><code>void</code></td>
-<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#testRetrieveFromFile--">testRetrieveFromFile</a></span>()</code>&nbsp;</td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#testOffsetProducesPositiveOutput--">testOffsetProducesPositiveOutput</a></span>()</code>&nbsp;</td>
 </tr>
 <tr id="i19" class="rowColor">
 <td class="colFirst"><code>void</code></td>
-<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#testValidBucketCacheConfigs--">testValidBucketCacheConfigs</a></span>()</code>&nbsp;</td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#testRetrieveFromFile--">testRetrieveFromFile</a></span>()</code>&nbsp;</td>
 </tr>
 <tr id="i20" class="altColor">
+<td class="colFirst"><code>void</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#testValidBucketCacheConfigs--">testValidBucketCacheConfigs</a></span>()</code>&nbsp;</td>
+</tr>
+<tr id="i21" class="rowColor">
 <td class="colFirst"><code>private void</code></td>
 <td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#validateGetPartitionSize-org.apache.hadoop.hbase.io.hfile.bucket.BucketCache-float-float-">validateGetPartitionSize</a></span>(org.apache.hadoop.hbase.io.hfile.bucket.BucketCache&nbsp;bucketCache,
                         float&nbsp;partitionFactor,
@@ -363,7 +367,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>CLASS_RULE</h4>
-<pre>public static final&nbsp;<a href="../../../../../../../org/apache/hadoop/hbase/HBaseClassTestRule.html" title="class in org.apache.hadoop.hbase">HBaseClassTestRule</a> <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.66">CLASS_RULE</a></pre>
+<pre>public static final&nbsp;<a href="../../../../../../../org/apache/hadoop/hbase/HBaseClassTestRule.html" title="class in org.apache.hadoop.hbase">HBaseClassTestRule</a> <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.73">CLASS_RULE</a></pre>
 </li>
 </ul>
 <a name="RAND">
@@ -372,7 +376,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>RAND</h4>
-<pre>private static final&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/Random.html?is-external=true" title="class or interface in java.util">Random</a> <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.69">RAND</a></pre>
+<pre>private static final&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/Random.html?is-external=true" title="class or interface in java.util">Random</a> <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.76">RAND</a></pre>
 </li>
 </ul>
 <a name="constructedBlockSize">
@@ -381,7 +385,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>constructedBlockSize</h4>
-<pre>public&nbsp;int <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.83">constructedBlockSize</a></pre>
+<pre>public&nbsp;int <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.90">constructedBlockSize</a></pre>
 </li>
 </ul>
 <a name="constructedBlockSizes">
@@ -390,7 +394,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>constructedBlockSizes</h4>
-<pre>public&nbsp;int[] <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.86">constructedBlockSizes</a></pre>
+<pre>public&nbsp;int[] <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.93">constructedBlockSizes</a></pre>
 </li>
 </ul>
 <a name="cache">
@@ -399,7 +403,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>cache</h4>
-<pre>org.apache.hadoop.hbase.io.hfile.bucket.BucketCache <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.88">cache</a></pre>
+<pre>org.apache.hadoop.hbase.io.hfile.bucket.BucketCache <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.95">cache</a></pre>
 </li>
 </ul>
 <a name="CACHE_SIZE">
@@ -408,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>CACHE_SIZE</h4>
-<pre>final&nbsp;int <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.89">CACHE_SIZE</a></pre>
+<pre>final&nbsp;int <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.96">CACHE_SIZE</a></pre>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
 <dd><a href="../../../../../../../constant-values.html#org.apache.hadoop.hbase.io.hfile.bucket.TestBucketCache.CACHE_SIZE">Constant Field Values</a></dd>
@@ -421,7 +425,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>NUM_BLOCKS</h4>
-<pre>final&nbsp;int <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.90">NUM_BLOCKS</a></pre>
+<pre>final&nbsp;int <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.97">NUM_BLOCKS</a></pre>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
 <dd><a href="../../../../../../../constant-values.html#org.apache.hadoop.hbase.io.hfile.bucket.TestBucketCache.NUM_BLOCKS">Constant Field Values</a></dd>
@@ -434,7 +438,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>BLOCK_SIZE</h4>
-<pre>final&nbsp;int <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.91">BLOCK_SIZE</a></pre>
+<pre>final&nbsp;int <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.98">BLOCK_SIZE</a></pre>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
 <dd><a href="../../../../../../../constant-values.html#org.apache.hadoop.hbase.io.hfile.bucket.TestBucketCache.BLOCK_SIZE">Constant Field Values</a></dd>
@@ -447,7 +451,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>NUM_THREADS</h4>
-<pre>final&nbsp;int <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.92">NUM_THREADS</a></pre>
+<pre>final&nbsp;int <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.99">NUM_THREADS</a></pre>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
 <dd><a href="../../../../../../../constant-values.html#org.apache.hadoop.hbase.io.hfile.bucket.TestBucketCache.NUM_THREADS">Constant Field Values</a></dd>
@@ -460,7 +464,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>NUM_QUERIES</h4>
-<pre>final&nbsp;int <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.93">NUM_QUERIES</a></pre>
+<pre>final&nbsp;int <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.100">NUM_QUERIES</a></pre>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
 <dd><a href="../../../../../../../constant-values.html#org.apache.hadoop.hbase.io.hfile.bucket.TestBucketCache.NUM_QUERIES">Constant Field Values</a></dd>
@@ -473,7 +477,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>capacitySize</h4>
-<pre>final&nbsp;long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.95">capacitySize</a></pre>
+<pre>final&nbsp;long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.102">capacitySize</a></pre>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
 <dd><a href="../../../../../../../constant-values.html#org.apache.hadoop.hbase.io.hfile.bucket.TestBucketCache.capacitySize">Constant Field Values</a></dd>
@@ -486,7 +490,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>writeThreads</h4>
-<pre>final&nbsp;int <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.96">writeThreads</a></pre>
+<pre>final&nbsp;int <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.103">writeThreads</a></pre>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
 <dd><a href="../../../../../../../constant-values.html#org.apache.hadoop.hbase.io.hfile.bucket.TestBucketCache.writeThreads">Constant Field Values</a></dd>
@@ -499,7 +503,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>writerQLen</h4>
-<pre>final&nbsp;int <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.97">writerQLen</a></pre>
+<pre>final&nbsp;int <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.104">writerQLen</a></pre>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
 <dd><a href="../../../../../../../constant-values.html#org.apache.hadoop.hbase.io.hfile.bucket.TestBucketCache.writerQLen">Constant Field Values</a></dd>
@@ -512,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>ioEngineName</h4>
-<pre><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/io/hfile/bucket/TestBucketCache.html#line.98">ioEngineName</a></pre>
+<pre><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/io/hfile/bucket/TestBucketCache.html#line.105">ioEngineName</a></pre>
 </li>
 </ul>
 <a name="persistencePath">
@@ -521,7 +525,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>persistencePath</h4>
-<pre><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/io/hfile/bucket/TestBucketCache.html#line.99">persistencePath</a></pre>
+<pre><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/io/hfile/bucket/TestBucketCache.html#line.106">persistencePath</a></pre>
 </li>
 </ul>
 </li>
@@ -538,7 +542,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>TestBucketCache</h4>
-<pre>public&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.63">TestBucketCache</a>()</pre>
+<pre>public&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.70">TestBucketCache</a>()</pre>
 </li>
 </ul>
 </li>
@@ -555,7 +559,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>data</h4>
-<pre>public static&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Iterable.html?is-external=true" title="class or interface in java.lang">Iterable</a>&lt;<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>[]&gt;&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.72">data</a>()</pre>
+<pre>public static&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Iterable.html?is-external=true" title="class or interface in java.lang">Iterable</a>&lt;<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>[]&gt;&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.79">data</a>()</pre>
 </li>
 </ul>
 <a name="setup--">
@@ -564,7 +568,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>setup</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.129">setup</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.130">setup</a>()
            throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/FileNotFoundException.html?is-external=true" title="class or interface in java.io">FileNotFoundException</a>,
                   <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>
@@ -580,7 +584,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>tearDown</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.136">tearDown</a>()</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.137">tearDown</a>()</pre>
 </li>
 </ul>
 <a name="randFrom-java.util.List-">
@@ -589,7 +593,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>randFrom</h4>
-<pre>private static&nbsp;&lt;T&gt;&nbsp;T&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.143">randFrom</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html?is-external=true" title="class or interface in java.util">List</a>&lt;T&gt;&nbsp;a)</pre>
+<pre>private static&nbsp;&lt;T&gt;&nbsp;T&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.144">randFrom</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html?is-external=true" title="class or interface in java.util">List</a>&lt;T&gt;&nbsp;a)</pre>
 <div class="block">Return a random element from <code>a</code>.</div>
 </li>
 </ul>
@@ -599,7 +603,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>testBucketAllocator</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.148">testBucketAllocator</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.149">testBucketAllocator</a>()
                          throws org.apache.hadoop.hbase.io.hfile.bucket.BucketAllocatorException</pre>
 <dl>
 <dt><span class="throwsLabel">Throws:</span></dt>
@@ -613,7 +617,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>testCacheSimple</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.184">testCacheSimple</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.185">testCacheSimple</a>()
                      throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
 <dl>
 <dt><span class="throwsLabel">Throws:</span></dt>
@@ -627,7 +631,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>testCacheMultiThreadedSingleKey</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.189">testCacheMultiThreadedSingleKey</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.190">testCacheMultiThreadedSingleKey</a>()
                                      throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
 <dl>
 <dt><span class="throwsLabel">Throws:</span></dt>
@@ -641,7 +645,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>testHeapSizeChanges</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.194">testHeapSizeChanges</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.195">testHeapSizeChanges</a>()
                          throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
 <dl>
 <dt><span class="throwsLabel">Throws:</span></dt>
@@ -655,7 +659,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>cacheAndWaitUntilFlushedToBucket</h4>
-<pre>private&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.201">cacheAndWaitUntilFlushedToBucket</a>(org.apache.hadoop.hbase.io.hfile.bucket.BucketCache&nbsp;cache,
+<pre>private&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.202">cacheAndWaitUntilFlushedToBucket</a>(org.apache.hadoop.hbase.io.hfile.bucket.BucketCache&nbsp;cache,
                                               org.apache.hadoop.hbase.io.hfile.BlockCacheKey&nbsp;cacheKey,
                                               org.apache.hadoop.hbase.io.hfile.Cacheable&nbsp;block)
                                        throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/InterruptedException.html?is-external=true" title="class or interface in java.lang">InterruptedException</a></pre>
@@ -671,7 +675,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>testMemoryLeak</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.210">testMemoryLeak</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.211">testMemoryLeak</a>()
                     throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
 <dl>
 <dt><span class="throwsLabel">Throws:</span></dt>
@@ -685,7 +689,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>testRetrieveFromFile</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.238">testRetrieveFromFile</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.239">testRetrieveFromFile</a>()
                           throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
 <dl>
 <dt><span class="throwsLabel">Throws:</span></dt>
@@ -699,7 +703,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>testBucketAllocatorLargeBuckets</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.283">testBucketAllocatorLargeBuckets</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.284">testBucketAllocatorLargeBuckets</a>()
                                      throws org.apache.hadoop.hbase.io.hfile.bucket.BucketAllocatorException</pre>
 <dl>
 <dt><span class="throwsLabel">Throws:</span></dt>
@@ -713,7 +717,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>testGetPartitionSize</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.291">testGetPartitionSize</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.292">testGetPartitionSize</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>
@@ -727,7 +731,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>testValidBucketCacheConfigs</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.310">testValidBucketCacheConfigs</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.311">testValidBucketCacheConfigs</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>
@@ -741,7 +745,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>testInvalidAcceptFactorConfig</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.337">testInvalidAcceptFactorConfig</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.338">testInvalidAcceptFactorConfig</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>
@@ -755,7 +759,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>testInvalidMinFactorConfig</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.346">testInvalidMinFactorConfig</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.347">testInvalidMinFactorConfig</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>
@@ -769,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>testInvalidExtraFreeFactorConfig</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.357">testInvalidExtraFreeFactorConfig</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.358">testInvalidExtraFreeFactorConfig</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>
@@ -783,7 +787,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>testInvalidCacheSplitFactorConfig</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.367">testInvalidCacheSplitFactorConfig</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.368">testInvalidCacheSplitFactorConfig</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>
@@ -797,7 +801,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>checkConfigValues</h4>
-<pre>private&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.380">checkConfigValues</a>(org.apache.hadoop.conf.Configuration&nbsp;conf,
+<pre>private&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.381">checkConfigValues</a>(org.apache.hadoop.conf.Configuration&nbsp;conf,
                                <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>,float[]&gt;&nbsp;configMap,
                                boolean[]&nbsp;expectSuccess)
                         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>
@@ -813,7 +817,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>validateGetPartitionSize</h4>
-<pre>private&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.396">validateGetPartitionSize</a>(org.apache.hadoop.hbase.io.hfile.bucket.BucketCache&nbsp;bucketCache,
+<pre>private&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.397">validateGetPartitionSize</a>(org.apache.hadoop.hbase.io.hfile.bucket.BucketCache&nbsp;bucketCache,
                                       float&nbsp;partitionFactor,
                                       float&nbsp;minFactor)</pre>
 </li>
@@ -821,10 +825,19 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <a name="testOffsetProducesPositiveOutput--">
 <!--   -->
 </a>
-<ul class="blockListLast">
+<ul class="blockList">
 <li class="blockList">
 <h4>testOffsetProducesPositiveOutput</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.402">testOffsetProducesPositiveOutput</a>()</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.403">testOffsetProducesPositiveOutput</a>()</pre>
+</li>
+</ul>
+<a name="testCacheBlockNextBlockMetadataMissing--">
+<!--   -->
+</a>
+<ul class="blockListLast">
+<li class="blockList">
+<h4>testCacheBlockNextBlockMetadataMissing</h4>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#line.412">testCacheBlockNextBlockMetadataMissing</a>()</pre>
 </li>
 </ul>
 </li>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/org/apache/hadoop/hbase/package-tree.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/org/apache/hadoop/hbase/package-tree.html b/testdevapidocs/org/apache/hadoop/hbase/package-tree.html
index 45c9c23..33caf32 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/package-tree.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/package-tree.html
@@ -570,15 +570,15 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true" title="class or interface in java.io">Serializable</a>)
 <ul>
-<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/ClusterManager.ServiceType.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">ClusterManager.ServiceType</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/PerformanceEvaluation.Counter.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">PerformanceEvaluation.Counter</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/HBaseClusterManager.CommandProvider.Operation.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">HBaseClusterManager.CommandProvider.Operation</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/IntegrationTestDDLMasterFailover.ACTION.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">IntegrationTestDDLMasterFailover.ACTION</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/IntegrationTestRegionReplicaPerf.Stat.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">IntegrationTestRegionReplicaPerf.Stat</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/RESTApiClusterManager.RoleCommand.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">RESTApiClusterManager.RoleCommand</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/ResourceChecker.Phase.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">ResourceChecker.Phase</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/RESTApiClusterManager.Service.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">RESTApiClusterManager.Service</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/PerformanceEvaluation.Counter.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">PerformanceEvaluation.Counter</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/IntegrationTestRegionReplicaPerf.Stat.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">IntegrationTestRegionReplicaPerf.Stat</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/ScanPerformanceEvaluation.ScanCounter.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">ScanPerformanceEvaluation.ScanCounter</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/HBaseClusterManager.CommandProvider.Operation.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">HBaseClusterManager.CommandProvider.Operation</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/ResourceChecker.Phase.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">ResourceChecker.Phase</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/ClusterManager.ServiceType.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">ClusterManager.ServiceType</span></a></li>
 </ul>
 </li>
 </ul>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/org/apache/hadoop/hbase/procedure/package-tree.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/org/apache/hadoop/hbase/procedure/package-tree.html b/testdevapidocs/org/apache/hadoop/hbase/procedure/package-tree.html
index a1c9b1d..28973e0 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/procedure/package-tree.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/procedure/package-tree.html
@@ -81,14 +81,14 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Object</span></a>
 <ul>
-<li type="circle">org.apache.hadoop.hbase.procedure.Procedure (implements java.util.concurrent.<a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Callable.html?is-external=true" title="class or interface in java.util.concurrent">Callable</a>&lt;V&gt;, org.apache.hadoop.hbase.errorhandling.ForeignExceptionListener)
+<li type="circle">org.apache.hadoop.hbase.procedure2.Procedure&lt;TEnvironment&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;)
 <ul>
-<li type="circle">org.apache.hadoop.hbase.procedure.<a href="../../../../../org/apache/hadoop/hbase/procedure/TestProcedure.LatchedProcedure.html" title="class in org.apache.hadoop.hbase.procedure"><span class="typeNameLink">TestProcedure.LatchedProcedure</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.procedure.<a href="../../../../../org/apache/hadoop/hbase/procedure/TestProcedureDescriber.TestProcedure.html" title="class in org.apache.hadoop.hbase.procedure"><span class="typeNameLink">TestProcedureDescriber.TestProcedure</span></a></li>
 </ul>
 </li>
-<li type="circle">org.apache.hadoop.hbase.procedure2.Procedure&lt;TEnvironment&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;)
+<li type="circle">org.apache.hadoop.hbase.procedure.Procedure (implements java.util.concurrent.<a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Callable.html?is-external=true" title="class or interface in java.util.concurrent">Callable</a>&lt;V&gt;, org.apache.hadoop.hbase.errorhandling.ForeignExceptionListener)
 <ul>
-<li type="circle">org.apache.hadoop.hbase.procedure.<a href="../../../../../org/apache/hadoop/hbase/procedure/TestProcedureDescriber.TestProcedure.html" title="class in org.apache.hadoop.hbase.procedure"><span class="typeNameLink">TestProcedureDescriber.TestProcedure</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.procedure.<a href="../../../../../org/apache/hadoop/hbase/procedure/TestProcedure.LatchedProcedure.html" title="class in org.apache.hadoop.hbase.procedure"><span class="typeNameLink">TestProcedure.LatchedProcedure</span></a></li>
 </ul>
 </li>
 <li type="circle">org.apache.hadoop.hbase.procedure.ProcedureManager

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/org/apache/hadoop/hbase/procedure2/package-tree.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/org/apache/hadoop/hbase/procedure2/package-tree.html b/testdevapidocs/org/apache/hadoop/hbase/procedure2/package-tree.html
index e9c1d93..ca2f47e 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/procedure2/package-tree.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/procedure2/package-tree.html
@@ -206,8 +206,8 @@
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true" title="class or interface in java.io">Serializable</a>)
 <ul>
 <li type="circle">org.apache.hadoop.hbase.procedure2.<a href="../../../../../org/apache/hadoop/hbase/procedure2/TestStateMachineProcedure.TestSMProcedureState.html" title="enum in org.apache.hadoop.hbase.procedure2"><span class="typeNameLink">TestStateMachineProcedure.TestSMProcedureState</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.procedure2.<a href="../../../../../org/apache/hadoop/hbase/procedure2/TestYieldProcedures.TestStateMachineProcedure.State.html" title="enum in org.apache.hadoop.hbase.procedure2"><span class="typeNameLink">TestYieldProcedures.TestStateMachineProcedure.State</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.procedure2.<a href="../../../../../org/apache/hadoop/hbase/procedure2/TestProcedureRecovery.TestStateMachineProcedure.State.html" title="enum in org.apache.hadoop.hbase.procedure2"><span class="typeNameLink">TestProcedureRecovery.TestStateMachineProcedure.State</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.procedure2.<a href="../../../../../org/apache/hadoop/hbase/procedure2/TestYieldProcedures.TestStateMachineProcedure.State.html" title="enum in org.apache.hadoop.hbase.procedure2"><span class="typeNameLink">TestYieldProcedures.TestStateMachineProcedure.State</span></a></li>
 </ul>
 </li>
 </ul>


[02/50] hbase-site git commit: Published site at 26babcf013de696b899d76a3c39434b794440d8d.

Posted by gi...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextColFilter.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextColFilter.html b/testdevapidocs/src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextColFilter.html
new file mode 100644
index 0000000..6f38b3f
--- /dev/null
+++ b/testdevapidocs/src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextColFilter.html
@@ -0,0 +1,334 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html lang="en">
+<head>
+<title>Source code</title>
+<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
+</head>
+<body>
+<div class="sourceContainer">
+<pre><span class="sourceLineNo">001</span>/**<a name="line.1"></a>
+<span class="sourceLineNo">002</span> * Licensed to the Apache Software Foundation (ASF) under one<a name="line.2"></a>
+<span class="sourceLineNo">003</span> * or more contributor license agreements.  See the NOTICE file<a name="line.3"></a>
+<span class="sourceLineNo">004</span> * distributed with this work for additional information<a name="line.4"></a>
+<span class="sourceLineNo">005</span> * regarding copyright ownership.  The ASF licenses this file<a name="line.5"></a>
+<span class="sourceLineNo">006</span> * to you under the Apache License, Version 2.0 (the<a name="line.6"></a>
+<span class="sourceLineNo">007</span> * "License"); you may not use this file except in compliance<a name="line.7"></a>
+<span class="sourceLineNo">008</span> * with the License.  You may obtain a copy of the License at<a name="line.8"></a>
+<span class="sourceLineNo">009</span> *<a name="line.9"></a>
+<span class="sourceLineNo">010</span> *     http://www.apache.org/licenses/LICENSE-2.0<a name="line.10"></a>
+<span class="sourceLineNo">011</span> *<a name="line.11"></a>
+<span class="sourceLineNo">012</span> * Unless required by applicable law or agreed to in writing, software<a name="line.12"></a>
+<span class="sourceLineNo">013</span> * distributed under the License is distributed on an "AS IS" BASIS,<a name="line.13"></a>
+<span class="sourceLineNo">014</span> * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.<a name="line.14"></a>
+<span class="sourceLineNo">015</span> * See the License for the specific language governing permissions and<a name="line.15"></a>
+<span class="sourceLineNo">016</span> * limitations under the License.<a name="line.16"></a>
+<span class="sourceLineNo">017</span> */<a name="line.17"></a>
+<span class="sourceLineNo">018</span>package org.apache.hadoop.hbase.regionserver;<a name="line.18"></a>
+<span class="sourceLineNo">019</span><a name="line.19"></a>
+<span class="sourceLineNo">020</span>import static org.junit.Assert.assertEquals;<a name="line.20"></a>
+<span class="sourceLineNo">021</span>import static org.junit.Assert.assertFalse;<a name="line.21"></a>
+<span class="sourceLineNo">022</span>import static org.junit.Assert.assertTrue;<a name="line.22"></a>
+<span class="sourceLineNo">023</span><a name="line.23"></a>
+<span class="sourceLineNo">024</span>import java.io.IOException;<a name="line.24"></a>
+<span class="sourceLineNo">025</span>import java.util.ArrayList;<a name="line.25"></a>
+<span class="sourceLineNo">026</span>import java.util.List;<a name="line.26"></a>
+<span class="sourceLineNo">027</span>import java.util.concurrent.ThreadLocalRandom;<a name="line.27"></a>
+<span class="sourceLineNo">028</span>import org.apache.hadoop.hbase.Cell;<a name="line.28"></a>
+<span class="sourceLineNo">029</span>import org.apache.hadoop.hbase.HBaseClassTestRule;<a name="line.29"></a>
+<span class="sourceLineNo">030</span>import org.apache.hadoop.hbase.HBaseTestingUtility;<a name="line.30"></a>
+<span class="sourceLineNo">031</span>import org.apache.hadoop.hbase.TableName;<a name="line.31"></a>
+<span class="sourceLineNo">032</span>import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder;<a name="line.32"></a>
+<span class="sourceLineNo">033</span>import org.apache.hadoop.hbase.client.Put;<a name="line.33"></a>
+<span class="sourceLineNo">034</span>import org.apache.hadoop.hbase.client.Result;<a name="line.34"></a>
+<span class="sourceLineNo">035</span>import org.apache.hadoop.hbase.client.Scan;<a name="line.35"></a>
+<span class="sourceLineNo">036</span>import org.apache.hadoop.hbase.client.TableDescriptorBuilder;<a name="line.36"></a>
+<span class="sourceLineNo">037</span>import org.apache.hadoop.hbase.filter.Filter;<a name="line.37"></a>
+<span class="sourceLineNo">038</span>import org.apache.hadoop.hbase.filter.FilterBase;<a name="line.38"></a>
+<span class="sourceLineNo">039</span>import org.apache.hadoop.hbase.regionserver.HRegion.RegionScannerImpl;<a name="line.39"></a>
+<span class="sourceLineNo">040</span>import org.apache.hadoop.hbase.regionserver.ScannerContext.LimitScope;<a name="line.40"></a>
+<span class="sourceLineNo">041</span>import org.apache.hadoop.hbase.testclassification.MediumTests;<a name="line.41"></a>
+<span class="sourceLineNo">042</span>import org.apache.hadoop.hbase.testclassification.RegionServerTests;<a name="line.42"></a>
+<span class="sourceLineNo">043</span>import org.apache.hadoop.hbase.util.Bytes;<a name="line.43"></a>
+<span class="sourceLineNo">044</span>import org.junit.AfterClass;<a name="line.44"></a>
+<span class="sourceLineNo">045</span>import org.junit.BeforeClass;<a name="line.45"></a>
+<span class="sourceLineNo">046</span>import org.junit.ClassRule;<a name="line.46"></a>
+<span class="sourceLineNo">047</span>import org.junit.Ignore;<a name="line.47"></a>
+<span class="sourceLineNo">048</span>import org.junit.Test;<a name="line.48"></a>
+<span class="sourceLineNo">049</span>import org.junit.experimental.categories.Category;<a name="line.49"></a>
+<span class="sourceLineNo">050</span><a name="line.50"></a>
+<span class="sourceLineNo">051</span>@Category({ RegionServerTests.class, MediumTests.class })<a name="line.51"></a>
+<span class="sourceLineNo">052</span>public class TestSwitchToStreamRead {<a name="line.52"></a>
+<span class="sourceLineNo">053</span><a name="line.53"></a>
+<span class="sourceLineNo">054</span>  @ClassRule<a name="line.54"></a>
+<span class="sourceLineNo">055</span>  public static final HBaseClassTestRule CLASS_RULE =<a name="line.55"></a>
+<span class="sourceLineNo">056</span>    HBaseClassTestRule.forClass(TestSwitchToStreamRead.class);<a name="line.56"></a>
+<span class="sourceLineNo">057</span><a name="line.57"></a>
+<span class="sourceLineNo">058</span>  private static final HBaseTestingUtility UTIL = new HBaseTestingUtility();<a name="line.58"></a>
+<span class="sourceLineNo">059</span><a name="line.59"></a>
+<span class="sourceLineNo">060</span>  private static TableName TABLE_NAME = TableName.valueOf("stream");<a name="line.60"></a>
+<span class="sourceLineNo">061</span><a name="line.61"></a>
+<span class="sourceLineNo">062</span>  private static byte[] FAMILY = Bytes.toBytes("cf");<a name="line.62"></a>
+<span class="sourceLineNo">063</span><a name="line.63"></a>
+<span class="sourceLineNo">064</span>  private static byte[] QUAL = Bytes.toBytes("cq");<a name="line.64"></a>
+<span class="sourceLineNo">065</span><a name="line.65"></a>
+<span class="sourceLineNo">066</span>  private static String VALUE_PREFIX;<a name="line.66"></a>
+<span class="sourceLineNo">067</span><a name="line.67"></a>
+<span class="sourceLineNo">068</span>  private static HRegion REGION;<a name="line.68"></a>
+<span class="sourceLineNo">069</span><a name="line.69"></a>
+<span class="sourceLineNo">070</span>  @BeforeClass<a name="line.70"></a>
+<span class="sourceLineNo">071</span>  public static void setUp() throws IOException {<a name="line.71"></a>
+<span class="sourceLineNo">072</span>    UTIL.getConfiguration().setLong(StoreScanner.STORESCANNER_PREAD_MAX_BYTES, 2048);<a name="line.72"></a>
+<span class="sourceLineNo">073</span>    StringBuilder sb = new StringBuilder(256);<a name="line.73"></a>
+<span class="sourceLineNo">074</span>    for (int i = 0; i &lt; 255; i++) {<a name="line.74"></a>
+<span class="sourceLineNo">075</span>      sb.append((char) ThreadLocalRandom.current().nextInt('A', 'z' + 1));<a name="line.75"></a>
+<span class="sourceLineNo">076</span>    }<a name="line.76"></a>
+<span class="sourceLineNo">077</span>    VALUE_PREFIX = sb.append("-").toString();<a name="line.77"></a>
+<span class="sourceLineNo">078</span>    REGION = UTIL.createLocalHRegion(<a name="line.78"></a>
+<span class="sourceLineNo">079</span>      TableDescriptorBuilder.newBuilder(TABLE_NAME)<a name="line.79"></a>
+<span class="sourceLineNo">080</span>        .setColumnFamily(<a name="line.80"></a>
+<span class="sourceLineNo">081</span>          ColumnFamilyDescriptorBuilder.newBuilder(FAMILY).setBlocksize(1024).build())<a name="line.81"></a>
+<span class="sourceLineNo">082</span>        .build(),<a name="line.82"></a>
+<span class="sourceLineNo">083</span>      null, null);<a name="line.83"></a>
+<span class="sourceLineNo">084</span>    for (int i = 0; i &lt; 900; i++) {<a name="line.84"></a>
+<span class="sourceLineNo">085</span>      REGION<a name="line.85"></a>
+<span class="sourceLineNo">086</span>        .put(new Put(Bytes.toBytes(i)).addColumn(FAMILY, QUAL, Bytes.toBytes(VALUE_PREFIX + i)));<a name="line.86"></a>
+<span class="sourceLineNo">087</span>    }<a name="line.87"></a>
+<span class="sourceLineNo">088</span>    REGION.flush(true);<a name="line.88"></a>
+<span class="sourceLineNo">089</span>    for (int i = 900; i &lt; 1000; i++) {<a name="line.89"></a>
+<span class="sourceLineNo">090</span>      REGION<a name="line.90"></a>
+<span class="sourceLineNo">091</span>        .put(new Put(Bytes.toBytes(i)).addColumn(FAMILY, QUAL, Bytes.toBytes(VALUE_PREFIX + i)));<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>  @AfterClass<a name="line.95"></a>
+<span class="sourceLineNo">096</span>  public static void tearDown() throws IOException {<a name="line.96"></a>
+<span class="sourceLineNo">097</span>    REGION.close(true);<a name="line.97"></a>
+<span class="sourceLineNo">098</span>    UTIL.cleanupTestDir();<a name="line.98"></a>
+<span class="sourceLineNo">099</span>  }<a name="line.99"></a>
+<span class="sourceLineNo">100</span><a name="line.100"></a>
+<span class="sourceLineNo">101</span>  @Test<a name="line.101"></a>
+<span class="sourceLineNo">102</span>  public void test() throws IOException {<a name="line.102"></a>
+<span class="sourceLineNo">103</span>    try (RegionScannerImpl scanner = REGION.getScanner(new Scan())) {<a name="line.103"></a>
+<span class="sourceLineNo">104</span>      StoreScanner storeScanner =<a name="line.104"></a>
+<span class="sourceLineNo">105</span>        (StoreScanner) (scanner).getStoreHeapForTesting().getCurrentForTesting();<a name="line.105"></a>
+<span class="sourceLineNo">106</span>      for (KeyValueScanner kvs : storeScanner.getAllScannersForTesting()) {<a name="line.106"></a>
+<span class="sourceLineNo">107</span>        if (kvs instanceof StoreFileScanner) {<a name="line.107"></a>
+<span class="sourceLineNo">108</span>          StoreFileScanner sfScanner = (StoreFileScanner) kvs;<a name="line.108"></a>
+<span class="sourceLineNo">109</span>          // starting from pread so we use shared reader here.<a name="line.109"></a>
+<span class="sourceLineNo">110</span>          assertTrue(sfScanner.getReader().shared);<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>      List&lt;Cell&gt; cells = new ArrayList&lt;&gt;();<a name="line.113"></a>
+<span class="sourceLineNo">114</span>      for (int i = 0; i &lt; 500; i++) {<a name="line.114"></a>
+<span class="sourceLineNo">115</span>        assertTrue(scanner.next(cells));<a name="line.115"></a>
+<span class="sourceLineNo">116</span>        Result result = Result.create(cells);<a name="line.116"></a>
+<span class="sourceLineNo">117</span>        assertEquals(VALUE_PREFIX + i, Bytes.toString(result.getValue(FAMILY, QUAL)));<a name="line.117"></a>
+<span class="sourceLineNo">118</span>        cells.clear();<a name="line.118"></a>
+<span class="sourceLineNo">119</span>        scanner.shipped();<a name="line.119"></a>
+<span class="sourceLineNo">120</span>      }<a name="line.120"></a>
+<span class="sourceLineNo">121</span>      for (KeyValueScanner kvs : storeScanner.getAllScannersForTesting()) {<a name="line.121"></a>
+<span class="sourceLineNo">122</span>        if (kvs instanceof StoreFileScanner) {<a name="line.122"></a>
+<span class="sourceLineNo">123</span>          StoreFileScanner sfScanner = (StoreFileScanner) kvs;<a name="line.123"></a>
+<span class="sourceLineNo">124</span>          // we should have convert to use stream read now.<a name="line.124"></a>
+<span class="sourceLineNo">125</span>          assertFalse(sfScanner.getReader().shared);<a name="line.125"></a>
+<span class="sourceLineNo">126</span>        }<a name="line.126"></a>
+<span class="sourceLineNo">127</span>      }<a name="line.127"></a>
+<span class="sourceLineNo">128</span>      for (int i = 500; i &lt; 1000; i++) {<a name="line.128"></a>
+<span class="sourceLineNo">129</span>        assertEquals(i != 999, scanner.next(cells));<a name="line.129"></a>
+<span class="sourceLineNo">130</span>        Result result = Result.create(cells);<a name="line.130"></a>
+<span class="sourceLineNo">131</span>        assertEquals(VALUE_PREFIX + i, Bytes.toString(result.getValue(FAMILY, QUAL)));<a name="line.131"></a>
+<span class="sourceLineNo">132</span>        cells.clear();<a name="line.132"></a>
+<span class="sourceLineNo">133</span>        scanner.shipped();<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>    // make sure all scanners are closed.<a name="line.136"></a>
+<span class="sourceLineNo">137</span>    for (HStoreFile sf : REGION.getStore(FAMILY).getStorefiles()) {<a name="line.137"></a>
+<span class="sourceLineNo">138</span>      assertFalse(sf.isReferencedInReads());<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>  public static final class MatchLastRowKeyFilter extends FilterBase {<a name="line.142"></a>
+<span class="sourceLineNo">143</span><a name="line.143"></a>
+<span class="sourceLineNo">144</span>    @Override<a name="line.144"></a>
+<span class="sourceLineNo">145</span>    public boolean filterRowKey(Cell cell) throws IOException {<a name="line.145"></a>
+<span class="sourceLineNo">146</span>      return Bytes.toInt(cell.getRowArray(), cell.getRowOffset()) != 999;<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>  private void testFilter(Filter filter) throws IOException {<a name="line.150"></a>
+<span class="sourceLineNo">151</span>    try (RegionScannerImpl scanner = REGION.getScanner(new Scan().setFilter(filter))) {<a name="line.151"></a>
+<span class="sourceLineNo">152</span>      StoreScanner storeScanner =<a name="line.152"></a>
+<span class="sourceLineNo">153</span>        (StoreScanner) (scanner).getStoreHeapForTesting().getCurrentForTesting();<a name="line.153"></a>
+<span class="sourceLineNo">154</span>      for (KeyValueScanner kvs : storeScanner.getAllScannersForTesting()) {<a name="line.154"></a>
+<span class="sourceLineNo">155</span>        if (kvs instanceof StoreFileScanner) {<a name="line.155"></a>
+<span class="sourceLineNo">156</span>          StoreFileScanner sfScanner = (StoreFileScanner) kvs;<a name="line.156"></a>
+<span class="sourceLineNo">157</span>          // starting from pread so we use shared reader here.<a name="line.157"></a>
+<span class="sourceLineNo">158</span>          assertTrue(sfScanner.getReader().shared);<a name="line.158"></a>
+<span class="sourceLineNo">159</span>        }<a name="line.159"></a>
+<span class="sourceLineNo">160</span>      }<a name="line.160"></a>
+<span class="sourceLineNo">161</span>      List&lt;Cell&gt; cells = new ArrayList&lt;&gt;();<a name="line.161"></a>
+<span class="sourceLineNo">162</span>      // should return before finishing the scan as we want to switch from pread to stream<a name="line.162"></a>
+<span class="sourceLineNo">163</span>      assertTrue(scanner.next(cells,<a name="line.163"></a>
+<span class="sourceLineNo">164</span>        ScannerContext.newBuilder().setTimeLimit(LimitScope.BETWEEN_CELLS, -1).build()));<a name="line.164"></a>
+<span class="sourceLineNo">165</span>      assertTrue(cells.isEmpty());<a name="line.165"></a>
+<span class="sourceLineNo">166</span>      scanner.shipped();<a name="line.166"></a>
+<span class="sourceLineNo">167</span><a name="line.167"></a>
+<span class="sourceLineNo">168</span>      for (KeyValueScanner kvs : storeScanner.getAllScannersForTesting()) {<a name="line.168"></a>
+<span class="sourceLineNo">169</span>        if (kvs instanceof StoreFileScanner) {<a name="line.169"></a>
+<span class="sourceLineNo">170</span>          StoreFileScanner sfScanner = (StoreFileScanner) kvs;<a name="line.170"></a>
+<span class="sourceLineNo">171</span>          // we should have convert to use stream read now.<a name="line.171"></a>
+<span class="sourceLineNo">172</span>          assertFalse(sfScanner.getReader().shared);<a name="line.172"></a>
+<span class="sourceLineNo">173</span>        }<a name="line.173"></a>
+<span class="sourceLineNo">174</span>      }<a name="line.174"></a>
+<span class="sourceLineNo">175</span>      assertFalse(scanner.next(cells,<a name="line.175"></a>
+<span class="sourceLineNo">176</span>        ScannerContext.newBuilder().setTimeLimit(LimitScope.BETWEEN_CELLS, -1).build()));<a name="line.176"></a>
+<span class="sourceLineNo">177</span>      Result result = Result.create(cells);<a name="line.177"></a>
+<span class="sourceLineNo">178</span>      assertEquals(VALUE_PREFIX + 999, Bytes.toString(result.getValue(FAMILY, QUAL)));<a name="line.178"></a>
+<span class="sourceLineNo">179</span>      cells.clear();<a name="line.179"></a>
+<span class="sourceLineNo">180</span>      scanner.shipped();<a name="line.180"></a>
+<span class="sourceLineNo">181</span>    }<a name="line.181"></a>
+<span class="sourceLineNo">182</span>    // make sure all scanners are closed.<a name="line.182"></a>
+<span class="sourceLineNo">183</span>    for (HStoreFile sf : REGION.getStore(FAMILY).getStorefiles()) {<a name="line.183"></a>
+<span class="sourceLineNo">184</span>      assertFalse(sf.isReferencedInReads());<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>  // We use a different logic to implement filterRowKey, where we will keep calling kvHeap.next<a name="line.188"></a>
+<span class="sourceLineNo">189</span>  // until the row key is changed. And there we can only use NoLimitScannerContext so we can not<a name="line.189"></a>
+<span class="sourceLineNo">190</span>  // make the upper layer return immediately. Simply do not use NoLimitScannerContext will lead to<a name="line.190"></a>
+<span class="sourceLineNo">191</span>  // an infinite loop. Need to dig more, the code are way too complicated...<a name="line.191"></a>
+<span class="sourceLineNo">192</span>  @Ignore<a name="line.192"></a>
+<span class="sourceLineNo">193</span>  @Test<a name="line.193"></a>
+<span class="sourceLineNo">194</span>  public void testFilterRowKey() throws IOException {<a name="line.194"></a>
+<span class="sourceLineNo">195</span>    testFilter(new MatchLastRowKeyFilter());<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>  public static final class MatchLastRowCellNextColFilter extends FilterBase {<a name="line.198"></a>
+<span class="sourceLineNo">199</span><a name="line.199"></a>
+<span class="sourceLineNo">200</span>    @Override<a name="line.200"></a>
+<span class="sourceLineNo">201</span>    public ReturnCode filterCell(Cell c) throws IOException {<a name="line.201"></a>
+<span class="sourceLineNo">202</span>      if (Bytes.toInt(c.getRowArray(), c.getRowOffset()) == 999) {<a name="line.202"></a>
+<span class="sourceLineNo">203</span>        return ReturnCode.INCLUDE;<a name="line.203"></a>
+<span class="sourceLineNo">204</span>      } else {<a name="line.204"></a>
+<span class="sourceLineNo">205</span>        return ReturnCode.NEXT_COL;<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>  }<a name="line.208"></a>
+<span class="sourceLineNo">209</span><a name="line.209"></a>
+<span class="sourceLineNo">210</span>  @Test<a name="line.210"></a>
+<span class="sourceLineNo">211</span>  public void testFilterCellNextCol() throws IOException {<a name="line.211"></a>
+<span class="sourceLineNo">212</span>    testFilter(new MatchLastRowCellNextColFilter());<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>  public static final class MatchLastRowCellNextRowFilter extends FilterBase {<a name="line.215"></a>
+<span class="sourceLineNo">216</span><a name="line.216"></a>
+<span class="sourceLineNo">217</span>    @Override<a name="line.217"></a>
+<span class="sourceLineNo">218</span>    public ReturnCode filterCell(Cell c) throws IOException {<a name="line.218"></a>
+<span class="sourceLineNo">219</span>      if (Bytes.toInt(c.getRowArray(), c.getRowOffset()) == 999) {<a name="line.219"></a>
+<span class="sourceLineNo">220</span>        return ReturnCode.INCLUDE;<a name="line.220"></a>
+<span class="sourceLineNo">221</span>      } else {<a name="line.221"></a>
+<span class="sourceLineNo">222</span>        return ReturnCode.NEXT_ROW;<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>  }<a name="line.225"></a>
+<span class="sourceLineNo">226</span><a name="line.226"></a>
+<span class="sourceLineNo">227</span>  @Test<a name="line.227"></a>
+<span class="sourceLineNo">228</span>  public void testFilterCellNextRow() throws IOException {<a name="line.228"></a>
+<span class="sourceLineNo">229</span>    testFilter(new MatchLastRowCellNextRowFilter());<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>  public static final class MatchLastRowFilterRowFilter extends FilterBase {<a name="line.232"></a>
+<span class="sourceLineNo">233</span><a name="line.233"></a>
+<span class="sourceLineNo">234</span>    private boolean exclude;<a name="line.234"></a>
+<span class="sourceLineNo">235</span><a name="line.235"></a>
+<span class="sourceLineNo">236</span>    @Override<a name="line.236"></a>
+<span class="sourceLineNo">237</span>    public void filterRowCells(List&lt;Cell&gt; kvs) throws IOException {<a name="line.237"></a>
+<span class="sourceLineNo">238</span>      Cell c = kvs.get(0);<a name="line.238"></a>
+<span class="sourceLineNo">239</span>      exclude = Bytes.toInt(c.getRowArray(), c.getRowOffset()) != 999;<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>    @Override<a name="line.242"></a>
+<span class="sourceLineNo">243</span>    public void reset() throws IOException {<a name="line.243"></a>
+<span class="sourceLineNo">244</span>      exclude = false;<a name="line.244"></a>
+<span class="sourceLineNo">245</span>    }<a name="line.245"></a>
+<span class="sourceLineNo">246</span><a name="line.246"></a>
+<span class="sourceLineNo">247</span>    @Override<a name="line.247"></a>
+<span class="sourceLineNo">248</span>    public boolean filterRow() throws IOException {<a name="line.248"></a>
+<span class="sourceLineNo">249</span>      return exclude;<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>    @Override<a name="line.252"></a>
+<span class="sourceLineNo">253</span>    public boolean hasFilterRow() {<a name="line.253"></a>
+<span class="sourceLineNo">254</span>      return true;<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>  @Test<a name="line.258"></a>
+<span class="sourceLineNo">259</span>  public void testFilterRow() throws IOException {<a name="line.259"></a>
+<span class="sourceLineNo">260</span>    testFilter(new MatchLastRowFilterRowFilter());<a name="line.260"></a>
+<span class="sourceLineNo">261</span>  }<a name="line.261"></a>
+<span class="sourceLineNo">262</span>}<a name="line.262"></a>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</div>
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextRowFilter.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextRowFilter.html b/testdevapidocs/src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextRowFilter.html
new file mode 100644
index 0000000..6f38b3f
--- /dev/null
+++ b/testdevapidocs/src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextRowFilter.html
@@ -0,0 +1,334 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html lang="en">
+<head>
+<title>Source code</title>
+<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
+</head>
+<body>
+<div class="sourceContainer">
+<pre><span class="sourceLineNo">001</span>/**<a name="line.1"></a>
+<span class="sourceLineNo">002</span> * Licensed to the Apache Software Foundation (ASF) under one<a name="line.2"></a>
+<span class="sourceLineNo">003</span> * or more contributor license agreements.  See the NOTICE file<a name="line.3"></a>
+<span class="sourceLineNo">004</span> * distributed with this work for additional information<a name="line.4"></a>
+<span class="sourceLineNo">005</span> * regarding copyright ownership.  The ASF licenses this file<a name="line.5"></a>
+<span class="sourceLineNo">006</span> * to you under the Apache License, Version 2.0 (the<a name="line.6"></a>
+<span class="sourceLineNo">007</span> * "License"); you may not use this file except in compliance<a name="line.7"></a>
+<span class="sourceLineNo">008</span> * with the License.  You may obtain a copy of the License at<a name="line.8"></a>
+<span class="sourceLineNo">009</span> *<a name="line.9"></a>
+<span class="sourceLineNo">010</span> *     http://www.apache.org/licenses/LICENSE-2.0<a name="line.10"></a>
+<span class="sourceLineNo">011</span> *<a name="line.11"></a>
+<span class="sourceLineNo">012</span> * Unless required by applicable law or agreed to in writing, software<a name="line.12"></a>
+<span class="sourceLineNo">013</span> * distributed under the License is distributed on an "AS IS" BASIS,<a name="line.13"></a>
+<span class="sourceLineNo">014</span> * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.<a name="line.14"></a>
+<span class="sourceLineNo">015</span> * See the License for the specific language governing permissions and<a name="line.15"></a>
+<span class="sourceLineNo">016</span> * limitations under the License.<a name="line.16"></a>
+<span class="sourceLineNo">017</span> */<a name="line.17"></a>
+<span class="sourceLineNo">018</span>package org.apache.hadoop.hbase.regionserver;<a name="line.18"></a>
+<span class="sourceLineNo">019</span><a name="line.19"></a>
+<span class="sourceLineNo">020</span>import static org.junit.Assert.assertEquals;<a name="line.20"></a>
+<span class="sourceLineNo">021</span>import static org.junit.Assert.assertFalse;<a name="line.21"></a>
+<span class="sourceLineNo">022</span>import static org.junit.Assert.assertTrue;<a name="line.22"></a>
+<span class="sourceLineNo">023</span><a name="line.23"></a>
+<span class="sourceLineNo">024</span>import java.io.IOException;<a name="line.24"></a>
+<span class="sourceLineNo">025</span>import java.util.ArrayList;<a name="line.25"></a>
+<span class="sourceLineNo">026</span>import java.util.List;<a name="line.26"></a>
+<span class="sourceLineNo">027</span>import java.util.concurrent.ThreadLocalRandom;<a name="line.27"></a>
+<span class="sourceLineNo">028</span>import org.apache.hadoop.hbase.Cell;<a name="line.28"></a>
+<span class="sourceLineNo">029</span>import org.apache.hadoop.hbase.HBaseClassTestRule;<a name="line.29"></a>
+<span class="sourceLineNo">030</span>import org.apache.hadoop.hbase.HBaseTestingUtility;<a name="line.30"></a>
+<span class="sourceLineNo">031</span>import org.apache.hadoop.hbase.TableName;<a name="line.31"></a>
+<span class="sourceLineNo">032</span>import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder;<a name="line.32"></a>
+<span class="sourceLineNo">033</span>import org.apache.hadoop.hbase.client.Put;<a name="line.33"></a>
+<span class="sourceLineNo">034</span>import org.apache.hadoop.hbase.client.Result;<a name="line.34"></a>
+<span class="sourceLineNo">035</span>import org.apache.hadoop.hbase.client.Scan;<a name="line.35"></a>
+<span class="sourceLineNo">036</span>import org.apache.hadoop.hbase.client.TableDescriptorBuilder;<a name="line.36"></a>
+<span class="sourceLineNo">037</span>import org.apache.hadoop.hbase.filter.Filter;<a name="line.37"></a>
+<span class="sourceLineNo">038</span>import org.apache.hadoop.hbase.filter.FilterBase;<a name="line.38"></a>
+<span class="sourceLineNo">039</span>import org.apache.hadoop.hbase.regionserver.HRegion.RegionScannerImpl;<a name="line.39"></a>
+<span class="sourceLineNo">040</span>import org.apache.hadoop.hbase.regionserver.ScannerContext.LimitScope;<a name="line.40"></a>
+<span class="sourceLineNo">041</span>import org.apache.hadoop.hbase.testclassification.MediumTests;<a name="line.41"></a>
+<span class="sourceLineNo">042</span>import org.apache.hadoop.hbase.testclassification.RegionServerTests;<a name="line.42"></a>
+<span class="sourceLineNo">043</span>import org.apache.hadoop.hbase.util.Bytes;<a name="line.43"></a>
+<span class="sourceLineNo">044</span>import org.junit.AfterClass;<a name="line.44"></a>
+<span class="sourceLineNo">045</span>import org.junit.BeforeClass;<a name="line.45"></a>
+<span class="sourceLineNo">046</span>import org.junit.ClassRule;<a name="line.46"></a>
+<span class="sourceLineNo">047</span>import org.junit.Ignore;<a name="line.47"></a>
+<span class="sourceLineNo">048</span>import org.junit.Test;<a name="line.48"></a>
+<span class="sourceLineNo">049</span>import org.junit.experimental.categories.Category;<a name="line.49"></a>
+<span class="sourceLineNo">050</span><a name="line.50"></a>
+<span class="sourceLineNo">051</span>@Category({ RegionServerTests.class, MediumTests.class })<a name="line.51"></a>
+<span class="sourceLineNo">052</span>public class TestSwitchToStreamRead {<a name="line.52"></a>
+<span class="sourceLineNo">053</span><a name="line.53"></a>
+<span class="sourceLineNo">054</span>  @ClassRule<a name="line.54"></a>
+<span class="sourceLineNo">055</span>  public static final HBaseClassTestRule CLASS_RULE =<a name="line.55"></a>
+<span class="sourceLineNo">056</span>    HBaseClassTestRule.forClass(TestSwitchToStreamRead.class);<a name="line.56"></a>
+<span class="sourceLineNo">057</span><a name="line.57"></a>
+<span class="sourceLineNo">058</span>  private static final HBaseTestingUtility UTIL = new HBaseTestingUtility();<a name="line.58"></a>
+<span class="sourceLineNo">059</span><a name="line.59"></a>
+<span class="sourceLineNo">060</span>  private static TableName TABLE_NAME = TableName.valueOf("stream");<a name="line.60"></a>
+<span class="sourceLineNo">061</span><a name="line.61"></a>
+<span class="sourceLineNo">062</span>  private static byte[] FAMILY = Bytes.toBytes("cf");<a name="line.62"></a>
+<span class="sourceLineNo">063</span><a name="line.63"></a>
+<span class="sourceLineNo">064</span>  private static byte[] QUAL = Bytes.toBytes("cq");<a name="line.64"></a>
+<span class="sourceLineNo">065</span><a name="line.65"></a>
+<span class="sourceLineNo">066</span>  private static String VALUE_PREFIX;<a name="line.66"></a>
+<span class="sourceLineNo">067</span><a name="line.67"></a>
+<span class="sourceLineNo">068</span>  private static HRegion REGION;<a name="line.68"></a>
+<span class="sourceLineNo">069</span><a name="line.69"></a>
+<span class="sourceLineNo">070</span>  @BeforeClass<a name="line.70"></a>
+<span class="sourceLineNo">071</span>  public static void setUp() throws IOException {<a name="line.71"></a>
+<span class="sourceLineNo">072</span>    UTIL.getConfiguration().setLong(StoreScanner.STORESCANNER_PREAD_MAX_BYTES, 2048);<a name="line.72"></a>
+<span class="sourceLineNo">073</span>    StringBuilder sb = new StringBuilder(256);<a name="line.73"></a>
+<span class="sourceLineNo">074</span>    for (int i = 0; i &lt; 255; i++) {<a name="line.74"></a>
+<span class="sourceLineNo">075</span>      sb.append((char) ThreadLocalRandom.current().nextInt('A', 'z' + 1));<a name="line.75"></a>
+<span class="sourceLineNo">076</span>    }<a name="line.76"></a>
+<span class="sourceLineNo">077</span>    VALUE_PREFIX = sb.append("-").toString();<a name="line.77"></a>
+<span class="sourceLineNo">078</span>    REGION = UTIL.createLocalHRegion(<a name="line.78"></a>
+<span class="sourceLineNo">079</span>      TableDescriptorBuilder.newBuilder(TABLE_NAME)<a name="line.79"></a>
+<span class="sourceLineNo">080</span>        .setColumnFamily(<a name="line.80"></a>
+<span class="sourceLineNo">081</span>          ColumnFamilyDescriptorBuilder.newBuilder(FAMILY).setBlocksize(1024).build())<a name="line.81"></a>
+<span class="sourceLineNo">082</span>        .build(),<a name="line.82"></a>
+<span class="sourceLineNo">083</span>      null, null);<a name="line.83"></a>
+<span class="sourceLineNo">084</span>    for (int i = 0; i &lt; 900; i++) {<a name="line.84"></a>
+<span class="sourceLineNo">085</span>      REGION<a name="line.85"></a>
+<span class="sourceLineNo">086</span>        .put(new Put(Bytes.toBytes(i)).addColumn(FAMILY, QUAL, Bytes.toBytes(VALUE_PREFIX + i)));<a name="line.86"></a>
+<span class="sourceLineNo">087</span>    }<a name="line.87"></a>
+<span class="sourceLineNo">088</span>    REGION.flush(true);<a name="line.88"></a>
+<span class="sourceLineNo">089</span>    for (int i = 900; i &lt; 1000; i++) {<a name="line.89"></a>
+<span class="sourceLineNo">090</span>      REGION<a name="line.90"></a>
+<span class="sourceLineNo">091</span>        .put(new Put(Bytes.toBytes(i)).addColumn(FAMILY, QUAL, Bytes.toBytes(VALUE_PREFIX + i)));<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>  @AfterClass<a name="line.95"></a>
+<span class="sourceLineNo">096</span>  public static void tearDown() throws IOException {<a name="line.96"></a>
+<span class="sourceLineNo">097</span>    REGION.close(true);<a name="line.97"></a>
+<span class="sourceLineNo">098</span>    UTIL.cleanupTestDir();<a name="line.98"></a>
+<span class="sourceLineNo">099</span>  }<a name="line.99"></a>
+<span class="sourceLineNo">100</span><a name="line.100"></a>
+<span class="sourceLineNo">101</span>  @Test<a name="line.101"></a>
+<span class="sourceLineNo">102</span>  public void test() throws IOException {<a name="line.102"></a>
+<span class="sourceLineNo">103</span>    try (RegionScannerImpl scanner = REGION.getScanner(new Scan())) {<a name="line.103"></a>
+<span class="sourceLineNo">104</span>      StoreScanner storeScanner =<a name="line.104"></a>
+<span class="sourceLineNo">105</span>        (StoreScanner) (scanner).getStoreHeapForTesting().getCurrentForTesting();<a name="line.105"></a>
+<span class="sourceLineNo">106</span>      for (KeyValueScanner kvs : storeScanner.getAllScannersForTesting()) {<a name="line.106"></a>
+<span class="sourceLineNo">107</span>        if (kvs instanceof StoreFileScanner) {<a name="line.107"></a>
+<span class="sourceLineNo">108</span>          StoreFileScanner sfScanner = (StoreFileScanner) kvs;<a name="line.108"></a>
+<span class="sourceLineNo">109</span>          // starting from pread so we use shared reader here.<a name="line.109"></a>
+<span class="sourceLineNo">110</span>          assertTrue(sfScanner.getReader().shared);<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>      List&lt;Cell&gt; cells = new ArrayList&lt;&gt;();<a name="line.113"></a>
+<span class="sourceLineNo">114</span>      for (int i = 0; i &lt; 500; i++) {<a name="line.114"></a>
+<span class="sourceLineNo">115</span>        assertTrue(scanner.next(cells));<a name="line.115"></a>
+<span class="sourceLineNo">116</span>        Result result = Result.create(cells);<a name="line.116"></a>
+<span class="sourceLineNo">117</span>        assertEquals(VALUE_PREFIX + i, Bytes.toString(result.getValue(FAMILY, QUAL)));<a name="line.117"></a>
+<span class="sourceLineNo">118</span>        cells.clear();<a name="line.118"></a>
+<span class="sourceLineNo">119</span>        scanner.shipped();<a name="line.119"></a>
+<span class="sourceLineNo">120</span>      }<a name="line.120"></a>
+<span class="sourceLineNo">121</span>      for (KeyValueScanner kvs : storeScanner.getAllScannersForTesting()) {<a name="line.121"></a>
+<span class="sourceLineNo">122</span>        if (kvs instanceof StoreFileScanner) {<a name="line.122"></a>
+<span class="sourceLineNo">123</span>          StoreFileScanner sfScanner = (StoreFileScanner) kvs;<a name="line.123"></a>
+<span class="sourceLineNo">124</span>          // we should have convert to use stream read now.<a name="line.124"></a>
+<span class="sourceLineNo">125</span>          assertFalse(sfScanner.getReader().shared);<a name="line.125"></a>
+<span class="sourceLineNo">126</span>        }<a name="line.126"></a>
+<span class="sourceLineNo">127</span>      }<a name="line.127"></a>
+<span class="sourceLineNo">128</span>      for (int i = 500; i &lt; 1000; i++) {<a name="line.128"></a>
+<span class="sourceLineNo">129</span>        assertEquals(i != 999, scanner.next(cells));<a name="line.129"></a>
+<span class="sourceLineNo">130</span>        Result result = Result.create(cells);<a name="line.130"></a>
+<span class="sourceLineNo">131</span>        assertEquals(VALUE_PREFIX + i, Bytes.toString(result.getValue(FAMILY, QUAL)));<a name="line.131"></a>
+<span class="sourceLineNo">132</span>        cells.clear();<a name="line.132"></a>
+<span class="sourceLineNo">133</span>        scanner.shipped();<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>    // make sure all scanners are closed.<a name="line.136"></a>
+<span class="sourceLineNo">137</span>    for (HStoreFile sf : REGION.getStore(FAMILY).getStorefiles()) {<a name="line.137"></a>
+<span class="sourceLineNo">138</span>      assertFalse(sf.isReferencedInReads());<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>  public static final class MatchLastRowKeyFilter extends FilterBase {<a name="line.142"></a>
+<span class="sourceLineNo">143</span><a name="line.143"></a>
+<span class="sourceLineNo">144</span>    @Override<a name="line.144"></a>
+<span class="sourceLineNo">145</span>    public boolean filterRowKey(Cell cell) throws IOException {<a name="line.145"></a>
+<span class="sourceLineNo">146</span>      return Bytes.toInt(cell.getRowArray(), cell.getRowOffset()) != 999;<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>  private void testFilter(Filter filter) throws IOException {<a name="line.150"></a>
+<span class="sourceLineNo">151</span>    try (RegionScannerImpl scanner = REGION.getScanner(new Scan().setFilter(filter))) {<a name="line.151"></a>
+<span class="sourceLineNo">152</span>      StoreScanner storeScanner =<a name="line.152"></a>
+<span class="sourceLineNo">153</span>        (StoreScanner) (scanner).getStoreHeapForTesting().getCurrentForTesting();<a name="line.153"></a>
+<span class="sourceLineNo">154</span>      for (KeyValueScanner kvs : storeScanner.getAllScannersForTesting()) {<a name="line.154"></a>
+<span class="sourceLineNo">155</span>        if (kvs instanceof StoreFileScanner) {<a name="line.155"></a>
+<span class="sourceLineNo">156</span>          StoreFileScanner sfScanner = (StoreFileScanner) kvs;<a name="line.156"></a>
+<span class="sourceLineNo">157</span>          // starting from pread so we use shared reader here.<a name="line.157"></a>
+<span class="sourceLineNo">158</span>          assertTrue(sfScanner.getReader().shared);<a name="line.158"></a>
+<span class="sourceLineNo">159</span>        }<a name="line.159"></a>
+<span class="sourceLineNo">160</span>      }<a name="line.160"></a>
+<span class="sourceLineNo">161</span>      List&lt;Cell&gt; cells = new ArrayList&lt;&gt;();<a name="line.161"></a>
+<span class="sourceLineNo">162</span>      // should return before finishing the scan as we want to switch from pread to stream<a name="line.162"></a>
+<span class="sourceLineNo">163</span>      assertTrue(scanner.next(cells,<a name="line.163"></a>
+<span class="sourceLineNo">164</span>        ScannerContext.newBuilder().setTimeLimit(LimitScope.BETWEEN_CELLS, -1).build()));<a name="line.164"></a>
+<span class="sourceLineNo">165</span>      assertTrue(cells.isEmpty());<a name="line.165"></a>
+<span class="sourceLineNo">166</span>      scanner.shipped();<a name="line.166"></a>
+<span class="sourceLineNo">167</span><a name="line.167"></a>
+<span class="sourceLineNo">168</span>      for (KeyValueScanner kvs : storeScanner.getAllScannersForTesting()) {<a name="line.168"></a>
+<span class="sourceLineNo">169</span>        if (kvs instanceof StoreFileScanner) {<a name="line.169"></a>
+<span class="sourceLineNo">170</span>          StoreFileScanner sfScanner = (StoreFileScanner) kvs;<a name="line.170"></a>
+<span class="sourceLineNo">171</span>          // we should have convert to use stream read now.<a name="line.171"></a>
+<span class="sourceLineNo">172</span>          assertFalse(sfScanner.getReader().shared);<a name="line.172"></a>
+<span class="sourceLineNo">173</span>        }<a name="line.173"></a>
+<span class="sourceLineNo">174</span>      }<a name="line.174"></a>
+<span class="sourceLineNo">175</span>      assertFalse(scanner.next(cells,<a name="line.175"></a>
+<span class="sourceLineNo">176</span>        ScannerContext.newBuilder().setTimeLimit(LimitScope.BETWEEN_CELLS, -1).build()));<a name="line.176"></a>
+<span class="sourceLineNo">177</span>      Result result = Result.create(cells);<a name="line.177"></a>
+<span class="sourceLineNo">178</span>      assertEquals(VALUE_PREFIX + 999, Bytes.toString(result.getValue(FAMILY, QUAL)));<a name="line.178"></a>
+<span class="sourceLineNo">179</span>      cells.clear();<a name="line.179"></a>
+<span class="sourceLineNo">180</span>      scanner.shipped();<a name="line.180"></a>
+<span class="sourceLineNo">181</span>    }<a name="line.181"></a>
+<span class="sourceLineNo">182</span>    // make sure all scanners are closed.<a name="line.182"></a>
+<span class="sourceLineNo">183</span>    for (HStoreFile sf : REGION.getStore(FAMILY).getStorefiles()) {<a name="line.183"></a>
+<span class="sourceLineNo">184</span>      assertFalse(sf.isReferencedInReads());<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>  // We use a different logic to implement filterRowKey, where we will keep calling kvHeap.next<a name="line.188"></a>
+<span class="sourceLineNo">189</span>  // until the row key is changed. And there we can only use NoLimitScannerContext so we can not<a name="line.189"></a>
+<span class="sourceLineNo">190</span>  // make the upper layer return immediately. Simply do not use NoLimitScannerContext will lead to<a name="line.190"></a>
+<span class="sourceLineNo">191</span>  // an infinite loop. Need to dig more, the code are way too complicated...<a name="line.191"></a>
+<span class="sourceLineNo">192</span>  @Ignore<a name="line.192"></a>
+<span class="sourceLineNo">193</span>  @Test<a name="line.193"></a>
+<span class="sourceLineNo">194</span>  public void testFilterRowKey() throws IOException {<a name="line.194"></a>
+<span class="sourceLineNo">195</span>    testFilter(new MatchLastRowKeyFilter());<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>  public static final class MatchLastRowCellNextColFilter extends FilterBase {<a name="line.198"></a>
+<span class="sourceLineNo">199</span><a name="line.199"></a>
+<span class="sourceLineNo">200</span>    @Override<a name="line.200"></a>
+<span class="sourceLineNo">201</span>    public ReturnCode filterCell(Cell c) throws IOException {<a name="line.201"></a>
+<span class="sourceLineNo">202</span>      if (Bytes.toInt(c.getRowArray(), c.getRowOffset()) == 999) {<a name="line.202"></a>
+<span class="sourceLineNo">203</span>        return ReturnCode.INCLUDE;<a name="line.203"></a>
+<span class="sourceLineNo">204</span>      } else {<a name="line.204"></a>
+<span class="sourceLineNo">205</span>        return ReturnCode.NEXT_COL;<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>  }<a name="line.208"></a>
+<span class="sourceLineNo">209</span><a name="line.209"></a>
+<span class="sourceLineNo">210</span>  @Test<a name="line.210"></a>
+<span class="sourceLineNo">211</span>  public void testFilterCellNextCol() throws IOException {<a name="line.211"></a>
+<span class="sourceLineNo">212</span>    testFilter(new MatchLastRowCellNextColFilter());<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>  public static final class MatchLastRowCellNextRowFilter extends FilterBase {<a name="line.215"></a>
+<span class="sourceLineNo">216</span><a name="line.216"></a>
+<span class="sourceLineNo">217</span>    @Override<a name="line.217"></a>
+<span class="sourceLineNo">218</span>    public ReturnCode filterCell(Cell c) throws IOException {<a name="line.218"></a>
+<span class="sourceLineNo">219</span>      if (Bytes.toInt(c.getRowArray(), c.getRowOffset()) == 999) {<a name="line.219"></a>
+<span class="sourceLineNo">220</span>        return ReturnCode.INCLUDE;<a name="line.220"></a>
+<span class="sourceLineNo">221</span>      } else {<a name="line.221"></a>
+<span class="sourceLineNo">222</span>        return ReturnCode.NEXT_ROW;<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>  }<a name="line.225"></a>
+<span class="sourceLineNo">226</span><a name="line.226"></a>
+<span class="sourceLineNo">227</span>  @Test<a name="line.227"></a>
+<span class="sourceLineNo">228</span>  public void testFilterCellNextRow() throws IOException {<a name="line.228"></a>
+<span class="sourceLineNo">229</span>    testFilter(new MatchLastRowCellNextRowFilter());<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>  public static final class MatchLastRowFilterRowFilter extends FilterBase {<a name="line.232"></a>
+<span class="sourceLineNo">233</span><a name="line.233"></a>
+<span class="sourceLineNo">234</span>    private boolean exclude;<a name="line.234"></a>
+<span class="sourceLineNo">235</span><a name="line.235"></a>
+<span class="sourceLineNo">236</span>    @Override<a name="line.236"></a>
+<span class="sourceLineNo">237</span>    public void filterRowCells(List&lt;Cell&gt; kvs) throws IOException {<a name="line.237"></a>
+<span class="sourceLineNo">238</span>      Cell c = kvs.get(0);<a name="line.238"></a>
+<span class="sourceLineNo">239</span>      exclude = Bytes.toInt(c.getRowArray(), c.getRowOffset()) != 999;<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>    @Override<a name="line.242"></a>
+<span class="sourceLineNo">243</span>    public void reset() throws IOException {<a name="line.243"></a>
+<span class="sourceLineNo">244</span>      exclude = false;<a name="line.244"></a>
+<span class="sourceLineNo">245</span>    }<a name="line.245"></a>
+<span class="sourceLineNo">246</span><a name="line.246"></a>
+<span class="sourceLineNo">247</span>    @Override<a name="line.247"></a>
+<span class="sourceLineNo">248</span>    public boolean filterRow() throws IOException {<a name="line.248"></a>
+<span class="sourceLineNo">249</span>      return exclude;<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>    @Override<a name="line.252"></a>
+<span class="sourceLineNo">253</span>    public boolean hasFilterRow() {<a name="line.253"></a>
+<span class="sourceLineNo">254</span>      return true;<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>  @Test<a name="line.258"></a>
+<span class="sourceLineNo">259</span>  public void testFilterRow() throws IOException {<a name="line.259"></a>
+<span class="sourceLineNo">260</span>    testFilter(new MatchLastRowFilterRowFilter());<a name="line.260"></a>
+<span class="sourceLineNo">261</span>  }<a name="line.261"></a>
+<span class="sourceLineNo">262</span>}<a name="line.262"></a>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</div>
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html b/testdevapidocs/src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html
new file mode 100644
index 0000000..6f38b3f
--- /dev/null
+++ b/testdevapidocs/src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html
@@ -0,0 +1,334 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html lang="en">
+<head>
+<title>Source code</title>
+<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
+</head>
+<body>
+<div class="sourceContainer">
+<pre><span class="sourceLineNo">001</span>/**<a name="line.1"></a>
+<span class="sourceLineNo">002</span> * Licensed to the Apache Software Foundation (ASF) under one<a name="line.2"></a>
+<span class="sourceLineNo">003</span> * or more contributor license agreements.  See the NOTICE file<a name="line.3"></a>
+<span class="sourceLineNo">004</span> * distributed with this work for additional information<a name="line.4"></a>
+<span class="sourceLineNo">005</span> * regarding copyright ownership.  The ASF licenses this file<a name="line.5"></a>
+<span class="sourceLineNo">006</span> * to you under the Apache License, Version 2.0 (the<a name="line.6"></a>
+<span class="sourceLineNo">007</span> * "License"); you may not use this file except in compliance<a name="line.7"></a>
+<span class="sourceLineNo">008</span> * with the License.  You may obtain a copy of the License at<a name="line.8"></a>
+<span class="sourceLineNo">009</span> *<a name="line.9"></a>
+<span class="sourceLineNo">010</span> *     http://www.apache.org/licenses/LICENSE-2.0<a name="line.10"></a>
+<span class="sourceLineNo">011</span> *<a name="line.11"></a>
+<span class="sourceLineNo">012</span> * Unless required by applicable law or agreed to in writing, software<a name="line.12"></a>
+<span class="sourceLineNo">013</span> * distributed under the License is distributed on an "AS IS" BASIS,<a name="line.13"></a>
+<span class="sourceLineNo">014</span> * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.<a name="line.14"></a>
+<span class="sourceLineNo">015</span> * See the License for the specific language governing permissions and<a name="line.15"></a>
+<span class="sourceLineNo">016</span> * limitations under the License.<a name="line.16"></a>
+<span class="sourceLineNo">017</span> */<a name="line.17"></a>
+<span class="sourceLineNo">018</span>package org.apache.hadoop.hbase.regionserver;<a name="line.18"></a>
+<span class="sourceLineNo">019</span><a name="line.19"></a>
+<span class="sourceLineNo">020</span>import static org.junit.Assert.assertEquals;<a name="line.20"></a>
+<span class="sourceLineNo">021</span>import static org.junit.Assert.assertFalse;<a name="line.21"></a>
+<span class="sourceLineNo">022</span>import static org.junit.Assert.assertTrue;<a name="line.22"></a>
+<span class="sourceLineNo">023</span><a name="line.23"></a>
+<span class="sourceLineNo">024</span>import java.io.IOException;<a name="line.24"></a>
+<span class="sourceLineNo">025</span>import java.util.ArrayList;<a name="line.25"></a>
+<span class="sourceLineNo">026</span>import java.util.List;<a name="line.26"></a>
+<span class="sourceLineNo">027</span>import java.util.concurrent.ThreadLocalRandom;<a name="line.27"></a>
+<span class="sourceLineNo">028</span>import org.apache.hadoop.hbase.Cell;<a name="line.28"></a>
+<span class="sourceLineNo">029</span>import org.apache.hadoop.hbase.HBaseClassTestRule;<a name="line.29"></a>
+<span class="sourceLineNo">030</span>import org.apache.hadoop.hbase.HBaseTestingUtility;<a name="line.30"></a>
+<span class="sourceLineNo">031</span>import org.apache.hadoop.hbase.TableName;<a name="line.31"></a>
+<span class="sourceLineNo">032</span>import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder;<a name="line.32"></a>
+<span class="sourceLineNo">033</span>import org.apache.hadoop.hbase.client.Put;<a name="line.33"></a>
+<span class="sourceLineNo">034</span>import org.apache.hadoop.hbase.client.Result;<a name="line.34"></a>
+<span class="sourceLineNo">035</span>import org.apache.hadoop.hbase.client.Scan;<a name="line.35"></a>
+<span class="sourceLineNo">036</span>import org.apache.hadoop.hbase.client.TableDescriptorBuilder;<a name="line.36"></a>
+<span class="sourceLineNo">037</span>import org.apache.hadoop.hbase.filter.Filter;<a name="line.37"></a>
+<span class="sourceLineNo">038</span>import org.apache.hadoop.hbase.filter.FilterBase;<a name="line.38"></a>
+<span class="sourceLineNo">039</span>import org.apache.hadoop.hbase.regionserver.HRegion.RegionScannerImpl;<a name="line.39"></a>
+<span class="sourceLineNo">040</span>import org.apache.hadoop.hbase.regionserver.ScannerContext.LimitScope;<a name="line.40"></a>
+<span class="sourceLineNo">041</span>import org.apache.hadoop.hbase.testclassification.MediumTests;<a name="line.41"></a>
+<span class="sourceLineNo">042</span>import org.apache.hadoop.hbase.testclassification.RegionServerTests;<a name="line.42"></a>
+<span class="sourceLineNo">043</span>import org.apache.hadoop.hbase.util.Bytes;<a name="line.43"></a>
+<span class="sourceLineNo">044</span>import org.junit.AfterClass;<a name="line.44"></a>
+<span class="sourceLineNo">045</span>import org.junit.BeforeClass;<a name="line.45"></a>
+<span class="sourceLineNo">046</span>import org.junit.ClassRule;<a name="line.46"></a>
+<span class="sourceLineNo">047</span>import org.junit.Ignore;<a name="line.47"></a>
+<span class="sourceLineNo">048</span>import org.junit.Test;<a name="line.48"></a>
+<span class="sourceLineNo">049</span>import org.junit.experimental.categories.Category;<a name="line.49"></a>
+<span class="sourceLineNo">050</span><a name="line.50"></a>
+<span class="sourceLineNo">051</span>@Category({ RegionServerTests.class, MediumTests.class })<a name="line.51"></a>
+<span class="sourceLineNo">052</span>public class TestSwitchToStreamRead {<a name="line.52"></a>
+<span class="sourceLineNo">053</span><a name="line.53"></a>
+<span class="sourceLineNo">054</span>  @ClassRule<a name="line.54"></a>
+<span class="sourceLineNo">055</span>  public static final HBaseClassTestRule CLASS_RULE =<a name="line.55"></a>
+<span class="sourceLineNo">056</span>    HBaseClassTestRule.forClass(TestSwitchToStreamRead.class);<a name="line.56"></a>
+<span class="sourceLineNo">057</span><a name="line.57"></a>
+<span class="sourceLineNo">058</span>  private static final HBaseTestingUtility UTIL = new HBaseTestingUtility();<a name="line.58"></a>
+<span class="sourceLineNo">059</span><a name="line.59"></a>
+<span class="sourceLineNo">060</span>  private static TableName TABLE_NAME = TableName.valueOf("stream");<a name="line.60"></a>
+<span class="sourceLineNo">061</span><a name="line.61"></a>
+<span class="sourceLineNo">062</span>  private static byte[] FAMILY = Bytes.toBytes("cf");<a name="line.62"></a>
+<span class="sourceLineNo">063</span><a name="line.63"></a>
+<span class="sourceLineNo">064</span>  private static byte[] QUAL = Bytes.toBytes("cq");<a name="line.64"></a>
+<span class="sourceLineNo">065</span><a name="line.65"></a>
+<span class="sourceLineNo">066</span>  private static String VALUE_PREFIX;<a name="line.66"></a>
+<span class="sourceLineNo">067</span><a name="line.67"></a>
+<span class="sourceLineNo">068</span>  private static HRegion REGION;<a name="line.68"></a>
+<span class="sourceLineNo">069</span><a name="line.69"></a>
+<span class="sourceLineNo">070</span>  @BeforeClass<a name="line.70"></a>
+<span class="sourceLineNo">071</span>  public static void setUp() throws IOException {<a name="line.71"></a>
+<span class="sourceLineNo">072</span>    UTIL.getConfiguration().setLong(StoreScanner.STORESCANNER_PREAD_MAX_BYTES, 2048);<a name="line.72"></a>
+<span class="sourceLineNo">073</span>    StringBuilder sb = new StringBuilder(256);<a name="line.73"></a>
+<span class="sourceLineNo">074</span>    for (int i = 0; i &lt; 255; i++) {<a name="line.74"></a>
+<span class="sourceLineNo">075</span>      sb.append((char) ThreadLocalRandom.current().nextInt('A', 'z' + 1));<a name="line.75"></a>
+<span class="sourceLineNo">076</span>    }<a name="line.76"></a>
+<span class="sourceLineNo">077</span>    VALUE_PREFIX = sb.append("-").toString();<a name="line.77"></a>
+<span class="sourceLineNo">078</span>    REGION = UTIL.createLocalHRegion(<a name="line.78"></a>
+<span class="sourceLineNo">079</span>      TableDescriptorBuilder.newBuilder(TABLE_NAME)<a name="line.79"></a>
+<span class="sourceLineNo">080</span>        .setColumnFamily(<a name="line.80"></a>
+<span class="sourceLineNo">081</span>          ColumnFamilyDescriptorBuilder.newBuilder(FAMILY).setBlocksize(1024).build())<a name="line.81"></a>
+<span class="sourceLineNo">082</span>        .build(),<a name="line.82"></a>
+<span class="sourceLineNo">083</span>      null, null);<a name="line.83"></a>
+<span class="sourceLineNo">084</span>    for (int i = 0; i &lt; 900; i++) {<a name="line.84"></a>
+<span class="sourceLineNo">085</span>      REGION<a name="line.85"></a>
+<span class="sourceLineNo">086</span>        .put(new Put(Bytes.toBytes(i)).addColumn(FAMILY, QUAL, Bytes.toBytes(VALUE_PREFIX + i)));<a name="line.86"></a>
+<span class="sourceLineNo">087</span>    }<a name="line.87"></a>
+<span class="sourceLineNo">088</span>    REGION.flush(true);<a name="line.88"></a>
+<span class="sourceLineNo">089</span>    for (int i = 900; i &lt; 1000; i++) {<a name="line.89"></a>
+<span class="sourceLineNo">090</span>      REGION<a name="line.90"></a>
+<span class="sourceLineNo">091</span>        .put(new Put(Bytes.toBytes(i)).addColumn(FAMILY, QUAL, Bytes.toBytes(VALUE_PREFIX + i)));<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>  @AfterClass<a name="line.95"></a>
+<span class="sourceLineNo">096</span>  public static void tearDown() throws IOException {<a name="line.96"></a>
+<span class="sourceLineNo">097</span>    REGION.close(true);<a name="line.97"></a>
+<span class="sourceLineNo">098</span>    UTIL.cleanupTestDir();<a name="line.98"></a>
+<span class="sourceLineNo">099</span>  }<a name="line.99"></a>
+<span class="sourceLineNo">100</span><a name="line.100"></a>
+<span class="sourceLineNo">101</span>  @Test<a name="line.101"></a>
+<span class="sourceLineNo">102</span>  public void test() throws IOException {<a name="line.102"></a>
+<span class="sourceLineNo">103</span>    try (RegionScannerImpl scanner = REGION.getScanner(new Scan())) {<a name="line.103"></a>
+<span class="sourceLineNo">104</span>      StoreScanner storeScanner =<a name="line.104"></a>
+<span class="sourceLineNo">105</span>        (StoreScanner) (scanner).getStoreHeapForTesting().getCurrentForTesting();<a name="line.105"></a>
+<span class="sourceLineNo">106</span>      for (KeyValueScanner kvs : storeScanner.getAllScannersForTesting()) {<a name="line.106"></a>
+<span class="sourceLineNo">107</span>        if (kvs instanceof StoreFileScanner) {<a name="line.107"></a>
+<span class="sourceLineNo">108</span>          StoreFileScanner sfScanner = (StoreFileScanner) kvs;<a name="line.108"></a>
+<span class="sourceLineNo">109</span>          // starting from pread so we use shared reader here.<a name="line.109"></a>
+<span class="sourceLineNo">110</span>          assertTrue(sfScanner.getReader().shared);<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>      List&lt;Cell&gt; cells = new ArrayList&lt;&gt;();<a name="line.113"></a>
+<span class="sourceLineNo">114</span>      for (int i = 0; i &lt; 500; i++) {<a name="line.114"></a>
+<span class="sourceLineNo">115</span>        assertTrue(scanner.next(cells));<a name="line.115"></a>
+<span class="sourceLineNo">116</span>        Result result = Result.create(cells);<a name="line.116"></a>
+<span class="sourceLineNo">117</span>        assertEquals(VALUE_PREFIX + i, Bytes.toString(result.getValue(FAMILY, QUAL)));<a name="line.117"></a>
+<span class="sourceLineNo">118</span>        cells.clear();<a name="line.118"></a>
+<span class="sourceLineNo">119</span>        scanner.shipped();<a name="line.119"></a>
+<span class="sourceLineNo">120</span>      }<a name="line.120"></a>
+<span class="sourceLineNo">121</span>      for (KeyValueScanner kvs : storeScanner.getAllScannersForTesting()) {<a name="line.121"></a>
+<span class="sourceLineNo">122</span>        if (kvs instanceof StoreFileScanner) {<a name="line.122"></a>
+<span class="sourceLineNo">123</span>          StoreFileScanner sfScanner = (StoreFileScanner) kvs;<a name="line.123"></a>
+<span class="sourceLineNo">124</span>          // we should have convert to use stream read now.<a name="line.124"></a>
+<span class="sourceLineNo">125</span>          assertFalse(sfScanner.getReader().shared);<a name="line.125"></a>
+<span class="sourceLineNo">126</span>        }<a name="line.126"></a>
+<span class="sourceLineNo">127</span>      }<a name="line.127"></a>
+<span class="sourceLineNo">128</span>      for (int i = 500; i &lt; 1000; i++) {<a name="line.128"></a>
+<span class="sourceLineNo">129</span>        assertEquals(i != 999, scanner.next(cells));<a name="line.129"></a>
+<span class="sourceLineNo">130</span>        Result result = Result.create(cells);<a name="line.130"></a>
+<span class="sourceLineNo">131</span>        assertEquals(VALUE_PREFIX + i, Bytes.toString(result.getValue(FAMILY, QUAL)));<a name="line.131"></a>
+<span class="sourceLineNo">132</span>        cells.clear();<a name="line.132"></a>
+<span class="sourceLineNo">133</span>        scanner.shipped();<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>    // make sure all scanners are closed.<a name="line.136"></a>
+<span class="sourceLineNo">137</span>    for (HStoreFile sf : REGION.getStore(FAMILY).getStorefiles()) {<a name="line.137"></a>
+<span class="sourceLineNo">138</span>      assertFalse(sf.isReferencedInReads());<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>  public static final class MatchLastRowKeyFilter extends FilterBase {<a name="line.142"></a>
+<span class="sourceLineNo">143</span><a name="line.143"></a>
+<span class="sourceLineNo">144</span>    @Override<a name="line.144"></a>
+<span class="sourceLineNo">145</span>    public boolean filterRowKey(Cell cell) throws IOException {<a name="line.145"></a>
+<span class="sourceLineNo">146</span>      return Bytes.toInt(cell.getRowArray(), cell.getRowOffset()) != 999;<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>  private void testFilter(Filter filter) throws IOException {<a name="line.150"></a>
+<span class="sourceLineNo">151</span>    try (RegionScannerImpl scanner = REGION.getScanner(new Scan().setFilter(filter))) {<a name="line.151"></a>
+<span class="sourceLineNo">152</span>      StoreScanner storeScanner =<a name="line.152"></a>
+<span class="sourceLineNo">153</span>        (StoreScanner) (scanner).getStoreHeapForTesting().getCurrentForTesting();<a name="line.153"></a>
+<span class="sourceLineNo">154</span>      for (KeyValueScanner kvs : storeScanner.getAllScannersForTesting()) {<a name="line.154"></a>
+<span class="sourceLineNo">155</span>        if (kvs instanceof StoreFileScanner) {<a name="line.155"></a>
+<span class="sourceLineNo">156</span>          StoreFileScanner sfScanner = (StoreFileScanner) kvs;<a name="line.156"></a>
+<span class="sourceLineNo">157</span>          // starting from pread so we use shared reader here.<a name="line.157"></a>
+<span class="sourceLineNo">158</span>          assertTrue(sfScanner.getReader().shared);<a name="line.158"></a>
+<span class="sourceLineNo">159</span>        }<a name="line.159"></a>
+<span class="sourceLineNo">160</span>      }<a name="line.160"></a>
+<span class="sourceLineNo">161</span>      List&lt;Cell&gt; cells = new ArrayList&lt;&gt;();<a name="line.161"></a>
+<span class="sourceLineNo">162</span>      // should return before finishing the scan as we want to switch from pread to stream<a name="line.162"></a>
+<span class="sourceLineNo">163</span>      assertTrue(scanner.next(cells,<a name="line.163"></a>
+<span class="sourceLineNo">164</span>        ScannerContext.newBuilder().setTimeLimit(LimitScope.BETWEEN_CELLS, -1).build()));<a name="line.164"></a>
+<span class="sourceLineNo">165</span>      assertTrue(cells.isEmpty());<a name="line.165"></a>
+<span class="sourceLineNo">166</span>      scanner.shipped();<a name="line.166"></a>
+<span class="sourceLineNo">167</span><a name="line.167"></a>
+<span class="sourceLineNo">168</span>      for (KeyValueScanner kvs : storeScanner.getAllScannersForTesting()) {<a name="line.168"></a>
+<span class="sourceLineNo">169</span>        if (kvs instanceof StoreFileScanner) {<a name="line.169"></a>
+<span class="sourceLineNo">170</span>          StoreFileScanner sfScanner = (StoreFileScanner) kvs;<a name="line.170"></a>
+<span class="sourceLineNo">171</span>          // we should have convert to use stream read now.<a name="line.171"></a>
+<span class="sourceLineNo">172</span>          assertFalse(sfScanner.getReader().shared);<a name="line.172"></a>
+<span class="sourceLineNo">173</span>        }<a name="line.173"></a>
+<span class="sourceLineNo">174</span>      }<a name="line.174"></a>
+<span class="sourceLineNo">175</span>      assertFalse(scanner.next(cells,<a name="line.175"></a>
+<span class="sourceLineNo">176</span>        ScannerContext.newBuilder().setTimeLimit(LimitScope.BETWEEN_CELLS, -1).build()));<a name="line.176"></a>
+<span class="sourceLineNo">177</span>      Result result = Result.create(cells);<a name="line.177"></a>
+<span class="sourceLineNo">178</span>      assertEquals(VALUE_PREFIX + 999, Bytes.toString(result.getValue(FAMILY, QUAL)));<a name="line.178"></a>
+<span class="sourceLineNo">179</span>      cells.clear();<a name="line.179"></a>
+<span class="sourceLineNo">180</span>      scanner.shipped();<a name="line.180"></a>
+<span class="sourceLineNo">181</span>    }<a name="line.181"></a>
+<span class="sourceLineNo">182</span>    // make sure all scanners are closed.<a name="line.182"></a>
+<span class="sourceLineNo">183</span>    for (HStoreFile sf : REGION.getStore(FAMILY).getStorefiles()) {<a name="line.183"></a>
+<span class="sourceLineNo">184</span>      assertFalse(sf.isReferencedInReads());<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>  // We use a different logic to implement filterRowKey, where we will keep calling kvHeap.next<a name="line.188"></a>
+<span class="sourceLineNo">189</span>  // until the row key is changed. And there we can only use NoLimitScannerContext so we can not<a name="line.189"></a>
+<span class="sourceLineNo">190</span>  // make the upper layer return immediately. Simply do not use NoLimitScannerContext will lead to<a name="line.190"></a>
+<span class="sourceLineNo">191</span>  // an infinite loop. Need to dig more, the code are way too complicated...<a name="line.191"></a>
+<span class="sourceLineNo">192</span>  @Ignore<a name="line.192"></a>
+<span class="sourceLineNo">193</span>  @Test<a name="line.193"></a>
+<span class="sourceLineNo">194</span>  public void testFilterRowKey() throws IOException {<a name="line.194"></a>
+<span class="sourceLineNo">195</span>    testFilter(new MatchLastRowKeyFilter());<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>  public static final class MatchLastRowCellNextColFilter extends FilterBase {<a name="line.198"></a>
+<span class="sourceLineNo">199</span><a name="line.199"></a>
+<span class="sourceLineNo">200</span>    @Override<a name="line.200"></a>
+<span class="sourceLineNo">201</span>    public ReturnCode filterCell(Cell c) throws IOException {<a name="line.201"></a>
+<span class="sourceLineNo">202</span>      if (Bytes.toInt(c.getRowArray(), c.getRowOffset()) == 999) {<a name="line.202"></a>
+<span class="sourceLineNo">203</span>        return ReturnCode.INCLUDE;<a name="line.203"></a>
+<span class="sourceLineNo">204</span>      } else {<a name="line.204"></a>
+<span class="sourceLineNo">205</span>        return ReturnCode.NEXT_COL;<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>  }<a name="line.208"></a>
+<span class="sourceLineNo">209</span><a name="line.209"></a>
+<span class="sourceLineNo">210</span>  @Test<a name="line.210"></a>
+<span class="sourceLineNo">211</span>  public void testFilterCellNextCol() throws IOException {<a name="line.211"></a>
+<span class="sourceLineNo">212</span>    testFilter(new MatchLastRowCellNextColFilter());<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>  public static final class MatchLastRowCellNextRowFilter extends FilterBase {<a name="line.215"></a>
+<span class="sourceLineNo">216</span><a name="line.216"></a>
+<span class="sourceLineNo">217</span>    @Override<a name="line.217"></a>
+<span class="sourceLineNo">218</span>    public ReturnCode filterCell(Cell c) throws IOException {<a name="line.218"></a>
+<span class="sourceLineNo">219</span>      if (Bytes.toInt(c.getRowArray(), c.getRowOffset()) == 999) {<a name="line.219"></a>
+<span class="sourceLineNo">220</span>        return ReturnCode.INCLUDE;<a name="line.220"></a>
+<span class="sourceLineNo">221</span>      } else {<a name="line.221"></a>
+<span class="sourceLineNo">222</span>        return ReturnCode.NEXT_ROW;<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>  }<a name="line.225"></a>
+<span class="sourceLineNo">226</span><a name="line.226"></a>
+<span class="sourceLineNo">227</span>  @Test<a name="line.227"></a>
+<span class="sourceLineNo">228</span>  public void testFilterCellNextRow() throws IOException {<a name="line.228"></a>
+<span class="sourceLineNo">229</span>    testFilter(new MatchLastRowCellNextRowFilter());<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>  public static final class MatchLastRowFilterRowFilter extends FilterBase {<a name="line.232"></a>
+<span class="sourceLineNo">233</span><a name="line.233"></a>
+<span class="sourceLineNo">234</span>    private boolean exclude;<a name="line.234"></a>
+<span class="sourceLineNo">235</span><a name="line.235"></a>
+<span class="sourceLineNo">236</span>    @Override<a name="line.236"></a>
+<span class="sourceLineNo">237</span>    public void filterRowCells(List&lt;Cell&gt; kvs) throws IOException {<a name="line.237"></a>
+<span class="sourceLineNo">238</span>      Cell c = kvs.get(0);<a name="line.238"></a>
+<span class="sourceLineNo">239</span>      exclude = Bytes.toInt(c.getRowArray(), c.getRowOffset()) != 999;<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>    @Override<a name="line.242"></a>
+<span class="sourceLineNo">243</span>    public void reset() throws IOException {<a name="line.243"></a>
+<span class="sourceLineNo">244</span>      exclude = false;<a name="line.244"></a>
+<span class="sourceLineNo">245</span>    }<a name="line.245"></a>
+<span class="sourceLineNo">246</span><a name="line.246"></a>
+<span class="sourceLineNo">247</span>    @Override<a name="line.247"></a>
+<span class="sourceLineNo">248</span>    public boolean filterRow() throws IOException {<a name="line.248"></a>
+<span class="sourceLineNo">249</span>      return exclude;<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>    @Override<a name="line.252"></a>
+<span class="sourceLineNo">253</span>    public boolean hasFilterRow() {<a name="line.253"></a>
+<span class="sourceLineNo">254</span>      return true;<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>  @Test<a name="line.258"></a>
+<span class="sourceLineNo">259</span>  public void testFilterRow() throws IOException {<a name="line.259"></a>
+<span class="sourceLineNo">260</span>    testFilter(new MatchLastRowFilterRowFilter());<a name="line.260"></a>
+<span class="sourceLineNo">261</span>  }<a name="line.261"></a>
+<span class="sourceLineNo">262</span>}<a name="line.262"></a>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+</div>
+</body>
+</html>


[49/50] hbase-site git commit: Published site at 26babcf013de696b899d76a3c39434b794440d8d.

Posted by gi...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/filter/package-tree.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/filter/package-tree.html b/devapidocs/org/apache/hadoop/hbase/filter/package-tree.html
index 3eaeafd..4aaab52 100644
--- a/devapidocs/org/apache/hadoop/hbase/filter/package-tree.html
+++ b/devapidocs/org/apache/hadoop/hbase/filter/package-tree.html
@@ -183,14 +183,14 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true" title="class or interface in java.io">Serializable</a>)
 <ul>
-<li type="circle">org.apache.hadoop.hbase.filter.<a href="../../../../../org/apache/hadoop/hbase/filter/FuzzyRowFilter.SatisfiesCode.html" title="enum in org.apache.hadoop.hbase.filter"><span class="typeNameLink">FuzzyRowFilter.SatisfiesCode</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.filter.<a href="../../../../../org/apache/hadoop/hbase/filter/FuzzyRowFilter.Order.html" title="enum in org.apache.hadoop.hbase.filter"><span class="typeNameLink">FuzzyRowFilter.Order</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.filter.<a href="../../../../../org/apache/hadoop/hbase/filter/FilterList.Operator.html" title="enum in org.apache.hadoop.hbase.filter"><span class="typeNameLink">FilterList.Operator</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.filter.<a href="../../../../../org/apache/hadoop/hbase/filter/RegexStringComparator.EngineType.html" title="enum in org.apache.hadoop.hbase.filter"><span class="typeNameLink">RegexStringComparator.EngineType</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.filter.<a href="../../../../../org/apache/hadoop/hbase/filter/CompareFilter.CompareOp.html" title="enum in org.apache.hadoop.hbase.filter"><span class="typeNameLink">CompareFilter.CompareOp</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.filter.<a href="../../../../../org/apache/hadoop/hbase/filter/FilterWrapper.FilterRowRetCode.html" title="enum in org.apache.hadoop.hbase.filter"><span class="typeNameLink">FilterWrapper.FilterRowRetCode</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.filter.<a href="../../../../../org/apache/hadoop/hbase/filter/FuzzyRowFilter.SatisfiesCode.html" title="enum in org.apache.hadoop.hbase.filter"><span class="typeNameLink">FuzzyRowFilter.SatisfiesCode</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.filter.<a href="../../../../../org/apache/hadoop/hbase/filter/BitComparator.BitwiseOp.html" title="enum in org.apache.hadoop.hbase.filter"><span class="typeNameLink">BitComparator.BitwiseOp</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.filter.<a href="../../../../../org/apache/hadoop/hbase/filter/FilterList.Operator.html" title="enum in org.apache.hadoop.hbase.filter"><span class="typeNameLink">FilterList.Operator</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.filter.<a href="../../../../../org/apache/hadoop/hbase/filter/Filter.ReturnCode.html" title="enum in org.apache.hadoop.hbase.filter"><span class="typeNameLink">Filter.ReturnCode</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.filter.<a href="../../../../../org/apache/hadoop/hbase/filter/RegexStringComparator.EngineType.html" title="enum in org.apache.hadoop.hbase.filter"><span class="typeNameLink">RegexStringComparator.EngineType</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.filter.<a href="../../../../../org/apache/hadoop/hbase/filter/FilterWrapper.FilterRowRetCode.html" title="enum in org.apache.hadoop.hbase.filter"><span class="typeNameLink">FilterWrapper.FilterRowRetCode</span></a></li>
 </ul>
 </li>
 </ul>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlockCountsPerFile.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlockCountsPerFile.html b/devapidocs/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlockCountsPerFile.html
index 3ccf518..d643098 100644
--- a/devapidocs/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlockCountsPerFile.html
+++ b/devapidocs/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlockCountsPerFile.html
@@ -113,7 +113,7 @@ var activeTableTab = "activeTableTab";
 </dl>
 <hr>
 <br>
-<pre>static class <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html#line.69">BlockCacheUtil.CachedBlockCountsPerFile</a>
+<pre>static class <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html#line.72">BlockCacheUtil.CachedBlockCountsPerFile</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">Little data structure to hold counts for a file.
  Used doing a toJSON.</div>
@@ -235,7 +235,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>count</h4>
-<pre>private&nbsp;int <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlockCountsPerFile.html#line.70">count</a></pre>
+<pre>private&nbsp;int <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlockCountsPerFile.html#line.73">count</a></pre>
 </li>
 </ul>
 <a name="size">
@@ -244,7 +244,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>size</h4>
-<pre>private&nbsp;long <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlockCountsPerFile.html#line.71">size</a></pre>
+<pre>private&nbsp;long <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlockCountsPerFile.html#line.74">size</a></pre>
 </li>
 </ul>
 <a name="countData">
@@ -253,7 +253,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>countData</h4>
-<pre>private&nbsp;int <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlockCountsPerFile.html#line.72">countData</a></pre>
+<pre>private&nbsp;int <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlockCountsPerFile.html#line.75">countData</a></pre>
 </li>
 </ul>
 <a name="sizeData">
@@ -262,7 +262,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>sizeData</h4>
-<pre>private&nbsp;long <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlockCountsPerFile.html#line.73">sizeData</a></pre>
+<pre>private&nbsp;long <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlockCountsPerFile.html#line.76">sizeData</a></pre>
 </li>
 </ul>
 <a name="filename">
@@ -271,7 +271,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>filename</h4>
-<pre>private 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/io/hfile/BlockCacheUtil.CachedBlockCountsPerFile.html#line.74">filename</a></pre>
+<pre>private 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/io/hfile/BlockCacheUtil.CachedBlockCountsPerFile.html#line.77">filename</a></pre>
 </li>
 </ul>
 </li>
@@ -288,7 +288,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>CachedBlockCountsPerFile</h4>
-<pre><a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlockCountsPerFile.html#line.76">CachedBlockCountsPerFile</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;filename)</pre>
+<pre><a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlockCountsPerFile.html#line.79">CachedBlockCountsPerFile</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;filename)</pre>
 </li>
 </ul>
 </li>
@@ -305,7 +305,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getCount</h4>
-<pre>public&nbsp;int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlockCountsPerFile.html#line.80">getCount</a>()</pre>
+<pre>public&nbsp;int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlockCountsPerFile.html#line.83">getCount</a>()</pre>
 </li>
 </ul>
 <a name="getSize--">
@@ -314,7 +314,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getSize</h4>
-<pre>public&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlockCountsPerFile.html#line.84">getSize</a>()</pre>
+<pre>public&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlockCountsPerFile.html#line.87">getSize</a>()</pre>
 </li>
 </ul>
 <a name="getCountData--">
@@ -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>getCountData</h4>
-<pre>public&nbsp;int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlockCountsPerFile.html#line.88">getCountData</a>()</pre>
+<pre>public&nbsp;int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlockCountsPerFile.html#line.91">getCountData</a>()</pre>
 </li>
 </ul>
 <a name="getSizeData--">
@@ -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>getSizeData</h4>
-<pre>public&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlockCountsPerFile.html#line.92">getSizeData</a>()</pre>
+<pre>public&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlockCountsPerFile.html#line.95">getSizeData</a>()</pre>
 </li>
 </ul>
 <a name="getFilename--">
@@ -341,7 +341,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>getFilename</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/io/hfile/BlockCacheUtil.CachedBlockCountsPerFile.html#line.96">getFilename</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/io/hfile/BlockCacheUtil.CachedBlockCountsPerFile.html#line.99">getFilename</a>()</pre>
 </li>
 </ul>
 </li>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html b/devapidocs/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html
index 5e01e61..884c9b1 100644
--- a/devapidocs/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html
+++ b/devapidocs/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html
@@ -113,7 +113,7 @@ var activeTableTab = "activeTableTab";
 </dl>
 <hr>
 <br>
-<pre>public static class <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html#line.191">BlockCacheUtil.CachedBlocksByFile</a>
+<pre>public static class <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html#line.223">BlockCacheUtil.CachedBlocksByFile</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">Use one of these to keep a running account of cached blocks by file.  Throw it away when done.
  This is different than metrics in that it is stats on current state of a cache.
@@ -275,7 +275,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>count</h4>
-<pre>private&nbsp;int <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html#line.192">count</a></pre>
+<pre>private&nbsp;int <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html#line.224">count</a></pre>
 </li>
 </ul>
 <a name="dataBlockCount">
@@ -284,7 +284,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>dataBlockCount</h4>
-<pre>private&nbsp;int <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html#line.193">dataBlockCount</a></pre>
+<pre>private&nbsp;int <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html#line.225">dataBlockCount</a></pre>
 </li>
 </ul>
 <a name="size">
@@ -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>size</h4>
-<pre>private&nbsp;long <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html#line.194">size</a></pre>
+<pre>private&nbsp;long <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html#line.226">size</a></pre>
 </li>
 </ul>
 <a name="dataSize">
@@ -302,7 +302,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>dataSize</h4>
-<pre>private&nbsp;long <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html#line.195">dataSize</a></pre>
+<pre>private&nbsp;long <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html#line.227">dataSize</a></pre>
 </li>
 </ul>
 <a name="now">
@@ -311,7 +311,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>now</h4>
-<pre>private final&nbsp;long <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html#line.196">now</a></pre>
+<pre>private final&nbsp;long <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html#line.228">now</a></pre>
 </li>
 </ul>
 <a name="max">
@@ -320,7 +320,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>max</h4>
-<pre>private final&nbsp;int <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html#line.204">max</a></pre>
+<pre>private final&nbsp;int <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html#line.236">max</a></pre>
 <div class="block">How many blocks to look at before we give up.
  There could be many millions of blocks. We don't want the
  ui to freeze while we run through 1B blocks... users will
@@ -334,7 +334,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>DEFAULT_MAX</h4>
-<pre>public static final&nbsp;int <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html#line.205">DEFAULT_MAX</a></pre>
+<pre>public static final&nbsp;int <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html#line.237">DEFAULT_MAX</a></pre>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
 <dd><a href="../../../../../../constant-values.html#org.apache.hadoop.hbase.io.hfile.BlockCacheUtil.CachedBlocksByFile.DEFAULT_MAX">Constant Field Values</a></dd>
@@ -347,7 +347,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>cachedBlockByFile</h4>
-<pre>private&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/NavigableMap.html?is-external=true" title="class or interface in java.util">NavigableMap</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/util/NavigableSet.html?is-external=true" title="class or interface in java.util">NavigableSet</a>&lt;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/CachedBlock.html" title="interface in org.apache.hadoop.hbase.io.hfile">CachedBlock</a>&gt;&gt; <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html#line.218">cachedBlockByFile</a></pre>
+<pre>private&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/NavigableMap.html?is-external=true" title="class or interface in java.util">NavigableMap</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/util/NavigableSet.html?is-external=true" title="class or interface in java.util">NavigableSet</a>&lt;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/CachedBlock.html" title="interface in org.apache.hadoop.hbase.io.hfile">CachedBlock</a>&gt;&gt; <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html#line.250">cachedBlockByFile</a></pre>
 <div class="block">Map by filename. use concurent utils because we want our Map and contained blocks sorted.</div>
 </li>
 </ul>
@@ -357,7 +357,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>hist</h4>
-<pre><a href="../../../../../../org/apache/hadoop/hbase/metrics/impl/FastLongHistogram.html" title="class in org.apache.hadoop.hbase.metrics.impl">FastLongHistogram</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html#line.219">hist</a></pre>
+<pre><a href="../../../../../../org/apache/hadoop/hbase/metrics/impl/FastLongHistogram.html" title="class in org.apache.hadoop.hbase.metrics.impl">FastLongHistogram</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html#line.251">hist</a></pre>
 </li>
 </ul>
 </li>
@@ -374,7 +374,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>CachedBlocksByFile</h4>
-<pre><a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html#line.207">CachedBlocksByFile</a>()</pre>
+<pre><a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html#line.239">CachedBlocksByFile</a>()</pre>
 </li>
 </ul>
 <a name="CachedBlocksByFile-org.apache.hadoop.conf.Configuration-">
@@ -383,7 +383,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>CachedBlocksByFile</h4>
-<pre><a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html#line.211">CachedBlocksByFile</a>(org.apache.hadoop.conf.Configuration&nbsp;c)</pre>
+<pre><a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html#line.243">CachedBlocksByFile</a>(org.apache.hadoop.conf.Configuration&nbsp;c)</pre>
 </li>
 </ul>
 </li>
@@ -400,7 +400,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>update</h4>
-<pre>public&nbsp;boolean&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html#line.225">update</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/CachedBlock.html" title="interface in org.apache.hadoop.hbase.io.hfile">CachedBlock</a>&nbsp;cb)</pre>
+<pre>public&nbsp;boolean&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html#line.257">update</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/CachedBlock.html" title="interface in org.apache.hadoop.hbase.io.hfile">CachedBlock</a>&nbsp;cb)</pre>
 <dl>
 <dt><span class="paramLabel">Parameters:</span></dt>
 <dd><code>cb</code> - </dd>
@@ -415,7 +415,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>isFull</h4>
-<pre>public&nbsp;boolean&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html#line.250">isFull</a>()</pre>
+<pre>public&nbsp;boolean&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html#line.282">isFull</a>()</pre>
 <dl>
 <dt><span class="returnLabel">Returns:</span></dt>
 <dd>True if full; i.e. there are more items in the cache but we only loaded up
@@ -430,7 +430,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getCachedBlockStatsByFile</h4>
-<pre>public&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/NavigableMap.html?is-external=true" title="class or interface in java.util">NavigableMap</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/util/NavigableSet.html?is-external=true" title="class or interface in java.util">NavigableSet</a>&lt;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/CachedBlock.html" title="interface in org.apache.hadoop.hbase.io.hfile">CachedBlock</a>&gt;&gt;&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html#line.254">getCachedBlockStatsByFile</a>()</pre>
+<pre>public&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/NavigableMap.html?is-external=true" title="class or interface in java.util">NavigableMap</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/util/NavigableSet.html?is-external=true" title="class or interface in java.util">NavigableSet</a>&lt;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/CachedBlock.html" title="interface in org.apache.hadoop.hbase.io.hfile">CachedBlock</a>&gt;&gt;&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html#line.286">getCachedBlockStatsByFile</a>()</pre>
 </li>
 </ul>
 <a name="getCount--">
@@ -439,7 +439,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getCount</h4>
-<pre>public&nbsp;int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html#line.261">getCount</a>()</pre>
+<pre>public&nbsp;int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html#line.293">getCount</a>()</pre>
 <dl>
 <dt><span class="returnLabel">Returns:</span></dt>
 <dd>count of blocks in the cache</dd>
@@ -452,7 +452,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getDataCount</h4>
-<pre>public&nbsp;int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html#line.265">getDataCount</a>()</pre>
+<pre>public&nbsp;int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html#line.297">getDataCount</a>()</pre>
 </li>
 </ul>
 <a name="getSize--">
@@ -461,7 +461,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getSize</h4>
-<pre>public&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html#line.272">getSize</a>()</pre>
+<pre>public&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html#line.304">getSize</a>()</pre>
 <dl>
 <dt><span class="returnLabel">Returns:</span></dt>
 <dd>size of blocks in the cache</dd>
@@ -474,7 +474,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getDataSize</h4>
-<pre>public&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html#line.279">getDataSize</a>()</pre>
+<pre>public&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html#line.311">getDataSize</a>()</pre>
 <dl>
 <dt><span class="returnLabel">Returns:</span></dt>
 <dd>Size of data.</dd>
@@ -487,7 +487,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getAgeInCacheSnapshot</h4>
-<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/AgeSnapshot.html" title="class in org.apache.hadoop.hbase.io.hfile">AgeSnapshot</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html#line.283">getAgeInCacheSnapshot</a>()</pre>
+<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/AgeSnapshot.html" title="class in org.apache.hadoop.hbase.io.hfile">AgeSnapshot</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html#line.315">getAgeInCacheSnapshot</a>()</pre>
 </li>
 </ul>
 <a name="toString--">
@@ -496,7 +496,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>toString</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/io/hfile/BlockCacheUtil.CachedBlocksByFile.html#line.288">toString</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/io/hfile/BlockCacheUtil.CachedBlocksByFile.html#line.320">toString</a>()</pre>
 <dl>
 <dt><span class="overrideSpecifyLabel">Overrides:</span></dt>
 <dd><code><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true#toString--" title="class or interface in java.lang">toString</a></code>&nbsp;in class&nbsp;<code><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></code></dd>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html b/devapidocs/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html
index 4040aa1..6b86d0c 100644
--- a/devapidocs/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html
+++ b/devapidocs/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html
@@ -18,7 +18,7 @@
     catch(err) {
     }
 //-->
-var methods = {"i0":9,"i1":9,"i2":9,"i3":9,"i4":9,"i5":9,"i6":9};
+var methods = {"i0":9,"i1":9,"i2":9,"i3":9,"i4":9,"i5":9,"i6":9,"i7":9};
 var tabs = {65535:["t0","All Methods"],1:["t1","Static Methods"],8:["t4","Concrete Methods"]};
 var altColor = "altColor";
 var rowColor = "rowColor";
@@ -110,7 +110,7 @@ var activeTableTab = "activeTableTab";
 <hr>
 <br>
 <pre>@InterfaceAudience.Private
-public class <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html#line.42">BlockCacheUtil</a>
+public class <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html#line.44">BlockCacheUtil</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">Utilty for aggregating counts in CachedBlocks and toString/toJSON CachedBlocks and BlockCaches.
  No attempt has been made at making this thread safe.</div>
@@ -160,12 +160,16 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <th class="colLast" scope="col">Field and Description</th>
 </tr>
 <tr class="altColor">
+<td class="colFirst"><code>private static org.slf4j.Logger</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html#LOG">LOG</a></span></code>&nbsp;</td>
+</tr>
+<tr class="rowColor">
 <td class="colFirst"><code>private static com.fasterxml.jackson.databind.ObjectMapper</code></td>
 <td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html#MAPPER">MAPPER</a></span></code>
 <div class="block">Needed generating JSON.</div>
 </td>
 </tr>
-<tr class="rowColor">
+<tr class="altColor">
 <td class="colFirst"><code>static long</code></td>
 <td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html#NANOS_PER_SECOND">NANOS_PER_SECOND</a></span></code>&nbsp;</td>
 </tr>
@@ -202,9 +206,10 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <th class="colLast" scope="col">Method and Description</th>
 </tr>
 <tr id="i0" class="altColor">
-<td class="colFirst"><code>static int</code></td>
-<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html#compareCacheBlock-org.apache.hadoop.hbase.io.hfile.Cacheable-org.apache.hadoop.hbase.io.hfile.Cacheable-">compareCacheBlock</a></span>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html" title="interface in org.apache.hadoop.hbase.io.hfile">Cacheable</a>&nbsp;left,
-                 <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html" title="interface in org.apache.hadoop.hbase.io.hfile">Cacheable</a>&nbsp;right)</code>&nbsp;</td>
+<td class="colFirst"><code>private static int</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html#compareCacheBlock-org.apache.hadoop.hbase.io.hfile.Cacheable-org.apache.hadoop.hbase.io.hfile.Cacheable-boolean-">compareCacheBlock</a></span>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html" title="interface in org.apache.hadoop.hbase.io.hfile">Cacheable</a>&nbsp;left,
+                 <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html" title="interface in org.apache.hadoop.hbase.io.hfile">Cacheable</a>&nbsp;right,
+                 boolean&nbsp;includeNextBlockMetadata)</code>&nbsp;</td>
 </tr>
 <tr id="i1" class="rowColor">
 <td class="colFirst"><code>static <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheUtil.CachedBlocksByFile</a></code></td>
@@ -237,6 +242,15 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html#toStringMinusFileName-org.apache.hadoop.hbase.io.hfile.CachedBlock-long-">toStringMinusFileName</a></span>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/CachedBlock.html" title="interface in org.apache.hadoop.hbase.io.hfile">CachedBlock</a>&nbsp;cb,
                      long&nbsp;now)</code>&nbsp;</td>
 </tr>
+<tr id="i7" class="rowColor">
+<td class="colFirst"><code>static int</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html#validateBlockAddition-org.apache.hadoop.hbase.io.hfile.Cacheable-org.apache.hadoop.hbase.io.hfile.Cacheable-org.apache.hadoop.hbase.io.hfile.BlockCacheKey-">validateBlockAddition</a></span>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html" title="interface in org.apache.hadoop.hbase.io.hfile">Cacheable</a>&nbsp;existing,
+                     <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html" title="interface in org.apache.hadoop.hbase.io.hfile">Cacheable</a>&nbsp;newBlock,
+                     <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a>&nbsp;cacheKey)</code>
+<div class="block">Validate that the existing and newBlock are the same without including the nextBlockMetadata,
+ if not, throw an exception.</div>
+</td>
+</tr>
 </table>
 <ul class="blockList">
 <li class="blockList"><a name="methods.inherited.from.class.java.lang.Object">
@@ -259,13 +273,22 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <!--   -->
 </a>
 <h3>Field Detail</h3>
+<a name="LOG">
+<!--   -->
+</a>
+<ul class="blockList">
+<li class="blockList">
+<h4>LOG</h4>
+<pre>private static final&nbsp;org.slf4j.Logger <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html#line.46">LOG</a></pre>
+</li>
+</ul>
 <a name="NANOS_PER_SECOND">
 <!--   -->
 </a>
 <ul class="blockList">
 <li class="blockList">
 <h4>NANOS_PER_SECOND</h4>
-<pre>public static final&nbsp;long <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html#line.45">NANOS_PER_SECOND</a></pre>
+<pre>public static final&nbsp;long <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html#line.48">NANOS_PER_SECOND</a></pre>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
 <dd><a href="../../../../../../constant-values.html#org.apache.hadoop.hbase.io.hfile.BlockCacheUtil.NANOS_PER_SECOND">Constant Field Values</a></dd>
@@ -278,7 +301,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>MAPPER</h4>
-<pre>private static final&nbsp;com.fasterxml.jackson.databind.ObjectMapper <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html#line.50">MAPPER</a></pre>
+<pre>private static final&nbsp;com.fasterxml.jackson.databind.ObjectMapper <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html#line.53">MAPPER</a></pre>
 <div class="block">Needed generating JSON.</div>
 </li>
 </ul>
@@ -296,7 +319,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>BlockCacheUtil</h4>
-<pre>public&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html#line.42">BlockCacheUtil</a>()</pre>
+<pre>public&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html#line.44">BlockCacheUtil</a>()</pre>
 </li>
 </ul>
 </li>
@@ -313,7 +336,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>toString</h4>
-<pre>public static&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html#line.61">toString</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/CachedBlock.html" title="interface in org.apache.hadoop.hbase.io.hfile">CachedBlock</a>&nbsp;cb,
+<pre>public static&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html#line.64">toString</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/CachedBlock.html" title="interface in org.apache.hadoop.hbase.io.hfile">CachedBlock</a>&nbsp;cb,
                               long&nbsp;now)</pre>
 <dl>
 <dt><span class="paramLabel">Parameters:</span></dt>
@@ -329,7 +352,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>toJSON</h4>
-<pre>public static&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html#line.109">toJSON</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;filename,
+<pre>public static&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html#line.112">toJSON</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;filename,
                             <a href="https://docs.oracle.com/javase/8/docs/api/java/util/NavigableSet.html?is-external=true" title="class or interface in java.util">NavigableSet</a>&lt;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/CachedBlock.html" title="interface in org.apache.hadoop.hbase.io.hfile">CachedBlock</a>&gt;&nbsp;blocks)
                      throws com.fasterxml.jackson.core.JsonGenerationException,
                             com.fasterxml.jackson.databind.JsonMappingException,
@@ -353,7 +376,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>toJSON</h4>
-<pre>public static&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html#line.131">toJSON</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheUtil.CachedBlocksByFile</a>&nbsp;cbsbf)
+<pre>public static&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html#line.134">toJSON</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheUtil.CachedBlocksByFile</a>&nbsp;cbsbf)
                      throws com.fasterxml.jackson.core.JsonGenerationException,
                             com.fasterxml.jackson.databind.JsonMappingException,
                             <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>
@@ -375,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>toJSON</h4>
-<pre>public static&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html#line.143">toJSON</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCache.html" title="interface in org.apache.hadoop.hbase.io.hfile">BlockCache</a>&nbsp;bc)
+<pre>public static&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html#line.146">toJSON</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCache.html" title="interface in org.apache.hadoop.hbase.io.hfile">BlockCache</a>&nbsp;bc)
                      throws com.fasterxml.jackson.core.JsonGenerationException,
                             com.fasterxml.jackson.databind.JsonMappingException,
                             <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>
@@ -397,7 +420,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>toStringMinusFileName</h4>
-<pre>public static&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html#line.152">toStringMinusFileName</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/CachedBlock.html" title="interface in org.apache.hadoop.hbase.io.hfile">CachedBlock</a>&nbsp;cb,
+<pre>public static&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html#line.155">toStringMinusFileName</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/CachedBlock.html" title="interface in org.apache.hadoop.hbase.io.hfile">CachedBlock</a>&nbsp;cb,
                                            long&nbsp;now)</pre>
 <dl>
 <dt><span class="paramLabel">Parameters:</span></dt>
@@ -413,7 +436,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getLoadedCachedBlocksByFile</h4>
-<pre>public static&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheUtil.CachedBlocksByFile</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html#line.167">getLoadedCachedBlocksByFile</a>(org.apache.hadoop.conf.Configuration&nbsp;conf,
+<pre>public static&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheUtil.CachedBlocksByFile</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html#line.170">getLoadedCachedBlocksByFile</a>(org.apache.hadoop.conf.Configuration&nbsp;conf,
                                                                             <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCache.html" title="interface in org.apache.hadoop.hbase.io.hfile">BlockCache</a>&nbsp;bc)</pre>
 <div class="block">Get a <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html" title="class in org.apache.hadoop.hbase.io.hfile"><code>BlockCacheUtil.CachedBlocksByFile</code></a> instance and load it up by iterating content in
  <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCache.html" title="interface in org.apache.hadoop.hbase.io.hfile"><code>BlockCache</code></a>.</div>
@@ -426,14 +449,37 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 </dl>
 </li>
 </ul>
-<a name="compareCacheBlock-org.apache.hadoop.hbase.io.hfile.Cacheable-org.apache.hadoop.hbase.io.hfile.Cacheable-">
+<a name="compareCacheBlock-org.apache.hadoop.hbase.io.hfile.Cacheable-org.apache.hadoop.hbase.io.hfile.Cacheable-boolean-">
 <!--   -->
 </a>
-<ul class="blockListLast">
+<ul class="blockList">
 <li class="blockList">
 <h4>compareCacheBlock</h4>
-<pre>public static&nbsp;int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html#line.176">compareCacheBlock</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html" title="interface in org.apache.hadoop.hbase.io.hfile">Cacheable</a>&nbsp;left,
-                                    <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html" title="interface in org.apache.hadoop.hbase.io.hfile">Cacheable</a>&nbsp;right)</pre>
+<pre>private static&nbsp;int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html#line.179">compareCacheBlock</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html" title="interface in org.apache.hadoop.hbase.io.hfile">Cacheable</a>&nbsp;left,
+                                     <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html" title="interface in org.apache.hadoop.hbase.io.hfile">Cacheable</a>&nbsp;right,
+                                     boolean&nbsp;includeNextBlockMetadata)</pre>
+</li>
+</ul>
+<a name="validateBlockAddition-org.apache.hadoop.hbase.io.hfile.Cacheable-org.apache.hadoop.hbase.io.hfile.Cacheable-org.apache.hadoop.hbase.io.hfile.BlockCacheKey-">
+<!--   -->
+</a>
+<ul class="blockListLast">
+<li class="blockList">
+<h4>validateBlockAddition</h4>
+<pre>public static&nbsp;int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html#line.199">validateBlockAddition</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html" title="interface in org.apache.hadoop.hbase.io.hfile">Cacheable</a>&nbsp;existing,
+                                        <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html" title="interface in org.apache.hadoop.hbase.io.hfile">Cacheable</a>&nbsp;newBlock,
+                                        <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a>&nbsp;cacheKey)</pre>
+<div class="block">Validate that the existing and newBlock are the same without including the nextBlockMetadata,
+ if not, throw an exception. If they are the same without the nextBlockMetadata,
+ return the comparison.</div>
+<dl>
+<dt><span class="paramLabel">Parameters:</span></dt>
+<dd><code>existing</code> - block that is existing in the cache.</dd>
+<dd><code>newBlock</code> - block that is trying to be cached.</dd>
+<dd><code>cacheKey</code> - the cache key of the blocks.</dd>
+<dt><span class="returnLabel">Returns:</span></dt>
+<dd>comparison of the existing block to the newBlock.</dd>
+</dl>
 </li>
 </ul>
 </li>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/io/hfile/Cacheable.MemoryType.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/io/hfile/Cacheable.MemoryType.html b/devapidocs/org/apache/hadoop/hbase/io/hfile/Cacheable.MemoryType.html
index bfab06f..c3270a3 100644
--- a/devapidocs/org/apache/hadoop/hbase/io/hfile/Cacheable.MemoryType.html
+++ b/devapidocs/org/apache/hadoop/hbase/io/hfile/Cacheable.MemoryType.html
@@ -122,7 +122,7 @@ var activeTableTab = "activeTableTab";
 </dl>
 <hr>
 <br>
-<pre>public static enum <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/Cacheable.html#line.75">Cacheable.MemoryType</a>
+<pre>public static enum <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/Cacheable.html#line.76">Cacheable.MemoryType</a>
 extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang">Enum</a>&lt;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.MemoryType.html" title="enum in org.apache.hadoop.hbase.io.hfile">Cacheable.MemoryType</a>&gt;</pre>
 <div class="block">SHARED means when this Cacheable is read back from cache it refers to the same memory area as
  used by the cache for caching it.
@@ -214,7 +214,7 @@ the order they are declared.</div>
 <ul class="blockList">
 <li class="blockList">
 <h4>SHARED</h4>
-<pre>public static final&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.MemoryType.html" title="enum in org.apache.hadoop.hbase.io.hfile">Cacheable.MemoryType</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/Cacheable.MemoryType.html#line.76">SHARED</a></pre>
+<pre>public static final&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.MemoryType.html" title="enum in org.apache.hadoop.hbase.io.hfile">Cacheable.MemoryType</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/Cacheable.MemoryType.html#line.77">SHARED</a></pre>
 </li>
 </ul>
 <a name="EXCLUSIVE">
@@ -223,7 +223,7 @@ the order they are declared.</div>
 <ul class="blockListLast">
 <li class="blockList">
 <h4>EXCLUSIVE</h4>
-<pre>public static final&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.MemoryType.html" title="enum in org.apache.hadoop.hbase.io.hfile">Cacheable.MemoryType</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/Cacheable.MemoryType.html#line.76">EXCLUSIVE</a></pre>
+<pre>public static final&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.MemoryType.html" title="enum in org.apache.hadoop.hbase.io.hfile">Cacheable.MemoryType</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/Cacheable.MemoryType.html#line.77">EXCLUSIVE</a></pre>
 </li>
 </ul>
 </li>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/io/hfile/Cacheable.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/io/hfile/Cacheable.html b/devapidocs/org/apache/hadoop/hbase/io/hfile/Cacheable.html
index ac0c1f6..1f7161d 100644
--- a/devapidocs/org/apache/hadoop/hbase/io/hfile/Cacheable.html
+++ b/devapidocs/org/apache/hadoop/hbase/io/hfile/Cacheable.html
@@ -180,7 +180,8 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/io/HeapSize.html" tit
 </tr>
 <tr id="i4" class="altColor">
 <td class="colFirst"><code>void</code></td>
-<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html#serialize-java.nio.ByteBuffer-">serialize</a></span>(<a href="https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html?is-external=true" title="class or interface in java.nio">ByteBuffer</a>&nbsp;destination)</code>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html#serialize-java.nio.ByteBuffer-boolean-">serialize</a></span>(<a href="https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html?is-external=true" title="class or interface in java.nio">ByteBuffer</a>&nbsp;destination,
+         boolean&nbsp;includeNextBlockMetadata)</code>
 <div class="block">Serializes its data into destination.</div>
 </td>
 </tr>
@@ -221,17 +222,19 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/io/HeapSize.html" tit
 </dl>
 </li>
 </ul>
-<a name="serialize-java.nio.ByteBuffer-">
+<a name="serialize-java.nio.ByteBuffer-boolean-">
 <!--   -->
 </a>
 <ul class="blockList">
 <li class="blockList">
 <h4>serialize</h4>
-<pre>void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/Cacheable.html#line.50">serialize</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html?is-external=true" title="class or interface in java.nio">ByteBuffer</a>&nbsp;destination)</pre>
+<pre>void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/Cacheable.html#line.51">serialize</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html?is-external=true" title="class or interface in java.nio">ByteBuffer</a>&nbsp;destination,
+               boolean&nbsp;includeNextBlockMetadata)</pre>
 <div class="block">Serializes its data into destination.</div>
 <dl>
 <dt><span class="paramLabel">Parameters:</span></dt>
 <dd><code>destination</code> - Where to serialize to</dd>
+<dd><code>includeNextBlockMetadata</code> - Whether to include nextBlockMetadata in the Cache block.</dd>
 </dl>
 </li>
 </ul>
@@ -241,7 +244,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/io/HeapSize.html" tit
 <ul class="blockList">
 <li class="blockList">
 <h4>getDeserializer</h4>
-<pre><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/CacheableDeserializer.html" title="interface in org.apache.hadoop.hbase.io.hfile">CacheableDeserializer</a>&lt;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html" title="interface in org.apache.hadoop.hbase.io.hfile">Cacheable</a>&gt;&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/Cacheable.html#line.57">getDeserializer</a>()</pre>
+<pre><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/CacheableDeserializer.html" title="interface in org.apache.hadoop.hbase.io.hfile">CacheableDeserializer</a>&lt;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html" title="interface in org.apache.hadoop.hbase.io.hfile">Cacheable</a>&gt;&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/Cacheable.html#line.58">getDeserializer</a>()</pre>
 <div class="block">Returns CacheableDeserializer instance which reconstructs original object from ByteBuffer.</div>
 <dl>
 <dt><span class="returnLabel">Returns:</span></dt>
@@ -255,7 +258,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/io/HeapSize.html" tit
 <ul class="blockList">
 <li class="blockList">
 <h4>getBlockType</h4>
-<pre><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockType.html" title="enum in org.apache.hadoop.hbase.io.hfile">BlockType</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/Cacheable.html#line.62">getBlockType</a>()</pre>
+<pre><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockType.html" title="enum in org.apache.hadoop.hbase.io.hfile">BlockType</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/Cacheable.html#line.63">getBlockType</a>()</pre>
 <dl>
 <dt><span class="returnLabel">Returns:</span></dt>
 <dd>the block type of this cached HFile block</dd>
@@ -268,7 +271,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/io/HeapSize.html" tit
 <ul class="blockListLast">
 <li class="blockList">
 <h4>getMemoryType</h4>
-<pre><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.MemoryType.html" title="enum in org.apache.hadoop.hbase.io.hfile">Cacheable.MemoryType</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/Cacheable.html#line.67">getMemoryType</a>()</pre>
+<pre><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.MemoryType.html" title="enum in org.apache.hadoop.hbase.io.hfile">Cacheable.MemoryType</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/Cacheable.html#line.68">getMemoryType</a>()</pre>
 <dl>
 <dt><span class="returnLabel">Returns:</span></dt>
 <dd>the <code>MemoryType</code> of this Cacheable</dd>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/io/hfile/HFileBlock.BlockIterator.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/io/hfile/HFileBlock.BlockIterator.html b/devapidocs/org/apache/hadoop/hbase/io/hfile/HFileBlock.BlockIterator.html
index 5dc4da8..b6e49f2 100644
--- a/devapidocs/org/apache/hadoop/hbase/io/hfile/HFileBlock.BlockIterator.html
+++ b/devapidocs/org/apache/hadoop/hbase/io/hfile/HFileBlock.BlockIterator.html
@@ -105,7 +105,7 @@ var activeTableTab = "activeTableTab";
 </dl>
 <hr>
 <br>
-<pre>static interface <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.1343">HFileBlock.BlockIterator</a></pre>
+<pre>static interface <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.1345">HFileBlock.BlockIterator</a></pre>
 <div class="block">Iterator for <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.html" title="class in org.apache.hadoop.hbase.io.hfile"><code>HFileBlock</code></a>s.</div>
 </li>
 </ul>
@@ -159,7 +159,7 @@ var activeTableTab = "activeTableTab";
 <ul class="blockList">
 <li class="blockList">
 <h4>nextBlock</h4>
-<pre><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.html" title="class in org.apache.hadoop.hbase.io.hfile">HFileBlock</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.BlockIterator.html#line.1347">nextBlock</a>()
+<pre><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.html" title="class in org.apache.hadoop.hbase.io.hfile">HFileBlock</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.BlockIterator.html#line.1349">nextBlock</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">Get the next block, or null if there are no more blocks to iterate.</div>
 <dl>
@@ -174,7 +174,7 @@ var activeTableTab = "activeTableTab";
 <ul class="blockListLast">
 <li class="blockList">
 <h4>nextBlockWithBlockType</h4>
-<pre><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.html" title="class in org.apache.hadoop.hbase.io.hfile">HFileBlock</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.BlockIterator.html#line.1353">nextBlockWithBlockType</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockType.html" title="enum in org.apache.hadoop.hbase.io.hfile">BlockType</a>&nbsp;blockType)
+<pre><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.html" title="class in org.apache.hadoop.hbase.io.hfile">HFileBlock</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.BlockIterator.html#line.1355">nextBlockWithBlockType</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockType.html" title="enum in org.apache.hadoop.hbase.io.hfile">BlockType</a>&nbsp;blockType)
                            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">Similar to <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.BlockIterator.html#nextBlock--"><code>nextBlock()</code></a> but checks block type, throws an
  exception if incorrect, and returns the HFile block</div>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/io/hfile/HFileBlock.BlockWritable.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/io/hfile/HFileBlock.BlockWritable.html b/devapidocs/org/apache/hadoop/hbase/io/hfile/HFileBlock.BlockWritable.html
index 79aa02f..823ec80 100644
--- a/devapidocs/org/apache/hadoop/hbase/io/hfile/HFileBlock.BlockWritable.html
+++ b/devapidocs/org/apache/hadoop/hbase/io/hfile/HFileBlock.BlockWritable.html
@@ -105,7 +105,7 @@ var activeTableTab = "activeTableTab";
 </dl>
 <hr>
 <br>
-<pre>static interface <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.1329">HFileBlock.BlockWritable</a></pre>
+<pre>static interface <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.1331">HFileBlock.BlockWritable</a></pre>
 <div class="block">Something that can be written into a block.</div>
 </li>
 </ul>
@@ -158,7 +158,7 @@ var activeTableTab = "activeTableTab";
 <ul class="blockList">
 <li class="blockList">
 <h4>getBlockType</h4>
-<pre><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockType.html" title="enum in org.apache.hadoop.hbase.io.hfile">BlockType</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.BlockWritable.html#line.1331">getBlockType</a>()</pre>
+<pre><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockType.html" title="enum in org.apache.hadoop.hbase.io.hfile">BlockType</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.BlockWritable.html#line.1333">getBlockType</a>()</pre>
 <div class="block">The type of block this data should use.</div>
 </li>
 </ul>
@@ -168,7 +168,7 @@ var activeTableTab = "activeTableTab";
 <ul class="blockListLast">
 <li class="blockList">
 <h4>writeToBlock</h4>
-<pre>void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.BlockWritable.html#line.1339">writeToBlock</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/io/DataOutput.html?is-external=true" title="class or interface in java.io">DataOutput</a>&nbsp;out)
+<pre>void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.BlockWritable.html#line.1341">writeToBlock</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/io/DataOutput.html?is-external=true" title="class or interface in java.io">DataOutput</a>&nbsp;out)
            throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
 <div class="block">Writes the block to the provided stream. Must not write any magic
  records.</div>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReader.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReader.html b/devapidocs/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReader.html
index 01d64d3..70e0e81 100644
--- a/devapidocs/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReader.html
+++ b/devapidocs/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReader.html
@@ -109,7 +109,7 @@ var activeTableTab = "activeTableTab";
 </dl>
 <hr>
 <br>
-<pre>static interface <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.1357">HFileBlock.FSReader</a></pre>
+<pre>static interface <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.1359">HFileBlock.FSReader</a></pre>
 <div class="block">An HFile block reader with iteration ability.</div>
 </li>
 </ul>
@@ -199,7 +199,7 @@ var activeTableTab = "activeTableTab";
 <ul class="blockList">
 <li class="blockList">
 <h4>readBlockData</h4>
-<pre><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.html" title="class in org.apache.hadoop.hbase.io.hfile">HFileBlock</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReader.html#line.1367">readBlockData</a>(long&nbsp;offset,
+<pre><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.html" title="class in org.apache.hadoop.hbase.io.hfile">HFileBlock</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReader.html#line.1369">readBlockData</a>(long&nbsp;offset,
                          long&nbsp;onDiskSize,
                          boolean&nbsp;pread,
                          boolean&nbsp;updateMetrics)
@@ -224,7 +224,7 @@ var activeTableTab = "activeTableTab";
 <ul class="blockList">
 <li class="blockList">
 <h4>blockRange</h4>
-<pre><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.BlockIterator.html" title="interface in org.apache.hadoop.hbase.io.hfile">HFileBlock.BlockIterator</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReader.html#line.1381">blockRange</a>(long&nbsp;startOffset,
+<pre><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.BlockIterator.html" title="interface in org.apache.hadoop.hbase.io.hfile">HFileBlock.BlockIterator</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReader.html#line.1383">blockRange</a>(long&nbsp;startOffset,
                                     long&nbsp;endOffset)</pre>
 <div class="block">Creates a block iterator over the given portion of the <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFile.html" title="class in org.apache.hadoop.hbase.io.hfile"><code>HFile</code></a>.
  The iterator returns blocks starting with offset such that offset &lt;=
@@ -246,7 +246,7 @@ var activeTableTab = "activeTableTab";
 <ul class="blockList">
 <li class="blockList">
 <h4>closeStreams</h4>
-<pre>void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReader.html#line.1384">closeStreams</a>()
+<pre>void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReader.html#line.1386">closeStreams</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">Closes the backing streams</div>
 <dl>
@@ -261,7 +261,7 @@ var activeTableTab = "activeTableTab";
 <ul class="blockList">
 <li class="blockList">
 <h4>getBlockDecodingContext</h4>
-<pre><a href="../../../../../../org/apache/hadoop/hbase/io/encoding/HFileBlockDecodingContext.html" title="interface in org.apache.hadoop.hbase.io.encoding">HFileBlockDecodingContext</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReader.html#line.1387">getBlockDecodingContext</a>()</pre>
+<pre><a href="../../../../../../org/apache/hadoop/hbase/io/encoding/HFileBlockDecodingContext.html" title="interface in org.apache.hadoop.hbase.io.encoding">HFileBlockDecodingContext</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReader.html#line.1389">getBlockDecodingContext</a>()</pre>
 <div class="block">Get a decoder for <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockType.html#ENCODED_DATA"><code>BlockType.ENCODED_DATA</code></a> blocks from this file.</div>
 </li>
 </ul>
@@ -271,7 +271,7 @@ var activeTableTab = "activeTableTab";
 <ul class="blockList">
 <li class="blockList">
 <h4>getDefaultBlockDecodingContext</h4>
-<pre><a href="../../../../../../org/apache/hadoop/hbase/io/encoding/HFileBlockDecodingContext.html" title="interface in org.apache.hadoop.hbase.io.encoding">HFileBlockDecodingContext</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReader.html#line.1390">getDefaultBlockDecodingContext</a>()</pre>
+<pre><a href="../../../../../../org/apache/hadoop/hbase/io/encoding/HFileBlockDecodingContext.html" title="interface in org.apache.hadoop.hbase.io.encoding">HFileBlockDecodingContext</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReader.html#line.1392">getDefaultBlockDecodingContext</a>()</pre>
 <div class="block">Get the default decoder for blocks from this file.</div>
 </li>
 </ul>
@@ -281,7 +281,7 @@ var activeTableTab = "activeTableTab";
 <ul class="blockList">
 <li class="blockList">
 <h4>setIncludesMemStoreTS</h4>
-<pre>void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReader.html#line.1392">setIncludesMemStoreTS</a>(boolean&nbsp;includesMemstoreTS)</pre>
+<pre>void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReader.html#line.1394">setIncludesMemStoreTS</a>(boolean&nbsp;includesMemstoreTS)</pre>
 </li>
 </ul>
 <a name="setDataBlockEncoder-org.apache.hadoop.hbase.io.hfile.HFileDataBlockEncoder-">
@@ -290,7 +290,7 @@ var activeTableTab = "activeTableTab";
 <ul class="blockList">
 <li class="blockList">
 <h4>setDataBlockEncoder</h4>
-<pre>void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReader.html#line.1393">setDataBlockEncoder</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileDataBlockEncoder.html" title="interface in org.apache.hadoop.hbase.io.hfile">HFileDataBlockEncoder</a>&nbsp;encoder)</pre>
+<pre>void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReader.html#line.1395">setDataBlockEncoder</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileDataBlockEncoder.html" title="interface in org.apache.hadoop.hbase.io.hfile">HFileDataBlockEncoder</a>&nbsp;encoder)</pre>
 </li>
 </ul>
 <a name="unbufferStream--">
@@ -299,7 +299,7 @@ var activeTableTab = "activeTableTab";
 <ul class="blockListLast">
 <li class="blockList">
 <h4>unbufferStream</h4>
-<pre>void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReader.html#line.1399">unbufferStream</a>()</pre>
+<pre>void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReader.html#line.1401">unbufferStream</a>()</pre>
 <div class="block">To close the stream's socket. Note: This can be concurrently called from multiple threads and
  implementation should take care of thread safety.</div>
 </li>


[27/50] hbase-site git commit: Published site at 26babcf013de696b899d76a3c39434b794440d8d.

Posted by gi...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html
----------------------------------------------------------------------
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html
index f5747c6..b94ef5e 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html
@@ -388,811 +388,816 @@
 <span class="sourceLineNo">380</span><a name="line.380"></a>
 <span class="sourceLineNo">381</span>    LruCachedBlock cb = map.get(cacheKey);<a name="line.381"></a>
 <span class="sourceLineNo">382</span>    if (cb != null) {<a name="line.382"></a>
-<span class="sourceLineNo">383</span>      // compare the contents, if they are not equal, we are in big trouble<a name="line.383"></a>
-<span class="sourceLineNo">384</span>      if (BlockCacheUtil.compareCacheBlock(buf, cb.getBuffer()) != 0) {<a name="line.384"></a>
-<span class="sourceLineNo">385</span>        throw new RuntimeException("Cached block contents differ, which should not have happened."<a name="line.385"></a>
-<span class="sourceLineNo">386</span>          + "cacheKey:" + cacheKey);<a name="line.386"></a>
-<span class="sourceLineNo">387</span>      }<a name="line.387"></a>
-<span class="sourceLineNo">388</span>      String msg = "Cached an already cached block: " + cacheKey + " cb:" + cb.getCacheKey();<a name="line.388"></a>
-<span class="sourceLineNo">389</span>      msg += ". This is harmless and can happen in rare cases (see HBASE-8547)";<a name="line.389"></a>
-<span class="sourceLineNo">390</span>      LOG.warn(msg);<a name="line.390"></a>
-<span class="sourceLineNo">391</span>      return;<a name="line.391"></a>
-<span class="sourceLineNo">392</span>    }<a name="line.392"></a>
-<span class="sourceLineNo">393</span>    long currentSize = size.get();<a name="line.393"></a>
-<span class="sourceLineNo">394</span>    long currentAcceptableSize = acceptableSize();<a name="line.394"></a>
-<span class="sourceLineNo">395</span>    long hardLimitSize = (long) (hardCapacityLimitFactor * currentAcceptableSize);<a name="line.395"></a>
-<span class="sourceLineNo">396</span>    if (currentSize &gt;= hardLimitSize) {<a name="line.396"></a>
-<span class="sourceLineNo">397</span>      stats.failInsert();<a name="line.397"></a>
-<span class="sourceLineNo">398</span>      if (LOG.isTraceEnabled()) {<a name="line.398"></a>
-<span class="sourceLineNo">399</span>        LOG.trace("LruBlockCache current size " + StringUtils.byteDesc(currentSize)<a name="line.399"></a>
-<span class="sourceLineNo">400</span>          + " has exceeded acceptable size " + StringUtils.byteDesc(currentAcceptableSize) + "."<a name="line.400"></a>
-<span class="sourceLineNo">401</span>          + " The hard limit size is " + StringUtils.byteDesc(hardLimitSize)<a name="line.401"></a>
-<span class="sourceLineNo">402</span>          + ", failed to put cacheKey:" + cacheKey + " into LruBlockCache.");<a name="line.402"></a>
-<span class="sourceLineNo">403</span>      }<a name="line.403"></a>
-<span class="sourceLineNo">404</span>      if (!evictionInProgress) {<a name="line.404"></a>
-<span class="sourceLineNo">405</span>        runEviction();<a name="line.405"></a>
-<span class="sourceLineNo">406</span>      }<a name="line.406"></a>
-<span class="sourceLineNo">407</span>      return;<a name="line.407"></a>
-<span class="sourceLineNo">408</span>    }<a name="line.408"></a>
-<span class="sourceLineNo">409</span>    cb = new LruCachedBlock(cacheKey, buf, count.incrementAndGet(), inMemory);<a name="line.409"></a>
-<span class="sourceLineNo">410</span>    long newSize = updateSizeMetrics(cb, false);<a name="line.410"></a>
-<span class="sourceLineNo">411</span>    map.put(cacheKey, cb);<a name="line.411"></a>
-<span class="sourceLineNo">412</span>    long val = elements.incrementAndGet();<a name="line.412"></a>
-<span class="sourceLineNo">413</span>    if (buf.getBlockType().isData()) {<a name="line.413"></a>
-<span class="sourceLineNo">414</span>       dataBlockElements.increment();<a name="line.414"></a>
-<span class="sourceLineNo">415</span>    }<a name="line.415"></a>
-<span class="sourceLineNo">416</span>    if (LOG.isTraceEnabled()) {<a name="line.416"></a>
-<span class="sourceLineNo">417</span>      long size = map.size();<a name="line.417"></a>
-<span class="sourceLineNo">418</span>      assertCounterSanity(size, val);<a name="line.418"></a>
-<span class="sourceLineNo">419</span>    }<a name="line.419"></a>
-<span class="sourceLineNo">420</span>    if (newSize &gt; currentAcceptableSize &amp;&amp; !evictionInProgress) {<a name="line.420"></a>
-<span class="sourceLineNo">421</span>      runEviction();<a name="line.421"></a>
-<span class="sourceLineNo">422</span>    }<a name="line.422"></a>
-<span class="sourceLineNo">423</span>  }<a name="line.423"></a>
-<span class="sourceLineNo">424</span><a name="line.424"></a>
-<span class="sourceLineNo">425</span>  /**<a name="line.425"></a>
-<span class="sourceLineNo">426</span>   * Sanity-checking for parity between actual block cache content and metrics.<a name="line.426"></a>
-<span class="sourceLineNo">427</span>   * Intended only for use with TRACE level logging and -ea JVM.<a name="line.427"></a>
-<span class="sourceLineNo">428</span>   */<a name="line.428"></a>
-<span class="sourceLineNo">429</span>  private static void assertCounterSanity(long mapSize, long counterVal) {<a name="line.429"></a>
-<span class="sourceLineNo">430</span>    if (counterVal &lt; 0) {<a name="line.430"></a>
-<span class="sourceLineNo">431</span>      LOG.trace("counterVal overflow. Assertions unreliable. counterVal=" + counterVal +<a name="line.431"></a>
-<span class="sourceLineNo">432</span>        ", mapSize=" + mapSize);<a name="line.432"></a>
-<span class="sourceLineNo">433</span>      return;<a name="line.433"></a>
-<span class="sourceLineNo">434</span>    }<a name="line.434"></a>
-<span class="sourceLineNo">435</span>    if (mapSize &lt; Integer.MAX_VALUE) {<a name="line.435"></a>
-<span class="sourceLineNo">436</span>      double pct_diff = Math.abs((((double) counterVal) / ((double) mapSize)) - 1.);<a name="line.436"></a>
-<span class="sourceLineNo">437</span>      if (pct_diff &gt; 0.05) {<a name="line.437"></a>
-<span class="sourceLineNo">438</span>        LOG.trace("delta between reported and actual size &gt; 5%. counterVal=" + counterVal +<a name="line.438"></a>
-<span class="sourceLineNo">439</span>          ", mapSize=" + mapSize);<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><a name="line.443"></a>
-<span class="sourceLineNo">444</span>  /**<a name="line.444"></a>
-<span class="sourceLineNo">445</span>   * Cache the block with the specified name and buffer.<a name="line.445"></a>
-<span class="sourceLineNo">446</span>   * &lt;p&gt;<a name="line.446"></a>
-<span class="sourceLineNo">447</span>   *<a name="line.447"></a>
-<span class="sourceLineNo">448</span>   * @param cacheKey block's cache key<a name="line.448"></a>
-<span class="sourceLineNo">449</span>   * @param buf      block buffer<a name="line.449"></a>
-<span class="sourceLineNo">450</span>   */<a name="line.450"></a>
-<span class="sourceLineNo">451</span>  @Override<a name="line.451"></a>
-<span class="sourceLineNo">452</span>  public void cacheBlock(BlockCacheKey cacheKey, Cacheable buf) {<a name="line.452"></a>
-<span class="sourceLineNo">453</span>    cacheBlock(cacheKey, buf, false);<a name="line.453"></a>
-<span class="sourceLineNo">454</span>  }<a name="line.454"></a>
-<span class="sourceLineNo">455</span><a name="line.455"></a>
-<span class="sourceLineNo">456</span>  /**<a name="line.456"></a>
-<span class="sourceLineNo">457</span>   * Helper function that updates the local size counter and also updates any<a name="line.457"></a>
-<span class="sourceLineNo">458</span>   * per-cf or per-blocktype metrics it can discern from given<a name="line.458"></a>
-<span class="sourceLineNo">459</span>   * {@link LruCachedBlock}<a name="line.459"></a>
-<span class="sourceLineNo">460</span>   */<a name="line.460"></a>
-<span class="sourceLineNo">461</span>  private long updateSizeMetrics(LruCachedBlock cb, boolean evict) {<a name="line.461"></a>
-<span class="sourceLineNo">462</span>    long heapsize = cb.heapSize();<a name="line.462"></a>
-<span class="sourceLineNo">463</span>    BlockType bt = cb.getBuffer().getBlockType();<a name="line.463"></a>
-<span class="sourceLineNo">464</span>    if (evict) {<a name="line.464"></a>
-<span class="sourceLineNo">465</span>      heapsize *= -1;<a name="line.465"></a>
-<span class="sourceLineNo">466</span>    }<a name="line.466"></a>
-<span class="sourceLineNo">467</span>    if (bt != null &amp;&amp; bt.isData()) {<a name="line.467"></a>
-<span class="sourceLineNo">468</span>       dataBlockSize.add(heapsize);<a name="line.468"></a>
-<span class="sourceLineNo">469</span>    }<a name="line.469"></a>
-<span class="sourceLineNo">470</span>    return size.addAndGet(heapsize);<a name="line.470"></a>
-<span class="sourceLineNo">471</span>  }<a name="line.471"></a>
-<span class="sourceLineNo">472</span><a name="line.472"></a>
-<span class="sourceLineNo">473</span>  /**<a name="line.473"></a>
-<span class="sourceLineNo">474</span>   * Get the buffer of the block with the specified name.<a name="line.474"></a>
-<span class="sourceLineNo">475</span>   *<a name="line.475"></a>
-<span class="sourceLineNo">476</span>   * @param cacheKey           block's cache key<a name="line.476"></a>
-<span class="sourceLineNo">477</span>   * @param caching            true if the caller caches blocks on cache misses<a name="line.477"></a>
-<span class="sourceLineNo">478</span>   * @param repeat             Whether this is a repeat lookup for the same block<a name="line.478"></a>
-<span class="sourceLineNo">479</span>   *                           (used to avoid double counting cache misses when doing double-check<a name="line.479"></a>
-<span class="sourceLineNo">480</span>   *                           locking)<a name="line.480"></a>
-<span class="sourceLineNo">481</span>   * @param updateCacheMetrics Whether to update cache metrics or not<a name="line.481"></a>
-<span class="sourceLineNo">482</span>   *<a name="line.482"></a>
-<span class="sourceLineNo">483</span>   * @return buffer of specified cache key, or null if not in cache<a name="line.483"></a>
-<span class="sourceLineNo">484</span>   */<a name="line.484"></a>
-<span class="sourceLineNo">485</span>  @Override<a name="line.485"></a>
-<span class="sourceLineNo">486</span>  public Cacheable getBlock(BlockCacheKey cacheKey, boolean caching, boolean repeat,<a name="line.486"></a>
-<span class="sourceLineNo">487</span>      boolean updateCacheMetrics) {<a name="line.487"></a>
-<span class="sourceLineNo">488</span>    LruCachedBlock cb = map.get(cacheKey);<a name="line.488"></a>
-<span class="sourceLineNo">489</span>    if (cb == null) {<a name="line.489"></a>
-<span class="sourceLineNo">490</span>      if (!repeat &amp;&amp; updateCacheMetrics) {<a name="line.490"></a>
-<span class="sourceLineNo">491</span>        stats.miss(caching, cacheKey.isPrimary(), cacheKey.getBlockType());<a name="line.491"></a>
-<span class="sourceLineNo">492</span>      }<a name="line.492"></a>
-<span class="sourceLineNo">493</span>      // If there is another block cache then try and read there.<a name="line.493"></a>
-<span class="sourceLineNo">494</span>      // However if this is a retry ( second time in double checked locking )<a name="line.494"></a>
-<span class="sourceLineNo">495</span>      // And it's already a miss then the l2 will also be a miss.<a name="line.495"></a>
-<span class="sourceLineNo">496</span>      if (victimHandler != null &amp;&amp; !repeat) {<a name="line.496"></a>
-<span class="sourceLineNo">497</span>        Cacheable result = victimHandler.getBlock(cacheKey, caching, repeat, updateCacheMetrics);<a name="line.497"></a>
-<span class="sourceLineNo">498</span><a name="line.498"></a>
-<span class="sourceLineNo">499</span>        // Promote this to L1.<a name="line.499"></a>
-<span class="sourceLineNo">500</span>        if (result != null &amp;&amp; caching) {<a name="line.500"></a>
-<span class="sourceLineNo">501</span>          if (result instanceof HFileBlock &amp;&amp; ((HFileBlock) result).usesSharedMemory()) {<a name="line.501"></a>
-<span class="sourceLineNo">502</span>            result = ((HFileBlock) result).deepClone();<a name="line.502"></a>
-<span class="sourceLineNo">503</span>          }<a name="line.503"></a>
-<span class="sourceLineNo">504</span>          cacheBlock(cacheKey, result, /* inMemory = */ false);<a name="line.504"></a>
-<span class="sourceLineNo">505</span>        }<a name="line.505"></a>
-<span class="sourceLineNo">506</span>        return result;<a name="line.506"></a>
-<span class="sourceLineNo">507</span>      }<a name="line.507"></a>
-<span class="sourceLineNo">508</span>      return null;<a name="line.508"></a>
-<span class="sourceLineNo">509</span>    }<a name="line.509"></a>
-<span class="sourceLineNo">510</span>    if (updateCacheMetrics) stats.hit(caching, cacheKey.isPrimary(), cacheKey.getBlockType());<a name="line.510"></a>
-<span class="sourceLineNo">511</span>    cb.access(count.incrementAndGet());<a name="line.511"></a>
-<span class="sourceLineNo">512</span>    return cb.getBuffer();<a name="line.512"></a>
-<span class="sourceLineNo">513</span>  }<a name="line.513"></a>
-<span class="sourceLineNo">514</span><a name="line.514"></a>
-<span class="sourceLineNo">515</span>  /**<a name="line.515"></a>
-<span class="sourceLineNo">516</span>   * Whether the cache contains block with specified cacheKey<a name="line.516"></a>
-<span class="sourceLineNo">517</span>   *<a name="line.517"></a>
-<span class="sourceLineNo">518</span>   * @return true if contains the block<a name="line.518"></a>
-<span class="sourceLineNo">519</span>   */<a name="line.519"></a>
-<span class="sourceLineNo">520</span>  public boolean containsBlock(BlockCacheKey cacheKey) {<a name="line.520"></a>
-<span class="sourceLineNo">521</span>    return map.containsKey(cacheKey);<a name="line.521"></a>
-<span class="sourceLineNo">522</span>  }<a name="line.522"></a>
-<span class="sourceLineNo">523</span><a name="line.523"></a>
-<span class="sourceLineNo">524</span>  @Override<a name="line.524"></a>
-<span class="sourceLineNo">525</span>  public boolean evictBlock(BlockCacheKey cacheKey) {<a name="line.525"></a>
-<span class="sourceLineNo">526</span>    LruCachedBlock cb = map.get(cacheKey);<a name="line.526"></a>
-<span class="sourceLineNo">527</span>    return cb != null &amp;&amp; evictBlock(cb, false) &gt; 0;<a name="line.527"></a>
-<span class="sourceLineNo">528</span>  }<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>   * Evicts all blocks for a specific HFile. This is an<a name="line.531"></a>
-<span class="sourceLineNo">532</span>   * expensive operation implemented as a linear-time search through all blocks<a name="line.532"></a>
-<span class="sourceLineNo">533</span>   * in the cache. Ideally this should be a search in a log-access-time map.<a name="line.533"></a>
-<span class="sourceLineNo">534</span>   *<a name="line.534"></a>
-<span class="sourceLineNo">535</span>   * &lt;p&gt;<a name="line.535"></a>
-<span class="sourceLineNo">536</span>   * This is used for evict-on-close to remove all blocks of a specific HFile.<a name="line.536"></a>
-<span class="sourceLineNo">537</span>   *<a name="line.537"></a>
-<span class="sourceLineNo">538</span>   * @return the number of blocks evicted<a name="line.538"></a>
-<span class="sourceLineNo">539</span>   */<a name="line.539"></a>
-<span class="sourceLineNo">540</span>  @Override<a name="line.540"></a>
-<span class="sourceLineNo">541</span>  public int evictBlocksByHfileName(String hfileName) {<a name="line.541"></a>
-<span class="sourceLineNo">542</span>    int numEvicted = 0;<a name="line.542"></a>
-<span class="sourceLineNo">543</span>    for (BlockCacheKey key : map.keySet()) {<a name="line.543"></a>
-<span class="sourceLineNo">544</span>      if (key.getHfileName().equals(hfileName)) {<a name="line.544"></a>
-<span class="sourceLineNo">545</span>        if (evictBlock(key))<a name="line.545"></a>
-<span class="sourceLineNo">546</span>          ++numEvicted;<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>    if (victimHandler != null) {<a name="line.549"></a>
-<span class="sourceLineNo">550</span>      numEvicted += victimHandler.evictBlocksByHfileName(hfileName);<a name="line.550"></a>
-<span class="sourceLineNo">551</span>    }<a name="line.551"></a>
-<span class="sourceLineNo">552</span>    return numEvicted;<a name="line.552"></a>
-<span class="sourceLineNo">553</span>  }<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>   * Evict the block, and it will be cached by the victim handler if exists &amp;amp;&amp;amp;<a name="line.556"></a>
-<span class="sourceLineNo">557</span>   * block may be read again later<a name="line.557"></a>
-<span class="sourceLineNo">558</span>   *<a name="line.558"></a>
-<span class="sourceLineNo">559</span>   * @param evictedByEvictionProcess true if the given block is evicted by<a name="line.559"></a>
-<span class="sourceLineNo">560</span>   *          EvictionThread<a name="line.560"></a>
-<span class="sourceLineNo">561</span>   * @return the heap size of evicted block<a name="line.561"></a>
-<span class="sourceLineNo">562</span>   */<a name="line.562"></a>
-<span class="sourceLineNo">563</span>  protected long evictBlock(LruCachedBlock block, boolean evictedByEvictionProcess) {<a name="line.563"></a>
-<span class="sourceLineNo">564</span>    boolean found = map.remove(block.getCacheKey()) != null;<a name="line.564"></a>
-<span class="sourceLineNo">565</span>    if (!found) {<a name="line.565"></a>
-<span class="sourceLineNo">566</span>      return 0;<a name="line.566"></a>
-<span class="sourceLineNo">567</span>    }<a name="line.567"></a>
-<span class="sourceLineNo">568</span>    updateSizeMetrics(block, true);<a name="line.568"></a>
-<span class="sourceLineNo">569</span>    long val = elements.decrementAndGet();<a name="line.569"></a>
-<span class="sourceLineNo">570</span>    if (LOG.isTraceEnabled()) {<a name="line.570"></a>
-<span class="sourceLineNo">571</span>      long size = map.size();<a name="line.571"></a>
-<span class="sourceLineNo">572</span>      assertCounterSanity(size, val);<a name="line.572"></a>
-<span class="sourceLineNo">573</span>    }<a name="line.573"></a>
-<span class="sourceLineNo">574</span>    if (block.getBuffer().getBlockType().isData()) {<a name="line.574"></a>
-<span class="sourceLineNo">575</span>       dataBlockElements.decrement();<a name="line.575"></a>
-<span class="sourceLineNo">576</span>    }<a name="line.576"></a>
-<span class="sourceLineNo">577</span>    if (evictedByEvictionProcess) {<a name="line.577"></a>
-<span class="sourceLineNo">578</span>      // When the eviction of the block happened because of invalidation of HFiles, no need to<a name="line.578"></a>
-<span class="sourceLineNo">579</span>      // update the stats counter.<a name="line.579"></a>
-<span class="sourceLineNo">580</span>      stats.evicted(block.getCachedTime(), block.getCacheKey().isPrimary());<a name="line.580"></a>
-<span class="sourceLineNo">581</span>      if (victimHandler != null) {<a name="line.581"></a>
-<span class="sourceLineNo">582</span>        victimHandler.cacheBlock(block.getCacheKey(), block.getBuffer());<a name="line.582"></a>
-<span class="sourceLineNo">583</span>      }<a name="line.583"></a>
-<span class="sourceLineNo">584</span>    }<a name="line.584"></a>
-<span class="sourceLineNo">585</span>    return block.heapSize();<a name="line.585"></a>
-<span class="sourceLineNo">586</span>  }<a name="line.586"></a>
-<span class="sourceLineNo">587</span><a name="line.587"></a>
-<span class="sourceLineNo">588</span>  /**<a name="line.588"></a>
-<span class="sourceLineNo">589</span>   * Multi-threaded call to run the eviction process.<a name="line.589"></a>
-<span class="sourceLineNo">590</span>   */<a name="line.590"></a>
-<span class="sourceLineNo">591</span>  private void runEviction() {<a name="line.591"></a>
-<span class="sourceLineNo">592</span>    if (evictionThread == null) {<a name="line.592"></a>
-<span class="sourceLineNo">593</span>      evict();<a name="line.593"></a>
-<span class="sourceLineNo">594</span>    } else {<a name="line.594"></a>
-<span class="sourceLineNo">595</span>      evictionThread.evict();<a name="line.595"></a>
-<span class="sourceLineNo">596</span>    }<a name="line.596"></a>
-<span class="sourceLineNo">597</span>  }<a name="line.597"></a>
-<span class="sourceLineNo">598</span><a name="line.598"></a>
-<span class="sourceLineNo">599</span>  @VisibleForTesting<a name="line.599"></a>
-<span class="sourceLineNo">600</span>  boolean isEvictionInProgress() {<a name="line.600"></a>
-<span class="sourceLineNo">601</span>    return evictionInProgress;<a name="line.601"></a>
+<span class="sourceLineNo">383</span>      int comparison = BlockCacheUtil.validateBlockAddition(cb.getBuffer(), buf, cacheKey);<a name="line.383"></a>
+<span class="sourceLineNo">384</span>      if (comparison != 0) {<a name="line.384"></a>
+<span class="sourceLineNo">385</span>        if (comparison &lt; 0) {<a name="line.385"></a>
+<span class="sourceLineNo">386</span>          LOG.warn("Cached block contents differ by nextBlockOnDiskSize. Keeping cached block.");<a name="line.386"></a>
+<span class="sourceLineNo">387</span>          return;<a name="line.387"></a>
+<span class="sourceLineNo">388</span>        } else {<a name="line.388"></a>
+<span class="sourceLineNo">389</span>          LOG.warn("Cached block contents differ by nextBlockOnDiskSize. Caching new block.");<a name="line.389"></a>
+<span class="sourceLineNo">390</span>        }<a name="line.390"></a>
+<span class="sourceLineNo">391</span>      } else {<a name="line.391"></a>
+<span class="sourceLineNo">392</span>        String msg = "Cached an already cached block: " + cacheKey + " cb:" + cb.getCacheKey();<a name="line.392"></a>
+<span class="sourceLineNo">393</span>        msg += ". This is harmless and can happen in rare cases (see HBASE-8547)";<a name="line.393"></a>
+<span class="sourceLineNo">394</span>        LOG.warn(msg);<a name="line.394"></a>
+<span class="sourceLineNo">395</span>        return;<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>    long currentSize = size.get();<a name="line.398"></a>
+<span class="sourceLineNo">399</span>    long currentAcceptableSize = acceptableSize();<a name="line.399"></a>
+<span class="sourceLineNo">400</span>    long hardLimitSize = (long) (hardCapacityLimitFactor * currentAcceptableSize);<a name="line.400"></a>
+<span class="sourceLineNo">401</span>    if (currentSize &gt;= hardLimitSize) {<a name="line.401"></a>
+<span class="sourceLineNo">402</span>      stats.failInsert();<a name="line.402"></a>
+<span class="sourceLineNo">403</span>      if (LOG.isTraceEnabled()) {<a name="line.403"></a>
+<span class="sourceLineNo">404</span>        LOG.trace("LruBlockCache current size " + StringUtils.byteDesc(currentSize)<a name="line.404"></a>
+<span class="sourceLineNo">405</span>          + " has exceeded acceptable size " + StringUtils.byteDesc(currentAcceptableSize) + "."<a name="line.405"></a>
+<span class="sourceLineNo">406</span>          + " The hard limit size is " + StringUtils.byteDesc(hardLimitSize)<a name="line.406"></a>
+<span class="sourceLineNo">407</span>          + ", failed to put cacheKey:" + cacheKey + " into LruBlockCache.");<a name="line.407"></a>
+<span class="sourceLineNo">408</span>      }<a name="line.408"></a>
+<span class="sourceLineNo">409</span>      if (!evictionInProgress) {<a name="line.409"></a>
+<span class="sourceLineNo">410</span>        runEviction();<a name="line.410"></a>
+<span class="sourceLineNo">411</span>      }<a name="line.411"></a>
+<span class="sourceLineNo">412</span>      return;<a name="line.412"></a>
+<span class="sourceLineNo">413</span>    }<a name="line.413"></a>
+<span class="sourceLineNo">414</span>    cb = new LruCachedBlock(cacheKey, buf, count.incrementAndGet(), inMemory);<a name="line.414"></a>
+<span class="sourceLineNo">415</span>    long newSize = updateSizeMetrics(cb, false);<a name="line.415"></a>
+<span class="sourceLineNo">416</span>    map.put(cacheKey, cb);<a name="line.416"></a>
+<span class="sourceLineNo">417</span>    long val = elements.incrementAndGet();<a name="line.417"></a>
+<span class="sourceLineNo">418</span>    if (buf.getBlockType().isData()) {<a name="line.418"></a>
+<span class="sourceLineNo">419</span>       dataBlockElements.increment();<a name="line.419"></a>
+<span class="sourceLineNo">420</span>    }<a name="line.420"></a>
+<span class="sourceLineNo">421</span>    if (LOG.isTraceEnabled()) {<a name="line.421"></a>
+<span class="sourceLineNo">422</span>      long size = map.size();<a name="line.422"></a>
+<span class="sourceLineNo">423</span>      assertCounterSanity(size, val);<a name="line.423"></a>
+<span class="sourceLineNo">424</span>    }<a name="line.424"></a>
+<span class="sourceLineNo">425</span>    if (newSize &gt; currentAcceptableSize &amp;&amp; !evictionInProgress) {<a name="line.425"></a>
+<span class="sourceLineNo">426</span>      runEviction();<a name="line.426"></a>
+<span class="sourceLineNo">427</span>    }<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>   * Sanity-checking for parity between actual block cache content and metrics.<a name="line.431"></a>
+<span class="sourceLineNo">432</span>   * Intended only for use with TRACE level logging and -ea JVM.<a name="line.432"></a>
+<span class="sourceLineNo">433</span>   */<a name="line.433"></a>
+<span class="sourceLineNo">434</span>  private static void assertCounterSanity(long mapSize, long counterVal) {<a name="line.434"></a>
+<span class="sourceLineNo">435</span>    if (counterVal &lt; 0) {<a name="line.435"></a>
+<span class="sourceLineNo">436</span>      LOG.trace("counterVal overflow. Assertions unreliable. counterVal=" + counterVal +<a name="line.436"></a>
+<span class="sourceLineNo">437</span>        ", mapSize=" + mapSize);<a name="line.437"></a>
+<span class="sourceLineNo">438</span>      return;<a name="line.438"></a>
+<span class="sourceLineNo">439</span>    }<a name="line.439"></a>
+<span class="sourceLineNo">440</span>    if (mapSize &lt; Integer.MAX_VALUE) {<a name="line.440"></a>
+<span class="sourceLineNo">441</span>      double pct_diff = Math.abs((((double) counterVal) / ((double) mapSize)) - 1.);<a name="line.441"></a>
+<span class="sourceLineNo">442</span>      if (pct_diff &gt; 0.05) {<a name="line.442"></a>
+<span class="sourceLineNo">443</span>        LOG.trace("delta between reported and actual size &gt; 5%. counterVal=" + counterVal +<a name="line.443"></a>
+<span class="sourceLineNo">444</span>          ", mapSize=" + mapSize);<a name="line.444"></a>
+<span class="sourceLineNo">445</span>      }<a name="line.445"></a>
+<span class="sourceLineNo">446</span>    }<a name="line.446"></a>
+<span class="sourceLineNo">447</span>  }<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>   * Cache the block with the specified name and buffer.<a name="line.450"></a>
+<span class="sourceLineNo">451</span>   * &lt;p&gt;<a name="line.451"></a>
+<span class="sourceLineNo">452</span>   *<a name="line.452"></a>
+<span class="sourceLineNo">453</span>   * @param cacheKey block's cache key<a name="line.453"></a>
+<span class="sourceLineNo">454</span>   * @param buf      block buffer<a name="line.454"></a>
+<span class="sourceLineNo">455</span>   */<a name="line.455"></a>
+<span class="sourceLineNo">456</span>  @Override<a name="line.456"></a>
+<span class="sourceLineNo">457</span>  public void cacheBlock(BlockCacheKey cacheKey, Cacheable buf) {<a name="line.457"></a>
+<span class="sourceLineNo">458</span>    cacheBlock(cacheKey, buf, false);<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>  /**<a name="line.461"></a>
+<span class="sourceLineNo">462</span>   * Helper function that updates the local size counter and also updates any<a name="line.462"></a>
+<span class="sourceLineNo">463</span>   * per-cf or per-blocktype metrics it can discern from given<a name="line.463"></a>
+<span class="sourceLineNo">464</span>   * {@link LruCachedBlock}<a name="line.464"></a>
+<span class="sourceLineNo">465</span>   */<a name="line.465"></a>
+<span class="sourceLineNo">466</span>  private long updateSizeMetrics(LruCachedBlock cb, boolean evict) {<a name="line.466"></a>
+<span class="sourceLineNo">467</span>    long heapsize = cb.heapSize();<a name="line.467"></a>
+<span class="sourceLineNo">468</span>    BlockType bt = cb.getBuffer().getBlockType();<a name="line.468"></a>
+<span class="sourceLineNo">469</span>    if (evict) {<a name="line.469"></a>
+<span class="sourceLineNo">470</span>      heapsize *= -1;<a name="line.470"></a>
+<span class="sourceLineNo">471</span>    }<a name="line.471"></a>
+<span class="sourceLineNo">472</span>    if (bt != null &amp;&amp; bt.isData()) {<a name="line.472"></a>
+<span class="sourceLineNo">473</span>       dataBlockSize.add(heapsize);<a name="line.473"></a>
+<span class="sourceLineNo">474</span>    }<a name="line.474"></a>
+<span class="sourceLineNo">475</span>    return size.addAndGet(heapsize);<a name="line.475"></a>
+<span class="sourceLineNo">476</span>  }<a name="line.476"></a>
+<span class="sourceLineNo">477</span><a name="line.477"></a>
+<span class="sourceLineNo">478</span>  /**<a name="line.478"></a>
+<span class="sourceLineNo">479</span>   * Get the buffer of the block with the specified name.<a name="line.479"></a>
+<span class="sourceLineNo">480</span>   *<a name="line.480"></a>
+<span class="sourceLineNo">481</span>   * @param cacheKey           block's cache key<a name="line.481"></a>
+<span class="sourceLineNo">482</span>   * @param caching            true if the caller caches blocks on cache misses<a name="line.482"></a>
+<span class="sourceLineNo">483</span>   * @param repeat             Whether this is a repeat lookup for the same block<a name="line.483"></a>
+<span class="sourceLineNo">484</span>   *                           (used to avoid double counting cache misses when doing double-check<a name="line.484"></a>
+<span class="sourceLineNo">485</span>   *                           locking)<a name="line.485"></a>
+<span class="sourceLineNo">486</span>   * @param updateCacheMetrics Whether to update cache metrics or not<a name="line.486"></a>
+<span class="sourceLineNo">487</span>   *<a name="line.487"></a>
+<span class="sourceLineNo">488</span>   * @return buffer of specified cache key, or null if not in cache<a name="line.488"></a>
+<span class="sourceLineNo">489</span>   */<a name="line.489"></a>
+<span class="sourceLineNo">490</span>  @Override<a name="line.490"></a>
+<span class="sourceLineNo">491</span>  public Cacheable getBlock(BlockCacheKey cacheKey, boolean caching, boolean repeat,<a name="line.491"></a>
+<span class="sourceLineNo">492</span>      boolean updateCacheMetrics) {<a name="line.492"></a>
+<span class="sourceLineNo">493</span>    LruCachedBlock cb = map.get(cacheKey);<a name="line.493"></a>
+<span class="sourceLineNo">494</span>    if (cb == null) {<a name="line.494"></a>
+<span class="sourceLineNo">495</span>      if (!repeat &amp;&amp; updateCacheMetrics) {<a name="line.495"></a>
+<span class="sourceLineNo">496</span>        stats.miss(caching, cacheKey.isPrimary(), cacheKey.getBlockType());<a name="line.496"></a>
+<span class="sourceLineNo">497</span>      }<a name="line.497"></a>
+<span class="sourceLineNo">498</span>      // If there is another block cache then try and read there.<a name="line.498"></a>
+<span class="sourceLineNo">499</span>      // However if this is a retry ( second time in double checked locking )<a name="line.499"></a>
+<span class="sourceLineNo">500</span>      // And it's already a miss then the l2 will also be a miss.<a name="line.500"></a>
+<span class="sourceLineNo">501</span>      if (victimHandler != null &amp;&amp; !repeat) {<a name="line.501"></a>
+<span class="sourceLineNo">502</span>        Cacheable result = victimHandler.getBlock(cacheKey, caching, repeat, updateCacheMetrics);<a name="line.502"></a>
+<span class="sourceLineNo">503</span><a name="line.503"></a>
+<span class="sourceLineNo">504</span>        // Promote this to L1.<a name="line.504"></a>
+<span class="sourceLineNo">505</span>        if (result != null &amp;&amp; caching) {<a name="line.505"></a>
+<span class="sourceLineNo">506</span>          if (result instanceof HFileBlock &amp;&amp; ((HFileBlock) result).usesSharedMemory()) {<a name="line.506"></a>
+<span class="sourceLineNo">507</span>            result = ((HFileBlock) result).deepClone();<a name="line.507"></a>
+<span class="sourceLineNo">508</span>          }<a name="line.508"></a>
+<span class="sourceLineNo">509</span>          cacheBlock(cacheKey, result, /* inMemory = */ false);<a name="line.509"></a>
+<span class="sourceLineNo">510</span>        }<a name="line.510"></a>
+<span class="sourceLineNo">511</span>        return result;<a name="line.511"></a>
+<span class="sourceLineNo">512</span>      }<a name="line.512"></a>
+<span class="sourceLineNo">513</span>      return null;<a name="line.513"></a>
+<span class="sourceLineNo">514</span>    }<a name="line.514"></a>
+<span class="sourceLineNo">515</span>    if (updateCacheMetrics) stats.hit(caching, cacheKey.isPrimary(), cacheKey.getBlockType());<a name="line.515"></a>
+<span class="sourceLineNo">516</span>    cb.access(count.incrementAndGet());<a name="line.516"></a>
+<span class="sourceLineNo">517</span>    return cb.getBuffer();<a name="line.517"></a>
+<span class="sourceLineNo">518</span>  }<a name="line.518"></a>
+<span class="sourceLineNo">519</span><a name="line.519"></a>
+<span class="sourceLineNo">520</span>  /**<a name="line.520"></a>
+<span class="sourceLineNo">521</span>   * Whether the cache contains block with specified cacheKey<a name="line.521"></a>
+<span class="sourceLineNo">522</span>   *<a name="line.522"></a>
+<span class="sourceLineNo">523</span>   * @return true if contains the block<a name="line.523"></a>
+<span class="sourceLineNo">524</span>   */<a name="line.524"></a>
+<span class="sourceLineNo">525</span>  public boolean containsBlock(BlockCacheKey cacheKey) {<a name="line.525"></a>
+<span class="sourceLineNo">526</span>    return map.containsKey(cacheKey);<a name="line.526"></a>
+<span class="sourceLineNo">527</span>  }<a name="line.527"></a>
+<span class="sourceLineNo">528</span><a name="line.528"></a>
+<span class="sourceLineNo">529</span>  @Override<a name="line.529"></a>
+<span class="sourceLineNo">530</span>  public boolean evictBlock(BlockCacheKey cacheKey) {<a name="line.530"></a>
+<span class="sourceLineNo">531</span>    LruCachedBlock cb = map.get(cacheKey);<a name="line.531"></a>
+<span class="sourceLineNo">532</span>    return cb != null &amp;&amp; evictBlock(cb, false) &gt; 0;<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>   * Evicts all blocks for a specific HFile. This is an<a name="line.536"></a>
+<span class="sourceLineNo">537</span>   * expensive operation implemented as a linear-time search through all blocks<a name="line.537"></a>
+<span class="sourceLineNo">538</span>   * in the cache. Ideally this should be a search in a log-access-time map.<a name="line.538"></a>
+<span class="sourceLineNo">539</span>   *<a name="line.539"></a>
+<span class="sourceLineNo">540</span>   * &lt;p&gt;<a name="line.540"></a>
+<span class="sourceLineNo">541</span>   * This is used for evict-on-close to remove all blocks of a specific HFile.<a name="line.541"></a>
+<span class="sourceLineNo">542</span>   *<a name="line.542"></a>
+<span class="sourceLineNo">543</span>   * @return the number of blocks evicted<a name="line.543"></a>
+<span class="sourceLineNo">544</span>   */<a name="line.544"></a>
+<span class="sourceLineNo">545</span>  @Override<a name="line.545"></a>
+<span class="sourceLineNo">546</span>  public int evictBlocksByHfileName(String hfileName) {<a name="line.546"></a>
+<span class="sourceLineNo">547</span>    int numEvicted = 0;<a name="line.547"></a>
+<span class="sourceLineNo">548</span>    for (BlockCacheKey key : map.keySet()) {<a name="line.548"></a>
+<span class="sourceLineNo">549</span>      if (key.getHfileName().equals(hfileName)) {<a name="line.549"></a>
+<span class="sourceLineNo">550</span>        if (evictBlock(key))<a name="line.550"></a>
+<span class="sourceLineNo">551</span>          ++numEvicted;<a name="line.551"></a>
+<span class="sourceLineNo">552</span>      }<a name="line.552"></a>
+<span class="sourceLineNo">553</span>    }<a name="line.553"></a>
+<span class="sourceLineNo">554</span>    if (victimHandler != null) {<a name="line.554"></a>
+<span class="sourceLineNo">555</span>      numEvicted += victimHandler.evictBlocksByHfileName(hfileName);<a name="line.555"></a>
+<span class="sourceLineNo">556</span>    }<a name="line.556"></a>
+<span class="sourceLineNo">557</span>    return numEvicted;<a name="line.557"></a>
+<span class="sourceLineNo">558</span>  }<a name="line.558"></a>
+<span class="sourceLineNo">559</span><a name="line.559"></a>
+<span class="sourceLineNo">560</span>  /**<a name="line.560"></a>
+<span class="sourceLineNo">561</span>   * Evict the block, and it will be cached by the victim handler if exists &amp;amp;&amp;amp;<a name="line.561"></a>
+<span class="sourceLineNo">562</span>   * block may be read again later<a name="line.562"></a>
+<span class="sourceLineNo">563</span>   *<a name="line.563"></a>
+<span class="sourceLineNo">564</span>   * @param evictedByEvictionProcess true if the given block is evicted by<a name="line.564"></a>
+<span class="sourceLineNo">565</span>   *          EvictionThread<a name="line.565"></a>
+<span class="sourceLineNo">566</span>   * @return the heap size of evicted block<a name="line.566"></a>
+<span class="sourceLineNo">567</span>   */<a name="line.567"></a>
+<span class="sourceLineNo">568</span>  protected long evictBlock(LruCachedBlock block, boolean evictedByEvictionProcess) {<a name="line.568"></a>
+<span class="sourceLineNo">569</span>    boolean found = map.remove(block.getCacheKey()) != null;<a name="line.569"></a>
+<span class="sourceLineNo">570</span>    if (!found) {<a name="line.570"></a>
+<span class="sourceLineNo">571</span>      return 0;<a name="line.571"></a>
+<span class="sourceLineNo">572</span>    }<a name="line.572"></a>
+<span class="sourceLineNo">573</span>    updateSizeMetrics(block, true);<a name="line.573"></a>
+<span class="sourceLineNo">574</span>    long val = elements.decrementAndGet();<a name="line.574"></a>
+<span class="sourceLineNo">575</span>    if (LOG.isTraceEnabled()) {<a name="line.575"></a>
+<span class="sourceLineNo">576</span>      long size = map.size();<a name="line.576"></a>
+<span class="sourceLineNo">577</span>      assertCounterSanity(size, val);<a name="line.577"></a>
+<span class="sourceLineNo">578</span>    }<a name="line.578"></a>
+<span class="sourceLineNo">579</span>    if (block.getBuffer().getBlockType().isData()) {<a name="line.579"></a>
+<span class="sourceLineNo">580</span>       dataBlockElements.decrement();<a name="line.580"></a>
+<span class="sourceLineNo">581</span>    }<a name="line.581"></a>
+<span class="sourceLineNo">582</span>    if (evictedByEvictionProcess) {<a name="line.582"></a>
+<span class="sourceLineNo">583</span>      // When the eviction of the block happened because of invalidation of HFiles, no need to<a name="line.583"></a>
+<span class="sourceLineNo">584</span>      // update the stats counter.<a name="line.584"></a>
+<span class="sourceLineNo">585</span>      stats.evicted(block.getCachedTime(), block.getCacheKey().isPrimary());<a name="line.585"></a>
+<span class="sourceLineNo">586</span>      if (victimHandler != null) {<a name="line.586"></a>
+<span class="sourceLineNo">587</span>        victimHandler.cacheBlock(block.getCacheKey(), block.getBuffer());<a name="line.587"></a>
+<span class="sourceLineNo">588</span>      }<a name="line.588"></a>
+<span class="sourceLineNo">589</span>    }<a name="line.589"></a>
+<span class="sourceLineNo">590</span>    return block.heapSize();<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>   * Multi-threaded call to run the eviction process.<a name="line.594"></a>
+<span class="sourceLineNo">595</span>   */<a name="line.595"></a>
+<span class="sourceLineNo">596</span>  private void runEviction() {<a name="line.596"></a>
+<span class="sourceLineNo">597</span>    if (evictionThread == null) {<a name="line.597"></a>
+<span class="sourceLineNo">598</span>      evict();<a name="line.598"></a>
+<span class="sourceLineNo">599</span>    } else {<a name="line.599"></a>
+<span class="sourceLineNo">600</span>      evictionThread.evict();<a name="line.600"></a>
+<span class="sourceLineNo">601</span>    }<a name="line.601"></a>
 <span class="sourceLineNo">602</span>  }<a name="line.602"></a>
 <span class="sourceLineNo">603</span><a name="line.603"></a>
 <span class="sourceLineNo">604</span>  @VisibleForTesting<a name="line.604"></a>
-<span class="sourceLineNo">605</span>  long getOverhead() {<a name="line.605"></a>
-<span class="sourceLineNo">606</span>    return overhead;<a name="line.606"></a>
+<span class="sourceLineNo">605</span>  boolean isEvictionInProgress() {<a name="line.605"></a>
+<span class="sourceLineNo">606</span>    return evictionInProgress;<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>   * Eviction method.<a name="line.610"></a>
-<span class="sourceLineNo">611</span>   */<a name="line.611"></a>
-<span class="sourceLineNo">612</span>  void evict() {<a name="line.612"></a>
+<span class="sourceLineNo">609</span>  @VisibleForTesting<a name="line.609"></a>
+<span class="sourceLineNo">610</span>  long getOverhead() {<a name="line.610"></a>
+<span class="sourceLineNo">611</span>    return overhead;<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>    // Ensure only one eviction at a time<a name="line.614"></a>
-<span class="sourceLineNo">615</span>    if(!evictionLock.tryLock()) return;<a name="line.615"></a>
-<span class="sourceLineNo">616</span><a name="line.616"></a>
-<span class="sourceLineNo">617</span>    try {<a name="line.617"></a>
-<span class="sourceLineNo">618</span>      evictionInProgress = true;<a name="line.618"></a>
-<span class="sourceLineNo">619</span>      long currentSize = this.size.get();<a name="line.619"></a>
-<span class="sourceLineNo">620</span>      long bytesToFree = currentSize - minSize();<a name="line.620"></a>
+<span class="sourceLineNo">614</span>  /**<a name="line.614"></a>
+<span class="sourceLineNo">615</span>   * Eviction method.<a name="line.615"></a>
+<span class="sourceLineNo">616</span>   */<a name="line.616"></a>
+<span class="sourceLineNo">617</span>  void evict() {<a name="line.617"></a>
+<span class="sourceLineNo">618</span><a name="line.618"></a>
+<span class="sourceLineNo">619</span>    // Ensure only one eviction at a time<a name="line.619"></a>
+<span class="sourceLineNo">620</span>    if(!evictionLock.tryLock()) return;<a name="line.620"></a>
 <span class="sourceLineNo">621</span><a name="line.621"></a>
-<span class="sourceLineNo">622</span>      if (LOG.isTraceEnabled()) {<a name="line.622"></a>
-<span class="sourceLineNo">623</span>        LOG.trace("Block cache LRU eviction started; Attempting to free " +<a name="line.623"></a>
-<span class="sourceLineNo">624</span>          StringUtils.byteDesc(bytesToFree) + " of total=" +<a name="line.624"></a>
-<span class="sourceLineNo">625</span>          StringUtils.byteDesc(currentSize));<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>      if (bytesToFree &lt;= 0) return;<a name="line.628"></a>
-<span class="sourceLineNo">629</span><a name="line.629"></a>
-<span class="sourceLineNo">630</span>      // Instantiate priority buckets<a name="line.630"></a>
-<span class="sourceLineNo">631</span>      BlockBucket bucketSingle = new BlockBucket("single", bytesToFree, blockSize, singleSize());<a name="line.631"></a>
-<span class="sourceLineNo">632</span>      BlockBucket bucketMulti = new BlockBucket("multi", bytesToFree, blockSize, multiSize());<a name="line.632"></a>
-<span class="sourceLineNo">633</span>      BlockBucket bucketMemory = new BlockBucket("memory", bytesToFree, blockSize, memorySize());<a name="line.633"></a>
+<span class="sourceLineNo">622</span>    try {<a name="line.622"></a>
+<span class="sourceLineNo">623</span>      evictionInProgress = true;<a name="line.623"></a>
+<span class="sourceLineNo">624</span>      long currentSize = this.size.get();<a name="line.624"></a>
+<span class="sourceLineNo">625</span>      long bytesToFree = currentSize - minSize();<a name="line.625"></a>
+<span class="sourceLineNo">626</span><a name="line.626"></a>
+<span class="sourceLineNo">627</span>      if (LOG.isTraceEnabled()) {<a name="line.627"></a>
+<span class="sourceLineNo">628</span>        LOG.trace("Block cache LRU eviction started; Attempting to free " +<a name="line.628"></a>
+<span class="sourceLineNo">629</span>          StringUtils.byteDesc(bytesToFree) + " of total=" +<a name="line.629"></a>
+<span class="sourceLineNo">630</span>          StringUtils.byteDesc(currentSize));<a name="line.630"></a>
+<span class="sourceLineNo">631</span>      }<a name="line.631"></a>
+<span class="sourceLineNo">632</span><a name="line.632"></a>
+<span class="sourceLineNo">633</span>      if (bytesToFree &lt;= 0) return;<a name="line.633"></a>
 <span class="sourceLineNo">634</span><a name="line.634"></a>
-<span class="sourceLineNo">635</span>      // Scan entire map putting into appropriate buckets<a name="line.635"></a>
-<span class="sourceLineNo">636</span>      for (LruCachedBlock cachedBlock : map.values()) {<a name="line.636"></a>
-<span class="sourceLineNo">637</span>        switch (cachedBlock.getPriority()) {<a name="line.637"></a>
-<span class="sourceLineNo">638</span>          case SINGLE: {<a name="line.638"></a>
-<span class="sourceLineNo">639</span>            bucketSingle.add(cachedBlock);<a name="line.639"></a>
-<span class="sourceLineNo">640</span>            break;<a name="line.640"></a>
-<span class="sourceLineNo">641</span>          }<a name="line.641"></a>
-<span class="sourceLineNo">642</span>          case MULTI: {<a name="line.642"></a>
-<span class="sourceLineNo">643</span>            bucketMulti.add(cachedBlock);<a name="line.643"></a>
-<span class="sourceLineNo">644</span>            break;<a name="line.644"></a>
-<span class="sourceLineNo">645</span>          }<a name="line.645"></a>
-<span class="sourceLineNo">646</span>          case MEMORY: {<a name="line.646"></a>
-<span class="sourceLineNo">647</span>            bucketMemory.add(cachedBlock);<a name="line.647"></a>
-<span class="sourceLineNo">648</span>            break;<a name="line.648"></a>
-<span class="sourceLineNo">649</span>          }<a name="line.649"></a>
-<span class="sourceLineNo">650</span>        }<a name="line.650"></a>
-<span class="sourceLineNo">651</span>      }<a name="line.651"></a>
-<span class="sourceLineNo">652</span><a name="line.652"></a>
-<span class="sourceLineNo">653</span>      long bytesFreed = 0;<a name="line.653"></a>
-<span class="sourceLineNo">654</span>      if (forceInMemory || memoryFactor &gt; 0.999f) {<a name="line.654"></a>
-<span class="sourceLineNo">655</span>        long s = bucketSingle.totalSize();<a name="line.655"></a>
-<span class="sourceLineNo">656</span>        long m = bucketMulti.totalSize();<a name="line.656"></a>
-<span class="sourceLineNo">657</span>        if (bytesToFree &gt; (s + m)) {<a name="line.657"></a>
-<span class="sourceLineNo">658</span>          // this means we need to evict blocks in memory bucket to make room,<a name="line.658"></a>
-<span class="sourceLineNo">659</span>          // so the single and multi buckets will be emptied<a name="line.659"></a>
-<span class="sourceLineNo">660</span>          bytesFreed = bucketSingle.free(s);<a name="line.660"></a>
-<span class="sourceLineNo">661</span>          bytesFreed += bucketMulti.free(m);<a name="line.661"></a>
-<span class="sourceLineNo">662</span>          if (LOG.isTraceEnabled()) {<a name="line.662"></a>
-<span class="sourceLineNo">663</span>            LOG.trace("freed " + StringUtils.byteDesc(bytesFreed) +<a name="line.663"></a>
-<span class="sourceLineNo">664</span>              " from single and multi buckets");<a name="line.664"></a>
-<span class="sourceLineNo">665</span>          }<a name="line.665"></a>
-<span class="sourceLineNo">666</span>          bytesFreed += bucketMemory.free(bytesToFree - bytesFreed);<a name="line.666"></a>
+<span class="sourceLineNo">635</span>      // Instantiate priority buckets<a name="line.635"></a>
+<span class="sourceLineNo">636</span>      BlockBucket bucketSingle = new BlockBucket("single", bytesToFree, blockSize, singleSize());<a name="line.636"></a>
+<span class="sourceLineNo">637</span>      BlockBucket bucketMulti = new BlockBucket("multi", bytesToFree, blockSize, multiSize());<a name="line.637"></a>
+<span class="sourceLineNo">638</span>      BlockBucket bucketMemory = new BlockBucket("memory", bytesToFree, blockSize, memorySize());<a name="line.638"></a>
+<span class="sourceLineNo">639</span><a name="line.639"></a>
+<span class="sourceLineNo">640</span>      // Scan entire map putting into appropriate buckets<a name="line.640"></a>
+<span class="sourceLineNo">641</span>      for (LruCachedBlock cachedBlock : map.values()) {<a name="line.641"></a>
+<span class="sourceLineNo">642</span>        switch (cachedBlock.getPriority()) {<a name="line.642"></a>
+<span class="sourceLineNo">643</span>          case SINGLE: {<a name="line.643"></a>
+<span class="sourceLineNo">644</span>            bucketSingle.add(cachedBlock);<a name="line.644"></a>
+<span class="sourceLineNo">645</span>            break;<a name="line.645"></a>
+<span class="sourceLineNo">646</span>          }<a name="line.646"></a>
+<span class="sourceLineNo">647</span>          case MULTI: {<a name="line.647"></a>
+<span class="sourceLineNo">648</span>            bucketMulti.add(cachedBlock);<a name="line.648"></a>
+<span class="sourceLineNo">649</span>            break;<a name="line.649"></a>
+<span class="sourceLineNo">650</span>          }<a name="line.650"></a>
+<span class="sourceLineNo">651</span>          case MEMORY: {<a name="line.651"></a>
+<span class="sourceLineNo">652</span>            bucketMemory.add(cachedBlock);<a name="line.652"></a>
+<span class="sourceLineNo">653</span>            break;<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>      }<a name="line.656"></a>
+<span class="sourceLineNo">657</span><a name="line.657"></a>
+<span class="sourceLineNo">658</span>      long bytesFreed = 0;<a name="line.658"></a>
+<span class="sourceLineNo">659</span>      if (forceInMemory || memoryFactor &gt; 0.999f) {<a name="line.659"></a>
+<span class="sourceLineNo">660</span>        long s = bucketSingle.totalSize();<a name="line.660"></a>
+<span class="sourceLineNo">661</span>        long m = bucketMulti.totalSize();<a name="line.661"></a>
+<span class="sourceLineNo">662</span>        if (bytesToFree &gt; (s + m)) {<a name="line.662"></a>
+<span class="sourceLineNo">663</span>          // this means we need to evict blocks in memory bucket to make room,<a name="line.663"></a>
+<span class="sourceLineNo">664</span>          // so the single and multi buckets will be emptied<a name="line.664"></a>
+<span class="sourceLineNo">665</span>          bytesFreed = bucketSingle.free(s);<a name="line.665"></a>
+<span class="sourceLineNo">666</span>          bytesFreed += bucketMulti.free(m);<a name="line.666"></a>
 <span class="sourceLineNo">667</span>          if (LOG.isTraceEnabled()) {<a name="line.667"></a>
 <span class="sourceLineNo">668</span>            LOG.trace("freed " + StringUtils.byteDesc(bytesFreed) +<a name="line.668"></a>
-<span class="sourceLineNo">669</span>              " total from all three buckets ");<a name="line.669"></a>
+<span class="sourceLineNo">669</span>              " from single and multi buckets");<a name="line.669"></a>
 <span class="sourceLineNo">670</span>          }<a name="line.670"></a>
-<span class="sourceLineNo">671</span>        } else {<a name="line.671"></a>
-<span class="sourceLineNo">672</span>          // this means no need to evict block in memory bucket,<a name="line.672"></a>
-<span class="sourceLineNo">673</span>          // and we try best to make the ratio between single-bucket and<a name="line.673"></a>
-<span class="sourceLineNo">674</span>          // multi-bucket is 1:2<a name="line.674"></a>
-<span class="sourceLineNo">675</span>          long bytesRemain = s + m - bytesToFree;<a name="line.675"></a>
-<span class="sourceLineNo">676</span>          if (3 * s &lt;= bytesRemain) {<a name="line.676"></a>
-<span class="sourceLineNo">677</span>            // single-bucket is small enough that no eviction happens for it<a name="line.677"></a>
-<span class="sourceLineNo">678</span>            // hence all eviction goes from multi-bucket<a name="line.678"></a>
-<span class="sourceLineNo">679</span>            bytesFreed = bucketMulti.free(bytesToFree);<a name="line.679"></a>
-<span class="sourceLineNo">680</span>          } else if (3 * m &lt;= 2 * bytesRemain) {<a name="line.680"></a>
-<span class="sourceLineNo">681</span>            // multi-bucket is small enough that no eviction happens for it<a name="line.681"></a>
-<span class="sourceLineNo">682</span>            // hence all eviction goes from single-bucket<a name="line.682"></a>
-<span class="sourceLineNo">683</span>            bytesFreed = bucketSingle.free(bytesToFree);<a name="line.683"></a>
-<span class="sourceLineNo">684</span>          } else {<a name="line.684"></a>
-<span class="sourceLineNo">685</span>            // both buckets need to evict some blocks<a name="line.685"></a>
-<span class="sourceLineNo">686</span>            bytesFreed = bucketSingle.free(s - bytesRemain / 3);<a name="line.686"></a>
-<span class="sourceLineNo">687</span>            if (bytesFreed &lt; bytesToFree) {<a name="line.687"></a>
-<span class="sourceLineNo">688</span>              bytesFreed += bucketMulti.free(bytesToFree - bytesFreed);<a name="line.688"></a>
-<span class="sourceLineNo">689</span>            }<a name="line.689"></a>
-<span class="sourceLineNo">690</span>          }<a name="line.690"></a>
-<span class="sourceLineNo">691</span>        }<a name="line.691"></a>
-<span class="sourceLineNo">692</span>      } else {<a name="line.692"></a>
-<span class="sourceLineNo">693</span>        PriorityQueue&lt;BlockBucket&gt; bucketQueue = new PriorityQueue&lt;&gt;(3);<a name="line.693"></a>
-<span class="sourceLineNo">694</span><a name="line.694"></a>
-<span class="sourceLineNo">695</span>        bucketQueue.add(bucketSingle);<a name="line.695"></a>
-<span class="sourceLineNo">696</span>        bucketQueue.add(bucketMulti);<a name="line.696"></a>
-<span class="sourceLineNo">697</span>        bucketQueue.add(bucketMemory);<a name="line.697"></a>
-<span class="sourceLineNo">698</span><a name="line.698"></a>
-<span class="sourceLineNo">699</span>        int remainingBuckets = 3;<a name="line.699"></a>
-<span class="sourceLineNo">700</span><a name="line.700"></a>
-<span class="sourceLineNo">701</span>        BlockBucket bucket;<a name="line.701"></a>
-<span class="sourceLineNo">702</span>        while ((bucket = bucketQueue.poll()) != null) {<a name="line.702"></a>
-<span class="sourceLineNo">703</span>          long overflow = bucket.overflow();<a name="line.703"></a>
-<span class="sourceLineNo">704</span>          if (overflow &gt; 0) {<a name="line.704"></a>
-<span class="sourceLineNo">705</span>            long bucketBytesToFree =<a name="line.705"></a>
-<span class="sourceLineNo">706</span>                Math.min(overflow, (bytesToFree - bytesFreed) / remainingBuckets);<a name="line.706"></a>
-<span class="sourceLineNo">707</span>            bytesFreed += bucket.free(bucketBytesToFree);<a name="line.707"></a>
-<span class="sourceLineNo">708</span>          }<a name="line.708"></a>
-<span class="sourceLineNo">709</span>          remainingBuckets--;<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>      if (LOG.isTraceEnabled()) {<a name="line.712"></a>
-<span class="sourceLineNo">713</span>        long single = bucketSingle.totalSize();<a name="line.713"></a>
-<span class="sourceLineNo">714</span>        long multi = bucketMulti.totalSize();<a name="line.714"></a>
-<span class="sourceLineNo">715</span>        long memory = bucketMemory.totalSize();<a name="line.715"></a>
-<span class="sourceLineNo">716</span>        LOG.trace("Block cache LRU eviction completed; " +<a name="line.716"></a>
-<span class="sourceLineNo">717</span>          "freed=" + StringUtils.byteDesc(bytesFreed) + ", " +<a name="line.717"></a>
-<span class="sourceLineNo">718</span>          "total=" + StringUtils.byteDesc(this.size.get()) + ", " +<a name="line.718"></a>
-<span class="sourceLineNo">719</span>          "single=" + StringUtils.byteDesc(single) + ", " +<a name="line.719"></a>
-<span class="sourceLineNo">720</span>          "multi=" + StringUtils.byteDesc(multi) + ", " +<a name="line.720"></a>
-<span class="sourceLineNo">721</span>          "memory=" + StringUtils.byteDesc(memory));<a name="line.721"></a>
-<span class="sourceLineNo">722</span>      }<a name="line.722"></a>
-<span class="sourceLineNo">723</span>    } finally {<a name="line.723"></a>
-<span class="sourceLineNo">724</span>      stats.evict();<a name="line.724"></a>
-<span class="sourceLineNo">725</span>      evictionInProgress = false;<a name="line.725"></a>
-<span class="sourceLineNo">726</span>      evictionLock.unlock();<a name="line.726"></a>
-<span class="sourceLineNo">727</span>    }<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>  @Override<a name="line.730"></a>
-<span class="sourceLineNo">731</span>  public String toString() {<a name="line.731"></a>
-<span class="sourceLineNo">732</span>    return MoreObjects.toStringHelper(this)<a name="line.732"></a>
-<span class="sourceLineNo">733</span>      .add("blockCount", getBlockCount())<a name="line.733"></a>
-<span class="sourceLineNo">734</span>      .add("currentSize", StringUtils.byteDesc(getCurrentSize()))<a name="line.734"></a>
-<span class="sourceLineNo">735</span>      .add("freeSize", StringUtils.byteDesc(getFreeSize()))<a name="line.735"></a>
-<span class="sourceLineNo">736</span>      .add("maxSize", StringUtils.byteDesc(getMaxSize()))<a name="line.736"></a>
-<span class="sourceLineNo">737</span>      .add("heapSize", StringUtils.byteDesc(heapSize()))<a name="line.737"></a>
-<span class="sourceLineNo">738</span>      .add("minSize", StringUtils.byteDesc(minSize()))<a name="line.738"></a>
-<span class="sourceLineNo">739</span>      .add("minFactor", minFactor)<a name="line.739"></a>
-<span class="sourceLineNo">740</span>      .add("multiSize", StringUtils.byteDesc(multiSize()))<a name="line.740"></a>
-<span class="sourceLineNo">741</span>      .add("multiFactor", multiFactor)<a name="line.741"></a>
-<span class="sourceLineNo">742</span>      .add("singleSize", StringUtils.byteDesc(singleSize()))<a name="line.742"></a>
-<span class="sourceLineNo">743</span>      .add("singleFactor", singleFactor)<a name="line.743"></a>
-<span class="sourceLineNo">744</span>      .toString();<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>  /**<a name="line.747"></a>
-<span class="sourceLineNo">748</span>   * Used to group blocks into priority buckets.  There will be a BlockBucket<a name="line.748"></a>
-<span class="sourceLineNo">749</span>   * for each priority (single, multi, memory).  Once bucketed, the eviction<a name="line.749"></a>
-<span class="sourceLineNo">750</span>   * algorithm takes the appropriate number of elements out of each according<a name="line.750"></a>
-<span class="sourceLineNo">751</span>   * to configuration parameters and their relatives sizes.<a name="line.751"></a>
-<span class="sourceLineNo">752</span>   */<a name="line.752"></a>
-<span class="sourceLineNo">753</span>  private class BlockBucket implements Comparable&lt;BlockBucket&gt; {<a name="line.753"></a>
-<span class="sourceLineNo">754</span><a name="line.754"></a>
-<span class="sourceLineNo">755</span>    private final String name;<a name="line.755"></a>
-<span class="sourceLineNo">756</span>    private LruCachedBlockQueue queue;<a name="line.756"></a>
-<span class="sourceLineNo">757</span>    private long totalSize = 0;<a name="line.757"></a>
-<span class="sourceLineNo">758</span>    private long bucketSize;<a name="line.758"></a>
+<span class="sourceLineNo">671</span>          bytesFreed += bucketMemory.free(bytesToFree - bytesFreed);<a name="line.671"></a>
+<span class="sourceLineNo">672</span>          if (LOG.isTraceEnabled()) {<a name="line.672"></a>
+<span class="sourceLineNo">673</span>            LOG.trace("freed " + StringUtils.byteDesc(bytesFreed) +<a name="line.673"></a>
+<span class="sourceLineNo">674</span>              " total from all three buckets ");<a name="line.674"></a>
+<span class="sourceLineNo">675</span>          }<a name="line.675"></a>
+<span class="sourceLineNo">676</span>        } else {<a name="line.676"></a>
+<span class="sourceLineNo">677</span>          // this means no need to evict block in memory bucket,<a name="line.677"></a>
+<span class="sourceLineNo">678</span>          // and we try best to make the ratio between single-bucket and<a name="line.678"></a>
+<span class="sourceLineNo">679</span>          // multi-bucket is 1:2<a name="line.679"></a>
+<span class="sourceLineNo">680</span>          long bytesRemain = s + m - bytesToFree;<a name="line.680"></a>
+<span class="sourceLineNo">681</span>          if (3 * s &lt;= bytesRemain) {<a name="line.681"></a>
+<span class="sourceLineNo">682</span>            // single-bucket is small enough that no eviction happens for it<a name="line.682"></a>
+<span class="sourceLineNo">683</span>            // hence all eviction goes from multi-bucket<a name="line.683"></a>
+<span class="sourceLineNo">684</span>            bytesFreed = bucketMulti.free(bytesToFree);<a name="line.684"></a>
+<span class="sourceLineNo">685</span>          } else if (3 * m &lt;= 2 * bytesRemain) {<a name="line.685"></a>
+<span class="sourceLineNo">686</span>            // multi-bucket is small enough that no eviction happens for it<a name="line.686"></a>
+<span class="sourceLineNo">687</span>            // hence all eviction goes from single-bucket<a name="line.687"></a>
+<span class="sourceLineNo">688</span>            bytesFreed = bucketSingle.free(bytesToFree);<a name="line.688"></a>
+<span class="sourceLineNo">689</span>          } else {<a name="line.689"></a>
+<span class="sourceLineNo">690</span>            // both buckets need to evict some blocks<a name="line.690"></a>
+<span class="sourceLineNo">691</span>            bytesFreed = bucketSingle.free(s - bytesRemain / 3);<a name="line.691"></a>
+<span class="sourceLineNo">692</span>            if (bytesFreed &lt; bytesToFree) {<a name="line.692"></a>
+<span class="sourceLineNo">693</span>              bytesFreed += bucketMulti.free(bytesToFree - bytesFreed);<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>        }<a name="line.696"></a>
+<span class="sourceLineNo">697</span>      } else {<a name="line.697"></a>
+<span class="sourceLineNo">698</span>        PriorityQueue&lt;BlockBucket&gt; bucketQueue = new PriorityQueue&lt;&gt;(3);<a name="line.698"></a>
+<span class="sourceLineNo">699</span><a name="line.699"></a>
+<span class="sourceLineNo">700</span>        bucketQueue.add(bucketSingle);<a name="line.700"></a>
+<span class="sourceLineNo">701</span>        bucketQueue.add(bucketMulti);<a name="line.701"></a>
+<span class="sourceLineNo">702</span>        bucketQueue.add(bucketMemory);<a name="line.702"></a>
+<span class="sourceLineNo">703</span><a name="line.703"></a>
+<span class="sourceLineNo">704</span>        int remainingBuckets = 3;<a name="line.704"></a>
+<span class="sourceLineNo">705</span><a name="line.705"></a>
+<span class="sourceLineNo">706</span>        BlockBucket bucket;<a name="line.706"></a>
+<span class="sourceLineNo">707</span>        while ((bucket = bucketQueue.poll()) != null) {<a name="line.707"></a>
+<span class="sourceLineNo">708</span>          long overflow = bucket.overflow();<a name="line.708"></a>
+<span class="sourceLineNo">709</span>          if (overflow &gt; 0) {<a name="line.709"></a>
+<span class="sourceLineNo">710</span>            long bucketBytesToFree =<a name="line.710"></a>
+<span class="sourceLineNo">711</span>                Math.min(overflow, (bytesToFree - bytesFreed) / remainingBuckets);<a name="line.711"></a>
+<span class="sourceLineNo">712</span>            bytesFreed += bucket.free(bucketBytesToFree);<a name="line.712"></a>
+<span class="sourceLineNo">713</span>          }<a name="line.713"></a>
+<span class="sourceLineNo">714</span>          remainingBuckets--;<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">717</span>      if (LOG.isTraceEnabled()) {<a name="line.717"></a>
+<span class="sourceLineNo">718</span>        long single = bucketSingle.totalSize();<a name="line.718"></a>
+<span class="sourceLineNo">719</span>        long multi = bucketMulti.totalSize();<a name="line.719"></a>
+<span class="sourceLineNo">720</span>        long memory = bucketMemory.totalSize();<a name="line.720"></a>
+<span class="sourceLineNo">721</span>        LOG.trace("Block cache LRU eviction completed; " +<a name="line.721"></a>
+<span class="sourceLineNo">722</span>          "freed=" + StringUtils.byteDesc(bytesFreed) + ", " +<a name="line.722"></a>
+<span class="sourceLineNo">723</span>          "total=" + StringUtils.byteDesc(this.size.get()) + ", " +<a name="line.723"></a>
+<span class="sourceLineNo">724</span>          "single=" + StringUtils.byteDesc(single) + ", " +<a name="line.724"></a>
+<span class="sourceLineNo">725</span>          "multi=" + StringUtils.byteDesc(multi) + ", " +<a name="line.725"></a>
+<span class="sourceLineNo">726</span>          "memory=" + StringUtils.byteDesc(memory));<a name="line.726"></a>
+<span class="sourceLineNo">727</span>      }<a name="line.727"></a>
+<span class="sourceLineNo">728</span>    } finally {<a name="line.728"></a>
+<span class="sourceLineNo">729</span>      stats.evict();<a name="line.729"></a>
+<span class="sourceLineNo">730</span>      evictionInProgress = false;<a name="line.730"></a>
+<span class="sourceLineNo">731</span>      evictionLock.unlock();<a name="line.731"></a>
+<span class="sourceLineNo">732</span>    }<a name="line.732"></a>
+<span class="sourceLineNo">733</span>  }<a name="line.733"></a>
+<span class="sourceLineNo">734</span><a name="line.734"></a>
+<span class="sourceLineNo">735</span>  @Override<a name="line.735"></a>
+<span class="sourceLineNo">736</span>  public String toString() {<a name="line.736"></a>
+<span class="sourceLineNo">737</span>    return MoreObjects.toStringHelper(this)<a name="line.737"></a>
+<span class="sourceLineNo">738</span>      .add("blockCount", getBlockCount())<a name="line.738"></a>
+<span class="sourceLineNo">739</span>      .add("currentSize", StringUtils.byteDesc(getCurrentSize()))<a name="line.739"></a>
+<span class="sourceLineNo">740</span>      .add("freeSize", StringUtils.byteDesc(getFreeSize()))<a name="line.740"></a>
+<span class="sourceLineNo">741</span>      .add("maxSize", StringUtils.byteDesc(getMaxSize()))<a name="line.741"></a>
+<span class="sourceLineNo">742</span>      .add("heapSize", StringUtils.byteDesc(heapSize()))<a name="line.742"></a>
+<span class="sourceLineNo">743</span>      .add("minSize", StringUtils.byteDesc(minSize()))<a name="line.743"></a>
+<span class="sourceLineNo">744</span>      .add("minFactor", minFactor)<a name="line.744"></a>
+<span class="sourceLineNo">745</span>      .add("multiSize", StringUtils.byteDesc(multiSize()))<a name="line.745"></a>
+<span class="sourceLineNo">746</span>      .add("multiFactor", multiFactor)<a name="line.746"></a>
+<span class="sourceLineNo">747</span>      .add("singleSize", StringUtils.byteDesc(singleSize()))<a name="line.747"></a>
+<span class="sourceLineNo">748</span>      .add("singleFactor", singleFactor)<a name="line.748"></a>
+<span class="sourceLineNo">749</span>      .toString();<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>   * Used to group blocks into priority buckets.  There will be a BlockBucket<a name="line.753"></a>
+<span class="sourceLineNo">754</span>   * for each priority (single, multi, memory).  Once bucketed, the eviction<a name="line.754"></a>
+<span class="sourceLineNo">755</span>   * algorithm takes the appropriate number of elements out of each according<a name="line.755"></a>
+<span class="sourceLineNo">756</span>   * to configuration parameters and their relatives sizes.<a name="line.756"></a>
+<span class="sourceLineNo">757</span>   */<a name="line.757"></a>
+<span class="sourceLineNo">758</span>  private class BlockBucket implements Comparable&lt;BlockBucket&gt; {<a name="line.758"></a>
 <span class="sourceLineNo">759</span><a name="line.759"></a>
-<span class="sourceLineNo">760</span>    public BlockBucket(String name, long bytesToFree, long blockSize, long bucketSize) {<a name="line.760"></a>
-<span class="sourceLineNo">761</span>      this.name = name;<a name="line.761"></a>
-<span class="sourceLineNo">762</span>      this.bucketSize = bucketSize;<a name="line.762"></a>
-<span class="sourceLineNo">763</span>      queue = new LruCachedBlockQueue(bytesToFree, blockSize);<a name="line.763"></a>
-<span class="sourceLineNo">764</span>      totalSize = 0;<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>    public void add(LruCachedBlock block) {<a name="line.767"></a>
-<span class="sourceLineNo">768</span>      totalSize += block.heapSize();<a name="line.768"></a>
-<span class="sourceLineNo">769</span>      queue.add(block);<a name="line.769"></a>
+<span class="sourceLineNo">760</span>    private final String name;<a name="line.760"></a>
+<span class="sourceLineNo">761</span>    private LruCachedBlockQueue queue;<a name="line.761"></a>
+<span class="sourceLineNo">762</span>    private long totalSize = 0;<a name="line.762"></a>
+<span class="sourceLineNo">763</span>    private long bucketSize;<a name="line.763"></a>
+<span class="sourceLineNo">764</span><a name="line.764"></a>
+<span class="sourceLineNo">765</span>    public BlockBucket(String name, long bytesToFree, long blockSize, long bucketSize) {<a name="line.765"></a>
+<span class="sourceLineNo">766</span>      this.name = name;<a name="line.766"></a>
+<span class="sourceLineNo">767</span>      this.bucketSize = bucketSize;<a name="line.767"></a>
+<span class="sourceLineNo">768</span>      queue = new LruCachedBlockQueue(bytesToFree, blockSize);<a name="line.768"></a>
+<span class="sourceLineNo">769</span>      totalSize = 0;<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>    public long free(long toFree) {<a name="line.772"></a>
-<span class="sourceLineNo">773</span>      if (LOG.isTraceEnabled()) {<a name="line.773"></a>
-<span class="sourceLineNo">774</span>        LOG.trace("freeing " + StringUtils.byteDesc(toFree) + " from " + this);<a name="line.774"></a>
-<span class="sourceLineNo">775</span>      }<a name="line.775"></a>
-<span class="sourceLineNo">776</span>      LruCachedBlock cb;<a name="line.776"></a>
-<span class="sourceLineNo">777</span>      long freedBytes = 0;<a name="line.777"></a>
-<span class="sourceLineNo">778</span>      while ((cb = queue.pollLast()) != null) {<a name="line.778"></a>
-<span class="sourceLineNo">779</span>        freedBytes += evictBlock(cb, true);<a name="line.779"></a>
-<span class="sourceLineNo">780</span>        if (freedBytes &gt;= toFree) {<a name="line.780"></a>
-<span class="sourceLineNo">781</span>          return freedBytes;<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>      if (LOG.isTraceEnabled()) {<a name="line.784"></a>
-<span class="sourceLineNo">785</span>        LOG.trace("freed " + StringUtils.byteDesc(freedBytes) + " from " + this);<a name="line.785"></a>
-<span class="sourceLineNo">786</span>      }<a name="line.786"></a>
-<span class="sourceLineNo">787</span>      return freedBytes;<a name="line.787"></a>
-<span class="sourceLineNo">788</span>    }<a name="line.788"></a>
-<span class="sourceLineNo">789</span><a name="line.789"></a>
-<span class="sourceLineNo">790</span>    public long overflow() {<a name="line.790"></a>
-<span class="sourceLineNo">791</span>      return totalSize - bucketSize;<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>
-<span class="sourceLineNo">794</span>    public long totalSize() {<a name="line.794"></a>
-<span class="sourceLineNo">795</span>      return totalSize;<a name="line.795"></a>
-<span class="sourceLineNo">796</span>    }<a name="line.796"></a>
-<span class="sourceLineNo">797</span><a name="line.797"></a>
-<span class="sourceLineNo">798</span>    @Override<a name="line.798"></a>
-<span class="sourceLineNo">799</span>    public int compareTo(BlockBucket that) {<a name="line.799"></a>
-<span class="sourceLineNo">800</span>      return Long.compare(this.overflow(), that.overflow());<a name="line.800"></a>
+<span class="sourceLineNo">772</span>    public void add(LruCachedBlock block) {<a name="line.772"></a>
+<span class="sourceLineNo">773</span>      totalSize += block.heapSize();<a name="line.773"></a>
+<span class="sourceLineNo">774</span>      queue.add(block);<a name="line.774"></a>
+<span class="sourceLineNo">775</span>    }<a name="line.775"></a>
+<span class="sourceLineNo">776</span><a name="line.776"></a>
+<span class="sourceLineNo">777</span>    public long free(long toFree) {<a name="line.777"></a>
+<span class="sourceLineNo">778</span>      if (LOG.isTraceEnabled()) {<a name="line.778"></a>
+<span class="sourceLineNo">779</span>        LOG.trace("freeing " + StringUtils.byteDesc(toFree) + " from " + this);<a name="line.779"></a>
+<span class="sourceLineNo">780</span>      }<a name="line.780"></a>
+<span class="sourceLineNo">781</span>      LruCachedBlock cb;<a name="line.781"></a>
+<span class="sourceLineNo">782</span>      long freedBytes = 0;<a name="line.782"></a>
+<span class="sourceLineNo">783</span>      while ((cb = queue.pollLast()) != null) {<a name="line.783"></a>
+<span class="sourceLineNo">784</span>        freedBytes += evictBlock(cb, true);<a name="line.784"></a>
+<span class="sourceLineNo">785</span>        if (freedBytes &gt;= toFree) {<a name="line.785"></a>
+<span class="sourceLineNo">786</span>          return freedBytes;<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>      if (LOG.isTraceEnabled()) {<a name="line.789"></a>
+<span class="sourceLineNo">790</span>        LOG.trace("freed " + StringUtils.byteDesc(freedBytes) + " from " + this);<a name="line.790"></a>
+<span class="sourceLineNo">791</span>      }<a name="line.791"></a>
+<span class="sourceLineNo">792</span>      return freedBytes;<a name="line.792"></a>
+<span class="sourceLineNo">793</span>    }<a name="line.793"></a>
+<span class="sourceLineNo">794</span><a name="line.794"></a>
+<span class="sourceLineNo">795</span>    public long overflow() {<a name="line.795"></a>
+<span class="sourceLineNo">796</span>      return totalSize - bucketSize;<a name="line.796"></a>
+<span class="sourceLineNo">797</span>    }<a name="line.797"></a>
+<span class="sourceLineNo">798</span><a name="line.798"></a>
+<span class="sourceLineNo">799</span>    public long totalSize() {<a name="line.799"></a>
+<span class="sourceLineNo">800</span>      return totalSize;<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>    @Override<a name="line.803"></a>
-<span class="sourceLineNo">804</span>    public boolean equals(Object that) {<a name="line.804"></a>
-<span class="sourceLineNo">805</span>      if (that == null || !(that instanceof BlockBucket)) {<a name="line.805"></a>
-<span class="sourceLineNo">806</span>        return false;<a name="line.806"></a>
-<span class="sourceLineNo">807</span>      }<a name="line.807"></a>
-<span class="sourceLineNo">808</span>      return compareTo((BlockBucket)that) == 0;<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>    @Override<a name="line.811"></a>
-<span class="sourceLineNo">812</span>    public int hashCode() {<a name="line.812"></a>
-<span class="sourceLineNo">813</span>      return Objects.hashCode(name, bucketSize, queue, totalSize);<a name="line.813"></a>
+<span class="sourceLineNo">804</span>    public int compareTo(BlockBucket that) {<a name="line.804"></a>
+<span class="sourceLineNo">805</span>      return Long.compare(this.overflow(), that.overflow());<a name="line.805"></a>
+<span class="sourceLineNo">806</span>    }<a name="line.806"></a>
+<span class="sourceLineNo">807</span><a name="line.807"></a>
+<span class="sourceLineNo">808</span>    @Override<a name="line.808"></a>
+<span class="sourceLineNo">809</span>    public boolean equals(Object that) {<a name="line.809"></a>
+<span class="sourceLineNo">810</span>      if (that == null || !(that instanceof BlockBucket)) {<a name="line.810"></a>
+<span class="sourceLineNo">811</span>        return false;<a name="line.811"></a>
+<span class="sourceLineNo">812</span>      }<a name="line.812"></a>
+<span class="sourceLineNo">813</span>      return compareTo((BlockBucket)that) == 0;<a name="line.813"></a>
 <span class="sourceLineNo">814</span>    }<a name="line.814"></a>
 <span class="sourceLineNo">815</span><a name="line.815"></a>
 <span class="sourceLineNo">816</span>    @Override<a name="line.816"></a>
-<span class="sourceLineNo">817</span>    public String toString() {<a name="line.817"></a>
-<span class="sourceLineNo">818</span>      return MoreObjects.toStringHelper(this)<a name="line.818"></a>
-<span class="sourceLineNo">819</span>        .add("name", name)<a name="line.819"></a>
-<span class="sourceLineNo">820</span>        .add("totalSize", StringUtils.byteDesc(totalSize))<a name="line.820"></a>
-<span class="sourceLineNo">821</span>        .add("bucketSize", StringUtils.byteDesc(bucketSize))<a name="line.821"></a>
-<span class="sourceLineNo">822</span>        .toString();<a name="line.822"></a>
-<span class="sourceLineNo">823</span>    }<a name="line.823"></a>
-<span class="sourceLineNo">824</span>  }<a name="line.824"></a>
-<span class="sourceLineNo">825</span><a name="line.825"></a>
-<span class="sourceLineNo">826</span>  /**<a name="line.826"></a>
-<span class="sourceLineNo">827</span>   * Get the maximum size of this cache.<a name="line.827"></a>
-<span class="sourceLineNo">828</span>   *<a name="line.828"></a>
-<span class="sourceLineNo">829</span>   * @return max size in bytes<a name="line.829"></a>
-<span class="sourceLineNo">830</span>   */<a name="line.830"></a>
-<span class="sourceLineNo">831</span><a name="line.831"></a>
-<span class="sourceLineNo">832</span>  @Override<a name="line.832"></a>
-<span class="sourceLineNo">833</span>  public long getMaxSize() {<a name="line.833"></a>
-<span class="sourceLineNo">834</span>    return this.maxSize;<a name="line.834"></a>
-<span class="sourceLineNo">835</span>  }<a name="line.835"></a>
+<span class="sourceLineNo">817</span>    public int hashCode() {<a name="line.817"></a>
+<span class="sourceLineNo">818</span>      return Objects.hashCode(name, bucketSize, queue, totalSize);<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>    @Override<a name="line.821"></a>
+<span class="sourceLineNo">822</span>    public String toString() {<a name="line.822"></a>
+<span class="sourceLineNo">823</span>      return MoreObjects.toStringHelper(this)<a name="line.823"></a>
+<span class="sourceLineNo">824</span>        .add("name", name)<a name="line.824"></a>
+<span class="sourceLineNo">825</span>        .add("totalSize", StringUtils.byteDesc(totalSize))<a name="line.825"></a>
+<span class="sourceLineNo">826</span>        .add("bucketSize", StringUtils.byteDesc(bucketSize))<a name="line.826"></a>
+<span class="sourceLineNo">827</span>        .toString();<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">830</span><a name="line.830"></a>
+<span class="sourceLineNo">831</span>  /**<a name="line.831"></a>
+<span class="sourceLineNo">832</span>   * Get the maximum size of this cache.<a name="line.832"></a>
+<span class="sourceLineNo">833</span>   *<a name="line.833"></a>
+<span class="sourceLineNo">834</span>   * @return max size in bytes<a name="line.834"></a>
+<span class="sourceLineNo">835</span>   */<a name="line.835"></a>
 <span class="sourceLineNo">836</span><a name="line.836"></a>
 <span class="sourceLineNo">837</span>  @Override<a name="line.837"></a>
-<span class="sourceLineNo">838</span>  public long getCurrentSize() {<a name="line.838"></a>
-<span class="sourceLineNo">839</span>    return this.size.get();<a name="line.839"></a>
+<span class="sourceLineNo">838</span>  public long getMaxSize() {<a name="line.838"></a>
+<span class="sourceLineNo">839</span>    return this.maxSize;<a name="line.839"></a>
 <span class="sourceLineNo">840</span>  }<a name="line.840"></a>
 <span class="sourceLineNo">841</span><a name="line.841"></a>
 <span class="sourceLineNo">842</span>  @Override<a name="line.842"></a>
-<span class="sourceLineNo">843</span>  public long getCurrentDataSize() {<a name="line.843"></a>
-<span class="sourceLineNo">844</span>    return this.dataBlockSize.sum();<a name="line.844"></a>
+<span class="sourceLineNo">843</span>  public long getCurrentSize() {<a name="line.843"></a>
+<span class="sourceLineNo">844</span>    return this.size.get();<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>  @Override<a name="line.847"></a>
-<span class="sourceLineNo">848</span>  public long getFreeSize() {<a name="line.848"></a>
-<span class="sourceLineNo">849</span>    return getMaxSize() - getCurrentSize();<a name="line.849"></a>
+<span class="sourceLineNo">848</span>  public long getCurrentDataSize() {<a name="line.848"></a>
+<span class="sourceLineNo">849</span>    return this.dataBlockSize.sum();<a name="line.849"></a>
 <span class="sourceLineNo">850</span>  }<a name="line.850"></a>
 <span class="sourceLineNo">851</span><a name="line.851"></a>
 <span class="sourceLineNo">852</span>  @Override<a name="line.852"></a>
-<span class="sourceLineNo">853</span>  public long size() {<a name="line.853"></a>
-<span class="sourceLineNo">854</span>    return getMaxSize();<a name="line.854"></a>
+<span class="sourceLineNo">853</span>  public long getFreeSize() {<a name="line.853"></a>
+<span class="sourceLineNo">854</span>    return getMaxSize() - getCurrentSize();<a name="line.854"></a>
 <span class="sourceLineNo">855</span>  }<a name="line.855"></a>
 <span class="sourceLineNo">856</span><a name="line.856"></a>
 <span class="sourceLineNo">857</span>  @Override<a name="line.857"></a>
-<span class="sourceLineNo">858</span>  public long getBlockCount() {<a name="line.858"></a>
-<span class="sourceLineNo">859</span>    return this.elements.get();<a name="line.859"></a>
+<span class="sourceLineNo">858</span>  public long size() {<a name="line.858"></a>
+<span class="sourceLineNo">859</span>    return getMaxSize();<a name="line.859"></a>
 <span class="sourceLineNo">860</span>  }<a name="line.860"></a>
 <span class="sourceLineNo">861</span><a name="line.861"></a>
 <span class="sourceLineNo">862</span>  @Override<a name="line.862"></a>
-<span class="sourceLineNo">863</span>  public long getDataBlockCount() {<a name="line.863"></a>
-<span class="sourceLineNo">864</span>    return this.dataBlockElements.sum();<a name="line.864"></a>
+<span class="sourceLineNo">863</span>  public long getBlockCount() {<a name="line.863"></a>
+<span class="sourceLineNo">864</span>    return this.elements.get();<a name="line.864"></a>
 <span class="sourceLineNo">865</span>  }<a name="line.865"></a>
 <span class="sourceLineNo">866</span><a name="line.866"></a>
-<span class="sourceLineNo">867</span>  EvictionThread getEvictionThread() {<a name="line.867"></a>
-<span class="sourceLineNo">868</span>    return this.evictionThread;<a name="line.868"></a>
-<span class="sourceLineNo">869</span>  }<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>   * Eviction thread.  Sits in waiting state until an eviction is triggered<a name="line.872"></a>
-<span class="sourceLineNo">873</span>   * when the cache size grows above the acceptable level.&lt;p&gt;<a name="line.873"></a>
-<span class="sourceLineNo">874</span>

<TRUNCATED>

[06/50] hbase-site git commit: Published site at 26babcf013de696b899d76a3c39434b794440d8d.

Posted by gi...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.CachedItem.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.CachedItem.html b/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.CachedItem.html
index 1774db3..2ab8397 100644
--- a/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.CachedItem.html
+++ b/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.CachedItem.html
@@ -39,879 +39,933 @@
 <span class="sourceLineNo">031</span>import org.apache.hadoop.conf.Configuration;<a name="line.31"></a>
 <span class="sourceLineNo">032</span>import org.apache.hadoop.hbase.HBaseClassTestRule;<a name="line.32"></a>
 <span class="sourceLineNo">033</span>import org.apache.hadoop.hbase.HBaseConfiguration;<a name="line.33"></a>
-<span class="sourceLineNo">034</span>import org.apache.hadoop.hbase.Waiter;<a name="line.34"></a>
-<span class="sourceLineNo">035</span>import org.apache.hadoop.hbase.Waiter.ExplainingPredicate;<a name="line.35"></a>
-<span class="sourceLineNo">036</span>import org.apache.hadoop.hbase.io.HeapSize;<a name="line.36"></a>
-<span class="sourceLineNo">037</span>import org.apache.hadoop.hbase.io.hfile.LruBlockCache.EvictionThread;<a name="line.37"></a>
-<span class="sourceLineNo">038</span>import org.apache.hadoop.hbase.testclassification.IOTests;<a name="line.38"></a>
-<span class="sourceLineNo">039</span>import org.apache.hadoop.hbase.testclassification.SmallTests;<a name="line.39"></a>
-<span class="sourceLineNo">040</span>import org.apache.hadoop.hbase.util.ClassSize;<a name="line.40"></a>
-<span class="sourceLineNo">041</span>import org.junit.ClassRule;<a name="line.41"></a>
-<span class="sourceLineNo">042</span>import org.junit.Test;<a name="line.42"></a>
-<span class="sourceLineNo">043</span>import org.junit.experimental.categories.Category;<a name="line.43"></a>
-<span class="sourceLineNo">044</span><a name="line.44"></a>
-<span class="sourceLineNo">045</span>/**<a name="line.45"></a>
-<span class="sourceLineNo">046</span> * Tests the concurrent LruBlockCache.&lt;p&gt;<a name="line.46"></a>
-<span class="sourceLineNo">047</span> *<a name="line.47"></a>
-<span class="sourceLineNo">048</span> * Tests will ensure it grows and shrinks in size properly,<a name="line.48"></a>
-<span class="sourceLineNo">049</span> * evictions run when they're supposed to and do what they should,<a name="line.49"></a>
-<span class="sourceLineNo">050</span> * and that cached blocks are accessible when expected to be.<a name="line.50"></a>
-<span class="sourceLineNo">051</span> */<a name="line.51"></a>
-<span class="sourceLineNo">052</span>@Category({IOTests.class, SmallTests.class})<a name="line.52"></a>
-<span class="sourceLineNo">053</span>public class TestLruBlockCache {<a name="line.53"></a>
-<span class="sourceLineNo">054</span><a name="line.54"></a>
-<span class="sourceLineNo">055</span>  @ClassRule<a name="line.55"></a>
-<span class="sourceLineNo">056</span>  public static final HBaseClassTestRule CLASS_RULE =<a name="line.56"></a>
-<span class="sourceLineNo">057</span>      HBaseClassTestRule.forClass(TestLruBlockCache.class);<a name="line.57"></a>
-<span class="sourceLineNo">058</span><a name="line.58"></a>
-<span class="sourceLineNo">059</span>  @Test<a name="line.59"></a>
-<span class="sourceLineNo">060</span>  public void testCacheEvictionThreadSafe() throws Exception {<a name="line.60"></a>
-<span class="sourceLineNo">061</span>    long maxSize = 100000;<a name="line.61"></a>
-<span class="sourceLineNo">062</span>    int numBlocks = 9;<a name="line.62"></a>
-<span class="sourceLineNo">063</span>    int testRuns = 10;<a name="line.63"></a>
-<span class="sourceLineNo">064</span>    final long blockSize = calculateBlockSizeDefault(maxSize, numBlocks);<a name="line.64"></a>
-<span class="sourceLineNo">065</span>    assertTrue("calculateBlockSize appears broken.", blockSize * numBlocks &lt;= maxSize);<a name="line.65"></a>
-<span class="sourceLineNo">066</span><a name="line.66"></a>
-<span class="sourceLineNo">067</span>    final Configuration conf = HBaseConfiguration.create();<a name="line.67"></a>
-<span class="sourceLineNo">068</span>    final LruBlockCache cache = new LruBlockCache(maxSize, blockSize);<a name="line.68"></a>
-<span class="sourceLineNo">069</span>    EvictionThread evictionThread = cache.getEvictionThread();<a name="line.69"></a>
-<span class="sourceLineNo">070</span>    assertTrue(evictionThread != null);<a name="line.70"></a>
-<span class="sourceLineNo">071</span>    while (!evictionThread.isEnteringRun()) {<a name="line.71"></a>
-<span class="sourceLineNo">072</span>      Thread.sleep(1);<a name="line.72"></a>
-<span class="sourceLineNo">073</span>    }<a name="line.73"></a>
-<span class="sourceLineNo">074</span>    final String hfileName = "hfile";<a name="line.74"></a>
-<span class="sourceLineNo">075</span>    int threads = 10;<a name="line.75"></a>
-<span class="sourceLineNo">076</span>    final int blocksPerThread = 5 * numBlocks;<a name="line.76"></a>
-<span class="sourceLineNo">077</span>    for (int run = 0; run != testRuns; ++run) {<a name="line.77"></a>
-<span class="sourceLineNo">078</span>      final AtomicInteger blockCount = new AtomicInteger(0);<a name="line.78"></a>
-<span class="sourceLineNo">079</span>      ExecutorService service = Executors.newFixedThreadPool(threads);<a name="line.79"></a>
-<span class="sourceLineNo">080</span>      for (int i = 0; i != threads; ++i) {<a name="line.80"></a>
-<span class="sourceLineNo">081</span>        service.execute(new Runnable() {<a name="line.81"></a>
-<span class="sourceLineNo">082</span>          @Override<a name="line.82"></a>
-<span class="sourceLineNo">083</span>          public void run() {<a name="line.83"></a>
-<span class="sourceLineNo">084</span>            for (int blockIndex = 0; blockIndex &lt; blocksPerThread || (!cache.isEvictionInProgress()); ++blockIndex) {<a name="line.84"></a>
-<span class="sourceLineNo">085</span>              CachedItem block = new CachedItem(hfileName, (int) blockSize, blockCount.getAndIncrement());<a name="line.85"></a>
-<span class="sourceLineNo">086</span>              boolean inMemory = Math.random() &gt; 0.5;<a name="line.86"></a>
-<span class="sourceLineNo">087</span>              cache.cacheBlock(block.cacheKey, block, inMemory);<a name="line.87"></a>
-<span class="sourceLineNo">088</span>            }<a name="line.88"></a>
-<span class="sourceLineNo">089</span>            cache.evictBlocksByHfileName(hfileName);<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>      }<a name="line.92"></a>
-<span class="sourceLineNo">093</span>      service.shutdown();<a name="line.93"></a>
-<span class="sourceLineNo">094</span>      // The test may fail here if the evict thread frees the blocks too fast<a name="line.94"></a>
-<span class="sourceLineNo">095</span>      service.awaitTermination(10, TimeUnit.MINUTES);<a name="line.95"></a>
-<span class="sourceLineNo">096</span>      Waiter.waitFor(conf, 10000, 100, new ExplainingPredicate&lt;Exception&gt;() {<a name="line.96"></a>
-<span class="sourceLineNo">097</span>        @Override<a name="line.97"></a>
-<span class="sourceLineNo">098</span>        public boolean evaluate() throws Exception {<a name="line.98"></a>
-<span class="sourceLineNo">099</span>          return cache.getBlockCount() == 0;<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>        @Override<a name="line.102"></a>
-<span class="sourceLineNo">103</span>        public String explainFailure() throws Exception {<a name="line.103"></a>
-<span class="sourceLineNo">104</span>          return "Cache block count failed to return to 0";<a name="line.104"></a>
-<span class="sourceLineNo">105</span>        }<a name="line.105"></a>
-<span class="sourceLineNo">106</span>      });<a name="line.106"></a>
-<span class="sourceLineNo">107</span>      assertEquals(0, cache.getBlockCount());<a name="line.107"></a>
-<span class="sourceLineNo">108</span>      assertEquals(cache.getOverhead(), cache.getCurrentSize());<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>  @Test<a name="line.111"></a>
-<span class="sourceLineNo">112</span>  public void testBackgroundEvictionThread() throws Exception {<a name="line.112"></a>
-<span class="sourceLineNo">113</span>    long maxSize = 100000;<a name="line.113"></a>
-<span class="sourceLineNo">114</span>    int numBlocks = 9;<a name="line.114"></a>
-<span class="sourceLineNo">115</span>    long blockSize = calculateBlockSizeDefault(maxSize, numBlocks);<a name="line.115"></a>
-<span class="sourceLineNo">116</span>    assertTrue("calculateBlockSize appears broken.", blockSize * numBlocks &lt;= maxSize);<a name="line.116"></a>
-<span class="sourceLineNo">117</span><a name="line.117"></a>
-<span class="sourceLineNo">118</span>    LruBlockCache cache = new LruBlockCache(maxSize,blockSize);<a name="line.118"></a>
-<span class="sourceLineNo">119</span>    EvictionThread evictionThread = cache.getEvictionThread();<a name="line.119"></a>
-<span class="sourceLineNo">120</span>    assertTrue(evictionThread != null);<a name="line.120"></a>
-<span class="sourceLineNo">121</span><a name="line.121"></a>
-<span class="sourceLineNo">122</span>    CachedItem[] blocks = generateFixedBlocks(numBlocks + 1, blockSize, "block");<a name="line.122"></a>
-<span class="sourceLineNo">123</span><a name="line.123"></a>
-<span class="sourceLineNo">124</span>    // Make sure eviction thread has entered run method<a name="line.124"></a>
-<span class="sourceLineNo">125</span>    while (!evictionThread.isEnteringRun()) {<a name="line.125"></a>
-<span class="sourceLineNo">126</span>      Thread.sleep(1);<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>    // Add all the blocks<a name="line.129"></a>
-<span class="sourceLineNo">130</span>    for (CachedItem block : blocks) {<a name="line.130"></a>
-<span class="sourceLineNo">131</span>      cache.cacheBlock(block.cacheKey, block);<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>    // wait until at least one eviction has run<a name="line.134"></a>
-<span class="sourceLineNo">135</span>    int n = 0;<a name="line.135"></a>
-<span class="sourceLineNo">136</span>    while(cache.getStats().getEvictionCount() == 0) {<a name="line.136"></a>
-<span class="sourceLineNo">137</span>      Thread.sleep(200);<a name="line.137"></a>
-<span class="sourceLineNo">138</span>      assertTrue("Eviction never happened.", n++ &lt; 20);<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>    // let cache stabilize<a name="line.141"></a>
-<span class="sourceLineNo">142</span>    // On some systems, the cache will run multiple evictions before it attains<a name="line.142"></a>
-<span class="sourceLineNo">143</span>    // steady-state. For instance, after populating the cache with 10 blocks,<a name="line.143"></a>
-<span class="sourceLineNo">144</span>    // the first eviction evicts a single block and then a second eviction<a name="line.144"></a>
-<span class="sourceLineNo">145</span>    // evicts another. I think this is due to the delta between minSize and<a name="line.145"></a>
-<span class="sourceLineNo">146</span>    // acceptableSize, combined with variance between object overhead on<a name="line.146"></a>
-<span class="sourceLineNo">147</span>    // different environments.<a name="line.147"></a>
-<span class="sourceLineNo">148</span>    n = 0;<a name="line.148"></a>
-<span class="sourceLineNo">149</span>    for (long prevCnt = 0 /* &lt; number of blocks added */,<a name="line.149"></a>
-<span class="sourceLineNo">150</span>              curCnt = cache.getBlockCount();<a name="line.150"></a>
-<span class="sourceLineNo">151</span>        prevCnt != curCnt; prevCnt = curCnt, curCnt = cache.getBlockCount()) {<a name="line.151"></a>
-<span class="sourceLineNo">152</span>      Thread.sleep(200);<a name="line.152"></a>
-<span class="sourceLineNo">153</span>      assertTrue("Cache never stabilized.", n++ &lt; 20);<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>    long evictionCount = cache.getStats().getEvictionCount();<a name="line.156"></a>
-<span class="sourceLineNo">157</span>    assertTrue(evictionCount &gt;= 1);<a name="line.157"></a>
-<span class="sourceLineNo">158</span>    System.out.println("Background Evictions run: " + evictionCount);<a name="line.158"></a>
-<span class="sourceLineNo">159</span>  }<a name="line.159"></a>
-<span class="sourceLineNo">160</span><a name="line.160"></a>
-<span class="sourceLineNo">161</span>  @Test<a name="line.161"></a>
-<span class="sourceLineNo">162</span>  public void testCacheSimple() throws Exception {<a name="line.162"></a>
-<span class="sourceLineNo">163</span><a name="line.163"></a>
-<span class="sourceLineNo">164</span>    long maxSize = 1000000;<a name="line.164"></a>
-<span class="sourceLineNo">165</span>    long blockSize = calculateBlockSizeDefault(maxSize, 101);<a name="line.165"></a>
-<span class="sourceLineNo">166</span><a name="line.166"></a>
-<span class="sourceLineNo">167</span>    LruBlockCache cache = new LruBlockCache(maxSize, blockSize);<a name="line.167"></a>
-<span class="sourceLineNo">168</span><a name="line.168"></a>
-<span class="sourceLineNo">169</span>    CachedItem [] blocks = generateRandomBlocks(100, blockSize);<a name="line.169"></a>
-<span class="sourceLineNo">170</span><a name="line.170"></a>
-<span class="sourceLineNo">171</span>    long expectedCacheSize = cache.heapSize();<a name="line.171"></a>
-<span class="sourceLineNo">172</span><a name="line.172"></a>
-<span class="sourceLineNo">173</span>    // Confirm empty<a name="line.173"></a>
-<span class="sourceLineNo">174</span>    for (CachedItem block : blocks) {<a name="line.174"></a>
-<span class="sourceLineNo">175</span>      assertTrue(cache.getBlock(block.cacheKey, true, false, true) == null);<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>    // Add blocks<a name="line.178"></a>
-<span class="sourceLineNo">179</span>    for (CachedItem block : blocks) {<a name="line.179"></a>
-<span class="sourceLineNo">180</span>      cache.cacheBlock(block.cacheKey, block);<a name="line.180"></a>
-<span class="sourceLineNo">181</span>      expectedCacheSize += block.cacheBlockHeapSize();<a name="line.181"></a>
-<span class="sourceLineNo">182</span>    }<a name="line.182"></a>
-<span class="sourceLineNo">183</span><a name="line.183"></a>
-<span class="sourceLineNo">184</span>    // Verify correctly calculated cache heap size<a name="line.184"></a>
-<span class="sourceLineNo">185</span>    assertEquals(expectedCacheSize, cache.heapSize());<a name="line.185"></a>
-<span class="sourceLineNo">186</span><a name="line.186"></a>
-<span class="sourceLineNo">187</span>    // Check if all blocks are properly cached and retrieved<a name="line.187"></a>
-<span class="sourceLineNo">188</span>    for (CachedItem block : blocks) {<a name="line.188"></a>
-<span class="sourceLineNo">189</span>      HeapSize buf = cache.getBlock(block.cacheKey, true, false, true);<a name="line.189"></a>
-<span class="sourceLineNo">190</span>      assertTrue(buf != null);<a name="line.190"></a>
-<span class="sourceLineNo">191</span>      assertEquals(buf.heapSize(), block.heapSize());<a name="line.191"></a>
-<span class="sourceLineNo">192</span>    }<a name="line.192"></a>
-<span class="sourceLineNo">193</span><a name="line.193"></a>
-<span class="sourceLineNo">194</span>    // Re-add same blocks and ensure nothing has changed<a name="line.194"></a>
-<span class="sourceLineNo">195</span>    long expectedBlockCount = cache.getBlockCount();<a name="line.195"></a>
-<span class="sourceLineNo">196</span>    for (CachedItem block : blocks) {<a name="line.196"></a>
-<span class="sourceLineNo">197</span>      cache.cacheBlock(block.cacheKey, block);<a name="line.197"></a>
-<span class="sourceLineNo">198</span>    }<a name="line.198"></a>
-<span class="sourceLineNo">199</span>    assertEquals(<a name="line.199"></a>
-<span class="sourceLineNo">200</span>            "Cache should ignore cache requests for blocks already in cache",<a name="line.200"></a>
-<span class="sourceLineNo">201</span>            expectedBlockCount, cache.getBlockCount());<a name="line.201"></a>
-<span class="sourceLineNo">202</span><a name="line.202"></a>
-<span class="sourceLineNo">203</span>    // Verify correctly calculated cache heap size<a name="line.203"></a>
-<span class="sourceLineNo">204</span>    assertEquals(expectedCacheSize, cache.heapSize());<a name="line.204"></a>
-<span class="sourceLineNo">205</span><a name="line.205"></a>
-<span class="sourceLineNo">206</span>    // Check if all blocks are properly cached and retrieved<a name="line.206"></a>
-<span class="sourceLineNo">207</span>    for (CachedItem block : blocks) {<a name="line.207"></a>
-<span class="sourceLineNo">208</span>      HeapSize buf = cache.getBlock(block.cacheKey, true, false, true);<a name="line.208"></a>
-<span class="sourceLineNo">209</span>      assertTrue(buf != null);<a name="line.209"></a>
-<span class="sourceLineNo">210</span>      assertEquals(buf.heapSize(), block.heapSize());<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>    // Expect no evictions<a name="line.213"></a>
-<span class="sourceLineNo">214</span>    assertEquals(0, cache.getStats().getEvictionCount());<a name="line.214"></a>
-<span class="sourceLineNo">215</span>    Thread t = new LruBlockCache.StatisticsThread(cache);<a name="line.215"></a>
-<span class="sourceLineNo">216</span>    t.start();<a name="line.216"></a>
-<span class="sourceLineNo">217</span>    t.join();<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>  @Test<a name="line.220"></a>
-<span class="sourceLineNo">221</span>  public void testCacheEvictionSimple() throws Exception {<a name="line.221"></a>
-<span class="sourceLineNo">222</span><a name="line.222"></a>
-<span class="sourceLineNo">223</span>    long maxSize = 100000;<a name="line.223"></a>
-<span class="sourceLineNo">224</span>    long blockSize = calculateBlockSizeDefault(maxSize, 10);<a name="line.224"></a>
-<span class="sourceLineNo">225</span><a name="line.225"></a>
-<span class="sourceLineNo">226</span>    LruBlockCache cache = new LruBlockCache(maxSize,blockSize,false);<a name="line.226"></a>
-<span class="sourceLineNo">227</span><a name="line.227"></a>
-<span class="sourceLineNo">228</span>    CachedItem [] blocks = generateFixedBlocks(10, blockSize, "block");<a name="line.228"></a>
-<span class="sourceLineNo">229</span><a name="line.229"></a>
-<span class="sourceLineNo">230</span>    long expectedCacheSize = cache.heapSize();<a name="line.230"></a>
-<span class="sourceLineNo">231</span><a name="line.231"></a>
-<span class="sourceLineNo">232</span>    // Add all the blocks<a name="line.232"></a>
-<span class="sourceLineNo">233</span>    for (CachedItem block : blocks) {<a name="line.233"></a>
-<span class="sourceLineNo">234</span>      cache.cacheBlock(block.cacheKey, block);<a name="line.234"></a>
-<span class="sourceLineNo">235</span>      expectedCacheSize += block.cacheBlockHeapSize();<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>    // A single eviction run should have occurred<a name="line.238"></a>
-<span class="sourceLineNo">239</span>    assertEquals(1, cache.getStats().getEvictionCount());<a name="line.239"></a>
-<span class="sourceLineNo">240</span><a name="line.240"></a>
-<span class="sourceLineNo">241</span>    // Our expected size overruns acceptable limit<a name="line.241"></a>
-<span class="sourceLineNo">242</span>    assertTrue(expectedCacheSize &gt;<a name="line.242"></a>
-<span class="sourceLineNo">243</span>      (maxSize * LruBlockCache.DEFAULT_ACCEPTABLE_FACTOR));<a name="line.243"></a>
-<span class="sourceLineNo">244</span><a name="line.244"></a>
-<span class="sourceLineNo">245</span>    // But the cache did not grow beyond max<a name="line.245"></a>
-<span class="sourceLineNo">246</span>    assertTrue(cache.heapSize() &lt; maxSize);<a name="line.246"></a>
-<span class="sourceLineNo">247</span><a name="line.247"></a>
-<span class="sourceLineNo">248</span>    // And is still below the acceptable limit<a name="line.248"></a>
-<span class="sourceLineNo">249</span>    assertTrue(cache.heapSize() &lt;<a name="line.249"></a>
-<span class="sourceLineNo">250</span>        (maxSize * LruBlockCache.DEFAULT_ACCEPTABLE_FACTOR));<a name="line.250"></a>
-<span class="sourceLineNo">251</span><a name="line.251"></a>
-<span class="sourceLineNo">252</span>    // All blocks except block 0  should be in the cache<a name="line.252"></a>
-<span class="sourceLineNo">253</span>    assertTrue(cache.getBlock(blocks[0].cacheKey, true, false, true) == null);<a name="line.253"></a>
-<span class="sourceLineNo">254</span>    for(int i=1;i&lt;blocks.length;i++) {<a name="line.254"></a>
-<span class="sourceLineNo">255</span>      assertEquals(cache.getBlock(blocks[i].cacheKey, true, false, true),<a name="line.255"></a>
-<span class="sourceLineNo">256</span>          blocks[i]);<a name="line.256"></a>
-<span class="sourceLineNo">257</span>    }<a name="line.257"></a>
-<span class="sourceLineNo">258</span>  }<a name="line.258"></a>
-<span class="sourceLineNo">259</span><a name="line.259"></a>
-<span class="sourceLineNo">260</span>  @Test<a name="line.260"></a>
-<span class="sourceLineNo">261</span>  public void testCacheEvictionTwoPriorities() throws Exception {<a name="line.261"></a>
-<span class="sourceLineNo">262</span><a name="line.262"></a>
-<span class="sourceLineNo">263</span>    long maxSize = 100000;<a name="line.263"></a>
-<span class="sourceLineNo">264</span>    long blockSize = calculateBlockSizeDefault(maxSize, 10);<a name="line.264"></a>
-<span class="sourceLineNo">265</span><a name="line.265"></a>
-<span class="sourceLineNo">266</span>    LruBlockCache cache = new LruBlockCache(maxSize,blockSize,false);<a name="line.266"></a>
-<span class="sourceLineNo">267</span><a name="line.267"></a>
-<span class="sourceLineNo">268</span>    CachedItem [] singleBlocks = generateFixedBlocks(5, 10000, "single");<a name="line.268"></a>
-<span class="sourceLineNo">269</span>    CachedItem [] multiBlocks = generateFixedBlocks(5, 10000, "multi");<a name="line.269"></a>
-<span class="sourceLineNo">270</span><a name="line.270"></a>
-<span class="sourceLineNo">271</span>    long expectedCacheSize = cache.heapSize();<a name="line.271"></a>
-<span class="sourceLineNo">272</span><a name="line.272"></a>
-<span class="sourceLineNo">273</span>    // Add and get the multi blocks<a name="line.273"></a>
-<span class="sourceLineNo">274</span>    for (CachedItem block : multiBlocks) {<a name="line.274"></a>
-<span class="sourceLineNo">275</span>      cache.cacheBlock(block.cacheKey, block);<a name="line.275"></a>
-<span class="sourceLineNo">276</span>      expectedCacheSize += block.cacheBlockHeapSize();<a name="line.276"></a>
-<span class="sourceLineNo">277</span>      assertEquals(cache.getBlock(block.cacheKey, true, false, true), block);<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>    // Add the single blocks (no get)<a name="line.280"></a>
-<span class="sourceLineNo">281</span>    for (CachedItem block : singleBlocks) {<a name="line.281"></a>
-<span class="sourceLineNo">282</span>      cache.cacheBlock(block.cacheKey, block);<a name="line.282"></a>
-<span class="sourceLineNo">283</span>      expectedCacheSize += block.heapSize();<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>    // A single eviction run should have occurred<a name="line.286"></a>
-<span class="sourceLineNo">287</span>    assertEquals(1, cache.getStats().getEvictionCount());<a name="line.287"></a>
-<span class="sourceLineNo">288</span><a name="line.288"></a>
-<span class="sourceLineNo">289</span>    // We expect two entries evicted<a name="line.289"></a>
-<span class="sourceLineNo">290</span>    assertEquals(2, cache.getStats().getEvictedCount());<a name="line.290"></a>
-<span class="sourceLineNo">291</span><a name="line.291"></a>
-<span class="sourceLineNo">292</span>    // Our expected size overruns acceptable limit<a name="line.292"></a>
-<span class="sourceLineNo">293</span>    assertTrue(expectedCacheSize &gt;<a name="line.293"></a>
-<span class="sourceLineNo">294</span>      (maxSize * LruBlockCache.DEFAULT_ACCEPTABLE_FACTOR));<a name="line.294"></a>
-<span class="sourceLineNo">295</span><a name="line.295"></a>
-<span class="sourceLineNo">296</span>    // But the cache did not grow beyond max<a name="line.296"></a>
-<span class="sourceLineNo">297</span>    assertTrue(cache.heapSize() &lt;= maxSize);<a name="line.297"></a>
-<span class="sourceLineNo">298</span><a name="line.298"></a>
-<span class="sourceLineNo">299</span>    // And is now below the acceptable limit<a name="line.299"></a>
-<span class="sourceLineNo">300</span>    assertTrue(cache.heapSize() &lt;=<a name="line.300"></a>
-<span class="sourceLineNo">301</span>        (maxSize * LruBlockCache.DEFAULT_ACCEPTABLE_FACTOR));<a name="line.301"></a>
-<span class="sourceLineNo">302</span><a name="line.302"></a>
-<span class="sourceLineNo">303</span>    // We expect fairness across the two priorities.<a name="line.303"></a>
-<span class="sourceLineNo">304</span>    // This test makes multi go barely over its limit, in-memory<a name="line.304"></a>
-<span class="sourceLineNo">305</span>    // empty, and the rest in single.  Two single evictions and<a name="line.305"></a>
-<span class="sourceLineNo">306</span>    // one multi eviction expected.<a name="line.306"></a>
-<span class="sourceLineNo">307</span>    assertTrue(cache.getBlock(singleBlocks[0].cacheKey, true, false, true) == null);<a name="line.307"></a>
-<span class="sourceLineNo">308</span>    assertTrue(cache.getBlock(multiBlocks[0].cacheKey, true, false, true) == null);<a name="line.308"></a>
-<span class="sourceLineNo">309</span><a name="line.309"></a>
-<span class="sourceLineNo">310</span>    // And all others to be cached<a name="line.310"></a>
-<span class="sourceLineNo">311</span>    for(int i=1;i&lt;4;i++) {<a name="line.311"></a>
-<span class="sourceLineNo">312</span>      assertEquals(cache.getBlock(singleBlocks[i].cacheKey, true, false, true),<a name="line.312"></a>
-<span class="sourceLineNo">313</span>          singleBlocks[i]);<a name="line.313"></a>
-<span class="sourceLineNo">314</span>      assertEquals(cache.getBlock(multiBlocks[i].cacheKey, true, false, true),<a name="line.314"></a>
-<span class="sourceLineNo">315</span>          multiBlocks[i]);<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><a name="line.318"></a>
-<span class="sourceLineNo">319</span>  @Test<a name="line.319"></a>
-<span class="sourceLineNo">320</span>  public void testCacheEvictionThreePriorities() throws Exception {<a name="line.320"></a>
-<span class="sourceLineNo">321</span><a name="line.321"></a>
-<span class="sourceLineNo">322</span>    long maxSize = 100000;<a name="line.322"></a>
-<span class="sourceLineNo">323</span>    long blockSize = calculateBlockSize(maxSize, 10);<a name="line.323"></a>
-<span class="sourceLineNo">324</span><a name="line.324"></a>
-<span class="sourceLineNo">325</span>    LruBlockCache cache = new LruBlockCache(maxSize, blockSize, false,<a name="line.325"></a>
-<span class="sourceLineNo">326</span>        (int)Math.ceil(1.2*maxSize/blockSize),<a name="line.326"></a>
-<span class="sourceLineNo">327</span>        LruBlockCache.DEFAULT_LOAD_FACTOR,<a name="line.327"></a>
-<span class="sourceLineNo">328</span>        LruBlockCache.DEFAULT_CONCURRENCY_LEVEL,<a name="line.328"></a>
-<span class="sourceLineNo">329</span>        0.98f, // min<a name="line.329"></a>
-<span class="sourceLineNo">330</span>        0.99f, // acceptable<a name="line.330"></a>
-<span class="sourceLineNo">331</span>        0.33f, // single<a name="line.331"></a>
-<span class="sourceLineNo">332</span>        0.33f, // multi<a name="line.332"></a>
-<span class="sourceLineNo">333</span>        0.34f, // memory<a name="line.333"></a>
-<span class="sourceLineNo">334</span>        1.2f,  // limit<a name="line.334"></a>
-<span class="sourceLineNo">335</span>        false,<a name="line.335"></a>
-<span class="sourceLineNo">336</span>        16 * 1024 * 1024);<a name="line.336"></a>
-<span class="sourceLineNo">337</span><a name="line.337"></a>
-<span class="sourceLineNo">338</span>    CachedItem [] singleBlocks = generateFixedBlocks(5, blockSize, "single");<a name="line.338"></a>
-<span class="sourceLineNo">339</span>    CachedItem [] multiBlocks = generateFixedBlocks(5, blockSize, "multi");<a name="line.339"></a>
-<span class="sourceLineNo">340</span>    CachedItem [] memoryBlocks = generateFixedBlocks(5, blockSize, "memory");<a name="line.340"></a>
-<span class="sourceLineNo">341</span><a name="line.341"></a>
-<span class="sourceLineNo">342</span>    long expectedCacheSize = cache.heapSize();<a name="line.342"></a>
-<span class="sourceLineNo">343</span><a name="line.343"></a>
-<span class="sourceLineNo">344</span>    // Add 3 blocks from each priority<a name="line.344"></a>
-<span class="sourceLineNo">345</span>    for(int i=0;i&lt;3;i++) {<a name="line.345"></a>
-<span class="sourceLineNo">346</span><a name="line.346"></a>
-<span class="sourceLineNo">347</span>      // Just add single blocks<a name="line.347"></a>
-<span class="sourceLineNo">348</span>      cache.cacheBlock(singleBlocks[i].cacheKey, singleBlocks[i]);<a name="line.348"></a>
-<span class="sourceLineNo">349</span>      expectedCacheSize += singleBlocks[i].cacheBlockHeapSize();<a name="line.349"></a>
-<span class="sourceLineNo">350</span><a name="line.350"></a>
-<span class="sourceLineNo">351</span>      // Add and get multi blocks<a name="line.351"></a>
-<span class="sourceLineNo">352</span>      cache.cacheBlock(multiBlocks[i].cacheKey, multiBlocks[i]);<a name="line.352"></a>
-<span class="sourceLineNo">353</span>      expectedCacheSize += multiBlocks[i].cacheBlockHeapSize();<a name="line.353"></a>
-<span class="sourceLineNo">354</span>      cache.getBlock(multiBlocks[i].cacheKey, true, false, true);<a name="line.354"></a>
-<span class="sourceLineNo">355</span><a name="line.355"></a>
-<span class="sourceLineNo">356</span>      // Add memory blocks as such<a name="line.356"></a>
-<span class="sourceLineNo">357</span>      cache.cacheBlock(memoryBlocks[i].cacheKey, memoryBlocks[i], true);<a name="line.357"></a>
-<span class="sourceLineNo">358</span>      expectedCacheSize += memoryBlocks[i].cacheBlockHeapSize();<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>    // Do not expect any evictions yet<a name="line.362"></a>
-<span class="sourceLineNo">363</span>    assertEquals(0, cache.getStats().getEvictionCount());<a name="line.363"></a>
-<span class="sourceLineNo">364</span><a name="line.364"></a>
-<span class="sourceLineNo">365</span>    // Verify cache size<a name="line.365"></a>
-<span class="sourceLineNo">366</span>    assertEquals(expectedCacheSize, cache.heapSize());<a name="line.366"></a>
-<span class="sourceLineNo">367</span><a name="line.367"></a>
-<span class="sourceLineNo">368</span>    // Insert a single block, oldest single should be evicted<a name="line.368"></a>
-<span class="sourceLineNo">369</span>    cache.cacheBlock(singleBlocks[3].cacheKey, singleBlocks[3]);<a name="line.369"></a>
-<span class="sourceLineNo">370</span><a name="line.370"></a>
-<span class="sourceLineNo">371</span>    // Single eviction, one thing evicted<a name="line.371"></a>
-<span class="sourceLineNo">372</span>    assertEquals(1, cache.getStats().getEvictionCount());<a name="line.372"></a>
-<span class="sourceLineNo">373</span>    assertEquals(1, cache.getStats().getEvictedCount());<a name="line.373"></a>
-<span class="sourceLineNo">374</span><a name="line.374"></a>
-<span class="sourceLineNo">375</span>    // Verify oldest single block is the one evicted<a name="line.375"></a>
-<span class="sourceLineNo">376</span>    assertEquals(null, cache.getBlock(singleBlocks[0].cacheKey, true, false, true));<a name="line.376"></a>
-<span class="sourceLineNo">377</span><a name="line.377"></a>
-<span class="sourceLineNo">378</span>    // Change the oldest remaining single block to a multi<a name="line.378"></a>
-<span class="sourceLineNo">379</span>    cache.getBlock(singleBlocks[1].cacheKey, true, false, true);<a name="line.379"></a>
-<span class="sourceLineNo">380</span><a name="line.380"></a>
-<span class="sourceLineNo">381</span>    // Insert another single block<a name="line.381"></a>
-<span class="sourceLineNo">382</span>    cache.cacheBlock(singleBlocks[4].cacheKey, singleBlocks[4]);<a name="line.382"></a>
-<span class="sourceLineNo">383</span><a name="line.383"></a>
-<span class="sourceLineNo">384</span>    // Two evictions, two evicted.<a name="line.384"></a>
-<span class="sourceLineNo">385</span>    assertEquals(2, cache.getStats().getEvictionCount());<a name="line.385"></a>
-<span class="sourceLineNo">386</span>    assertEquals(2, cache.getStats().getEvictedCount());<a name="line.386"></a>
-<span class="sourceLineNo">387</span><a name="line.387"></a>
-<span class="sourceLineNo">388</span>    // Oldest multi block should be evicted now<a name="line.388"></a>
-<span class="sourceLineNo">389</span>    assertEquals(null, cache.getBlock(multiBlocks[0].cacheKey, true, false, true));<a name="line.389"></a>
-<span class="sourceLineNo">390</span><a name="line.390"></a>
-<span class="sourceLineNo">391</span>    // Insert another memory block<a name="line.391"></a>
-<span class="sourceLineNo">392</span>    cache.cacheBlock(memoryBlocks[3].cacheKey, memoryBlocks[3], true);<a name="line.392"></a>
-<span class="sourceLineNo">393</span><a name="line.393"></a>
-<span class="sourceLineNo">394</span>    // Three evictions, three evicted.<a name="line.394"></a>
-<span class="sourceLineNo">395</span>    assertEquals(3, cache.getStats().getEvictionCount());<a name="line.395"></a>
-<span class="sourceLineNo">396</span>    assertEquals(3, cache.getStats().getEvictedCount());<a name="line.396"></a>
-<span class="sourceLineNo">397</span><a name="line.397"></a>
-<span class="sourceLineNo">398</span>    // Oldest memory block should be evicted now<a name="line.398"></a>
-<span class="sourceLineNo">399</span>    assertEquals(null, cache.getBlock(memoryBlocks[0].cacheKey, true, false, true));<a name="line.399"></a>
-<span class="sourceLineNo">400</span><a name="line.400"></a>
-<span class="sourceLineNo">401</span>    // Add a block that is twice as big (should force two evictions)<a name="line.401"></a>
-<span class="sourceLineNo">402</span>    CachedItem [] bigBlocks = generateFixedBlocks(3, blockSize*3, "big");<a name="line.402"></a>
-<span class="sourceLineNo">403</span>    cache.cacheBlock(bigBlocks[0].cacheKey, bigBlocks[0]);<a name="line.403"></a>
-<span class="sourceLineNo">404</span><a name="line.404"></a>
-<span class="sourceLineNo">405</span>    // Four evictions, six evicted (inserted block 3X size, expect +3 evicted)<a name="line.405"></a>
-<span class="sourceLineNo">406</span>    assertEquals(4, cache.getStats().getEvictionCount());<a name="line.406"></a>
-<span class="sourceLineNo">407</span>    assertEquals(6, cache.getStats().getEvictedCount());<a name="line.407"></a>
-<span class="sourceLineNo">408</span><a name="line.408"></a>
-<span class="sourceLineNo">409</span>    // Expect three remaining singles to be evicted<a name="line.409"></a>
-<span class="sourceLineNo">410</span>    assertEquals(null, cache.getBlock(singleBlocks[2].cacheKey, true, false, true));<a name="line.410"></a>
-<span class="sourceLineNo">411</span>    assertEquals(null, cache.getBlock(singleBlocks[3].cacheKey, true, false, true));<a name="line.411"></a>
-<span class="sourceLineNo">412</span>    assertEquals(null, cache.getBlock(singleBlocks[4].cacheKey, true, false, true));<a name="line.412"></a>
-<span class="sourceLineNo">413</span><a name="line.413"></a>
-<span class="sourceLineNo">414</span>    // Make the big block a multi block<a name="line.414"></a>
-<span class="sourceLineNo">415</span>    cache.getBlock(bigBlocks[0].cacheKey, true, false, true);<a name="line.415"></a>
-<span class="sourceLineNo">416</span><a name="line.416"></a>
-<span class="sourceLineNo">417</span>    // Cache another single big block<a name="line.417"></a>
-<span class="sourceLineNo">418</span>    cache.cacheBlock(bigBlocks[1].cacheKey, bigBlocks[1]);<a name="line.418"></a>
-<span class="sourceLineNo">419</span><a name="line.419"></a>
-<span class="sourceLineNo">420</span>    // Five evictions, nine evicted (3 new)<a name="line.420"></a>
-<span class="sourceLineNo">421</span>    assertEquals(5, cache.getStats().getEvictionCount());<a name="line.421"></a>
-<span class="sourceLineNo">422</span>    assertEquals(9, cache.getStats().getEvictedCount());<a name="line.422"></a>
-<span class="sourceLineNo">423</span><a name="line.423"></a>
-<span class="sourceLineNo">424</span>    // Expect three remaining multis to be evicted<a name="line.424"></a>
-<span class="sourceLineNo">425</span>    assertEquals(null, cache.getBlock(singleBlocks[1].cacheKey, true, false, true));<a name="line.425"></a>
-<span class="sourceLineNo">426</span>    assertEquals(null, cache.getBlock(multiBlocks[1].cacheKey, true, false, true));<a name="line.426"></a>
-<span class="sourceLineNo">427</span>    assertEquals(null, cache.getBlock(multiBlocks[2].cacheKey, true, false, true));<a name="line.427"></a>
-<span class="sourceLineNo">428</span><a name="line.428"></a>
-<span class="sourceLineNo">429</span>    // Cache a big memory block<a name="line.429"></a>
-<span class="sourceLineNo">430</span>    cache.cacheBlock(bigBlocks[2].cacheKey, bigBlocks[2], true);<a name="line.430"></a>
-<span class="sourceLineNo">431</span><a name="line.431"></a>
-<span class="sourceLineNo">432</span>    // Six evictions, twelve evicted (3 new)<a name="line.432"></a>
-<span class="sourceLineNo">433</span>    assertEquals(6, cache.getStats().getEvictionCount());<a name="line.433"></a>
-<span class="sourceLineNo">434</span>    assertEquals(12, cache.getStats().getEvictedCount());<a name="line.434"></a>
-<span class="sourceLineNo">435</span><a name="line.435"></a>
-<span class="sourceLineNo">436</span>    // Expect three remaining in-memory to be evicted<a name="line.436"></a>
-<span class="sourceLineNo">437</span>    assertEquals(null, cache.getBlock(memoryBlocks[1].cacheKey, true, false, true));<a name="line.437"></a>
-<span class="sourceLineNo">438</span>    assertEquals(null, cache.getBlock(memoryBlocks[2].cacheKey, true, false, true));<a name="line.438"></a>
-<span class="sourceLineNo">439</span>    assertEquals(null, cache.getBlock(memoryBlocks[3].cacheKey, true, false, true));<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>  @Test<a name="line.442"></a>
-<span class="sourceLineNo">443</span>  public void testCacheEvictionInMemoryForceMode() throws Exception {<a name="line.443"></a>
-<span class="sourceLineNo">444</span>    long maxSize = 100000;<a name="line.444"></a>
-<span class="sourceLineNo">445</span>    long blockSize = calculateBlockSize(maxSize, 10);<a name="line.445"></a>
-<span class="sourceLineNo">446</span><a name="line.446"></a>
-<span class="sourceLineNo">447</span>    LruBlockCache cache = new LruBlockCache(maxSize, blockSize, false,<a name="line.447"></a>
-<span class="sourceLineNo">448</span>        (int)Math.ceil(1.2*maxSize/blockSize),<a name="line.448"></a>
-<span class="sourceLineNo">449</span>        LruBlockCache.DEFAULT_LOAD_FACTOR,<a name="line.449"></a>
-<span class="sourceLineNo">450</span>        LruBlockCache.DEFAULT_CONCURRENCY_LEVEL,<a name="line.450"></a>
-<span class="sourceLineNo">451</span>        0.98f, // min<a name="line.451"></a>
-<span class="sourceLineNo">452</span>        0.99f, // acceptable<a name="line.452"></a>
-<span class="sourceLineNo">453</span>        0.2f, // single<a name="line.453"></a>
-<span class="sourceLineNo">454</span>        0.3f, // multi<a name="line.454"></a>
-<span class="sourceLineNo">455</span>        0.5f, // memory<a name="line.455"></a>
-<span class="sourceLineNo">456</span>        1.2f, // limit<a name="line.456"></a>
-<span class="sourceLineNo">457</span>        true,<a name="line.457"></a>
-<span class="sourceLineNo">458</span>        16 * 1024 * 1024);<a name="line.458"></a>
-<span class="sourceLineNo">459</span><a name="line.459"></a>
-<span class="sourceLineNo">460</span>    CachedItem [] singleBlocks = generateFixedBlocks(10, blockSize, "single");<a name="line.460"></a>
-<span class="sourceLineNo">461</span>    CachedItem [] multiBlocks = generateFixedBlocks(10, blockSize, "multi");<a name="line.461"></a>
-<span class="sourceLineNo">462</span>    CachedItem [] memoryBlocks = generateFixedBlocks(10, blockSize, "memory");<a name="line.462"></a>
-<span class="sourceLineNo">463</span><a name="line.463"></a>
-<span class="sourceLineNo">464</span>    long expectedCacheSize = cache.heapSize();<a name="line.464"></a>
-<span class="sourceLineNo">465</span><a name="line.465"></a>
-<span class="sourceLineNo">466</span>    // 0. Add 5 single blocks and 4 multi blocks to make cache full, si:mu:me = 5:4:0<a name="line.466"></a>
-<span class="sourceLineNo">467</span>    for(int i = 0; i &lt; 4; i++) {<a name="line.467"></a>
-<span class="sourceLineNo">468</span>      // Just add single blocks<a name="line.468"></a>
-<span class="sourceLineNo">469</span>      cache.cacheBlock(singleBlocks[i].cacheKey, singleBlocks[i]);<a name="line.469"></a>
-<span class="sourceLineNo">470</span>      expectedCacheSize += singleBlocks[i].cacheBlockHeapSize();<a name="line.470"></a>
-<span class="sourceLineNo">471</span>      // Add and get multi blocks<a name="line.471"></a>
-<span class="sourceLineNo">472</span>      cache.cacheBlock(multiBlocks[i].cacheKey, multiBlocks[i]);<a name="line.472"></a>
-<span class="sourceLineNo">473</span>      expectedCacheSize += multiBlocks[i].cacheBlockHeapSize();<a name="line.473"></a>
-<span class="sourceLineNo">474</span>      cache.getBlock(multiBlocks[i].cacheKey, true, false, true);<a name="line.474"></a>
-<span class="sourceLineNo">475</span>    }<a name="line.475"></a>
-<span class="sourceLineNo">476</span>    // 5th single block<a name="line.476"></a>
-<span class="sourceLineNo">477</span>    cache.cacheBlock(singleBlocks[4].cacheKey, singleBlocks[4]);<a name="line.477"></a>
-<span class="sourceLineNo">478</span>    expectedCacheSize += singleBlocks[4].cacheBlockHeapSize();<a name="line.478"></a>
-<span class="sourceLineNo">479</span>    // Do not expect any evictions yet<a name="line.479"></a>
-<span class="sourceLineNo">480</span>    assertEquals(0, cache.getStats().getEvictionCount());<a name="line.480"></a>
-<span class="sourceLineNo">481</span>    // Verify cache size<a name="line.481"></a>
-<span class="sourceLineNo">482</span>    assertEquals(expectedCacheSize, cache.heapSize());<a name="line.482"></a>
-<span class="sourceLineNo">483</span><a name="line.483"></a>
-<span class="sourceLineNo">484</span>    // 1. Insert a memory block, oldest single should be evicted, si:mu:me = 4:4:1<a name="line.484"></a>
-<span class="sourceLineNo">485</span>    cache.cacheBlock(memoryBlocks[0].cacheKey, memoryBlocks[0], true);<a name="line.485"></a>
-<span class="sourceLineNo">486</span>    // Single eviction, one block evicted<a name="line.486"></a>
-<span class="sourceLineNo">487</span>    assertEquals(1, cache.getStats().getEvictionCount());<a name="line.487"></a>
-<span class="sourceLineNo">488</span>    assertEquals(1, cache.getStats().getEvictedCount());<a name="line.488"></a>
-<span class="sourceLineNo">489</span>    // Verify oldest single block (index = 0) is the one evicted<a name="line.489"></a>
-<span class="sourceLineNo">490</span>    assertEquals(null, cache.getBlock(singleBlocks[0].cacheKey, true, false, true));<a name="line.490"></a>
-<span class="sourceLineNo">491</span><a name="line.491"></a>
-<span class="sourceLineNo">492</span>    // 2. Insert another memory block, another single evicted, si:mu:me = 3:4:2<a name="line.492"></a>
-<span class="sourceLineNo">493</span>    cache.cacheBlock(memoryBlocks[1].cacheKey, memoryBlocks[1], true);<a name="line.493"></a>
-<span class="sourceLineNo">494</span>    // Two evictions, two evicted.<a name="line.494"></a>
-<span class="sourceLineNo">495</span>    assertEquals(2, cache.getStats().getEvictionCount());<a name="line.495"></a>
-<span class="sourceLineNo">496</span>    assertEquals(2, cache.getStats().getEvictedCount());<a name="line.496"></a>
-<span class="sourceLineNo">497</span>    // Current oldest single block (index = 1) should be evicted now<a name="line.497"></a>
-<span class="sourceLineNo">498</span>    assertEquals(null, cache.getBlock(singleBlocks[1].cacheKey, true, false, true));<a name="line.498"></a>
-<span class="sourceLineNo">499</span><a name="line.499"></a>
-<span class="sourceLineNo">500</span>    // 3. Insert 4 memory blocks, 2 single and 2 multi evicted, si:mu:me = 1:2:6<a name="line.500"></a>
-<span class="sourceLineNo">501</span>    cache.cacheBlock(memoryBlocks[2].cacheKey, memoryBlocks[2], true);<a name="line.501"></a>
-<span class="sourceLineNo">502</span>    cache.cacheBlock(memoryBlocks[3].cacheKey, memoryBlocks[3], true);<a name="line.502"></a>
-<span class="sourceLineNo">503</span>    cache.cacheBlock(memoryBlocks[4].cacheKey, memoryBlocks[4], true);<a name="line.503"></a>
-<span class="sourceLineNo">504</span>    cache.cacheBlock(memoryBlocks[5].cacheKey, memoryBlocks[5], true);<a name="line.504"></a>
-<span class="sourceLineNo">505</span>    // Three evictions, three evicted.<a name="line.505"></a>
-<span class="sourceLineNo">506</span>    assertEquals(6, cache.getStats().getEvictionCount());<a name="line.506"></a>
-<span class="sourceLineNo">507</span>    assertEquals(6, cache.getStats().getEvictedCount());<a name="line.507"></a>
-<span class="sourceLineNo">508</span>    // two oldest single blocks and two oldest multi blocks evicted<a name="line.508"></a>
-<span class="sourceLineNo">509</span>    assertEquals(null, cache.getBlock(singleBlocks[2].cacheKey, true, false, true));<a name="line.509"></a>
-<span class="sourceLineNo">510</span>    assertEquals(null, cache.getBlock(singleBlocks[3].cacheKey, true, false, true));<a name="line.510"></a>
-<span class="sourceLineNo">511</span>    assertEquals(null, cache.getBlock(multiBlocks[0].cacheKey, true, false, true));<a name="line.511"></a>
-<span class="sourceLineNo">512</span>    assertEquals(null, cache.getBlock(multiBlocks[1].cacheKey, true, false, true));<a name="line.512"></a>
-<span class="sourceLineNo">513</span><a name="line.513"></a>
-<span class="sourceLineNo">514</span>    // 4. Insert 3 memory blocks, the remaining 1 single and 2 multi evicted<a name="line.514"></a>
-<span class="sourceLineNo">515</span>    // si:mu:me = 0:0:9<a name="line.515"></a>
-<span class="sourceLineNo">516</span>    cache.cacheBlock(memoryBlocks[6].cacheKey, memoryBlocks[6], true);<a name="line.516"></a>
-<span class="sourceLineNo">517</span>    cache.cacheBlock(memoryBlocks[7].cacheKey, memoryBlocks[7], true);<a name="line.517"></a>
-<span class="sourceLineNo">518</span>    cache.cacheBlock(memoryBlocks[8].cacheKey, memoryBlocks[8], true);<a name="line.518"></a>
-<span class="sourceLineNo">519</span>    // Three evictions, three evicted.<a name="line.519"></a>
-<span class="sourceLineNo">520</span>    assertEquals(9, cache.getStats().getEvictionCount());<a name="line.520"></a>
-<span class="sourceLineNo">521</span>    assertEquals(9, cache.getStats().getEvictedCount());<a name="line.521"></a>
-<span class="sourceLineNo">522</span>    // one oldest single block and two oldest multi blocks evicted<a name="line.522"></a>
-<span class="sourceLineNo">523</span>    assertEquals(null, cache.getBlock(singleBlocks[4].cacheKey, true, false, true));<a name="line.523"></a>
-<span class="sourceLineNo">524</span>    assertEquals(null, cache.getBlock(multiBlocks[2].cacheKey, true, false, true));<a name="line.524"></a>
-<span class="sourceLineNo">525</span>    assertEquals(null, cache.getBlock(multiBlocks[3].cacheKey, true, false, true));<a name="line.525"></a>
-<span class="sourceLineNo">526</span><a name="line.526"></a>
-<span class="sourceLineNo">527</span>    // 5. Insert one memory block, the oldest memory evicted<a name="line.527"></a>
-<span class="sourceLineNo">528</span>    // si:mu:me = 0:0:9<a name="line.528"></a>
-<span class="sourceLineNo">529</span>    cache.cacheBlock(memoryBlocks[9].cacheKey, memoryBlocks[9], true);<a name="line.529"></a>
-<span class="sourceLineNo">530</span>    // one eviction, one evicted.<a name="line.530"></a>
-<span class="sourceLineNo">531</span>    assertEquals(10, cache.getStats().getEvictionCount());<a name="line.531"></a>
-<span class="sourceLineNo">532</span>    assertEquals(10, cache.getStats().getEvictedCount());<a name="line.532"></a>
-<span class="sourceLineNo">533</span>    // oldest memory block evicted<a name="line.533"></a>
-<span class="sourceLineNo">534</span>    assertEquals(null, cache.getBlock(memoryBlocks[0].cacheKey, true, false, true));<a name="line.534"></a>
-<span class="sourceLineNo">535</span><a name="line.535"></a>
-<span class="sourceLineNo">536</span>    // 6. Insert one new single block, itself evicted immediately since<a name="line.536"></a>
-<span class="sourceLineNo">537</span>    //    all blocks in cache are memory-type which have higher priority<a name="line.537"></a>
-<span class="sourceLineNo">538</span>    // si:mu:me = 0:0:9 (no change)<a name="line.538"></a>
-<span class="sourceLineNo">539</span>    cache.cacheBlock(singleBlocks[9].cacheKey, singleBlocks[9]);<a name="line.539"></a>
-<span class="sourceLineNo">540</span>    // one eviction, one evicted.<a name="line.540"></a>
-<span class="sourceLineNo">541</span>    assertEquals(11, cache.getStats().getEvictionCount());<a name="line.541"></a>
-<span class="sourceLineNo">542</span>    assertEquals(11, cache.getStats().getEvictedCount());<a name="line.542"></a>
-<span class="sourceLineNo">543</span>    // the single block just cached now evicted (can't evict memory)<a name="line.543"></a>
-<span class="sourceLineNo">544</span>    assertEquals(null, cache.getBlock(singleBlocks[9].cacheKey, true, false, true));<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>  // test scan resistance<a name="line.547"></a>
-<span class="sourceLineNo">548</span>  @Test<a name="line.548"></a>
-<span class="sourceLineNo">549</span>  public void testScanResistance() throws Exception {<a name="line.549"></a>
-<span class="sourceLineNo">550</span><a name="line.550"></a>
-<span class="sourceLineNo">551</span>    long maxSize = 100000;<a name="line.551"></a>
-<span class="sourceLineNo">552</span>    long blockSize = calculateBlockSize(maxSize, 10);<a name="line.552"></a>
-<span class="sourceLineNo">553</span><a name="line.553"></a>
-<span class="sourceLineNo">554</span>    LruBlockCache cache = new LruBlockCache(maxSize, blockSize, false,<a name="line.554"></a>
-<span class="sourceLineNo">555</span>        (int)Math.ceil(1.2*maxSize/blockSize),<a name="line.555"></a>
-<span class="sourceLineNo">556</span>        LruBlockCache.DEFAULT_LOAD_FACTOR,<a name="line.556"></a>
-<span class="sourceLineNo">557</span>        LruBlockCache.DEFAULT_CONCURRENCY_LEVEL,<a name="line.557"></a>
-<span class="sourceLineNo">558</span>        0.66f, // min<a name="line.558"></a>
-<span class="sourceLineNo">559</span>        0.99f, // acceptable<a name="line.559"></a>
-<span class="sourceLineNo">560</span>        0.33f, // single<a name="line.560"></a>
-<span class="sourceLineNo">561</span>        0.33f, // multi<a name="line.561"></a>
-<span class="sourceLineNo">562</span>        0.34f, // memory<a name="line.562"></a>
-<span class="sourceLineNo">563</span>        1.2f,  // limit<a name="line.563"></a>
-<span class="sourceLineNo">564</span>        false,<a name="line.564"></a>
-<span class="sourceLineNo">565</span>        16 * 1024 * 1024);<a name="line.565"></a>
-<span class="sourceLineNo">566</span><a name="line.566"></a>
-<span class="sourceLineNo">567</span>    CachedItem [] singleBlocks = generateFixedBlocks(20, blockSize, "single");<a name="line.567"></a>
-<span class="sourceLineNo">568</span>    CachedItem [] multiBlocks = generateFixedBlocks(5, blockSize, "multi");<a name="line.568"></a>
-<span class="sourceLineNo">569</span><a name="line.569"></a>
-<span class="sourceLineNo">570</span>    // Add 5 multi blocks<a name="line.570"></a>
-<span class="sourceLineNo">571</span>    for (CachedItem block : multiBlocks) {<a name="line.571"></a>
-<span class="sourceLineNo">572</span>      cache.cacheBlock(block.cacheKey, block);<a name="line.572"></a>
-<span class="sourceLineNo">573</span>      cache.getBlock(block.cacheKey, true, false, true);<a name="line.573"></a>
-<span class="sourceLineNo">574</span>    }<a name="line.574"></a>
-<span class="sourceLineNo">575</span><a name="line.575"></a>
-<span class="sourceLineNo">576</span>    // Add 5 single blocks<a name="line.576"></a>
-<span class="sourceLineNo">577</span>    for(int i=0;i&lt;5;i++) {<a name="line.577"></a>
-<span class="sourceLineNo">578</span>      cache.cacheBlock(singleBlocks[i].cacheKey, singleBlocks[i]);<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>    // An eviction ran<a name="line.581"></a>
-<span class="sourceLineNo">582</span>    assertEquals(1, cache.getStats().getEvictionCount());<a name="line.582"></a>
-<span class="sourceLineNo">583</span><a name="line.583"></a>
-<span class="sourceLineNo">584</span>    // To drop down to 2/3 capacity, we'll need to evict 4 blocks<a name="line.584"></a>
-<span class="sourceLineNo">585</span>    assertEquals(4, cache.getStats().getEvictedCount());<a name="line.585"></a>
-<span class="sourceLineNo">586</span><a name="line.586"></a>
-<span class="sourceLineNo">587</span>    // Should have been taken off equally from single and multi<a name="line.587"></a>
-<span class="sourceLineNo">588</span>    assertEquals(null, cache.getBlock(singleBlocks[0].cacheKey, true, false, true));<a name="line.588"></a>
-<span class="sourceLineNo">589</span>    assertEquals(null, cache.getBlock(singleBlocks[1].cacheKey, true, false, true));<a name="line.589"></a>
-<span class="sourceLineNo">590</span>    assertEquals(null, cache.getBlock(multiBlocks[0].cacheKey, true, false, true));<a name="line.590"></a>
-<span class="sourceLineNo">591</span>    assertEquals(null, cache.getBlock(multiBlocks[1].cacheKey, true, false, true));<a name="line.591"></a>
-<span class="sourceLineNo">592</span><a name="line.592"></a>
-<span class="sourceLineNo">593</span>    // Let's keep "scanning" by adding single blocks.  From here on we only<a name="line.593"></a>
-<span class="sourceLineNo">594</span>    // expect evictions from the single bucket.<a name="line.594"></a>
-<span class="sourceLineNo">595</span><a name="line.595"></a>
-<span class="sourceLineNo">596</span>    // Every time we reach 10 total blocks (every 4 inserts) we get 4 single<a name="line.596"></a>
-<span class="sourceLineNo">597</span>    // blocks evicted.  Inserting 13 blocks should yield 3 more evictions and<a name="line.597"></a>
-<span class="sourceLineNo">598</span>    // 12 more evicted.<a name="line.598"></a>
-<span class="sourceLineNo">599</span><a name="line.599"></a>
-<span class="sourceLineNo">600</span>    for(int i=5;i&lt;18;i++) {<a name="line.600"></a>
-<span class="sourceLineNo">601</span>      cache.cacheBlock(singleBlocks[i].cacheKey, singleBlocks[i]);<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>    // 4 total evictions, 16 total evicted<a name="line.604"></a>
-<span class="sourceLineNo">605</span>    assertEquals(4, cache.getStats().getEvictionCount());<a name="line.605"></a>
-<span class="sourceLineNo">606</span>    assertEquals(16, cache.getStats().getEvictedCount());<a name="line.606"></a>
-<span class="sourceLineNo">607</span><a name="line.607"></a>
-<span class="sourceLineNo">608</span>    // Should now have 7 total blocks<a name="line.608"></a>
-<span class="sourceLineNo">609</span>    assertEquals(7, cache.getBlockCount());<a name="line.609"></a>
-<span class="sourceLineNo">610</span><a name="line.610"></a>
-<span class="sourceLineNo">611</span>  }<a name="line.611"></a>
-<span class="sourceLineNo">612</span><a name="line.612"></a>
-<span class="sourceLineNo">613</span>  @Test<a name="line.613"></a>
-<span class="sourceLineNo">614</span>  public void testMaxBlockSize() throws Exception {<a name="line.614"></a>
-<span class="sourceLineNo">615</span>    long maxSize = 100000;<a name="line.615"></a>
-<span class="sourceLineNo">616</span>    long blockSize = calculateBlockSize(maxSize, 10);<a name="line.616"></a>
-<span class="sourceLineNo">617</span><a name="line.617"></a>
-<span class="sourceLineNo">618</span>    LruBlockCache cache = new LruBlockCache(maxSize, blockSize, false,<a name="line.618"></a>
-<span class="sourceLineNo">619</span>        (int)Math.ceil(1.2*maxSize/blockSize),<a name="line.619"></a>
-<span class="sourceLineNo">620</span>        LruBlockCache.DEFAULT_LOAD_FACTOR,<a name="line.620"></a>
-<span class="sourceLineNo">621</span>        LruBlockCache.DEFAULT_CONCURRENCY_LEVEL,<a name="line.621"></a>
-<span class="sourceLineNo">622</span>        0.66f, // min<a name="line.622"></a>
-<span class="sourceLineNo">623</span>        0.99f, // acceptable<a name="line.623"></a>
-<span class="sourceLineNo">624</span>        0.33f, // single<a name="line.624"></a>
-<span class="sourceLineNo">625</span>        0.33f, // multi<a name="line.625"></a>
-<span class="sourceLineNo">626</span>        0.34f, // memory<a name="line.626"></a>
-<span class="sourceLineNo">627</span>        1.2f,  // limit<a name="line.627"></a>
-<span class="sourceLineNo">628</span>        false,<a name="line.628"></a>
-<span class="sourceLineNo">629</span>        1024);<a name="line.629"></a>
-<span class="sourceLineNo">630</span>    CachedItem [] tooLong = generateFixedBlocks(10, 1024+5, "long");<a name="line.630"></a>
-<span class="sourceLineNo">631</span>    CachedItem [] small = generateFixedBlocks(15, 600, "small");<a name="line.631"></a>
-<span class="sourceLineNo">632</span><a name="line.632"></a>
+<span class="sourceLineNo">034</span>import org.apache.hadoop.hbase.HConstants;<a name="line.34"></a>
+<span class="sourceLineNo">035</span>import org.apache.hadoop.hbase.Waiter;<a name="line.35"></a>
+<span class="sourceLineNo">036</span>import org.apache.hadoop.hbase.Waiter.ExplainingPredicate;<a name="line.36"></a>
+<span class="sourceLineNo">037</span>import org.apache.hadoop.hbase.io.HeapSize;<a name="line.37"></a>
+<span class="sourceLineNo">038</span>import org.apache.hadoop.hbase.io.hfile.LruBlockCache.EvictionThread;<a name="line.38"></a>
+<span class="sourceLineNo">039</span>import org.apache.hadoop.hbase.testclassification.IOTests;<a name="line.39"></a>
+<span class="sourceLineNo">040</span>import org.apache.hadoop.hbase.testclassification.SmallTests;<a name="line.40"></a>
+<span class="sourceLineNo">041</span>import org.apache.hadoop.hbase.util.ClassSize;<a name="line.41"></a>
+<span class="sourceLineNo">042</span>import org.junit.ClassRule;<a name="line.42"></a>
+<span class="sourceLineNo">043</span>import org.junit.Test;<a name="line.43"></a>
+<span class="sourceLineNo">044</span>import org.junit.experimental.categories.Category;<a name="line.44"></a>
+<span class="sourceLineNo">045</span><a name="line.45"></a>
+<span class="sourceLineNo">046</span>/**<a name="line.46"></a>
+<span class="sourceLineNo">047</span> * Tests the concurrent LruBlockCache.&lt;p&gt;<a name="line.47"></a>
+<span class="sourceLineNo">048</span> *<a name="line.48"></a>
+<span class="sourceLineNo">049</span> * Tests will ensure it grows and shrinks in size properly,<a name="line.49"></a>
+<span class="sourceLineNo">050</span> * evictions run when they're supposed to and do what they should,<a name="line.50"></a>
+<span class="sourceLineNo">051</span> * and that cached blocks are accessible when expected to be.<a name="line.51"></a>
+<span class="sourceLineNo">052</span> */<a name="line.52"></a>
+<span class="sourceLineNo">053</span>@Category({IOTests.class, SmallTests.class})<a name="line.53"></a>
+<span class="sourceLineNo">054</span>public class TestLruBlockCache {<a name="line.54"></a>
+<span class="sourceLineNo">055</span><a name="line.55"></a>
+<span class="sourceLineNo">056</span>  @ClassRule<a name="line.56"></a>
+<span class="sourceLineNo">057</span>  public static final HBaseClassTestRule CLASS_RULE =<a name="line.57"></a>
+<span class="sourceLineNo">058</span>      HBaseClassTestRule.forClass(TestLruBlockCache.class);<a name="line.58"></a>
+<span class="sourceLineNo">059</span><a name="line.59"></a>
+<span class="sourceLineNo">060</span>  @Test<a name="line.60"></a>
+<span class="sourceLineNo">061</span>  public void testCacheEvictionThreadSafe() throws Exception {<a name="line.61"></a>
+<span class="sourceLineNo">062</span>    long maxSize = 100000;<a name="line.62"></a>
+<span class="sourceLineNo">063</span>    int numBlocks = 9;<a name="line.63"></a>
+<span class="sourceLineNo">064</span>    int testRuns = 10;<a name="line.64"></a>
+<span class="sourceLineNo">065</span>    final long blockSize = calculateBlockSizeDefault(maxSize, numBlocks);<a name="line.65"></a>
+<span class="sourceLineNo">066</span>    assertTrue("calculateBlockSize appears broken.", blockSize * numBlocks &lt;= maxSize);<a name="line.66"></a>
+<span class="sourceLineNo">067</span><a name="line.67"></a>
+<span class="sourceLineNo">068</span>    final Configuration conf = HBaseConfiguration.create();<a name="line.68"></a>
+<span class="sourceLineNo">069</span>    final LruBlockCache cache = new LruBlockCache(maxSize, blockSize);<a name="line.69"></a>
+<span class="sourceLineNo">070</span>    EvictionThread evictionThread = cache.getEvictionThread();<a name="line.70"></a>
+<span class="sourceLineNo">071</span>    assertTrue(evictionThread != null);<a name="line.71"></a>
+<span class="sourceLineNo">072</span>    while (!evictionThread.isEnteringRun()) {<a name="line.72"></a>
+<span class="sourceLineNo">073</span>      Thread.sleep(1);<a name="line.73"></a>
+<span class="sourceLineNo">074</span>    }<a name="line.74"></a>
+<span class="sourceLineNo">075</span>    final String hfileName = "hfile";<a name="line.75"></a>
+<span class="sourceLineNo">076</span>    int threads = 10;<a name="line.76"></a>
+<span class="sourceLineNo">077</span>    final int blocksPerThread = 5 * numBlocks;<a name="line.77"></a>
+<span class="sourceLineNo">078</span>    for (int run = 0; run != testRuns; ++run) {<a name="line.78"></a>
+<span class="sourceLineNo">079</span>      final AtomicInteger blockCount = new AtomicInteger(0);<a name="line.79"></a>
+<span class="sourceLineNo">080</span>      ExecutorService service = Executors.newFixedThreadPool(threads);<a name="line.80"></a>
+<span class="sourceLineNo">081</span>      for (int i = 0; i != threads; ++i) {<a name="line.81"></a>
+<span class="sourceLineNo">082</span>        service.execute(new Runnable() {<a name="line.82"></a>
+<span class="sourceLineNo">083</span>          @Override<a name="line.83"></a>
+<span class="sourceLineNo">084</span>          public void run() {<a name="line.84"></a>
+<span class="sourceLineNo">085</span>            for (int blockIndex = 0; blockIndex &lt; blocksPerThread || (!cache.isEvictionInProgress()); ++blockIndex) {<a name="line.85"></a>
+<span class="sourceLineNo">086</span>              CachedItem block = new CachedItem(hfileName, (int) blockSize, blockCount.getAndIncrement());<a name="line.86"></a>
+<span class="sourceLineNo">087</span>              boolean inMemory = Math.random() &gt; 0.5;<a name="line.87"></a>
+<span class="sourceLineNo">088</span>              cache.cacheBlock(block.cacheKey, block, inMemory);<a name="line.88"></a>
+<span class="sourceLineNo">089</span>            }<a name="line.89"></a>
+<span class="sourceLineNo">090</span>            cache.evictBlocksByHfileName(hfileName);<a name="line.90"></a>
+<span class="sourceLineNo">091</span>          }<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>      service.shutdown();<a name="line.94"></a>
+<span class="sourceLineNo">095</span>      // The test may fail here if the evict thread frees the blocks too fast<a name="line.95"></a>
+<span class="sourceLineNo">096</span>      service.awaitTermination(10, TimeUnit.MINUTES);<a name="line.96"></a>
+<span class="sourceLineNo">097</span>      Waiter.waitFor(conf, 10000, 100, new ExplainingPredicate&lt;Exception&gt;() {<a name="line.97"></a>
+<span class="sourceLineNo">098</span>        @Override<a name="line.98"></a>
+<span class="sourceLineNo">099</span>        public boolean evaluate() throws Exception {<a name="line.99"></a>
+<span class="sourceLineNo">100</span>          return cache.getBlockCount() == 0;<a name="line.100"></a>
+<span class="sourceLineNo">101</span>        }<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 String explainFailure() throws Exception {<a name="line.104"></a>
+<span class="sourceLineNo">105</span>          return "Cache block count failed to return to 0";<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>      assertEquals(0, cache.getBlockCount());<a name="line.108"></a>
+<span class="sourceLineNo">109</span>      assertEquals(cache.getOverhead(), cache.getCurrentSize());<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>  @Test<a name="line.112"></a>
+<span class="sourceLineNo">113</span>  public void testBackgroundEvictionThread() throws Exception {<a name="line.113"></a>
+<span class="sourceLineNo">114</span>    long maxSize = 100000;<a name="line.114"></a>
+<span class="sourceLineNo">115</span>    int numBlocks = 9;<a name="line.115"></a>
+<span class="sourceLineNo">116</span>    long blockSize = calculateBlockSizeDefault(maxSize, numBlocks);<a name="line.116"></a>
+<span class="sourceLineNo">117</span>    assertTrue("calculateBlockSize appears broken.", blockSize * numBlocks &lt;= maxSize);<a name="line.117"></a>
+<span class="sourceLineNo">118</span><a name="line.118"></a>
+<span class="sourceLineNo">119</span>    LruBlockCache cache = new LruBlockCache(maxSize,blockSize);<a name="line.119"></a>
+<span class="sourceLineNo">120</span>    EvictionThread evictionThread = cache.getEvictionThread();<a name="line.120"></a>
+<span class="sourceLineNo">121</span>    assertTrue(evictionThread != null);<a name="line.121"></a>
+<span class="sourceLineNo">122</span><a name="line.122"></a>
+<span class="sourceLineNo">123</span>    CachedItem[] blocks = generateFixedBlocks(numBlocks + 1, blockSize, "block");<a name="line.123"></a>
+<span class="sourceLineNo">124</span><a name="line.124"></a>
+<span class="sourceLineNo">125</span>    // Make sure eviction thread has entered run method<a name="line.125"></a>
+<span class="sourceLineNo">126</span>    while (!evictionThread.isEnteringRun()) {<a name="line.126"></a>
+<span class="sourceLineNo">127</span>      Thread.sleep(1);<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>    // Add all the blocks<a name="line.130"></a>
+<span class="sourceLineNo">131</span>    for (CachedItem block : blocks) {<a name="line.131"></a>
+<span class="sourceLineNo">132</span>      cache.cacheBlock(block.cacheKey, block);<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>    // wait until at least one eviction has run<a name="line.135"></a>
+<span class="sourceLineNo">136</span>    int n = 0;<a name="line.136"></a>
+<span class="sourceLineNo">137</span>    while(cache.getStats().getEvictionCount() == 0) {<a name="line.137"></a>
+<span class="sourceLineNo">138</span>      Thread.sleep(200);<a name="line.138"></a>
+<span class="sourceLineNo">139</span>      assertTrue("Eviction never happened.", n++ &lt; 20);<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>    // let cache stabilize<a name="line.142"></a>
+<span class="sourceLineNo">143</span>    // On some systems, the cache will run multiple evictions before it attains<a name="line.143"></a>
+<span class="sourceLineNo">144</span>    // steady-state. For instance, after populating the cache with 10 blocks,<a name="line.144"></a>
+<span class="sourceLineNo">145</span>    // the first eviction evicts a single block and then a second eviction<a name="line.145"></a>
+<span class="sourceLineNo">146</span>    // evicts another. I think this is due to the delta between minSize and<a name="line.146"></a>
+<span class="sourceLineNo">147</span>    // acceptableSize, combined with variance between object overhead on<a name="line.147"></a>
+<span class="sourceLineNo">148</span>    // different environments.<a name="line.148"></a>
+<span class="sourceLineNo">149</span>    n = 0;<a name="line.149"></a>
+<span class="sourceLineNo">150</span>    for (long prevCnt = 0 /* &lt; number of blocks added */,<a name="line.150"></a>
+<span class="sourceLineNo">151</span>              curCnt = cache.getBlockCount();<a name="line.151"></a>
+<span class="sourceLineNo">152</span>        prevCnt != curCnt; prevCnt = curCnt, curCnt = cache.getBlockCount()) {<a name="line.152"></a>
+<span class="sourceLineNo">153</span>      Thread.sleep(200);<a name="line.153"></a>
+<span class="sourceLineNo">154</span>      assertTrue("Cache never stabilized.", n++ &lt; 20);<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>    long evictionCount = cache.getStats().getEvictionCount();<a name="line.157"></a>
+<span class="sourceLineNo">158</span>    assertTrue(evictionCount &gt;= 1);<a name="line.158"></a>
+<span class="sourceLineNo">159</span>    System.out.println("Background Evictions run: " + evictionCount);<a name="line.159"></a>
+<span class="sourceLineNo">160</span>  }<a name="line.160"></a>
+<span class="sourceLineNo">161</span><a name="line.161"></a>
+<span class="sourceLineNo">162</span>  @Test<a name="line.162"></a>
+<span class="sourceLineNo">163</span>  public void testCacheSimple() throws Exception {<a name="line.163"></a>
+<span class="sourceLineNo">164</span><a name="line.164"></a>
+<span class="sourceLineNo">165</span>    long maxSize = 1000000;<a name="line.165"></a>
+<span class="sourceLineNo">166</span>    long blockSize = calculateBlockSizeDefault(maxSize, 101);<a name="line.166"></a>
+<span class="sourceLineNo">167</span><a name="line.167"></a>
+<span class="sourceLineNo">168</span>    LruBlockCache cache = new LruBlockCache(maxSize, blockSize);<a name="line.168"></a>
+<span class="sourceLineNo">169</span><a name="line.169"></a>
+<span class="sourceLineNo">170</span>    CachedItem [] blocks = generateRandomBlocks(100, blockSize);<a name="line.170"></a>
+<span class="sourceLineNo">171</span><a name="line.171"></a>
+<span class="sourceLineNo">172</span>    long expectedCacheSize = cache.heapSize();<a name="line.172"></a>
+<span class="sourceLineNo">173</span><a name="line.173"></a>
+<span class="sourceLineNo">174</span>    // Confirm empty<a name="line.174"></a>
+<span class="sourceLineNo">175</span>    for (CachedItem block : blocks) {<a name="line.175"></a>
+<span class="sourceLineNo">176</span>      assertTrue(cache.getBlock(block.cacheKey, true, false, true) == null);<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>    // Add blocks<a name="line.179"></a>
+<span class="sourceLineNo">180</span>    for (CachedItem block : blocks) {<a name="line.180"></a>
+<span class="sourceLineNo">181</span>      cache.cacheBlock(block.cacheKey, block);<a name="line.181"></a>
+<span class="sourceLineNo">182</span>      expectedCacheSize += block.cacheBlockHeapSize();<a name="line.182"></a>
+<span class="sourceLineNo">183</span>    }<a name="line.183"></a>
+<span class="sourceLineNo">184</span><a name="line.184"></a>
+<span class="sourceLineNo">185</span>    // Verify correctly calculated cache heap size<a name="line.185"></a>
+<span class="sourceLineNo">186</span>    assertEquals(expectedCacheSize, cache.heapSize());<a name="line.186"></a>
+<span class="sourceLineNo">187</span><a name="line.187"></a>
+<span class="sourceLineNo">188</span>    // Check if all blocks are properly cached and retrieved<a name="line.188"></a>
+<span class="sourceLineNo">189</span>    for (CachedItem block : blocks) {<a name="line.189"></a>
+<span class="sourceLineNo">190</span>      HeapSize buf = cache.getBlock(block.cacheKey, true, false, true);<a name="line.190"></a>
+<span class="sourceLineNo">191</span>      assertTrue(buf != null);<a name="line.191"></a>
+<span class="sourceLineNo">192</span>      assertEquals(buf.heapSize(), block.heapSize());<a name="line.192"></a>
+<span class="sourceLineNo">193</span>    }<a name="line.193"></a>
+<span class="sourceLineNo">194</span><a name="line.194"></a>
+<span class="sourceLineNo">195</span>    // Re-add same blocks and ensure nothing has changed<a name="line.195"></a>
+<span class="sourceLineNo">196</span>    long expectedBlockCount = cache.getBlockCount();<a name="line.196"></a>
+<span class="sourceLineNo">197</span>    for (CachedItem block : blocks) {<a name="line.197"></a>
+<span class="sourceLineNo">198</span>      cache.cacheBlock(block.cacheKey, block);<a name="line.198"></a>
+<span class="sourceLineNo">199</span>    }<a name="line.199"></a>
+<span class="sourceLineNo">200</span>    assertEquals(<a name="line.200"></a>
+<span class="sourceLineNo">201</span>            "Cache should ignore cache requests for blocks already in cache",<a name="line.201"></a>
+<span class="sourceLineNo">202</span>            expectedBlockCount, cache.getBlockCount());<a name="line.202"></a>
+<span class="sourceLineNo">203</span><a name="line.203"></a>
+<span class="sourceLineNo">204</span>    // Verify correctly calculated cache heap size<a name="line.204"></a>
+<span class="sourceLineNo">205</span>    assertEquals(expectedCacheSize, cache.heapSize());<a name="line.205"></a>
+<span class="sourceLineNo">206</span><a name="line.206"></a>
+<span class="sourceLineNo">207</span>    // Check if all blocks are properly cached and retrieved<a name="line.207"></a>
+<span class="sourceLineNo">208</span>    for (CachedItem block : blocks) {<a name="line.208"></a>
+<span class="sourceLineNo">209</span>      HeapSize buf = cache.getBlock(block.cacheKey, true, false, true);<a name="line.209"></a>
+<span class="sourceLineNo">210</span>      assertTrue(buf != null);<a name="line.210"></a>
+<span class="sourceLineNo">211</span>      assertEquals(buf.heapSize(), block.heapSize());<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>    // Expect no evictions<a name="line.214"></a>
+<span class="sourceLineNo">215</span>    assertEquals(0, cache.getStats().getEvictionCount());<a name="line.215"></a>
+<span class="sourceLineNo">216</span>    Thread t = new LruBlockCache.StatisticsThread(cache);<a name="line.216"></a>
+<span class="sourceLineNo">217</span>    t.start();<a name="line.217"></a>
+<span class="sourceLineNo">218</span>    t.join();<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>  @Test<a name="line.221"></a>
+<span class="sourceLineNo">222</span>  public void testCacheEvictionSimple() throws Exception {<a name="line.222"></a>
+<span class="sourceLineNo">223</span><a name="line.223"></a>
+<span class="sourceLineNo">224</span>    long maxSize = 100000;<a name="line.224"></a>
+<span class="sourceLineNo">225</span>    long blockSize = calculateBlockSizeDefault(maxSize, 10);<a name="line.225"></a>
+<span class="sourceLineNo">226</span><a name="line.226"></a>
+<span class="sourceLineNo">227</span>    LruBlockCache cache = new LruBlockCache(maxSize,blockSize,false);<a name="line.227"></a>
+<span class="sourceLineNo">228</span><a name="line.228"></a>
+<span class="sourceLineNo">229</span>    CachedItem [] blocks = generateFixedBlocks(10, blockSize, "block");<a name="line.229"></a>
+<span class="sourceLineNo">230</span><a name="line.230"></a>
+<span class="sourceLineNo">231</span>    long expectedCacheSize = cache.heapSize();<a name="line.231"></a>
+<span class="sourceLineNo">232</span><a name="line.232"></a>
+<span class="sourceLineNo">233</span>    // Add all the blocks<a name="line.233"></a>
+<span class="sourceLineNo">234</span>    for (CachedItem block : blocks) {<a name="line.234"></a>
+<span class="sourceLineNo">235</span>      cache.cacheBlock(block.cacheKey, block);<a name="line.235"></a>
+<span class="sourceLineNo">236</span>      expectedCacheSize += block.cacheBlockHeapSize();<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>    // A single eviction run should have occurred<a name="line.239"></a>
+<span class="sourceLineNo">240</span>    assertEquals(1, cache.getStats().getEvictionCount());<a name="line.240"></a>
+<span class="sourceLineNo">241</span><a name="line.241"></a>
+<span class="sourceLineNo">242</span>    // Our expected size overruns acceptable limit<a name="line.242"></a>
+<span class="sourceLineNo">243</span>    assertTrue(expectedCacheSize &gt;<a name="line.243"></a>
+<span class="sourceLineNo">244</span>      (maxSize * LruBlockCache.DEFAULT_ACCEPTABLE_FACTOR));<a name="line.244"></a>
+<span class="sourceLineNo">245</span><a name="line.245"></a>
+<span class="sourceLineNo">246</span>    // But the cache did not grow beyond max<a name="line.246"></a>
+<span class="sourceLineNo">247</span>    assertTrue(cache.heapSize() &lt; maxSize);<a name="line.247"></a>
+<span class="sourceLineNo">248</span><a name="line.248"></a>
+<span class="sourceLineNo">249</span>    // And is still below the acceptable limit<a name="line.249"></a>
+<span class="sourceLineNo">250</span>    assertTrue(cache.heapSize() &lt;<a name="line.250"></a>
+<span class="sourceLineNo">251</span>        (maxSize * LruBlockCache.DEFAULT_ACCEPTABLE_FACTOR));<a name="line.251"></a>
+<span class="sourceLineNo">252</span><a name="line.252"></a>
+<span class="sourceLineNo">253</span>    // All blocks except block 0  should be in the cache<a name="line.253"></a>
+<span class="sourceLineNo">254</span>    assertTrue(cache.getBlock(blocks[0].cacheKey, true, false, true) == null);<a name="line.254"></a>
+<span class="sourceLineNo">255</span>    for(int i=1;i&lt;blocks.length;i++) {<a name="line.255"></a>
+<span class="sourceLineNo">256</span>      assertEquals(cache.getBlock(blocks[i].cacheKey, true, false, true),<a name="line.256"></a>
+<span class="sourceLineNo">257</span>          blocks[i]);<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>  @Test<a name="line.261"></a>
+<span class="sourceLineNo">262</span>  public void testCacheEvictionTwoPriorities() throws Exception {<a name="line.262"></a>
+<span class="sourceLineNo">263</span><a name="line.263"></a>
+<span class="sourceLineNo">264</span>    long maxSize = 100000;<a name="line.264"></a>
+<span class="sourceLineNo">265</span>    long blockSize = calculateBlockSizeDefault(maxSize, 10);<a name="line.265"></a>
+<span class="sourceLineNo">266</span><a name="line.266"></a>
+<span class="sourceLineNo">267</span>    LruBlockCache cache = new LruBlockCache(maxSize,blockSize,false);<a name="line.267"></a>
+<span class="sourceLineNo">268</span><a name="line.268"></a>
+<span class="sourceLineNo">269</span>    CachedItem [] singleBlocks = generateFixedBlocks(5, 10000, "single");<a name="line.269"></a>
+<span class="sourceLineNo">270</span>    CachedItem [] multiBlocks = generateFixedBlocks(5, 10000, "multi");<a name="line.270"></a>
+<span class="sourceLineNo">271</span><a name="line.271"></a>
+<span class="sourceLineNo">272</span>    long expectedCacheSize = cache.heapSize();<a name="line.272"></a>
+<span class="sourceLineNo">273</span><a name="line.273"></a>
+<span class="sourceLineNo">274</span>    // Add and get the multi blocks<a name="line.274"></a>
+<span class="sourceLineNo">275</span>    for (CachedItem block : multiBlocks) {<a name="line.275"></a>
+<span class="sourceLineNo">276</span>      cache.cacheBlock(block.cacheKey, block);<a name="line.276"></a>
+<span class="sourceLineNo">277</span>      expectedCacheSize += block.cacheBlockHeapSize();<a name="line.277"></a>
+<span class="sourceLineNo">278</span>      assertEquals(cache.getBlock(block.cacheKey, true, false, true), block);<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>    // Add the single blocks (no get)<a name="line.281"></a>
+<span class="sourceLineNo">282</span>    for (CachedItem block : singleBlocks) {<a name="line.282"></a>
+<span class="sourceLineNo">283</span>      cache.cacheBlock(block.cacheKey, block);<a name="line.283"></a>
+<span class="sourceLineNo">284</span>      expectedCacheSize += block.heapSize();<a name="line.284"></a>
+<span class="sourceLineNo">285</span>    }<a name="line.285"></a>
+<span class="sourceLineNo">286</span><a name="line.286"></a>
+<span class="sourceLineNo">287</span>    // A single eviction run should have occurred<a name="line.287"></a>
+<span class="sourceLineNo">288</span>    assertEquals(1, cache.getStats().getEvictionCount());<a name="line.288"></a>
+<span class="sourceLineNo">289</span><a name="line.289"></a>
+<span class="sourceLineNo">290</span>    // We expect two entries evicted<a name="line.290"></a>
+<span class="sourceLineNo">291</span>    assertEquals(2, cache.getStats().getEvictedCount());<a name="line.291"></a>
+<span class="sourceLineNo">292</span><a name="line.292"></a>
+<span class="sourceLineNo">293</span>    // Our expected size overruns acceptable limit<a name="line.293"></a>
+<span class="sourceLineNo">294</span>    assertTrue(expectedCacheSize &gt;<a name="line.294"></a>
+<span class="sourceLineNo">295</span>      (maxSize * LruBlockCache.DEFAULT_ACCEPTABLE_FACTOR));<a name="line.295"></a>
+<span class="sourceLineNo">296</span><a name="line.296"></a>
+<span class="sourceLineNo">297</span>    // But the cache did not grow beyond max<a name="line.297"></a>
+<span class="sourceLineNo">298</span>    assertTrue(cache.heapSize() &lt;= maxSize);<a name="line.298"></a>
+<span class="sourceLineNo">299</span><a name="line.299"></a>
+<span class="sourceLineNo">300</span>    // And is now below the acceptable limit<a name="line.300"></a>
+<span class="sourceLineNo">301</span>    assertTrue(cache.heapSize() &lt;=<a name="line.301"></a>
+<span class="sourceLineNo">302</span>        (maxSize * LruBlockCache.DEFAULT_ACCEPTABLE_FACTOR));<a name="line.302"></a>
+<span class="sourceLineNo">303</span><a name="line.303"></a>
+<span class="sourceLineNo">304</span>    // We expect fairness across the two priorities.<a name="line.304"></a>
+<span class="sourceLineNo">305</span>    // This test makes multi go barely over its limit, in-memory<a name="line.305"></a>
+<span class="sourceLineNo">306</span>    // empty, and the rest in single.  Two single evictions and<a name="line.306"></a>
+<span class="sourceLineNo">307</span>    // one multi eviction expected.<a name="line.307"></a>
+<span class="sourceLineNo">308</span>    assertTrue(cache.getBlock(singleBlocks[0].cacheKey, true, false, true) == null);<a name="line.308"></a>
+<span class="sourceLineNo">309</span>    assertTrue(cache.getBlock(multiBlocks[0].cacheKey, true, false, true) == null);<a name="line.309"></a>
+<span class="sourceLineNo">310</span><a name="line.310"></a>
+<span class="sourceLineNo">311</span>    // And all others to be cached<a name="line.311"></a>
+<span class="sourceLineNo">312</span>    for(int i=1;i&lt;4;i++) {<a name="line.312"></a>
+<span class="sourceLineNo">313</span>      assertEquals(cache.getBlock(singleBlocks[i].cacheKey, true, false, true),<a name="line.313"></a>
+<span class="sourceLineNo">314</span>          singleBlocks[i]);<a name="line.314"></a>
+<span class="sourceLineNo">315</span>      assertEquals(cache.getBlock(multiBlocks[i].cacheKey, true, false, true),<a name="line.315"></a>
+<span class="sourceLineNo">316</span>          multiBlocks[i]);<a name="line.316"></a>
+<span class="sourceLineNo">317</span>    }<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>  @Test<a name="line.320"></a>
+<span class="sourceLineNo">321</span>  public void testCacheEvictionThreePriorities() throws Exception {<a name="line.321"></a>
+<span class="sourceLineNo">322</span><a name="line.322"></a>
+<span class="sourceLineNo">323</span>    long maxSize = 100000;<a name="line.323"></a>
+<span class="sourceLineNo">324</span>    long blockSize = calculateBlockSize(maxSize, 10);<a name="line.324"></a>
+<span class="sourceLineNo">325</span><a name="line.325"></a>
+<span class="sourceLineNo">326</span>    LruBlockCache cache = new LruBlockCache(maxSize, blockSize, false,<a name="line.326"></a>
+<span class="sourceLineNo">327</span>        (i

<TRUNCATED>

[33/50] hbase-site git commit: Published site at 26babcf013de696b899d76a3c39434b794440d8d.

Posted by gi...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.State.html
----------------------------------------------------------------------
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.State.html b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.State.html
index 97ceefd..b7b4236 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.State.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.State.html
@@ -103,8 +103,8 @@
 <span class="sourceLineNo">095</span> * Caches cache whole blocks with trailing checksums if any. We then tag on some metadata, the<a name="line.95"></a>
 <span class="sourceLineNo">096</span> * content of BLOCK_METADATA_SPACE which will be flag on if we are doing 'hbase'<a name="line.96"></a>
 <span class="sourceLineNo">097</span> * checksums and then the offset into the file which is needed when we re-make a cache key<a name="line.97"></a>
-<span class="sourceLineNo">098</span> * when we return the block to the cache as 'done'. See {@link Cacheable#serialize(ByteBuffer)} and<a name="line.98"></a>
-<span class="sourceLineNo">099</span> * {@link Cacheable#getDeserializer()}.<a name="line.99"></a>
+<span class="sourceLineNo">098</span> * when we return the block to the cache as 'done'.<a name="line.98"></a>
+<span class="sourceLineNo">099</span> * See {@link Cacheable#serialize(ByteBuffer, boolean)} and {@link Cacheable#getDeserializer()}.<a name="line.99"></a>
 <span class="sourceLineNo">100</span> *<a name="line.100"></a>
 <span class="sourceLineNo">101</span> * &lt;p&gt;TODO: Should we cache the checksums? Down in Writer#getBlockForCaching(CacheConfig) where<a name="line.101"></a>
 <span class="sourceLineNo">102</span> * we make a block to cache-on-write, there is an attempt at turning off checksums. This is not the<a name="line.102"></a>
@@ -333,1579 +333,1579 @@
 <span class="sourceLineNo">325</span>   * Creates a new {@link HFile} block from the given fields. This constructor<a name="line.325"></a>
 <span class="sourceLineNo">326</span>   * is used only while writing blocks and caching,<a name="line.326"></a>
 <span class="sourceLineNo">327</span>   * and is sitting in a byte buffer and we want to stuff the block into cache.<a name="line.327"></a>
-<span class="sourceLineNo">328</span>   * See {@link Writer#getBlockForCaching(CacheConfig)}.<a name="line.328"></a>
-<span class="sourceLineNo">329</span>   *<a name="line.329"></a>
-<span class="sourceLineNo">330</span>   * &lt;p&gt;TODO: The caller presumes no checksumming<a name="line.330"></a>
-<span class="sourceLineNo">331</span>   * required of this block instance since going into cache; checksum already verified on<a name="line.331"></a>
-<span class="sourceLineNo">332</span>   * underlying block data pulled in from filesystem. Is that correct? What if cache is SSD?<a name="line.332"></a>
-<span class="sourceLineNo">333</span>   *<a name="line.333"></a>
-<span class="sourceLineNo">334</span>   * @param blockType the type of this block, see {@link BlockType}<a name="line.334"></a>
-<span class="sourceLineNo">335</span>   * @param onDiskSizeWithoutHeader see {@link #onDiskSizeWithoutHeader}<a name="line.335"></a>
-<span class="sourceLineNo">336</span>   * @param uncompressedSizeWithoutHeader see {@link #uncompressedSizeWithoutHeader}<a name="line.336"></a>
-<span class="sourceLineNo">337</span>   * @param prevBlockOffset see {@link #prevBlockOffset}<a name="line.337"></a>
-<span class="sourceLineNo">338</span>   * @param b block header ({@link HConstants#HFILEBLOCK_HEADER_SIZE} bytes)<a name="line.338"></a>
-<span class="sourceLineNo">339</span>   * @param fillHeader when true, write the first 4 header fields into passed buffer.<a name="line.339"></a>
-<span class="sourceLineNo">340</span>   * @param offset the file offset the block was read from<a name="line.340"></a>
-<span class="sourceLineNo">341</span>   * @param onDiskDataSizeWithHeader see {@link #onDiskDataSizeWithHeader}<a name="line.341"></a>
-<span class="sourceLineNo">342</span>   * @param fileContext HFile meta data<a name="line.342"></a>
-<span class="sourceLineNo">343</span>   */<a name="line.343"></a>
-<span class="sourceLineNo">344</span>  HFileBlock(BlockType blockType, int onDiskSizeWithoutHeader, int uncompressedSizeWithoutHeader,<a name="line.344"></a>
-<span class="sourceLineNo">345</span>      long prevBlockOffset, ByteBuffer b, boolean fillHeader, long offset,<a name="line.345"></a>
-<span class="sourceLineNo">346</span>      final int nextBlockOnDiskSize, int onDiskDataSizeWithHeader, HFileContext fileContext) {<a name="line.346"></a>
-<span class="sourceLineNo">347</span>    init(blockType, onDiskSizeWithoutHeader, uncompressedSizeWithoutHeader,<a name="line.347"></a>
-<span class="sourceLineNo">348</span>        prevBlockOffset, offset, onDiskDataSizeWithHeader, nextBlockOnDiskSize, fileContext);<a name="line.348"></a>
-<span class="sourceLineNo">349</span>    this.buf = new SingleByteBuff(b);<a name="line.349"></a>
-<span class="sourceLineNo">350</span>    if (fillHeader) {<a name="line.350"></a>
-<span class="sourceLineNo">351</span>      overwriteHeader();<a name="line.351"></a>
-<span class="sourceLineNo">352</span>    }<a name="line.352"></a>
-<span class="sourceLineNo">353</span>    this.buf.rewind();<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>  /**<a name="line.356"></a>
-<span class="sourceLineNo">357</span>   * Creates a block from an existing buffer starting with a header. Rewinds<a name="line.357"></a>
-<span class="sourceLineNo">358</span>   * and takes ownership of the buffer. By definition of rewind, ignores the<a name="line.358"></a>
-<span class="sourceLineNo">359</span>   * buffer position, but if you slice the buffer beforehand, it will rewind<a name="line.359"></a>
-<span class="sourceLineNo">360</span>   * to that point.<a name="line.360"></a>
-<span class="sourceLineNo">361</span>   * @param buf Has header, content, and trailing checksums if present.<a name="line.361"></a>
-<span class="sourceLineNo">362</span>   */<a name="line.362"></a>
-<span class="sourceLineNo">363</span>  HFileBlock(ByteBuff buf, boolean usesHBaseChecksum, MemoryType memType, final long offset,<a name="line.363"></a>
-<span class="sourceLineNo">364</span>      final int nextBlockOnDiskSize, HFileContext fileContext) throws IOException {<a name="line.364"></a>
-<span class="sourceLineNo">365</span>    buf.rewind();<a name="line.365"></a>
-<span class="sourceLineNo">366</span>    final BlockType blockType = BlockType.read(buf);<a name="line.366"></a>
-<span class="sourceLineNo">367</span>    final int onDiskSizeWithoutHeader = buf.getInt(Header.ON_DISK_SIZE_WITHOUT_HEADER_INDEX);<a name="line.367"></a>
-<span class="sourceLineNo">368</span>    final int uncompressedSizeWithoutHeader =<a name="line.368"></a>
-<span class="sourceLineNo">369</span>        buf.getInt(Header.UNCOMPRESSED_SIZE_WITHOUT_HEADER_INDEX);<a name="line.369"></a>
-<span class="sourceLineNo">370</span>    final long prevBlockOffset = buf.getLong(Header.PREV_BLOCK_OFFSET_INDEX);<a name="line.370"></a>
-<span class="sourceLineNo">371</span>    // This constructor is called when we deserialize a block from cache and when we read a block in<a name="line.371"></a>
-<span class="sourceLineNo">372</span>    // from the fs. fileCache is null when deserialized from cache so need to make up one.<a name="line.372"></a>
-<span class="sourceLineNo">373</span>    HFileContextBuilder fileContextBuilder = fileContext != null?<a name="line.373"></a>
-<span class="sourceLineNo">374</span>        new HFileContextBuilder(fileContext): new HFileContextBuilder();<a name="line.374"></a>
-<span class="sourceLineNo">375</span>    fileContextBuilder.withHBaseCheckSum(usesHBaseChecksum);<a name="line.375"></a>
-<span class="sourceLineNo">376</span>    int onDiskDataSizeWithHeader;<a name="line.376"></a>
-<span class="sourceLineNo">377</span>    if (usesHBaseChecksum) {<a name="line.377"></a>
-<span class="sourceLineNo">378</span>      byte checksumType = buf.get(Header.CHECKSUM_TYPE_INDEX);<a name="line.378"></a>
-<span class="sourceLineNo">379</span>      int bytesPerChecksum = buf.getInt(Header.BYTES_PER_CHECKSUM_INDEX);<a name="line.379"></a>
-<span class="sourceLineNo">380</span>      onDiskDataSizeWithHeader = buf.getInt(Header.ON_DISK_DATA_SIZE_WITH_HEADER_INDEX);<a name="line.380"></a>
-<span class="sourceLineNo">381</span>      // Use the checksum type and bytes per checksum from header, not from filecontext.<a name="line.381"></a>
-<span class="sourceLineNo">382</span>      fileContextBuilder.withChecksumType(ChecksumType.codeToType(checksumType));<a name="line.382"></a>
-<span class="sourceLineNo">383</span>      fileContextBuilder.withBytesPerCheckSum(bytesPerChecksum);<a name="line.383"></a>
-<span class="sourceLineNo">384</span>    } else {<a name="line.384"></a>
-<span class="sourceLineNo">385</span>      fileContextBuilder.withChecksumType(ChecksumType.NULL);<a name="line.385"></a>
-<span class="sourceLineNo">386</span>      fileContextBuilder.withBytesPerCheckSum(0);<a name="line.386"></a>
-<span class="sourceLineNo">387</span>      // Need to fix onDiskDataSizeWithHeader; there are not checksums after-block-data<a name="line.387"></a>
-<span class="sourceLineNo">388</span>      onDiskDataSizeWithHeader = onDiskSizeWithoutHeader + headerSize(usesHBaseChecksum);<a name="line.388"></a>
-<span class="sourceLineNo">389</span>    }<a name="line.389"></a>
-<span class="sourceLineNo">390</span>    fileContext = fileContextBuilder.build();<a name="line.390"></a>
-<span class="sourceLineNo">391</span>    assert usesHBaseChecksum == fileContext.isUseHBaseChecksum();<a name="line.391"></a>
-<span class="sourceLineNo">392</span>    init(blockType, onDiskSizeWithoutHeader, uncompressedSizeWithoutHeader,<a name="line.392"></a>
-<span class="sourceLineNo">393</span>        prevBlockOffset, offset, onDiskDataSizeWithHeader, nextBlockOnDiskSize, fileContext);<a name="line.393"></a>
-<span class="sourceLineNo">394</span>    this.memType = memType;<a name="line.394"></a>
-<span class="sourceLineNo">395</span>    this.offset = offset;<a name="line.395"></a>
-<span class="sourceLineNo">396</span>    this.buf = buf;<a name="line.396"></a>
-<span class="sourceLineNo">397</span>    this.buf.rewind();<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>  /**<a name="line.400"></a>
-<span class="sourceLineNo">401</span>   * Called from constructors.<a name="line.401"></a>
-<span class="sourceLineNo">402</span>   */<a name="line.402"></a>
-<span class="sourceLineNo">403</span>  private void init(BlockType blockType, int onDiskSizeWithoutHeader,<a name="line.403"></a>
-<span class="sourceLineNo">404</span>      int uncompressedSizeWithoutHeader, long prevBlockOffset,<a name="line.404"></a>
-<span class="sourceLineNo">405</span>      long offset, int onDiskDataSizeWithHeader, final int nextBlockOnDiskSize,<a name="line.405"></a>
-<span class="sourceLineNo">406</span>      HFileContext fileContext) {<a name="line.406"></a>
-<span class="sourceLineNo">407</span>    this.blockType = blockType;<a name="line.407"></a>
-<span class="sourceLineNo">408</span>    this.onDiskSizeWithoutHeader = onDiskSizeWithoutHeader;<a name="line.408"></a>
-<span class="sourceLineNo">409</span>    this.uncompressedSizeWithoutHeader = uncompressedSizeWithoutHeader;<a name="line.409"></a>
-<span class="sourceLineNo">410</span>    this.prevBlockOffset = prevBlockOffset;<a name="line.410"></a>
-<span class="sourceLineNo">411</span>    this.offset = offset;<a name="line.411"></a>
-<span class="sourceLineNo">412</span>    this.onDiskDataSizeWithHeader = onDiskDataSizeWithHeader;<a name="line.412"></a>
-<span class="sourceLineNo">413</span>    this.nextBlockOnDiskSize = nextBlockOnDiskSize;<a name="line.413"></a>
-<span class="sourceLineNo">414</span>    this.fileContext = fileContext;<a name="line.414"></a>
-<span class="sourceLineNo">415</span>  }<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">418</span>   * Parse total on disk size including header and checksum.<a name="line.418"></a>
-<span class="sourceLineNo">419</span>   * @param headerBuf Header ByteBuffer. Presumed exact size of header.<a name="line.419"></a>
-<span class="sourceLineNo">420</span>   * @param verifyChecksum true if checksum verification is in use.<a name="line.420"></a>
-<span class="sourceLineNo">421</span>   * @return Size of the block with header included.<a name="line.421"></a>
-<span class="sourceLineNo">422</span>   */<a name="line.422"></a>
-<span class="sourceLineNo">423</span>  private static int getOnDiskSizeWithHeader(final ByteBuffer headerBuf,<a name="line.423"></a>
-<span class="sourceLineNo">424</span>      boolean verifyChecksum) {<a name="line.424"></a>
-<span class="sourceLineNo">425</span>    return headerBuf.getInt(Header.ON_DISK_SIZE_WITHOUT_HEADER_INDEX) +<a name="line.425"></a>
-<span class="sourceLineNo">426</span>      headerSize(verifyChecksum);<a name="line.426"></a>
-<span class="sourceLineNo">427</span>  }<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>   * @return the on-disk size of the next block (including the header size and any checksums if<a name="line.430"></a>
-<span class="sourceLineNo">431</span>   * present) read by peeking into the next block's header; use as a hint when doing<a name="line.431"></a>
-<span class="sourceLineNo">432</span>   * a read of the next block when scanning or running over a file.<a name="line.432"></a>
-<span class="sourceLineNo">433</span>   */<a name="line.433"></a>
-<span class="sourceLineNo">434</span>  int getNextBlockOnDiskSize() {<a name="line.434"></a>
-<span class="sourceLineNo">435</span>    return nextBlockOnDiskSize;<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>  @Override<a name="line.438"></a>
-<span class="sourceLineNo">439</span>  public BlockType getBlockType() {<a name="line.439"></a>
-<span class="sourceLineNo">440</span>    return blockType;<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>  /** @return get data block encoding id that was used to encode this block */<a name="line.443"></a>
-<span class="sourceLineNo">444</span>  short getDataBlockEncodingId() {<a name="line.444"></a>
-<span class="sourceLineNo">445</span>    if (blockType != BlockType.ENCODED_DATA) {<a name="line.445"></a>
-<span class="sourceLineNo">446</span>      throw new IllegalArgumentException("Querying encoder ID of a block " +<a name="line.446"></a>
-<span class="sourceLineNo">447</span>          "of type other than " + BlockType.ENCODED_DATA + ": " + blockType);<a name="line.447"></a>
-<span class="sourceLineNo">448</span>    }<a name="line.448"></a>
-<span class="sourceLineNo">449</span>    return buf.getShort(headerSize());<a name="line.449"></a>
-<span class="sourceLineNo">450</span>  }<a name="line.450"></a>
-<span class="sourceLineNo">451</span><a name="line.451"></a>
-<span class="sourceLineNo">452</span>  /**<a name="line.452"></a>
-<span class="sourceLineNo">453</span>   * @return the on-disk size of header + data part + checksum.<a name="line.453"></a>
-<span class="sourceLineNo">454</span>   */<a name="line.454"></a>
-<span class="sourceLineNo">455</span>  public int getOnDiskSizeWithHeader() {<a name="line.455"></a>
-<span class="sourceLineNo">456</span>    return onDiskSizeWithoutHeader + headerSize();<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>   * @return the on-disk size of the data part + checksum (header excluded).<a name="line.460"></a>
-<span class="sourceLineNo">461</span>   */<a name="line.461"></a>
-<span class="sourceLineNo">462</span>  int getOnDiskSizeWithoutHeader() {<a name="line.462"></a>
-<span class="sourceLineNo">463</span>    return onDiskSizeWithoutHeader;<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>  /**<a name="line.466"></a>
-<span class="sourceLineNo">467</span>   * @return the uncompressed size of data part (header and checksum excluded).<a name="line.467"></a>
-<span class="sourceLineNo">468</span>   */<a name="line.468"></a>
-<span class="sourceLineNo">469</span>   int getUncompressedSizeWithoutHeader() {<a name="line.469"></a>
-<span class="sourceLineNo">470</span>    return uncompressedSizeWithoutHeader;<a name="line.470"></a>
-<span class="sourceLineNo">471</span>  }<a name="line.471"></a>
-<span class="sourceLineNo">472</span><a name="line.472"></a>
-<span class="sourceLineNo">473</span>  /**<a name="line.473"></a>
-<span class="sourceLineNo">474</span>   * @return the offset of the previous block of the same type in the file, or<a name="line.474"></a>
-<span class="sourceLineNo">475</span>   *         -1 if unknown<a name="line.475"></a>
-<span class="sourceLineNo">476</span>   */<a name="line.476"></a>
-<span class="sourceLineNo">477</span>  long getPrevBlockOffset() {<a name="line.477"></a>
-<span class="sourceLineNo">478</span>    return prevBlockOffset;<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>   * Rewinds {@code buf} and writes first 4 header fields. {@code buf} position<a name="line.482"></a>
-<span class="sourceLineNo">483</span>   * is modified as side-effect.<a name="line.483"></a>
-<span class="sourceLineNo">484</span>   */<a name="line.484"></a>
-<span class="sourceLineNo">485</span>  private void overwriteHeader() {<a name="line.485"></a>
-<span class="sourceLineNo">486</span>    buf.rewind();<a name="line.486"></a>
-<span class="sourceLineNo">487</span>    blockType.write(buf);<a name="line.487"></a>
-<span class="sourceLineNo">488</span>    buf.putInt(onDiskSizeWithoutHeader);<a name="line.488"></a>
-<span class="sourceLineNo">489</span>    buf.putInt(uncompressedSizeWithoutHeader);<a name="line.489"></a>
-<span class="sourceLineNo">490</span>    buf.putLong(prevBlockOffset);<a name="line.490"></a>
-<span class="sourceLineNo">491</span>    if (this.fileContext.isUseHBaseChecksum()) {<a name="line.491"></a>
-<span class="sourceLineNo">492</span>      buf.put(fileContext.getChecksumType().getCode());<a name="line.492"></a>
-<span class="sourceLineNo">493</span>      buf.putInt(fileContext.getBytesPerChecksum());<a name="line.493"></a>
-<span class="sourceLineNo">494</span>      buf.putInt(onDiskDataSizeWithHeader);<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>  /**<a name="line.498"></a>
-<span class="sourceLineNo">499</span>   * Returns a buffer that does not include the header or checksum.<a name="line.499"></a>
-<span class="sourceLineNo">500</span>   *<a name="line.500"></a>
-<span class="sourceLineNo">501</span>   * @return the buffer with header skipped and checksum omitted.<a name="line.501"></a>
-<span class="sourceLineNo">502</span>   */<a name="line.502"></a>
-<span class="sourceLineNo">503</span>  public ByteBuff getBufferWithoutHeader() {<a name="line.503"></a>
-<span class="sourceLineNo">504</span>    ByteBuff dup = getBufferReadOnly();<a name="line.504"></a>
-<span class="sourceLineNo">505</span>    // Now set it up so Buffer spans content only -- no header or no checksums.<a name="line.505"></a>
-<span class="sourceLineNo">506</span>    return dup.position(headerSize()).limit(buf.limit() - totalChecksumBytes()).slice();<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 a read-only duplicate of the buffer this block stores internally ready to be read.<a name="line.510"></a>
-<span class="sourceLineNo">511</span>   * Clients must not modify the buffer object though they may set position and limit on the<a name="line.511"></a>
-<span class="sourceLineNo">512</span>   * returned buffer since we pass back a duplicate. This method has to be public because it is used<a name="line.512"></a>
-<span class="sourceLineNo">513</span>   * in {@link CompoundBloomFilter} to avoid object creation on every Bloom<a name="line.513"></a>
-<span class="sourceLineNo">514</span>   * filter lookup, but has to be used with caution. Buffer holds header, block content,<a name="line.514"></a>
-<span class="sourceLineNo">515</span>   * and any follow-on checksums if present.<a name="line.515"></a>
-<span class="sourceLineNo">516</span>   *<a name="line.516"></a>
-<span class="sourceLineNo">517</span>   * @return the buffer of this block for read-only operations<a name="line.517"></a>
-<span class="sourceLineNo">518</span>   */<a name="line.518"></a>
-<span class="sourceLineNo">519</span>  public ByteBuff getBufferReadOnly() {<a name="line.519"></a>
-<span class="sourceLineNo">520</span>    // TODO: ByteBuf does not support asReadOnlyBuffer(). Fix.<a name="line.520"></a>
-<span class="sourceLineNo">521</span>    ByteBuff dup = this.buf.duplicate();<a name="line.521"></a>
-<span class="sourceLineNo">522</span>    assert dup.position() == 0;<a name="line.522"></a>
-<span class="sourceLineNo">523</span>    return dup;<a name="line.523"></a>
-<span class="sourceLineNo">524</span>  }<a name="line.524"></a>
-<span class="sourceLineNo">525</span><a name="line.525"></a>
-<span class="sourceLineNo">526</span>  @VisibleForTesting<a name="line.526"></a>
-<span class="sourceLineNo">527</span>  private void sanityCheckAssertion(long valueFromBuf, long valueFromField,<a name="line.527"></a>
-<span class="sourceLineNo">528</span>      String fieldName) throws IOException {<a name="line.528"></a>
-<span class="sourceLineNo">529</span>    if (valueFromBuf != valueFromField) {<a name="line.529"></a>
-<span class="sourceLineNo">530</span>      throw new AssertionError(fieldName + " in the buffer (" + valueFromBuf<a name="line.530"></a>
-<span class="sourceLineNo">531</span>          + ") is different from that in the field (" + valueFromField + ")");<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>  @VisibleForTesting<a name="line.535"></a>
-<span class="sourceLineNo">536</span>  private void sanityCheckAssertion(BlockType valueFromBuf, BlockType valueFromField)<a name="line.536"></a>
-<span class="sourceLineNo">537</span>      throws IOException {<a name="line.537"></a>
-<span class="sourceLineNo">538</span>    if (valueFromBuf != valueFromField) {<a name="line.538"></a>
-<span class="sourceLineNo">539</span>      throw new IOException("Block type stored in the buffer: " +<a name="line.539"></a>
-<span class="sourceLineNo">540</span>        valueFromBuf + ", block type field: " + valueFromField);<a name="line.540"></a>
-<span class="sourceLineNo">541</span>    }<a name="line.541"></a>
-<span class="sourceLineNo">542</span>  }<a name="line.542"></a>
-<span class="sourceLineNo">543</span><a name="line.543"></a>
-<span class="sourceLineNo">544</span>  /**<a name="line.544"></a>
-<span class="sourceLineNo">545</span>   * Checks if the block is internally consistent, i.e. the first<a name="line.545"></a>
-<span class="sourceLineNo">546</span>   * {@link HConstants#HFILEBLOCK_HEADER_SIZE} bytes of the buffer contain a<a name="line.546"></a>
-<span class="sourceLineNo">547</span>   * valid header consistent with the fields. Assumes a packed block structure.<a name="line.547"></a>
-<span class="sourceLineNo">548</span>   * This function is primary for testing and debugging, and is not<a name="line.548"></a>
-<span class="sourceLineNo">549</span>   * thread-safe, because it alters the internal buffer pointer.<a name="line.549"></a>
-<span class="sourceLineNo">550</span>   * Used by tests only.<a name="line.550"></a>
-<span class="sourceLineNo">551</span>   */<a name="line.551"></a>
-<span class="sourceLineNo">552</span>  @VisibleForTesting<a name="line.552"></a>
-<span class="sourceLineNo">553</span>  void sanityCheck() throws IOException {<a name="line.553"></a>
-<span class="sourceLineNo">554</span>    // Duplicate so no side-effects<a name="line.554"></a>
-<span class="sourceLineNo">555</span>    ByteBuff dup = this.buf.duplicate().rewind();<a name="line.555"></a>
-<span class="sourceLineNo">556</span>    sanityCheckAssertion(BlockType.read(dup), blockType);<a name="line.556"></a>
-<span class="sourceLineNo">557</span><a name="line.557"></a>
-<span class="sourceLineNo">558</span>    sanityCheckAssertion(dup.getInt(), onDiskSizeWithoutHeader, "onDiskSizeWithoutHeader");<a name="line.558"></a>
-<span class="sourceLineNo">559</span><a name="line.559"></a>
-<span class="sourceLineNo">560</span>    sanityCheckAssertion(dup.getInt(), uncompressedSizeWithoutHeader,<a name="line.560"></a>
-<span class="sourceLineNo">561</span>        "uncompressedSizeWithoutHeader");<a name="line.561"></a>
-<span class="sourceLineNo">562</span><a name="line.562"></a>
-<span class="sourceLineNo">563</span>    sanityCheckAssertion(dup.getLong(), prevBlockOffset, "prevBlockOffset");<a name="line.563"></a>
-<span class="sourceLineNo">564</span>    if (this.fileContext.isUseHBaseChecksum()) {<a name="line.564"></a>
-<span class="sourceLineNo">565</span>      sanityCheckAssertion(dup.get(), this.fileContext.getChecksumType().getCode(), "checksumType");<a name="line.565"></a>
-<span class="sourceLineNo">566</span>      sanityCheckAssertion(dup.getInt(), this.fileContext.getBytesPerChecksum(),<a name="line.566"></a>
-<span class="sourceLineNo">567</span>          "bytesPerChecksum");<a name="line.567"></a>
-<span class="sourceLineNo">568</span>      sanityCheckAssertion(dup.getInt(), onDiskDataSizeWithHeader, "onDiskDataSizeWithHeader");<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>    int cksumBytes = totalChecksumBytes();<a name="line.571"></a>
-<span class="sourceLineNo">572</span>    int expectedBufLimit = onDiskDataSizeWithHeader + cksumBytes;<a name="line.572"></a>
-<span class="sourceLineNo">573</span>    if (dup.limit() != expectedBufLimit) {<a name="line.573"></a>
-<span class="sourceLineNo">574</span>      throw new AssertionError("Expected limit " + expectedBufLimit + ", got " + dup.limit());<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>    // We might optionally allocate HFILEBLOCK_HEADER_SIZE more bytes to read the next<a name="line.577"></a>
-<span class="sourceLineNo">578</span>    // block's header, so there are two sensible values for buffer capacity.<a name="line.578"></a>
-<span class="sourceLineNo">579</span>    int hdrSize = headerSize();<a name="line.579"></a>
-<span class="sourceLineNo">580</span>    if (dup.capacity() != expectedBufLimit &amp;&amp; dup.capacity() != expectedBufLimit + hdrSize) {<a name="line.580"></a>
-<span class="sourceLineNo">581</span>      throw new AssertionError("Invalid buffer capacity: " + dup.capacity() +<a name="line.581"></a>
-<span class="sourceLineNo">582</span>          ", expected " + expectedBufLimit + " or " + (expectedBufLimit + hdrSize));<a name="line.582"></a>
-<span class="sourceLineNo">583</span>    }<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>  @Override<a name="line.586"></a>
-<span class="sourceLineNo">587</span>  public String toString() {<a name="line.587"></a>
-<span class="sourceLineNo">588</span>    StringBuilder sb = new StringBuilder()<a name="line.588"></a>
-<span class="sourceLineNo">589</span>      .append("[")<a name="line.589"></a>
-<span class="sourceLineNo">590</span>      .append("blockType=").append(blockType)<a name="line.590"></a>
-<span class="sourceLineNo">591</span>      .append(", fileOffset=").append(offset)<a name="line.591"></a>
-<span class="sourceLineNo">592</span>      .append(", headerSize=").append(headerSize())<a name="line.592"></a>
-<span class="sourceLineNo">593</span>      .append(", onDiskSizeWithoutHeader=").append(onDiskSizeWithoutHeader)<a name="line.593"></a>
-<span class="sourceLineNo">594</span>      .append(", uncompressedSizeWithoutHeader=").append(uncompressedSizeWithoutHeader)<a name="line.594"></a>
-<span class="sourceLineNo">595</span>      .append(", prevBlockOffset=").append(prevBlockOffset)<a name="line.595"></a>
-<span class="sourceLineNo">596</span>      .append(", isUseHBaseChecksum=").append(fileContext.isUseHBaseChecksum());<a name="line.596"></a>
-<span class="sourceLineNo">597</span>    if (fileContext.isUseHBaseChecksum()) {<a name="line.597"></a>
-<span class="sourceLineNo">598</span>      sb.append(", checksumType=").append(ChecksumType.codeToType(this.buf.get(24)))<a name="line.598"></a>
-<span class="sourceLineNo">599</span>        .append(", bytesPerChecksum=").append(this.buf.getInt(24 + 1))<a name="line.599"></a>
-<span class="sourceLineNo">600</span>        .append(", onDiskDataSizeWithHeader=").append(onDiskDataSizeWithHeader);<a name="line.600"></a>
-<span class="sourceLineNo">601</span>    } else {<a name="line.601"></a>
-<span class="sourceLineNo">602</span>      sb.append(", onDiskDataSizeWithHeader=").append(onDiskDataSizeWithHeader)<a name="line.602"></a>
-<span class="sourceLineNo">603</span>        .append("(").append(onDiskSizeWithoutHeader)<a name="line.603"></a>
-<span class="sourceLineNo">604</span>        .append("+").append(HConstants.HFILEBLOCK_HEADER_SIZE_NO_CHECKSUM).append(")");<a name="line.604"></a>
-<span class="sourceLineNo">605</span>    }<a name="line.605"></a>
-<span class="sourceLineNo">606</span>    String dataBegin = null;<a name="line.606"></a>
-<span class="sourceLineNo">607</span>    if (buf.hasArray()) {<a name="line.607"></a>
-<span class="sourceLineNo">608</span>      dataBegin = Bytes.toStringBinary(buf.array(), buf.arrayOffset() + headerSize(),<a name="line.608"></a>
-<span class="sourceLineNo">609</span>          Math.min(32, buf.limit() - buf.arrayOffset() - headerSize()));<a name="line.609"></a>
-<span class="sourceLineNo">610</span>    } else {<a name="line.610"></a>
-<span class="sourceLineNo">611</span>      ByteBuff bufWithoutHeader = getBufferWithoutHeader();<a name="line.611"></a>
-<span class="sourceLineNo">612</span>      byte[] dataBeginBytes = new byte[Math.min(32,<a name="line.612"></a>
-<span class="sourceLineNo">613</span>          bufWithoutHeader.limit() - bufWithoutHeader.position())];<a name="line.613"></a>
-<span class="sourceLineNo">614</span>      bufWithoutHeader.get(dataBeginBytes);<a name="line.614"></a>
-<span class="sourceLineNo">615</span>      dataBegin = Bytes.toStringBinary(dataBeginBytes);<a name="line.615"></a>
-<span class="sourceLineNo">616</span>    }<a name="line.616"></a>
-<span class="sourceLineNo">617</span>    sb.append(", getOnDiskSizeWithHeader=").append(getOnDiskSizeWithHeader())<a name="line.617"></a>
-<span class="sourceLineNo">618</span>      .append(", totalChecksumBytes=").append(totalChecksumBytes())<a name="line.618"></a>
-<span class="sourceLineNo">619</span>      .append(", isUnpacked=").append(isUnpacked())<a name="line.619"></a>
-<span class="sourceLineNo">620</span>      .append(", buf=[").append(buf).append("]")<a name="line.620"></a>
-<span class="sourceLineNo">621</span>      .append(", dataBeginsWith=").append(dataBegin)<a name="line.621"></a>
-<span class="sourceLineNo">622</span>      .append(", fileContext=").append(fileContext)<a name="line.622"></a>
-<span class="sourceLineNo">623</span>      .append("]");<a name="line.623"></a>
-<span class="sourceLineNo">624</span>    return sb.toString();<a name="line.624"></a>
-<span class="sourceLineNo">625</span>  }<a name="line.625"></a>
-<span class="sourceLineNo">626</span><a name="line.626"></a>
-<span class="sourceLineNo">627</span>  /**<a name="line.627"></a>
-<span class="sourceLineNo">628</span>   * Retrieves the decompressed/decrypted view of this block. An encoded block remains in its<a name="line.628"></a>
-<span class="sourceLineNo">629</span>   * encoded structure. Internal structures are shared between instances where applicable.<a name="line.629"></a>
-<span class="sourceLineNo">630</span>   */<a name="line.630"></a>
-<span class="sourceLineNo">631</span>  HFileBlock unpack(HFileContext fileContext, FSReader reader) throws IOException {<a name="line.631"></a>
-<span class="sourceLineNo">632</span>    if (!fileContext.isCompressedOrEncrypted()) {<a name="line.632"></a>
-<span class="sourceLineNo">633</span>      // TODO: cannot use our own fileContext here because HFileBlock(ByteBuffer, boolean),<a name="line.633"></a>
-<span class="sourceLineNo">634</span>      // which is used for block serialization to L2 cache, does not preserve encoding and<a name="line.634"></a>
-<span class="sourceLineNo">635</span>      // encryption details.<a name="line.635"></a>
-<span class="sourceLineNo">636</span>      return this;<a name="line.636"></a>
-<span class="sourceLineNo">637</span>    }<a name="line.637"></a>
-<span class="sourceLineNo">638</span><a name="line.638"></a>
-<span class="sourceLineNo">639</span>    HFileBlock unpacked = new HFileBlock(this);<a name="line.639"></a>
-<span class="sourceLineNo">640</span>    unpacked.allocateBuffer(); // allocates space for the decompressed block<a name="line.640"></a>
-<span class="sourceLineNo">641</span><a name="line.641"></a>
-<span class="sourceLineNo">642</span>    HFileBlockDecodingContext ctx = blockType == BlockType.ENCODED_DATA ?<a name="line.642"></a>
-<span class="sourceLineNo">643</span>      reader.getBlockDecodingContext() : reader.getDefaultBlockDecodingContext();<a name="line.643"></a>
-<span class="sourceLineNo">644</span><a name="line.644"></a>
-<span class="sourceLineNo">645</span>    ByteBuff dup = this.buf.duplicate();<a name="line.645"></a>
-<span class="sourceLineNo">646</span>    dup.position(this.headerSize());<a name="line.646"></a>
-<span class="sourceLineNo">647</span>    dup = dup.slice();<a name="line.647"></a>
-<span class="sourceLineNo">648</span>    ctx.prepareDecoding(unpacked.getOnDiskSizeWithoutHeader(),<a name="line.648"></a>
-<span class="sourceLineNo">649</span>      unpacked.getUncompressedSizeWithoutHeader(), unpacked.getBufferWithoutHeader(),<a name="line.649"></a>
-<span class="sourceLineNo">650</span>      dup);<a name="line.650"></a>
-<span class="sourceLineNo">651</span>    return unpacked;<a name="line.651"></a>
-<span class="sourceLineNo">652</span>  }<a name="line.652"></a>
-<span class="sourceLineNo">653</span><a name="line.653"></a>
-<span class="sourceLineNo">654</span>  /**<a name="line.654"></a>
-<span class="sourceLineNo">655</span>   * Always allocates a new buffer of the correct size. Copies header bytes<a name="line.655"></a>
-<span class="sourceLineNo">656</span>   * from the existing buffer. Does not change header fields.<a name="line.656"></a>
-<span class="sourceLineNo">657</span>   * Reserve room to keep checksum bytes too.<a name="line.657"></a>
-<span class="sourceLineNo">658</span>   */<a name="line.658"></a>
-<span class="sourceLineNo">659</span>  private void allocateBuffer() {<a name="line.659"></a>
-<span class="sourceLineNo">660</span>    int cksumBytes = totalChecksumBytes();<a name="line.660"></a>
-<span class="sourceLineNo">661</span>    int headerSize = headerSize();<a name="line.661"></a>
-<span class="sourceLineNo">662</span>    int capacityNeeded = headerSize + uncompressedSizeWithoutHeader + cksumBytes;<a name="line.662"></a>
-<span class="sourceLineNo">663</span><a name="line.663"></a>
-<span class="sourceLineNo">664</span>    // TODO we need consider allocating offheap here?<a name="line.664"></a>
-<span class="sourceLineNo">665</span>    ByteBuffer newBuf = ByteBuffer.allocate(capacityNeeded);<a name="line.665"></a>
-<span class="sourceLineNo">666</span><a name="line.666"></a>
-<span class="sourceLineNo">667</span>    // Copy header bytes into newBuf.<a name="line.667"></a>
-<span class="sourceLineNo">668</span>    // newBuf is HBB so no issue in calling array()<a name="line.668"></a>
-<span class="sourceLineNo">669</span>    buf.position(0);<a name="line.669"></a>
-<span class="sourceLineNo">670</span>    buf.get(newBuf.array(), newBuf.arrayOffset(), headerSize);<a name="line.670"></a>
-<span class="sourceLineNo">671</span><a name="line.671"></a>
-<span class="sourceLineNo">672</span>    buf = new SingleByteBuff(newBuf);<a name="line.672"></a>
-<span class="sourceLineNo">673</span>    // set limit to exclude next block's header<a name="line.673"></a>
-<span class="sourceLineNo">674</span>    buf.limit(headerSize + uncompressedSizeWithoutHeader + cksumBytes);<a name="line.674"></a>
-<span class="sourceLineNo">675</span>  }<a name="line.675"></a>
-<span class="sourceLineNo">676</span><a name="line.676"></a>
-<span class="sourceLineNo">677</span>  /**<a name="line.677"></a>
-<span class="sourceLineNo">678</span>   * Return true when this block's buffer has been unpacked, false otherwise. Note this is a<a name="line.678"></a>
-<span class="sourceLineNo">679</span>   * calculated heuristic, not tracked attribute of the block.<a name="line.679"></a>
-<span class="sourceLineNo">680</span>   */<a name="line.680"></a>
-<span class="sourceLineNo">681</span>  public boolean isUnpacked() {<a name="line.681"></a>
-<span class="sourceLineNo">682</span>    final int cksumBytes = totalChecksumBytes();<a name="line.682"></a>
-<span class="sourceLineNo">683</span>    final int headerSize = headerSize();<a name="line.683"></a>
-<span class="sourceLineNo">684</span>    final int expectedCapacity = headerSize + uncompressedSizeWithoutHeader + cksumBytes;<a name="line.684"></a>
-<span class="sourceLineNo">685</span>    final int bufCapacity = buf.capacity();<a name="line.685"></a>
-<span class="sourceLineNo">686</span>    return bufCapacity == expectedCapacity || bufCapacity == expectedCapacity + headerSize;<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>  /** An additional sanity-check in case no compression or encryption is being used. */<a name="line.689"></a>
-<span class="sourceLineNo">690</span>  @VisibleForTesting<a name="line.690"></a>
-<span class="sourceLineNo">691</span>  void sanityCheckUncompressedSize() throws IOException {<a name="line.691"></a>
-<span class="sourceLineNo">692</span>    if (onDiskSizeWithoutHeader != uncompressedSizeWithoutHeader + totalChecksumBytes()) {<a name="line.692"></a>
-<span class="sourceLineNo">693</span>      throw new IOException("Using no compression but "<a name="line.693"></a>
-<span class="sourceLineNo">694</span>          + "onDiskSizeWithoutHeader=" + onDiskSizeWithoutHeader + ", "<a name="line.694"></a>
-<span class="sourceLineNo">695</span>          + "uncompressedSizeWithoutHeader=" + uncompressedSizeWithoutHeader<a name="line.695"></a>
-<span class="sourceLineNo">696</span>          + ", numChecksumbytes=" + totalChecksumBytes());<a name="line.696"></a>
-<span class="sourceLineNo">697</span>    }<a name="line.697"></a>
-<span class="sourceLineNo">698</span>  }<a name="line.698"></a>
-<span class="sourceLineNo">699</span><a name="line.699"></a>
-<span class="sourceLineNo">700</span>  /**<a name="line.700"></a>
-<span class="sourceLineNo">701</span>   * Cannot be {@link #UNSET}. Must be a legitimate value. Used re-making the {@link BlockCacheKey} when<a name="line.701"></a>
-<span class="sourceLineNo">702</span>   * block is returned to the cache.<a name="line.702"></a>
-<span class="sourceLineNo">703</span>   * @return the offset of this block in the file it was read from<a name="line.703"></a>
-<span class="sourceLineNo">704</span>   */<a name="line.704"></a>
-<span class="sourceLineNo">705</span>  long getOffset() {<a name="line.705"></a>
-<span class="sourceLineNo">706</span>    if (offset &lt; 0) {<a name="line.706"></a>
-<span class="sourceLineNo">707</span>      throw new IllegalStateException("HFile block offset not initialized properly");<a name="line.707"></a>
-<span class="sourceLineNo">708</span>    }<a name="line.708"></a>
-<span class="sourceLineNo">709</span>    return offset;<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>   * @return a byte stream reading the data + checksum of this block<a name="line.713"></a>
-<span class="sourceLineNo">714</span>   */<a name="line.714"></a>
-<span class="sourceLineNo">715</span>  DataInputStream getByteStream() {<a name="line.715"></a>
-<span class="sourceLineNo">716</span>    ByteBuff dup = this.buf.duplicate();<a name="line.716"></a>
-<span class="sourceLineNo">717</span>    dup.position(this.headerSize());<a name="line.717"></a>
-<span class="sourceLineNo">718</span>    return new DataInputStream(new ByteBuffInputStream(dup));<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>
-<span class="sourceLineNo">721</span>  @Override<a name="line.721"></a>
-<span class="sourceLineNo">722</span>  public long heapSize() {<a name="line.722"></a>
-<span class="sourceLineNo">723</span>    long size = ClassSize.align(<a name="line.723"></a>
-<span class="sourceLineNo">724</span>        ClassSize.OBJECT +<a name="line.724"></a>
-<span class="sourceLineNo">725</span>        // Block type, multi byte buffer, MemoryType and meta references<a name="line.725"></a>
-<span class="sourceLineNo">726</span>        4 * ClassSize.REFERENCE +<a name="line.726"></a>
-<span class="sourceLineNo">727</span>        // On-disk size, uncompressed size, and next block's on-disk size<a name="line.727"></a>
-<span class="sourceLineNo">728</span>        // bytePerChecksum and onDiskDataSize<a name="line.728"></a>
-<span class="sourceLineNo">729</span>        4 * Bytes.SIZEOF_INT +<a name="line.729"></a>
-<span class="sourceLineNo">730</span>        // This and previous block offset<a name="line.730"></a>
-<span class="sourceLineNo">731</span>        2 * Bytes.SIZEOF_LONG +<a name="line.731"></a>
-<span class="sourceLineNo">732</span>        // Heap size of the meta object. meta will be always not null.<a name="line.732"></a>
-<span class="sourceLineNo">733</span>        fileContext.heapSize()<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>    if (buf != null) {<a name="line.736"></a>
-<span class="sourceLineNo">737</span>      // Deep overhead of the byte buffer. Needs to be aligned separately.<a name="line.737"></a>
-<span class="sourceLineNo">738</span>      size += ClassSize.align(buf.capacity() + MULTI_BYTE_BUFFER_HEAP_SIZE);<a name="line.738"></a>
-<span class="sourceLineNo">739</span>    }<a name="line.739"></a>
-<span class="sourceLineNo">740</span><a name="line.740"></a>
-<span class="sourceLineNo">741</span>    return ClassSize.align(size);<a name="line.741"></a>
-<span class="sourceLineNo">742</span>  }<a name="line.742"></a>
-<span class="sourceLineNo">743</span><a name="line.743"></a>
-<span class="sourceLineNo">744</span>  /**<a name="line.744"></a>
-<span class="sourceLineNo">745</span>   * Read from an input stream at least &lt;code&gt;necessaryLen&lt;/code&gt; and if possible,<a name="line.745"></a>
-<span class="sourceLineNo">746</span>   * &lt;code&gt;extraLen&lt;/code&gt; also if available. Analogous to<a name="line.746"></a>
-<span class="sourceLineNo">747</span>   * {@link IOUtils#readFully(InputStream, byte[], int, int)}, but specifies a<a name="line.747"></a>
-<span class="sourceLineNo">748</span>   * number of "extra" bytes to also optionally read.<a name="line.748"></a>
-<span class="sourceLineNo">749</span>   *<a name="line.749"></a>
-<span class="sourceLineNo">750</span>   * @param in the input stream to read from<a name="line.750"></a>
-<span class="sourceLineNo">751</span>   * @param buf the buffer to read into<a name="line.751"></a>
-<span class="sourceLineNo">752</span>   * @param bufOffset the destination offset in the buffer<a name="line.752"></a>
-<span class="sourceLineNo">753</span>   * @param necessaryLen the number of bytes that are absolutely necessary to read<a name="line.753"></a>
-<span class="sourceLineNo">754</span>   * @param extraLen the number of extra bytes that would be nice to read<a name="line.754"></a>
-<span class="sourceLineNo">755</span>   * @return true if succeeded reading the extra bytes<a name="line.755"></a>
-<span class="sourceLineNo">756</span>   * @throws IOException if failed to read the necessary bytes<a name="line.756"></a>
-<span class="sourceLineNo">757</span>   */<a name="line.757"></a>
-<span class="sourceLineNo">758</span>  static boolean readWithExtra(InputStream in, byte[] buf,<a name="line.758"></a>
-<span class="sourceLineNo">759</span>      int bufOffset, int necessaryLen, int extraLen) throws IOException {<a name="line.759"></a>
-<span class="sourceLineNo">760</span>    int bytesRemaining = necessaryLen + extraLen;<a name="line.760"></a>
-<span class="sourceLineNo">761</span>    while (bytesRemaining &gt; 0) {<a name="line.761"></a>
-<span class="sourceLineNo">762</span>      int ret = in.read(buf, bufOffset, bytesRemaining);<a name="line.762"></a>
-<span class="sourceLineNo">763</span>      if (ret == -1 &amp;&amp; bytesRemaining &lt;= extraLen) {<a name="line.763"></a>
-<span class="sourceLineNo">764</span>        // We could not read the "extra data", but that is OK.<a name="line.764"></a>
-<span class="sourceLineNo">765</span>        break;<a name="line.765"></a>
-<span class="sourceLineNo">766</span>      }<a name="line.766"></a>
-<span class="sourceLineNo">767</span>      if (ret &lt; 0) {<a name="line.767"></a>
-<span class="sourceLineNo">768</span>        throw new IOException("Premature EOF from inputStream (read "<a name="line.768"></a>
-<span class="sourceLineNo">769</span>            + "returned " + ret + ", was trying to read " + necessaryLen<a name="line.769"></a>
-<span class="sourceLineNo">770</span>            + " necessary bytes and " + extraLen + " extra bytes, "<a name="line.770"></a>
-<span class="sourceLineNo">771</span>            + "successfully read "<a name="line.771"></a>
-<span class="sourceLineNo">772</span>            + (necessaryLen + extraLen - bytesRemaining));<a name="line.772"></a>
-<span class="sourceLineNo">773</span>      }<a name="line.773"></a>
-<span class="sourceLineNo">774</span>      bufOffset += ret;<a name="line.774"></a>
-<span class="sourceLineNo">775</span>      bytesRemaining -= ret;<a name="line.775"></a>
-<span class="sourceLineNo">776</span>    }<a name="line.776"></a>
-<span class="sourceLineNo">777</span>    return bytesRemaining &lt;= 0;<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>   * Read from an input stream at least &lt;code&gt;necessaryLen&lt;/code&gt; and if possible,<a name="line.781"></a>
-<span class="sourceLineNo">782</span>   * &lt;code&gt;extraLen&lt;/code&gt; also if available. Analogous to<a name="line.782"></a>
-<span class="sourceLineNo">783</span>   * {@link IOUtils#readFully(InputStream, byte[], int, int)}, but uses<a name="line.783"></a>
-<span class="sourceLineNo">784</span>   * positional read and specifies a number of "extra" bytes that would be<a name="line.784"></a>
-<span class="sourceLineNo">785</span>   * desirable but not absolutely necessary to read.<a name="line.785"></a>
-<span class="sourceLineNo">786</span>   *<a name="line.786"></a>
-<span class="sourceLineNo">787</span>   * @param in the input stream to read from<a name="line.787"></a>
-<span class="sourceLineNo">788</span>   * @param position the position within the stream from which to start reading<a name="line.788"></a>
-<span class="sourceLineNo">789</span>   * @param buf the buffer to read into<a name="line.789"></a>
-<span class="sourceLineNo">790</span>   * @param bufOffset the destination offset in the buffer<a name="line.790"></a>
-<span class="sourceLineNo">791</span>   * @param necessaryLen the number of bytes that are absolutely necessary to<a name="line.791"></a>
-<span class="sourceLineNo">792</span>   *     read<a name="line.792"></a>
-<span class="sourceLineNo">793</span>   * @param extraLen the number of extra bytes that would be nice to read<a name="line.793"></a>
-<span class="sourceLineNo">794</span>   * @return true if and only if extraLen is &gt; 0 and reading those extra bytes<a name="line.794"></a>
-<span class="sourceLineNo">795</span>   *     was successful<a name="line.795"></a>
-<span class="sourceLineNo">796</span>   * @throws IOException if failed to read the necessary bytes<a name="line.796"></a>
-<span class="sourceLineNo">797</span>   */<a name="line.797"></a>
-<span class="sourceLineNo">798</span>  @VisibleForTesting<a name="line.798"></a>
-<span class="sourceLineNo">799</span>  static boolean positionalReadWithExtra(FSDataInputStream in,<a name="line.799"></a>
-<span class="sourceLineNo">800</span>      long position, byte[] buf, int bufOffset, int necessaryLen, int extraLen)<a name="line.800"></a>
-<span class="sourceLineNo">801</span>      throws IOException {<a name="line.801"></a>
-<span class="sourceLineNo">802</span>    int bytesRemaining = necessaryLen + extraLen;<a name="line.802"></a>
-<span class="sourceLineNo">803</span>    int bytesRead = 0;<a name="line.803"></a>
-<span class="sourceLineNo">804</span>    while (bytesRead &lt; necessaryLen) {<a name="line.804"></a>
-<span class="sourceLineNo">805</span>      int ret = in.read(position, buf, bufOffset, bytesRemaining);<a name="line.805"></a>
-<span class="sourceLineNo">806</span>      if (ret &lt; 0) {<a name="line.806"></a>
-<span class="sourceLineNo">807</span>        throw new IOException("Premature EOF from inputStream (positional read "<a name="line.807"></a>
-<span class="sourceLineNo">808</span>            + "returned " + ret + ", was trying to read " + necessaryLen<a name="line.808"></a>
-<span class="sourceLineNo">809</span>            + " necessary bytes and " + extraLen + " extra bytes, "<a name="line.809"></a>
-<span class="sourceLineNo">810</span>            + "successfully read " + bytesRead);<a name="line.810"></a>
-<span class="sourceLineNo">811</span>      }<a name="line.811"></a>
-<span class="sourceLineNo">812</span>      position += ret;<a name="line.812"></a>
-<span class="sourceLineNo">813</span>      bufOffset += ret;<a name="line.813"></a>
-<span class="sourceLineNo">814</span>      bytesRemaining -= ret;<a name="line.814"></a>
-<span class="sourceLineNo">815</span>      bytesRead += ret;<a name="line.815"></a>
-<span class="sourceLineNo">816</span>    }<a name="line.816"></a>
-<span class="sourceLineNo">817</span>    return bytesRead != necessaryLen &amp;&amp; bytesRemaining &lt;= 0;<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>   * Unified version 2 {@link HFile} block writer. The intended usage pattern<a name="line.821"></a>
-<span class="sourceLineNo">822</span>   * is as follows:<a name="line.822"></a>
-<span class="sourceLineNo">823</span>   * &lt;ol&gt;<a name="line.823"></a>
-<span class="sourceLineNo">824</span>   * &lt;li&gt;Construct an {@link HFileBlock.Writer}, providing a compression algorithm.<a name="line.824"></a>
-<span class="sourceLineNo">825</span>   * &lt;li&gt;Call {@link Writer#startWriting} and get a data stream to write to.<a name="line.825"></a>
-<span class="sourceLineNo">826</span>   * &lt;li&gt;Write your data into the stream.<a name="line.826"></a>
-<span class="sourceLineNo">827</span>   * &lt;li&gt;Call Writer#writeHeaderAndData(FSDataOutputStream) as many times as you need to.<a name="line.827"></a>
-<span class="sourceLineNo">828</span>   * store the serialized block into an external stream.<a name="line.828"></a>
-<span class="sourceLineNo">829</span>   * &lt;li&gt;Repeat to write more blocks.<a name="line.829"></a>
-<span class="sourceLineNo">830</span>   * &lt;/ol&gt;<a name="line.830"></a>
-<span class="sourceLineNo">831</span>   * &lt;p&gt;<a name="line.831"></a>
-<span class="sourceLineNo">832</span>   */<a name="line.832"></a>
-<span class="sourceLineNo">833</span>  static class Writer {<a name="line.833"></a>
-<span class="sourceLineNo">834</span>    private enum State {<a name="line.834"></a>
-<span class="sourceLineNo">835</span>      INIT,<a name="line.835"></a>
-<span class="sourceLineNo">836</span>      WRITING,<a name="line.836"></a>
-<span class="sourceLineNo">837</span>      BLOCK_READY<a name="line.837"></a>
-<span class="sourceLineNo">838</span>    }<a name="line.838"></a>
-<span class="sourceLineNo">839</span><a name="line.839"></a>
-<span class="sourceLineNo">840</span>    /** Writer state. Used to ensure the correct usage protocol. */<a name="line.840"></a>
-<span class="sourceLineNo">841</span>    private State state = State.INIT;<a name="line.841"></a>
-<span class="sourceLineNo">842</span><a name="line.842"></a>
-<span class="sourceLineNo">843</span>    /** Data block encoder used for data blocks */<a name="line.843"></a>
-<span class="sourceLineNo">844</span>    private final HFileDataBlockEncoder dataBlockEncoder;<a name="line.844"></a>
-<span class="sourceLineNo">845</span><a name="line.845"></a>
-<span class="sourceLineNo">846</span>    private HFileBlockEncodingContext dataBlockEncodingCtx;<a name="line.846"></a>
+<span class="sourceLineNo">328</span>   *<a name="line.328"></a>
+<span class="sourceLineNo">329</span>   * &lt;p&gt;TODO: The caller presumes no checksumming<a name="line.329"></a>
+<span class="sourceLineNo">330</span>   * required of this block instance since going into cache; checksum already verified on<a name="line.330"></a>
+<span class="sourceLineNo">331</span>   * underlying block data pulled in from filesystem. Is that correct? What if cache is SSD?<a name="line.331"></a>
+<span class="sourceLineNo">332</span>   *<a name="line.332"></a>
+<span class="sourceLineNo">333</span>   * @param blockType the type of this block, see {@link BlockType}<a name="line.333"></a>
+<span class="sourceLineNo">334</span>   * @param onDiskSizeWithoutHeader see {@link #onDiskSizeWithoutHeader}<a name="line.334"></a>
+<span class="sourceLineNo">335</span>   * @param uncompressedSizeWithoutHeader see {@link #uncompressedSizeWithoutHeader}<a name="line.335"></a>
+<span class="sourceLineNo">336</span>   * @param prevBlockOffset see {@link #prevBlockOffset}<a name="line.336"></a>
+<span class="sourceLineNo">337</span>   * @param b block header ({@link HConstants#HFILEBLOCK_HEADER_SIZE} bytes)<a name="line.337"></a>
+<span class="sourceLineNo">338</span>   * @param fillHeader when true, write the first 4 header fields into passed buffer.<a name="line.338"></a>
+<span class="sourceLineNo">339</span>   * @param offset the file offset the block was read from<a name="line.339"></a>
+<span class="sourceLineNo">340</span>   * @param onDiskDataSizeWithHeader see {@link #onDiskDataSizeWithHeader}<a name="line.340"></a>
+<span class="sourceLineNo">341</span>   * @param fileContext HFile meta data<a name="line.341"></a>
+<span class="sourceLineNo">342</span>   */<a name="line.342"></a>
+<span class="sourceLineNo">343</span>  @VisibleForTesting<a name="line.343"></a>
+<span class="sourceLineNo">344</span>  public HFileBlock(BlockType blockType, int onDiskSizeWithoutHeader,<a name="line.344"></a>
+<span class="sourceLineNo">345</span>      int uncompressedSizeWithoutHeader, long prevBlockOffset, ByteBuffer b, boolean fillHeader,<a name="line.345"></a>
+<span class="sourceLineNo">346</span>      long offset, final int nextBlockOnDiskSize, int onDiskDataSizeWithHeader,<a name="line.346"></a>
+<span class="sourceLineNo">347</span>      HFileContext fileContext) {<a name="line.347"></a>
+<span class="sourceLineNo">348</span>    init(blockType, onDiskSizeWithoutHeader, uncompressedSizeWithoutHeader,<a name="line.348"></a>
+<span class="sourceLineNo">349</span>        prevBlockOffset, offset, onDiskDataSizeWithHeader, nextBlockOnDiskSize, fileContext);<a name="line.349"></a>
+<span class="sourceLineNo">350</span>    this.buf = new SingleByteBuff(b);<a name="line.350"></a>
+<span class="sourceLineNo">351</span>    if (fillHeader) {<a name="line.351"></a>
+<span class="sourceLineNo">352</span>      overwriteHeader();<a name="line.352"></a>
+<span class="sourceLineNo">353</span>    }<a name="line.353"></a>
+<span class="sourceLineNo">354</span>    this.buf.rewind();<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">357</span>  /**<a name="line.357"></a>
+<span class="sourceLineNo">358</span>   * Creates a block from an existing buffer starting with a header. Rewinds<a name="line.358"></a>
+<span class="sourceLineNo">359</span>   * and takes ownership of the buffer. By definition of rewind, ignores the<a name="line.359"></a>
+<span class="sourceLineNo">360</span>   * buffer position, but if you slice the buffer beforehand, it will rewind<a name="line.360"></a>
+<span class="sourceLineNo">361</span>   * to that point.<a name="line.361"></a>
+<span class="sourceLineNo">362</span>   * @param buf Has header, content, and trailing checksums if present.<a name="line.362"></a>
+<span class="sourceLineNo">363</span>   */<a name="line.363"></a>
+<span class="sourceLineNo">364</span>  HFileBlock(ByteBuff buf, boolean usesHBaseChecksum, MemoryType memType, final long offset,<a name="line.364"></a>
+<span class="sourceLineNo">365</span>      final int nextBlockOnDiskSize, HFileContext fileContext) throws IOException {<a name="line.365"></a>
+<span class="sourceLineNo">366</span>    buf.rewind();<a name="line.366"></a>
+<span class="sourceLineNo">367</span>    final BlockType blockType = BlockType.read(buf);<a name="line.367"></a>
+<span class="sourceLineNo">368</span>    final int onDiskSizeWithoutHeader = buf.getInt(Header.ON_DISK_SIZE_WITHOUT_HEADER_INDEX);<a name="line.368"></a>
+<span class="sourceLineNo">369</span>    final int uncompressedSizeWithoutHeader =<a name="line.369"></a>
+<span class="sourceLineNo">370</span>        buf.getInt(Header.UNCOMPRESSED_SIZE_WITHOUT_HEADER_INDEX);<a name="line.370"></a>
+<span class="sourceLineNo">371</span>    final long prevBlockOffset = buf.getLong(Header.PREV_BLOCK_OFFSET_INDEX);<a name="line.371"></a>
+<span class="sourceLineNo">372</span>    // This constructor is called when we deserialize a block from cache and when we read a block in<a name="line.372"></a>
+<span class="sourceLineNo">373</span>    // from the fs. fileCache is null when deserialized from cache so need to make up one.<a name="line.373"></a>
+<span class="sourceLineNo">374</span>    HFileContextBuilder fileContextBuilder = fileContext != null?<a name="line.374"></a>
+<span class="sourceLineNo">375</span>        new HFileContextBuilder(fileContext): new HFileContextBuilder();<a name="line.375"></a>
+<span class="sourceLineNo">376</span>    fileContextBuilder.withHBaseCheckSum(usesHBaseChecksum);<a name="line.376"></a>
+<span class="sourceLineNo">377</span>    int onDiskDataSizeWithHeader;<a name="line.377"></a>
+<span class="sourceLineNo">378</span>    if (usesHBaseChecksum) {<a name="line.378"></a>
+<span class="sourceLineNo">379</span>      byte checksumType = buf.get(Header.CHECKSUM_TYPE_INDEX);<a name="line.379"></a>
+<span class="sourceLineNo">380</span>      int bytesPerChecksum = buf.getInt(Header.BYTES_PER_CHECKSUM_INDEX);<a name="line.380"></a>
+<span class="sourceLineNo">381</span>      onDiskDataSizeWithHeader = buf.getInt(Header.ON_DISK_DATA_SIZE_WITH_HEADER_INDEX);<a name="line.381"></a>
+<span class="sourceLineNo">382</span>      // Use the checksum type and bytes per checksum from header, not from filecontext.<a name="line.382"></a>
+<span class="sourceLineNo">383</span>      fileContextBuilder.withChecksumType(ChecksumType.codeToType(checksumType));<a name="line.383"></a>
+<span class="sourceLineNo">384</span>      fileContextBuilder.withBytesPerCheckSum(bytesPerChecksum);<a name="line.384"></a>
+<span class="sourceLineNo">385</span>    } else {<a name="line.385"></a>
+<span class="sourceLineNo">386</span>      fileContextBuilder.withChecksumType(ChecksumType.NULL);<a name="line.386"></a>
+<span class="sourceLineNo">387</span>      fileContextBuilder.withBytesPerCheckSum(0);<a name="line.387"></a>
+<span class="sourceLineNo">388</span>      // Need to fix onDiskDataSizeWithHeader; there are not checksums after-block-data<a name="line.388"></a>
+<span class="sourceLineNo">389</span>      onDiskDataSizeWithHeader = onDiskSizeWithoutHeader + headerSize(usesHBaseChecksum);<a name="line.389"></a>
+<span class="sourceLineNo">390</span>    }<a name="line.390"></a>
+<span class="sourceLineNo">391</span>    fileContext = fileContextBuilder.build();<a name="line.391"></a>
+<span class="sourceLineNo">392</span>    assert usesHBaseChecksum == fileContext.isUseHBaseChecksum();<a name="line.392"></a>
+<span class="sourceLineNo">393</span>    init(blockType, onDiskSizeWithoutHeader, uncompressedSizeWithoutHeader,<a name="line.393"></a>
+<span class="sourceLineNo">394</span>        prevBlockOffset, offset, onDiskDataSizeWithHeader, nextBlockOnDiskSize, fileContext);<a name="line.394"></a>
+<span class="sourceLineNo">395</span>    this.memType = memType;<a name="line.395"></a>
+<span class="sourceLineNo">396</span>    this.offset = offset;<a name="line.396"></a>
+<span class="sourceLineNo">397</span>    this.buf = buf;<a name="line.397"></a>
+<span class="sourceLineNo">398</span>    this.buf.rewind();<a name="line.398"></a>
+<span class="sourceLineNo">399</span>  }<a name="line.399"></a>
+<span class="sourceLineNo">400</span><a name="line.400"></a>
+<span class="sourceLineNo">401</span>  /**<a name="line.401"></a>
+<span class="sourceLineNo">402</span>   * Called from constructors.<a name="line.402"></a>
+<span class="sourceLineNo">403</span>   */<a name="line.403"></a>
+<span class="sourceLineNo">404</span>  private void init(BlockType blockType, int onDiskSizeWithoutHeader,<a name="line.404"></a>
+<span class="sourceLineNo">405</span>      int uncompressedSizeWithoutHeader, long prevBlockOffset,<a name="line.405"></a>
+<span class="sourceLineNo">406</span>      long offset, int onDiskDataSizeWithHeader, final int nextBlockOnDiskSize,<a name="line.406"></a>
+<span class="sourceLineNo">407</span>      HFileContext fileContext) {<a name="line.407"></a>
+<span class="sourceLineNo">408</span>    this.blockType = blockType;<a name="line.408"></a>
+<span class="sourceLineNo">409</span>    this.onDiskSizeWithoutHeader = onDiskSizeWithoutHeader;<a name="line.409"></a>
+<span class="sourceLineNo">410</span>    this.uncompressedSizeWithoutHeader = uncompressedSizeWithoutHeader;<a name="line.410"></a>
+<span class="sourceLineNo">411</span>    this.prevBlockOffset = prevBlockOffset;<a name="line.411"></a>
+<span class="sourceLineNo">412</span>    this.offset = offset;<a name="line.412"></a>
+<span class="sourceLineNo">413</span>    this.onDiskDataSizeWithHeader = onDiskDataSizeWithHeader;<a name="line.413"></a>
+<span class="sourceLineNo">414</span>    this.nextBlockOnDiskSize = nextBlockOnDiskSize;<a name="line.414"></a>
+<span class="sourceLineNo">415</span>    this.fileContext = fileContext;<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">418</span>  /**<a name="line.418"></a>
+<span class="sourceLineNo">419</span>   * Parse total on disk size including header and checksum.<a name="line.419"></a>
+<span class="sourceLineNo">420</span>   * @param headerBuf Header ByteBuffer. Presumed exact size of header.<a name="line.420"></a>
+<span class="sourceLineNo">421</span>   * @param verifyChecksum true if checksum verification is in use.<a name="line.421"></a>
+<span class="sourceLineNo">422</span>   * @return Size of the block with header included.<a name="line.422"></a>
+<span class="sourceLineNo">423</span>   */<a name="line.423"></a>
+<span class="sourceLineNo">424</span>  private static int getOnDiskSizeWithHeader(final ByteBuffer headerBuf,<a name="line.424"></a>
+<span class="sourceLineNo">425</span>      boolean verifyChecksum) {<a name="line.425"></a>
+<span class="sourceLineNo">426</span>    return headerBuf.getInt(Header.ON_DISK_SIZE_WITHOUT_HEADER_INDEX) +<a name="line.426"></a>
+<span class="sourceLineNo">427</span>      headerSize(verifyChecksum);<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>   * @return the on-disk size of the next block (including the header size and any checksums if<a name="line.431"></a>
+<span class="sourceLineNo">432</span>   * present) read by peeking into the next block's header; use as a hint when doing<a name="line.432"></a>
+<span class="sourceLineNo">433</span>   * a read of the next block when scanning or running over a file.<a name="line.433"></a>
+<span class="sourceLineNo">434</span>   */<a name="line.434"></a>
+<span class="sourceLineNo">435</span>  int getNextBlockOnDiskSize() {<a name="line.435"></a>
+<span class="sourceLineNo">436</span>    return nextBlockOnDiskSize;<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>  @Override<a name="line.439"></a>
+<span class="sourceLineNo">440</span>  public BlockType getBlockType() {<a name="line.440"></a>
+<span class="sourceLineNo">441</span>    return blockType;<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>  /** @return get data block encoding id that was used to encode this block */<a name="line.444"></a>
+<span class="sourceLineNo">445</span>  short getDataBlockEncodingId() {<a name="line.445"></a>
+<span class="sourceLineNo">446</span>    if (blockType != BlockType.ENCODED_DATA) {<a name="line.446"></a>
+<span class="sourceLineNo">447</span>      throw new IllegalArgumentException("Querying encoder ID of a block " +<a name="line.447"></a>
+<span class="sourceLineNo">448</span>          "of type other than " + BlockType.ENCODED_DATA + ": " + blockType);<a name="line.448"></a>
+<span class="sourceLineNo">449</span>    }<a name="line.449"></a>
+<span class="sourceLineNo">450</span>    return buf.getShort(headerSize());<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>   * @return the on-disk size of header + data part + checksum.<a name="line.454"></a>
+<span class="sourceLineNo">455</span>   */<a name="line.455"></a>
+<span class="sourceLineNo">456</span>  public int getOnDiskSizeWithHeader() {<a name="line.456"></a>
+<span class="sourceLineNo">457</span>    return onDiskSizeWithoutHeader + headerSize();<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>   * @return the on-disk size of the data part + checksum (header excluded).<a name="line.461"></a>
+<span class="sourceLineNo">462</span>   */<a name="line.462"></a>
+<span class="sourceLineNo">463</span>  int getOnDiskSizeWithoutHeader() {<a name="line.463"></a>
+<span class="sourceLineNo">464</span>    return onDiskSizeWithoutHeader;<a name="line.464"></a>
+<span class="sourceLineNo">465</span>  }<a name="line.465"></a>
+<span class="sourceLineNo">466</span><a name="line.466"></a>
+<span class="sourceLineNo">467</span>  /**<a name="line.467"></a>
+<span class="sourceLineNo">468</span>   * @return the uncompressed size of data part (header and checksum excluded).<a name="line.468"></a>
+<span class="sourceLineNo">469</span>   */<a name="line.469"></a>
+<span class="sourceLineNo">470</span>   int getUncompressedSizeWithoutHeader() {<a name="line.470"></a>
+<span class="sourceLineNo">471</span>    return uncompressedSizeWithoutHeader;<a name="line.471"></a>
+<span class="sourceLineNo">472</span>  }<a name="line.472"></a>
+<span class="sourceLineNo">473</span><a name="line.473"></a>
+<span class="sourceLineNo">474</span>  /**<a name="line.474"></a>
+<span class="sourceLineNo">475</span>   * @return the offset of the previous block of the same type in the file, or<a name="line.475"></a>
+<span class="sourceLineNo">476</span>   *         -1 if unknown<a name="line.476"></a>
+<span class="sourceLineNo">477</span>   */<a name="line.477"></a>
+<span class="sourceLineNo">478</span>  long getPrevBlockOffset() {<a name="line.478"></a>
+<span class="sourceLineNo">479</span>    return prevBlockOffset;<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>   * Rewinds {@code buf} and writes first 4 header fields. {@code buf} position<a name="line.483"></a>
+<span class="sourceLineNo">484</span>   * is modified as side-effect.<a name="line.484"></a>
+<span class="sourceLineNo">485</span>   */<a name="line.485"></a>
+<span class="sourceLineNo">486</span>  private void overwriteHeader() {<a name="line.486"></a>
+<span class="sourceLineNo">487</span>    buf.rewind();<a name="line.487"></a>
+<span class="sourceLineNo">488</span>    blockType.write(buf);<a name="line.488"></a>
+<span class="sourceLineNo">489</span>    buf.putInt(onDiskSizeWithoutHeader);<a name="line.489"></a>
+<span class="sourceLineNo">490</span>    buf.putInt(uncompressedSizeWithoutHeader);<a name="line.490"></a>
+<span class="sourceLineNo">491</span>    buf.putLong(prevBlockOffset);<a name="line.491"></a>
+<span class="sourceLineNo">492</span>    if (this.fileContext.isUseHBaseChecksum()) {<a name="line.492"></a>
+<span class="sourceLineNo">493</span>      buf.put(fileContext.getChecksumType().getCode());<a name="line.493"></a>
+<span class="sourceLineNo">494</span>      buf.putInt(fileContext.getBytesPerChecksum());<a name="line.494"></a>
+<span class="sourceLineNo">495</span>      buf.putInt(onDiskDataSizeWithHeader);<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><a name="line.498"></a>
+<span class="sourceLineNo">499</span>  /**<a name="line.499"></a>
+<span class="sourceLineNo">500</span>   * Returns a buffer that does not include the header or checksum.<a name="line.500"></a>
+<span class="sourceLineNo">501</span>   *<a name="line.501"></a>
+<span class="sourceLineNo">502</span>   * @return the buffer with header skipped and checksum omitted.<a name="line.502"></a>
+<span class="sourceLineNo">503</span>   */<a name="line.503"></a>
+<span class="sourceLineNo">504</span>  public ByteBuff getBufferWithoutHeader() {<a name="line.504"></a>
+<span class="sourceLineNo">505</span>    ByteBuff dup = getBufferReadOnly();<a name="line.505"></a>
+<span class="sourceLineNo">506</span>    // Now set it up so Buffer spans content only -- no header or no checksums.<a name="line.506"></a>
+<span class="sourceLineNo">507</span>    return dup.position(headerSize()).limit(buf.limit() - totalChecksumBytes()).slice();<a name="line.507"></a>
+<span class="sourceLineNo">508</span>  }<a name="line.508"></a>
+<span class="sourceLineNo">509</span><a name="line.509"></a>
+<span class="sourceLineNo">510</span>  /**<a name="line.510"></a>
+<span class="sourceLineNo">511</span>   * Returns a read-only duplicate of the buffer this block stores internally ready to be read.<a name="line.511"></a>
+<span class="sourceLineNo">512</span>   * Clients must not modify the buffer object though they may set position and limit on the<a name="line.512"></a>
+<span class="sourceLineNo">513</span>   * returned buffer since we pass back a duplicate. This method has to be public because it is used<a name="line.513"></a>
+<span class="sourceLineNo">514</span>   * in {@link CompoundBloomFilter} to avoid object creation on every Bloom<a name="line.514"></a>
+<span class="sourceLineNo">515</span>   * filter lookup, but has to be used with caution. Buffer holds header, block content,<a name="line.515"></a>
+<span class="sourceLineNo">516</span>   * and any follow-on checksums if present.<a name="line.516"></a>
+<span class="sourceLineNo">517</span>   *<a name="line.517"></a>
+<span class="sourceLineNo">518</span>   * @return the buffer of this block for read-only operations<a name="line.518"></a>
+<span class="sourceLineNo">519</span>   */<a name="line.519"></a>
+<span class="sourceLineNo">520</span>  public ByteBuff getBufferReadOnly() {<a name="line.520"></a>
+<span class="sourceLineNo">521</span>    // TODO: ByteBuf does not support asReadOnlyBuffer(). Fix.<a name="line.521"></a>
+<span class="sourceLineNo">522</span>    ByteBuff dup = this.buf.duplicate();<a name="line.522"></a>
+<span class="sourceLineNo">523</span>    assert dup.position() == 0;<a name="line.523"></a>
+<span class="sourceLineNo">524</span>    return dup;<a name="line.524"></a>
+<span class="sourceLineNo">525</span>  }<a name="line.525"></a>
+<span class="sourceLineNo">526</span><a name="line.526"></a>
+<span class="sourceLineNo">527</span>  @VisibleForTesting<a name="line.527"></a>
+<span class="sourceLineNo">528</span>  private void sanityCheckAssertion(long valueFromBuf, long valueFromField,<a name="line.528"></a>
+<span class="sourceLineNo">529</span>      String fieldName) throws IOException {<a name="line.529"></a>
+<span class="sourceLineNo">530</span>    if (valueFromBuf != valueFromField) {<a name="line.530"></a>
+<span class="sourceLineNo">531</span>      throw new AssertionError(fieldName + " in the buffer (" + valueFromBuf<a name="line.531"></a>
+<span class="sourceLineNo">532</span>          + ") is different from that in the field (" + valueFromField + ")");<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>  @VisibleForTesting<a name="line.536"></a>
+<span class="sourceLineNo">537</span>  private void sanityCheckAssertion(BlockType valueFromBuf, BlockType valueFromField)<a name="line.537"></a>
+<span class="sourceLineNo">538</span>      throws IOException {<a name="line.538"></a>
+<span class="sourceLineNo">539</span>    if (valueFromBuf != valueFromField) {<a name="line.539"></a>
+<span class="sourceLineNo">540</span>      throw new IOException("Block type stored in the buffer: " +<a name="line.540"></a>
+<span class="sourceLineNo">541</span>        valueFromBuf + ", block type field: " + valueFromField);<a name="line.541"></a>
+<span class="sourceLineNo">542</span>    }<a name="line.542"></a>
+<span class="sourceLineNo">543</span>  }<a name="line.543"></a>
+<span class="sourceLineNo">544</span><a name="line.544"></a>
+<span class="sourceLineNo">545</span>  /**<a name="line.545"></a>
+<span class="sourceLineNo">546</span>   * Checks if the block is internally consistent, i.e. the first<a name="line.546"></a>
+<span class="sourceLineNo">547</span>   * {@link HConstants#HFILEBLOCK_HEADER_SIZE} bytes of the buffer contain a<a name="line.547"></a>
+<span class="sourceLineNo">548</span>   * valid header consistent with the fields. Assumes a packed block structure.<a name="line.548"></a>
+<span class="sourceLineNo">549</span>   * This function is primary for testing and debugging, and is not<a name="line.549"></a>
+<span class="sourceLineNo">550</span>   * thread-safe, because it alters the internal buffer pointer.<a name="line.550"></a>
+<span class="sourceLineNo">551</span>   * Used by tests only.<a name="line.551"></a>
+<span class="sourceLineNo">552</span>   */<a name="line.552"></a>
+<span class="sourceLineNo">553</span>  @VisibleForTesting<a name="line.553"></a>
+<span class="sourceLineNo">554</span>  void sanityCheck() throws IOException {<a name="line.554"></a>
+<span class="sourceLineNo">555</span>    // Duplicate so no side-effects<a name="line.555"></a>
+<span class="sourceLineNo">556</span>    ByteBuff dup = this.buf.duplicate().rewind();<a name="line.556"></a>
+<span class="sourceLineNo">557</span>    sanityCheckAssertion(BlockType.read(dup), blockType);<a name="line.557"></a>
+<span class="sourceLineNo">558</span><a name="line.558"></a>
+<span class="sourceLineNo">559</span>    sanityCheckAssertion(dup.getInt(), onDiskSizeWithoutHeader, "onDiskSizeWithoutHeader");<a name="line.559"></a>
+<span class="sourceLineNo">560</span><a name="line.560"></a>
+<span class="sourceLineNo">561</span>    sanityCheckAssertion(dup.getInt(), uncompressedSizeWithoutHeader,<a name="line.561"></a>
+<span class="sourceLineNo">562</span>        "uncompressedSizeWithoutHeader");<a name="line.562"></a>
+<span class="sourceLineNo">563</span><a name="line.563"></a>
+<span class="sourceLineNo">564</span>    sanityCheckAssertion(dup.getLong(), prevBlockOffset, "prevBlockOffset");<a name="line.564"></a>
+<span class="sourceLineNo">565</span>    if (this.fileContext.isUseHBaseChecksum()) {<a name="line.565"></a>
+<span class="sourceLineNo">566</span>      sanityCheckAssertion(dup.get(), this.fileContext.getChecksumType().getCode(), "checksumType");<a name="line.566"></a>
+<span class="sourceLineNo">567</span>      sanityCheckAssertion(dup.getInt(), this.fileContext.getBytesPerChecksum(),<a name="line.567"></a>
+<span class="sourceLineNo">568</span>          "bytesPerChecksum");<a name="line.568"></a>
+<span class="sourceLineNo">569</span>      sanityCheckAssertion(dup.getInt(), onDiskDataSizeWithHeader, "onDiskDataSizeWithHeader");<a name="line.569"></a>
+<span class="sourceLineNo">570</span>    }<a name="line.570"></a>
+<span class="sourceLineNo">571</span><a name="line.571"></a>
+<span class="sourceLineNo">572</span>    int cksumBytes = totalChecksumBytes();<a name="line.572"></a>
+<span class="sourceLineNo">573</span>    int expectedBufLimit = onDiskDataSizeWithHeader + cksumBytes;<a name="line.573"></a>
+<span class="sourceLineNo">574</span>    if (dup.limit() != expectedBufLimit) {<a name="line.574"></a>
+<span class="sourceLineNo">575</span>      throw new AssertionError("Expected limit " + expectedBufLimit + ", got " + dup.limit());<a name="line.575"></a>
+<span class="sourceLineNo">576</span>    }<a name="line.576"></a>
+<span class="sourceLineNo">577</span><a name="line.577"></a>
+<span class="sourceLineNo">578</span>    // We might optionally allocate HFILEBLOCK_HEADER_SIZE more bytes to read the next<a name="line.578"></a>
+<span class="sourceLineNo">579</span>    // block's header, so there are two sensible values for buffer capacity.<a name="line.579"></a>
+<span class="sourceLineNo">580</span>    int hdrSize = headerSize();<a name="line.580"></a>
+<span class="sourceLineNo">581</span>    if (dup.capacity() != expectedBufLimit &amp;&amp; dup.capacity() != expectedBufLimit + hdrSize) {<a name="line.581"></a>
+<span class="sourceLineNo">582</span>      throw new AssertionError("Invalid buffer capacity: " + dup.capacity() +<a name="line.582"></a>
+<span class="sourceLineNo">583</span>          ", expected " + expectedBufLimit + " or " + (expectedBufLimit + hdrSize));<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>  @Override<a name="line.587"></a>
+<span class="sourceLineNo">588</span>  public String toString() {<a name="line.588"></a>
+<span class="sourceLineNo">589</span>    StringBuilder sb = new StringBuilder()<a name="line.589"></a>
+<span class="sourceLineNo">590</span>      .append("[")<a name="line.590"></a>
+<span class="sourceLineNo">591</span>      .append("blockType=").append(blockType)<a name="line.591"></a>
+<span class="sourceLineNo">592</span>      .append(", fileOffset=").append(offset)<a name="line.592"></a>
+<span class="sourceLineNo">593</span>      .append(", headerSize=").append(headerSize())<a name="line.593"></a>
+<span class="sourceLineNo">594</span>      .append(", onDiskSizeWithoutHeader=").append(onDiskSizeWithoutHeader)<a name="line.594"></a>
+<span class="sourceLineNo">595</span>      .append(", uncompressedSizeWithoutHeader=").append(uncompressedSizeWithoutHeader)<a name="line.595"></a>
+<span class="sourceLineNo">596</span>      .append(", prevBlockOffset=").append(prevBlockOffset)<a name="line.596"></a>
+<span class="sourceLineNo">597</span>      .append(", isUseHBaseChecksum=").append(fileContext.isUseHBaseChecksum());<a name="line.597"></a>
+<span class="sourceLineNo">598</span>    if (fileContext.isUseHBaseChecksum()) {<a name="line.598"></a>
+<span class="sourceLineNo">599</span>      sb.append(", checksumType=").append(ChecksumType.codeToType(this.buf.get(24)))<a name="line.599"></a>
+<span class="sourceLineNo">600</span>        .append(", bytesPerChecksum=").append(this.buf.getInt(24 + 1))<a name="line.600"></a>
+<span class="sourceLineNo">601</span>        .append(", onDiskDataSizeWithHeader=").append(onDiskDataSizeWithHeader);<a name="line.601"></a>
+<span class="sourceLineNo">602</span>    } else {<a name="line.602"></a>
+<span class="sourceLineNo">603</span>      sb.append(", onDiskDataSizeWithHeader=").append(onDiskDataSizeWithHeader)<a name="line.603"></a>
+<span class="sourceLineNo">604</span>        .append("(").append(onDiskSizeWithoutHeader)<a name="line.604"></a>
+<span class="sourceLineNo">605</span>        .append("+").append(HConstants.HFILEBLOCK_HEADER_SIZE_NO_CHECKSUM).append(")");<a name="line.605"></a>
+<span class="sourceLineNo">606</span>    }<a name="line.606"></a>
+<span class="sourceLineNo">607</span>    String dataBegin = null;<a name="line.607"></a>
+<span class="sourceLineNo">608</span>    if (buf.hasArray()) {<a name="line.608"></a>
+<span class="sourceLineNo">609</span>      dataBegin = Bytes.toStringBinary(buf.array(), buf.arrayOffset() + headerSize(),<a name="line.609"></a>
+<span class="sourceLineNo">610</span>          Math.min(32, buf.limit() - buf.arrayOffset() - headerSize()));<a name="line.610"></a>
+<span class="sourceLineNo">611</span>    } else {<a name="line.611"></a>
+<span class="sourceLineNo">612</span>      ByteBuff bufWithoutHeader = getBufferWithoutHeader();<a name="line.612"></a>
+<span class="sourceLineNo">613</span>      byte[] dataBeginBytes = new byte[Math.min(32,<a name="line.613"></a>
+<span class="sourceLineNo">614</span>          bufWithoutHeader.limit() - bufWithoutHeader.position())];<a name="line.614"></a>
+<span class="sourceLineNo">615</span>      bufWithoutHeader.get(dataBeginBytes);<a name="line.615"></a>
+<span class="sourceLineNo">616</span>      dataBegin = Bytes.toStringBinary(dataBeginBytes);<a name="line.616"></a>
+<span class="sourceLineNo">617</span>    }<a name="line.617"></a>
+<span class="sourceLineNo">618</span>    sb.append(", getOnDiskSizeWithHeader=").append(getOnDiskSizeWithHeader())<a name="line.618"></a>
+<span class="sourceLineNo">619</span>      .append(", totalChecksumBytes=").append(totalChecksumBytes())<a name="line.619"></a>
+<span class="sourceLineNo">620</span>      .append(", isUnpacked=").append(isUnpacked())<a name="line.620"></a>
+<span class="sourceLineNo">621</span>      .append(", buf=[").append(buf).append("]")<a name="line.621"></a>
+<span class="sourceLineNo">622</span>      .append(", dataBeginsWith=").append(dataBegin)<a name="line.622"></a>
+<span class="sourceLineNo">623</span>      .append(", fileContext=").append(fileContext)<a name="line.623"></a>
+<span class="sourceLineNo">624</span>      .append(", nextBlockOnDiskSize=").append(nextBlockOnDiskSize)<a name="line.624"></a>
+<span class="sourceLineNo">625</span>      .append("]");<a name="line.625"></a>
+<span class="sourceLineNo">626</span>    return sb.toString();<a name="line.626"></a>
+<span class="sourceLineNo">627</span>  }<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>   * Retrieves the decompressed/decrypted view of this block. An encoded block remains in its<a name="line.630"></a>
+<span class="sourceLineNo">631</span>   * encoded structure. Internal structures are shared between instances where applicable.<a name="line.631"></a>
+<span class="sourceLineNo">632</span>   */<a name="line.632"></a>
+<span class="sourceLineNo">633</span>  HFileBlock unpack(HFileContext fileContext, FSReader reader) throws IOException {<a name="line.633"></a>
+<span class="sourceLineNo">634</span>    if (!fileContext.isCompressedOrEncrypted()) {<a name="line.634"></a>
+<span class="sourceLineNo">635</span>      // TODO: cannot use our own fileContext here because HFileBlock(ByteBuffer, boolean),<a name="line.635"></a>
+<span class="sourceLineNo">636</span>      // which is used for block serialization to L2 cache, does not preserve encoding and<a name="line.636"></a>
+<span class="sourceLineNo">637</span>      // encryption details.<a name="line.637"></a>
+<span class="sourceLineNo">638</span>      return this;<a name="line.638"></a>
+<span class="sourceLineNo">639</span>    }<a name="line.639"></a>
+<span class="sourceLineNo">640</span><a name="line.640"></a>
+<span class="sourceLineNo">641</span>    HFileBlock unpacked = new HFileBlock(this);<a name="line.641"></a>
+<span class="sourceLineNo">642</span>    unpacked.allocateBuffer(); // allocates space for the decompressed block<a name="line.642"></a>
+<span class="sourceLineNo">643</span><a name="line.643"></a>
+<span class="sourceLineNo">644</span>    HFileBlockDecodingContext ctx = blockType == BlockType.ENCODED_DATA ?<a name="line.644"></a>
+<span class="sourceLineNo">645</span>      reader.getBlockDecodingContext() : reader.getDefaultBlockDecodingContext();<a name="line.645"></a>
+<span class="sourceLineNo">646</span><a name="line.646"></a>
+<span class="sourceLineNo">647</span>    ByteBuff dup = this.buf.duplicate();<a name="line.647"></a>
+<span class="sourceLineNo">648</span>    dup.position(this.headerSize());<a name="line.648"></a>
+<span class="sourceLineNo">649</span>    dup = dup.slice();<a name="line.649"></a>
+<span class="sourceLineNo">650</span>    ctx.prepareDecodi

<TRUNCATED>

[34/50] hbase-site git commit: Published site at 26babcf013de696b899d76a3c39434b794440d8d.

Posted by gi...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.PrefetchedHeader.html
----------------------------------------------------------------------
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.PrefetchedHeader.html b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.PrefetchedHeader.html
index 97ceefd..b7b4236 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.PrefetchedHeader.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.PrefetchedHeader.html
@@ -103,8 +103,8 @@
 <span class="sourceLineNo">095</span> * Caches cache whole blocks with trailing checksums if any. We then tag on some metadata, the<a name="line.95"></a>
 <span class="sourceLineNo">096</span> * content of BLOCK_METADATA_SPACE which will be flag on if we are doing 'hbase'<a name="line.96"></a>
 <span class="sourceLineNo">097</span> * checksums and then the offset into the file which is needed when we re-make a cache key<a name="line.97"></a>
-<span class="sourceLineNo">098</span> * when we return the block to the cache as 'done'. See {@link Cacheable#serialize(ByteBuffer)} and<a name="line.98"></a>
-<span class="sourceLineNo">099</span> * {@link Cacheable#getDeserializer()}.<a name="line.99"></a>
+<span class="sourceLineNo">098</span> * when we return the block to the cache as 'done'.<a name="line.98"></a>
+<span class="sourceLineNo">099</span> * See {@link Cacheable#serialize(ByteBuffer, boolean)} and {@link Cacheable#getDeserializer()}.<a name="line.99"></a>
 <span class="sourceLineNo">100</span> *<a name="line.100"></a>
 <span class="sourceLineNo">101</span> * &lt;p&gt;TODO: Should we cache the checksums? Down in Writer#getBlockForCaching(CacheConfig) where<a name="line.101"></a>
 <span class="sourceLineNo">102</span> * we make a block to cache-on-write, there is an attempt at turning off checksums. This is not the<a name="line.102"></a>
@@ -333,1579 +333,1579 @@
 <span class="sourceLineNo">325</span>   * Creates a new {@link HFile} block from the given fields. This constructor<a name="line.325"></a>
 <span class="sourceLineNo">326</span>   * is used only while writing blocks and caching,<a name="line.326"></a>
 <span class="sourceLineNo">327</span>   * and is sitting in a byte buffer and we want to stuff the block into cache.<a name="line.327"></a>
-<span class="sourceLineNo">328</span>   * See {@link Writer#getBlockForCaching(CacheConfig)}.<a name="line.328"></a>
-<span class="sourceLineNo">329</span>   *<a name="line.329"></a>
-<span class="sourceLineNo">330</span>   * &lt;p&gt;TODO: The caller presumes no checksumming<a name="line.330"></a>
-<span class="sourceLineNo">331</span>   * required of this block instance since going into cache; checksum already verified on<a name="line.331"></a>
-<span class="sourceLineNo">332</span>   * underlying block data pulled in from filesystem. Is that correct? What if cache is SSD?<a name="line.332"></a>
-<span class="sourceLineNo">333</span>   *<a name="line.333"></a>
-<span class="sourceLineNo">334</span>   * @param blockType the type of this block, see {@link BlockType}<a name="line.334"></a>
-<span class="sourceLineNo">335</span>   * @param onDiskSizeWithoutHeader see {@link #onDiskSizeWithoutHeader}<a name="line.335"></a>
-<span class="sourceLineNo">336</span>   * @param uncompressedSizeWithoutHeader see {@link #uncompressedSizeWithoutHeader}<a name="line.336"></a>
-<span class="sourceLineNo">337</span>   * @param prevBlockOffset see {@link #prevBlockOffset}<a name="line.337"></a>
-<span class="sourceLineNo">338</span>   * @param b block header ({@link HConstants#HFILEBLOCK_HEADER_SIZE} bytes)<a name="line.338"></a>
-<span class="sourceLineNo">339</span>   * @param fillHeader when true, write the first 4 header fields into passed buffer.<a name="line.339"></a>
-<span class="sourceLineNo">340</span>   * @param offset the file offset the block was read from<a name="line.340"></a>
-<span class="sourceLineNo">341</span>   * @param onDiskDataSizeWithHeader see {@link #onDiskDataSizeWithHeader}<a name="line.341"></a>
-<span class="sourceLineNo">342</span>   * @param fileContext HFile meta data<a name="line.342"></a>
-<span class="sourceLineNo">343</span>   */<a name="line.343"></a>
-<span class="sourceLineNo">344</span>  HFileBlock(BlockType blockType, int onDiskSizeWithoutHeader, int uncompressedSizeWithoutHeader,<a name="line.344"></a>
-<span class="sourceLineNo">345</span>      long prevBlockOffset, ByteBuffer b, boolean fillHeader, long offset,<a name="line.345"></a>
-<span class="sourceLineNo">346</span>      final int nextBlockOnDiskSize, int onDiskDataSizeWithHeader, HFileContext fileContext) {<a name="line.346"></a>
-<span class="sourceLineNo">347</span>    init(blockType, onDiskSizeWithoutHeader, uncompressedSizeWithoutHeader,<a name="line.347"></a>
-<span class="sourceLineNo">348</span>        prevBlockOffset, offset, onDiskDataSizeWithHeader, nextBlockOnDiskSize, fileContext);<a name="line.348"></a>
-<span class="sourceLineNo">349</span>    this.buf = new SingleByteBuff(b);<a name="line.349"></a>
-<span class="sourceLineNo">350</span>    if (fillHeader) {<a name="line.350"></a>
-<span class="sourceLineNo">351</span>      overwriteHeader();<a name="line.351"></a>
-<span class="sourceLineNo">352</span>    }<a name="line.352"></a>
-<span class="sourceLineNo">353</span>    this.buf.rewind();<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>  /**<a name="line.356"></a>
-<span class="sourceLineNo">357</span>   * Creates a block from an existing buffer starting with a header. Rewinds<a name="line.357"></a>
-<span class="sourceLineNo">358</span>   * and takes ownership of the buffer. By definition of rewind, ignores the<a name="line.358"></a>
-<span class="sourceLineNo">359</span>   * buffer position, but if you slice the buffer beforehand, it will rewind<a name="line.359"></a>
-<span class="sourceLineNo">360</span>   * to that point.<a name="line.360"></a>
-<span class="sourceLineNo">361</span>   * @param buf Has header, content, and trailing checksums if present.<a name="line.361"></a>
-<span class="sourceLineNo">362</span>   */<a name="line.362"></a>
-<span class="sourceLineNo">363</span>  HFileBlock(ByteBuff buf, boolean usesHBaseChecksum, MemoryType memType, final long offset,<a name="line.363"></a>
-<span class="sourceLineNo">364</span>      final int nextBlockOnDiskSize, HFileContext fileContext) throws IOException {<a name="line.364"></a>
-<span class="sourceLineNo">365</span>    buf.rewind();<a name="line.365"></a>
-<span class="sourceLineNo">366</span>    final BlockType blockType = BlockType.read(buf);<a name="line.366"></a>
-<span class="sourceLineNo">367</span>    final int onDiskSizeWithoutHeader = buf.getInt(Header.ON_DISK_SIZE_WITHOUT_HEADER_INDEX);<a name="line.367"></a>
-<span class="sourceLineNo">368</span>    final int uncompressedSizeWithoutHeader =<a name="line.368"></a>
-<span class="sourceLineNo">369</span>        buf.getInt(Header.UNCOMPRESSED_SIZE_WITHOUT_HEADER_INDEX);<a name="line.369"></a>
-<span class="sourceLineNo">370</span>    final long prevBlockOffset = buf.getLong(Header.PREV_BLOCK_OFFSET_INDEX);<a name="line.370"></a>
-<span class="sourceLineNo">371</span>    // This constructor is called when we deserialize a block from cache and when we read a block in<a name="line.371"></a>
-<span class="sourceLineNo">372</span>    // from the fs. fileCache is null when deserialized from cache so need to make up one.<a name="line.372"></a>
-<span class="sourceLineNo">373</span>    HFileContextBuilder fileContextBuilder = fileContext != null?<a name="line.373"></a>
-<span class="sourceLineNo">374</span>        new HFileContextBuilder(fileContext): new HFileContextBuilder();<a name="line.374"></a>
-<span class="sourceLineNo">375</span>    fileContextBuilder.withHBaseCheckSum(usesHBaseChecksum);<a name="line.375"></a>
-<span class="sourceLineNo">376</span>    int onDiskDataSizeWithHeader;<a name="line.376"></a>
-<span class="sourceLineNo">377</span>    if (usesHBaseChecksum) {<a name="line.377"></a>
-<span class="sourceLineNo">378</span>      byte checksumType = buf.get(Header.CHECKSUM_TYPE_INDEX);<a name="line.378"></a>
-<span class="sourceLineNo">379</span>      int bytesPerChecksum = buf.getInt(Header.BYTES_PER_CHECKSUM_INDEX);<a name="line.379"></a>
-<span class="sourceLineNo">380</span>      onDiskDataSizeWithHeader = buf.getInt(Header.ON_DISK_DATA_SIZE_WITH_HEADER_INDEX);<a name="line.380"></a>
-<span class="sourceLineNo">381</span>      // Use the checksum type and bytes per checksum from header, not from filecontext.<a name="line.381"></a>
-<span class="sourceLineNo">382</span>      fileContextBuilder.withChecksumType(ChecksumType.codeToType(checksumType));<a name="line.382"></a>
-<span class="sourceLineNo">383</span>      fileContextBuilder.withBytesPerCheckSum(bytesPerChecksum);<a name="line.383"></a>
-<span class="sourceLineNo">384</span>    } else {<a name="line.384"></a>
-<span class="sourceLineNo">385</span>      fileContextBuilder.withChecksumType(ChecksumType.NULL);<a name="line.385"></a>
-<span class="sourceLineNo">386</span>      fileContextBuilder.withBytesPerCheckSum(0);<a name="line.386"></a>
-<span class="sourceLineNo">387</span>      // Need to fix onDiskDataSizeWithHeader; there are not checksums after-block-data<a name="line.387"></a>
-<span class="sourceLineNo">388</span>      onDiskDataSizeWithHeader = onDiskSizeWithoutHeader + headerSize(usesHBaseChecksum);<a name="line.388"></a>
-<span class="sourceLineNo">389</span>    }<a name="line.389"></a>
-<span class="sourceLineNo">390</span>    fileContext = fileContextBuilder.build();<a name="line.390"></a>
-<span class="sourceLineNo">391</span>    assert usesHBaseChecksum == fileContext.isUseHBaseChecksum();<a name="line.391"></a>
-<span class="sourceLineNo">392</span>    init(blockType, onDiskSizeWithoutHeader, uncompressedSizeWithoutHeader,<a name="line.392"></a>
-<span class="sourceLineNo">393</span>        prevBlockOffset, offset, onDiskDataSizeWithHeader, nextBlockOnDiskSize, fileContext);<a name="line.393"></a>
-<span class="sourceLineNo">394</span>    this.memType = memType;<a name="line.394"></a>
-<span class="sourceLineNo">395</span>    this.offset = offset;<a name="line.395"></a>
-<span class="sourceLineNo">396</span>    this.buf = buf;<a name="line.396"></a>
-<span class="sourceLineNo">397</span>    this.buf.rewind();<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>  /**<a name="line.400"></a>
-<span class="sourceLineNo">401</span>   * Called from constructors.<a name="line.401"></a>
-<span class="sourceLineNo">402</span>   */<a name="line.402"></a>
-<span class="sourceLineNo">403</span>  private void init(BlockType blockType, int onDiskSizeWithoutHeader,<a name="line.403"></a>
-<span class="sourceLineNo">404</span>      int uncompressedSizeWithoutHeader, long prevBlockOffset,<a name="line.404"></a>
-<span class="sourceLineNo">405</span>      long offset, int onDiskDataSizeWithHeader, final int nextBlockOnDiskSize,<a name="line.405"></a>
-<span class="sourceLineNo">406</span>      HFileContext fileContext) {<a name="line.406"></a>
-<span class="sourceLineNo">407</span>    this.blockType = blockType;<a name="line.407"></a>
-<span class="sourceLineNo">408</span>    this.onDiskSizeWithoutHeader = onDiskSizeWithoutHeader;<a name="line.408"></a>
-<span class="sourceLineNo">409</span>    this.uncompressedSizeWithoutHeader = uncompressedSizeWithoutHeader;<a name="line.409"></a>
-<span class="sourceLineNo">410</span>    this.prevBlockOffset = prevBlockOffset;<a name="line.410"></a>
-<span class="sourceLineNo">411</span>    this.offset = offset;<a name="line.411"></a>
-<span class="sourceLineNo">412</span>    this.onDiskDataSizeWithHeader = onDiskDataSizeWithHeader;<a name="line.412"></a>
-<span class="sourceLineNo">413</span>    this.nextBlockOnDiskSize = nextBlockOnDiskSize;<a name="line.413"></a>
-<span class="sourceLineNo">414</span>    this.fileContext = fileContext;<a name="line.414"></a>
-<span class="sourceLineNo">415</span>  }<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">418</span>   * Parse total on disk size including header and checksum.<a name="line.418"></a>
-<span class="sourceLineNo">419</span>   * @param headerBuf Header ByteBuffer. Presumed exact size of header.<a name="line.419"></a>
-<span class="sourceLineNo">420</span>   * @param verifyChecksum true if checksum verification is in use.<a name="line.420"></a>
-<span class="sourceLineNo">421</span>   * @return Size of the block with header included.<a name="line.421"></a>
-<span class="sourceLineNo">422</span>   */<a name="line.422"></a>
-<span class="sourceLineNo">423</span>  private static int getOnDiskSizeWithHeader(final ByteBuffer headerBuf,<a name="line.423"></a>
-<span class="sourceLineNo">424</span>      boolean verifyChecksum) {<a name="line.424"></a>
-<span class="sourceLineNo">425</span>    return headerBuf.getInt(Header.ON_DISK_SIZE_WITHOUT_HEADER_INDEX) +<a name="line.425"></a>
-<span class="sourceLineNo">426</span>      headerSize(verifyChecksum);<a name="line.426"></a>
-<span class="sourceLineNo">427</span>  }<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>   * @return the on-disk size of the next block (including the header size and any checksums if<a name="line.430"></a>
-<span class="sourceLineNo">431</span>   * present) read by peeking into the next block's header; use as a hint when doing<a name="line.431"></a>
-<span class="sourceLineNo">432</span>   * a read of the next block when scanning or running over a file.<a name="line.432"></a>
-<span class="sourceLineNo">433</span>   */<a name="line.433"></a>
-<span class="sourceLineNo">434</span>  int getNextBlockOnDiskSize() {<a name="line.434"></a>
-<span class="sourceLineNo">435</span>    return nextBlockOnDiskSize;<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>  @Override<a name="line.438"></a>
-<span class="sourceLineNo">439</span>  public BlockType getBlockType() {<a name="line.439"></a>
-<span class="sourceLineNo">440</span>    return blockType;<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>  /** @return get data block encoding id that was used to encode this block */<a name="line.443"></a>
-<span class="sourceLineNo">444</span>  short getDataBlockEncodingId() {<a name="line.444"></a>
-<span class="sourceLineNo">445</span>    if (blockType != BlockType.ENCODED_DATA) {<a name="line.445"></a>
-<span class="sourceLineNo">446</span>      throw new IllegalArgumentException("Querying encoder ID of a block " +<a name="line.446"></a>
-<span class="sourceLineNo">447</span>          "of type other than " + BlockType.ENCODED_DATA + ": " + blockType);<a name="line.447"></a>
-<span class="sourceLineNo">448</span>    }<a name="line.448"></a>
-<span class="sourceLineNo">449</span>    return buf.getShort(headerSize());<a name="line.449"></a>
-<span class="sourceLineNo">450</span>  }<a name="line.450"></a>
-<span class="sourceLineNo">451</span><a name="line.451"></a>
-<span class="sourceLineNo">452</span>  /**<a name="line.452"></a>
-<span class="sourceLineNo">453</span>   * @return the on-disk size of header + data part + checksum.<a name="line.453"></a>
-<span class="sourceLineNo">454</span>   */<a name="line.454"></a>
-<span class="sourceLineNo">455</span>  public int getOnDiskSizeWithHeader() {<a name="line.455"></a>
-<span class="sourceLineNo">456</span>    return onDiskSizeWithoutHeader + headerSize();<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>   * @return the on-disk size of the data part + checksum (header excluded).<a name="line.460"></a>
-<span class="sourceLineNo">461</span>   */<a name="line.461"></a>
-<span class="sourceLineNo">462</span>  int getOnDiskSizeWithoutHeader() {<a name="line.462"></a>
-<span class="sourceLineNo">463</span>    return onDiskSizeWithoutHeader;<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>  /**<a name="line.466"></a>
-<span class="sourceLineNo">467</span>   * @return the uncompressed size of data part (header and checksum excluded).<a name="line.467"></a>
-<span class="sourceLineNo">468</span>   */<a name="line.468"></a>
-<span class="sourceLineNo">469</span>   int getUncompressedSizeWithoutHeader() {<a name="line.469"></a>
-<span class="sourceLineNo">470</span>    return uncompressedSizeWithoutHeader;<a name="line.470"></a>
-<span class="sourceLineNo">471</span>  }<a name="line.471"></a>
-<span class="sourceLineNo">472</span><a name="line.472"></a>
-<span class="sourceLineNo">473</span>  /**<a name="line.473"></a>
-<span class="sourceLineNo">474</span>   * @return the offset of the previous block of the same type in the file, or<a name="line.474"></a>
-<span class="sourceLineNo">475</span>   *         -1 if unknown<a name="line.475"></a>
-<span class="sourceLineNo">476</span>   */<a name="line.476"></a>
-<span class="sourceLineNo">477</span>  long getPrevBlockOffset() {<a name="line.477"></a>
-<span class="sourceLineNo">478</span>    return prevBlockOffset;<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>   * Rewinds {@code buf} and writes first 4 header fields. {@code buf} position<a name="line.482"></a>
-<span class="sourceLineNo">483</span>   * is modified as side-effect.<a name="line.483"></a>
-<span class="sourceLineNo">484</span>   */<a name="line.484"></a>
-<span class="sourceLineNo">485</span>  private void overwriteHeader() {<a name="line.485"></a>
-<span class="sourceLineNo">486</span>    buf.rewind();<a name="line.486"></a>
-<span class="sourceLineNo">487</span>    blockType.write(buf);<a name="line.487"></a>
-<span class="sourceLineNo">488</span>    buf.putInt(onDiskSizeWithoutHeader);<a name="line.488"></a>
-<span class="sourceLineNo">489</span>    buf.putInt(uncompressedSizeWithoutHeader);<a name="line.489"></a>
-<span class="sourceLineNo">490</span>    buf.putLong(prevBlockOffset);<a name="line.490"></a>
-<span class="sourceLineNo">491</span>    if (this.fileContext.isUseHBaseChecksum()) {<a name="line.491"></a>
-<span class="sourceLineNo">492</span>      buf.put(fileContext.getChecksumType().getCode());<a name="line.492"></a>
-<span class="sourceLineNo">493</span>      buf.putInt(fileContext.getBytesPerChecksum());<a name="line.493"></a>
-<span class="sourceLineNo">494</span>      buf.putInt(onDiskDataSizeWithHeader);<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>  /**<a name="line.498"></a>
-<span class="sourceLineNo">499</span>   * Returns a buffer that does not include the header or checksum.<a name="line.499"></a>
-<span class="sourceLineNo">500</span>   *<a name="line.500"></a>
-<span class="sourceLineNo">501</span>   * @return the buffer with header skipped and checksum omitted.<a name="line.501"></a>
-<span class="sourceLineNo">502</span>   */<a name="line.502"></a>
-<span class="sourceLineNo">503</span>  public ByteBuff getBufferWithoutHeader() {<a name="line.503"></a>
-<span class="sourceLineNo">504</span>    ByteBuff dup = getBufferReadOnly();<a name="line.504"></a>
-<span class="sourceLineNo">505</span>    // Now set it up so Buffer spans content only -- no header or no checksums.<a name="line.505"></a>
-<span class="sourceLineNo">506</span>    return dup.position(headerSize()).limit(buf.limit() - totalChecksumBytes()).slice();<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 a read-only duplicate of the buffer this block stores internally ready to be read.<a name="line.510"></a>
-<span class="sourceLineNo">511</span>   * Clients must not modify the buffer object though they may set position and limit on the<a name="line.511"></a>
-<span class="sourceLineNo">512</span>   * returned buffer since we pass back a duplicate. This method has to be public because it is used<a name="line.512"></a>
-<span class="sourceLineNo">513</span>   * in {@link CompoundBloomFilter} to avoid object creation on every Bloom<a name="line.513"></a>
-<span class="sourceLineNo">514</span>   * filter lookup, but has to be used with caution. Buffer holds header, block content,<a name="line.514"></a>
-<span class="sourceLineNo">515</span>   * and any follow-on checksums if present.<a name="line.515"></a>
-<span class="sourceLineNo">516</span>   *<a name="line.516"></a>
-<span class="sourceLineNo">517</span>   * @return the buffer of this block for read-only operations<a name="line.517"></a>
-<span class="sourceLineNo">518</span>   */<a name="line.518"></a>
-<span class="sourceLineNo">519</span>  public ByteBuff getBufferReadOnly() {<a name="line.519"></a>
-<span class="sourceLineNo">520</span>    // TODO: ByteBuf does not support asReadOnlyBuffer(). Fix.<a name="line.520"></a>
-<span class="sourceLineNo">521</span>    ByteBuff dup = this.buf.duplicate();<a name="line.521"></a>
-<span class="sourceLineNo">522</span>    assert dup.position() == 0;<a name="line.522"></a>
-<span class="sourceLineNo">523</span>    return dup;<a name="line.523"></a>
-<span class="sourceLineNo">524</span>  }<a name="line.524"></a>
-<span class="sourceLineNo">525</span><a name="line.525"></a>
-<span class="sourceLineNo">526</span>  @VisibleForTesting<a name="line.526"></a>
-<span class="sourceLineNo">527</span>  private void sanityCheckAssertion(long valueFromBuf, long valueFromField,<a name="line.527"></a>
-<span class="sourceLineNo">528</span>      String fieldName) throws IOException {<a name="line.528"></a>
-<span class="sourceLineNo">529</span>    if (valueFromBuf != valueFromField) {<a name="line.529"></a>
-<span class="sourceLineNo">530</span>      throw new AssertionError(fieldName + " in the buffer (" + valueFromBuf<a name="line.530"></a>
-<span class="sourceLineNo">531</span>          + ") is different from that in the field (" + valueFromField + ")");<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>  @VisibleForTesting<a name="line.535"></a>
-<span class="sourceLineNo">536</span>  private void sanityCheckAssertion(BlockType valueFromBuf, BlockType valueFromField)<a name="line.536"></a>
-<span class="sourceLineNo">537</span>      throws IOException {<a name="line.537"></a>
-<span class="sourceLineNo">538</span>    if (valueFromBuf != valueFromField) {<a name="line.538"></a>
-<span class="sourceLineNo">539</span>      throw new IOException("Block type stored in the buffer: " +<a name="line.539"></a>
-<span class="sourceLineNo">540</span>        valueFromBuf + ", block type field: " + valueFromField);<a name="line.540"></a>
-<span class="sourceLineNo">541</span>    }<a name="line.541"></a>
-<span class="sourceLineNo">542</span>  }<a name="line.542"></a>
-<span class="sourceLineNo">543</span><a name="line.543"></a>
-<span class="sourceLineNo">544</span>  /**<a name="line.544"></a>
-<span class="sourceLineNo">545</span>   * Checks if the block is internally consistent, i.e. the first<a name="line.545"></a>
-<span class="sourceLineNo">546</span>   * {@link HConstants#HFILEBLOCK_HEADER_SIZE} bytes of the buffer contain a<a name="line.546"></a>
-<span class="sourceLineNo">547</span>   * valid header consistent with the fields. Assumes a packed block structure.<a name="line.547"></a>
-<span class="sourceLineNo">548</span>   * This function is primary for testing and debugging, and is not<a name="line.548"></a>
-<span class="sourceLineNo">549</span>   * thread-safe, because it alters the internal buffer pointer.<a name="line.549"></a>
-<span class="sourceLineNo">550</span>   * Used by tests only.<a name="line.550"></a>
-<span class="sourceLineNo">551</span>   */<a name="line.551"></a>
-<span class="sourceLineNo">552</span>  @VisibleForTesting<a name="line.552"></a>
-<span class="sourceLineNo">553</span>  void sanityCheck() throws IOException {<a name="line.553"></a>
-<span class="sourceLineNo">554</span>    // Duplicate so no side-effects<a name="line.554"></a>
-<span class="sourceLineNo">555</span>    ByteBuff dup = this.buf.duplicate().rewind();<a name="line.555"></a>
-<span class="sourceLineNo">556</span>    sanityCheckAssertion(BlockType.read(dup), blockType);<a name="line.556"></a>
-<span class="sourceLineNo">557</span><a name="line.557"></a>
-<span class="sourceLineNo">558</span>    sanityCheckAssertion(dup.getInt(), onDiskSizeWithoutHeader, "onDiskSizeWithoutHeader");<a name="line.558"></a>
-<span class="sourceLineNo">559</span><a name="line.559"></a>
-<span class="sourceLineNo">560</span>    sanityCheckAssertion(dup.getInt(), uncompressedSizeWithoutHeader,<a name="line.560"></a>
-<span class="sourceLineNo">561</span>        "uncompressedSizeWithoutHeader");<a name="line.561"></a>
-<span class="sourceLineNo">562</span><a name="line.562"></a>
-<span class="sourceLineNo">563</span>    sanityCheckAssertion(dup.getLong(), prevBlockOffset, "prevBlockOffset");<a name="line.563"></a>
-<span class="sourceLineNo">564</span>    if (this.fileContext.isUseHBaseChecksum()) {<a name="line.564"></a>
-<span class="sourceLineNo">565</span>      sanityCheckAssertion(dup.get(), this.fileContext.getChecksumType().getCode(), "checksumType");<a name="line.565"></a>
-<span class="sourceLineNo">566</span>      sanityCheckAssertion(dup.getInt(), this.fileContext.getBytesPerChecksum(),<a name="line.566"></a>
-<span class="sourceLineNo">567</span>          "bytesPerChecksum");<a name="line.567"></a>
-<span class="sourceLineNo">568</span>      sanityCheckAssertion(dup.getInt(), onDiskDataSizeWithHeader, "onDiskDataSizeWithHeader");<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>    int cksumBytes = totalChecksumBytes();<a name="line.571"></a>
-<span class="sourceLineNo">572</span>    int expectedBufLimit = onDiskDataSizeWithHeader + cksumBytes;<a name="line.572"></a>
-<span class="sourceLineNo">573</span>    if (dup.limit() != expectedBufLimit) {<a name="line.573"></a>
-<span class="sourceLineNo">574</span>      throw new AssertionError("Expected limit " + expectedBufLimit + ", got " + dup.limit());<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>    // We might optionally allocate HFILEBLOCK_HEADER_SIZE more bytes to read the next<a name="line.577"></a>
-<span class="sourceLineNo">578</span>    // block's header, so there are two sensible values for buffer capacity.<a name="line.578"></a>
-<span class="sourceLineNo">579</span>    int hdrSize = headerSize();<a name="line.579"></a>
-<span class="sourceLineNo">580</span>    if (dup.capacity() != expectedBufLimit &amp;&amp; dup.capacity() != expectedBufLimit + hdrSize) {<a name="line.580"></a>
-<span class="sourceLineNo">581</span>      throw new AssertionError("Invalid buffer capacity: " + dup.capacity() +<a name="line.581"></a>
-<span class="sourceLineNo">582</span>          ", expected " + expectedBufLimit + " or " + (expectedBufLimit + hdrSize));<a name="line.582"></a>
-<span class="sourceLineNo">583</span>    }<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>  @Override<a name="line.586"></a>
-<span class="sourceLineNo">587</span>  public String toString() {<a name="line.587"></a>
-<span class="sourceLineNo">588</span>    StringBuilder sb = new StringBuilder()<a name="line.588"></a>
-<span class="sourceLineNo">589</span>      .append("[")<a name="line.589"></a>
-<span class="sourceLineNo">590</span>      .append("blockType=").append(blockType)<a name="line.590"></a>
-<span class="sourceLineNo">591</span>      .append(", fileOffset=").append(offset)<a name="line.591"></a>
-<span class="sourceLineNo">592</span>      .append(", headerSize=").append(headerSize())<a name="line.592"></a>
-<span class="sourceLineNo">593</span>      .append(", onDiskSizeWithoutHeader=").append(onDiskSizeWithoutHeader)<a name="line.593"></a>
-<span class="sourceLineNo">594</span>      .append(", uncompressedSizeWithoutHeader=").append(uncompressedSizeWithoutHeader)<a name="line.594"></a>
-<span class="sourceLineNo">595</span>      .append(", prevBlockOffset=").append(prevBlockOffset)<a name="line.595"></a>
-<span class="sourceLineNo">596</span>      .append(", isUseHBaseChecksum=").append(fileContext.isUseHBaseChecksum());<a name="line.596"></a>
-<span class="sourceLineNo">597</span>    if (fileContext.isUseHBaseChecksum()) {<a name="line.597"></a>
-<span class="sourceLineNo">598</span>      sb.append(", checksumType=").append(ChecksumType.codeToType(this.buf.get(24)))<a name="line.598"></a>
-<span class="sourceLineNo">599</span>        .append(", bytesPerChecksum=").append(this.buf.getInt(24 + 1))<a name="line.599"></a>
-<span class="sourceLineNo">600</span>        .append(", onDiskDataSizeWithHeader=").append(onDiskDataSizeWithHeader);<a name="line.600"></a>
-<span class="sourceLineNo">601</span>    } else {<a name="line.601"></a>
-<span class="sourceLineNo">602</span>      sb.append(", onDiskDataSizeWithHeader=").append(onDiskDataSizeWithHeader)<a name="line.602"></a>
-<span class="sourceLineNo">603</span>        .append("(").append(onDiskSizeWithoutHeader)<a name="line.603"></a>
-<span class="sourceLineNo">604</span>        .append("+").append(HConstants.HFILEBLOCK_HEADER_SIZE_NO_CHECKSUM).append(")");<a name="line.604"></a>
-<span class="sourceLineNo">605</span>    }<a name="line.605"></a>
-<span class="sourceLineNo">606</span>    String dataBegin = null;<a name="line.606"></a>
-<span class="sourceLineNo">607</span>    if (buf.hasArray()) {<a name="line.607"></a>
-<span class="sourceLineNo">608</span>      dataBegin = Bytes.toStringBinary(buf.array(), buf.arrayOffset() + headerSize(),<a name="line.608"></a>
-<span class="sourceLineNo">609</span>          Math.min(32, buf.limit() - buf.arrayOffset() - headerSize()));<a name="line.609"></a>
-<span class="sourceLineNo">610</span>    } else {<a name="line.610"></a>
-<span class="sourceLineNo">611</span>      ByteBuff bufWithoutHeader = getBufferWithoutHeader();<a name="line.611"></a>
-<span class="sourceLineNo">612</span>      byte[] dataBeginBytes = new byte[Math.min(32,<a name="line.612"></a>
-<span class="sourceLineNo">613</span>          bufWithoutHeader.limit() - bufWithoutHeader.position())];<a name="line.613"></a>
-<span class="sourceLineNo">614</span>      bufWithoutHeader.get(dataBeginBytes);<a name="line.614"></a>
-<span class="sourceLineNo">615</span>      dataBegin = Bytes.toStringBinary(dataBeginBytes);<a name="line.615"></a>
-<span class="sourceLineNo">616</span>    }<a name="line.616"></a>
-<span class="sourceLineNo">617</span>    sb.append(", getOnDiskSizeWithHeader=").append(getOnDiskSizeWithHeader())<a name="line.617"></a>
-<span class="sourceLineNo">618</span>      .append(", totalChecksumBytes=").append(totalChecksumBytes())<a name="line.618"></a>
-<span class="sourceLineNo">619</span>      .append(", isUnpacked=").append(isUnpacked())<a name="line.619"></a>
-<span class="sourceLineNo">620</span>      .append(", buf=[").append(buf).append("]")<a name="line.620"></a>
-<span class="sourceLineNo">621</span>      .append(", dataBeginsWith=").append(dataBegin)<a name="line.621"></a>
-<span class="sourceLineNo">622</span>      .append(", fileContext=").append(fileContext)<a name="line.622"></a>
-<span class="sourceLineNo">623</span>      .append("]");<a name="line.623"></a>
-<span class="sourceLineNo">624</span>    return sb.toString();<a name="line.624"></a>
-<span class="sourceLineNo">625</span>  }<a name="line.625"></a>
-<span class="sourceLineNo">626</span><a name="line.626"></a>
-<span class="sourceLineNo">627</span>  /**<a name="line.627"></a>
-<span class="sourceLineNo">628</span>   * Retrieves the decompressed/decrypted view of this block. An encoded block remains in its<a name="line.628"></a>
-<span class="sourceLineNo">629</span>   * encoded structure. Internal structures are shared between instances where applicable.<a name="line.629"></a>
-<span class="sourceLineNo">630</span>   */<a name="line.630"></a>
-<span class="sourceLineNo">631</span>  HFileBlock unpack(HFileContext fileContext, FSReader reader) throws IOException {<a name="line.631"></a>
-<span class="sourceLineNo">632</span>    if (!fileContext.isCompressedOrEncrypted()) {<a name="line.632"></a>
-<span class="sourceLineNo">633</span>      // TODO: cannot use our own fileContext here because HFileBlock(ByteBuffer, boolean),<a name="line.633"></a>
-<span class="sourceLineNo">634</span>      // which is used for block serialization to L2 cache, does not preserve encoding and<a name="line.634"></a>
-<span class="sourceLineNo">635</span>      // encryption details.<a name="line.635"></a>
-<span class="sourceLineNo">636</span>      return this;<a name="line.636"></a>
-<span class="sourceLineNo">637</span>    }<a name="line.637"></a>
-<span class="sourceLineNo">638</span><a name="line.638"></a>
-<span class="sourceLineNo">639</span>    HFileBlock unpacked = new HFileBlock(this);<a name="line.639"></a>
-<span class="sourceLineNo">640</span>    unpacked.allocateBuffer(); // allocates space for the decompressed block<a name="line.640"></a>
-<span class="sourceLineNo">641</span><a name="line.641"></a>
-<span class="sourceLineNo">642</span>    HFileBlockDecodingContext ctx = blockType == BlockType.ENCODED_DATA ?<a name="line.642"></a>
-<span class="sourceLineNo">643</span>      reader.getBlockDecodingContext() : reader.getDefaultBlockDecodingContext();<a name="line.643"></a>
-<span class="sourceLineNo">644</span><a name="line.644"></a>
-<span class="sourceLineNo">645</span>    ByteBuff dup = this.buf.duplicate();<a name="line.645"></a>
-<span class="sourceLineNo">646</span>    dup.position(this.headerSize());<a name="line.646"></a>
-<span class="sourceLineNo">647</span>    dup = dup.slice();<a name="line.647"></a>
-<span class="sourceLineNo">648</span>    ctx.prepareDecoding(unpacked.getOnDiskSizeWithoutHeader(),<a name="line.648"></a>
-<span class="sourceLineNo">649</span>      unpacked.getUncompressedSizeWithoutHeader(), unpacked.getBufferWithoutHeader(),<a name="line.649"></a>
-<span class="sourceLineNo">650</span>      dup);<a name="line.650"></a>
-<span class="sourceLineNo">651</span>    return unpacked;<a name="line.651"></a>
-<span class="sourceLineNo">652</span>  }<a name="line.652"></a>
-<span class="sourceLineNo">653</span><a name="line.653"></a>
-<span class="sourceLineNo">654</span>  /**<a name="line.654"></a>
-<span class="sourceLineNo">655</span>   * Always allocates a new buffer of the correct size. Copies header bytes<a name="line.655"></a>
-<span class="sourceLineNo">656</span>   * from the existing buffer. Does not change header fields.<a name="line.656"></a>
-<span class="sourceLineNo">657</span>   * Reserve room to keep checksum bytes too.<a name="line.657"></a>
-<span class="sourceLineNo">658</span>   */<a name="line.658"></a>
-<span class="sourceLineNo">659</span>  private void allocateBuffer() {<a name="line.659"></a>
-<span class="sourceLineNo">660</span>    int cksumBytes = totalChecksumBytes();<a name="line.660"></a>
-<span class="sourceLineNo">661</span>    int headerSize = headerSize();<a name="line.661"></a>
-<span class="sourceLineNo">662</span>    int capacityNeeded = headerSize + uncompressedSizeWithoutHeader + cksumBytes;<a name="line.662"></a>
-<span class="sourceLineNo">663</span><a name="line.663"></a>
-<span class="sourceLineNo">664</span>    // TODO we need consider allocating offheap here?<a name="line.664"></a>
-<span class="sourceLineNo">665</span>    ByteBuffer newBuf = ByteBuffer.allocate(capacityNeeded);<a name="line.665"></a>
-<span class="sourceLineNo">666</span><a name="line.666"></a>
-<span class="sourceLineNo">667</span>    // Copy header bytes into newBuf.<a name="line.667"></a>
-<span class="sourceLineNo">668</span>    // newBuf is HBB so no issue in calling array()<a name="line.668"></a>
-<span class="sourceLineNo">669</span>    buf.position(0);<a name="line.669"></a>
-<span class="sourceLineNo">670</span>    buf.get(newBuf.array(), newBuf.arrayOffset(), headerSize);<a name="line.670"></a>
-<span class="sourceLineNo">671</span><a name="line.671"></a>
-<span class="sourceLineNo">672</span>    buf = new SingleByteBuff(newBuf);<a name="line.672"></a>
-<span class="sourceLineNo">673</span>    // set limit to exclude next block's header<a name="line.673"></a>
-<span class="sourceLineNo">674</span>    buf.limit(headerSize + uncompressedSizeWithoutHeader + cksumBytes);<a name="line.674"></a>
-<span class="sourceLineNo">675</span>  }<a name="line.675"></a>
-<span class="sourceLineNo">676</span><a name="line.676"></a>
-<span class="sourceLineNo">677</span>  /**<a name="line.677"></a>
-<span class="sourceLineNo">678</span>   * Return true when this block's buffer has been unpacked, false otherwise. Note this is a<a name="line.678"></a>
-<span class="sourceLineNo">679</span>   * calculated heuristic, not tracked attribute of the block.<a name="line.679"></a>
-<span class="sourceLineNo">680</span>   */<a name="line.680"></a>
-<span class="sourceLineNo">681</span>  public boolean isUnpacked() {<a name="line.681"></a>
-<span class="sourceLineNo">682</span>    final int cksumBytes = totalChecksumBytes();<a name="line.682"></a>
-<span class="sourceLineNo">683</span>    final int headerSize = headerSize();<a name="line.683"></a>
-<span class="sourceLineNo">684</span>    final int expectedCapacity = headerSize + uncompressedSizeWithoutHeader + cksumBytes;<a name="line.684"></a>
-<span class="sourceLineNo">685</span>    final int bufCapacity = buf.capacity();<a name="line.685"></a>
-<span class="sourceLineNo">686</span>    return bufCapacity == expectedCapacity || bufCapacity == expectedCapacity + headerSize;<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>  /** An additional sanity-check in case no compression or encryption is being used. */<a name="line.689"></a>
-<span class="sourceLineNo">690</span>  @VisibleForTesting<a name="line.690"></a>
-<span class="sourceLineNo">691</span>  void sanityCheckUncompressedSize() throws IOException {<a name="line.691"></a>
-<span class="sourceLineNo">692</span>    if (onDiskSizeWithoutHeader != uncompressedSizeWithoutHeader + totalChecksumBytes()) {<a name="line.692"></a>
-<span class="sourceLineNo">693</span>      throw new IOException("Using no compression but "<a name="line.693"></a>
-<span class="sourceLineNo">694</span>          + "onDiskSizeWithoutHeader=" + onDiskSizeWithoutHeader + ", "<a name="line.694"></a>
-<span class="sourceLineNo">695</span>          + "uncompressedSizeWithoutHeader=" + uncompressedSizeWithoutHeader<a name="line.695"></a>
-<span class="sourceLineNo">696</span>          + ", numChecksumbytes=" + totalChecksumBytes());<a name="line.696"></a>
-<span class="sourceLineNo">697</span>    }<a name="line.697"></a>
-<span class="sourceLineNo">698</span>  }<a name="line.698"></a>
-<span class="sourceLineNo">699</span><a name="line.699"></a>
-<span class="sourceLineNo">700</span>  /**<a name="line.700"></a>
-<span class="sourceLineNo">701</span>   * Cannot be {@link #UNSET}. Must be a legitimate value. Used re-making the {@link BlockCacheKey} when<a name="line.701"></a>
-<span class="sourceLineNo">702</span>   * block is returned to the cache.<a name="line.702"></a>
-<span class="sourceLineNo">703</span>   * @return the offset of this block in the file it was read from<a name="line.703"></a>
-<span class="sourceLineNo">704</span>   */<a name="line.704"></a>
-<span class="sourceLineNo">705</span>  long getOffset() {<a name="line.705"></a>
-<span class="sourceLineNo">706</span>    if (offset &lt; 0) {<a name="line.706"></a>
-<span class="sourceLineNo">707</span>      throw new IllegalStateException("HFile block offset not initialized properly");<a name="line.707"></a>
-<span class="sourceLineNo">708</span>    }<a name="line.708"></a>
-<span class="sourceLineNo">709</span>    return offset;<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>   * @return a byte stream reading the data + checksum of this block<a name="line.713"></a>
-<span class="sourceLineNo">714</span>   */<a name="line.714"></a>
-<span class="sourceLineNo">715</span>  DataInputStream getByteStream() {<a name="line.715"></a>
-<span class="sourceLineNo">716</span>    ByteBuff dup = this.buf.duplicate();<a name="line.716"></a>
-<span class="sourceLineNo">717</span>    dup.position(this.headerSize());<a name="line.717"></a>
-<span class="sourceLineNo">718</span>    return new DataInputStream(new ByteBuffInputStream(dup));<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>
-<span class="sourceLineNo">721</span>  @Override<a name="line.721"></a>
-<span class="sourceLineNo">722</span>  public long heapSize() {<a name="line.722"></a>
-<span class="sourceLineNo">723</span>    long size = ClassSize.align(<a name="line.723"></a>
-<span class="sourceLineNo">724</span>        ClassSize.OBJECT +<a name="line.724"></a>
-<span class="sourceLineNo">725</span>        // Block type, multi byte buffer, MemoryType and meta references<a name="line.725"></a>
-<span class="sourceLineNo">726</span>        4 * ClassSize.REFERENCE +<a name="line.726"></a>
-<span class="sourceLineNo">727</span>        // On-disk size, uncompressed size, and next block's on-disk size<a name="line.727"></a>
-<span class="sourceLineNo">728</span>        // bytePerChecksum and onDiskDataSize<a name="line.728"></a>
-<span class="sourceLineNo">729</span>        4 * Bytes.SIZEOF_INT +<a name="line.729"></a>
-<span class="sourceLineNo">730</span>        // This and previous block offset<a name="line.730"></a>
-<span class="sourceLineNo">731</span>        2 * Bytes.SIZEOF_LONG +<a name="line.731"></a>
-<span class="sourceLineNo">732</span>        // Heap size of the meta object. meta will be always not null.<a name="line.732"></a>
-<span class="sourceLineNo">733</span>        fileContext.heapSize()<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>    if (buf != null) {<a name="line.736"></a>
-<span class="sourceLineNo">737</span>      // Deep overhead of the byte buffer. Needs to be aligned separately.<a name="line.737"></a>
-<span class="sourceLineNo">738</span>      size += ClassSize.align(buf.capacity() + MULTI_BYTE_BUFFER_HEAP_SIZE);<a name="line.738"></a>
-<span class="sourceLineNo">739</span>    }<a name="line.739"></a>
-<span class="sourceLineNo">740</span><a name="line.740"></a>
-<span class="sourceLineNo">741</span>    return ClassSize.align(size);<a name="line.741"></a>
-<span class="sourceLineNo">742</span>  }<a name="line.742"></a>
-<span class="sourceLineNo">743</span><a name="line.743"></a>
-<span class="sourceLineNo">744</span>  /**<a name="line.744"></a>
-<span class="sourceLineNo">745</span>   * Read from an input stream at least &lt;code&gt;necessaryLen&lt;/code&gt; and if possible,<a name="line.745"></a>
-<span class="sourceLineNo">746</span>   * &lt;code&gt;extraLen&lt;/code&gt; also if available. Analogous to<a name="line.746"></a>
-<span class="sourceLineNo">747</span>   * {@link IOUtils#readFully(InputStream, byte[], int, int)}, but specifies a<a name="line.747"></a>
-<span class="sourceLineNo">748</span>   * number of "extra" bytes to also optionally read.<a name="line.748"></a>
-<span class="sourceLineNo">749</span>   *<a name="line.749"></a>
-<span class="sourceLineNo">750</span>   * @param in the input stream to read from<a name="line.750"></a>
-<span class="sourceLineNo">751</span>   * @param buf the buffer to read into<a name="line.751"></a>
-<span class="sourceLineNo">752</span>   * @param bufOffset the destination offset in the buffer<a name="line.752"></a>
-<span class="sourceLineNo">753</span>   * @param necessaryLen the number of bytes that are absolutely necessary to read<a name="line.753"></a>
-<span class="sourceLineNo">754</span>   * @param extraLen the number of extra bytes that would be nice to read<a name="line.754"></a>
-<span class="sourceLineNo">755</span>   * @return true if succeeded reading the extra bytes<a name="line.755"></a>
-<span class="sourceLineNo">756</span>   * @throws IOException if failed to read the necessary bytes<a name="line.756"></a>
-<span class="sourceLineNo">757</span>   */<a name="line.757"></a>
-<span class="sourceLineNo">758</span>  static boolean readWithExtra(InputStream in, byte[] buf,<a name="line.758"></a>
-<span class="sourceLineNo">759</span>      int bufOffset, int necessaryLen, int extraLen) throws IOException {<a name="line.759"></a>
-<span class="sourceLineNo">760</span>    int bytesRemaining = necessaryLen + extraLen;<a name="line.760"></a>
-<span class="sourceLineNo">761</span>    while (bytesRemaining &gt; 0) {<a name="line.761"></a>
-<span class="sourceLineNo">762</span>      int ret = in.read(buf, bufOffset, bytesRemaining);<a name="line.762"></a>
-<span class="sourceLineNo">763</span>      if (ret == -1 &amp;&amp; bytesRemaining &lt;= extraLen) {<a name="line.763"></a>
-<span class="sourceLineNo">764</span>        // We could not read the "extra data", but that is OK.<a name="line.764"></a>
-<span class="sourceLineNo">765</span>        break;<a name="line.765"></a>
-<span class="sourceLineNo">766</span>      }<a name="line.766"></a>
-<span class="sourceLineNo">767</span>      if (ret &lt; 0) {<a name="line.767"></a>
-<span class="sourceLineNo">768</span>        throw new IOException("Premature EOF from inputStream (read "<a name="line.768"></a>
-<span class="sourceLineNo">769</span>            + "returned " + ret + ", was trying to read " + necessaryLen<a name="line.769"></a>
-<span class="sourceLineNo">770</span>            + " necessary bytes and " + extraLen + " extra bytes, "<a name="line.770"></a>
-<span class="sourceLineNo">771</span>            + "successfully read "<a name="line.771"></a>
-<span class="sourceLineNo">772</span>            + (necessaryLen + extraLen - bytesRemaining));<a name="line.772"></a>
-<span class="sourceLineNo">773</span>      }<a name="line.773"></a>
-<span class="sourceLineNo">774</span>      bufOffset += ret;<a name="line.774"></a>
-<span class="sourceLineNo">775</span>      bytesRemaining -= ret;<a name="line.775"></a>
-<span class="sourceLineNo">776</span>    }<a name="line.776"></a>
-<span class="sourceLineNo">777</span>    return bytesRemaining &lt;= 0;<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>   * Read from an input stream at least &lt;code&gt;necessaryLen&lt;/code&gt; and if possible,<a name="line.781"></a>
-<span class="sourceLineNo">782</span>   * &lt;code&gt;extraLen&lt;/code&gt; also if available. Analogous to<a name="line.782"></a>
-<span class="sourceLineNo">783</span>   * {@link IOUtils#readFully(InputStream, byte[], int, int)}, but uses<a name="line.783"></a>
-<span class="sourceLineNo">784</span>   * positional read and specifies a number of "extra" bytes that would be<a name="line.784"></a>
-<span class="sourceLineNo">785</span>   * desirable but not absolutely necessary to read.<a name="line.785"></a>
-<span class="sourceLineNo">786</span>   *<a name="line.786"></a>
-<span class="sourceLineNo">787</span>   * @param in the input stream to read from<a name="line.787"></a>
-<span class="sourceLineNo">788</span>   * @param position the position within the stream from which to start reading<a name="line.788"></a>
-<span class="sourceLineNo">789</span>   * @param buf the buffer to read into<a name="line.789"></a>
-<span class="sourceLineNo">790</span>   * @param bufOffset the destination offset in the buffer<a name="line.790"></a>
-<span class="sourceLineNo">791</span>   * @param necessaryLen the number of bytes that are absolutely necessary to<a name="line.791"></a>
-<span class="sourceLineNo">792</span>   *     read<a name="line.792"></a>
-<span class="sourceLineNo">793</span>   * @param extraLen the number of extra bytes that would be nice to read<a name="line.793"></a>
-<span class="sourceLineNo">794</span>   * @return true if and only if extraLen is &gt; 0 and reading those extra bytes<a name="line.794"></a>
-<span class="sourceLineNo">795</span>   *     was successful<a name="line.795"></a>
-<span class="sourceLineNo">796</span>   * @throws IOException if failed to read the necessary bytes<a name="line.796"></a>
-<span class="sourceLineNo">797</span>   */<a name="line.797"></a>
-<span class="sourceLineNo">798</span>  @VisibleForTesting<a name="line.798"></a>
-<span class="sourceLineNo">799</span>  static boolean positionalReadWithExtra(FSDataInputStream in,<a name="line.799"></a>
-<span class="sourceLineNo">800</span>      long position, byte[] buf, int bufOffset, int necessaryLen, int extraLen)<a name="line.800"></a>
-<span class="sourceLineNo">801</span>      throws IOException {<a name="line.801"></a>
-<span class="sourceLineNo">802</span>    int bytesRemaining = necessaryLen + extraLen;<a name="line.802"></a>
-<span class="sourceLineNo">803</span>    int bytesRead = 0;<a name="line.803"></a>
-<span class="sourceLineNo">804</span>    while (bytesRead &lt; necessaryLen) {<a name="line.804"></a>
-<span class="sourceLineNo">805</span>      int ret = in.read(position, buf, bufOffset, bytesRemaining);<a name="line.805"></a>
-<span class="sourceLineNo">806</span>      if (ret &lt; 0) {<a name="line.806"></a>
-<span class="sourceLineNo">807</span>        throw new IOException("Premature EOF from inputStream (positional read "<a name="line.807"></a>
-<span class="sourceLineNo">808</span>            + "returned " + ret + ", was trying to read " + necessaryLen<a name="line.808"></a>
-<span class="sourceLineNo">809</span>            + " necessary bytes and " + extraLen + " extra bytes, "<a name="line.809"></a>
-<span class="sourceLineNo">810</span>            + "successfully read " + bytesRead);<a name="line.810"></a>
-<span class="sourceLineNo">811</span>      }<a name="line.811"></a>
-<span class="sourceLineNo">812</span>      position += ret;<a name="line.812"></a>
-<span class="sourceLineNo">813</span>      bufOffset += ret;<a name="line.813"></a>
-<span class="sourceLineNo">814</span>      bytesRemaining -= ret;<a name="line.814"></a>
-<span class="sourceLineNo">815</span>      bytesRead += ret;<a name="line.815"></a>
-<span class="sourceLineNo">816</span>    }<a name="line.816"></a>
-<span class="sourceLineNo">817</span>    return bytesRead != necessaryLen &amp;&amp; bytesRemaining &lt;= 0;<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>   * Unified version 2 {@link HFile} block writer. The intended usage pattern<a name="line.821"></a>
-<span class="sourceLineNo">822</span>   * is as follows:<a name="line.822"></a>
-<span class="sourceLineNo">823</span>   * &lt;ol&gt;<a name="line.823"></a>
-<span class="sourceLineNo">824</span>   * &lt;li&gt;Construct an {@link HFileBlock.Writer}, providing a compression algorithm.<a name="line.824"></a>
-<span class="sourceLineNo">825</span>   * &lt;li&gt;Call {@link Writer#startWriting} and get a data stream to write to.<a name="line.825"></a>
-<span class="sourceLineNo">826</span>   * &lt;li&gt;Write your data into the stream.<a name="line.826"></a>
-<span class="sourceLineNo">827</span>   * &lt;li&gt;Call Writer#writeHeaderAndData(FSDataOutputStream) as many times as you need to.<a name="line.827"></a>
-<span class="sourceLineNo">828</span>   * store the serialized block into an external stream.<a name="line.828"></a>
-<span class="sourceLineNo">829</span>   * &lt;li&gt;Repeat to write more blocks.<a name="line.829"></a>
-<span class="sourceLineNo">830</span>   * &lt;/ol&gt;<a name="line.830"></a>
-<span class="sourceLineNo">831</span>   * &lt;p&gt;<a name="line.831"></a>
-<span class="sourceLineNo">832</span>   */<a name="line.832"></a>
-<span class="sourceLineNo">833</span>  static class Writer {<a name="line.833"></a>
-<span class="sourceLineNo">834</span>    private enum State {<a name="line.834"></a>
-<span class="sourceLineNo">835</span>      INIT,<a name="line.835"></a>
-<span class="sourceLineNo">836</span>      WRITING,<a name="line.836"></a>
-<span class="sourceLineNo">837</span>      BLOCK_READY<a name="line.837"></a>
-<span class="sourceLineNo">838</span>    }<a name="line.838"></a>
-<span class="sourceLineNo">839</span><a name="line.839"></a>
-<span class="sourceLineNo">840</span>    /** Writer state. Used to ensure the correct usage protocol. */<a name="line.840"></a>
-<span class="sourceLineNo">841</span>    private State state = State.INIT;<a name="line.841"></a>
-<span class="sourceLineNo">842</span><a name="line.842"></a>
-<span class="sourceLineNo">843</span>    /** Data block encoder used for data blocks */<a name="line.843"></a>
-<span class="sourceLineNo">844</span>    private final HFileDataBlockEncoder dataBlockEncoder;<a name="line.844"></a>
-<span class="sourceLineNo">845</span><a name="line.845"></a>
-<span class="sourceLineNo">846</span>    private HFileBlockEncodingContext dataBlockEncodingCtx;<a name="line.846"></a>
+<span class="sourceLineNo">328</span>   *<a name="line.328"></a>
+<span class="sourceLineNo">329</span>   * &lt;p&gt;TODO: The caller presumes no checksumming<a name="line.329"></a>
+<span class="sourceLineNo">330</span>   * required of this block instance since going into cache; checksum already verified on<a name="line.330"></a>
+<span class="sourceLineNo">331</span>   * underlying block data pulled in from filesystem. Is that correct? What if cache is SSD?<a name="line.331"></a>
+<span class="sourceLineNo">332</span>   *<a name="line.332"></a>
+<span class="sourceLineNo">333</span>   * @param blockType the type of this block, see {@link BlockType}<a name="line.333"></a>
+<span class="sourceLineNo">334</span>   * @param onDiskSizeWithoutHeader see {@link #onDiskSizeWithoutHeader}<a name="line.334"></a>
+<span class="sourceLineNo">335</span>   * @param uncompressedSizeWithoutHeader see {@link #uncompressedSizeWithoutHeader}<a name="line.335"></a>
+<span class="sourceLineNo">336</span>   * @param prevBlockOffset see {@link #prevBlockOffset}<a name="line.336"></a>
+<span class="sourceLineNo">337</span>   * @param b block header ({@link HConstants#HFILEBLOCK_HEADER_SIZE} bytes)<a name="line.337"></a>
+<span class="sourceLineNo">338</span>   * @param fillHeader when true, write the first 4 header fields into passed buffer.<a name="line.338"></a>
+<span class="sourceLineNo">339</span>   * @param offset the file offset the block was read from<a name="line.339"></a>
+<span class="sourceLineNo">340</span>   * @param onDiskDataSizeWithHeader see {@link #onDiskDataSizeWithHeader}<a name="line.340"></a>
+<span class="sourceLineNo">341</span>   * @param fileContext HFile meta data<a name="line.341"></a>
+<span class="sourceLineNo">342</span>   */<a name="line.342"></a>
+<span class="sourceLineNo">343</span>  @VisibleForTesting<a name="line.343"></a>
+<span class="sourceLineNo">344</span>  public HFileBlock(BlockType blockType, int onDiskSizeWithoutHeader,<a name="line.344"></a>
+<span class="sourceLineNo">345</span>      int uncompressedSizeWithoutHeader, long prevBlockOffset, ByteBuffer b, boolean fillHeader,<a name="line.345"></a>
+<span class="sourceLineNo">346</span>      long offset, final int nextBlockOnDiskSize, int onDiskDataSizeWithHeader,<a name="line.346"></a>
+<span class="sourceLineNo">347</span>      HFileContext fileContext) {<a name="line.347"></a>
+<span class="sourceLineNo">348</span>    init(blockType, onDiskSizeWithoutHeader, uncompressedSizeWithoutHeader,<a name="line.348"></a>
+<span class="sourceLineNo">349</span>        prevBlockOffset, offset, onDiskDataSizeWithHeader, nextBlockOnDiskSize, fileContext);<a name="line.349"></a>
+<span class="sourceLineNo">350</span>    this.buf = new SingleByteBuff(b);<a name="line.350"></a>
+<span class="sourceLineNo">351</span>    if (fillHeader) {<a name="line.351"></a>
+<span class="sourceLineNo">352</span>      overwriteHeader();<a name="line.352"></a>
+<span class="sourceLineNo">353</span>    }<a name="line.353"></a>
+<span class="sourceLineNo">354</span>    this.buf.rewind();<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">357</span>  /**<a name="line.357"></a>
+<span class="sourceLineNo">358</span>   * Creates a block from an existing buffer starting with a header. Rewinds<a name="line.358"></a>
+<span class="sourceLineNo">359</span>   * and takes ownership of the buffer. By definition of rewind, ignores the<a name="line.359"></a>
+<span class="sourceLineNo">360</span>   * buffer position, but if you slice the buffer beforehand, it will rewind<a name="line.360"></a>
+<span class="sourceLineNo">361</span>   * to that point.<a name="line.361"></a>
+<span class="sourceLineNo">362</span>   * @param buf Has header, content, and trailing checksums if present.<a name="line.362"></a>
+<span class="sourceLineNo">363</span>   */<a name="line.363"></a>
+<span class="sourceLineNo">364</span>  HFileBlock(ByteBuff buf, boolean usesHBaseChecksum, MemoryType memType, final long offset,<a name="line.364"></a>
+<span class="sourceLineNo">365</span>      final int nextBlockOnDiskSize, HFileContext fileContext) throws IOException {<a name="line.365"></a>
+<span class="sourceLineNo">366</span>    buf.rewind();<a name="line.366"></a>
+<span class="sourceLineNo">367</span>    final BlockType blockType = BlockType.read(buf);<a name="line.367"></a>
+<span class="sourceLineNo">368</span>    final int onDiskSizeWithoutHeader = buf.getInt(Header.ON_DISK_SIZE_WITHOUT_HEADER_INDEX);<a name="line.368"></a>
+<span class="sourceLineNo">369</span>    final int uncompressedSizeWithoutHeader =<a name="line.369"></a>
+<span class="sourceLineNo">370</span>        buf.getInt(Header.UNCOMPRESSED_SIZE_WITHOUT_HEADER_INDEX);<a name="line.370"></a>
+<span class="sourceLineNo">371</span>    final long prevBlockOffset = buf.getLong(Header.PREV_BLOCK_OFFSET_INDEX);<a name="line.371"></a>
+<span class="sourceLineNo">372</span>    // This constructor is called when we deserialize a block from cache and when we read a block in<a name="line.372"></a>
+<span class="sourceLineNo">373</span>    // from the fs. fileCache is null when deserialized from cache so need to make up one.<a name="line.373"></a>
+<span class="sourceLineNo">374</span>    HFileContextBuilder fileContextBuilder = fileContext != null?<a name="line.374"></a>
+<span class="sourceLineNo">375</span>        new HFileContextBuilder(fileContext): new HFileContextBuilder();<a name="line.375"></a>
+<span class="sourceLineNo">376</span>    fileContextBuilder.withHBaseCheckSum(usesHBaseChecksum);<a name="line.376"></a>
+<span class="sourceLineNo">377</span>    int onDiskDataSizeWithHeader;<a name="line.377"></a>
+<span class="sourceLineNo">378</span>    if (usesHBaseChecksum) {<a name="line.378"></a>
+<span class="sourceLineNo">379</span>      byte checksumType = buf.get(Header.CHECKSUM_TYPE_INDEX);<a name="line.379"></a>
+<span class="sourceLineNo">380</span>      int bytesPerChecksum = buf.getInt(Header.BYTES_PER_CHECKSUM_INDEX);<a name="line.380"></a>
+<span class="sourceLineNo">381</span>      onDiskDataSizeWithHeader = buf.getInt(Header.ON_DISK_DATA_SIZE_WITH_HEADER_INDEX);<a name="line.381"></a>
+<span class="sourceLineNo">382</span>      // Use the checksum type and bytes per checksum from header, not from filecontext.<a name="line.382"></a>
+<span class="sourceLineNo">383</span>      fileContextBuilder.withChecksumType(ChecksumType.codeToType(checksumType));<a name="line.383"></a>
+<span class="sourceLineNo">384</span>      fileContextBuilder.withBytesPerCheckSum(bytesPerChecksum);<a name="line.384"></a>
+<span class="sourceLineNo">385</span>    } else {<a name="line.385"></a>
+<span class="sourceLineNo">386</span>      fileContextBuilder.withChecksumType(ChecksumType.NULL);<a name="line.386"></a>
+<span class="sourceLineNo">387</span>      fileContextBuilder.withBytesPerCheckSum(0);<a name="line.387"></a>
+<span class="sourceLineNo">388</span>      // Need to fix onDiskDataSizeWithHeader; there are not checksums after-block-data<a name="line.388"></a>
+<span class="sourceLineNo">389</span>      onDiskDataSizeWithHeader = onDiskSizeWithoutHeader + headerSize(usesHBaseChecksum);<a name="line.389"></a>
+<span class="sourceLineNo">390</span>    }<a name="line.390"></a>
+<span class="sourceLineNo">391</span>    fileContext = fileContextBuilder.build();<a name="line.391"></a>
+<span class="sourceLineNo">392</span>    assert usesHBaseChecksum == fileContext.isUseHBaseChecksum();<a name="line.392"></a>
+<span class="sourceLineNo">393</span>    init(blockType, onDiskSizeWithoutHeader, uncompressedSizeWithoutHeader,<a name="line.393"></a>
+<span class="sourceLineNo">394</span>        prevBlockOffset, offset, onDiskDataSizeWithHeader, nextBlockOnDiskSize, fileContext);<a name="line.394"></a>
+<span class="sourceLineNo">395</span>    this.memType = memType;<a name="line.395"></a>
+<span class="sourceLineNo">396</span>    this.offset = offset;<a name="line.396"></a>
+<span class="sourceLineNo">397</span>    this.buf = buf;<a name="line.397"></a>
+<span class="sourceLineNo">398</span>    this.buf.rewind();<a name="line.398"></a>
+<span class="sourceLineNo">399</span>  }<a name="line.399"></a>
+<span class="sourceLineNo">400</span><a name="line.400"></a>
+<span class="sourceLineNo">401</span>  /**<a name="line.401"></a>
+<span class="sourceLineNo">402</span>   * Called from constructors.<a name="line.402"></a>
+<span class="sourceLineNo">403</span>   */<a name="line.403"></a>
+<span class="sourceLineNo">404</span>  private void init(BlockType blockType, int onDiskSizeWithoutHeader,<a name="line.404"></a>
+<span class="sourceLineNo">405</span>      int uncompressedSizeWithoutHeader, long prevBlockOffset,<a name="line.405"></a>
+<span class="sourceLineNo">406</span>      long offset, int onDiskDataSizeWithHeader, final int nextBlockOnDiskSize,<a name="line.406"></a>
+<span class="sourceLineNo">407</span>      HFileContext fileContext) {<a name="line.407"></a>
+<span class="sourceLineNo">408</span>    this.blockType = blockType;<a name="line.408"></a>
+<span class="sourceLineNo">409</span>    this.onDiskSizeWithoutHeader = onDiskSizeWithoutHeader;<a name="line.409"></a>
+<span class="sourceLineNo">410</span>    this.uncompressedSizeWithoutHeader = uncompressedSizeWithoutHeader;<a name="line.410"></a>
+<span class="sourceLineNo">411</span>    this.prevBlockOffset = prevBlockOffset;<a name="line.411"></a>
+<span class="sourceLineNo">412</span>    this.offset = offset;<a name="line.412"></a>
+<span class="sourceLineNo">413</span>    this.onDiskDataSizeWithHeader = onDiskDataSizeWithHeader;<a name="line.413"></a>
+<span class="sourceLineNo">414</span>    this.nextBlockOnDiskSize = nextBlockOnDiskSize;<a name="line.414"></a>
+<span class="sourceLineNo">415</span>    this.fileContext = fileContext;<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">418</span>  /**<a name="line.418"></a>
+<span class="sourceLineNo">419</span>   * Parse total on disk size including header and checksum.<a name="line.419"></a>
+<span class="sourceLineNo">420</span>   * @param headerBuf Header ByteBuffer. Presumed exact size of header.<a name="line.420"></a>
+<span class="sourceLineNo">421</span>   * @param verifyChecksum true if checksum verification is in use.<a name="line.421"></a>
+<span class="sourceLineNo">422</span>   * @return Size of the block with header included.<a name="line.422"></a>
+<span class="sourceLineNo">423</span>   */<a name="line.423"></a>
+<span class="sourceLineNo">424</span>  private static int getOnDiskSizeWithHeader(final ByteBuffer headerBuf,<a name="line.424"></a>
+<span class="sourceLineNo">425</span>      boolean verifyChecksum) {<a name="line.425"></a>
+<span class="sourceLineNo">426</span>    return headerBuf.getInt(Header.ON_DISK_SIZE_WITHOUT_HEADER_INDEX) +<a name="line.426"></a>
+<span class="sourceLineNo">427</span>      headerSize(verifyChecksum);<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>   * @return the on-disk size of the next block (including the header size and any checksums if<a name="line.431"></a>
+<span class="sourceLineNo">432</span>   * present) read by peeking into the next block's header; use as a hint when doing<a name="line.432"></a>
+<span class="sourceLineNo">433</span>   * a read of the next block when scanning or running over a file.<a name="line.433"></a>
+<span class="sourceLineNo">434</span>   */<a name="line.434"></a>
+<span class="sourceLineNo">435</span>  int getNextBlockOnDiskSize() {<a name="line.435"></a>
+<span class="sourceLineNo">436</span>    return nextBlockOnDiskSize;<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>  @Override<a name="line.439"></a>
+<span class="sourceLineNo">440</span>  public BlockType getBlockType() {<a name="line.440"></a>
+<span class="sourceLineNo">441</span>    return blockType;<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>  /** @return get data block encoding id that was used to encode this block */<a name="line.444"></a>
+<span class="sourceLineNo">445</span>  short getDataBlockEncodingId() {<a name="line.445"></a>
+<span class="sourceLineNo">446</span>    if (blockType != BlockType.ENCODED_DATA) {<a name="line.446"></a>
+<span class="sourceLineNo">447</span>      throw new IllegalArgumentException("Querying encoder ID of a block " +<a name="line.447"></a>
+<span class="sourceLineNo">448</span>          "of type other than " + BlockType.ENCODED_DATA + ": " + blockType);<a name="line.448"></a>
+<span class="sourceLineNo">449</span>    }<a name="line.449"></a>
+<span class="sourceLineNo">450</span>    return buf.getShort(headerSize());<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>   * @return the on-disk size of header + data part + checksum.<a name="line.454"></a>
+<span class="sourceLineNo">455</span>   */<a name="line.455"></a>
+<span class="sourceLineNo">456</span>  public int getOnDiskSizeWithHeader() {<a name="line.456"></a>
+<span class="sourceLineNo">457</span>    return onDiskSizeWithoutHeader + headerSize();<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>   * @return the on-disk size of the data part + checksum (header excluded).<a name="line.461"></a>
+<span class="sourceLineNo">462</span>   */<a name="line.462"></a>
+<span class="sourceLineNo">463</span>  int getOnDiskSizeWithoutHeader() {<a name="line.463"></a>
+<span class="sourceLineNo">464</span>    return onDiskSizeWithoutHeader;<a name="line.464"></a>
+<span class="sourceLineNo">465</span>  }<a name="line.465"></a>
+<span class="sourceLineNo">466</span><a name="line.466"></a>
+<span class="sourceLineNo">467</span>  /**<a name="line.467"></a>
+<span class="sourceLineNo">468</span>   * @return the uncompressed size of data part (header and checksum excluded).<a name="line.468"></a>
+<span class="sourceLineNo">469</span>   */<a name="line.469"></a>
+<span class="sourceLineNo">470</span>   int getUncompressedSizeWithoutHeader() {<a name="line.470"></a>
+<span class="sourceLineNo">471</span>    return uncompressedSizeWithoutHeader;<a name="line.471"></a>
+<span class="sourceLineNo">472</span>  }<a name="line.472"></a>
+<span class="sourceLineNo">473</span><a name="line.473"></a>
+<span class="sourceLineNo">474</span>  /**<a name="line.474"></a>
+<span class="sourceLineNo">475</span>   * @return the offset of the previous block of the same type in the file, or<a name="line.475"></a>
+<span class="sourceLineNo">476</span>   *         -1 if unknown<a name="line.476"></a>
+<span class="sourceLineNo">477</span>   */<a name="line.477"></a>
+<span class="sourceLineNo">478</span>  long getPrevBlockOffset() {<a name="line.478"></a>
+<span class="sourceLineNo">479</span>    return prevBlockOffset;<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>   * Rewinds {@code buf} and writes first 4 header fields. {@code buf} position<a name="line.483"></a>
+<span class="sourceLineNo">484</span>   * is modified as side-effect.<a name="line.484"></a>
+<span class="sourceLineNo">485</span>   */<a name="line.485"></a>
+<span class="sourceLineNo">486</span>  private void overwriteHeader() {<a name="line.486"></a>
+<span class="sourceLineNo">487</span>    buf.rewind();<a name="line.487"></a>
+<span class="sourceLineNo">488</span>    blockType.write(buf);<a name="line.488"></a>
+<span class="sourceLineNo">489</span>    buf.putInt(onDiskSizeWithoutHeader);<a name="line.489"></a>
+<span class="sourceLineNo">490</span>    buf.putInt(uncompressedSizeWithoutHeader);<a name="line.490"></a>
+<span class="sourceLineNo">491</span>    buf.putLong(prevBlockOffset);<a name="line.491"></a>
+<span class="sourceLineNo">492</span>    if (this.fileContext.isUseHBaseChecksum()) {<a name="line.492"></a>
+<span class="sourceLineNo">493</span>      buf.put(fileContext.getChecksumType().getCode());<a name="line.493"></a>
+<span class="sourceLineNo">494</span>      buf.putInt(fileContext.getBytesPerChecksum());<a name="line.494"></a>
+<span class="sourceLineNo">495</span>      buf.putInt(onDiskDataSizeWithHeader);<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><a name="line.498"></a>
+<span class="sourceLineNo">499</span>  /**<a name="line.499"></a>
+<span class="sourceLineNo">500</span>   * Returns a buffer that does not include the header or checksum.<a name="line.500"></a>
+<span class="sourceLineNo">501</span>   *<a name="line.501"></a>
+<span class="sourceLineNo">502</span>   * @return the buffer with header skipped and checksum omitted.<a name="line.502"></a>
+<span class="sourceLineNo">503</span>   */<a name="line.503"></a>
+<span class="sourceLineNo">504</span>  public ByteBuff getBufferWithoutHeader() {<a name="line.504"></a>
+<span class="sourceLineNo">505</span>    ByteBuff dup = getBufferReadOnly();<a name="line.505"></a>
+<span class="sourceLineNo">506</span>    // Now set it up so Buffer spans content only -- no header or no checksums.<a name="line.506"></a>
+<span class="sourceLineNo">507</span>    return dup.position(headerSize()).limit(buf.limit() - totalChecksumBytes()).slice();<a name="line.507"></a>
+<span class="sourceLineNo">508</span>  }<a name="line.508"></a>
+<span class="sourceLineNo">509</span><a name="line.509"></a>
+<span class="sourceLineNo">510</span>  /**<a name="line.510"></a>
+<span class="sourceLineNo">511</span>   * Returns a read-only duplicate of the buffer this block stores internally ready to be read.<a name="line.511"></a>
+<span class="sourceLineNo">512</span>   * Clients must not modify the buffer object though they may set position and limit on the<a name="line.512"></a>
+<span class="sourceLineNo">513</span>   * returned buffer since we pass back a duplicate. This method has to be public because it is used<a name="line.513"></a>
+<span class="sourceLineNo">514</span>   * in {@link CompoundBloomFilter} to avoid object creation on every Bloom<a name="line.514"></a>
+<span class="sourceLineNo">515</span>   * filter lookup, but has to be used with caution. Buffer holds header, block content,<a name="line.515"></a>
+<span class="sourceLineNo">516</span>   * and any follow-on checksums if present.<a name="line.516"></a>
+<span class="sourceLineNo">517</span>   *<a name="line.517"></a>
+<span class="sourceLineNo">518</span>   * @return the buffer of this block for read-only operations<a name="line.518"></a>
+<span class="sourceLineNo">519</span>   */<a name="line.519"></a>
+<span class="sourceLineNo">520</span>  public ByteBuff getBufferReadOnly() {<a name="line.520"></a>
+<span class="sourceLineNo">521</span>    // TODO: ByteBuf does not support asReadOnlyBuffer(). Fix.<a name="line.521"></a>
+<span class="sourceLineNo">522</span>    ByteBuff dup = this.buf.duplicate();<a name="line.522"></a>
+<span class="sourceLineNo">523</span>    assert dup.position() == 0;<a name="line.523"></a>
+<span class="sourceLineNo">524</span>    return dup;<a name="line.524"></a>
+<span class="sourceLineNo">525</span>  }<a name="line.525"></a>
+<span class="sourceLineNo">526</span><a name="line.526"></a>
+<span class="sourceLineNo">527</span>  @VisibleForTesting<a name="line.527"></a>
+<span class="sourceLineNo">528</span>  private void sanityCheckAssertion(long valueFromBuf, long valueFromField,<a name="line.528"></a>
+<span class="sourceLineNo">529</span>      String fieldName) throws IOException {<a name="line.529"></a>
+<span class="sourceLineNo">530</span>    if (valueFromBuf != valueFromField) {<a name="line.530"></a>
+<span class="sourceLineNo">531</span>      throw new AssertionError(fieldName + " in the buffer (" + valueFromBuf<a name="line.531"></a>
+<span class="sourceLineNo">532</span>          + ") is different from that in the field (" + valueFromField + ")");<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>  @VisibleForTesting<a name="line.536"></a>
+<span class="sourceLineNo">537</span>  private void sanityCheckAssertion(BlockType valueFromBuf, BlockType valueFromField)<a name="line.537"></a>
+<span class="sourceLineNo">538</span>      throws IOException {<a name="line.538"></a>
+<span class="sourceLineNo">539</span>    if (valueFromBuf != valueFromField) {<a name="line.539"></a>
+<span class="sourceLineNo">540</span>      throw new IOException("Block type stored in the buffer: " +<a name="line.540"></a>
+<span class="sourceLineNo">541</span>        valueFromBuf + ", block type field: " + valueFromField);<a name="line.541"></a>
+<span class="sourceLineNo">542</span>    }<a name="line.542"></a>
+<span class="sourceLineNo">543</span>  }<a name="line.543"></a>
+<span class="sourceLineNo">544</span><a name="line.544"></a>
+<span class="sourceLineNo">545</span>  /**<a name="line.545"></a>
+<span class="sourceLineNo">546</span>   * Checks if the block is internally consistent, i.e. the first<a name="line.546"></a>
+<span class="sourceLineNo">547</span>   * {@link HConstants#HFILEBLOCK_HEADER_SIZE} bytes of the buffer contain a<a name="line.547"></a>
+<span class="sourceLineNo">548</span>   * valid header consistent with the fields. Assumes a packed block structure.<a name="line.548"></a>
+<span class="sourceLineNo">549</span>   * This function is primary for testing and debugging, and is not<a name="line.549"></a>
+<span class="sourceLineNo">550</span>   * thread-safe, because it alters the internal buffer pointer.<a name="line.550"></a>
+<span class="sourceLineNo">551</span>   * Used by tests only.<a name="line.551"></a>
+<span class="sourceLineNo">552</span>   */<a name="line.552"></a>
+<span class="sourceLineNo">553</span>  @VisibleForTesting<a name="line.553"></a>
+<span class="sourceLineNo">554</span>  void sanityCheck() throws IOException {<a name="line.554"></a>
+<span class="sourceLineNo">555</span>    // Duplicate so no side-effects<a name="line.555"></a>
+<span class="sourceLineNo">556</span>    ByteBuff dup = this.buf.duplicate().rewind();<a name="line.556"></a>
+<span class="sourceLineNo">557</span>    sanityCheckAssertion(BlockType.read(dup), blockType);<a name="line.557"></a>
+<span class="sourceLineNo">558</span><a name="line.558"></a>
+<span class="sourceLineNo">559</span>    sanityCheckAssertion(dup.getInt(), onDiskSizeWithoutHeader, "onDiskSizeWithoutHeader");<a name="line.559"></a>
+<span class="sourceLineNo">560</span><a name="line.560"></a>
+<span class="sourceLineNo">561</span>    sanityCheckAssertion(dup.getInt(), uncompressedSizeWithoutHeader,<a name="line.561"></a>
+<span class="sourceLineNo">562</span>        "uncompressedSizeWithoutHeader");<a name="line.562"></a>
+<span class="sourceLineNo">563</span><a name="line.563"></a>
+<span class="sourceLineNo">564</span>    sanityCheckAssertion(dup.getLong(), prevBlockOffset, "prevBlockOffset");<a name="line.564"></a>
+<span class="sourceLineNo">565</span>    if (this.fileContext.isUseHBaseChecksum()) {<a name="line.565"></a>
+<span class="sourceLineNo">566</span>      sanityCheckAssertion(dup.get(), this.fileContext.getChecksumType().getCode(), "checksumType");<a name="line.566"></a>
+<span class="sourceLineNo">567</span>      sanityCheckAssertion(dup.getInt(), this.fileContext.getBytesPerChecksum(),<a name="line.567"></a>
+<span class="sourceLineNo">568</span>          "bytesPerChecksum");<a name="line.568"></a>
+<span class="sourceLineNo">569</span>      sanityCheckAssertion(dup.getInt(), onDiskDataSizeWithHeader, "onDiskDataSizeWithHeader");<a name="line.569"></a>
+<span class="sourceLineNo">570</span>    }<a name="line.570"></a>
+<span class="sourceLineNo">571</span><a name="line.571"></a>
+<span class="sourceLineNo">572</span>    int cksumBytes = totalChecksumBytes();<a name="line.572"></a>
+<span class="sourceLineNo">573</span>    int expectedBufLimit = onDiskDataSizeWithHeader + cksumBytes;<a name="line.573"></a>
+<span class="sourceLineNo">574</span>    if (dup.limit() != expectedBufLimit) {<a name="line.574"></a>
+<span class="sourceLineNo">575</span>      throw new AssertionError("Expected limit " + expectedBufLimit + ", got " + dup.limit());<a name="line.575"></a>
+<span class="sourceLineNo">576</span>    }<a name="line.576"></a>
+<span class="sourceLineNo">577</span><a name="line.577"></a>
+<span class="sourceLineNo">578</span>    // We might optionally allocate HFILEBLOCK_HEADER_SIZE more bytes to read the next<a name="line.578"></a>
+<span class="sourceLineNo">579</span>    // block's header, so there are two sensible values for buffer capacity.<a name="line.579"></a>
+<span class="sourceLineNo">580</span>    int hdrSize = headerSize();<a name="line.580"></a>
+<span class="sourceLineNo">581</span>    if (dup.capacity() != expectedBufLimit &amp;&amp; dup.capacity() != expectedBufLimit + hdrSize) {<a name="line.581"></a>
+<span class="sourceLineNo">582</span>      throw new AssertionError("Invalid buffer capacity: " + dup.capacity() +<a name="line.582"></a>
+<span class="sourceLineNo">583</span>          ", expected " + expectedBufLimit + " or " + (expectedBufLimit + hdrSize));<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>  @Override<a name="line.587"></a>
+<span class="sourceLineNo">588</span>  public String toString() {<a name="line.588"></a>
+<span class="sourceLineNo">589</span>    StringBuilder sb = new StringBuilder()<a name="line.589"></a>
+<span class="sourceLineNo">590</span>      .append("[")<a name="line.590"></a>
+<span class="sourceLineNo">591</span>      .append("blockType=").append(blockType)<a name="line.591"></a>
+<span class="sourceLineNo">592</span>      .append(", fileOffset=").append(offset)<a name="line.592"></a>
+<span class="sourceLineNo">593</span>      .append(", headerSize=").append(headerSize())<a name="line.593"></a>
+<span class="sourceLineNo">594</span>      .append(", onDiskSizeWithoutHeader=").append(onDiskSizeWithoutHeader)<a name="line.594"></a>
+<span class="sourceLineNo">595</span>      .append(", uncompressedSizeWithoutHeader=").append(uncompressedSizeWithoutHeader)<a name="line.595"></a>
+<span class="sourceLineNo">596</span>      .append(", prevBlockOffset=").append(prevBlockOffset)<a name="line.596"></a>
+<span class="sourceLineNo">597</span>      .append(", isUseHBaseChecksum=").append(fileContext.isUseHBaseChecksum());<a name="line.597"></a>
+<span class="sourceLineNo">598</span>    if (fileContext.isUseHBaseChecksum()) {<a name="line.598"></a>
+<span class="sourceLineNo">599</span>      sb.append(", checksumType=").append(ChecksumType.codeToType(this.buf.get(24)))<a name="line.599"></a>
+<span class="sourceLineNo">600</span>        .append(", bytesPerChecksum=").append(this.buf.getInt(24 + 1))<a name="line.600"></a>
+<span class="sourceLineNo">601</span>        .append(", onDiskDataSizeWithHeader=").append(onDiskDataSizeWithHeader);<a name="line.601"></a>
+<span class="sourceLineNo">602</span>    } else {<a name="line.602"></a>
+<span class="sourceLineNo">603</span>      sb.append(", onDiskDataSizeWithHeader=").append(onDiskDataSizeWithHeader)<a name="line.603"></a>
+<span class="sourceLineNo">604</span>        .append("(").append(onDiskSizeWithoutHeader)<a name="line.604"></a>
+<span class="sourceLineNo">605</span>        .append("+").append(HConstants.HFILEBLOCK_HEADER_SIZE_NO_CHECKSUM).append(")");<a name="line.605"></a>
+<span class="sourceLineNo">606</span>    }<a name="line.606"></a>
+<span class="sourceLineNo">607</span>    String dataBegin = null;<a name="line.607"></a>
+<span class="sourceLineNo">608</span>    if (buf.hasArray()) {<a name="line.608"></a>
+<span class="sourceLineNo">609</span>      dataBegin = Bytes.toStringBinary(buf.array(), buf.arrayOffset() + headerSize(),<a name="line.609"></a>
+<span class="sourceLineNo">610</span>          Math.min(32, buf.limit() - buf.arrayOffset() - headerSize()));<a name="line.610"></a>
+<span class="sourceLineNo">611</span>    } else {<a name="line.611"></a>
+<span class="sourceLineNo">612</span>      ByteBuff bufWithoutHeader = getBufferWithoutHeader();<a name="line.612"></a>
+<span class="sourceLineNo">613</span>      byte[] dataBeginBytes = new byte[Math.min(32,<a name="line.613"></a>
+<span class="sourceLineNo">614</span>          bufWithoutHeader.limit() - bufWithoutHeader.position())];<a name="line.614"></a>
+<span class="sourceLineNo">615</span>      bufWithoutHeader.get(dataBeginBytes);<a name="line.615"></a>
+<span class="sourceLineNo">616</span>      dataBegin = Bytes.toStringBinary(dataBeginBytes);<a name="line.616"></a>
+<span class="sourceLineNo">617</span>    }<a name="line.617"></a>
+<span class="sourceLineNo">618</span>    sb.append(", getOnDiskSizeWithHeader=").append(getOnDiskSizeWithHeader())<a name="line.618"></a>
+<span class="sourceLineNo">619</span>      .append(", totalChecksumBytes=").append(totalChecksumBytes())<a name="line.619"></a>
+<span class="sourceLineNo">620</span>      .append(", isUnpacked=").append(isUnpacked())<a name="line.620"></a>
+<span class="sourceLineNo">621</span>      .append(", buf=[").append(buf).append("]")<a name="line.621"></a>
+<span class="sourceLineNo">622</span>      .append(", dataBeginsWith=").append(dataBegin)<a name="line.622"></a>
+<span class="sourceLineNo">623</span>      .append(", fileContext=").append(fileContext)<a name="line.623"></a>
+<span class="sourceLineNo">624</span>      .append(", nextBlockOnDiskSize=").append(nextBlockOnDiskSize)<a name="line.624"></a>
+<span class="sourceLineNo">625</span>      .append("]");<a name="line.625"></a>
+<span class="sourceLineNo">626</span>    return sb.toString();<a name="line.626"></a>
+<span class="sourceLineNo">627</span>  }<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>   * Retrieves the decompressed/decrypted view of this block. An encoded block remains in its<a name="line.630"></a>
+<span class="sourceLineNo">631</span>   * encoded structure. Internal structures are shared between instances where applicable.<a name="line.631"></a>
+<span class="sourceLineNo">632</span>   */<a name="line.632"></a>
+<span class="sourceLineNo">633</span>  HFileBlock unpack(HFileContext fileContext, FSReader reader) throws IOException {<a name="line.633"></a>
+<span class="sourceLineNo">634</span>    if (!fileContext.isCompressedOrEncrypted()) {<a name="line.634"></a>
+<span class="sourceLineNo">635</span>      // TODO: cannot use our own fileContext here because HFileBlock(ByteBuffer, boolean),<a name="line.635"></a>
+<span class="sourceLineNo">636</span>      // which is used for block serialization to L2 cache, does not preserve encoding and<a name="line.636"></a>
+<span class="sourceLineNo">637</span>      // encryption details.<a name="line.637"></a>
+<span class="sourceLineNo">638</span>      return this;<a name="line.638"></a>
+<span class="sourceLineNo">639</span>    }<a name="line.639"></a>
+<span class="sourceLineNo">640</span><a name="line.640"></a>
+<span class="sourceLineNo">641</span>    HFileBlock unpacked = new HFileBlock(this);<a name="line.641"></a>
+<span class="sourceLineNo">642</span>    unpacked.allocateBuffer(); // allocates space for the decompressed block<a name="line.642"></a>
+<span class="sourceLineNo">643</span><a name="line.643"></a>
+<span class="sourceLineNo">644</span>    HFileBlockDecodingContext ctx = blockType == BlockType.ENCODED_DATA ?<a name="line.644"></a>
+<span class="sourceLineNo">645</span>      reader.getBlockDecodingContext() : reader.getDefaultBlockDecodingContext();<a name="line.645"></a>
+<span class="sourceLineNo">646</span><a name="line.646"></a>
+<span class="sourceLineNo">647</span>    ByteBuff dup = this.buf.duplicate();<a name="line.647"></a>
+<span class="sourceLineNo">648</span>    dup.position(this.headerSize());<a name="line.648"></a>
+<span class="sourceLineNo">649</span>    dup = dup.slice();<a name="line.649"></a>
+<span class="sourceLineNo">650</span> 

<TRUNCATED>

[08/50] hbase-site git commit: Published site at 26babcf013de696b899d76a3c39434b794440d8d.

Posted by gi...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html b/testdevapidocs/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html
index 224dcde..2217fe3 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html
@@ -18,7 +18,7 @@
     catch(err) {
     }
 //-->
-var methods = {"i0":9,"i1":9,"i2":10};
+var methods = {"i0":9,"i1":9,"i2":10,"i3":10,"i4":10,"i5":10,"i6":10,"i7":10};
 var tabs = {65535:["t0","All Methods"],1:["t1","Static Methods"],2:["t2","Instance Methods"],8:["t4","Concrete Methods"]};
 var altColor = "altColor";
 var rowColor = "rowColor";
@@ -50,7 +50,7 @@ var activeTableTab = "activeTableTab";
 <div class="subNav">
 <ul class="navList">
 <li><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestStripeStoreFileManager.html" title="class in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">Prev&nbsp;Class</span></a></li>
-<li><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSyncTimeRangeTracker.html" title="class in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">Next&nbsp;Class</span></a></li>
+<li><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextColFilter.html" title="class in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">Next&nbsp;Class</span></a></li>
 </ul>
 <ul class="navList">
 <li><a href="../../../../../index.html?org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html" target="_top">Frames</a></li>
@@ -74,7 +74,7 @@ var activeTableTab = "activeTableTab";
 <div>
 <ul class="subNavList">
 <li>Summary:&nbsp;</li>
-<li>Nested&nbsp;|&nbsp;</li>
+<li><a href="#nested.class.summary">Nested</a>&nbsp;|&nbsp;</li>
 <li><a href="#field.summary">Field</a>&nbsp;|&nbsp;</li>
 <li><a href="#constructor.summary">Constr</a>&nbsp;|&nbsp;</li>
 <li><a href="#method.summary">Method</a></li>
@@ -109,7 +109,7 @@ var activeTableTab = "activeTableTab";
 <li class="blockList">
 <hr>
 <br>
-<pre>public class <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html#line.48">TestSwitchToStreamRead</a>
+<pre>public class <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html#line.52">TestSwitchToStreamRead</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>
 </li>
 </ul>
@@ -117,6 +117,37 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <div class="summary">
 <ul class="blockList">
 <li class="blockList">
+<!-- ======== NESTED CLASS SUMMARY ======== -->
+<ul class="blockList">
+<li class="blockList"><a name="nested.class.summary">
+<!--   -->
+</a>
+<h3>Nested Class Summary</h3>
+<table class="memberSummary" border="0" cellpadding="3" cellspacing="0" summary="Nested Class Summary table, listing nested classes, and an explanation">
+<caption><span>Nested Classes</span><span class="tabEnd">&nbsp;</span></caption>
+<tr>
+<th class="colFirst" scope="col">Modifier and Type</th>
+<th class="colLast" scope="col">Class and Description</th>
+</tr>
+<tr class="altColor">
+<td class="colFirst"><code>static class&nbsp;</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextColFilter.html" title="class in org.apache.hadoop.hbase.regionserver">TestSwitchToStreamRead.MatchLastRowCellNextColFilter</a></span></code>&nbsp;</td>
+</tr>
+<tr class="rowColor">
+<td class="colFirst"><code>static class&nbsp;</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextRowFilter.html" title="class in org.apache.hadoop.hbase.regionserver">TestSwitchToStreamRead.MatchLastRowCellNextRowFilter</a></span></code>&nbsp;</td>
+</tr>
+<tr class="altColor">
+<td class="colFirst"><code>static class&nbsp;</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html" title="class in org.apache.hadoop.hbase.regionserver">TestSwitchToStreamRead.MatchLastRowFilterRowFilter</a></span></code>&nbsp;</td>
+</tr>
+<tr class="rowColor">
+<td class="colFirst"><code>static class&nbsp;</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowKeyFilter.html" title="class in org.apache.hadoop.hbase.regionserver">TestSwitchToStreamRead.MatchLastRowKeyFilter</a></span></code>&nbsp;</td>
+</tr>
+</table>
+</li>
+</ul>
 <!-- =========== FIELD SUMMARY =========== -->
 <ul class="blockList">
 <li class="blockList"><a name="field.summary">
@@ -201,6 +232,26 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <td class="colFirst"><code>void</code></td>
 <td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html#test--">test</a></span>()</code>&nbsp;</td>
 </tr>
+<tr id="i3" class="rowColor">
+<td class="colFirst"><code>private void</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html#testFilter-org.apache.hadoop.hbase.filter.Filter-">testFilter</a></span>(org.apache.hadoop.hbase.filter.Filter&nbsp;filter)</code>&nbsp;</td>
+</tr>
+<tr id="i4" class="altColor">
+<td class="colFirst"><code>void</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html#testFilterCellNextCol--">testFilterCellNextCol</a></span>()</code>&nbsp;</td>
+</tr>
+<tr id="i5" class="rowColor">
+<td class="colFirst"><code>void</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html#testFilterCellNextRow--">testFilterCellNextRow</a></span>()</code>&nbsp;</td>
+</tr>
+<tr id="i6" class="altColor">
+<td class="colFirst"><code>void</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html#testFilterRow--">testFilterRow</a></span>()</code>&nbsp;</td>
+</tr>
+<tr id="i7" class="rowColor">
+<td class="colFirst"><code>void</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html#testFilterRowKey--">testFilterRowKey</a></span>()</code>&nbsp;</td>
+</tr>
 </table>
 <ul class="blockList">
 <li class="blockList"><a name="methods.inherited.from.class.java.lang.Object">
@@ -229,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>CLASS_RULE</h4>
-<pre>public static final&nbsp;<a href="../../../../../org/apache/hadoop/hbase/HBaseClassTestRule.html" title="class in org.apache.hadoop.hbase">HBaseClassTestRule</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html#line.51">CLASS_RULE</a></pre>
+<pre>public static final&nbsp;<a href="../../../../../org/apache/hadoop/hbase/HBaseClassTestRule.html" title="class in org.apache.hadoop.hbase">HBaseClassTestRule</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html#line.55">CLASS_RULE</a></pre>
 </li>
 </ul>
 <a name="UTIL">
@@ -238,7 +289,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>UTIL</h4>
-<pre>private static final&nbsp;<a href="../../../../../org/apache/hadoop/hbase/HBaseTestingUtility.html" title="class in org.apache.hadoop.hbase">HBaseTestingUtility</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html#line.54">UTIL</a></pre>
+<pre>private static final&nbsp;<a href="../../../../../org/apache/hadoop/hbase/HBaseTestingUtility.html" title="class in org.apache.hadoop.hbase">HBaseTestingUtility</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html#line.58">UTIL</a></pre>
 </li>
 </ul>
 <a name="TABLE_NAME">
@@ -247,7 +298,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>TABLE_NAME</h4>
-<pre>private static&nbsp;org.apache.hadoop.hbase.TableName <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html#line.56">TABLE_NAME</a></pre>
+<pre>private static&nbsp;org.apache.hadoop.hbase.TableName <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html#line.60">TABLE_NAME</a></pre>
 </li>
 </ul>
 <a name="FAMILY">
@@ -256,7 +307,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>FAMILY</h4>
-<pre>private static&nbsp;byte[] <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html#line.58">FAMILY</a></pre>
+<pre>private static&nbsp;byte[] <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html#line.62">FAMILY</a></pre>
 </li>
 </ul>
 <a name="QUAL">
@@ -265,7 +316,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>QUAL</h4>
-<pre>private static&nbsp;byte[] <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html#line.60">QUAL</a></pre>
+<pre>private static&nbsp;byte[] <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html#line.64">QUAL</a></pre>
 </li>
 </ul>
 <a name="VALUE_PREFIX">
@@ -274,7 +325,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>VALUE_PREFIX</h4>
-<pre>private static&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html#line.62">VALUE_PREFIX</a></pre>
+<pre>private static&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html#line.66">VALUE_PREFIX</a></pre>
 </li>
 </ul>
 <a name="REGION">
@@ -283,7 +334,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>REGION</h4>
-<pre>private static&nbsp;org.apache.hadoop.hbase.regionserver.HRegion <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html#line.64">REGION</a></pre>
+<pre>private static&nbsp;org.apache.hadoop.hbase.regionserver.HRegion <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html#line.68">REGION</a></pre>
 </li>
 </ul>
 </li>
@@ -300,7 +351,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>TestSwitchToStreamRead</h4>
-<pre>public&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html#line.48">TestSwitchToStreamRead</a>()</pre>
+<pre>public&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html#line.52">TestSwitchToStreamRead</a>()</pre>
 </li>
 </ul>
 </li>
@@ -317,7 +368,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>setUp</h4>
-<pre>public static&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html#line.67">setUp</a>()
+<pre>public static&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html#line.71">setUp</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>
@@ -331,7 +382,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>tearDown</h4>
-<pre>public static&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html#line.92">tearDown</a>()
+<pre>public static&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html#line.96">tearDown</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>
@@ -342,10 +393,10 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <a name="test--">
 <!--   -->
 </a>
-<ul class="blockListLast">
+<ul class="blockList">
 <li class="blockList">
 <h4>test</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html#line.98">test</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html#line.102">test</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>
@@ -353,6 +404,76 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 </dl>
 </li>
 </ul>
+<a name="testFilter-org.apache.hadoop.hbase.filter.Filter-">
+<!--   -->
+</a>
+<ul class="blockList">
+<li class="blockList">
+<h4>testFilter</h4>
+<pre>private&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html#line.150">testFilter</a>(org.apache.hadoop.hbase.filter.Filter&nbsp;filter)
+                 throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
+<dl>
+<dt><span class="throwsLabel">Throws:</span></dt>
+<dd><code><a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></code></dd>
+</dl>
+</li>
+</ul>
+<a name="testFilterRowKey--">
+<!--   -->
+</a>
+<ul class="blockList">
+<li class="blockList">
+<h4>testFilterRowKey</h4>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html#line.194">testFilterRowKey</a>()
+                      throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
+<dl>
+<dt><span class="throwsLabel">Throws:</span></dt>
+<dd><code><a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></code></dd>
+</dl>
+</li>
+</ul>
+<a name="testFilterCellNextCol--">
+<!--   -->
+</a>
+<ul class="blockList">
+<li class="blockList">
+<h4>testFilterCellNextCol</h4>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html#line.211">testFilterCellNextCol</a>()
+                           throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
+<dl>
+<dt><span class="throwsLabel">Throws:</span></dt>
+<dd><code><a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></code></dd>
+</dl>
+</li>
+</ul>
+<a name="testFilterCellNextRow--">
+<!--   -->
+</a>
+<ul class="blockList">
+<li class="blockList">
+<h4>testFilterCellNextRow</h4>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html#line.228">testFilterCellNextRow</a>()
+                           throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
+<dl>
+<dt><span class="throwsLabel">Throws:</span></dt>
+<dd><code><a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></code></dd>
+</dl>
+</li>
+</ul>
+<a name="testFilterRow--">
+<!--   -->
+</a>
+<ul class="blockListLast">
+<li class="blockList">
+<h4>testFilterRow</h4>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html#line.259">testFilterRow</a>()
+                   throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
+<dl>
+<dt><span class="throwsLabel">Throws:</span></dt>
+<dd><code><a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></code></dd>
+</dl>
+</li>
+</ul>
 </li>
 </ul>
 </li>
@@ -382,7 +503,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <div class="subNav">
 <ul class="navList">
 <li><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestStripeStoreFileManager.html" title="class in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">Prev&nbsp;Class</span></a></li>
-<li><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSyncTimeRangeTracker.html" title="class in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">Next&nbsp;Class</span></a></li>
+<li><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextColFilter.html" title="class in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">Next&nbsp;Class</span></a></li>
 </ul>
 <ul class="navList">
 <li><a href="../../../../../index.html?org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html" target="_top">Frames</a></li>
@@ -406,7 +527,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <div>
 <ul class="subNavList">
 <li>Summary:&nbsp;</li>
-<li>Nested&nbsp;|&nbsp;</li>
+<li><a href="#nested.class.summary">Nested</a>&nbsp;|&nbsp;</li>
 <li><a href="#field.summary">Field</a>&nbsp;|&nbsp;</li>
 <li><a href="#constructor.summary">Constr</a>&nbsp;|&nbsp;</li>
 <li><a href="#method.summary">Method</a></li>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/org/apache/hadoop/hbase/regionserver/TestSyncTimeRangeTracker.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/org/apache/hadoop/hbase/regionserver/TestSyncTimeRangeTracker.html b/testdevapidocs/org/apache/hadoop/hbase/regionserver/TestSyncTimeRangeTracker.html
index cf5d8db..837062f 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/regionserver/TestSyncTimeRangeTracker.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/regionserver/TestSyncTimeRangeTracker.html
@@ -49,7 +49,7 @@ var activeTableTab = "activeTableTab";
 </div>
 <div class="subNav">
 <ul class="navList">
-<li><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html" title="class in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">Prev&nbsp;Class</span></a></li>
+<li><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowKeyFilter.html" title="class in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">Prev&nbsp;Class</span></a></li>
 <li><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSyncTimeRangeTracker.RandomTestData.html" title="class in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">Next&nbsp;Class</span></a></li>
 </ul>
 <ul class="navList">
@@ -397,7 +397,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSimpleT
 </div>
 <div class="subNav">
 <ul class="navList">
-<li><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html" title="class in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">Prev&nbsp;Class</span></a></li>
+<li><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowKeyFilter.html" title="class in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">Prev&nbsp;Class</span></a></li>
 <li><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSyncTimeRangeTracker.RandomTestData.html" title="class in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">Next&nbsp;Class</span></a></li>
 </ul>
 <ul class="navList">

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/org/apache/hadoop/hbase/regionserver/class-use/TestSwitchToStreamRead.MatchLastRowCellNextColFilter.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/org/apache/hadoop/hbase/regionserver/class-use/TestSwitchToStreamRead.MatchLastRowCellNextColFilter.html b/testdevapidocs/org/apache/hadoop/hbase/regionserver/class-use/TestSwitchToStreamRead.MatchLastRowCellNextColFilter.html
new file mode 100644
index 0000000..c07d2cc
--- /dev/null
+++ b/testdevapidocs/org/apache/hadoop/hbase/regionserver/class-use/TestSwitchToStreamRead.MatchLastRowCellNextColFilter.html
@@ -0,0 +1,125 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!-- NewPage -->
+<html lang="en">
+<head>
+<!-- Generated by javadoc -->
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Uses of Class org.apache.hadoop.hbase.regionserver.TestSwitchToStreamRead.MatchLastRowCellNextColFilter (Apache HBase 3.0.0-SNAPSHOT Test API)</title>
+<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
+<script type="text/javascript" src="../../../../../../script.js"></script>
+</head>
+<body>
+<script type="text/javascript"><!--
+    try {
+        if (location.href.indexOf('is-external=true') == -1) {
+            parent.document.title="Uses of Class org.apache.hadoop.hbase.regionserver.TestSwitchToStreamRead.MatchLastRowCellNextColFilter (Apache HBase 3.0.0-SNAPSHOT Test API)";
+        }
+    }
+    catch(err) {
+    }
+//-->
+</script>
+<noscript>
+<div>JavaScript is disabled on your browser.</div>
+</noscript>
+<!-- ========= START OF TOP NAVBAR ======= -->
+<div class="topNav"><a name="navbar.top">
+<!--   -->
+</a>
+<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
+<a name="navbar.top.firstrow">
+<!--   -->
+</a>
+<ul class="navList" title="Navigation">
+<li><a href="../../../../../../overview-summary.html">Overview</a></li>
+<li><a href="../package-summary.html">Package</a></li>
+<li><a href="../../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextColFilter.html" title="class in org.apache.hadoop.hbase.regionserver">Class</a></li>
+<li class="navBarCell1Rev">Use</li>
+<li><a href="../../../../../../overview-tree.html">Tree</a></li>
+<li><a href="../../../../../../deprecated-list.html">Deprecated</a></li>
+<li><a href="../../../../../../index-all.html">Index</a></li>
+<li><a href="../../../../../../help-doc.html">Help</a></li>
+</ul>
+</div>
+<div class="subNav">
+<ul class="navList">
+<li>Prev</li>
+<li>Next</li>
+</ul>
+<ul class="navList">
+<li><a href="../../../../../../index.html?org/apache/hadoop/hbase/regionserver/class-use/TestSwitchToStreamRead.MatchLastRowCellNextColFilter.html" target="_top">Frames</a></li>
+<li><a href="TestSwitchToStreamRead.MatchLastRowCellNextColFilter.html" target="_top">No&nbsp;Frames</a></li>
+</ul>
+<ul class="navList" id="allclasses_navbar_top">
+<li><a href="../../../../../../allclasses-noframe.html">All&nbsp;Classes</a></li>
+</ul>
+<div>
+<script type="text/javascript"><!--
+  allClassesLink = document.getElementById("allclasses_navbar_top");
+  if(window==top) {
+    allClassesLink.style.display = "block";
+  }
+  else {
+    allClassesLink.style.display = "none";
+  }
+  //-->
+</script>
+</div>
+<a name="skip.navbar.top">
+<!--   -->
+</a></div>
+<!-- ========= END OF TOP NAVBAR ========= -->
+<div class="header">
+<h2 title="Uses of Class org.apache.hadoop.hbase.regionserver.TestSwitchToStreamRead.MatchLastRowCellNextColFilter" class="title">Uses of Class<br>org.apache.hadoop.hbase.regionserver.TestSwitchToStreamRead.MatchLastRowCellNextColFilter</h2>
+</div>
+<div class="classUseContainer">No usage of org.apache.hadoop.hbase.regionserver.TestSwitchToStreamRead.MatchLastRowCellNextColFilter</div>
+<!-- ======= START OF BOTTOM NAVBAR ====== -->
+<div class="bottomNav"><a name="navbar.bottom">
+<!--   -->
+</a>
+<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
+<a name="navbar.bottom.firstrow">
+<!--   -->
+</a>
+<ul class="navList" title="Navigation">
+<li><a href="../../../../../../overview-summary.html">Overview</a></li>
+<li><a href="../package-summary.html">Package</a></li>
+<li><a href="../../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextColFilter.html" title="class in org.apache.hadoop.hbase.regionserver">Class</a></li>
+<li class="navBarCell1Rev">Use</li>
+<li><a href="../../../../../../overview-tree.html">Tree</a></li>
+<li><a href="../../../../../../deprecated-list.html">Deprecated</a></li>
+<li><a href="../../../../../../index-all.html">Index</a></li>
+<li><a href="../../../../../../help-doc.html">Help</a></li>
+</ul>
+</div>
+<div class="subNav">
+<ul class="navList">
+<li>Prev</li>
+<li>Next</li>
+</ul>
+<ul class="navList">
+<li><a href="../../../../../../index.html?org/apache/hadoop/hbase/regionserver/class-use/TestSwitchToStreamRead.MatchLastRowCellNextColFilter.html" target="_top">Frames</a></li>
+<li><a href="TestSwitchToStreamRead.MatchLastRowCellNextColFilter.html" target="_top">No&nbsp;Frames</a></li>
+</ul>
+<ul class="navList" id="allclasses_navbar_bottom">
+<li><a href="../../../../../../allclasses-noframe.html">All&nbsp;Classes</a></li>
+</ul>
+<div>
+<script type="text/javascript"><!--
+  allClassesLink = document.getElementById("allclasses_navbar_bottom");
+  if(window==top) {
+    allClassesLink.style.display = "block";
+  }
+  else {
+    allClassesLink.style.display = "none";
+  }
+  //-->
+</script>
+</div>
+<a name="skip.navbar.bottom">
+<!--   -->
+</a></div>
+<!-- ======== END OF BOTTOM NAVBAR ======= -->
+<p class="legalCopy"><small>Copyright &#169; 2007&#x2013;2018 <a href="https://www.apache.org/">The Apache Software Foundation</a>. All rights reserved.</small></p>
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/org/apache/hadoop/hbase/regionserver/class-use/TestSwitchToStreamRead.MatchLastRowCellNextRowFilter.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/org/apache/hadoop/hbase/regionserver/class-use/TestSwitchToStreamRead.MatchLastRowCellNextRowFilter.html b/testdevapidocs/org/apache/hadoop/hbase/regionserver/class-use/TestSwitchToStreamRead.MatchLastRowCellNextRowFilter.html
new file mode 100644
index 0000000..bf3b921
--- /dev/null
+++ b/testdevapidocs/org/apache/hadoop/hbase/regionserver/class-use/TestSwitchToStreamRead.MatchLastRowCellNextRowFilter.html
@@ -0,0 +1,125 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!-- NewPage -->
+<html lang="en">
+<head>
+<!-- Generated by javadoc -->
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Uses of Class org.apache.hadoop.hbase.regionserver.TestSwitchToStreamRead.MatchLastRowCellNextRowFilter (Apache HBase 3.0.0-SNAPSHOT Test API)</title>
+<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
+<script type="text/javascript" src="../../../../../../script.js"></script>
+</head>
+<body>
+<script type="text/javascript"><!--
+    try {
+        if (location.href.indexOf('is-external=true') == -1) {
+            parent.document.title="Uses of Class org.apache.hadoop.hbase.regionserver.TestSwitchToStreamRead.MatchLastRowCellNextRowFilter (Apache HBase 3.0.0-SNAPSHOT Test API)";
+        }
+    }
+    catch(err) {
+    }
+//-->
+</script>
+<noscript>
+<div>JavaScript is disabled on your browser.</div>
+</noscript>
+<!-- ========= START OF TOP NAVBAR ======= -->
+<div class="topNav"><a name="navbar.top">
+<!--   -->
+</a>
+<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
+<a name="navbar.top.firstrow">
+<!--   -->
+</a>
+<ul class="navList" title="Navigation">
+<li><a href="../../../../../../overview-summary.html">Overview</a></li>
+<li><a href="../package-summary.html">Package</a></li>
+<li><a href="../../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextRowFilter.html" title="class in org.apache.hadoop.hbase.regionserver">Class</a></li>
+<li class="navBarCell1Rev">Use</li>
+<li><a href="../../../../../../overview-tree.html">Tree</a></li>
+<li><a href="../../../../../../deprecated-list.html">Deprecated</a></li>
+<li><a href="../../../../../../index-all.html">Index</a></li>
+<li><a href="../../../../../../help-doc.html">Help</a></li>
+</ul>
+</div>
+<div class="subNav">
+<ul class="navList">
+<li>Prev</li>
+<li>Next</li>
+</ul>
+<ul class="navList">
+<li><a href="../../../../../../index.html?org/apache/hadoop/hbase/regionserver/class-use/TestSwitchToStreamRead.MatchLastRowCellNextRowFilter.html" target="_top">Frames</a></li>
+<li><a href="TestSwitchToStreamRead.MatchLastRowCellNextRowFilter.html" target="_top">No&nbsp;Frames</a></li>
+</ul>
+<ul class="navList" id="allclasses_navbar_top">
+<li><a href="../../../../../../allclasses-noframe.html">All&nbsp;Classes</a></li>
+</ul>
+<div>
+<script type="text/javascript"><!--
+  allClassesLink = document.getElementById("allclasses_navbar_top");
+  if(window==top) {
+    allClassesLink.style.display = "block";
+  }
+  else {
+    allClassesLink.style.display = "none";
+  }
+  //-->
+</script>
+</div>
+<a name="skip.navbar.top">
+<!--   -->
+</a></div>
+<!-- ========= END OF TOP NAVBAR ========= -->
+<div class="header">
+<h2 title="Uses of Class org.apache.hadoop.hbase.regionserver.TestSwitchToStreamRead.MatchLastRowCellNextRowFilter" class="title">Uses of Class<br>org.apache.hadoop.hbase.regionserver.TestSwitchToStreamRead.MatchLastRowCellNextRowFilter</h2>
+</div>
+<div class="classUseContainer">No usage of org.apache.hadoop.hbase.regionserver.TestSwitchToStreamRead.MatchLastRowCellNextRowFilter</div>
+<!-- ======= START OF BOTTOM NAVBAR ====== -->
+<div class="bottomNav"><a name="navbar.bottom">
+<!--   -->
+</a>
+<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
+<a name="navbar.bottom.firstrow">
+<!--   -->
+</a>
+<ul class="navList" title="Navigation">
+<li><a href="../../../../../../overview-summary.html">Overview</a></li>
+<li><a href="../package-summary.html">Package</a></li>
+<li><a href="../../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextRowFilter.html" title="class in org.apache.hadoop.hbase.regionserver">Class</a></li>
+<li class="navBarCell1Rev">Use</li>
+<li><a href="../../../../../../overview-tree.html">Tree</a></li>
+<li><a href="../../../../../../deprecated-list.html">Deprecated</a></li>
+<li><a href="../../../../../../index-all.html">Index</a></li>
+<li><a href="../../../../../../help-doc.html">Help</a></li>
+</ul>
+</div>
+<div class="subNav">
+<ul class="navList">
+<li>Prev</li>
+<li>Next</li>
+</ul>
+<ul class="navList">
+<li><a href="../../../../../../index.html?org/apache/hadoop/hbase/regionserver/class-use/TestSwitchToStreamRead.MatchLastRowCellNextRowFilter.html" target="_top">Frames</a></li>
+<li><a href="TestSwitchToStreamRead.MatchLastRowCellNextRowFilter.html" target="_top">No&nbsp;Frames</a></li>
+</ul>
+<ul class="navList" id="allclasses_navbar_bottom">
+<li><a href="../../../../../../allclasses-noframe.html">All&nbsp;Classes</a></li>
+</ul>
+<div>
+<script type="text/javascript"><!--
+  allClassesLink = document.getElementById("allclasses_navbar_bottom");
+  if(window==top) {
+    allClassesLink.style.display = "block";
+  }
+  else {
+    allClassesLink.style.display = "none";
+  }
+  //-->
+</script>
+</div>
+<a name="skip.navbar.bottom">
+<!--   -->
+</a></div>
+<!-- ======== END OF BOTTOM NAVBAR ======= -->
+<p class="legalCopy"><small>Copyright &#169; 2007&#x2013;2018 <a href="https://www.apache.org/">The Apache Software Foundation</a>. All rights reserved.</small></p>
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/org/apache/hadoop/hbase/regionserver/class-use/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/org/apache/hadoop/hbase/regionserver/class-use/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html b/testdevapidocs/org/apache/hadoop/hbase/regionserver/class-use/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html
new file mode 100644
index 0000000..7f058aa
--- /dev/null
+++ b/testdevapidocs/org/apache/hadoop/hbase/regionserver/class-use/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html
@@ -0,0 +1,125 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!-- NewPage -->
+<html lang="en">
+<head>
+<!-- Generated by javadoc -->
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Uses of Class org.apache.hadoop.hbase.regionserver.TestSwitchToStreamRead.MatchLastRowFilterRowFilter (Apache HBase 3.0.0-SNAPSHOT Test API)</title>
+<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
+<script type="text/javascript" src="../../../../../../script.js"></script>
+</head>
+<body>
+<script type="text/javascript"><!--
+    try {
+        if (location.href.indexOf('is-external=true') == -1) {
+            parent.document.title="Uses of Class org.apache.hadoop.hbase.regionserver.TestSwitchToStreamRead.MatchLastRowFilterRowFilter (Apache HBase 3.0.0-SNAPSHOT Test API)";
+        }
+    }
+    catch(err) {
+    }
+//-->
+</script>
+<noscript>
+<div>JavaScript is disabled on your browser.</div>
+</noscript>
+<!-- ========= START OF TOP NAVBAR ======= -->
+<div class="topNav"><a name="navbar.top">
+<!--   -->
+</a>
+<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
+<a name="navbar.top.firstrow">
+<!--   -->
+</a>
+<ul class="navList" title="Navigation">
+<li><a href="../../../../../../overview-summary.html">Overview</a></li>
+<li><a href="../package-summary.html">Package</a></li>
+<li><a href="../../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html" title="class in org.apache.hadoop.hbase.regionserver">Class</a></li>
+<li class="navBarCell1Rev">Use</li>
+<li><a href="../../../../../../overview-tree.html">Tree</a></li>
+<li><a href="../../../../../../deprecated-list.html">Deprecated</a></li>
+<li><a href="../../../../../../index-all.html">Index</a></li>
+<li><a href="../../../../../../help-doc.html">Help</a></li>
+</ul>
+</div>
+<div class="subNav">
+<ul class="navList">
+<li>Prev</li>
+<li>Next</li>
+</ul>
+<ul class="navList">
+<li><a href="../../../../../../index.html?org/apache/hadoop/hbase/regionserver/class-use/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html" target="_top">Frames</a></li>
+<li><a href="TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html" target="_top">No&nbsp;Frames</a></li>
+</ul>
+<ul class="navList" id="allclasses_navbar_top">
+<li><a href="../../../../../../allclasses-noframe.html">All&nbsp;Classes</a></li>
+</ul>
+<div>
+<script type="text/javascript"><!--
+  allClassesLink = document.getElementById("allclasses_navbar_top");
+  if(window==top) {
+    allClassesLink.style.display = "block";
+  }
+  else {
+    allClassesLink.style.display = "none";
+  }
+  //-->
+</script>
+</div>
+<a name="skip.navbar.top">
+<!--   -->
+</a></div>
+<!-- ========= END OF TOP NAVBAR ========= -->
+<div class="header">
+<h2 title="Uses of Class org.apache.hadoop.hbase.regionserver.TestSwitchToStreamRead.MatchLastRowFilterRowFilter" class="title">Uses of Class<br>org.apache.hadoop.hbase.regionserver.TestSwitchToStreamRead.MatchLastRowFilterRowFilter</h2>
+</div>
+<div class="classUseContainer">No usage of org.apache.hadoop.hbase.regionserver.TestSwitchToStreamRead.MatchLastRowFilterRowFilter</div>
+<!-- ======= START OF BOTTOM NAVBAR ====== -->
+<div class="bottomNav"><a name="navbar.bottom">
+<!--   -->
+</a>
+<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
+<a name="navbar.bottom.firstrow">
+<!--   -->
+</a>
+<ul class="navList" title="Navigation">
+<li><a href="../../../../../../overview-summary.html">Overview</a></li>
+<li><a href="../package-summary.html">Package</a></li>
+<li><a href="../../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html" title="class in org.apache.hadoop.hbase.regionserver">Class</a></li>
+<li class="navBarCell1Rev">Use</li>
+<li><a href="../../../../../../overview-tree.html">Tree</a></li>
+<li><a href="../../../../../../deprecated-list.html">Deprecated</a></li>
+<li><a href="../../../../../../index-all.html">Index</a></li>
+<li><a href="../../../../../../help-doc.html">Help</a></li>
+</ul>
+</div>
+<div class="subNav">
+<ul class="navList">
+<li>Prev</li>
+<li>Next</li>
+</ul>
+<ul class="navList">
+<li><a href="../../../../../../index.html?org/apache/hadoop/hbase/regionserver/class-use/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html" target="_top">Frames</a></li>
+<li><a href="TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html" target="_top">No&nbsp;Frames</a></li>
+</ul>
+<ul class="navList" id="allclasses_navbar_bottom">
+<li><a href="../../../../../../allclasses-noframe.html">All&nbsp;Classes</a></li>
+</ul>
+<div>
+<script type="text/javascript"><!--
+  allClassesLink = document.getElementById("allclasses_navbar_bottom");
+  if(window==top) {
+    allClassesLink.style.display = "block";
+  }
+  else {
+    allClassesLink.style.display = "none";
+  }
+  //-->
+</script>
+</div>
+<a name="skip.navbar.bottom">
+<!--   -->
+</a></div>
+<!-- ======== END OF BOTTOM NAVBAR ======= -->
+<p class="legalCopy"><small>Copyright &#169; 2007&#x2013;2018 <a href="https://www.apache.org/">The Apache Software Foundation</a>. All rights reserved.</small></p>
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/org/apache/hadoop/hbase/regionserver/class-use/TestSwitchToStreamRead.MatchLastRowKeyFilter.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/org/apache/hadoop/hbase/regionserver/class-use/TestSwitchToStreamRead.MatchLastRowKeyFilter.html b/testdevapidocs/org/apache/hadoop/hbase/regionserver/class-use/TestSwitchToStreamRead.MatchLastRowKeyFilter.html
new file mode 100644
index 0000000..a2a49d8
--- /dev/null
+++ b/testdevapidocs/org/apache/hadoop/hbase/regionserver/class-use/TestSwitchToStreamRead.MatchLastRowKeyFilter.html
@@ -0,0 +1,125 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!-- NewPage -->
+<html lang="en">
+<head>
+<!-- Generated by javadoc -->
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Uses of Class org.apache.hadoop.hbase.regionserver.TestSwitchToStreamRead.MatchLastRowKeyFilter (Apache HBase 3.0.0-SNAPSHOT Test API)</title>
+<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
+<script type="text/javascript" src="../../../../../../script.js"></script>
+</head>
+<body>
+<script type="text/javascript"><!--
+    try {
+        if (location.href.indexOf('is-external=true') == -1) {
+            parent.document.title="Uses of Class org.apache.hadoop.hbase.regionserver.TestSwitchToStreamRead.MatchLastRowKeyFilter (Apache HBase 3.0.0-SNAPSHOT Test API)";
+        }
+    }
+    catch(err) {
+    }
+//-->
+</script>
+<noscript>
+<div>JavaScript is disabled on your browser.</div>
+</noscript>
+<!-- ========= START OF TOP NAVBAR ======= -->
+<div class="topNav"><a name="navbar.top">
+<!--   -->
+</a>
+<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
+<a name="navbar.top.firstrow">
+<!--   -->
+</a>
+<ul class="navList" title="Navigation">
+<li><a href="../../../../../../overview-summary.html">Overview</a></li>
+<li><a href="../package-summary.html">Package</a></li>
+<li><a href="../../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowKeyFilter.html" title="class in org.apache.hadoop.hbase.regionserver">Class</a></li>
+<li class="navBarCell1Rev">Use</li>
+<li><a href="../../../../../../overview-tree.html">Tree</a></li>
+<li><a href="../../../../../../deprecated-list.html">Deprecated</a></li>
+<li><a href="../../../../../../index-all.html">Index</a></li>
+<li><a href="../../../../../../help-doc.html">Help</a></li>
+</ul>
+</div>
+<div class="subNav">
+<ul class="navList">
+<li>Prev</li>
+<li>Next</li>
+</ul>
+<ul class="navList">
+<li><a href="../../../../../../index.html?org/apache/hadoop/hbase/regionserver/class-use/TestSwitchToStreamRead.MatchLastRowKeyFilter.html" target="_top">Frames</a></li>
+<li><a href="TestSwitchToStreamRead.MatchLastRowKeyFilter.html" target="_top">No&nbsp;Frames</a></li>
+</ul>
+<ul class="navList" id="allclasses_navbar_top">
+<li><a href="../../../../../../allclasses-noframe.html">All&nbsp;Classes</a></li>
+</ul>
+<div>
+<script type="text/javascript"><!--
+  allClassesLink = document.getElementById("allclasses_navbar_top");
+  if(window==top) {
+    allClassesLink.style.display = "block";
+  }
+  else {
+    allClassesLink.style.display = "none";
+  }
+  //-->
+</script>
+</div>
+<a name="skip.navbar.top">
+<!--   -->
+</a></div>
+<!-- ========= END OF TOP NAVBAR ========= -->
+<div class="header">
+<h2 title="Uses of Class org.apache.hadoop.hbase.regionserver.TestSwitchToStreamRead.MatchLastRowKeyFilter" class="title">Uses of Class<br>org.apache.hadoop.hbase.regionserver.TestSwitchToStreamRead.MatchLastRowKeyFilter</h2>
+</div>
+<div class="classUseContainer">No usage of org.apache.hadoop.hbase.regionserver.TestSwitchToStreamRead.MatchLastRowKeyFilter</div>
+<!-- ======= START OF BOTTOM NAVBAR ====== -->
+<div class="bottomNav"><a name="navbar.bottom">
+<!--   -->
+</a>
+<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
+<a name="navbar.bottom.firstrow">
+<!--   -->
+</a>
+<ul class="navList" title="Navigation">
+<li><a href="../../../../../../overview-summary.html">Overview</a></li>
+<li><a href="../package-summary.html">Package</a></li>
+<li><a href="../../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowKeyFilter.html" title="class in org.apache.hadoop.hbase.regionserver">Class</a></li>
+<li class="navBarCell1Rev">Use</li>
+<li><a href="../../../../../../overview-tree.html">Tree</a></li>
+<li><a href="../../../../../../deprecated-list.html">Deprecated</a></li>
+<li><a href="../../../../../../index-all.html">Index</a></li>
+<li><a href="../../../../../../help-doc.html">Help</a></li>
+</ul>
+</div>
+<div class="subNav">
+<ul class="navList">
+<li>Prev</li>
+<li>Next</li>
+</ul>
+<ul class="navList">
+<li><a href="../../../../../../index.html?org/apache/hadoop/hbase/regionserver/class-use/TestSwitchToStreamRead.MatchLastRowKeyFilter.html" target="_top">Frames</a></li>
+<li><a href="TestSwitchToStreamRead.MatchLastRowKeyFilter.html" target="_top">No&nbsp;Frames</a></li>
+</ul>
+<ul class="navList" id="allclasses_navbar_bottom">
+<li><a href="../../../../../../allclasses-noframe.html">All&nbsp;Classes</a></li>
+</ul>
+<div>
+<script type="text/javascript"><!--
+  allClassesLink = document.getElementById("allclasses_navbar_bottom");
+  if(window==top) {
+    allClassesLink.style.display = "block";
+  }
+  else {
+    allClassesLink.style.display = "none";
+  }
+  //-->
+</script>
+</div>
+<a name="skip.navbar.bottom">
+<!--   -->
+</a></div>
+<!-- ======== END OF BOTTOM NAVBAR ======= -->
+<p class="legalCopy"><small>Copyright &#169; 2007&#x2013;2018 <a href="https://www.apache.org/">The Apache Software Foundation</a>. All rights reserved.</small></p>
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/org/apache/hadoop/hbase/regionserver/package-frame.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/org/apache/hadoop/hbase/regionserver/package-frame.html b/testdevapidocs/org/apache/hadoop/hbase/regionserver/package-frame.html
index fe980e3..cd1cbfc 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/regionserver/package-frame.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/regionserver/package-frame.html
@@ -267,6 +267,10 @@
 <li><a href="TestStripeStoreEngine.TestStoreEngine.html" title="class in org.apache.hadoop.hbase.regionserver" target="classFrame">TestStripeStoreEngine.TestStoreEngine</a></li>
 <li><a href="TestStripeStoreFileManager.html" title="class in org.apache.hadoop.hbase.regionserver" target="classFrame">TestStripeStoreFileManager</a></li>
 <li><a href="TestSwitchToStreamRead.html" title="class in org.apache.hadoop.hbase.regionserver" target="classFrame">TestSwitchToStreamRead</a></li>
+<li><a href="TestSwitchToStreamRead.MatchLastRowCellNextColFilter.html" title="class in org.apache.hadoop.hbase.regionserver" target="classFrame">TestSwitchToStreamRead.MatchLastRowCellNextColFilter</a></li>
+<li><a href="TestSwitchToStreamRead.MatchLastRowCellNextRowFilter.html" title="class in org.apache.hadoop.hbase.regionserver" target="classFrame">TestSwitchToStreamRead.MatchLastRowCellNextRowFilter</a></li>
+<li><a href="TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html" title="class in org.apache.hadoop.hbase.regionserver" target="classFrame">TestSwitchToStreamRead.MatchLastRowFilterRowFilter</a></li>
+<li><a href="TestSwitchToStreamRead.MatchLastRowKeyFilter.html" title="class in org.apache.hadoop.hbase.regionserver" target="classFrame">TestSwitchToStreamRead.MatchLastRowKeyFilter</a></li>
 <li><a href="TestSyncTimeRangeTracker.html" title="class in org.apache.hadoop.hbase.regionserver" target="classFrame">TestSyncTimeRangeTracker</a></li>
 <li><a href="TestSyncTimeRangeTracker.RandomTestData.html" title="class in org.apache.hadoop.hbase.regionserver" target="classFrame">TestSyncTimeRangeTracker.RandomTestData</a></li>
 <li><a href="TestSyncTimeRangeTracker.TrtUpdateRunnable.html" title="class in org.apache.hadoop.hbase.regionserver" target="classFrame">TestSyncTimeRangeTracker.TrtUpdateRunnable</a></li>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/org/apache/hadoop/hbase/regionserver/package-summary.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/org/apache/hadoop/hbase/regionserver/package-summary.html b/testdevapidocs/org/apache/hadoop/hbase/regionserver/package-summary.html
index 6ff7db7..88b8503 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/regionserver/package-summary.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/regionserver/package-summary.html
@@ -1360,6 +1360,22 @@
 <td class="colLast">&nbsp;</td>
 </tr>
 <tr class="altColor">
+<td class="colFirst"><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextColFilter.html" title="class in org.apache.hadoop.hbase.regionserver">TestSwitchToStreamRead.MatchLastRowCellNextColFilter</a></td>
+<td class="colLast">&nbsp;</td>
+</tr>
+<tr class="rowColor">
+<td class="colFirst"><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextRowFilter.html" title="class in org.apache.hadoop.hbase.regionserver">TestSwitchToStreamRead.MatchLastRowCellNextRowFilter</a></td>
+<td class="colLast">&nbsp;</td>
+</tr>
+<tr class="altColor">
+<td class="colFirst"><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html" title="class in org.apache.hadoop.hbase.regionserver">TestSwitchToStreamRead.MatchLastRowFilterRowFilter</a></td>
+<td class="colLast">&nbsp;</td>
+</tr>
+<tr class="rowColor">
+<td class="colFirst"><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowKeyFilter.html" title="class in org.apache.hadoop.hbase.regionserver">TestSwitchToStreamRead.MatchLastRowKeyFilter</a></td>
+<td class="colLast">&nbsp;</td>
+</tr>
+<tr class="altColor">
 <td class="colFirst"><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSyncTimeRangeTracker.html" title="class in org.apache.hadoop.hbase.regionserver">TestSyncTimeRangeTracker</a></td>
 <td class="colLast">&nbsp;</td>
 </tr>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/org/apache/hadoop/hbase/regionserver/package-tree.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/org/apache/hadoop/hbase/regionserver/package-tree.html b/testdevapidocs/org/apache/hadoop/hbase/regionserver/package-tree.html
index 87ba170..05fcabc 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/regionserver/package-tree.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/regionserver/package-tree.html
@@ -205,6 +205,10 @@
 <ul>
 <li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/TestScannerHeartbeatMessages.SparseCellFilter.html" title="class in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">TestScannerHeartbeatMessages.SparseCellFilter</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/TestScannerHeartbeatMessages.SparseRowFilter.html" title="class in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">TestScannerHeartbeatMessages.SparseRowFilter</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextColFilter.html" title="class in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">TestSwitchToStreamRead.MatchLastRowCellNextColFilter</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextRowFilter.html" title="class in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">TestSwitchToStreamRead.MatchLastRowCellNextRowFilter</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html" title="class in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">TestSwitchToStreamRead.MatchLastRowFilterRowFilter</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowKeyFilter.html" title="class in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">TestSwitchToStreamRead.MatchLastRowKeyFilter</span></a></li>
 </ul>
 </li>
 </ul>
@@ -655,10 +659,10 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true" title="class or interface in java.io">Serializable</a>)
 <ul>
+<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/TestCacheOnWriteInSchema.CacheOnWriteType.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">TestCacheOnWriteInSchema.CacheOnWriteType</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/TestAtomicOperation.TestStep.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">TestAtomicOperation.TestStep</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/TestMultiLogThreshold.ActionType.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">TestMultiLogThreshold.ActionType</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/TestRegionServerReadRequestMetrics.Metric.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">TestRegionServerReadRequestMetrics.Metric</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/TestAtomicOperation.TestStep.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">TestAtomicOperation.TestStep</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/TestCacheOnWriteInSchema.CacheOnWriteType.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">TestCacheOnWriteInSchema.CacheOnWriteType</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/DataBlockEncodingTool.Manipulation.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">DataBlockEncodingTool.Manipulation</span></a></li>
 </ul>
 </li>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/org/apache/hadoop/hbase/test/package-tree.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/org/apache/hadoop/hbase/test/package-tree.html b/testdevapidocs/org/apache/hadoop/hbase/test/package-tree.html
index 837933f..28ed7f0 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/test/package-tree.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/test/package-tree.html
@@ -253,10 +253,10 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true" title="class or interface in java.io">Serializable</a>)
 <ul>
-<li type="circle">org.apache.hadoop.hbase.test.<a href="../../../../../org/apache/hadoop/hbase/test/IntegrationTestBigLinkedList.Generator.Counts.html" title="enum in org.apache.hadoop.hbase.test"><span class="typeNameLink">IntegrationTestBigLinkedList.Generator.Counts</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.test.<a href="../../../../../org/apache/hadoop/hbase/test/IntegrationTestWithCellVisibilityLoadAndVerify.Counters.html" title="enum in org.apache.hadoop.hbase.test"><span class="typeNameLink">IntegrationTestWithCellVisibilityLoadAndVerify.Counters</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.test.<a href="../../../../../org/apache/hadoop/hbase/test/IntegrationTestBigLinkedList.Verify.Counts.html" title="enum in org.apache.hadoop.hbase.test"><span class="typeNameLink">IntegrationTestBigLinkedList.Verify.Counts</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.test.<a href="../../../../../org/apache/hadoop/hbase/test/IntegrationTestLoadAndVerify.Counters.html" title="enum in org.apache.hadoop.hbase.test"><span class="typeNameLink">IntegrationTestLoadAndVerify.Counters</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.test.<a href="../../../../../org/apache/hadoop/hbase/test/IntegrationTestBigLinkedList.Generator.Counts.html" title="enum in org.apache.hadoop.hbase.test"><span class="typeNameLink">IntegrationTestBigLinkedList.Generator.Counts</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.test.<a href="../../../../../org/apache/hadoop/hbase/test/IntegrationTestBigLinkedList.Verify.Counts.html" title="enum in org.apache.hadoop.hbase.test"><span class="typeNameLink">IntegrationTestBigLinkedList.Verify.Counts</span></a></li>
 </ul>
 </li>
 </ul>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/org/apache/hadoop/hbase/wal/package-tree.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/org/apache/hadoop/hbase/wal/package-tree.html b/testdevapidocs/org/apache/hadoop/hbase/wal/package-tree.html
index 4edd3f8..f7d6df6 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/wal/package-tree.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/wal/package-tree.html
@@ -140,8 +140,8 @@
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true" title="class or interface in java.io">Serializable</a>)
 <ul>
 <li type="circle">org.apache.hadoop.hbase.wal.<a href="../../../../../org/apache/hadoop/hbase/wal/IOTestProvider.AllowedOperations.html" title="enum in org.apache.hadoop.hbase.wal"><span class="typeNameLink">IOTestProvider.AllowedOperations</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.wal.<a href="../../../../../org/apache/hadoop/hbase/wal/FaultyFSLog.FailureType.html" title="enum in org.apache.hadoop.hbase.wal"><span class="typeNameLink">FaultyFSLog.FailureType</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.wal.<a href="../../../../../org/apache/hadoop/hbase/wal/TestWALSplit.Corruptions.html" title="enum in org.apache.hadoop.hbase.wal"><span class="typeNameLink">TestWALSplit.Corruptions</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.wal.<a href="../../../../../org/apache/hadoop/hbase/wal/FaultyFSLog.FailureType.html" title="enum in org.apache.hadoop.hbase.wal"><span class="typeNameLink">FaultyFSLog.FailureType</span></a></li>
 </ul>
 </li>
 </ul>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/overview-tree.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/overview-tree.html b/testdevapidocs/overview-tree.html
index 1d990ee..eda69b3 100644
--- a/testdevapidocs/overview-tree.html
+++ b/testdevapidocs/overview-tree.html
@@ -989,6 +989,10 @@
 <li type="circle">org.apache.hadoop.hbase.coprocessor.<a href="org/apache/hadoop/hbase/coprocessor/TestRegionObserverScannerOpenHook.NoDataFilter.html" title="class in org.apache.hadoop.hbase.coprocessor"><span class="typeNameLink">TestRegionObserverScannerOpenHook.NoDataFilter</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.regionserver.<a href="org/apache/hadoop/hbase/regionserver/TestScannerHeartbeatMessages.SparseCellFilter.html" title="class in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">TestScannerHeartbeatMessages.SparseCellFilter</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.regionserver.<a href="org/apache/hadoop/hbase/regionserver/TestScannerHeartbeatMessages.SparseRowFilter.html" title="class in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">TestScannerHeartbeatMessages.SparseRowFilter</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextColFilter.html" title="class in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">TestSwitchToStreamRead.MatchLastRowCellNextColFilter</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextRowFilter.html" title="class in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">TestSwitchToStreamRead.MatchLastRowCellNextRowFilter</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html" title="class in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">TestSwitchToStreamRead.MatchLastRowFilterRowFilter</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowKeyFilter.html" title="class in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">TestSwitchToStreamRead.MatchLastRowKeyFilter</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.regionserver.querymatcher.<a href="org/apache/hadoop/hbase/regionserver/querymatcher/TestUserScanQueryMatcher.AlwaysIncludeAndSeekNextRowFilter.html" title="class in org.apache.hadoop.hbase.regionserver.querymatcher"><span class="typeNameLink">TestUserScanQueryMatcher.AlwaysIncludeAndSeekNextRowFilter</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.regionserver.querymatcher.<a href="org/apache/hadoop/hbase/regionserver/querymatcher/TestUserScanQueryMatcher.AlwaysIncludeFilter.html" title="class in org.apache.hadoop.hbase.regionserver.querymatcher"><span class="typeNameLink">TestUserScanQueryMatcher.AlwaysIncludeFilter</span></a></li>
 </ul>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/CacheTestUtils.ByteArrayCacheable.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/CacheTestUtils.ByteArrayCacheable.html b/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/CacheTestUtils.ByteArrayCacheable.html
index d8c6305..c08cd82 100644
--- a/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/CacheTestUtils.ByteArrayCacheable.html
+++ b/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/CacheTestUtils.ByteArrayCacheable.html
@@ -319,7 +319,7 @@
 <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>    @Override<a name="line.313"></a>
-<span class="sourceLineNo">314</span>    public void serialize(ByteBuffer destination) {<a name="line.314"></a>
+<span class="sourceLineNo">314</span>    public void serialize(ByteBuffer destination, boolean includeNextBlockMetadata) {<a name="line.314"></a>
 <span class="sourceLineNo">315</span>      destination.putInt(buf.length);<a name="line.315"></a>
 <span class="sourceLineNo">316</span>      Thread.yield();<a name="line.316"></a>
 <span class="sourceLineNo">317</span>      destination.put(buf);<a name="line.317"></a>
@@ -406,7 +406,18 @@
 <span class="sourceLineNo">398</span>      return this.block;<a name="line.398"></a>
 <span class="sourceLineNo">399</span>    }<a name="line.399"></a>
 <span class="sourceLineNo">400</span>  }<a name="line.400"></a>
-<span class="sourceLineNo">401</span>}<a name="line.401"></a>
+<span class="sourceLineNo">401</span><a name="line.401"></a>
+<span class="sourceLineNo">402</span>  public static void getBlockAndAssertEquals(BlockCache cache, BlockCacheKey key,<a name="line.402"></a>
+<span class="sourceLineNo">403</span>                                             Cacheable blockToCache, ByteBuffer destBuffer,<a name="line.403"></a>
+<span class="sourceLineNo">404</span>                                             ByteBuffer expectedBuffer) {<a name="line.404"></a>
+<span class="sourceLineNo">405</span>    destBuffer.clear();<a name="line.405"></a>
+<span class="sourceLineNo">406</span>    cache.cacheBlock(key, blockToCache);<a name="line.406"></a>
+<span class="sourceLineNo">407</span>    Cacheable actualBlock = cache.getBlock(key, false, false, false);<a name="line.407"></a>
+<span class="sourceLineNo">408</span>    actualBlock.serialize(destBuffer, true);<a name="line.408"></a>
+<span class="sourceLineNo">409</span>    assertEquals(expectedBuffer, destBuffer);<a name="line.409"></a>
+<span class="sourceLineNo">410</span>    cache.returnBlock(key, actualBlock);<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>
 
 
 

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/CacheTestUtils.HFileBlockPair.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/CacheTestUtils.HFileBlockPair.html b/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/CacheTestUtils.HFileBlockPair.html
index d8c6305..c08cd82 100644
--- a/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/CacheTestUtils.HFileBlockPair.html
+++ b/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/CacheTestUtils.HFileBlockPair.html
@@ -319,7 +319,7 @@
 <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>    @Override<a name="line.313"></a>
-<span class="sourceLineNo">314</span>    public void serialize(ByteBuffer destination) {<a name="line.314"></a>
+<span class="sourceLineNo">314</span>    public void serialize(ByteBuffer destination, boolean includeNextBlockMetadata) {<a name="line.314"></a>
 <span class="sourceLineNo">315</span>      destination.putInt(buf.length);<a name="line.315"></a>
 <span class="sourceLineNo">316</span>      Thread.yield();<a name="line.316"></a>
 <span class="sourceLineNo">317</span>      destination.put(buf);<a name="line.317"></a>
@@ -406,7 +406,18 @@
 <span class="sourceLineNo">398</span>      return this.block;<a name="line.398"></a>
 <span class="sourceLineNo">399</span>    }<a name="line.399"></a>
 <span class="sourceLineNo">400</span>  }<a name="line.400"></a>
-<span class="sourceLineNo">401</span>}<a name="line.401"></a>
+<span class="sourceLineNo">401</span><a name="line.401"></a>
+<span class="sourceLineNo">402</span>  public static void getBlockAndAssertEquals(BlockCache cache, BlockCacheKey key,<a name="line.402"></a>
+<span class="sourceLineNo">403</span>                                             Cacheable blockToCache, ByteBuffer destBuffer,<a name="line.403"></a>
+<span class="sourceLineNo">404</span>                                             ByteBuffer expectedBuffer) {<a name="line.404"></a>
+<span class="sourceLineNo">405</span>    destBuffer.clear();<a name="line.405"></a>
+<span class="sourceLineNo">406</span>    cache.cacheBlock(key, blockToCache);<a name="line.406"></a>
+<span class="sourceLineNo">407</span>    Cacheable actualBlock = cache.getBlock(key, false, false, false);<a name="line.407"></a>
+<span class="sourceLineNo">408</span>    actualBlock.serialize(destBuffer, true);<a name="line.408"></a>
+<span class="sourceLineNo">409</span>    assertEquals(expectedBuffer, destBuffer);<a name="line.409"></a>
+<span class="sourceLineNo">410</span>    cache.returnBlock(key, actualBlock);<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>
 
 
 

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/CacheTestUtils.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/CacheTestUtils.html b/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/CacheTestUtils.html
index d8c6305..c08cd82 100644
--- a/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/CacheTestUtils.html
+++ b/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/CacheTestUtils.html
@@ -319,7 +319,7 @@
 <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>    @Override<a name="line.313"></a>
-<span class="sourceLineNo">314</span>    public void serialize(ByteBuffer destination) {<a name="line.314"></a>
+<span class="sourceLineNo">314</span>    public void serialize(ByteBuffer destination, boolean includeNextBlockMetadata) {<a name="line.314"></a>
 <span class="sourceLineNo">315</span>      destination.putInt(buf.length);<a name="line.315"></a>
 <span class="sourceLineNo">316</span>      Thread.yield();<a name="line.316"></a>
 <span class="sourceLineNo">317</span>      destination.put(buf);<a name="line.317"></a>
@@ -406,7 +406,18 @@
 <span class="sourceLineNo">398</span>      return this.block;<a name="line.398"></a>
 <span class="sourceLineNo">399</span>    }<a name="line.399"></a>
 <span class="sourceLineNo">400</span>  }<a name="line.400"></a>
-<span class="sourceLineNo">401</span>}<a name="line.401"></a>
+<span class="sourceLineNo">401</span><a name="line.401"></a>
+<span class="sourceLineNo">402</span>  public static void getBlockAndAssertEquals(BlockCache cache, BlockCacheKey key,<a name="line.402"></a>
+<span class="sourceLineNo">403</span>                                             Cacheable blockToCache, ByteBuffer destBuffer,<a name="line.403"></a>
+<span class="sourceLineNo">404</span>                                             ByteBuffer expectedBuffer) {<a name="line.404"></a>
+<span class="sourceLineNo">405</span>    destBuffer.clear();<a name="line.405"></a>
+<span class="sourceLineNo">406</span>    cache.cacheBlock(key, blockToCache);<a name="line.406"></a>
+<span class="sourceLineNo">407</span>    Cacheable actualBlock = cache.getBlock(key, false, false, false);<a name="line.407"></a>
+<span class="sourceLineNo">408</span>    actualBlock.serialize(destBuffer, true);<a name="line.408"></a>
+<span class="sourceLineNo">409</span>    assertEquals(expectedBuffer, destBuffer);<a name="line.409"></a>
+<span class="sourceLineNo">410</span>    cache.returnBlock(key, actualBlock);<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>
 
 
 

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestCacheConfig.DataCacheEntry.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestCacheConfig.DataCacheEntry.html b/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestCacheConfig.DataCacheEntry.html
index c5ad761..f8e34f2 100644
--- a/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestCacheConfig.DataCacheEntry.html
+++ b/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestCacheConfig.DataCacheEntry.html
@@ -144,7 +144,7 @@
 <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>    @Override<a name="line.138"></a>
-<span class="sourceLineNo">139</span>    public void serialize(ByteBuffer destination) {<a name="line.139"></a>
+<span class="sourceLineNo">139</span>    public void serialize(ByteBuffer destination, boolean includeNextBlockMetadata) {<a name="line.139"></a>
 <span class="sourceLineNo">140</span>      LOG.info("Serialized " + this + " to " + destination);<a name="line.140"></a>
 <span class="sourceLineNo">141</span>    }<a name="line.141"></a>
 <span class="sourceLineNo">142</span><a name="line.142"></a>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestCacheConfig.Deserializer.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestCacheConfig.Deserializer.html b/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestCacheConfig.Deserializer.html
index c5ad761..f8e34f2 100644
--- a/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestCacheConfig.Deserializer.html
+++ b/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestCacheConfig.Deserializer.html
@@ -144,7 +144,7 @@
 <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>    @Override<a name="line.138"></a>
-<span class="sourceLineNo">139</span>    public void serialize(ByteBuffer destination) {<a name="line.139"></a>
+<span class="sourceLineNo">139</span>    public void serialize(ByteBuffer destination, boolean includeNextBlockMetadata) {<a name="line.139"></a>
 <span class="sourceLineNo">140</span>      LOG.info("Serialized " + this + " to " + destination);<a name="line.140"></a>
 <span class="sourceLineNo">141</span>    }<a name="line.141"></a>
 <span class="sourceLineNo">142</span><a name="line.142"></a>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestCacheConfig.IndexCacheEntry.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestCacheConfig.IndexCacheEntry.html b/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestCacheConfig.IndexCacheEntry.html
index c5ad761..f8e34f2 100644
--- a/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestCacheConfig.IndexCacheEntry.html
+++ b/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestCacheConfig.IndexCacheEntry.html
@@ -144,7 +144,7 @@
 <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>    @Override<a name="line.138"></a>
-<span class="sourceLineNo">139</span>    public void serialize(ByteBuffer destination) {<a name="line.139"></a>
+<span class="sourceLineNo">139</span>    public void serialize(ByteBuffer destination, boolean includeNextBlockMetadata) {<a name="line.139"></a>
 <span class="sourceLineNo">140</span>      LOG.info("Serialized " + this + " to " + destination);<a name="line.140"></a>
 <span class="sourceLineNo">141</span>    }<a name="line.141"></a>
 <span class="sourceLineNo">142</span><a name="line.142"></a>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestCacheConfig.MetaCacheEntry.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestCacheConfig.MetaCacheEntry.html b/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestCacheConfig.MetaCacheEntry.html
index c5ad761..f8e34f2 100644
--- a/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestCacheConfig.MetaCacheEntry.html
+++ b/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestCacheConfig.MetaCacheEntry.html
@@ -144,7 +144,7 @@
 <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>    @Override<a name="line.138"></a>
-<span class="sourceLineNo">139</span>    public void serialize(ByteBuffer destination) {<a name="line.139"></a>
+<span class="sourceLineNo">139</span>    public void serialize(ByteBuffer destination, boolean includeNextBlockMetadata) {<a name="line.139"></a>
 <span class="sourceLineNo">140</span>      LOG.info("Serialized " + this + " to " + destination);<a name="line.140"></a>
 <span class="sourceLineNo">141</span>    }<a name="line.141"></a>
 <span class="sourceLineNo">142</span><a name="line.142"></a>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestCacheConfig.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestCacheConfig.html b/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestCacheConfig.html
index c5ad761..f8e34f2 100644
--- a/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestCacheConfig.html
+++ b/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestCacheConfig.html
@@ -144,7 +144,7 @@
 <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>    @Override<a name="line.138"></a>
-<span class="sourceLineNo">139</span>    public void serialize(ByteBuffer destination) {<a name="line.139"></a>
+<span class="sourceLineNo">139</span>    public void serialize(ByteBuffer destination, boolean includeNextBlockMetadata) {<a name="line.139"></a>
 <span class="sourceLineNo">140</span>      LOG.info("Serialized " + this + " to " + destination);<a name="line.140"></a>
 <span class="sourceLineNo">141</span>    }<a name="line.141"></a>
 <span class="sourceLineNo">142</span><a name="line.142"></a>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestCachedBlockQueue.CachedBlock.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestCachedBlockQueue.CachedBlock.html b/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestCachedBlockQueue.CachedBlock.html
index b082faa..dec73f7 100644
--- a/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestCachedBlockQueue.CachedBlock.html
+++ b/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestCachedBlockQueue.CachedBlock.html
@@ -139,7 +139,7 @@
 <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>            @Override<a name="line.133"></a>
-<span class="sourceLineNo">134</span>            public void serialize(ByteBuffer destination) {<a name="line.134"></a>
+<span class="sourceLineNo">134</span>            public void serialize(ByteBuffer destination, boolean includeNextBlockMetadata) {<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>            @Override<a name="line.137"></a>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestCachedBlockQueue.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestCachedBlockQueue.html b/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestCachedBlockQueue.html
index b082faa..dec73f7 100644
--- a/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestCachedBlockQueue.html
+++ b/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestCachedBlockQueue.html
@@ -139,7 +139,7 @@
 <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>            @Override<a name="line.133"></a>
-<span class="sourceLineNo">134</span>            public void serialize(ByteBuffer destination) {<a name="line.134"></a>
+<span class="sourceLineNo">134</span>            public void serialize(ByteBuffer destination, boolean includeNextBlockMetadata) {<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>            @Override<a name="line.137"></a>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestHFileBlock.BlockReaderThread.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestHFileBlock.BlockReaderThread.html b/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestHFileBlock.BlockReaderThread.html
index 37f7b15..da0a780 100644
--- a/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestHFileBlock.BlockReaderThread.html
+++ b/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestHFileBlock.BlockReaderThread.html
@@ -476,7 +476,7 @@
 <span class="sourceLineNo">468</span>            // test serialized blocks<a name="line.468"></a>
 <span class="sourceLineNo">469</span>            for (boolean reuseBuffer : new boolean[] { false, true }) {<a name="line.469"></a>
 <span class="sourceLineNo">470</span>              ByteBuffer serialized = ByteBuffer.allocate(blockFromHFile.getSerializedLength());<a name="line.470"></a>
-<span class="sourceLineNo">471</span>              blockFromHFile.serialize(serialized);<a name="line.471"></a>
+<span class="sourceLineNo">471</span>              blockFromHFile.serialize(serialized, true);<a name="line.471"></a>
 <span class="sourceLineNo">472</span>              HFileBlock deserialized =<a name="line.472"></a>
 <span class="sourceLineNo">473</span>                  (HFileBlock) blockFromHFile.getDeserializer().deserialize(<a name="line.473"></a>
 <span class="sourceLineNo">474</span>                    new SingleByteBuff(serialized), reuseBuffer, MemoryType.EXCLUSIVE);<a name="line.474"></a>
@@ -866,7 +866,30 @@
 <span class="sourceLineNo">858</span>          block.heapSize());<a name="line.858"></a>
 <span class="sourceLineNo">859</span>    }<a name="line.859"></a>
 <span class="sourceLineNo">860</span>  }<a name="line.860"></a>
-<span class="sourceLineNo">861</span>}<a name="line.861"></a>
+<span class="sourceLineNo">861</span><a name="line.861"></a>
+<span class="sourceLineNo">862</span>  @Test<a name="line.862"></a>
+<span class="sourceLineNo">863</span>  public void testSerializeWithoutNextBlockMetadata() {<a name="line.863"></a>
+<span class="sourceLineNo">864</span>    int size = 100;<a name="line.864"></a>
+<span class="sourceLineNo">865</span>    int length = HConstants.HFILEBLOCK_HEADER_SIZE + size;<a name="line.865"></a>
+<span class="sourceLineNo">866</span>    byte[] byteArr = new byte[length];<a name="line.866"></a>
+<span class="sourceLineNo">867</span>    ByteBuffer buf = ByteBuffer.wrap(byteArr, 0, size);<a name="line.867"></a>
+<span class="sourceLineNo">868</span>    HFileContext meta = new HFileContextBuilder().build();<a name="line.868"></a>
+<span class="sourceLineNo">869</span>    HFileBlock blockWithNextBlockMetadata = new HFileBlock(BlockType.DATA, size, size, -1, buf,<a name="line.869"></a>
+<span class="sourceLineNo">870</span>        HFileBlock.FILL_HEADER, -1, 52, -1, meta);<a name="line.870"></a>
+<span class="sourceLineNo">871</span>    HFileBlock blockWithoutNextBlockMetadata = new HFileBlock(BlockType.DATA, size, size, -1, buf,<a name="line.871"></a>
+<span class="sourceLineNo">872</span>        HFileBlock.FILL_HEADER, -1, -1, -1, meta);<a name="line.872"></a>
+<span class="sourceLineNo">873</span>    ByteBuffer buff1 = ByteBuffer.allocate(length);<a name="line.873"></a>
+<span class="sourceLineNo">874</span>    ByteBuffer buff2 = ByteBuffer.allocate(length);<a name="line.874"></a>
+<span class="sourceLineNo">875</span>    blockWithNextBlockMetadata.serialize(buff1, true);<a name="line.875"></a>
+<span class="sourceLineNo">876</span>    blockWithoutNextBlockMetadata.serialize(buff2, true);<a name="line.876"></a>
+<span class="sourceLineNo">877</span>    assertNotEquals(buff1, buff2);<a name="line.877"></a>
+<span class="sourceLineNo">878</span>    buff1.clear();<a name="line.878"></a>
+<span class="sourceLineNo">879</span>    buff2.clear();<a name="line.879"></a>
+<span class="sourceLineNo">880</span>    blockWithNextBlockMetadata.serialize(buff1, false);<a name="line.880"></a>
+<span class="sourceLineNo">881</span>    blockWithoutNextBlockMetadata.serialize(buff2, false);<a name="line.881"></a>
+<span class="sourceLineNo">882</span>    assertEquals(buff1, buff2);<a name="line.882"></a>
+<span class="sourceLineNo">883</span>  }<a name="line.883"></a>
+<span class="sourceLineNo">884</span>}<a name="line.884"></a>
 
 
 


[16/50] hbase-site git commit: Published site at 26babcf013de696b899d76a3c39434b794440d8d.

Posted by gi...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html
----------------------------------------------------------------------
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html b/devapidocs/src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html
index cabb570..90f3b1e 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html
@@ -107,660 +107,661 @@
 <span class="sourceLineNo">099</span><a name="line.99"></a>
 <span class="sourceLineNo">100</span>  private Cell lastPeekedCell = null;<a name="line.100"></a>
 <span class="sourceLineNo">101</span><a name="line.101"></a>
-<span class="sourceLineNo">102</span>  /**<a name="line.102"></a>
-<span class="sourceLineNo">103</span>   * Tracks the relevant server side metrics during scans. null when metrics should not be tracked<a name="line.103"></a>
-<span class="sourceLineNo">104</span>   */<a name="line.104"></a>
-<span class="sourceLineNo">105</span>  final ServerSideScanMetrics metrics;<a name="line.105"></a>
-<span class="sourceLineNo">106</span><a name="line.106"></a>
-<span class="sourceLineNo">107</span>  ScannerContext(boolean keepProgress, LimitFields limitsToCopy, boolean trackMetrics) {<a name="line.107"></a>
-<span class="sourceLineNo">108</span>    this.limits = new LimitFields();<a name="line.108"></a>
-<span class="sourceLineNo">109</span>    if (limitsToCopy != null) {<a name="line.109"></a>
-<span class="sourceLineNo">110</span>      this.limits.copy(limitsToCopy);<a name="line.110"></a>
-<span class="sourceLineNo">111</span>    }<a name="line.111"></a>
+<span class="sourceLineNo">102</span>  // Set this to true will have the same behavior with reaching the time limit.<a name="line.102"></a>
+<span class="sourceLineNo">103</span>  // This is used when you want to make the current RSRpcService.scan returns immediately. For<a name="line.103"></a>
+<span class="sourceLineNo">104</span>  // example, when we want to switch from pread to stream, we can only do it after the rpc call is<a name="line.104"></a>
+<span class="sourceLineNo">105</span>  // returned.<a name="line.105"></a>
+<span class="sourceLineNo">106</span>  private boolean returnImmediately;<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>   * Tracks the relevant server side metrics during scans. null when metrics should not be tracked<a name="line.109"></a>
+<span class="sourceLineNo">110</span>   */<a name="line.110"></a>
+<span class="sourceLineNo">111</span>  final ServerSideScanMetrics metrics;<a name="line.111"></a>
 <span class="sourceLineNo">112</span><a name="line.112"></a>
-<span class="sourceLineNo">113</span>    // Progress fields are initialized to 0<a name="line.113"></a>
-<span class="sourceLineNo">114</span>    progress = new ProgressFields(0, 0, 0);<a name="line.114"></a>
-<span class="sourceLineNo">115</span><a name="line.115"></a>
-<span class="sourceLineNo">116</span>    this.keepProgress = keepProgress;<a name="line.116"></a>
-<span class="sourceLineNo">117</span>    this.scannerState = DEFAULT_STATE;<a name="line.117"></a>
-<span class="sourceLineNo">118</span>    this.metrics = trackMetrics ? new ServerSideScanMetrics() : null;<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>  boolean isTrackingMetrics() {<a name="line.121"></a>
-<span class="sourceLineNo">122</span>    return this.metrics != null;<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>   * Get the metrics instance. Should only be called after a call to {@link #isTrackingMetrics()}<a name="line.126"></a>
-<span class="sourceLineNo">127</span>   * has been made to confirm that metrics are indeed being tracked.<a name="line.127"></a>
-<span class="sourceLineNo">128</span>   * @return {@link ServerSideScanMetrics} instance that is tracking metrics for this scan<a name="line.128"></a>
-<span class="sourceLineNo">129</span>   */<a name="line.129"></a>
-<span class="sourceLineNo">130</span>  ServerSideScanMetrics getMetrics() {<a name="line.130"></a>
-<span class="sourceLineNo">131</span>    assert isTrackingMetrics();<a name="line.131"></a>
-<span class="sourceLineNo">132</span>    return this.metrics;<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>   * @return true if the progress tracked so far in this instance will be considered during an<a name="line.136"></a>
-<span class="sourceLineNo">137</span>   *         invocation of {@link InternalScanner#next(java.util.List)} or<a name="line.137"></a>
-<span class="sourceLineNo">138</span>   *         {@link RegionScanner#next(java.util.List)}. false when the progress tracked so far<a name="line.138"></a>
-<span class="sourceLineNo">139</span>   *         should not be considered and should instead be wiped away via {@link #clearProgress()}<a name="line.139"></a>
-<span class="sourceLineNo">140</span>   */<a name="line.140"></a>
-<span class="sourceLineNo">141</span>  boolean getKeepProgress() {<a name="line.141"></a>
-<span class="sourceLineNo">142</span>    return keepProgress;<a name="line.142"></a>
-<span class="sourceLineNo">143</span>  }<a name="line.143"></a>
-<span class="sourceLineNo">144</span><a name="line.144"></a>
-<span class="sourceLineNo">145</span>  void setKeepProgress(boolean keepProgress) {<a name="line.145"></a>
-<span class="sourceLineNo">146</span>    this.keepProgress = keepProgress;<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>   * Progress towards the batch limit has been made. Increment internal tracking of batch progress<a name="line.150"></a>
-<span class="sourceLineNo">151</span>   */<a name="line.151"></a>
-<span class="sourceLineNo">152</span>  void incrementBatchProgress(int batch) {<a name="line.152"></a>
-<span class="sourceLineNo">153</span>    int currentBatch = progress.getBatch();<a name="line.153"></a>
-<span class="sourceLineNo">154</span>    progress.setBatch(currentBatch + batch);<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>   * Progress towards the size limit has been made. Increment internal tracking of size progress<a name="line.158"></a>
-<span class="sourceLineNo">159</span>   */<a name="line.159"></a>
-<span class="sourceLineNo">160</span>  void incrementSizeProgress(long dataSize, long heapSize) {<a name="line.160"></a>
-<span class="sourceLineNo">161</span>    long curDataSize = progress.getDataSize();<a name="line.161"></a>
-<span class="sourceLineNo">162</span>    progress.setDataSize(curDataSize + dataSize);<a name="line.162"></a>
-<span class="sourceLineNo">163</span>    long curHeapSize = progress.getHeapSize();<a name="line.163"></a>
-<span class="sourceLineNo">164</span>    progress.setHeapSize(curHeapSize + heapSize);<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>  int getBatchProgress() {<a name="line.167"></a>
-<span class="sourceLineNo">168</span>    return progress.getBatch();<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>  long getDataSizeProgress() {<a name="line.171"></a>
-<span class="sourceLineNo">172</span>    return progress.getDataSize();<a name="line.172"></a>
-<span class="sourceLineNo">173</span>  }<a name="line.173"></a>
-<span class="sourceLineNo">174</span><a name="line.174"></a>
-<span class="sourceLineNo">175</span>  long getHeapSizeProgress() {<a name="line.175"></a>
-<span class="sourceLineNo">176</span>    return progress.getHeapSize();<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>  void setProgress(int batchProgress, long sizeProgress, long heapSizeProgress) {<a name="line.179"></a>
-<span class="sourceLineNo">180</span>    setBatchProgress(batchProgress);<a name="line.180"></a>
-<span class="sourceLineNo">181</span>    setSizeProgress(sizeProgress, heapSizeProgress);<a name="line.181"></a>
-<span class="sourceLineNo">182</span>  }<a name="line.182"></a>
-<span class="sourceLineNo">183</span><a name="line.183"></a>
-<span class="sourceLineNo">184</span>  void setSizeProgress(long dataSizeProgress, long heapSizeProgress) {<a name="line.184"></a>
-<span class="sourceLineNo">185</span>    progress.setDataSize(dataSizeProgress);<a name="line.185"></a>
-<span class="sourceLineNo">186</span>    progress.setHeapSize(heapSizeProgress);<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>  void setBatchProgress(int batchProgress) {<a name="line.189"></a>
-<span class="sourceLineNo">190</span>    progress.setBatch(batchProgress);<a name="line.190"></a>
-<span class="sourceLineNo">191</span>  }<a name="line.191"></a>
-<span class="sourceLineNo">192</span><a name="line.192"></a>
-<span class="sourceLineNo">193</span>  /**<a name="line.193"></a>
-<span class="sourceLineNo">194</span>   * Clear away any progress that has been made so far. All progress fields are reset to initial<a name="line.194"></a>
-<span class="sourceLineNo">195</span>   * values<a name="line.195"></a>
-<span class="sourceLineNo">196</span>   */<a name="line.196"></a>
-<span class="sourceLineNo">197</span>  void clearProgress() {<a name="line.197"></a>
-<span class="sourceLineNo">198</span>    progress.setFields(0, 0, 0);<a name="line.198"></a>
-<span class="sourceLineNo">199</span>  }<a name="line.199"></a>
-<span class="sourceLineNo">200</span><a name="line.200"></a>
-<span class="sourceLineNo">201</span>  /**<a name="line.201"></a>
-<span class="sourceLineNo">202</span>   * Note that this is not a typical setter. This setter returns the {@link NextState} that was<a name="line.202"></a>
-<span class="sourceLineNo">203</span>   * passed in so that methods can be invoked against the new state. Furthermore, this pattern<a name="line.203"></a>
-<span class="sourceLineNo">204</span>   * allows the {@link NoLimitScannerContext} to cleanly override this setter and simply return the<a name="line.204"></a>
-<span class="sourceLineNo">205</span>   * new state, thus preserving the immutability of {@link NoLimitScannerContext}<a name="line.205"></a>
-<span class="sourceLineNo">206</span>   * @param state<a name="line.206"></a>
-<span class="sourceLineNo">207</span>   * @return The state that was passed in.<a name="line.207"></a>
-<span class="sourceLineNo">208</span>   */<a name="line.208"></a>
-<span class="sourceLineNo">209</span>  NextState setScannerState(NextState state) {<a name="line.209"></a>
-<span class="sourceLineNo">210</span>    if (!NextState.isValidState(state)) {<a name="line.210"></a>
-<span class="sourceLineNo">211</span>      throw new IllegalArgumentException("Cannot set to invalid state: " + state);<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>    this.scannerState = state;<a name="line.214"></a>
-<span class="sourceLineNo">215</span>    return state;<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>  /**<a name="line.218"></a>
-<span class="sourceLineNo">219</span>   * @return true when we have more cells for the current row. This usually because we have reached<a name="line.219"></a>
-<span class="sourceLineNo">220</span>   *         a limit in the middle of a row<a name="line.220"></a>
-<span class="sourceLineNo">221</span>   */<a name="line.221"></a>
-<span class="sourceLineNo">222</span>  boolean mayHaveMoreCellsInRow() {<a name="line.222"></a>
-<span class="sourceLineNo">223</span>    return scannerState == NextState.SIZE_LIMIT_REACHED_MID_ROW ||<a name="line.223"></a>
-<span class="sourceLineNo">224</span>        scannerState == NextState.TIME_LIMIT_REACHED_MID_ROW ||<a name="line.224"></a>
-<span class="sourceLineNo">225</span>        scannerState == NextState.BATCH_LIMIT_REACHED;<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>  /**<a name="line.228"></a>
-<span class="sourceLineNo">229</span>   * @param checkerScope<a name="line.229"></a>
-<span class="sourceLineNo">230</span>   * @return true if the batch limit can be enforced in the checker's scope<a name="line.230"></a>
-<span class="sourceLineNo">231</span>   */<a name="line.231"></a>
-<span class="sourceLineNo">232</span>  boolean hasBatchLimit(LimitScope checkerScope) {<a name="line.232"></a>
-<span class="sourceLineNo">233</span>    return limits.canEnforceBatchLimitFromScope(checkerScope) &amp;&amp; limits.getBatch() &gt; 0;<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>   * @param checkerScope<a name="line.237"></a>
-<span class="sourceLineNo">238</span>   * @return true if the size limit can be enforced in the checker's scope<a name="line.238"></a>
-<span class="sourceLineNo">239</span>   */<a name="line.239"></a>
-<span class="sourceLineNo">240</span>  boolean hasSizeLimit(LimitScope checkerScope) {<a name="line.240"></a>
-<span class="sourceLineNo">241</span>    return limits.canEnforceSizeLimitFromScope(checkerScope)<a name="line.241"></a>
-<span class="sourceLineNo">242</span>        &amp;&amp; (limits.getDataSize() &gt; 0 || limits.getHeapSize() &gt; 0);<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>  /**<a name="line.245"></a>
-<span class="sourceLineNo">246</span>   * @param checkerScope<a name="line.246"></a>
-<span class="sourceLineNo">247</span>   * @return true if the time limit can be enforced in the checker's scope<a name="line.247"></a>
-<span class="sourceLineNo">248</span>   */<a name="line.248"></a>
-<span class="sourceLineNo">249</span>  boolean hasTimeLimit(LimitScope checkerScope) {<a name="line.249"></a>
-<span class="sourceLineNo">250</span>    return limits.canEnforceTimeLimitFromScope(checkerScope) &amp;&amp; limits.getTime() &gt; 0;<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>   * @param checkerScope<a name="line.254"></a>
-<span class="sourceLineNo">255</span>   * @return true if any limit can be enforced within the checker's scope<a name="line.255"></a>
-<span class="sourceLineNo">256</span>   */<a name="line.256"></a>
-<span class="sourceLineNo">257</span>  boolean hasAnyLimit(LimitScope checkerScope) {<a name="line.257"></a>
-<span class="sourceLineNo">258</span>    return hasBatchLimit(checkerScope) || hasSizeLimit(checkerScope) || hasTimeLimit(checkerScope);<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>  /**<a name="line.261"></a>
-<span class="sourceLineNo">262</span>   * @param scope The scope in which the size limit will be enforced<a name="line.262"></a>
+<span class="sourceLineNo">113</span>  ScannerContext(boolean keepProgress, LimitFields limitsToCopy, boolean trackMetrics) {<a name="line.113"></a>
+<span class="sourceLineNo">114</span>    this.limits = new LimitFields();<a name="line.114"></a>
+<span class="sourceLineNo">115</span>    if (limitsToCopy != null) {<a name="line.115"></a>
+<span class="sourceLineNo">116</span>      this.limits.copy(limitsToCopy);<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>    // Progress fields are initialized to 0<a name="line.119"></a>
+<span class="sourceLineNo">120</span>    progress = new ProgressFields(0, 0, 0);<a name="line.120"></a>
+<span class="sourceLineNo">121</span><a name="line.121"></a>
+<span class="sourceLineNo">122</span>    this.keepProgress = keepProgress;<a name="line.122"></a>
+<span class="sourceLineNo">123</span>    this.scannerState = DEFAULT_STATE;<a name="line.123"></a>
+<span class="sourceLineNo">124</span>    this.metrics = trackMetrics ? new ServerSideScanMetrics() : null;<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>  boolean isTrackingMetrics() {<a name="line.127"></a>
+<span class="sourceLineNo">128</span>    return this.metrics != null;<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>   * Get the metrics instance. Should only be called after a call to {@link #isTrackingMetrics()}<a name="line.132"></a>
+<span class="sourceLineNo">133</span>   * has been made to confirm that metrics are indeed being tracked.<a name="line.133"></a>
+<span class="sourceLineNo">134</span>   * @return {@link ServerSideScanMetrics} instance that is tracking metrics for this scan<a name="line.134"></a>
+<span class="sourceLineNo">135</span>   */<a name="line.135"></a>
+<span class="sourceLineNo">136</span>  ServerSideScanMetrics getMetrics() {<a name="line.136"></a>
+<span class="sourceLineNo">137</span>    assert isTrackingMetrics();<a name="line.137"></a>
+<span class="sourceLineNo">138</span>    return this.metrics;<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>   * @return true if the progress tracked so far in this instance will be considered during an<a name="line.142"></a>
+<span class="sourceLineNo">143</span>   *         invocation of {@link InternalScanner#next(java.util.List)} or<a name="line.143"></a>
+<span class="sourceLineNo">144</span>   *         {@link RegionScanner#next(java.util.List)}. false when the progress tracked so far<a name="line.144"></a>
+<span class="sourceLineNo">145</span>   *         should not be considered and should instead be wiped away via {@link #clearProgress()}<a name="line.145"></a>
+<span class="sourceLineNo">146</span>   */<a name="line.146"></a>
+<span class="sourceLineNo">147</span>  boolean getKeepProgress() {<a name="line.147"></a>
+<span class="sourceLineNo">148</span>    return keepProgress;<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>  void setKeepProgress(boolean keepProgress) {<a name="line.151"></a>
+<span class="sourceLineNo">152</span>    this.keepProgress = keepProgress;<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>   * Progress towards the batch limit has been made. Increment internal tracking of batch progress<a name="line.156"></a>
+<span class="sourceLineNo">157</span>   */<a name="line.157"></a>
+<span class="sourceLineNo">158</span>  void incrementBatchProgress(int batch) {<a name="line.158"></a>
+<span class="sourceLineNo">159</span>    int currentBatch = progress.getBatch();<a name="line.159"></a>
+<span class="sourceLineNo">160</span>    progress.setBatch(currentBatch + batch);<a name="line.160"></a>
+<span class="sourceLineNo">161</span>  }<a name="line.161"></a>
+<span class="sourceLineNo">162</span><a name="line.162"></a>
+<span class="sourceLineNo">163</span>  /**<a name="line.163"></a>
+<span class="sourceLineNo">164</span>   * Progress towards the size limit has been made. Increment internal tracking of size progress<a name="line.164"></a>
+<span class="sourceLineNo">165</span>   */<a name="line.165"></a>
+<span class="sourceLineNo">166</span>  void incrementSizeProgress(long dataSize, long heapSize) {<a name="line.166"></a>
+<span class="sourceLineNo">167</span>    long curDataSize = progress.getDataSize();<a name="line.167"></a>
+<span class="sourceLineNo">168</span>    progress.setDataSize(curDataSize + dataSize);<a name="line.168"></a>
+<span class="sourceLineNo">169</span>    long curHeapSize = progress.getHeapSize();<a name="line.169"></a>
+<span class="sourceLineNo">170</span>    progress.setHeapSize(curHeapSize + heapSize);<a name="line.170"></a>
+<span class="sourceLineNo">171</span>  }<a name="line.171"></a>
+<span class="sourceLineNo">172</span><a name="line.172"></a>
+<span class="sourceLineNo">173</span>  int getBatchProgress() {<a name="line.173"></a>
+<span class="sourceLineNo">174</span>    return progress.getBatch();<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>  long getDataSizeProgress() {<a name="line.177"></a>
+<span class="sourceLineNo">178</span>    return progress.getDataSize();<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>  long getHeapSizeProgress() {<a name="line.181"></a>
+<span class="sourceLineNo">182</span>    return progress.getHeapSize();<a name="line.182"></a>
+<span class="sourceLineNo">183</span>  }<a name="line.183"></a>
+<span class="sourceLineNo">184</span><a name="line.184"></a>
+<span class="sourceLineNo">185</span>  void setProgress(int batchProgress, long sizeProgress, long heapSizeProgress) {<a name="line.185"></a>
+<span class="sourceLineNo">186</span>    setBatchProgress(batchProgress);<a name="line.186"></a>
+<span class="sourceLineNo">187</span>    setSizeProgress(sizeProgress, heapSizeProgress);<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>  void setSizeProgress(long dataSizeProgress, long heapSizeProgress) {<a name="line.190"></a>
+<span class="sourceLineNo">191</span>    progress.setDataSize(dataSizeProgress);<a name="line.191"></a>
+<span class="sourceLineNo">192</span>    progress.setHeapSize(heapSizeProgress);<a name="line.192"></a>
+<span class="sourceLineNo">193</span>  }<a name="line.193"></a>
+<span class="sourceLineNo">194</span><a name="line.194"></a>
+<span class="sourceLineNo">195</span>  void setBatchProgress(int batchProgress) {<a name="line.195"></a>
+<span class="sourceLineNo">196</span>    progress.setBatch(batchProgress);<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>   * Clear away any progress that has been made so far. All progress fields are reset to initial<a name="line.200"></a>
+<span class="sourceLineNo">201</span>   * values<a name="line.201"></a>
+<span class="sourceLineNo">202</span>   */<a name="line.202"></a>
+<span class="sourceLineNo">203</span>  void clearProgress() {<a name="line.203"></a>
+<span class="sourceLineNo">204</span>    progress.setFields(0, 0, 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>  /**<a name="line.207"></a>
+<span class="sourceLineNo">208</span>   * Note that this is not a typical setter. This setter returns the {@link NextState} that was<a name="line.208"></a>
+<span class="sourceLineNo">209</span>   * passed in so that methods can be invoked against the new state. Furthermore, this pattern<a name="line.209"></a>
+<span class="sourceLineNo">210</span>   * allows the {@link NoLimitScannerContext} to cleanly override this setter and simply return the<a name="line.210"></a>
+<span class="sourceLineNo">211</span>   * new state, thus preserving the immutability of {@link NoLimitScannerContext}<a name="line.211"></a>
+<span class="sourceLineNo">212</span>   * @param state<a name="line.212"></a>
+<span class="sourceLineNo">213</span>   * @return The state that was passed in.<a name="line.213"></a>
+<span class="sourceLineNo">214</span>   */<a name="line.214"></a>
+<span class="sourceLineNo">215</span>  NextState setScannerState(NextState state) {<a name="line.215"></a>
+<span class="sourceLineNo">216</span>    if (!NextState.isValidState(state)) {<a name="line.216"></a>
+<span class="sourceLineNo">217</span>      throw new IllegalArgumentException("Cannot set to invalid state: " + state);<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>    this.scannerState = state;<a name="line.220"></a>
+<span class="sourceLineNo">221</span>    return state;<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>  /**<a name="line.224"></a>
+<span class="sourceLineNo">225</span>   * @return true when we have more cells for the current row. This usually because we have reached<a name="line.225"></a>
+<span class="sourceLineNo">226</span>   *         a limit in the middle of a row<a name="line.226"></a>
+<span class="sourceLineNo">227</span>   */<a name="line.227"></a>
+<span class="sourceLineNo">228</span>  boolean mayHaveMoreCellsInRow() {<a name="line.228"></a>
+<span class="sourceLineNo">229</span>    return scannerState == NextState.SIZE_LIMIT_REACHED_MID_ROW ||<a name="line.229"></a>
+<span class="sourceLineNo">230</span>        scannerState == NextState.TIME_LIMIT_REACHED_MID_ROW ||<a name="line.230"></a>
+<span class="sourceLineNo">231</span>        scannerState == NextState.BATCH_LIMIT_REACHED;<a name="line.231"></a>
+<span class="sourceLineNo">232</span>  }<a name="line.232"></a>
+<span class="sourceLineNo">233</span><a name="line.233"></a>
+<span class="sourceLineNo">234</span>  /**<a name="line.234"></a>
+<span class="sourceLineNo">235</span>   * @param checkerScope<a name="line.235"></a>
+<span class="sourceLineNo">236</span>   * @return true if the batch limit can be enforced in the checker's scope<a name="line.236"></a>
+<span class="sourceLineNo">237</span>   */<a name="line.237"></a>
+<span class="sourceLineNo">238</span>  boolean hasBatchLimit(LimitScope checkerScope) {<a name="line.238"></a>
+<span class="sourceLineNo">239</span>    return limits.canEnforceBatchLimitFromScope(checkerScope) &amp;&amp; limits.getBatch() &gt; 0;<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>   * @param checkerScope<a name="line.243"></a>
+<span class="sourceLineNo">244</span>   * @return true if the size limit can be enforced in the checker's scope<a name="line.244"></a>
+<span class="sourceLineNo">245</span>   */<a name="line.245"></a>
+<span class="sourceLineNo">246</span>  boolean hasSizeLimit(LimitScope checkerScope) {<a name="line.246"></a>
+<span class="sourceLineNo">247</span>    return limits.canEnforceSizeLimitFromScope(checkerScope)<a name="line.247"></a>
+<span class="sourceLineNo">248</span>        &amp;&amp; (limits.getDataSize() &gt; 0 || limits.getHeapSize() &gt; 0);<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>
+<span class="sourceLineNo">252</span>   * @param checkerScope<a name="line.252"></a>
+<span class="sourceLineNo">253</span>   * @return true if the time limit can be enforced in the checker's scope<a name="line.253"></a>
+<span class="sourceLineNo">254</span>   */<a name="line.254"></a>
+<span class="sourceLineNo">255</span>  boolean hasTimeLimit(LimitScope checkerScope) {<a name="line.255"></a>
+<span class="sourceLineNo">256</span>    return limits.canEnforceTimeLimitFromScope(checkerScope) &amp;&amp;<a name="line.256"></a>
+<span class="sourceLineNo">257</span>      (limits.getTime() &gt; 0 || returnImmediately);<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>   * @param checkerScope<a name="line.261"></a>
+<span class="sourceLineNo">262</span>   * @return true if any limit can be enforced within the checker's scope<a name="line.262"></a>
 <span class="sourceLineNo">263</span>   */<a name="line.263"></a>
-<span class="sourceLineNo">264</span>  void setSizeLimitScope(LimitScope scope) {<a name="line.264"></a>
-<span class="sourceLineNo">265</span>    limits.setSizeScope(scope);<a name="line.265"></a>
+<span class="sourceLineNo">264</span>  boolean hasAnyLimit(LimitScope checkerScope) {<a name="line.264"></a>
+<span class="sourceLineNo">265</span>    return hasBatchLimit(checkerScope) || hasSizeLimit(checkerScope) || hasTimeLimit(checkerScope);<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>  /**<a name="line.268"></a>
-<span class="sourceLineNo">269</span>   * @param scope The scope in which the time limit will be enforced<a name="line.269"></a>
+<span class="sourceLineNo">269</span>   * @param scope The scope in which the size limit will be enforced<a name="line.269"></a>
 <span class="sourceLineNo">270</span>   */<a name="line.270"></a>
-<span class="sourceLineNo">271</span>  void setTimeLimitScope(LimitScope scope) {<a name="line.271"></a>
-<span class="sourceLineNo">272</span>    limits.setTimeScope(scope);<a name="line.272"></a>
+<span class="sourceLineNo">271</span>  void setSizeLimitScope(LimitScope scope) {<a name="line.271"></a>
+<span class="sourceLineNo">272</span>    limits.setSizeScope(scope);<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>  int getBatchLimit() {<a name="line.275"></a>
-<span class="sourceLineNo">276</span>    return limits.getBatch();<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>  long getDataSizeLimit() {<a name="line.279"></a>
-<span class="sourceLineNo">280</span>    return limits.getDataSize();<a name="line.280"></a>
-<span class="sourceLineNo">281</span>  }<a name="line.281"></a>
-<span class="sourceLineNo">282</span><a name="line.282"></a>
-<span class="sourceLineNo">283</span>  long getTimeLimit() {<a name="line.283"></a>
-<span class="sourceLineNo">284</span>    return limits.getTime();<a name="line.284"></a>
-<span class="sourceLineNo">285</span>  }<a name="line.285"></a>
-<span class="sourceLineNo">286</span><a name="line.286"></a>
-<span class="sourceLineNo">287</span>  /**<a name="line.287"></a>
-<span class="sourceLineNo">288</span>   * @param checkerScope The scope that the limit is being checked from<a name="line.288"></a>
-<span class="sourceLineNo">289</span>   * @return true when the limit is enforceable from the checker's scope and it has been reached<a name="line.289"></a>
-<span class="sourceLineNo">290</span>   */<a name="line.290"></a>
-<span class="sourceLineNo">291</span>  boolean checkBatchLimit(LimitScope checkerScope) {<a name="line.291"></a>
-<span class="sourceLineNo">292</span>    return hasBatchLimit(checkerScope) &amp;&amp; progress.getBatch() &gt;= limits.getBatch();<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>  /**<a name="line.295"></a>
-<span class="sourceLineNo">296</span>   * @param checkerScope The scope that the limit is being checked from<a name="line.296"></a>
-<span class="sourceLineNo">297</span>   * @return true when the limit is enforceable from the checker's scope and it has been reached<a name="line.297"></a>
-<span class="sourceLineNo">298</span>   */<a name="line.298"></a>
-<span class="sourceLineNo">299</span>  boolean checkSizeLimit(LimitScope checkerScope) {<a name="line.299"></a>
-<span class="sourceLineNo">300</span>    return hasSizeLimit(checkerScope) &amp;&amp; (progress.getDataSize() &gt;= limits.getDataSize()<a name="line.300"></a>
-<span class="sourceLineNo">301</span>        || progress.getHeapSize() &gt;= limits.getHeapSize());<a name="line.301"></a>
-<span class="sourceLineNo">302</span>  }<a name="line.302"></a>
-<span class="sourceLineNo">303</span><a name="line.303"></a>
-<span class="sourceLineNo">304</span>  /**<a name="line.304"></a>
-<span class="sourceLineNo">305</span>   * @param checkerScope The scope that the limit is being checked from. The time limit is always<a name="line.305"></a>
-<span class="sourceLineNo">306</span>   *          checked against {@link System#currentTimeMillis()}<a name="line.306"></a>
-<span class="sourceLineNo">307</span>   * @return true when the limit is enforceable from the checker's scope and it has been reached<a name="line.307"></a>
-<span class="sourceLineNo">308</span>   */<a name="line.308"></a>
-<span class="sourceLineNo">309</span>  boolean checkTimeLimit(LimitScope checkerScope) {<a name="line.309"></a>
-<span class="sourceLineNo">310</span>    return hasTimeLimit(checkerScope) &amp;&amp; (System.currentTimeMillis() &gt;= limits.getTime());<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>   * @param checkerScope The scope that the limits are being checked from<a name="line.314"></a>
-<span class="sourceLineNo">315</span>   * @return true when some limit is enforceable from the checker's scope and it has been reached<a name="line.315"></a>
-<span class="sourceLineNo">316</span>   */<a name="line.316"></a>
-<span class="sourceLineNo">317</span>  boolean checkAnyLimitReached(LimitScope checkerScope) {<a name="line.317"></a>
-<span class="sourceLineNo">318</span>    return checkSizeLimit(checkerScope) || checkBatchLimit(checkerScope)<a name="line.318"></a>
-<span class="sourceLineNo">319</span>        || checkTimeLimit(checkerScope);<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>  Cell getLastPeekedCell() {<a name="line.322"></a>
-<span class="sourceLineNo">323</span>    return lastPeekedCell;<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>  void setLastPeekedCell(Cell lastPeekedCell) {<a name="line.326"></a>
-<span class="sourceLineNo">327</span>    this.lastPeekedCell = lastPeekedCell;<a name="line.327"></a>
+<span class="sourceLineNo">275</span>  /**<a name="line.275"></a>
+<span class="sourceLineNo">276</span>   * @param scope The scope in which the time limit will be enforced<a name="line.276"></a>
+<span class="sourceLineNo">277</span>   */<a name="line.277"></a>
+<span class="sourceLineNo">278</span>  void setTimeLimitScope(LimitScope scope) {<a name="line.278"></a>
+<span class="sourceLineNo">279</span>    limits.setTimeScope(scope);<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>  int getBatchLimit() {<a name="line.282"></a>
+<span class="sourceLineNo">283</span>    return limits.getBatch();<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>  long getDataSizeLimit() {<a name="line.286"></a>
+<span class="sourceLineNo">287</span>    return limits.getDataSize();<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>  long getTimeLimit() {<a name="line.290"></a>
+<span class="sourceLineNo">291</span>    return limits.getTime();<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>   * @param checkerScope The scope that the limit is being checked from<a name="line.295"></a>
+<span class="sourceLineNo">296</span>   * @return true when the limit is enforceable from the checker's scope and it has been reached<a name="line.296"></a>
+<span class="sourceLineNo">297</span>   */<a name="line.297"></a>
+<span class="sourceLineNo">298</span>  boolean checkBatchLimit(LimitScope checkerScope) {<a name="line.298"></a>
+<span class="sourceLineNo">299</span>    return hasBatchLimit(checkerScope) &amp;&amp; progress.getBatch() &gt;= limits.getBatch();<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 checkerScope The scope that the limit is being checked from<a name="line.303"></a>
+<span class="sourceLineNo">304</span>   * @return true when the limit is enforceable from the checker's scope and it has been reached<a name="line.304"></a>
+<span class="sourceLineNo">305</span>   */<a name="line.305"></a>
+<span class="sourceLineNo">306</span>  boolean checkSizeLimit(LimitScope checkerScope) {<a name="line.306"></a>
+<span class="sourceLineNo">307</span>    return hasSizeLimit(checkerScope) &amp;&amp; (progress.getDataSize() &gt;= limits.getDataSize()<a name="line.307"></a>
+<span class="sourceLineNo">308</span>        || progress.getHeapSize() &gt;= limits.getHeapSize());<a name="line.308"></a>
+<span class="sourceLineNo">309</span>  }<a name="line.309"></a>
+<span class="sourceLineNo">310</span><a name="line.310"></a>
+<span class="sourceLineNo">311</span>  /**<a name="line.311"></a>
+<span class="sourceLineNo">312</span>   * @param checkerScope The scope that the limit is being checked from. The time limit is always<a name="line.312"></a>
+<span class="sourceLineNo">313</span>   *          checked against {@link System#currentTimeMillis()}<a name="line.313"></a>
+<span class="sourceLineNo">314</span>   * @return true when the limit is enforceable from the checker's scope and it has been reached<a name="line.314"></a>
+<span class="sourceLineNo">315</span>   */<a name="line.315"></a>
+<span class="sourceLineNo">316</span>  boolean checkTimeLimit(LimitScope checkerScope) {<a name="line.316"></a>
+<span class="sourceLineNo">317</span>    return hasTimeLimit(checkerScope) &amp;&amp;<a name="line.317"></a>
+<span class="sourceLineNo">318</span>      (returnImmediately || System.currentTimeMillis() &gt;= limits.getTime());<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>   * @param checkerScope The scope that the limits are being checked from<a name="line.322"></a>
+<span class="sourceLineNo">323</span>   * @return true when some limit is enforceable from the checker's scope and it has been reached<a name="line.323"></a>
+<span class="sourceLineNo">324</span>   */<a name="line.324"></a>
+<span class="sourceLineNo">325</span>  boolean checkAnyLimitReached(LimitScope checkerScope) {<a name="line.325"></a>
+<span class="sourceLineNo">326</span>    return checkSizeLimit(checkerScope) || checkBatchLimit(checkerScope)<a name="line.326"></a>
+<span class="sourceLineNo">327</span>        || checkTimeLimit(checkerScope);<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>  @Override<a name="line.330"></a>
-<span class="sourceLineNo">331</span>  public String toString() {<a name="line.331"></a>
-<span class="sourceLineNo">332</span>    StringBuilder sb = new StringBuilder();<a name="line.332"></a>
-<span class="sourceLineNo">333</span>    sb.append("{");<a name="line.333"></a>
-<span class="sourceLineNo">334</span><a name="line.334"></a>
-<span class="sourceLineNo">335</span>    sb.append("limits:");<a name="line.335"></a>
-<span class="sourceLineNo">336</span>    sb.append(limits);<a name="line.336"></a>
+<span class="sourceLineNo">330</span>  Cell getLastPeekedCell() {<a name="line.330"></a>
+<span class="sourceLineNo">331</span>    return lastPeekedCell;<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>  void setLastPeekedCell(Cell lastPeekedCell) {<a name="line.334"></a>
+<span class="sourceLineNo">335</span>    this.lastPeekedCell = lastPeekedCell;<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>    sb.append(", progress:");<a name="line.338"></a>
-<span class="sourceLineNo">339</span>    sb.append(progress);<a name="line.339"></a>
-<span class="sourceLineNo">340</span><a name="line.340"></a>
-<span class="sourceLineNo">341</span>    sb.append(", keepProgress:");<a name="line.341"></a>
-<span class="sourceLineNo">342</span>    sb.append(keepProgress);<a name="line.342"></a>
-<span class="sourceLineNo">343</span><a name="line.343"></a>
-<span class="sourceLineNo">344</span>    sb.append(", state:");<a name="line.344"></a>
-<span class="sourceLineNo">345</span>    sb.append(scannerState);<a name="line.345"></a>
+<span class="sourceLineNo">338</span>  void returnImmediately() {<a name="line.338"></a>
+<span class="sourceLineNo">339</span>    this.returnImmediately = true;<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>  @Override<a name="line.342"></a>
+<span class="sourceLineNo">343</span>  public String toString() {<a name="line.343"></a>
+<span class="sourceLineNo">344</span>    StringBuilder sb = new StringBuilder();<a name="line.344"></a>
+<span class="sourceLineNo">345</span>    sb.append("{");<a name="line.345"></a>
 <span class="sourceLineNo">346</span><a name="line.346"></a>
-<span class="sourceLineNo">347</span>    sb.append("}");<a name="line.347"></a>
-<span class="sourceLineNo">348</span>    return sb.toString();<a name="line.348"></a>
-<span class="sourceLineNo">349</span>  }<a name="line.349"></a>
-<span class="sourceLineNo">350</span><a name="line.350"></a>
-<span class="sourceLineNo">351</span>  public static Builder newBuilder() {<a name="line.351"></a>
-<span class="sourceLineNo">352</span>    return new Builder();<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 static Builder newBuilder(boolean keepProgress) {<a name="line.355"></a>
-<span class="sourceLineNo">356</span>    return new Builder(keepProgress);<a name="line.356"></a>
-<span class="sourceLineNo">357</span>  }<a name="line.357"></a>
+<span class="sourceLineNo">347</span>    sb.append("limits:");<a name="line.347"></a>
+<span class="sourceLineNo">348</span>    sb.append(limits);<a name="line.348"></a>
+<span class="sourceLineNo">349</span><a name="line.349"></a>
+<span class="sourceLineNo">350</span>    sb.append(", progress:");<a name="line.350"></a>
+<span class="sourceLineNo">351</span>    sb.append(progress);<a name="line.351"></a>
+<span class="sourceLineNo">352</span><a name="line.352"></a>
+<span class="sourceLineNo">353</span>    sb.append(", keepProgress:");<a name="line.353"></a>
+<span class="sourceLineNo">354</span>    sb.append(keepProgress);<a name="line.354"></a>
+<span class="sourceLineNo">355</span><a name="line.355"></a>
+<span class="sourceLineNo">356</span>    sb.append(", state:");<a name="line.356"></a>
+<span class="sourceLineNo">357</span>    sb.append(scannerState);<a name="line.357"></a>
 <span class="sourceLineNo">358</span><a name="line.358"></a>
-<span class="sourceLineNo">359</span>  public static final class Builder {<a name="line.359"></a>
-<span class="sourceLineNo">360</span>    boolean keepProgress = DEFAULT_KEEP_PROGRESS;<a name="line.360"></a>
-<span class="sourceLineNo">361</span>    boolean trackMetrics = false;<a name="line.361"></a>
-<span class="sourceLineNo">362</span>    LimitFields limits = new LimitFields();<a name="line.362"></a>
-<span class="sourceLineNo">363</span><a name="line.363"></a>
-<span class="sourceLineNo">364</span>    private Builder() {<a name="line.364"></a>
-<span class="sourceLineNo">365</span>    }<a name="line.365"></a>
+<span class="sourceLineNo">359</span>    sb.append("}");<a name="line.359"></a>
+<span class="sourceLineNo">360</span>    return sb.toString();<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 static Builder newBuilder() {<a name="line.363"></a>
+<span class="sourceLineNo">364</span>    return new Builder();<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>    private Builder(boolean keepProgress) {<a name="line.367"></a>
-<span class="sourceLineNo">368</span>      this.keepProgress = keepProgress;<a name="line.368"></a>
-<span class="sourceLineNo">369</span>    }<a name="line.369"></a>
+<span class="sourceLineNo">367</span>  public static Builder newBuilder(boolean keepProgress) {<a name="line.367"></a>
+<span class="sourceLineNo">368</span>    return new Builder(keepProgress);<a name="line.368"></a>
+<span class="sourceLineNo">369</span>  }<a name="line.369"></a>
 <span class="sourceLineNo">370</span><a name="line.370"></a>
-<span class="sourceLineNo">371</span>    public Builder setKeepProgress(boolean keepProgress) {<a name="line.371"></a>
-<span class="sourceLineNo">372</span>      this.keepProgress = keepProgress;<a name="line.372"></a>
-<span class="sourceLineNo">373</span>      return this;<a name="line.373"></a>
-<span class="sourceLineNo">374</span>    }<a name="line.374"></a>
+<span class="sourceLineNo">371</span>  public static final class Builder {<a name="line.371"></a>
+<span class="sourceLineNo">372</span>    boolean keepProgress = DEFAULT_KEEP_PROGRESS;<a name="line.372"></a>
+<span class="sourceLineNo">373</span>    boolean trackMetrics = false;<a name="line.373"></a>
+<span class="sourceLineNo">374</span>    LimitFields limits = new LimitFields();<a name="line.374"></a>
 <span class="sourceLineNo">375</span><a name="line.375"></a>
-<span class="sourceLineNo">376</span>    public Builder setTrackMetrics(boolean trackMetrics) {<a name="line.376"></a>
-<span class="sourceLineNo">377</span>      this.trackMetrics = trackMetrics;<a name="line.377"></a>
-<span class="sourceLineNo">378</span>      return this;<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 Builder setSizeLimit(LimitScope sizeScope, long dataSizeLimit, long heapSizeLimit) {<a name="line.381"></a>
-<span class="sourceLineNo">382</span>      limits.setDataSize(dataSizeLimit);<a name="line.382"></a>
-<span class="sourceLineNo">383</span>      limits.setHeapSize(heapSizeLimit);<a name="line.383"></a>
-<span class="sourceLineNo">384</span>      limits.setSizeScope(sizeScope);<a name="line.384"></a>
+<span class="sourceLineNo">376</span>    private Builder() {<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>    private Builder(boolean keepProgress) {<a name="line.379"></a>
+<span class="sourceLineNo">380</span>      this.keepProgress = keepProgress;<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>    public Builder setKeepProgress(boolean keepProgress) {<a name="line.383"></a>
+<span class="sourceLineNo">384</span>      this.keepProgress = keepProgress;<a name="line.384"></a>
 <span class="sourceLineNo">385</span>      return this;<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 Builder setTimeLimit(LimitScope timeScope, long timeLimit) {<a name="line.388"></a>
-<span class="sourceLineNo">389</span>      limits.setTime(timeLimit);<a name="line.389"></a>
-<span class="sourceLineNo">390</span>      limits.setTimeScope(timeScope);<a name="line.390"></a>
-<span class="sourceLineNo">391</span>      return this;<a name="line.391"></a>
-<span class="sourceLineNo">392</span>    }<a name="line.392"></a>
-<span class="sourceLineNo">393</span><a name="line.393"></a>
-<span class="sourceLineNo">394</span>    public Builder setBatchLimit(int batchLimit) {<a name="line.394"></a>
-<span class="sourceLineNo">395</span>      limits.setBatch(batchLimit);<a name="line.395"></a>
-<span class="sourceLineNo">396</span>      return this;<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>    public ScannerContext build() {<a name="line.399"></a>
-<span class="sourceLineNo">400</span>      return new ScannerContext(keepProgress, limits, trackMetrics);<a name="line.400"></a>
-<span class="sourceLineNo">401</span>    }<a name="line.401"></a>
-<span class="sourceLineNo">402</span>  }<a name="line.402"></a>
-<span class="sourceLineNo">403</span><a name="line.403"></a>
-<span class="sourceLineNo">404</span>  /**<a name="line.404"></a>
-<span class="sourceLineNo">405</span>   * The possible states a scanner may be in following a call to {@link InternalScanner#next(List)}<a name="line.405"></a>
-<span class="sourceLineNo">406</span>   */<a name="line.406"></a>
-<span class="sourceLineNo">407</span>  public enum NextState {<a name="line.407"></a>
-<span class="sourceLineNo">408</span>    MORE_VALUES(true, false),<a name="line.408"></a>
-<span class="sourceLineNo">409</span>    NO_MORE_VALUES(false, false),<a name="line.409"></a>
-<span class="sourceLineNo">410</span>    SIZE_LIMIT_REACHED(true, true),<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>     * Special case of size limit reached to indicate that the size limit was reached in the middle<a name="line.413"></a>
-<span class="sourceLineNo">414</span>     * of a row and thus a partial results was formed<a name="line.414"></a>
-<span class="sourceLineNo">415</span>     */<a name="line.415"></a>
-<span class="sourceLineNo">416</span>    SIZE_LIMIT_REACHED_MID_ROW(true, true),<a name="line.416"></a>
-<span class="sourceLineNo">417</span>    TIME_LIMIT_REACHED(true, true),<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>     * Special case of time limit reached to indicate that the time limit was reached in the middle<a name="line.420"></a>
-<span class="sourceLineNo">421</span>     * of a row and thus a partial results was formed<a name="line.421"></a>
-<span class="sourceLineNo">422</span>     */<a name="line.422"></a>
-<span class="sourceLineNo">423</span>    TIME_LIMIT_REACHED_MID_ROW(true, true),<a name="line.423"></a>
-<span class="sourceLineNo">424</span>    BATCH_LIMIT_REACHED(true, true);<a name="line.424"></a>
-<span class="sourceLineNo">425</span><a name="line.425"></a>
-<span class="sourceLineNo">426</span>    private final boolean moreValues;<a name="line.426"></a>
-<span class="sourceLineNo">427</span>    private final boolean limitReached;<a name="line.427"></a>
-<span class="sourceLineNo">428</span><a name="line.428"></a>
-<span class="sourceLineNo">429</span>    private NextState(boolean moreValues, boolean limitReached) {<a name="line.429"></a>
-<span class="sourceLineNo">430</span>      this.moreValues = moreValues;<a name="line.430"></a>
-<span class="sourceLineNo">431</span>      this.limitReached = limitReached;<a name="line.431"></a>
-<span class="sourceLineNo">432</span>    }<a name="line.432"></a>
-<span class="sourceLineNo">433</span><a name="line.433"></a>
-<span class="sourceLineNo">434</span>    /**<a name="line.434"></a>
-<span class="sourceLineNo">435</span>     * @return true when the state indicates that more values may follow those that have been<a name="line.435"></a>
-<span class="sourceLineNo">436</span>     *         returned<a name="line.436"></a>
-<span class="sourceLineNo">437</span>     */<a name="line.437"></a>
-<span class="sourceLineNo">438</span>    public boolean hasMoreValues() {<a name="line.438"></a>
-<span class="sourceLineNo">439</span>      return this.moreValues;<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>     * @return true when the state indicates that a limit has been reached and scan should stop<a name="line.443"></a>
-<span class="sourceLineNo">444</span>     */<a name="line.444"></a>
-<span class="sourceLineNo">445</span>    public boolean limitReached() {<a name="line.445"></a>
-<span class="sourceLineNo">446</span>      return this.limitReached;<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>    public static boolean isValidState(NextState state) {<a name="line.449"></a>
-<span class="sourceLineNo">450</span>      return state != null;<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>    public static boolean hasMoreValues(NextState state) {<a name="line.453"></a>
-<span class="sourceLineNo">454</span>      return isValidState(state) &amp;&amp; state.hasMoreValues();<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>  /**<a name="line.458"></a>
-<span class="sourceLineNo">459</span>   * The various scopes where a limit can be enforced. Used to differentiate when a limit should be<a name="line.459"></a>
-<span class="sourceLineNo">460</span>   * enforced or not.<a name="line.460"></a>
-<span class="sourceLineNo">461</span>   */<a name="line.461"></a>
-<span class="sourceLineNo">462</span>  public enum LimitScope {<a name="line.462"></a>
-<span class="sourceLineNo">463</span>    /**<a name="line.463"></a>
-<span class="sourceLineNo">464</span>     * Enforcing a limit between rows means that the limit will not be considered until all the<a name="line.464"></a>
-<span class="sourceLineNo">465</span>     * cells for a particular row have been retrieved<a name="line.465"></a>
-<span class="sourceLineNo">466</span>     */<a name="line.466"></a>
-<span class="sourceLineNo">467</span>    BETWEEN_ROWS(0),<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>     * Enforcing a limit between cells means that the limit will be considered after each full cell<a name="line.470"></a>
-<span class="sourceLineNo">471</span>     * has been retrieved<a name="line.471"></a>
-<span class="sourceLineNo">472</span>     */<a name="line.472"></a>
-<span class="sourceLineNo">473</span>    BETWEEN_CELLS(1);<a name="line.473"></a>
-<span class="sourceLineNo">474</span><a name="line.474"></a>
+<span class="sourceLineNo">388</span>    public Builder setTrackMetrics(boolean trackMetrics) {<a name="line.388"></a>
+<span class="sourceLineNo">389</span>      this.trackMetrics = trackMetrics;<a name="line.389"></a>
+<span class="sourceLineNo">390</span>      return this;<a name="line.390"></a>
+<span class="sourceLineNo">391</span>    }<a name="line.391"></a>
+<span class="sourceLineNo">392</span><a name="line.392"></a>
+<span class="sourceLineNo">393</span>    public Builder setSizeLimit(LimitScope sizeScope, long dataSizeLimit, long heapSizeLimit) {<a name="line.393"></a>
+<span class="sourceLineNo">394</span>      limits.setDataSize(dataSizeLimit);<a name="line.394"></a>
+<span class="sourceLineNo">395</span>      limits.setHeapSize(heapSizeLimit);<a name="line.395"></a>
+<span class="sourceLineNo">396</span>      limits.setSizeScope(sizeScope);<a name="line.396"></a>
+<span class="sourceLineNo">397</span>      return this;<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>    public Builder setTimeLimit(LimitScope timeScope, long timeLimit) {<a name="line.400"></a>
+<span class="sourceLineNo">401</span>      limits.setTime(timeLimit);<a name="line.401"></a>
+<span class="sourceLineNo">402</span>      limits.setTimeScope(timeScope);<a name="line.402"></a>
+<span class="sourceLineNo">403</span>      return this;<a name="line.403"></a>
+<span class="sourceLineNo">404</span>    }<a name="line.404"></a>
+<span class="sourceLineNo">405</span><a name="line.405"></a>
+<span class="sourceLineNo">406</span>    public Builder setBatchLimit(int batchLimit) {<a name="line.406"></a>
+<span class="sourceLineNo">407</span>      limits.setBatch(batchLimit);<a name="line.407"></a>
+<span class="sourceLineNo">408</span>      return this;<a name="line.408"></a>
+<span class="sourceLineNo">409</span>    }<a name="line.409"></a>
+<span class="sourceLineNo">410</span><a name="line.410"></a>
+<span class="sourceLineNo">411</span>    public ScannerContext build() {<a name="line.411"></a>
+<span class="sourceLineNo">412</span>      return new ScannerContext(keepProgress, limits, trackMetrics);<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><a name="line.415"></a>
+<span class="sourceLineNo">416</span>  /**<a name="line.416"></a>
+<span class="sourceLineNo">417</span>   * The possible states a scanner may be in following a call to {@link InternalScanner#next(List)}<a name="line.417"></a>
+<span class="sourceLineNo">418</span>   */<a name="line.418"></a>
+<span class="sourceLineNo">419</span>  public enum NextState {<a name="line.419"></a>
+<span class="sourceLineNo">420</span>    MORE_VALUES(true, false),<a name="line.420"></a>
+<span class="sourceLineNo">421</span>    NO_MORE_VALUES(false, false),<a name="line.421"></a>
+<span class="sourceLineNo">422</span>    SIZE_LIMIT_REACHED(true, true),<a name="line.422"></a>
+<span class="sourceLineNo">423</span><a name="line.423"></a>
+<span class="sourceLineNo">424</span>    /**<a name="line.424"></a>
+<span class="sourceLineNo">425</span>     * Special case of size limit reached to indicate that the size limit was reached in the middle<a name="line.425"></a>
+<span class="sourceLineNo">426</span>     * of a row and thus a partial results was formed<a name="line.426"></a>
+<span class="sourceLineNo">427</span>     */<a name="line.427"></a>
+<span class="sourceLineNo">428</span>    SIZE_LIMIT_REACHED_MID_ROW(true, true),<a name="line.428"></a>
+<span class="sourceLineNo">429</span>    TIME_LIMIT_REACHED(true, true),<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>     * Special case of time limit reached to indicate that the time limit was reached in the middle<a name="line.432"></a>
+<span class="sourceLineNo">433</span>     * of a row and thus a partial results was formed<a name="line.433"></a>
+<span class="sourceLineNo">434</span>     */<a name="line.434"></a>
+<span class="sourceLineNo">435</span>    TIME_LIMIT_REACHED_MID_ROW(true, true),<a name="line.435"></a>
+<span class="sourceLineNo">436</span>    BATCH_LIMIT_REACHED(true, true);<a name="line.436"></a>
+<span class="sourceLineNo">437</span><a name="line.437"></a>
+<span class="sourceLineNo">438</span>    private final boolean moreValues;<a name="line.438"></a>
+<span class="sourceLineNo">439</span>    private final boolean limitReached;<a name="line.439"></a>
+<span class="sourceLineNo">440</span><a name="line.440"></a>
+<span class="sourceLineNo">441</span>    private NextState(boolean moreValues, boolean limitReached) {<a name="line.441"></a>
+<span class="sourceLineNo">442</span>      this.moreValues = moreValues;<a name="line.442"></a>
+<span class="sourceLineNo">443</span>      this.limitReached = limitReached;<a name="line.443"></a>
+<span class="sourceLineNo">444</span>    }<a name="line.444"></a>
+<span class="sourceLineNo">445</span><a name="line.445"></a>
+<span class="sourceLineNo">446</span>    /**<a name="line.446"></a>
+<span class="sourceLineNo">447</span>     * @return true when the state indicates that more values may follow those that have been<a name="line.447"></a>
+<span class="sourceLineNo">448</span>     *         returned<a name="line.448"></a>
+<span class="sourceLineNo">449</span>     */<a name="line.449"></a>
+<span class="sourceLineNo">450</span>    public boolean hasMoreValues() {<a name="line.450"></a>
+<span class="sourceLineNo">451</span>      return this.moreValues;<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>     * @return true when the state indicates that a limit has been reached and scan should stop<a name="line.455"></a>
+<span class="sourceLineNo">456</span>     */<a name="line.456"></a>
+<span class="sourceLineNo">457</span>    public boolean limitReached() {<a name="line.457"></a>
+<span class="sourceLineNo">458</span>      return this.limitReached;<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>    public static boolean isValidState(NextState state) {<a name="line.461"></a>
+<span class="sourceLineNo">462</span>      return state != 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>    public static boolean hasMoreValues(NextState state) {<a name="line.465"></a>
+<span class="sourceLineNo">466</span>      return isValidState(state) &amp;&amp; state.hasMoreValues();<a name="line.466"></a>
+<span class="sourceLineNo">467</span>    }<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>   * The various scopes where a limit can be enforced. Used to differentiate when a limit should be<a name="line.471"></a>
+<span class="sourceLineNo">472</span>   * enforced or not.<a name="line.472"></a>
+<span class="sourceLineNo">473</span>   */<a name="line.473"></a>
+<span class="sourceLineNo">474</span>  public enum LimitScope {<a name="line.474"></a>
 <span class="sourceLineNo">475</span>    /**<a name="line.475"></a>
-<span class="sourceLineNo">476</span>     * When enforcing a limit, we must check that the scope is appropriate for enforcement.<a name="line.476"></a>
-<span class="sourceLineNo">477</span>     * &lt;p&gt;<a name="line.477"></a>
-<span class="sourceLineNo">478</span>     * To communicate this concept, each scope has a depth. A limit will be enforced if the depth of<a name="line.478"></a>
-<span class="sourceLineNo">479</span>     * the checker's scope is less than or equal to the limit's scope. This means that when checking<a name="line.479"></a>
-<span class="sourceLineNo">480</span>     * limits, the checker must know their own scope (i.e. are they checking the limits between<a name="line.480"></a>
-<span class="sourceLineNo">481</span>     * rows, between cells, etc...)<a name="line.481"></a>
-<span class="sourceLineNo">482</span>     */<a name="line.482"></a>
-<span class="sourceLineNo">483</span>    final int depth;<a name="line.483"></a>
-<span class="sourceLineNo">484</span><a name="line.484"></a>
-<span class="sourceLineNo">485</span>    LimitScope(int depth) {<a name="line.485"></a>
-<span class="sourceLineNo">486</span>      this.depth = depth;<a name="line.486"></a>
-<span class="sourceLineNo">487</span>    }<a name="line.487"></a>
-<span class="sourceLineNo">488</span><a name="line.488"></a>
-<span class="sourceLineNo">489</span>    final int depth() {<a name="line.489"></a>
-<span class="sourceLineNo">490</span>      return depth;<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>     * @param checkerScope The scope in which the limit is being checked<a name="line.494"></a>
-<span class="sourceLineNo">495</span>     * @return true when the checker is in a scope that indicates the limit can be enforced. Limits<a name="line.495"></a>
-<span class="sourceLineNo">496</span>     *         can be enforced from "higher or equal" scopes (i.e. the checker's scope is at a<a name="line.496"></a>
-<span class="sourceLineNo">497</span>     *         lesser depth than the limit)<a name="line.497"></a>
-<span class="sourceLineNo">498</span>     */<a name="line.498"></a>
-<span class="sourceLineNo">499</span>    boolean canEnforceLimitFromScope(LimitScope checkerScope) {<a name="line.499"></a>
-<span class="sourceLineNo">500</span>      return checkerScope != null &amp;&amp; checkerScope.depth() &lt;= depth;<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><a name="line.503"></a>
-<span class="sourceLineNo">504</span>  /**<a name="line.504"></a>
-<span class="sourceLineNo">505</span>   * The different fields that can be used as limits in calls to<a name="line.505"></a>
-<span class="sourceLineNo">506</span>   * {@link InternalScanner#next(java.util.List)} and {@link RegionScanner#next(java.util.List)}<a name="line.506"></a>
-<span class="sourceLineNo">507</span>   */<a name="line.507"></a>
-<span class="sourceLineNo">508</span>  private static class LimitFields {<a name="line.508"></a>
-<span class="sourceLineNo">509</span>    /**<a name="line.509"></a>
-<span class="sourceLineNo">510</span>     * Default values of the limit fields. Defined such that if a field does NOT change from its<a name="line.510"></a>
-<span class="sourceLineNo">511</span>     * default, it will not be enforced<a name="line.511"></a>
-<span class="sourceLineNo">512</span>     */<a name="line.512"></a>
-<span class="sourceLineNo">513</span>    private static int DEFAULT_BATCH = -1;<a name="line.513"></a>
-<span class="sourceLineNo">514</span>    private static long DEFAULT_SIZE = -1L;<a name="line.514"></a>
-<span class="sourceLineNo">515</span>    private static long DEFAULT_TIME = -1L;<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>     * Default scope that is assigned to a limit if a scope is not specified.<a name="line.518"></a>
-<span class="sourceLineNo">519</span>     */<a name="line.519"></a>
-<span class="sourceLineNo">520</span>    private static final LimitScope DEFAULT_SCOPE = LimitScope.BETWEEN_ROWS;<a name="line.520"></a>
-<span class="sourceLineNo">521</span><a name="line.521"></a>
-<span class="sourceLineNo">522</span>    // The batch limit will always be enforced between cells, thus, there isn't a field to hold the<a name="line.522"></a>
-<span class="sourceLineNo">523</span>    // batch scope<a name="line.523"></a>
-<span class="sourceLineNo">524</span>    int batch = DEFAULT_BATCH;<a name="line.524"></a>
-<span class="sourceLineNo">525</span><a name="line.525"></a>
-<span class="sourceLineNo">526</span>    LimitScope sizeScope = DEFAULT_SCOPE;<a name="line.526"></a>
-<span class="sourceLineNo">527</span>    // The sum of cell data sizes(key + value). The Cell data might be in on heap or off heap area.<a name="line.527"></a>
-<span class="sourceLineNo">528</span>    long dataSize = DEFAULT_SIZE;<a name="line.528"></a>
-<span class="sourceLineNo">529</span>    // The sum of heap space occupied by all tracked cells. This includes Cell POJO's overhead as<a name="line.529"></a>
-<span class="sourceLineNo">530</span>    // such AND data cells of Cells which are in on heap area.<a name="line.530"></a>
-<span class="sourceLineNo">531</span>    long heapSize = DEFAULT_SIZE;<a name="line.531"></a>
-<span class="sourceLineNo">532</span><a name="line.532"></a>
-<span class="sourceLineNo">533</span>    LimitScope timeScope = DEFAULT_SCOPE;<a name="line.533"></a>
-<span class="sourceLineNo">534</span>    long time = DEFAULT_TIME;<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>     * Fields keep their default values.<a name="line.537"></a>
-<span class="sourceLineNo">538</span>     */<a name="line.538"></a>
-<span class="sourceLineNo">539</span>    LimitFields() {<a name="line.539"></a>
-<span class="sourceLineNo">540</span>    }<a name="line.540"></a>
-<span class="sourceLineNo">541</span><a name="line.541"></a>
-<span class="sourceLineNo">542</span>    LimitFields(int batch, LimitScope sizeScope, long size, long heapSize, LimitScope timeScope,<a name="line.542"></a>
-<span class="sourceLineNo">543</span>        long time) {<a name="line.543"></a>
-<span class="sourceLineNo">544</span>      setFields(batch, sizeScope, size, heapSize, timeScope, time);<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>    void copy(LimitFields limitsToCopy) {<a name="line.547"></a>
-<span class="sourceLineNo">548</span>      if (limitsToCopy != null) {<a name="line.548"></a>
-<span class="sourceLineNo">549</span>        setFields(limitsToCopy.getBatch(), limitsToCopy.getSizeScope(), limitsToCopy.getDataSize(),<a name="line.549"></a>
-<span class="sourceLineNo">550</span>            limitsToCopy.getHeapSize(), limitsToCopy.getTimeScope(), limitsToCopy.getTime());<a name="line.550"></a>
-<span class="sourceLineNo">551</span>      }<a name="line.551"></a>
+<span class="sourceLineNo">476</span>     * Enforcing a limit between rows means that the limit will not be considered until all the<a name="line.476"></a>
+<span class="sourceLineNo">477</span>     * cells for a particular row have been retrieved<a name="line.477"></a>
+<span class="sourceLineNo">478</span>     */<a name="line.478"></a>
+<span class="sourceLineNo">479</span>    BETWEEN_ROWS(0),<a name="line.479"></a>
+<span class="sourceLineNo">480</span><a name="line.480"></a>
+<span class="sourceLineNo">481</span>    /**<a name="line.481"></a>
+<span class="sourceLineNo">482</span>     * Enforcing a limit between cells means that the limit will be considered after each full cell<a name="line.482"></a>
+<span class="sourceLineNo">483</span>     * has been retrieved<a name="line.483"></a>
+<span class="sourceLineNo">484</span>     */<a name="line.484"></a>
+<span class="sourceLineNo">485</span>    BETWEEN_CELLS(1);<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>     * When enforcing a limit, we must check that the scope is appropriate for enforcement.<a name="line.488"></a>
+<span class="sourceLineNo">489</span>     * &lt;p&gt;<a name="line.489"></a>
+<span class="sourceLineNo">490</span>     * To communicate this concept, each scope has a depth. A limit will be enforced if the depth of<a name="line.490"></a>
+<span class="sourceLineNo">491</span>     * the checker's scope is less than or equal to the limit's scope. This means that when checking<a name="line.491"></a>
+<span class="sourceLineNo">492</span>     * limits, the checker must know their own scope (i.e. are they checking the limits between<a name="line.492"></a>
+<span class="sourceLineNo">493</span>     * rows, between cells, etc...)<a name="line.493"></a>
+<span class="sourceLineNo">494</span>     */<a name="line.494"></a>
+<span class="sourceLineNo">495</span>    final int depth;<a name="line.495"></a>
+<span class="sourceLineNo">496</span><a name="line.496"></a>
+<span class="sourceLineNo">497</span>    LimitScope(int depth) {<a name="line.497"></a>
+<span class="sourceLineNo">498</span>      this.depth = depth;<a name="line.498"></a>
+<span class="sourceLineNo">499</span>    }<a name="line.499"></a>
+<span class="sourceLineNo">500</span><a name="line.500"></a>
+<span class="sourceLineNo">501</span>    final int depth() {<a name="line.501"></a>
+<span class="sourceLineNo">502</span>      return depth;<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>    /**<a name="line.505"></a>
+<span class="sourceLineNo">506</span>     * @param checkerScope The scope in which the limit is being checked<a name="line.506"></a>
+<span class="sourceLineNo">507</span>     * @return true when the checker is in a scope that indicates the limit can be enforced. Limits<a name="line.507"></a>
+<span class="sourceLineNo">508</span>     *         can be enforced from "higher or equal" scopes (i.e. the checker's scope is at a<a name="line.508"></a>
+<span class="sourceLineNo">509</span>     *         lesser depth than the limit)<a name="line.509"></a>
+<span class="sourceLineNo">510</span>     */<a name="line.510"></a>
+<span class="sourceLineNo">511</span>    boolean canEnforceLimitFromScope(LimitScope checkerScope) {<a name="line.511"></a>
+<span class="sourceLineNo">512</span>      return checkerScope != null &amp;&amp; checkerScope.depth() &lt;= depth;<a name="line.512"></a>
+<span class="sourceLineNo">513</span>    }<a name="line.513"></a>
+<span class="sourceLineNo">514</span>  }<a name="line.514"></a>
+<span class="sourceLineNo">515</span><a name="line.515"></a>
+<span class="sourceLineNo">516</span>  /**<a name="line.516"></a>
+<span class="sourceLineNo">517</span>   * The different fields that can be used as limits in calls to<a name="line.517"></a>
+<span class="sourceLineNo">518</span>   * {@link InternalScanner#next(java.util.List)} and {@link RegionScanner#next(java.util.List)}<a name="line.518"></a>
+<span class="sourceLineNo">519</span>   */<a name="line.519"></a>
+<span class="sourceLineNo">520</span>  private static class LimitFields {<a name="line.520"></a>
+<span class="sourceLineNo">521</span>    /**<a name="line.521"></a>
+<span class="sourceLineNo">522</span>     * Default values of the limit fields. Defined such that if a field does NOT change from its<a name="line.522"></a>
+<span class="sourceLineNo">523</span>     * default, it will not be enforced<a name="line.523"></a>
+<span class="sourceLineNo">524</span>     */<a name="line.524"></a>
+<span class="sourceLineNo">525</span>    private static int DEFAULT_BATCH = -1;<a name="line.525"></a>
+<span class="sourceLineNo">526</span>    private static long DEFAULT_SIZE = -1L;<a name="line.526"></a>
+<span class="sourceLineNo">527</span>    private static long DEFAULT_TIME = -1L;<a name="line.527"></a>
+<span class="sourceLineNo">528</span><a name="line.528"></a>
+<span class="sourceLineNo">529</span>    /**<a name="line.529"></a>
+<span class="sourceLineNo">530</span>     * Default scope that is assigned to a limit if a scope is not specified.<a name="line.530"></a>
+<span class="sourceLineNo">531</span>     */<a name="line.531"></a>
+<span class="sourceLineNo">532</span>    private static final LimitScope DEFAULT_SCOPE = LimitScope.BETWEEN_ROWS;<a name="line.532"></a>
+<span class="sourceLineNo">533</span><a name="line.533"></a>
+<span class="sourceLineNo">534</span>    // The batch limit will always be enforced between cells, thus, there isn't a field to hold the<a name="line.534"></a>
+<span class="sourceLineNo">535</span>    // batch scope<a name="line.535"></a>
+<span class="sourceLineNo">536</span>    int batch = DEFAULT_BATCH;<a name="line.536"></a>
+<span class="sourceLineNo">537</span><a name="line.537"></a>
+<span class="sourceLineNo">538</span>    LimitScope sizeScope = DEFAULT_SCOPE;<a name="line.538"></a>
+<span class="sourceLineNo">539</span>    // The sum of cell data sizes(key + value). The Cell data might be in on heap or off heap area.<a name="line.539"></a>
+<span class="sourceLineNo">540</span>    long dataSize = DEFAULT_SIZE;<a name="line.540"></a>
+<span class="sourceLineNo">541</span>    // The sum of heap space occupied by all tracked cells. This includes Cell POJO's overhead as<a name="line.541"></a>
+<span class="sourceLineNo">542</span>    // such AND data cells of Cells which are in on heap area.<a name="line.542"></a>
+<span class="sourceLineNo">543</span>    long heapSize = DEFAULT_SIZE;<a name="line.543"></a>
+<span class="sourceLineNo">544</span><a name="line.544"></a>
+<span class="sourceLineNo">545</span>    LimitScope timeScope = DEFAULT_SCOPE;<a name="line.545"></a>
+<span class="sourceLineNo">546</span>    long time = DEFAULT_TIME;<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>     * Fields keep their default values.<a name="line.549"></a>
+<span class="sourceLineNo">550</span>     */<a name="line.550"></a>
+<span class="sourceLineNo">551</span>    LimitFields() {<a name="line.551"></a>
 <span class="sourceLineNo">552</span>    }<a name="line.552"></a>
 <span class="sourceLineNo">553</span><a name="line.553"></a>
-<span class="sourceLineNo">554</span>    /**<a name="line.554"></a>
-<span class="sourceLineNo">555</span>     * Set all fields together.<a name="line.555"></a>
-<span class="sourceLineNo">556</span>     */<a name="line.556"></a>
-<span class="sourceLineNo">557</span>    void setFields(int batch, LimitScope sizeScope, long dataSize, long heapSize,<a name="line.557"></a>
-<span class="sourceLineNo">558</span>        LimitScope timeScope, long time) {<a name="line.558"></a>
-<span class="sourceLineNo">559</span>      setBatch(batch);<a name="line.559"></a>
-<span class="sourceLineNo">560</span>      setSizeScope(sizeScope);<a name="line.560"></a>
-<span class="sourceLineNo">561</span>      setDataSize(dataSize);<a name="line.561"></a>
-<span class="sourceLineNo">562</span>      setHeapSize(heapSize);<a name="line.562"></a>
-<span class="sourceLineNo">563</span>      setTimeScope(timeScope);<a name="line.563"></a>
-<span class="sourceLineNo">564</span>      setTime(time);<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>    int getBatch() {<a name="line.567"></a>
-<span class="sourceLineNo">568</span>      return this.batch;<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>    void setBatch(int batch) {<a name="line.571"></a>
-<span class="sourceLineNo">572</span>      this.batch = batch;<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>    /**<a name="line.575"></a>
-<span class="sourceLineNo">576</span>     * @param checkerScope<a name="line.576"></a>
-<span class="sourceLineNo">577</span>     * @return true when the limit can be enforced from the scope of the checker<a name="line.577"></a>
-<span class="sourceLineNo">578</span>     */<a name="line.578"></a>
-<span class="sourceLineNo">579</span>    boolean canEnforceBatchLimitFromScope(LimitScope checkerScope) {<a name="line.579"></a>
-<span class="sourceLineNo">580</span>      return LimitScope.BETWEEN_CELLS.canEnforceLimitFromScope(checkerScope);<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>    long getDataSize() {<a name="line.583"></a>
-<span class="sourceLineNo">584</span>      return this.dataSize;<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>    long getHeapSize() {<a name="line.587"></a>
-<span class="sourceLineNo">588</span>      return this.heapSize;<a name="line.588"></a>
-<span class="sourceLineNo">589</span>    }<a name="line.589"></a>
-<span class="sourceLineNo">590</span><a name="line.590"></a>
-<span class="sourceLineNo">591</span>    void setDataSize(long dataSize) {<a name="line.591"></a>
-<span class="sourceLineNo">592</span>      this.dataSize = dataSize;<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>    void setHeapSize(long heapSize) {<a name="line.595"></a>
-<span class="sourceLineNo">596</span>      this.heapSize = heapSize;<a name="line.596"></a>
-<span class="sourceLineNo">597</span>    }<a name="line.597"></a>
-<span class="sourceLineNo">598</span><a name="line.598"></a>
-<span class="sourceLineNo">599</span>    /**<a name="line.599"></a>
-<span class="sourceLineNo">600</span>     * @return {@link LimitScope} indicating scope in which the size limit is enforced<a name="line.600"></a>
-<span class="sourceLineNo">601</span>     */<a name="line.601"></a>
-<span class="sourceLineNo">602</span>    LimitScope getSizeScope() {<a name="line.602"></a>
-<span class="sourceLineNo">603</span>      return this.sizeScope;<a name="line.603"></a>
+<span class="sourceLineNo">554</span>    void copy(LimitFields limitsToCopy) {<a name="line.554"></a>
+<span class="sourceLineNo">555</span>      if (limitsToCopy != null) {<a name="line.555"></a>
+<span class="sourceLineNo">556</span>        setFields(limitsToCopy.getBatch(), limitsToCopy.getSizeScope(), limitsToCopy.getDataSize(),<a name="line.556"></a>
+<span class="sourceLineNo">557</span>            limitsToCopy.getHeapSize(), limitsToCopy.getTimeScope(), limitsToCopy.getTime());<a name="line.557"></a>
+<span class="sourceLineNo">558</span>      }<a name="line.558"></a>
+<span class="sourceLineNo">559</span>    }<a name="line.559"></a>
+<span class="sourceLineNo">560</span><a name="line.560"></a>
+<span class="sourceLineNo">561</span>    /**<a name="line.561"></a>
+<span class="sourceLineNo">562</span>     * Set all fields together.<a name="line.562"></a>
+<span class="sourceLineNo">563</span>     */<a name="line.563"></a>
+<span class="sourceLineNo">564</span>    void setFields(int batch, LimitScope sizeScope, long dataSize, long heapSize,<a name="line.564"></a>
+<span class="sourceLineNo">565</span>        LimitScope timeScope, long time) {<a name="line.565"></a>
+<span class="sourceLineNo">566</span>      setBatch(batch);<a name="line.566"></a>
+<span class="sourceLineNo">567</span>      setSizeScope(sizeScope);<a name="line.567"></a>
+<span class="sourceLineNo">568</span>      setDataSize(dataSize);<a name="line.568"></a>
+<span class="sourceLineNo">569</span>      setHeapSize(heapSize);<a name="line.569"></a>
+<span class="sourceLineNo">570</span>      setTimeScope(timeScope);<a name="line.570"></a>
+<span class="sourceLineNo">571</span>      setTime(time);<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>    int getBatch() {<a name="line.574"></a>
+<span class="sourceLineNo">575</span>      return this.batch;<a name="line.575"></a>
+<span class="sourceLineNo">576</span>    }<a name="line.576"></a>
+<span class="sourceLineNo">577</span><a name="line.577"></a>
+<span class="sourceLineNo">578</span>    void setBatch(int batch) {<a name="line.578"></a>
+<span class="sourceLineNo">579</span>      this.batch = batch;<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

<TRUNCATED>

[12/50] hbase-site git commit: Published site at 26babcf013de696b899d76a3c39434b794440d8d.

Posted by gi...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/src-html/org/apache/hadoop/hbase/regionserver/StoreScanner.html
----------------------------------------------------------------------
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/regionserver/StoreScanner.html b/devapidocs/src-html/org/apache/hadoop/hbase/regionserver/StoreScanner.html
index baef4a1..9e934af 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/regionserver/StoreScanner.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/regionserver/StoreScanner.html
@@ -561,594 +561,609 @@
 <span class="sourceLineNo">553</span><a name="line.553"></a>
 <span class="sourceLineNo">554</span>    LOOP: do {<a name="line.554"></a>
 <span class="sourceLineNo">555</span>      // Update and check the time limit based on the configured value of cellsPerTimeoutCheck<a name="line.555"></a>
-<span class="sourceLineNo">556</span>      if ((kvsScanned % cellsPerHeartbeatCheck == 0)) {<a name="line.556"></a>
-<span class="sourceLineNo">557</span>        if (scannerContext.checkTimeLimit(LimitScope.BETWEEN_CELLS)) {<a name="line.557"></a>
-<span class="sourceLineNo">558</span>          return scannerContext.setScannerState(NextState.TIME_LIMIT_REACHED).hasMoreValues();<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>      // Do object compare - we set prevKV from the same heap.<a name="line.561"></a>
-<span class="sourceLineNo">562</span>      if (prevCell != cell) {<a name="line.562"></a>
-<span class="sourceLineNo">563</span>        ++kvsScanned;<a name="line.563"></a>
-<span class="sourceLineNo">564</span>      }<a name="line.564"></a>
-<span class="sourceLineNo">565</span>      checkScanOrder(prevCell, cell, comparator);<a name="line.565"></a>
-<span class="sourceLineNo">566</span>      int cellSize = PrivateCellUtil.estimatedSerializedSizeOf(cell);<a name="line.566"></a>
-<span class="sourceLineNo">567</span>      bytesRead += cellSize;<a name="line.567"></a>
-<span class="sourceLineNo">568</span>      prevCell = cell;<a name="line.568"></a>
-<span class="sourceLineNo">569</span>      scannerContext.setLastPeekedCell(cell);<a name="line.569"></a>
-<span class="sourceLineNo">570</span>      topChanged = false;<a name="line.570"></a>
-<span class="sourceLineNo">571</span>      ScanQueryMatcher.MatchCode qcode = matcher.match(cell);<a name="line.571"></a>
-<span class="sourceLineNo">572</span>      switch (qcode) {<a name="line.572"></a>
-<span class="sourceLineNo">573</span>        case INCLUDE:<a name="line.573"></a>
-<span class="sourceLineNo">574</span>        case INCLUDE_AND_SEEK_NEXT_ROW:<a name="line.574"></a>
-<span class="sourceLineNo">575</span>        case INCLUDE_AND_SEEK_NEXT_COL:<a name="line.575"></a>
-<span class="sourceLineNo">576</span><a name="line.576"></a>
-<span class="sourceLineNo">577</span>          Filter f = matcher.getFilter();<a name="line.577"></a>
-<span class="sourceLineNo">578</span>          if (f != null) {<a name="line.578"></a>
-<span class="sourceLineNo">579</span>            cell = f.transformCell(cell);<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>          this.countPerRow++;<a name="line.582"></a>
-<span class="sourceLineNo">583</span>          if (storeLimit &gt; -1 &amp;&amp; this.countPerRow &gt; (storeLimit + storeOffset)) {<a name="line.583"></a>
-<span class="sourceLineNo">584</span>            // do what SEEK_NEXT_ROW does.<a name="line.584"></a>
-<span class="sourceLineNo">585</span>            if (!matcher.moreRowsMayExistAfter(cell)) {<a name="line.585"></a>
-<span class="sourceLineNo">586</span>              close(false);// Do all cleanup except heap.close()<a name="line.586"></a>
-<span class="sourceLineNo">587</span>              return scannerContext.setScannerState(NextState.NO_MORE_VALUES).hasMoreValues();<a name="line.587"></a>
-<span class="sourceLineNo">588</span>            }<a name="line.588"></a>
-<span class="sourceLineNo">589</span>            matcher.clearCurrentRow();<a name="line.589"></a>
-<span class="sourceLineNo">590</span>            seekToNextRow(cell);<a name="line.590"></a>
-<span class="sourceLineNo">591</span>            break LOOP;<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>          // add to results only if we have skipped #storeOffset kvs<a name="line.594"></a>
-<span class="sourceLineNo">595</span>          // also update metric accordingly<a name="line.595"></a>
-<span class="sourceLineNo">596</span>          if (this.countPerRow &gt; storeOffset) {<a name="line.596"></a>
-<span class="sourceLineNo">597</span>            outResult.add(cell);<a name="line.597"></a>
-<span class="sourceLineNo">598</span><a name="line.598"></a>
-<span class="sourceLineNo">599</span>            // Update local tracking information<a name="line.599"></a>
-<span class="sourceLineNo">600</span>            count++;<a name="line.600"></a>
-<span class="sourceLineNo">601</span>            totalBytesRead += cellSize;<a name="line.601"></a>
-<span class="sourceLineNo">602</span><a name="line.602"></a>
-<span class="sourceLineNo">603</span>            // Update the progress of the scanner context<a name="line.603"></a>
-<span class="sourceLineNo">604</span>            scannerContext.incrementSizeProgress(cellSize,<a name="line.604"></a>
-<span class="sourceLineNo">605</span>              PrivateCellUtil.estimatedSizeOfCell(cell));<a name="line.605"></a>
-<span class="sourceLineNo">606</span>            scannerContext.incrementBatchProgress(1);<a name="line.606"></a>
-<span class="sourceLineNo">607</span><a name="line.607"></a>
-<span class="sourceLineNo">608</span>            if (matcher.isUserScan() &amp;&amp; totalBytesRead &gt; maxRowSize) {<a name="line.608"></a>
-<span class="sourceLineNo">609</span>              throw new RowTooBigException(<a name="line.609"></a>
-<span class="sourceLineNo">610</span>                  "Max row size allowed: " + maxRowSize + ", but the row is bigger than that.");<a name="line.610"></a>
-<span class="sourceLineNo">611</span>            }<a name="line.611"></a>
-<span class="sourceLineNo">612</span>          }<a name="line.612"></a>
+<span class="sourceLineNo">556</span>      // Or if the preadMaxBytes is reached and we may want to return so we can switch to stream in<a name="line.556"></a>
+<span class="sourceLineNo">557</span>      // the shipped method below.<a name="line.557"></a>
+<span class="sourceLineNo">558</span>      if (kvsScanned % cellsPerHeartbeatCheck == 0 || (scanUsePread &amp;&amp;<a name="line.558"></a>
+<span class="sourceLineNo">559</span>        scan.getReadType() == Scan.ReadType.DEFAULT &amp;&amp; bytesRead &gt; preadMaxBytes)) {<a name="line.559"></a>
+<span class="sourceLineNo">560</span>        if (scannerContext.checkTimeLimit(LimitScope.BETWEEN_CELLS)) {<a name="line.560"></a>
+<span class="sourceLineNo">561</span>          return scannerContext.setScannerState(NextState.TIME_LIMIT_REACHED).hasMoreValues();<a name="line.561"></a>
+<span class="sourceLineNo">562</span>        }<a name="line.562"></a>
+<span class="sourceLineNo">563</span>      }<a name="line.563"></a>
+<span class="sourceLineNo">564</span>      // Do object compare - we set prevKV from the same heap.<a name="line.564"></a>
+<span class="sourceLineNo">565</span>      if (prevCell != cell) {<a name="line.565"></a>
+<span class="sourceLineNo">566</span>        ++kvsScanned;<a name="line.566"></a>
+<span class="sourceLineNo">567</span>      }<a name="line.567"></a>
+<span class="sourceLineNo">568</span>      checkScanOrder(prevCell, cell, comparator);<a name="line.568"></a>
+<span class="sourceLineNo">569</span>      int cellSize = PrivateCellUtil.estimatedSerializedSizeOf(cell);<a name="line.569"></a>
+<span class="sourceLineNo">570</span>      bytesRead += cellSize;<a name="line.570"></a>
+<span class="sourceLineNo">571</span>      if (scanUsePread &amp;&amp; scan.getReadType() == Scan.ReadType.DEFAULT &amp;&amp;<a name="line.571"></a>
+<span class="sourceLineNo">572</span>        bytesRead &gt; preadMaxBytes) {<a name="line.572"></a>
+<span class="sourceLineNo">573</span>        // return immediately if we want to switch from pread to stream. We need this because we can<a name="line.573"></a>
+<span class="sourceLineNo">574</span>        // only switch in the shipped method, if user use a filter to filter out everything and rpc<a name="line.574"></a>
+<span class="sourceLineNo">575</span>        // timeout is very large then the shipped method will never be called until the whole scan<a name="line.575"></a>
+<span class="sourceLineNo">576</span>        // is finished, but at that time we have already scan all the data...<a name="line.576"></a>
+<span class="sourceLineNo">577</span>        // See HBASE-20457 for more details.<a name="line.577"></a>
+<span class="sourceLineNo">578</span>        // And there is still a scenario that can not be handled. If we have a very large row, which<a name="line.578"></a>
+<span class="sourceLineNo">579</span>        // have millions of qualifiers, and filter.filterRow is used, then even if we set the flag<a name="line.579"></a>
+<span class="sourceLineNo">580</span>        // here, we still need to scan all the qualifiers before returning...<a name="line.580"></a>
+<span class="sourceLineNo">581</span>        scannerContext.returnImmediately();<a name="line.581"></a>
+<span class="sourceLineNo">582</span>      }<a name="line.582"></a>
+<span class="sourceLineNo">583</span>      prevCell = cell;<a name="line.583"></a>
+<span class="sourceLineNo">584</span>      scannerContext.setLastPeekedCell(cell);<a name="line.584"></a>
+<span class="sourceLineNo">585</span>      topChanged = false;<a name="line.585"></a>
+<span class="sourceLineNo">586</span>      ScanQueryMatcher.MatchCode qcode = matcher.match(cell);<a name="line.586"></a>
+<span class="sourceLineNo">587</span>      switch (qcode) {<a name="line.587"></a>
+<span class="sourceLineNo">588</span>        case INCLUDE:<a name="line.588"></a>
+<span class="sourceLineNo">589</span>        case INCLUDE_AND_SEEK_NEXT_ROW:<a name="line.589"></a>
+<span class="sourceLineNo">590</span>        case INCLUDE_AND_SEEK_NEXT_COL:<a name="line.590"></a>
+<span class="sourceLineNo">591</span><a name="line.591"></a>
+<span class="sourceLineNo">592</span>          Filter f = matcher.getFilter();<a name="line.592"></a>
+<span class="sourceLineNo">593</span>          if (f != null) {<a name="line.593"></a>
+<span class="sourceLineNo">594</span>            cell = f.transformCell(cell);<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>          this.countPerRow++;<a name="line.597"></a>
+<span class="sourceLineNo">598</span>          if (storeLimit &gt; -1 &amp;&amp; this.countPerRow &gt; (storeLimit + storeOffset)) {<a name="line.598"></a>
+<span class="sourceLineNo">599</span>            // do what SEEK_NEXT_ROW does.<a name="line.599"></a>
+<span class="sourceLineNo">600</span>            if (!matcher.moreRowsMayExistAfter(cell)) {<a name="line.600"></a>
+<span class="sourceLineNo">601</span>              close(false);// Do all cleanup except heap.close()<a name="line.601"></a>
+<span class="sourceLineNo">602</span>              return scannerContext.setScannerState(NextState.NO_MORE_VALUES).hasMoreValues();<a name="line.602"></a>
+<span class="sourceLineNo">603</span>            }<a name="line.603"></a>
+<span class="sourceLineNo">604</span>            matcher.clearCurrentRow();<a name="line.604"></a>
+<span class="sourceLineNo">605</span>            seekToNextRow(cell);<a name="line.605"></a>
+<span class="sourceLineNo">606</span>            break LOOP;<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>          // add to results only if we have skipped #storeOffset kvs<a name="line.609"></a>
+<span class="sourceLineNo">610</span>          // also update metric accordingly<a name="line.610"></a>
+<span class="sourceLineNo">611</span>          if (this.countPerRow &gt; storeOffset) {<a name="line.611"></a>
+<span class="sourceLineNo">612</span>            outResult.add(cell);<a name="line.612"></a>
 <span class="sourceLineNo">613</span><a name="line.613"></a>
-<span class="sourceLineNo">614</span>          if (qcode == ScanQueryMatcher.MatchCode.INCLUDE_AND_SEEK_NEXT_ROW) {<a name="line.614"></a>
-<span class="sourceLineNo">615</span>            if (!matcher.moreRowsMayExistAfter(cell)) {<a name="line.615"></a>
-<span class="sourceLineNo">616</span>              close(false);// Do all cleanup except heap.close()<a name="line.616"></a>
-<span class="sourceLineNo">617</span>              return scannerContext.setScannerState(NextState.NO_MORE_VALUES).hasMoreValues();<a name="line.617"></a>
-<span class="sourceLineNo">618</span>            }<a name="line.618"></a>
-<span class="sourceLineNo">619</span>            matcher.clearCurrentRow();<a name="line.619"></a>
-<span class="sourceLineNo">620</span>            seekOrSkipToNextRow(cell);<a name="line.620"></a>
-<span class="sourceLineNo">621</span>          } else if (qcode == ScanQueryMatcher.MatchCode.INCLUDE_AND_SEEK_NEXT_COL) {<a name="line.621"></a>
-<span class="sourceLineNo">622</span>            seekOrSkipToNextColumn(cell);<a name="line.622"></a>
-<span class="sourceLineNo">623</span>          } else {<a name="line.623"></a>
-<span class="sourceLineNo">624</span>            this.heap.next();<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>          if (scannerContext.checkBatchLimit(LimitScope.BETWEEN_CELLS)) {<a name="line.627"></a>
-<span class="sourceLineNo">628</span>            break LOOP;<a name="line.628"></a>
-<span class="sourceLineNo">629</span>          }<a name="line.629"></a>
-<span class="sourceLineNo">630</span>          if (scannerContext.checkSizeLimit(LimitScope.BETWEEN_CELLS)) {<a name="line.630"></a>
-<span class="sourceLineNo">631</span>            break LOOP;<a name="line.631"></a>
-<span class="sourceLineNo">632</span>          }<a name="line.632"></a>
-<span class="sourceLineNo">633</span>          continue;<a name="line.633"></a>
-<span class="sourceLineNo">634</span><a name="line.634"></a>
-<span class="sourceLineNo">635</span>        case DONE:<a name="line.635"></a>
-<span class="sourceLineNo">636</span>          // Optimization for Gets! If DONE, no more to get on this row, early exit!<a name="line.636"></a>
-<span class="sourceLineNo">637</span>          if (get) {<a name="line.637"></a>
-<span class="sourceLineNo">638</span>            // Then no more to this row... exit.<a name="line.638"></a>
-<span class="sourceLineNo">639</span>            close(false);// Do all cleanup except heap.close()<a name="line.639"></a>
-<span class="sourceLineNo">640</span>            return scannerContext.setScannerState(NextState.NO_MORE_VALUES).hasMoreValues();<a name="line.640"></a>
-<span class="sourceLineNo">641</span>          }<a name="line.641"></a>
-<span class="sourceLineNo">642</span>          matcher.clearCurrentRow();<a name="line.642"></a>
-<span class="sourceLineNo">643</span>          return scannerContext.setScannerState(NextState.MORE_VALUES).hasMoreValues();<a name="line.643"></a>
-<span class="sourceLineNo">644</span><a name="line.644"></a>
-<span class="sourceLineNo">645</span>        case DONE_SCAN:<a name="line.645"></a>
-<span class="sourceLineNo">646</span>          close(false);// Do all cleanup except heap.close()<a name="line.646"></a>
-<span class="sourceLineNo">647</span>          return scannerContext.setScannerState(NextState.NO_MORE_VALUES).hasMoreValues();<a name="line.647"></a>
-<span class="sourceLineNo">648</span><a name="line.648"></a>
-<span class="sourceLineNo">649</span>        case SEEK_NEXT_ROW:<a name="line.649"></a>
-<span class="sourceLineNo">650</span>          // This is just a relatively simple end of scan fix, to short-cut end<a name="line.650"></a>
-<span class="sourceLineNo">651</span>          // us if there is an endKey in the scan.<a name="line.651"></a>
-<span class="sourceLineNo">652</span>          if (!matcher.moreRowsMayExistAfter(cell)) {<a name="line.652"></a>
-<span class="sourceLineNo">653</span>            close(false);// Do all cleanup except heap.close()<a name="line.653"></a>
-<span class="sourceLineNo">654</span>            return scannerContext.setScannerState(NextState.NO_MORE_VALUES).hasMoreValues();<a name="line.654"></a>
-<span class="sourceLineNo">655</span>          }<a name="line.655"></a>
-<span class="sourceLineNo">656</span>          matcher.clearCurrentRow();<a name="line.656"></a>
-<span class="sourceLineNo">657</span>          seekOrSkipToNextRow(cell);<a name="line.657"></a>
-<span class="sourceLineNo">658</span>          NextState stateAfterSeekNextRow = needToReturn(outResult);<a name="line.658"></a>
-<span class="sourceLineNo">659</span>          if (stateAfterSeekNextRow != null) {<a name="line.659"></a>
-<span class="sourceLineNo">660</span>            return scannerContext.setScannerState(stateAfterSeekNextRow).hasMoreValues();<a name="line.660"></a>
-<span class="sourceLineNo">661</span>          }<a name="line.661"></a>
-<span class="sourceLineNo">662</span>          break;<a name="line.662"></a>
+<span class="sourceLineNo">614</span>            // Update local tracking information<a name="line.614"></a>
+<span class="sourceLineNo">615</span>            count++;<a name="line.615"></a>
+<span class="sourceLineNo">616</span>            totalBytesRead += cellSize;<a name="line.616"></a>
+<span class="sourceLineNo">617</span><a name="line.617"></a>
+<span class="sourceLineNo">618</span>            // Update the progress of the scanner context<a name="line.618"></a>
+<span class="sourceLineNo">619</span>            scannerContext.incrementSizeProgress(cellSize,<a name="line.619"></a>
+<span class="sourceLineNo">620</span>              PrivateCellUtil.estimatedSizeOfCell(cell));<a name="line.620"></a>
+<span class="sourceLineNo">621</span>            scannerContext.incrementBatchProgress(1);<a name="line.621"></a>
+<span class="sourceLineNo">622</span><a name="line.622"></a>
+<span class="sourceLineNo">623</span>            if (matcher.isUserScan() &amp;&amp; totalBytesRead &gt; maxRowSize) {<a name="line.623"></a>
+<span class="sourceLineNo">624</span>              throw new RowTooBigException(<a name="line.624"></a>
+<span class="sourceLineNo">625</span>                  "Max row size allowed: " + maxRowSize + ", but the row is bigger than that.");<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><a name="line.628"></a>
+<span class="sourceLineNo">629</span>          if (qcode == ScanQueryMatcher.MatchCode.INCLUDE_AND_SEEK_NEXT_ROW) {<a name="line.629"></a>
+<span class="sourceLineNo">630</span>            if (!matcher.moreRowsMayExistAfter(cell)) {<a name="line.630"></a>
+<span class="sourceLineNo">631</span>              close(false);// Do all cleanup except heap.close()<a name="line.631"></a>
+<span class="sourceLineNo">632</span>              return scannerContext.setScannerState(NextState.NO_MORE_VALUES).hasMoreValues();<a name="line.632"></a>
+<span class="sourceLineNo">633</span>            }<a name="line.633"></a>
+<span class="sourceLineNo">634</span>            matcher.clearCurrentRow();<a name="line.634"></a>
+<span class="sourceLineNo">635</span>            seekOrSkipToNextRow(cell);<a name="line.635"></a>
+<span class="sourceLineNo">636</span>          } else if (qcode == ScanQueryMatcher.MatchCode.INCLUDE_AND_SEEK_NEXT_COL) {<a name="line.636"></a>
+<span class="sourceLineNo">637</span>            seekOrSkipToNextColumn(cell);<a name="line.637"></a>
+<span class="sourceLineNo">638</span>          } else {<a name="line.638"></a>
+<span class="sourceLineNo">639</span>            this.heap.next();<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>          if (scannerContext.checkBatchLimit(LimitScope.BETWEEN_CELLS)) {<a name="line.642"></a>
+<span class="sourceLineNo">643</span>            break LOOP;<a name="line.643"></a>
+<span class="sourceLineNo">644</span>          }<a name="line.644"></a>
+<span class="sourceLineNo">645</span>          if (scannerContext.checkSizeLimit(LimitScope.BETWEEN_CELLS)) {<a name="line.645"></a>
+<span class="sourceLineNo">646</span>            break LOOP;<a name="line.646"></a>
+<span class="sourceLineNo">647</span>          }<a name="line.647"></a>
+<span class="sourceLineNo">648</span>          continue;<a name="line.648"></a>
+<span class="sourceLineNo">649</span><a name="line.649"></a>
+<span class="sourceLineNo">650</span>        case DONE:<a name="line.650"></a>
+<span class="sourceLineNo">651</span>          // Optimization for Gets! If DONE, no more to get on this row, early exit!<a name="line.651"></a>
+<span class="sourceLineNo">652</span>          if (get) {<a name="line.652"></a>
+<span class="sourceLineNo">653</span>            // Then no more to this row... exit.<a name="line.653"></a>
+<span class="sourceLineNo">654</span>            close(false);// Do all cleanup except heap.close()<a name="line.654"></a>
+<span class="sourceLineNo">655</span>            return scannerContext.setScannerState(NextState.NO_MORE_VALUES).hasMoreValues();<a name="line.655"></a>
+<span class="sourceLineNo">656</span>          }<a name="line.656"></a>
+<span class="sourceLineNo">657</span>          matcher.clearCurrentRow();<a name="line.657"></a>
+<span class="sourceLineNo">658</span>          return scannerContext.setScannerState(NextState.MORE_VALUES).hasMoreValues();<a name="line.658"></a>
+<span class="sourceLineNo">659</span><a name="line.659"></a>
+<span class="sourceLineNo">660</span>        case DONE_SCAN:<a name="line.660"></a>
+<span class="sourceLineNo">661</span>          close(false);// Do all cleanup except heap.close()<a name="line.661"></a>
+<span class="sourceLineNo">662</span>          return scannerContext.setScannerState(NextState.NO_MORE_VALUES).hasMoreValues();<a name="line.662"></a>
 <span class="sourceLineNo">663</span><a name="line.663"></a>
-<span class="sourceLineNo">664</span>        case SEEK_NEXT_COL:<a name="line.664"></a>
-<span class="sourceLineNo">665</span>          seekOrSkipToNextColumn(cell);<a name="line.665"></a>
-<span class="sourceLineNo">666</span>          NextState stateAfterSeekNextColumn = needToReturn(outResult);<a name="line.666"></a>
-<span class="sourceLineNo">667</span>          if (stateAfterSeekNextColumn != null) {<a name="line.667"></a>
-<span class="sourceLineNo">668</span>            return scannerContext.setScannerState(stateAfterSeekNextColumn).hasMoreValues();<a name="line.668"></a>
-<span class="sourceLineNo">669</span>          }<a name="line.669"></a>
-<span class="sourceLineNo">670</span>          break;<a name="line.670"></a>
-<span class="sourceLineNo">671</span><a name="line.671"></a>
-<span class="sourceLineNo">672</span>        case SKIP:<a name="line.672"></a>
-<span class="sourceLineNo">673</span>          this.heap.next();<a name="line.673"></a>
-<span class="sourceLineNo">674</span>          break;<a name="line.674"></a>
-<span class="sourceLineNo">675</span><a name="line.675"></a>
-<span class="sourceLineNo">676</span>        case SEEK_NEXT_USING_HINT:<a name="line.676"></a>
-<span class="sourceLineNo">677</span>          Cell nextKV = matcher.getNextKeyHint(cell);<a name="line.677"></a>
-<span class="sourceLineNo">678</span>          if (nextKV != null) {<a name="line.678"></a>
-<span class="sourceLineNo">679</span>            seekAsDirection(nextKV);<a name="line.679"></a>
-<span class="sourceLineNo">680</span>            NextState stateAfterSeekByHint = needToReturn(outResult);<a name="line.680"></a>
-<span class="sourceLineNo">681</span>            if (stateAfterSeekByHint != null) {<a name="line.681"></a>
-<span class="sourceLineNo">682</span>              return scannerContext.setScannerState(stateAfterSeekByHint).hasMoreValues();<a name="line.682"></a>
-<span class="sourceLineNo">683</span>            }<a name="line.683"></a>
-<span class="sourceLineNo">684</span>          } else {<a name="line.684"></a>
-<span class="sourceLineNo">685</span>            heap.next();<a name="line.685"></a>
-<span class="sourceLineNo">686</span>          }<a name="line.686"></a>
-<span class="sourceLineNo">687</span>          break;<a name="line.687"></a>
-<span class="sourceLineNo">688</span><a name="line.688"></a>
-<span class="sourceLineNo">689</span>        default:<a name="line.689"></a>
-<span class="sourceLineNo">690</span>          throw new RuntimeException("UNEXPECTED");<a name="line.690"></a>
-<span class="sourceLineNo">691</span>      }<a name="line.691"></a>
-<span class="sourceLineNo">692</span>    } while ((cell = this.heap.peek()) != null);<a name="line.692"></a>
-<span class="sourceLineNo">693</span><a name="line.693"></a>
-<span class="sourceLineNo">694</span>    if (count &gt; 0) {<a name="line.694"></a>
-<span class="sourceLineNo">695</span>      return scannerContext.setScannerState(NextState.MORE_VALUES).hasMoreValues();<a name="line.695"></a>
-<span class="sourceLineNo">696</span>    }<a name="line.696"></a>
-<span class="sourceLineNo">697</span><a name="line.697"></a>
-<span class="sourceLineNo">698</span>    // No more keys<a name="line.698"></a>
-<span class="sourceLineNo">699</span>    close(false);// Do all cleanup except heap.close()<a name="line.699"></a>
-<span class="sourceLineNo">700</span>    return scannerContext.setScannerState(NextState.NO_MORE_VALUES).hasMoreValues();<a name="line.700"></a>
-<span class="sourceLineNo">701</span>  }<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>   * If the top cell won't be flushed into disk, the new top cell may be<a name="line.704"></a>
-<span class="sourceLineNo">705</span>   * changed after #reopenAfterFlush. Because the older top cell only exist<a name="line.705"></a>
-<span class="sourceLineNo">706</span>   * in the memstore scanner but the memstore scanner is replaced by hfile<a name="line.706"></a>
-<span class="sourceLineNo">707</span>   * scanner after #reopenAfterFlush. If the row of top cell is changed,<a name="line.707"></a>
-<span class="sourceLineNo">708</span>   * we should return the current cells. Otherwise, we may return<a name="line.708"></a>
-<span class="sourceLineNo">709</span>   * the cells across different rows.<a name="line.709"></a>
-<span class="sourceLineNo">710</span>   * @param outResult the cells which are visible for user scan<a name="line.710"></a>
-<span class="sourceLineNo">711</span>   * @return null is the top cell doesn't change. Otherwise, the NextState<a name="line.711"></a>
-<span class="sourceLineNo">712</span>   *         to return<a name="line.712"></a>
-<span class="sourceLineNo">713</span>   */<a name="line.713"></a>
-<span class="sourceLineNo">714</span>  private NextState needToReturn(List&lt;Cell&gt; outResult) {<a name="line.714"></a>
-<span class="sourceLineNo">715</span>    if (!outResult.isEmpty() &amp;&amp; topChanged) {<a name="line.715"></a>
-<span class="sourceLineNo">716</span>      return heap.peek() == null ? NextState.NO_MORE_VALUES : NextState.MORE_VALUES;<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>
-<span class="sourceLineNo">721</span>  private void seekOrSkipToNextRow(Cell cell) throws IOException {<a name="line.721"></a>
-<span class="sourceLineNo">722</span>    // If it is a Get Scan, then we know that we are done with this row; there are no more<a name="line.722"></a>
-<span class="sourceLineNo">723</span>    // rows beyond the current one: don't try to optimize.<a name="line.723"></a>
-<span class="sourceLineNo">724</span>    if (!get) {<a name="line.724"></a>
-<span class="sourceLineNo">725</span>      if (trySkipToNextRow(cell)) {<a name="line.725"></a>
-<span class="sourceLineNo">726</span>        return;<a name="line.726"></a>
-<span class="sourceLineNo">727</span>      }<a name="line.727"></a>
-<span class="sourceLineNo">728</span>    }<a name="line.728"></a>
-<span class="sourceLineNo">729</span>    seekToNextRow(cell);<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>  private void seekOrSkipToNextColumn(Cell cell) throws IOException {<a name="line.732"></a>
-<span class="sourceLineNo">733</span>    if (!trySkipToNextColumn(cell)) {<a name="line.733"></a>
-<span class="sourceLineNo">734</span>      seekAsDirection(matcher.getKeyForNextColumn(cell));<a name="line.734"></a>
-<span class="sourceLineNo">735</span>    }<a name="line.735"></a>
-<span class="sourceLineNo">736</span>  }<a name="line.736"></a>
-<span class="sourceLineNo">737</span><a name="line.737"></a>
-<span class="sourceLineNo">738</span>  /**<a name="line.738"></a>
-<span class="sourceLineNo">739</span>   * See if we should actually SEEK or rather just SKIP to the next Cell (see HBASE-13109).<a name="line.739"></a>
-<span class="sourceLineNo">740</span>   * ScanQueryMatcher may issue SEEK hints, such as seek to next column, next row,<a name="line.740"></a>
-<span class="sourceLineNo">741</span>   * or seek to an arbitrary seek key. This method decides whether a seek is the most efficient<a name="line.741"></a>
-<span class="sourceLineNo">742</span>   * _actual_ way to get us to the requested cell (SEEKs are more expensive than SKIP, SKIP,<a name="line.742"></a>
-<span class="sourceLineNo">743</span>   * SKIP inside the current, loaded block).<a name="line.743"></a>
-<span class="sourceLineNo">744</span>   * It does this by looking at the next indexed key of the current HFile. This key<a name="line.744"></a>
-<span class="sourceLineNo">745</span>   * is then compared with the _SEEK_ key, where a SEEK key is an artificial 'last possible key<a name="line.745"></a>
-<span class="sourceLineNo">746</span>   * on the row' (only in here, we avoid actually creating a SEEK key; in the compare we work with<a name="line.746"></a>
-<span class="sourceLineNo">747</span>   * the current Cell but compare as though it were a seek key; see down in<a name="line.747"></a>
-<span class="sourceLineNo">748</span>   * matcher.compareKeyForNextRow, etc). If the compare gets us onto the<a name="line.748"></a>
-<span class="sourceLineNo">749</span>   * next block we *_SEEK, otherwise we just SKIP to the next requested cell.<a name="line.749"></a>
-<span class="sourceLineNo">750</span>   *<a name="line.750"></a>
-<span class="sourceLineNo">751</span>   * &lt;p&gt;Other notes:<a name="line.751"></a>
-<span class="sourceLineNo">752</span>   * &lt;ul&gt;<a name="line.752"></a>
-<span class="sourceLineNo">753</span>   * &lt;li&gt;Rows can straddle block boundaries&lt;/li&gt;<a name="line.753"></a>
-<span class="sourceLineNo">754</span>   * &lt;li&gt;Versions of columns can straddle block boundaries (i.e. column C1 at T1 might be in a<a name="line.754"></a>
-<span class="sourceLineNo">755</span>   * different block than column C1 at T2)&lt;/li&gt;<a name="line.755"></a>
-<span class="sourceLineNo">756</span>   * &lt;li&gt;We want to SKIP if the chance is high that we'll find the desired Cell after a<a name="line.756"></a>
-<span class="sourceLineNo">757</span>   * few SKIPs...&lt;/li&gt;<a name="line.757"></a>
-<span class="sourceLineNo">758</span>   * &lt;li&gt;We want to SEEK when the chance is high that we'll be able to seek<a name="line.758"></a>
-<span class="sourceLineNo">759</span>   * past many Cells, especially if we know we need to go to the next block.&lt;/li&gt;<a name="line.759"></a>
-<span class="sourceLineNo">760</span>   * &lt;/ul&gt;<a name="line.760"></a>
-<span class="sourceLineNo">761</span>   * &lt;p&gt;A good proxy (best effort) to determine whether SKIP is better than SEEK is whether<a name="line.761"></a>
-<span class="sourceLineNo">762</span>   * we'll likely end up seeking to the next block (or past the next block) to get our next column.<a name="line.762"></a>
-<span class="sourceLineNo">763</span>   * Example:<a name="line.763"></a>
-<span class="sourceLineNo">764</span>   * &lt;pre&gt;<a name="line.764"></a>
-<span class="sourceLineNo">765</span>   * |    BLOCK 1              |     BLOCK 2                   |<a name="line.765"></a>
-<span class="sourceLineNo">766</span>   * |  r1/c1, r1/c2, r1/c3    |    r1/c4, r1/c5, r2/c1        |<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>   *                           Next Index Key   SEEK_NEXT_ROW (before r2/c1)<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>   * |    BLOCK 1                       |     BLOCK 2                      |<a name="line.772"></a>
-<span class="sourceLineNo">773</span>   * |  r1/c1/t5, r1/c1/t4, r1/c1/t3    |    r1/c1/t2, r1/c1/T1, r1/c2/T3  |<a name="line.773"></a>
-<span class="sourceLineNo">774</span>   *                                            ^              ^<a name="line.774"></a>
-<span class="sourceLineNo">775</span>   *                                            |              |<a name="line.775"></a>
-<span class="sourceLineNo">776</span>   *                                    Next Index Key        SEEK_NEXT_COL<a name="line.776"></a>
-<span class="sourceLineNo">777</span>   * &lt;/pre&gt;<a name="line.777"></a>
-<span class="sourceLineNo">778</span>   * Now imagine we want columns c1 and c3 (see first diagram above), the 'Next Index Key' of r1/c4<a name="line.778"></a>
-<span class="sourceLineNo">779</span>   * is &gt; r1/c3 so we should seek to get to the c1 on the next row, r2. In second case, say we only<a name="line.779"></a>
-<span class="sourceLineNo">780</span>   * want one version of c1, after we have it, a SEEK_COL will be issued to get to c2. Looking at<a name="line.780"></a>
-<span class="sourceLineNo">781</span>   * the 'Next Index Key', it would land us in the next block, so we should SEEK. In other scenarios<a name="line.781"></a>
-<span class="sourceLineNo">782</span>   * where the SEEK will not land us in the next block, it is very likely better to issues a series<a name="line.782"></a>
-<span class="sourceLineNo">783</span>   * of SKIPs.<a name="line.783"></a>
-<span class="sourceLineNo">784</span>   * @param cell current cell<a name="line.784"></a>
-<span class="sourceLineNo">785</span>   * @return true means skip to next row, false means not<a name="line.785"></a>
-<span class="sourceLineNo">786</span>   */<a name="line.786"></a>
-<span class="sourceLineNo">787</span>  @VisibleForTesting<a name="line.787"></a>
-<span class="sourceLineNo">788</span>  protected boolean trySkipToNextRow(Cell cell) throws IOException {<a name="line.788"></a>
-<span class="sourceLineNo">789</span>    Cell nextCell = null;<a name="line.789"></a>
-<span class="sourceLineNo">790</span>    do {<a name="line.790"></a>
-<span class="sourceLineNo">791</span>      Cell nextIndexedKey = getNextIndexedKey();<a name="line.791"></a>
-<span class="sourceLineNo">792</span>      if (nextIndexedKey != null &amp;&amp; nextIndexedKey != KeyValueScanner.NO_NEXT_INDEXED_KEY<a name="line.792"></a>
-<span class="sourceLineNo">793</span>          &amp;&amp; matcher.compareKeyForNextRow(nextIndexedKey, cell) &gt;= 0) {<a name="line.793"></a>
-<span class="sourceLineNo">794</span>        this.heap.next();<a name="line.794"></a>
-<span class="sourceLineNo">795</span>        ++kvsScanned;<a name="line.795"></a>
-<span class="sourceLineNo">796</span>      } else {<a name="line.796"></a>
-<span class="sourceLineNo">797</span>        return false;<a name="line.797"></a>
-<span class="sourceLineNo">798</span>      }<a name="line.798"></a>
-<span class="sourceLineNo">799</span>    } while ((nextCell = this.heap.peek()) != null &amp;&amp; CellUtil.matchingRows(cell, nextCell));<a name="line.799"></a>
-<span class="sourceLineNo">800</span>    return true;<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>  /**<a name="line.803"></a>
-<span class="sourceLineNo">804</span>   * See {@link org.apache.hadoop.hbase.regionserver.StoreScanner#trySkipToNextRow(Cell)}<a name="line.804"></a>
-<span class="sourceLineNo">805</span>   * @param cell current cell<a name="line.805"></a>
-<span class="sourceLineNo">806</span>   * @return true means skip to next column, false means not<a name="line.806"></a>
-<span class="sourceLineNo">807</span>   */<a name="line.807"></a>
-<span class="sourceLineNo">808</span>  @VisibleForTesting<a name="line.808"></a>
-<span class="sourceLineNo">809</span>  protected boolean trySkipToNextColumn(Cell cell) throws IOException {<a name="line.809"></a>
-<span class="sourceLineNo">810</span>    Cell nextCell = null;<a name="line.810"></a>
-<span class="sourceLineNo">811</span>    do {<a name="line.811"></a>
-<span class="sourceLineNo">812</span>      Cell nextIndexedKey = getNextIndexedKey();<a name="line.812"></a>
-<span class="sourceLineNo">813</span>      if (nextIndexedKey != null &amp;&amp; nextIndexedKey != KeyValueScanner.NO_NEXT_INDEXED_KEY<a name="line.813"></a>
-<span class="sourceLineNo">814</span>          &amp;&amp; matcher.compareKeyForNextColumn(nextIndexedKey, cell) &gt;= 0) {<a name="line.814"></a>
-<span class="sourceLineNo">815</span>        this.heap.next();<a name="line.815"></a>
-<span class="sourceLineNo">816</span>        ++kvsScanned;<a name="line.816"></a>
-<span class="sourceLineNo">817</span>      } else {<a name="line.817"></a>
-<span class="sourceLineNo">818</span>        return false;<a name="line.818"></a>
-<span class="sourceLineNo">819</span>      }<a name="line.819"></a>
-<span class="sourceLineNo">820</span>    } while ((nextCell = this.heap.peek()) != null &amp;&amp; CellUtil.matchingRowColumn(cell, nextCell));<a name="line.820"></a>
-<span class="sourceLineNo">821</span>    // We need this check because it may happen that the new scanner that we get<a name="line.821"></a>
-<span class="sourceLineNo">822</span>    // during heap.next() is requiring reseek due of fake KV previously generated for<a name="line.822"></a>
-<span class="sourceLineNo">823</span>    // ROWCOL bloom filter optimization. See HBASE-19863 for more details<a name="line.823"></a>
-<span class="sourceLineNo">824</span>    if (nextCell != null &amp;&amp; matcher.compareKeyForNextColumn(nextCell, cell) &lt; 0) {<a name="line.824"></a>
-<span class="sourceLineNo">825</span>      return false;<a name="line.825"></a>
-<span class="sourceLineNo">826</span>    }<a name="line.826"></a>
-<span class="sourceLineNo">827</span>    return true;<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">830</span>  @Override<a name="line.830"></a>
-<span class="sourceLineNo">831</span>  public long getReadPoint() {<a name="line.831"></a>
-<span class="sourceLineNo">832</span>    return this.readPt;<a name="line.832"></a>
-<span class="sourceLineNo">833</span>  }<a name="line.833"></a>
-<span class="sourceLineNo">834</span><a name="line.834"></a>
-<span class="sourceLineNo">835</span>  private static void clearAndClose(List&lt;KeyValueScanner&gt; scanners) {<a name="line.835"></a>
-<span class="sourceLineNo">836</span>    for (KeyValueScanner s : scanners) {<a name="line.836"></a>
-<span class="sourceLineNo">837</span>      s.close();<a name="line.837"></a>
-<span class="sourceLineNo">838</span>    }<a name="line.838"></a>
-<span class="sourceLineNo">839</span>    scanners.clear();<a name="line.839"></a>
-<span class="sourceLineNo">840</span>  }<a name="line.840"></a>
-<span class="sourceLineNo">841</span><a name="line.841"></a>
-<span class="sourceLineNo">842</span>  // Implementation of ChangedReadersObserver<a name="line.842"></a>
-<span class="sourceLineNo">843</span>  @Override<a name="line.843"></a>
-<span class="sourceLineNo">844</span>  public void updateReaders(List&lt;HStoreFile&gt; sfs, List&lt;KeyValueScanner&gt; memStoreScanners)<a name="line.844"></a>
-<span class="sourceLineNo">845</span>      throws IOException {<a name="line.845"></a>
-<span class="sourceLineNo">846</span>    if (CollectionUtils.isEmpty(sfs) &amp;&amp; CollectionUtils.isEmpty(memStoreScanners)) {<a name="line.846"></a>
-<span class="sourceLineNo">847</span>      return;<a name="line.847"></a>
-<span class="sourceLineNo">848</span>    }<a name="line.848"></a>
-<span class="sourceLineNo">849</span>    flushLock.lock();<a name="line.849"></a>
-<span class="sourceLineNo">850</span>    try {<a name="line.850"></a>
-<span class="sourceLineNo">851</span>      flushed = true;<a name="line.851"></a>
-<span class="sourceLineNo">852</span>      final boolean isCompaction = false;<a name="line.852"></a>
-<span class="sourceLineNo">853</span>      boolean usePread = get || scanUsePread;<a name="line.853"></a>
-<span class="sourceLineNo">854</span>      // SEE HBASE-19468 where the flushed files are getting compacted even before a scanner<a name="line.854"></a>
-<span class="sourceLineNo">855</span>      // calls next(). So its better we create scanners here rather than next() call. Ensure<a name="line.855"></a>
-<span class="sourceLineNo">856</span>      // these scanners are properly closed() whether or not the scan is completed successfully<a name="line.856"></a>
-<span class="sourceLineNo">857</span>      // Eagerly creating scanners so that we have the ref counting ticking on the newly created<a name="line.857"></a>
-<span class="sourceLineNo">858</span>      // store files. In case of stream scanners this eager creation does not induce performance<a name="line.858"></a>
-<span class="sourceLineNo">859</span>      // penalty because in scans (that uses stream scanners) the next() call is bound to happen.<a name="line.859"></a>
-<span class="sourceLineNo">860</span>      List&lt;KeyValueScanner&gt; scanners = store.getScanners(sfs, cacheBlocks, get, usePread,<a name="line.860"></a>
-<span class="sourceLineNo">861</span>        isCompaction, matcher, scan.getStartRow(), scan.getStopRow(), this.readPt, false);<a name="line.861"></a>
-<span class="sourceLineNo">862</span>      flushedstoreFileScanners.addAll(scanners);<a name="line.862"></a>
-<span class="sourceLineNo">863</span>      if (!CollectionUtils.isEmpty(memStoreScanners)) {<a name="line.863"></a>
-<span class="sourceLineNo">864</span>        clearAndClose(memStoreScannersAfterFlush);<a name="line.864"></a>
-<span class="sourceLineNo">865</span>        memStoreScannersAfterFlush.addAll(memStoreScanners);<a name="line.865"></a>
-<span class="sourceLineNo">866</span>      }<a name="line.866"></a>
-<span class="sourceLineNo">867</span>    } finally {<a name="line.867"></a>
-<span class="sourceLineNo">868</span>      flushLock.unlock();<a name="line.868"></a>
-<span class="sourceLineNo">869</span>    }<a name="line.869"></a>
-<span class="sourceLineNo">870</span>    // Let the next() call handle re-creating and seeking<a name="line.870"></a>
-<span class="sourceLineNo">871</span>  }<a name="line.871"></a>
-<span class="sourceLineNo">872</span><a name="line.872"></a>
-<span class="sourceLineNo">873</span>  /**<a name="line.873"></a>
-<span class="sourceLineNo">874</span>   * @return if top of heap has changed (and KeyValueHeap has to try the next KV)<a name="line.874"></a>
-<span class="sourceLineNo">875</span>   */<a name="line.875"></a>
-<span class="sourceLineNo">876</span>  protected final boolean reopenAfterFlush() throws IOException {<a name="line.876"></a>
-<span class="sourceLineNo">877</span>    // here we can make sure that we have a Store instance so no null check on store.<a name="line.877"></a>
-<span class="sourceLineNo">878</span>    Cell lastTop = heap.peek();<a name="line.878"></a>
-<span class="sourceLineNo">879</span>    // When we have the scan object, should we not pass it to getScanners() to get a limited set of<a name="line.879"></a>
-<span class="sourceLineNo">880</span>    // scanners? We did so in the constructor and we could have done it now by storing the scan<a name="line.880"></a>
-<span class="sourceLineNo">881</span>    // object from the constructor<a name="line.881"></a>
-<span class="sourceLineNo">882</span>    List&lt;KeyValueScanner&gt; scanners;<a name="line.882"></a>
-<span class="sourceLineNo">883</span>    flushLock.lock();<a name="line.883"></a>
-<span class="sourceLineNo">884</span>    try {<a name="line.884"></a>
-<span class="sourceLineNo">885</span>      List&lt;KeyValueScanner&gt; allScanners =<a name="line.885"></a>
-<span class="sourceLineNo">886</span>          new ArrayList&lt;&gt;(flushedstoreFileScanners.size() + memStoreScannersAfterFlush.size());<a name="line.886"></a>
-<span class="sourceLineNo">887</span>      allScanners.addAll(flushedstoreFileScanners);<a name="line.887"></a>
-<span class="sourceLineNo">888</span>      allScanners.addAll(memStoreScannersAfterFlush);<a name="line.888"></a>
-<span class="sourceLineNo">889</span>      scanners = selectScannersFrom(store, allScanners);<a name="line.889"></a>
-<span class="sourceLineNo">890</span>      // Clear the current set of flushed store files scanners so that they don't get added again<a name="line.890"></a>
-<span class="sourceLineNo">891</span>      flushedstoreFileScanners.clear();<a name="line.891"></a>
-<span class="sourceLineNo">892</span>      memStoreScannersAfterFlush.clear();<a name="line.892"></a>
-<span class="sourceLineNo">893</span>    } finally {<a name="line.893"></a>
-<span class="sourceLineNo">894</span>      flushLock.unlock();<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>    // Seek the new scanners to the last key<a name="line.897"></a>
-<span class="sourceLineNo">898</span>    seekScanners(scanners, lastTop, false, parallelSeekEnabled);<a name="line.898"></a>
-<span class="sourceLineNo">899</span>    // remove the older memstore scanner<a name="line.899"></a>
-<span class="sourceLineNo">900</span>    for (int i = currentScanners.size() - 1; i &gt;=0; i--) {<a name="line.900"></a>
-<span class="sourceLineNo">901</span>      if (!currentScanners.get(i).isFileScanner()) {<a name="line.901"></a>
-<span class="sourceLineNo">902</span>        scannersForDelayedClose.add(currentScanners.remove(i));<a name="line.902"></a>
-<span class="sourceLineNo">903</span>      } else {<a name="line.903"></a>
-<span class="sourceLineNo">904</span>        // we add the memstore scanner to the end of currentScanners<a name="line.904"></a>
-<span class="sourceLineNo">905</span>        break;<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>    // add the newly created scanners on the flushed files and the current active memstore scanner<a name="line.908"></a>
-<span class="sourceLineNo">909</span>    addCurrentScanners(scanners);<a name="line.909"></a>
-<span class="sourceLineNo">910</span>    // Combine all seeked scanners with a heap<a name="line.910"></a>
-<span class="sourceLineNo">911</span>    resetKVHeap(this.currentScanners, store.getComparator());<a name="line.911"></a>
-<span class="sourceLineNo">912</span>    resetQueryMatcher(lastTop);<a name="line.912"></a>
-<span class="sourceLineNo">913</span>    if (heap.peek() == null || store.getComparator().compareRows(lastTop, this.heap.peek()) != 0) {<a name="line.913"></a>
-<span class="sourceLineNo">914</span>      LOG.info("Storescanner.peek() is changed where before = " + lastTop.toString() +<a name="line.914"></a>
-<span class="sourceLineNo">915</span>          ",and after = " + heap.peek());<a name="line.915"></a>
-<span class="sourceLineNo">916</span>      topChanged = true;<a name="line.916"></a>
-<span class="sourceLineNo">917</span>    } else {<a name="line.917"></a>
-<span class="sourceLineNo">918</span>      topChanged = false;<a name="line.918"></a>
-<span class="sourceLineNo">919</span>    }<a name="line.919"></a>
-<span class="sourceLineNo">920</span>    return topChanged;<a name="line.920"></a>
-<span class="sourceLineNo">921</span>  }<a name="line.921"></a>
-<span class="sourceLineNo">922</span><a name="line.922"></a>
-<span class="sourceLineNo">923</span>  private void resetQueryMatcher(Cell lastTopKey) {<a name="line.923"></a>
-<span class="sourceLineNo">924</span>    // Reset the state of the Query Matcher and set to top row.<a name="line.924"></a>
-<span class="sourceLineNo">925</span>    // Only reset and call setRow if the row changes; avoids confusing the<a name="line.925"></a>
-<span class="sourceLineNo">926</span>    // query matcher if scanning intra-row.<a name="line.926"></a>
-<span class="sourceLineNo">927</span>    Cell cell = heap.peek();<a name="line.927"></a>
-<span class="sourceLineNo">928</span>    if (cell == null) {<a name="line.928"></a>
-<span class="sourceLineNo">929</span>      cell = lastTopKey;<a name="line.929"></a>
-<span class="sourceLineNo">930</span>    }<a name="line.930"></a>
-<span class="sourceLineNo">931</span>    if ((matcher.currentRow() == null) || !CellUtil.matchingRows(cell, matcher.currentRow())) {<a name="line.931"></a>
-<span class="sourceLineNo">932</span>      this.countPerRow = 0;<a name="line.932"></a>
-<span class="sourceLineNo">933</span>      // The setToNewRow will call reset internally<a name="line.933"></a>
-<span class="sourceLineNo">934</span>      matcher.setToNewRow(cell);<a name="line.934"></a>
-<span class="sourceLineNo">935</span>    }<a name="line.935"></a>
+<span class="sourceLineNo">664</span>        case SEEK_NEXT_ROW:<a name="line.664"></a>
+<span class="sourceLineNo">665</span>          // This is just a relatively simple end of scan fix, to short-cut end<a name="line.665"></a>
+<span class="sourceLineNo">666</span>          // us if there is an endKey in the scan.<a name="line.666"></a>
+<span class="sourceLineNo">667</span>          if (!matcher.moreRowsMayExistAfter(cell)) {<a name="line.667"></a>
+<span class="sourceLineNo">668</span>            close(false);// Do all cleanup except heap.close()<a name="line.668"></a>
+<span class="sourceLineNo">669</span>            return scannerContext.setScannerState(NextState.NO_MORE_VALUES).hasMoreValues();<a name="line.669"></a>
+<span class="sourceLineNo">670</span>          }<a name="line.670"></a>
+<span class="sourceLineNo">671</span>          matcher.clearCurrentRow();<a name="line.671"></a>
+<span class="sourceLineNo">672</span>          seekOrSkipToNextRow(cell);<a name="line.672"></a>
+<span class="sourceLineNo">673</span>          NextState stateAfterSeekNextRow = needToReturn(outResult);<a name="line.673"></a>
+<span class="sourceLineNo">674</span>          if (stateAfterSeekNextRow != null) {<a name="line.674"></a>
+<span class="sourceLineNo">675</span>            return scannerContext.setScannerState(stateAfterSeekNextRow).hasMoreValues();<a name="line.675"></a>
+<span class="sourceLineNo">676</span>          }<a name="line.676"></a>
+<span class="sourceLineNo">677</span>          break;<a name="line.677"></a>
+<span class="sourceLineNo">678</span><a name="line.678"></a>
+<span class="sourceLineNo">679</span>        case SEEK_NEXT_COL:<a name="line.679"></a>
+<span class="sourceLineNo">680</span>          seekOrSkipToNextColumn(cell);<a name="line.680"></a>
+<span class="sourceLineNo">681</span>          NextState stateAfterSeekNextColumn = needToReturn(outResult);<a name="line.681"></a>
+<span class="sourceLineNo">682</span>          if (stateAfterSeekNextColumn != null) {<a name="line.682"></a>
+<span class="sourceLineNo">683</span>            return scannerContext.setScannerState(stateAfterSeekNextColumn).hasMoreValues();<a name="line.683"></a>
+<span class="sourceLineNo">684</span>          }<a name="line.684"></a>
+<span class="sourceLineNo">685</span>          break;<a name="line.685"></a>
+<span class="sourceLineNo">686</span><a name="line.686"></a>
+<span class="sourceLineNo">687</span>        case SKIP:<a name="line.687"></a>
+<span class="sourceLineNo">688</span>          this.heap.next();<a name="line.688"></a>
+<span class="sourceLineNo">689</span>          break;<a name="line.689"></a>
+<span class="sourceLineNo">690</span><a name="line.690"></a>
+<span class="sourceLineNo">691</span>        case SEEK_NEXT_USING_HINT:<a name="line.691"></a>
+<span class="sourceLineNo">692</span>          Cell nextKV = matcher.getNextKeyHint(cell);<a name="line.692"></a>
+<span class="sourceLineNo">693</span>          if (nextKV != null) {<a name="line.693"></a>
+<span class="sourceLineNo">694</span>            seekAsDirection(nextKV);<a name="line.694"></a>
+<span class="sourceLineNo">695</span>            NextState stateAfterSeekByHint = needToReturn(outResult);<a name="line.695"></a>
+<span class="sourceLineNo">696</span>            if (stateAfterSeekByHint != null) {<a name="line.696"></a>
+<span class="sourceLineNo">697</span>              return scannerContext.setScannerState(stateAfterSeekByHint).hasMoreValues();<a name="line.697"></a>
+<span class="sourceLineNo">698</span>            }<a name="line.698"></a>
+<span class="sourceLineNo">699</span>          } else {<a name="line.699"></a>
+<span class="sourceLineNo">700</span>            heap.next();<a name="line.700"></a>
+<span class="sourceLineNo">701</span>          }<a name="line.701"></a>
+<span class="sourceLineNo">702</span>          break;<a name="line.702"></a>
+<span class="sourceLineNo">703</span><a name="line.703"></a>
+<span class="sourceLineNo">704</span>        default:<a name="line.704"></a>
+<span class="sourceLineNo">705</span>          throw new RuntimeException("UNEXPECTED");<a name="line.705"></a>
+<span class="sourceLineNo">706</span>      }<a name="line.706"></a>
+<span class="sourceLineNo">707</span>    } while ((cell = this.heap.peek()) != null);<a name="line.707"></a>
+<span class="sourceLineNo">708</span><a name="line.708"></a>
+<span class="sourceLineNo">709</span>    if (count &gt; 0) {<a name="line.709"></a>
+<span class="sourceLineNo">710</span>      return scannerContext.setScannerState(NextState.MORE_VALUES).hasMoreValues();<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>    // No more keys<a name="line.713"></a>
+<span class="sourceLineNo">714</span>    close(false);// Do all cleanup except heap.close()<a name="line.714"></a>
+<span class="sourceLineNo">715</span>    return scannerContext.setScannerState(NextState.NO_MORE_VALUES).hasMoreValues();<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>  /**<a name="line.718"></a>
+<span class="sourceLineNo">719</span>   * If the top cell won't be flushed into disk, the new top cell may be<a name="line.719"></a>
+<span class="sourceLineNo">720</span>   * changed after #reopenAfterFlush. Because the older top cell only exist<a name="line.720"></a>
+<span class="sourceLineNo">721</span>   * in the memstore scanner but the memstore scanner is replaced by hfile<a name="line.721"></a>
+<span class="sourceLineNo">722</span>   * scanner after #reopenAfterFlush. If the row of top cell is changed,<a name="line.722"></a>
+<span class="sourceLineNo">723</span>   * we should return the current cells. Otherwise, we may return<a name="line.723"></a>
+<span class="sourceLineNo">724</span>   * the cells across different rows.<a name="line.724"></a>
+<span class="sourceLineNo">725</span>   * @param outResult the cells which are visible for user scan<a name="line.725"></a>
+<span class="sourceLineNo">726</span>   * @return null is the top cell doesn't change. Otherwise, the NextState<a name="line.726"></a>
+<span class="sourceLineNo">727</span>   *         to return<a name="line.727"></a>
+<span class="sourceLineNo">728</span>   */<a name="line.728"></a>
+<span class="sourceLineNo">729</span>  private NextState needToReturn(List&lt;Cell&gt; outResult) {<a name="line.729"></a>
+<span class="sourceLineNo">730</span>    if (!outResult.isEmpty() &amp;&amp; topChanged) {<a name="line.730"></a>
+<span class="sourceLineNo">731</span>      return heap.peek() == null ? NextState.NO_MORE_VALUES : NextState.MORE_VALUES;<a name="line.731"></a>
+<span class="sourceLineNo">732</span>    }<a name="line.732"></a>
+<span class="sourceLineNo">733</span>    return null;<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>  private void seekOrSkipToNextRow(Cell cell) throws IOException {<a name="line.736"></a>
+<span class="sourceLineNo">737</span>    // If it is a Get Scan, then we know that we are done with this row; there are no more<a name="line.737"></a>
+<span class="sourceLineNo">738</span>    // rows beyond the current one: don't try to optimize.<a name="line.738"></a>
+<span class="sourceLineNo">739</span>    if (!get) {<a name="line.739"></a>
+<span class="sourceLineNo">740</span>      if (trySkipToNextRow(cell)) {<a name="line.740"></a>
+<span class="sourceLineNo">741</span>        return;<a name="line.741"></a>
+<span class="sourceLineNo">742</span>      }<a name="line.742"></a>
+<span class="sourceLineNo">743</span>    }<a name="line.743"></a>
+<span class="sourceLineNo">744</span>    seekToNextRow(cell);<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>  private void seekOrSkipToNextColumn(Cell cell) throws IOException {<a name="line.747"></a>
+<span class="sourceLineNo">748</span>    if (!trySkipToNextColumn(cell)) {<a name="line.748"></a>
+<span class="sourceLineNo">749</span>      seekAsDirection(matcher.getKeyForNextColumn(cell));<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>  /**<a name="line.753"></a>
+<span class="sourceLineNo">754</span>   * See if we should actually SEEK or rather just SKIP to the next Cell (see HBASE-13109).<a name="line.754"></a>
+<span class="sourceLineNo">755</span>   * ScanQueryMatcher may issue SEEK hints, such as seek to next column, next row,<a name="line.755"></a>
+<span class="sourceLineNo">756</span>   * or seek to an arbitrary seek key. This method decides whether a seek is the most efficient<a name="line.756"></a>
+<span class="sourceLineNo">757</span>   * _actual_ way to get us to the requested cell (SEEKs are more expensive than SKIP, SKIP,<a name="line.757"></a>
+<span class="sourceLineNo">758</span>   * SKIP inside the current, loaded block).<a name="line.758"></a>
+<span class="sourceLineNo">759</span>   * It does this by looking at the next indexed key of the current HFile. This key<a name="line.759"></a>
+<span class="sourceLineNo">760</span>   * is then compared with the _SEEK_ key, where a SEEK key is an artificial 'last possible key<a name="line.760"></a>
+<span class="sourceLineNo">761</span>   * on the row' (only in here, we avoid actually creating a SEEK key; in the compare we work with<a name="line.761"></a>
+<span class="sourceLineNo">762</span>   * the current Cell but compare as though it were a seek key; see down in<a name="line.762"></a>
+<span class="sourceLineNo">763</span>   * matcher.compareKeyForNextRow, etc). If the compare gets us onto the<a name="line.763"></a>
+<span class="sourceLineNo">764</span>   * next block we *_SEEK, otherwise we just SKIP to the next requested cell.<a name="line.764"></a>
+<span class="sourceLineNo">765</span>   *<a name="line.765"></a>
+<span class="sourceLineNo">766</span>   * &lt;p&gt;Other notes:<a name="line.766"></a>
+<span class="sourceLineNo">767</span>   * &lt;ul&gt;<a name="line.767"></a>
+<span class="sourceLineNo">768</span>   * &lt;li&gt;Rows can straddle block boundaries&lt;/li&gt;<a name="line.768"></a>
+<span class="sourceLineNo">769</span>   * &lt;li&gt;Versions of columns can straddle block boundaries (i.e. column C1 at T1 might be in a<a name="line.769"></a>
+<span class="sourceLineNo">770</span>   * different block than column C1 at T2)&lt;/li&gt;<a name="line.770"></a>
+<span class="sourceLineNo">771</span>   * &lt;li&gt;We want to SKIP if the chance is high that we'll find the desired Cell after a<a name="line.771"></a>
+<span class="sourceLineNo">772</span>   * few SKIPs...&lt;/li&gt;<a name="line.772"></a>
+<span class="sourceLineNo">773</span>   * &lt;li&gt;We want to SEEK when the chance is high that we'll be able to seek<a name="line.773"></a>
+<span class="sourceLineNo">774</span>   * past many Cells, especially if we know we need to go to the next block.&lt;/li&gt;<a name="line.774"></a>
+<span class="sourceLineNo">775</span>   * &lt;/ul&gt;<a name="line.775"></a>
+<span class="sourceLineNo">776</span>   * &lt;p&gt;A good proxy (best effort) to determine whether SKIP is better than SEEK is whether<a name="line.776"></a>
+<span class="sourceLineNo">777</span>   * we'll likely end up seeking to the next block (or past the next block) to get our next column.<a name="line.777"></a>
+<span class="sourceLineNo">778</span>   * Example:<a name="line.778"></a>
+<span class="sourceLineNo">779</span>   * &lt;pre&gt;<a name="line.779"></a>
+<span class="sourceLineNo">780</span>   * |    BLOCK 1              |     BLOCK 2                   |<a name="line.780"></a>
+<span class="sourceLineNo">781</span>   * |  r1/c1, r1/c2, r1/c3    |    r1/c4, r1/c5, r2/c1        |<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>   *                           Next Index Key   SEEK_NEXT_ROW (before r2/c1)<a name="line.784"></a>
+<span class="sourceLineNo">785</span>   *<a name="line.785"></a>
+<span class="sourceLineNo">786</span>   *<a name="line.786"></a>
+<span class="sourceLineNo">787</span>   * |    BLOCK 1                       |     BLOCK 2                      |<a name="line.787"></a>
+<span class="sourceLineNo">788</span>   * |  r1/c1/t5, r1/c1/t4, r1/c1/t3    |    r1/c1/t2, r1/c1/T1, r1/c2/T3  |<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>   *                                    Next Index Key        SEEK_NEXT_COL<a name="line.791"></a>
+<span class="sourceLineNo">792</span>   * &lt;/pre&gt;<a name="line.792"></a>
+<span class="sourceLineNo">793</span>   * Now imagine we want columns c1 and c3 (see first diagram above), the 'Next Index Key' of r1/c4<a name="line.793"></a>
+<span class="sourceLineNo">794</span>   * is &gt; r1/c3 so we should seek to get to the c1 on the next row, r2. In second case, say we only<a name="line.794"></a>
+<span class="sourceLineNo">795</span>   * want one version of c1, after we have it, a SEEK_COL will be issued to get to c2. Looking at<a name="line.795"></a>
+<span class="sourceLineNo">796</span>   * the 'Next Index Key', it would land us in the next block, so we should SEEK. In other scenarios<a name="line.796"></a>
+<span class="sourceLineNo">797</span>   * where the SEEK will not land us in the next block, it is very likely better to issues a series<a name="line.797"></a>
+<span class="sourceLineNo">798</span>   * of SKIPs.<a name="line.798"></a>
+<span class="sourceLineNo">799</span>   * @param cell current cell<a name="line.799"></a>
+<span class="sourceLineNo">800</span>   * @return true means skip to next row, false means not<a name="line.800"></a>
+<span class="sourceLineNo">801</span>   */<a name="line.801"></a>
+<span class="sourceLineNo">802</span>  @VisibleForTesting<a name="line.802"></a>
+<span class="sourceLineNo">803</span>  protected boolean trySkipToNextRow(Cell cell) throws IOException {<a name="line.803"></a>
+<span class="sourceLineNo">804</span>    Cell nextCell = null;<a name="line.804"></a>
+<span class="sourceLineNo">805</span>    do {<a name="line.805"></a>
+<span class="sourceLineNo">806</span>      Cell nextIndexedKey = getNextIndexedKey();<a name="line.806"></a>
+<span class="sourceLineNo">807</span>      if (nextIndexedKey != null &amp;&amp; nextIndexedKey != KeyValueScanner.NO_NEXT_INDEXED_KEY<a name="line.807"></a>
+<span class="sourceLineNo">808</span>          &amp;&amp; matcher.compareKeyForNextRow(nextIndexedKey, cell) &gt;= 0) {<a name="line.808"></a>
+<span class="sourceLineNo">809</span>        this.heap.next();<a name="line.809"></a>
+<span class="sourceLineNo">810</span>        ++kvsScanned;<a name="line.810"></a>
+<span class="sourceLineNo">811</span>      } else {<a name="line.811"></a>
+<span class="sourceLineNo">812</span>        return false;<a name="line.812"></a>
+<span class="sourceLineNo">813</span>      }<a name="line.813"></a>
+<span class="sourceLineNo">814</span>    } while ((nextCell = this.heap.peek()) != null &amp;&amp; CellUtil.matchingRows(cell, nextCell));<a name="line.814"></a>
+<span class="sourceLineNo">815</span>    return true;<a name="line.815"></a>
+<span class="sourceLineNo">816</span>  }<a name="line.816"></a>
+<span class="sourceLineNo">817</span><a name="line.817"></a>
+<span class="sourceLineNo">818</span>  /**<a name="line.818"></a>
+<span class="sourceLineNo">819</span>   * See {@link org.apache.hadoop.hbase.regionserver.StoreScanner#trySkipToNextRow(Cell)}<a name="line.819"></a>
+<span class="sourceLineNo">820</span>   * @param cell current cell<a name="line.820"></a>
+<span class="sourceLineNo">821</span>   * @return true means skip to next column, false means not<a name="line.821"></a>
+<span class="sourceLineNo">822</span>   */<a name="line.822"></a>
+<span class="sourceLineNo">823</span>  @VisibleForTesting<a name="line.823"></a>
+<span class="sourceLineNo">824</span>  protected boolean trySkipToNextColumn(Cell cell) throws IOException {<a name="line.824"></a>
+<span class="sourceLineNo">825</span>    Cell nextCell = null;<a name="line.825"></a>
+<span class="sourceLineNo">826</span>    do {<a name="line.826"></a>
+<span class="sourceLineNo">827</span>      Cell nextIndexedKey = getNextIndexedKey();<a name="line.827"></a>
+<span class="sourceLineNo">828</span>      if (nextIndexedKey != null &amp;&amp; nextIndexedKey != KeyValueScanner.NO_NEXT_INDEXED_KEY<a name="line.828"></a>
+<span class="sourceLineNo">829</span>          &amp;&amp; matcher.compareKeyForNextColumn(nextIndexedKey, cell) &gt;= 0) {<a name="line.829"></a>
+<span class="sourceLineNo">830</span>        this.heap.next();<a name="line.830"></a>
+<span class="sourceLineNo">831</span>        ++kvsScanned;<a name="line.831"></a>
+<span class="sourceLineNo">832</span>      } else {<a name="line.832"></a>
+<span class="sourceLineNo">833</span>        return false;<a name="line.833"></a>
+<span class="sourceLineNo">834</span>      }<a name="line.834"></a>
+<span class="sourceLineNo">835</span>    } while ((nextCell = this.heap.peek()) != null &amp;&amp; CellUtil.matchingRowColumn(cell, nextCell));<a name="line.835"></a>
+<span class="sourceLineNo">836</span>    // We need this check because it may happen that the new scanner that we get<a name="line.836"></a>
+<span class="sourceLineNo">837</span>    // during heap.next() is requiring reseek due of fake KV previously generated for<a name="line.837"></a>
+<span class="sourceLineNo">838</span>    // ROWCOL bloom filter optimization. See HBASE-19863 for more details<a name="line.838"></a>
+<span class="sourceLineNo">839</span>    if (nextCell != null &amp;&amp; matcher.compareKeyForNextColumn(nextCell, cell) &lt; 0) {<a name="line.839"></a>
+<span class="sourceLineNo">840</span>      return false;<a name="line.840"></a>
+<span class="sourceLineNo">841</span>    }<a name="line.841"></a>
+<span class="sourceLineNo">842</span>    return true;<a name="line.842"></a>
+<span class="sourceLineNo">843</span>  }<a name="line.843"></a>
+<span class="sourceLineNo">844</span><a name="line.844"></a>
+<span class="sourceLineNo">845</span>  @Override<a name="line.845"></a>
+<span class="sourceLineNo">846</span>  public long getReadPoint() {<a name="line.846"></a>
+<span class="sourceLineNo">847</span>    return this.readPt;<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>  private static void clearAndClose(List&lt;KeyValueScanner&gt; scanners) {<a name="line.850"></a>
+<span class="sourceLineNo">851</span>    for (KeyValueScanner s : scanners) {<a name="line.851"></a>
+<span class="sourceLineNo">852</span>      s.close();<a name="line.852"></a>
+<span class="sourceLineNo">853</span>    }<a name="line.853"></a>
+<span class="sourceLineNo">854</span>    scanners.clear();<a name="line.854"></a>
+<span class="sourceLineNo">855</span>  }<a name="line.855"></a>
+<span class="sourceLineNo">856</span><a name="line.856"></a>
+<span class="sourceLineNo">857</span>  // Implementation of ChangedReadersObserver<a name="line.857"></a>
+<span class="sourceLineNo">858</span>  @Override<a name="line.858"></a>
+<span class="sourceLineNo">859</span>  public void updateReaders(List&lt;HStoreFile&gt; sfs, List&lt;KeyValueScanner&gt; memStoreScanners)<a name="line.859"></a>
+<span class="sourceLineNo">860</span>      throws IOException {<a name="line.860"></a>
+<span class="sourceLineNo">861</span>    if (CollectionUtils.isEmpty(sfs) &amp;&amp; CollectionUtils.isEmpty(memStoreScanners)) {<a name="line.861"></a>
+<span class="sourceLineNo">862</span>      return;<a name="line.862"></a>
+<span class="sourceLineNo">863</span>    }<a name="line.863"></a>
+<span class="sourceLineNo">864</span>    flushLock.lock();<a name="line.864"></a>
+<span class="sourceLineNo">865</span>    try {<a name="line.865"></a>
+<span class="sourceLineNo">866</span>      flushed = true;<a name="line.866"></a>
+<span class="sourceLineNo">867</span>      final boolean isCompaction = false;<a name="line.867"></a>
+<span class="sourceLineNo">868</span>      boolean usePread = get || scanUsePread;<a name="line.868"></a>
+<span class="sourceLineNo">869</span>      // SEE HBASE-19468 where the flushed files are getting compacted even before a scanner<a name="line.869"></a>
+<span class="sourceLineNo">870</span>      // calls next(). So its better we create scanners here rather than next() call. Ensure<a name="line.870"></a>
+<span class="sourceLineNo">871</span>      // these scanners are properly closed() whether or not the scan is completed successfully<a name="line.871"></a>
+<span class="sourceLineNo">872</span>      // Eagerly creating scanners so that we have the ref counting ticking on the newly created<a name="line.872"></a>
+<span class="sourceLineNo">873</span>      // store files. In case of stream scanners this eager creation does not induce performance<a name="line.873"></a>
+<span class="sourceLineNo">874</span>      // penalty because in scans (that uses stream scanners) the next() call is bound to happen.<a name="line.874"></a>
+<span class="sourceLineNo">875</span>      List&lt;KeyValueScanner&gt; scanners = store.getScanners(sfs, cacheBlocks, get, usePread,<a name="line.875"></a>
+<span class="sourceLineNo">876</span>        isCompaction, matcher, scan.getStartRow(), scan.getStopRow(), this.readPt, false);<a name="line.876"></a>
+<span class="sourceLineNo">877</span>      flushedstoreFileScanners.addAll(scanners);<a name="line.877"></a>
+<span class="sourceLineNo">878</span>      if (!CollectionUtils.isEmpty(memStoreScanners)) {<a name="line.878"></a>
+<span class="sourceLineNo">879</span>        clearAndClose(memStoreScannersAfterFlush);<a name="line.879"></a>
+<span class="sourceLineNo">880</span>        memStoreScannersAfterFlush.addAll(memStoreScanners);<a name="line.880"></a>
+<span class="sourceLineNo">881</span>      }<a name="line.881"></a>
+<span class="sourceLineNo">882</span>    } finally {<a name="line.882"></a>
+<span class="sourceLineNo">883</span>      flushLock.unlock();<a name="line.883"></a>
+<span class="sourceLineNo">884</span>    }<a name="line.884"></a>
+<span class="sourceLineNo">885</span>    // Let the next() call handle re-creating and seeking<a name="line.885"></a>
+<span class="sourceLineNo">886</span>  }<a name="line.886"></a>
+<span class="sourceLineNo">887</span><a name="line.887"></a>
+<span class="sourceLineNo">888</span>  /**<a name="line.888"></a>
+<span class="sourceLineNo">889</span>   * @return if top of heap has changed (and KeyValueHeap has to try the next KV)<a name="line.889"></a>
+<span class="sourceLineNo">890</span>   */<a name="line.890"></a>
+<span class="sourceLineNo">891</span>  protected final boolean reopenAfterFlush() throws IOException {<a name="line.891"></a>
+<span class="sourceLineNo">892</span>    // here we can make sure that we have a Store instance so no null check on store.<a name="line.892"></a>
+<span class="sourceLineNo">893</span>    Cell lastTop = heap.peek();<a name="line.893"></a>
+<span class="sourceLineNo">894</span>    // When we have the scan object, should we not pass it to getScanners() to get a limited set of<a name="line.894"></a>
+<span class="sourceLineNo">895</span>    // scanners? We did so in the constructor and we could have done it now by storing the scan<a name="line.895"></a>
+<span class="sourceLineNo">896</span>    // object from the constructor<a name="line.896"></a>
+<span class="sourceLineNo">897</span>    List&lt;KeyValueScanner&gt; scanners;<a name="line.897"></a>
+<span class="sourceLineNo">898</span>    flushLock.lock();<a name="line.898"></a>
+<span class="sourceLineNo">899</span>    try {<a name="line.899"></a>
+<span class="sourceLineNo">900</span>      List&lt;KeyValueScanner&gt; allScanners =<a name="line.900"></a>
+<span class="sourceLineNo">901</span>          new ArrayList&lt;&gt;(flushedstoreFileScanners.size() + memStoreScannersAfterFlush.size());<a name="line.901"></a>
+<span class="sourceLineNo">902</span>      allScanners.addAll(flushedstoreFileScanners);<a name="line.902"></a>
+<span class="sourceLineNo">903</span>      allScanners.addAll(memStoreScannersAfterFlush);<a name="line.903"></a>
+<span class="sourceLineNo">904</span>      scanners = selectScannersFrom(store, allScanners);<a name="line.904"></a>
+<span class="sourceLineNo">905</span>      // Clear the current set of flushed store files scanners so that they don't get added again<a name="line.905"></a>
+<span class="sourceLineNo">906</span>      flushedstoreFileScanners.clear();<a name="line.906"></a>
+<span class="sourceLineNo">907</span>      memStoreScannersAfterFlush.clear();<a name="line.907"></a>
+<span class="sourceLineNo">908</span>    } finally {<a name="line.908"></a>
+<span class="sourceLineNo">909</span>      flushLock.unlock();<a name="line.909"></a>
+<span class="sourceLineNo">910</span>    }<a name="line.910"></a>
+<span class="sourceLineNo">911</span><a name="line.911"></a>
+<span class="sourceLineNo">912</span>    // Seek the new scanners to the last key<a name="line.912"></a>
+<span class="sourceLineNo">913</span>    seekScanners(scanners, lastTop, false, parallelSeekEnabled);<a name="line.913"></a>
+<span class="sourceLineNo">914</span>    // remove the older memstore scanner<a name="line.914"></a>
+<span class="sourceLineNo">915</span>    for (int i = currentScanners.size() - 1; i &gt;=0; i--) {<a name="line.915"></a>
+<span class="sourceLineNo">916</span>      if (!currentScanners.get(i).isFileScanner()) {<a name="line.916"></a>
+<span class="sourceLineNo">917</span>        scannersForDelayedClose.add(currentScanners.remove(i));<a name="line.917"></a>
+<span class="sourceLineNo">918</span>      } else {<a name="line.918"></a>
+<span class="sourceLineNo">919</span>        // we add the memstore scanner to the end of currentScanners<a name="line.919"></a>
+<span class="sourceLineNo">920</span>        break;<a name="line.920"></a>
+<span class="sourceLineNo">921</span>      }<a name="line.921"></a>
+<span class="sourceLineNo">922</span>    }<a name="line.922"></a>
+<span class="sourceLineNo">923</span>    // add the newly created scanners on the flushed files and the current active memstore scanner<a name="line.923"></a>
+<span class="sourceLineNo">924</span>    addCurrentScanners(scanners);<a name="line.924"></a>
+<span class="sourceLineNo">925</span>    // Combine all seeked scanners with a heap<a name="line.925"></a>
+<span class="sourceLineNo">926</span>    resetKVHeap(this.currentScanners, store.getComparator());<a name="line.926"></a>
+<span class="sourceLineNo">927</span>    resetQueryMatcher(lastTop);<a name="line.927"></a>
+<span class="sourceLineNo">928</span>    if (heap.peek() == null || store.getComparator().compareRows(lastTop, this.heap.peek()) != 0) {<a name="line.928"></a>
+<span class="sourceLineNo">929</span>      LOG.info("Storescanner.peek() is changed where before = " + lastTop.toString() +<a name="line.929"></a>
+<span class="sourceLineNo">930</span>          ",and after = " + heap.peek());<a name="line.930"></a>
+<span class="sourceLineNo">931</span>      topChanged = true;<a name="line.931"></a>
+<span class="sourceLineNo">932</span>    } else {<a name="line.932"></a>
+<span class="sourceLineNo">933</span>      topChanged = false;<a name="line.933"></a>
+<span class="sourceLineNo">934</span>    }<a name="line.934"></a>
+<span class="sourceLineNo">935</span>    return topChanged;<a name="line.935"></a>
 <span class="sourceLineNo">936</span>  }<a name="line.936"></a>
 <span class="sourceLineNo">937</span><a name="line.937"></a>
-<span class="sourceLineNo">938</span>  /**<a name="line.938"></a>
-<span class="sourceLineNo">939</span>   * Check whether scan as expected order<a name="line.939"></a>
-<span class="sourceLineNo">940</span>   * @param prevKV<a name="line.940"></a>
-<span class="sourceLineNo">941</span>   * @param kv<a name="line.941"></a>
-<span class="sourceLineNo">942</span>   * @param comparator<a name="line.942"></a>
-<span class="sourceLineNo">943</span>   * @throws IOException<a name="line.943"></a>
-<span class="sourceLineNo">944</span>   */<a name="line.944"></a>
-<span class="sourceLineNo">945</span>  protected void checkScanOrder(Cell prevKV, Cell kv,<a name="line.945"></a>
-<span class="sourceLineNo">946</span>      CellComparator comparator) throws IOException {<a name="line.946"></a>
-<span class="sourceLineNo">947</span>    // Check that the heap gives us KVs in an increasing order.<a name="line.947"></a>
-<span class="sourceLineNo">948</span>    assert prevKV == null || comparator == null<a name="line.948"></a>
-<span class="sourceLineNo">949</span>        || comparator.compare(prevKV, kv) &lt;= 0 : "Key " + prevKV<a name="line.949"></a>
-<span class="sourceLineNo">950</span>        + " followed by a " + "smaller key " + kv + " in cf " + store;<a name="line.950"></a>
+<span class="sourceLineNo">938</span>  private void resetQueryMatcher(Cell lastTopKey) {<a name="line.938"></a>
+<span class="sourceLineNo">939</span>    // Reset the state of the Query Matcher and set to top row.<a name="line.939"></a>
+<span class="sourceLineNo">940</span>    // Only reset and call setRow if the row changes; avoids confusing the<a name="line.940"></a>
+<span class="sourceLineNo">941</span>    // query matcher if scanning intra-row.<a name="line.941"></a>
+<span class="sourceLineNo">942</span>    Cell cell = heap.peek();<a name="line.942"></a>
+<span class="sourceLineNo">943</span>    if (cell == null) {<a name="line.943"></a>
+<span class="sourceLineNo">944</span>      cell = lastTopKey;<a name="line.944"></a>
+<span class="sourceLineNo">945</span>    }<a name="line.945"></a>
+<span class="sourceLineNo">946</span>    if ((matcher.currentRow() == null) || !CellUtil.matchingRows(cell, matcher.currentRow())) {<a name="line.946"></a>
+<span class="sourceLineNo">947</span>      this.countPerRow = 0;<a name="line.947"></a>
+<span class="sourceLineNo">948</span>      // The setToNewRow will call reset internally<a name="line.948"></a>
+<span class="sourceLineNo">949</span>      matcher.setToNewRow(cell);<a name="line.949"></a>
+<span class="sourceLineNo">950</span>    }<a name="line.950"></a>
 <span class="sourceLineNo">951</span>  }<a name="line.951"></a>
 <span class="sourceLineNo">952</span><a name="line.952"></a>
-<span class="sourceLineNo">953</span>  protected boolean seekToNextRow(Cell c) throws IOException {<a name="line.953"></a>
-<span class="sourceLineNo">954</span>    return reseek(PrivateCellUtil.createLastOnRow(c));<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>
-<span class="sourceLineNo">958</span>   * Do a reseek in a normal StoreScanner(scan forward)<a name="line.958"></a>
-<span class="sourceLineNo">959</span>   * @param kv<a name="line.959"></a>
-<span class="sourceLineNo">960</span>   * @return true if scanner has values left, false if end of scanner<a name="line.960"></a>
-<span class="sourceLineNo">961</span>   * @throws IOException<a name="line.961"></a>
-<span class="sourceLineNo">962</span>   */<a name="line.962"></a>
-<span class="sourceLineNo">963</span>  protected boolean seekAsDirection(Cell kv)<a name="line.963"></a>
-<span class="sourceLineNo">964</span>      throws IOException {<a name="line.964"></a>
-<span class="sourceLineNo">965</span>    return reseek(kv);<a name="line.965"></a>
+<span class="sourceLineNo">953</span>  /**<a name="line.953"></a>
+<span class="sourceLineNo">954</span>   * Check whether scan as expected order<a name="line.954"></a>
+<span class="sourceLineNo">955</span>   * @param prevKV<a name="line.955"></a>
+<span class="sourceLineNo">956</span>   * @param kv<a name="line.956"></a>
+<span class="sourceLineNo">957</span>   * @param comparator<a name="line.957"></a>
+<span class="sourceLineNo">958</span>   * @throws IOException<a name="line.958"></a>
+<span class="sourceLineNo">959</span>   */<a name="line.959"></a>
+<span class="sourceLineNo">960</span>  protected void checkScanOrder(Cell prevKV, Cell kv,<a name="line.960"></a>
+<span class="sourceLineNo">961</span>      CellComparator comparator) throws IOException {<a name="line.961"></a>
+<span class="sourceLineNo">962</span>    // Check that the heap gives us KVs in an increasing order.<a name="line.962"></a>
+<span class="sourceLineNo">963</span>    assert prevKV == null || comparator == null<a name="line.963"></a>
+<span class="sourceLineNo">964</span>        || comparator.compare(prevKV, kv) &lt;= 0 : "Key " + prevKV<a name="line.964"></a>
+<span class="sourceLineNo">965</span>        + " followed by a " + "smaller key " + kv + " in cf " + store;<a name="line.965"></a>
 <span class="sourceLineNo">966</span>  }<a name="line.966"></a>
 <span class="sourceLineNo">967</span><a name="line.967"></a>
-<span class="sourceLineNo">968</span>  @Override<a name="line.968"></a>
-<span class="sourceLineNo">969</span>  public boolean reseek(Cell kv) throws IOException {<a name="line.969"></a>
-<span class="sourceLineNo">970</span>    if (checkFlushed()) {<a name="line.970"></a>
-<span class="sourceLineNo">971</span>      reopenAfterFlush();<a name="line.971"></a>
-<span class="sourceLineNo">972</span>    }<a name="line.972"></a>
-<span class="sourceLineNo">973</span>    if (explicitColumnQuery &amp;&amp; lazySeekEnabledGlobally) {<a name="line.973"></a>
-<span class="sourceLineNo">974</span>      return heap.requestSeek(kv, true, useRowColBloom);<a name="line.974"></a>
-<span class="sourceLineNo">975</span>    }<a name="line.975"></a>
-<span class="sourceLineNo">976</span>    return heap.reseek(kv);<a name="line.976"></a>
-<span class="sourceLineNo">977</span>  }<a name="line.977"></a>
-<span class="sourceLineNo">978</span><a name="line.978"></a>
-<span class="sourceLineNo">979</span>  @VisibleForTesting<a name="line.979"></a>
-<span class="sourceLineNo">980</span>  void trySwitchToStreamRead() {<a name="line.980"></a>
-<span class="sourceLineNo">981</span>    if (readType != Scan.ReadType.DEFAULT || !scanUsePread || closing ||<a name="line.981"></a>
-<span class="sourceLineNo">982</span>        heap.peek() == null || bytesRead &lt; preadMaxBytes) {<a name="line.982"></a>
-<span class="sourceLineNo">983</span>      return;<a name="line.983"></a>
-<span class="sourceLineNo">984</span>    }<a name="line.984"></a>
-<span class="sourceLineNo">985</span>    LOG.debug("Switch to stream read (scanned={} bytes) of {}", bytesRead,<a name="line.985"></a>
-<span class="sourceLineNo">986</span>        this.store.getColumnFamilyName());<a name="line.986"></a>
-<span class="sourceLineNo">987</span>    scanUsePread = false;<a name="line.987"></a>
-<span class="sourceLineNo">988</span>    Cell lastTop = heap.peek();<a name="line.988"></a>
-<span class="sourceLineNo">989</span>    List&lt;KeyValueScanner&gt; memstoreScanners = new ArrayList&lt;&gt;();<a name="line.989"></a>
-<span class="sourceLineNo">990</span>    List&lt;KeyValueScanner&gt; scannersToClose = new ArrayList&lt;&gt;();<a name="line.990"></a>
-<span class="sourceLineNo">991</span>    for (KeyValueScanner kvs : currentScanners) {<a name="line.991"></a>
-<span class="sourceLineNo">992</span>      if (!kvs.isFileScanner()) {<a name="line.992"></a>
-<span class="sourceLineNo">993</span>        // collect memstorescanners here<a name="line.993"></a>
-<span class="sourceLineNo">994</span>        memstoreScanners.add(kvs);<a name="line.994"></a>
-<span class="sourceLineNo">995</span>      } else {<a name="line.995"></a>
-<span class="sourceLineNo">996</span>        scannersToClose.add(kvs);<a name="line.996"></a>
-<span class="sourceLineNo">997</span>      }<a name="line.997"></a>
-<span class="sourceLineNo">998</span>    }<a name="line.998"></a>
-<span class="sourceLineNo">999</span>    List&lt;KeyValueScanner&gt; fileScanners = null;<a name="line.999"></a>
-<span class="sourceLineNo">1000</span>    List&lt;KeyValueScanner&gt; newCurrentScanners;<a name="line.1000"></a>
-<span class="sourceLineNo">1001</span>    KeyValueHeap newHeap;<a name="line.1001"></a>
-<span class="sourceLineNo">1002</span>    try {<a name="line.1002"></a>
-<span class="sourceLineNo">1003</span>      // We must have a store instance here so no null check<a name="line.1003"></a>
-<span class="sourceLineNo">1004</span>      // recreate the scanners on the current file scanners<a name="line.1004"></a>
-<span class="sourceLineNo">1005</span>      fileScanners = store.recreateScanners(scannersToClose, cacheBlocks, false, false,<a name="line.1005"></a>
-<span class="sourceLineNo">1006</span>        matcher, scan.getStartRow(), scan.includeStartRow(), scan.getStopRow(),<a name="line.1006"></a>
-<span class="sourceLineNo">1007</span>        scan.includeStopRow(), readPt, false);<a name="line.1007"></a>
-<span class="sourceLineNo">1008</

<TRUNCATED>

[42/50] hbase-site git commit: Published site at 26babcf013de696b899d76a3c39434b794440d8d.

Posted by gi...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlockCountsPerFile.html
----------------------------------------------------------------------
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlockCountsPerFile.html b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlockCountsPerFile.html
index f8ce32e..f118c08 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlockCountsPerFile.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlockCountsPerFile.html
@@ -41,273 +41,305 @@
 <span class="sourceLineNo">033</span>import org.apache.hadoop.conf.Configuration;<a name="line.33"></a>
 <span class="sourceLineNo">034</span>import org.apache.hadoop.hbase.metrics.impl.FastLongHistogram;<a name="line.34"></a>
 <span class="sourceLineNo">035</span>import org.apache.hadoop.hbase.util.Bytes;<a name="line.35"></a>
-<span class="sourceLineNo">036</span><a name="line.36"></a>
-<span class="sourceLineNo">037</span>/**<a name="line.37"></a>
-<span class="sourceLineNo">038</span> * Utilty for aggregating counts in CachedBlocks and toString/toJSON CachedBlocks and BlockCaches.<a name="line.38"></a>
-<span class="sourceLineNo">039</span> * No attempt has been made at making this thread safe.<a name="line.39"></a>
-<span class="sourceLineNo">040</span> */<a name="line.40"></a>
-<span class="sourceLineNo">041</span>@InterfaceAudience.Private<a name="line.41"></a>
-<span class="sourceLineNo">042</span>public class BlockCacheUtil {<a name="line.42"></a>
-<span class="sourceLineNo">043</span><a name="line.43"></a>
-<span class="sourceLineNo">044</span><a name="line.44"></a>
-<span class="sourceLineNo">045</span>  public static final long NANOS_PER_SECOND = 1000000000;<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>   * Needed generating JSON.<a name="line.48"></a>
-<span class="sourceLineNo">049</span>   */<a name="line.49"></a>
-<span class="sourceLineNo">050</span>  private static final ObjectMapper MAPPER = new ObjectMapper();<a name="line.50"></a>
-<span class="sourceLineNo">051</span>  static {<a name="line.51"></a>
-<span class="sourceLineNo">052</span>    MAPPER.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);<a name="line.52"></a>
-<span class="sourceLineNo">053</span>    MAPPER.configure(SerializationFeature.FLUSH_AFTER_WRITE_VALUE, true);<a name="line.53"></a>
-<span class="sourceLineNo">054</span>    MAPPER.configure(SerializationFeature.INDENT_OUTPUT, true);<a name="line.54"></a>
-<span class="sourceLineNo">055</span>  }<a name="line.55"></a>
-<span class="sourceLineNo">056</span><a name="line.56"></a>
-<span class="sourceLineNo">057</span>  /**<a name="line.57"></a>
-<span class="sourceLineNo">058</span>   * @param cb<a name="line.58"></a>
-<span class="sourceLineNo">059</span>   * @return The block content as String.<a name="line.59"></a>
-<span class="sourceLineNo">060</span>   */<a name="line.60"></a>
-<span class="sourceLineNo">061</span>  public static String toString(final CachedBlock cb, final long now) {<a name="line.61"></a>
-<span class="sourceLineNo">062</span>    return "filename=" + cb.getFilename() + ", " + toStringMinusFileName(cb, now);<a name="line.62"></a>
-<span class="sourceLineNo">063</span>  }<a name="line.63"></a>
-<span class="sourceLineNo">064</span><a name="line.64"></a>
-<span class="sourceLineNo">065</span>  /**<a name="line.65"></a>
-<span class="sourceLineNo">066</span>   * Little data structure to hold counts for a file.<a name="line.66"></a>
-<span class="sourceLineNo">067</span>   * Used doing a toJSON.<a name="line.67"></a>
-<span class="sourceLineNo">068</span>   */<a name="line.68"></a>
-<span class="sourceLineNo">069</span>  static class CachedBlockCountsPerFile {<a name="line.69"></a>
-<span class="sourceLineNo">070</span>    private int count = 0;<a name="line.70"></a>
-<span class="sourceLineNo">071</span>    private long size = 0;<a name="line.71"></a>
-<span class="sourceLineNo">072</span>    private int countData = 0;<a name="line.72"></a>
-<span class="sourceLineNo">073</span>    private long sizeData = 0;<a name="line.73"></a>
-<span class="sourceLineNo">074</span>    private final String filename;<a name="line.74"></a>
-<span class="sourceLineNo">075</span><a name="line.75"></a>
-<span class="sourceLineNo">076</span>    CachedBlockCountsPerFile(final String filename) {<a name="line.76"></a>
-<span class="sourceLineNo">077</span>      this.filename = filename;<a name="line.77"></a>
-<span class="sourceLineNo">078</span>    }<a name="line.78"></a>
-<span class="sourceLineNo">079</span><a name="line.79"></a>
-<span class="sourceLineNo">080</span>    public int getCount() {<a name="line.80"></a>
-<span class="sourceLineNo">081</span>      return count;<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>    public long getSize() {<a name="line.84"></a>
-<span class="sourceLineNo">085</span>      return size;<a name="line.85"></a>
-<span class="sourceLineNo">086</span>    }<a name="line.86"></a>
-<span class="sourceLineNo">087</span><a name="line.87"></a>
-<span class="sourceLineNo">088</span>    public int getCountData() {<a name="line.88"></a>
-<span class="sourceLineNo">089</span>      return countData;<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>    public long getSizeData() {<a name="line.92"></a>
-<span class="sourceLineNo">093</span>      return sizeData;<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>    public String getFilename() {<a name="line.96"></a>
-<span class="sourceLineNo">097</span>      return filename;<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>  /**<a name="line.101"></a>
-<span class="sourceLineNo">102</span>   * @param filename<a name="line.102"></a>
-<span class="sourceLineNo">103</span>   * @param blocks<a name="line.103"></a>
-<span class="sourceLineNo">104</span>   * @return A JSON String of &lt;code&gt;filename&lt;/code&gt; and counts of &lt;code&gt;blocks&lt;/code&gt;<a name="line.104"></a>
-<span class="sourceLineNo">105</span>   * @throws JsonGenerationException<a name="line.105"></a>
-<span class="sourceLineNo">106</span>   * @throws JsonMappingException<a name="line.106"></a>
-<span class="sourceLineNo">107</span>   * @throws IOException<a name="line.107"></a>
-<span class="sourceLineNo">108</span>   */<a name="line.108"></a>
-<span class="sourceLineNo">109</span>  public static String toJSON(final String filename, final NavigableSet&lt;CachedBlock&gt; blocks)<a name="line.109"></a>
-<span class="sourceLineNo">110</span>  throws JsonGenerationException, JsonMappingException, IOException {<a name="line.110"></a>
-<span class="sourceLineNo">111</span>    CachedBlockCountsPerFile counts = new CachedBlockCountsPerFile(filename);<a name="line.111"></a>
-<span class="sourceLineNo">112</span>    for (CachedBlock cb: blocks) {<a name="line.112"></a>
-<span class="sourceLineNo">113</span>      counts.count++;<a name="line.113"></a>
-<span class="sourceLineNo">114</span>      counts.size += cb.getSize();<a name="line.114"></a>
-<span class="sourceLineNo">115</span>      BlockType bt = cb.getBlockType();<a name="line.115"></a>
-<span class="sourceLineNo">116</span>      if (bt != null &amp;&amp; bt.isData()) {<a name="line.116"></a>
-<span class="sourceLineNo">117</span>        counts.countData++;<a name="line.117"></a>
-<span class="sourceLineNo">118</span>        counts.sizeData += cb.getSize();<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>    return MAPPER.writeValueAsString(counts);<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>   * @param cbsbf<a name="line.125"></a>
-<span class="sourceLineNo">126</span>   * @return JSON string of &lt;code&gt;cbsf&lt;/code&gt; aggregated<a name="line.126"></a>
-<span class="sourceLineNo">127</span>   * @throws JsonGenerationException<a name="line.127"></a>
-<span class="sourceLineNo">128</span>   * @throws JsonMappingException<a name="line.128"></a>
-<span class="sourceLineNo">129</span>   * @throws IOException<a name="line.129"></a>
-<span class="sourceLineNo">130</span>   */<a name="line.130"></a>
-<span class="sourceLineNo">131</span>  public static String toJSON(final CachedBlocksByFile cbsbf)<a name="line.131"></a>
-<span class="sourceLineNo">132</span>  throws JsonGenerationException, JsonMappingException, IOException {<a name="line.132"></a>
-<span class="sourceLineNo">133</span>    return MAPPER.writeValueAsString(cbsbf);<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>   * @param bc<a name="line.137"></a>
-<span class="sourceLineNo">138</span>   * @return JSON string of &lt;code&gt;bc&lt;/code&gt; content.<a name="line.138"></a>
-<span class="sourceLineNo">139</span>   * @throws JsonGenerationException<a name="line.139"></a>
-<span class="sourceLineNo">140</span>   * @throws JsonMappingException<a name="line.140"></a>
-<span class="sourceLineNo">141</span>   * @throws IOException<a name="line.141"></a>
-<span class="sourceLineNo">142</span>   */<a name="line.142"></a>
-<span class="sourceLineNo">143</span>  public static String toJSON(final BlockCache bc)<a name="line.143"></a>
-<span class="sourceLineNo">144</span>  throws JsonGenerationException, JsonMappingException, IOException {<a name="line.144"></a>
-<span class="sourceLineNo">145</span>    return MAPPER.writeValueAsString(bc);<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>  /**<a name="line.148"></a>
-<span class="sourceLineNo">149</span>   * @param cb<a name="line.149"></a>
-<span class="sourceLineNo">150</span>   * @return The block content of &lt;code&gt;bc&lt;/code&gt; as a String minus the filename.<a name="line.150"></a>
-<span class="sourceLineNo">151</span>   */<a name="line.151"></a>
-<span class="sourceLineNo">152</span>  public static String toStringMinusFileName(final CachedBlock cb, final long now) {<a name="line.152"></a>
-<span class="sourceLineNo">153</span>    return "offset=" + cb.getOffset() +<a name="line.153"></a>
-<span class="sourceLineNo">154</span>      ", size=" + cb.getSize() +<a name="line.154"></a>
-<span class="sourceLineNo">155</span>      ", age=" + (now - cb.getCachedTime()) +<a name="line.155"></a>
-<span class="sourceLineNo">156</span>      ", type=" + cb.getBlockType() +<a name="line.156"></a>
-<span class="sourceLineNo">157</span>      ", priority=" + cb.getBlockPriority();<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>  /**<a name="line.160"></a>
-<span class="sourceLineNo">161</span>   * Get a {@link CachedBlocksByFile} instance and load it up by iterating content in<a name="line.161"></a>
-<span class="sourceLineNo">162</span>   * {@link BlockCache}.<a name="line.162"></a>
-<span class="sourceLineNo">163</span>   * @param conf Used to read configurations<a name="line.163"></a>
-<span class="sourceLineNo">164</span>   * @param bc Block Cache to iterate.<a name="line.164"></a>
-<span class="sourceLineNo">165</span>   * @return Laoded up instance of CachedBlocksByFile<a name="line.165"></a>
-<span class="sourceLineNo">166</span>   */<a name="line.166"></a>
-<span class="sourceLineNo">167</span>  public static CachedBlocksByFile getLoadedCachedBlocksByFile(final Configuration conf,<a name="line.167"></a>
-<span class="sourceLineNo">168</span>      final BlockCache bc) {<a name="line.168"></a>
-<span class="sourceLineNo">169</span>    CachedBlocksByFile cbsbf = new CachedBlocksByFile(conf);<a name="line.169"></a>
-<span class="sourceLineNo">170</span>    for (CachedBlock cb: bc) {<a name="line.170"></a>
-<span class="sourceLineNo">171</span>      if (cbsbf.update(cb)) break;<a name="line.171"></a>
-<span class="sourceLineNo">172</span>    }<a name="line.172"></a>
-<span class="sourceLineNo">173</span>    return cbsbf;<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 static int compareCacheBlock(Cacheable left, Cacheable right) {<a name="line.176"></a>
-<span class="sourceLineNo">177</span>    ByteBuffer l = ByteBuffer.allocate(left.getSerializedLength());<a name="line.177"></a>
-<span class="sourceLineNo">178</span>    left.serialize(l);<a name="line.178"></a>
-<span class="sourceLineNo">179</span>    ByteBuffer r = ByteBuffer.allocate(right.getSerializedLength());<a name="line.179"></a>
-<span class="sourceLineNo">180</span>    right.serialize(r);<a name="line.180"></a>
-<span class="sourceLineNo">181</span>    return Bytes.compareTo(l.array(), l.arrayOffset(), l.limit(),<a name="line.181"></a>
-<span class="sourceLineNo">182</span>        r.array(), r.arrayOffset(), r.limit());<a name="line.182"></a>
-<span class="sourceLineNo">183</span>  }<a name="line.183"></a>
-<span class="sourceLineNo">184</span><a name="line.184"></a>
-<span class="sourceLineNo">185</span>  /**<a name="line.185"></a>
-<span class="sourceLineNo">186</span>   * Use one of these to keep a running account of cached blocks by file.  Throw it away when done.<a name="line.186"></a>
-<span class="sourceLineNo">187</span>   * This is different than metrics in that it is stats on current state of a cache.<a name="line.187"></a>
-<span class="sourceLineNo">188</span>   * See getLoadedCachedBlocksByFile<a name="line.188"></a>
-<span class="sourceLineNo">189</span>   */<a name="line.189"></a>
-<span class="sourceLineNo">190</span>  @JsonIgnoreProperties({"cachedBlockStatsByFile"})<a name="line.190"></a>
-<span class="sourceLineNo">191</span>  public static class CachedBlocksByFile {<a name="line.191"></a>
-<span class="sourceLineNo">192</span>    private int count;<a name="line.192"></a>
-<span class="sourceLineNo">193</span>    private int dataBlockCount;<a name="line.193"></a>
-<span class="sourceLineNo">194</span>    private long size;<a name="line.194"></a>
-<span class="sourceLineNo">195</span>    private long dataSize;<a name="line.195"></a>
-<span class="sourceLineNo">196</span>    private final long now = System.nanoTime();<a name="line.196"></a>
-<span class="sourceLineNo">197</span>    /**<a name="line.197"></a>
-<span class="sourceLineNo">198</span>     * How many blocks to look at before we give up.<a name="line.198"></a>
-<span class="sourceLineNo">199</span>     * There could be many millions of blocks. We don't want the<a name="line.199"></a>
-<span class="sourceLineNo">200</span>     * ui to freeze while we run through 1B blocks... users will<a name="line.200"></a>
-<span class="sourceLineNo">201</span>     * think hbase dead. UI displays warning in red when stats<a name="line.201"></a>
-<span class="sourceLineNo">202</span>     * are incomplete.<a name="line.202"></a>
-<span class="sourceLineNo">203</span>     */<a name="line.203"></a>
-<span class="sourceLineNo">204</span>    private final int max;<a name="line.204"></a>
-<span class="sourceLineNo">205</span>    public static final int DEFAULT_MAX = 1000000;<a name="line.205"></a>
-<span class="sourceLineNo">206</span><a name="line.206"></a>
-<span class="sourceLineNo">207</span>    CachedBlocksByFile() {<a name="line.207"></a>
-<span class="sourceLineNo">208</span>      this(null);<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>    CachedBlocksByFile(final Configuration c) {<a name="line.211"></a>
-<span class="sourceLineNo">212</span>      this.max = c == null? DEFAULT_MAX: c.getInt("hbase.ui.blockcache.by.file.max", DEFAULT_MAX);<a name="line.212"></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> * Utilty for aggregating counts in CachedBlocks and toString/toJSON CachedBlocks and BlockCaches.<a name="line.40"></a>
+<span class="sourceLineNo">041</span> * No attempt has been made at making this thread safe.<a name="line.41"></a>
+<span class="sourceLineNo">042</span> */<a name="line.42"></a>
+<span class="sourceLineNo">043</span>@InterfaceAudience.Private<a name="line.43"></a>
+<span class="sourceLineNo">044</span>public class BlockCacheUtil {<a name="line.44"></a>
+<span class="sourceLineNo">045</span><a name="line.45"></a>
+<span class="sourceLineNo">046</span>  private static final Logger LOG = LoggerFactory.getLogger(BlockCacheUtil.class);<a name="line.46"></a>
+<span class="sourceLineNo">047</span><a name="line.47"></a>
+<span class="sourceLineNo">048</span>  public static final long NANOS_PER_SECOND = 1000000000;<a name="line.48"></a>
+<span class="sourceLineNo">049</span><a name="line.49"></a>
+<span class="sourceLineNo">050</span>  /**<a name="line.50"></a>
+<span class="sourceLineNo">051</span>   * Needed generating JSON.<a name="line.51"></a>
+<span class="sourceLineNo">052</span>   */<a name="line.52"></a>
+<span class="sourceLineNo">053</span>  private static final ObjectMapper MAPPER = new ObjectMapper();<a name="line.53"></a>
+<span class="sourceLineNo">054</span>  static {<a name="line.54"></a>
+<span class="sourceLineNo">055</span>    MAPPER.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);<a name="line.55"></a>
+<span class="sourceLineNo">056</span>    MAPPER.configure(SerializationFeature.FLUSH_AFTER_WRITE_VALUE, true);<a name="line.56"></a>
+<span class="sourceLineNo">057</span>    MAPPER.configure(SerializationFeature.INDENT_OUTPUT, true);<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>  /**<a name="line.60"></a>
+<span class="sourceLineNo">061</span>   * @param cb<a name="line.61"></a>
+<span class="sourceLineNo">062</span>   * @return The block content as String.<a name="line.62"></a>
+<span class="sourceLineNo">063</span>   */<a name="line.63"></a>
+<span class="sourceLineNo">064</span>  public static String toString(final CachedBlock cb, final long now) {<a name="line.64"></a>
+<span class="sourceLineNo">065</span>    return "filename=" + cb.getFilename() + ", " + toStringMinusFileName(cb, now);<a name="line.65"></a>
+<span class="sourceLineNo">066</span>  }<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>   * Little data structure to hold counts for a file.<a name="line.69"></a>
+<span class="sourceLineNo">070</span>   * Used doing a toJSON.<a name="line.70"></a>
+<span class="sourceLineNo">071</span>   */<a name="line.71"></a>
+<span class="sourceLineNo">072</span>  static class CachedBlockCountsPerFile {<a name="line.72"></a>
+<span class="sourceLineNo">073</span>    private int count = 0;<a name="line.73"></a>
+<span class="sourceLineNo">074</span>    private long size = 0;<a name="line.74"></a>
+<span class="sourceLineNo">075</span>    private int countData = 0;<a name="line.75"></a>
+<span class="sourceLineNo">076</span>    private long sizeData = 0;<a name="line.76"></a>
+<span class="sourceLineNo">077</span>    private final String filename;<a name="line.77"></a>
+<span class="sourceLineNo">078</span><a name="line.78"></a>
+<span class="sourceLineNo">079</span>    CachedBlockCountsPerFile(final String filename) {<a name="line.79"></a>
+<span class="sourceLineNo">080</span>      this.filename = filename;<a name="line.80"></a>
+<span class="sourceLineNo">081</span>    }<a name="line.81"></a>
+<span class="sourceLineNo">082</span><a name="line.82"></a>
+<span class="sourceLineNo">083</span>    public int getCount() {<a name="line.83"></a>
+<span class="sourceLineNo">084</span>      return count;<a name="line.84"></a>
+<span class="sourceLineNo">085</span>    }<a name="line.85"></a>
+<span class="sourceLineNo">086</span><a name="line.86"></a>
+<span class="sourceLineNo">087</span>    public long getSize() {<a name="line.87"></a>
+<span class="sourceLineNo">088</span>      return size;<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>    public int getCountData() {<a name="line.91"></a>
+<span class="sourceLineNo">092</span>      return countData;<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>    public long getSizeData() {<a name="line.95"></a>
+<span class="sourceLineNo">096</span>      return sizeData;<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>    public String getFilename() {<a name="line.99"></a>
+<span class="sourceLineNo">100</span>      return filename;<a name="line.100"></a>
+<span class="sourceLineNo">101</span>    }<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>  /**<a name="line.104"></a>
+<span class="sourceLineNo">105</span>   * @param filename<a name="line.105"></a>
+<span class="sourceLineNo">106</span>   * @param blocks<a name="line.106"></a>
+<span class="sourceLineNo">107</span>   * @return A JSON String of &lt;code&gt;filename&lt;/code&gt; and counts of &lt;code&gt;blocks&lt;/code&gt;<a name="line.107"></a>
+<span class="sourceLineNo">108</span>   * @throws JsonGenerationException<a name="line.108"></a>
+<span class="sourceLineNo">109</span>   * @throws JsonMappingException<a name="line.109"></a>
+<span class="sourceLineNo">110</span>   * @throws IOException<a name="line.110"></a>
+<span class="sourceLineNo">111</span>   */<a name="line.111"></a>
+<span class="sourceLineNo">112</span>  public static String toJSON(final String filename, final NavigableSet&lt;CachedBlock&gt; blocks)<a name="line.112"></a>
+<span class="sourceLineNo">113</span>  throws JsonGenerationException, JsonMappingException, IOException {<a name="line.113"></a>
+<span class="sourceLineNo">114</span>    CachedBlockCountsPerFile counts = new CachedBlockCountsPerFile(filename);<a name="line.114"></a>
+<span class="sourceLineNo">115</span>    for (CachedBlock cb: blocks) {<a name="line.115"></a>
+<span class="sourceLineNo">116</span>      counts.count++;<a name="line.116"></a>
+<span class="sourceLineNo">117</span>      counts.size += cb.getSize();<a name="line.117"></a>
+<span class="sourceLineNo">118</span>      BlockType bt = cb.getBlockType();<a name="line.118"></a>
+<span class="sourceLineNo">119</span>      if (bt != null &amp;&amp; bt.isData()) {<a name="line.119"></a>
+<span class="sourceLineNo">120</span>        counts.countData++;<a name="line.120"></a>
+<span class="sourceLineNo">121</span>        counts.sizeData += cb.getSize();<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>    return MAPPER.writeValueAsString(counts);<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>  /**<a name="line.127"></a>
+<span class="sourceLineNo">128</span>   * @param cbsbf<a name="line.128"></a>
+<span class="sourceLineNo">129</span>   * @return JSON string of &lt;code&gt;cbsf&lt;/code&gt; aggregated<a name="line.129"></a>
+<span class="sourceLineNo">130</span>   * @throws JsonGenerationException<a name="line.130"></a>
+<span class="sourceLineNo">131</span>   * @throws JsonMappingException<a name="line.131"></a>
+<span class="sourceLineNo">132</span>   * @throws IOException<a name="line.132"></a>
+<span class="sourceLineNo">133</span>   */<a name="line.133"></a>
+<span class="sourceLineNo">134</span>  public static String toJSON(final CachedBlocksByFile cbsbf)<a name="line.134"></a>
+<span class="sourceLineNo">135</span>  throws JsonGenerationException, JsonMappingException, IOException {<a name="line.135"></a>
+<span class="sourceLineNo">136</span>    return MAPPER.writeValueAsString(cbsbf);<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>   * @param bc<a name="line.140"></a>
+<span class="sourceLineNo">141</span>   * @return JSON string of &lt;code&gt;bc&lt;/code&gt; content.<a name="line.141"></a>
+<span class="sourceLineNo">142</span>   * @throws JsonGenerationException<a name="line.142"></a>
+<span class="sourceLineNo">143</span>   * @throws JsonMappingException<a name="line.143"></a>
+<span class="sourceLineNo">144</span>   * @throws IOException<a name="line.144"></a>
+<span class="sourceLineNo">145</span>   */<a name="line.145"></a>
+<span class="sourceLineNo">146</span>  public static String toJSON(final BlockCache bc)<a name="line.146"></a>
+<span class="sourceLineNo">147</span>  throws JsonGenerationException, JsonMappingException, IOException {<a name="line.147"></a>
+<span class="sourceLineNo">148</span>    return MAPPER.writeValueAsString(bc);<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 name="line.151"></a>
+<span class="sourceLineNo">152</span>   * @param cb<a name="line.152"></a>
+<span class="sourceLineNo">153</span>   * @return The block content of &lt;code&gt;bc&lt;/code&gt; as a String minus the filename.<a name="line.153"></a>
+<span class="sourceLineNo">154</span>   */<a name="line.154"></a>
+<span class="sourceLineNo">155</span>  public static String toStringMinusFileName(final CachedBlock cb, final long now) {<a name="line.155"></a>
+<span class="sourceLineNo">156</span>    return "offset=" + cb.getOffset() +<a name="line.156"></a>
+<span class="sourceLineNo">157</span>      ", size=" + cb.getSize() +<a name="line.157"></a>
+<span class="sourceLineNo">158</span>      ", age=" + (now - cb.getCachedTime()) +<a name="line.158"></a>
+<span class="sourceLineNo">159</span>      ", type=" + cb.getBlockType() +<a name="line.159"></a>
+<span class="sourceLineNo">160</span>      ", priority=" + cb.getBlockPriority();<a name="line.160"></a>
+<span class="sourceLineNo">161</span>  }<a name="line.161"></a>
+<span class="sourceLineNo">162</span><a name="line.162"></a>
+<span class="sourceLineNo">163</span>  /**<a name="line.163"></a>
+<span class="sourceLineNo">164</span>   * Get a {@link CachedBlocksByFile} instance and load it up by iterating content in<a name="line.164"></a>
+<span class="sourceLineNo">165</span>   * {@link BlockCache}.<a name="line.165"></a>
+<span class="sourceLineNo">166</span>   * @param conf Used to read configurations<a name="line.166"></a>
+<span class="sourceLineNo">167</span>   * @param bc Block Cache to iterate.<a name="line.167"></a>
+<span class="sourceLineNo">168</span>   * @return Laoded up instance of CachedBlocksByFile<a name="line.168"></a>
+<span class="sourceLineNo">169</span>   */<a name="line.169"></a>
+<span class="sourceLineNo">170</span>  public static CachedBlocksByFile getLoadedCachedBlocksByFile(final Configuration conf,<a name="line.170"></a>
+<span class="sourceLineNo">171</span>      final BlockCache bc) {<a name="line.171"></a>
+<span class="sourceLineNo">172</span>    CachedBlocksByFile cbsbf = new CachedBlocksByFile(conf);<a name="line.172"></a>
+<span class="sourceLineNo">173</span>    for (CachedBlock cb: bc) {<a name="line.173"></a>
+<span class="sourceLineNo">174</span>      if (cbsbf.update(cb)) break;<a name="line.174"></a>
+<span class="sourceLineNo">175</span>    }<a name="line.175"></a>
+<span class="sourceLineNo">176</span>    return cbsbf;<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>  private static int compareCacheBlock(Cacheable left, Cacheable right,<a name="line.179"></a>
+<span class="sourceLineNo">180</span>                                       boolean includeNextBlockMetadata) {<a name="line.180"></a>
+<span class="sourceLineNo">181</span>    ByteBuffer l = ByteBuffer.allocate(left.getSerializedLength());<a name="line.181"></a>
+<span class="sourceLineNo">182</span>    left.serialize(l, includeNextBlockMetadata);<a name="line.182"></a>
+<span class="sourceLineNo">183</span>    ByteBuffer r = ByteBuffer.allocate(right.getSerializedLength());<a name="line.183"></a>
+<span class="sourceLineNo">184</span>    right.serialize(r, includeNextBlockMetadata);<a name="line.184"></a>
+<span class="sourceLineNo">185</span>    return Bytes.compareTo(l.array(), l.arrayOffset(), l.limit(),<a name="line.185"></a>
+<span class="sourceLineNo">186</span>        r.array(), r.arrayOffset(), r.limit());<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>   * Validate that the existing and newBlock are the same without including the nextBlockMetadata,<a name="line.190"></a>
+<span class="sourceLineNo">191</span>   * if not, throw an exception. If they are the same without the nextBlockMetadata,<a name="line.191"></a>
+<span class="sourceLineNo">192</span>   * return the comparison.<a name="line.192"></a>
+<span class="sourceLineNo">193</span>   *<a name="line.193"></a>
+<span class="sourceLineNo">194</span>   * @param existing block that is existing in the cache.<a name="line.194"></a>
+<span class="sourceLineNo">195</span>   * @param newBlock block that is trying to be cached.<a name="line.195"></a>
+<span class="sourceLineNo">196</span>   * @param cacheKey the cache key of the blocks.<a name="line.196"></a>
+<span class="sourceLineNo">197</span>   * @return comparison of the existing block to the newBlock.<a name="line.197"></a>
+<span class="sourceLineNo">198</span>   */<a name="line.198"></a>
+<span class="sourceLineNo">199</span>  public static int validateBlockAddition(Cacheable existing, Cacheable newBlock,<a name="line.199"></a>
+<span class="sourceLineNo">200</span>                                          BlockCacheKey cacheKey) {<a name="line.200"></a>
+<span class="sourceLineNo">201</span>    int comparison = compareCacheBlock(existing, newBlock, true);<a name="line.201"></a>
+<span class="sourceLineNo">202</span>    if (comparison != 0) {<a name="line.202"></a>
+<span class="sourceLineNo">203</span>      LOG.warn("Cached block contents differ, trying to just compare the block contents " +<a name="line.203"></a>
+<span class="sourceLineNo">204</span>          "without the next block. CacheKey: " + cacheKey);<a name="line.204"></a>
+<span class="sourceLineNo">205</span><a name="line.205"></a>
+<span class="sourceLineNo">206</span>      // compare the contents, if they are not equal, we are in big trouble<a name="line.206"></a>
+<span class="sourceLineNo">207</span>      int comparisonWithoutNextBlockMetadata = compareCacheBlock(existing, newBlock, false);<a name="line.207"></a>
+<span class="sourceLineNo">208</span><a name="line.208"></a>
+<span class="sourceLineNo">209</span>      if (comparisonWithoutNextBlockMetadata != 0) {<a name="line.209"></a>
+<span class="sourceLineNo">210</span>        throw new RuntimeException("Cached block contents differ, which should not have happened."<a name="line.210"></a>
+<span class="sourceLineNo">211</span>            + "cacheKey:" + cacheKey);<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>    /**<a name="line.215"></a>
-<span class="sourceLineNo">216</span>     * Map by filename. use concurent utils because we want our Map and contained blocks sorted.<a name="line.216"></a>
-<span class="sourceLineNo">217</span>     */<a name="line.217"></a>
-<span class="sourceLineNo">218</span>    private NavigableMap&lt;String, NavigableSet&lt;CachedBlock&gt;&gt; cachedBlockByFile = new ConcurrentSkipListMap&lt;&gt;();<a name="line.218"></a>
-<span class="sourceLineNo">219</span>    FastLongHistogram hist = new FastLongHistogram();<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>     * @param cb<a name="line.222"></a>
-<span class="sourceLineNo">223</span>     * @return True if full.... if we won't be adding any more.<a name="line.223"></a>
-<span class="sourceLineNo">224</span>     */<a name="line.224"></a>
-<span class="sourceLineNo">225</span>    public boolean update(final CachedBlock cb) {<a name="line.225"></a>
-<span class="sourceLineNo">226</span>      if (isFull()) return true;<a name="line.226"></a>
-<span class="sourceLineNo">227</span>      NavigableSet&lt;CachedBlock&gt; set = this.cachedBlockByFile.get(cb.getFilename());<a name="line.227"></a>
-<span class="sourceLineNo">228</span>      if (set == null) {<a name="line.228"></a>
-<span class="sourceLineNo">229</span>        set = new ConcurrentSkipListSet&lt;&gt;();<a name="line.229"></a>
-<span class="sourceLineNo">230</span>        this.cachedBlockByFile.put(cb.getFilename(), set);<a name="line.230"></a>
-<span class="sourceLineNo">231</span>      }<a name="line.231"></a>
-<span class="sourceLineNo">232</span>      set.add(cb);<a name="line.232"></a>
-<span class="sourceLineNo">233</span>      this.size += cb.getSize();<a name="line.233"></a>
-<span class="sourceLineNo">234</span>      this.count++;<a name="line.234"></a>
-<span class="sourceLineNo">235</span>      BlockType bt = cb.getBlockType();<a name="line.235"></a>
-<span class="sourceLineNo">236</span>      if (bt != null &amp;&amp; bt.isData()) {<a name="line.236"></a>
-<span class="sourceLineNo">237</span>        this.dataBlockCount++;<a name="line.237"></a>
-<span class="sourceLineNo">238</span>        this.dataSize += cb.getSize();<a name="line.238"></a>
-<span class="sourceLineNo">239</span>      }<a name="line.239"></a>
-<span class="sourceLineNo">240</span>      long age = (this.now - cb.getCachedTime())/NANOS_PER_SECOND;<a name="line.240"></a>
-<span class="sourceLineNo">241</span>      this.hist.add(age, 1);<a name="line.241"></a>
-<span class="sourceLineNo">242</span>      return false;<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>    /**<a name="line.245"></a>
-<span class="sourceLineNo">246</span>     * @return True if full; i.e. there are more items in the cache but we only loaded up<a name="line.246"></a>
-<span class="sourceLineNo">247</span>     * the maximum set in configuration &lt;code&gt;hbase.ui.blockcache.by.file.max&lt;/code&gt;<a name="line.247"></a>
-<span class="sourceLineNo">248</span>     * (Default: DEFAULT_MAX).<a name="line.248"></a>
+<span class="sourceLineNo">214</span>    return comparison;<a name="line.214"></a>
+<span class="sourceLineNo">215</span>  }<a name="line.215"></a>
+<span class="sourceLineNo">216</span><a name="line.216"></a>
+<span class="sourceLineNo">217</span>  /**<a name="line.217"></a>
+<span class="sourceLineNo">218</span>   * Use one of these to keep a running account of cached blocks by file.  Throw it away when done.<a name="line.218"></a>
+<span class="sourceLineNo">219</span>   * This is different than metrics in that it is stats on current state of a cache.<a name="line.219"></a>
+<span class="sourceLineNo">220</span>   * See getLoadedCachedBlocksByFile<a name="line.220"></a>
+<span class="sourceLineNo">221</span>   */<a name="line.221"></a>
+<span class="sourceLineNo">222</span>  @JsonIgnoreProperties({"cachedBlockStatsByFile"})<a name="line.222"></a>
+<span class="sourceLineNo">223</span>  public static class CachedBlocksByFile {<a name="line.223"></a>
+<span class="sourceLineNo">224</span>    private int count;<a name="line.224"></a>
+<span class="sourceLineNo">225</span>    private int dataBlockCount;<a name="line.225"></a>
+<span class="sourceLineNo">226</span>    private long size;<a name="line.226"></a>
+<span class="sourceLineNo">227</span>    private long dataSize;<a name="line.227"></a>
+<span class="sourceLineNo">228</span>    private final long now = System.nanoTime();<a name="line.228"></a>
+<span class="sourceLineNo">229</span>    /**<a name="line.229"></a>
+<span class="sourceLineNo">230</span>     * How many blocks to look at before we give up.<a name="line.230"></a>
+<span class="sourceLineNo">231</span>     * There could be many millions of blocks. We don't want the<a name="line.231"></a>
+<span class="sourceLineNo">232</span>     * ui to freeze while we run through 1B blocks... users will<a name="line.232"></a>
+<span class="sourceLineNo">233</span>     * think hbase dead. UI displays warning in red when stats<a name="line.233"></a>
+<span class="sourceLineNo">234</span>     * are incomplete.<a name="line.234"></a>
+<span class="sourceLineNo">235</span>     */<a name="line.235"></a>
+<span class="sourceLineNo">236</span>    private final int max;<a name="line.236"></a>
+<span class="sourceLineNo">237</span>    public static final int DEFAULT_MAX = 1000000;<a name="line.237"></a>
+<span class="sourceLineNo">238</span><a name="line.238"></a>
+<span class="sourceLineNo">239</span>    CachedBlocksByFile() {<a name="line.239"></a>
+<span class="sourceLineNo">240</span>      this(null);<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>    CachedBlocksByFile(final Configuration c) {<a name="line.243"></a>
+<span class="sourceLineNo">244</span>      this.max = c == null? DEFAULT_MAX: c.getInt("hbase.ui.blockcache.by.file.max", DEFAULT_MAX);<a name="line.244"></a>
+<span class="sourceLineNo">245</span>    }<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>     * Map by filename. use concurent utils because we want our Map and contained blocks sorted.<a name="line.248"></a>
 <span class="sourceLineNo">249</span>     */<a name="line.249"></a>
-<span class="sourceLineNo">250</span>    public boolean isFull() {<a name="line.250"></a>
-<span class="sourceLineNo">251</span>      return this.count &gt;= this.max;<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 NavigableMap&lt;String, NavigableSet&lt;CachedBlock&gt;&gt; getCachedBlockStatsByFile() {<a name="line.254"></a>
-<span class="sourceLineNo">255</span>      return this.cachedBlockByFile;<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 count of blocks in the cache<a name="line.259"></a>
-<span class="sourceLineNo">260</span>     */<a name="line.260"></a>
-<span class="sourceLineNo">261</span>    public int getCount() {<a name="line.261"></a>
-<span class="sourceLineNo">262</span>      return count;<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>    public int getDataCount() {<a name="line.265"></a>
-<span class="sourceLineNo">266</span>      return dataBlockCount;<a name="line.266"></a>
-<span class="sourceLineNo">267</span>    }<a name="line.267"></a>
-<span class="sourceLineNo">268</span><a name="line.268"></a>
-<span class="sourceLineNo">269</span>    /**<a name="line.269"></a>
-<span class="sourceLineNo">270</span>     * @return size of blocks in the cache<a name="line.270"></a>
-<span class="sourceLineNo">271</span>     */<a name="line.271"></a>
-<span class="sourceLineNo">272</span>    public long getSize() {<a name="line.272"></a>
-<span class="sourceLineNo">273</span>      return size;<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>     * @return Size of data.<a name="line.277"></a>
-<span class="sourceLineNo">278</span>     */<a name="line.278"></a>
-<span class="sourceLineNo">279</span>    public long getDataSize() {<a name="line.279"></a>
-<span class="sourceLineNo">280</span>      return dataSize;<a name="line.280"></a>
-<span class="sourceLineNo">281</span>    }<a name="line.281"></a>
-<span class="sourceLineNo">282</span><a name="line.282"></a>
-<span class="sourceLineNo">283</span>    public AgeSnapshot getAgeInCacheSnapshot() {<a name="line.283"></a>
-<span class="sourceLineNo">284</span>      return new AgeSnapshot(this.hist);<a name="line.284"></a>
-<span class="sourceLineNo">285</span>    }<a name="line.285"></a>
-<span class="sourceLineNo">286</span><a name="line.286"></a>
-<span class="sourceLineNo">287</span>    @Override<a name="line.287"></a>
-<span class="sourceLineNo">288</span>    public String toString() {<a name="line.288"></a>
-<span class="sourceLineNo">289</span>      AgeSnapshot snapshot = getAgeInCacheSnapshot();<a name="line.289"></a>
-<span class="sourceLineNo">290</span>      return "count=" + count + ", dataBlockCount=" + dataBlockCount + ", size=" + size +<a name="line.290"></a>
-<span class="sourceLineNo">291</span>          ", dataSize=" + getDataSize() +<a name="line.291"></a>
-<span class="sourceLineNo">292</span>          ", mean age=" + snapshot.getMean() +<a name="line.292"></a>
-<span class="sourceLineNo">293</span>          ", min age=" + snapshot.getMin() +<a name="line.293"></a>
-<span class="sourceLineNo">294</span>          ", max age=" + snapshot.getMax() +<a name="line.294"></a>
-<span class="sourceLineNo">295</span>          ", 75th percentile age="   + snapshot.get75thPercentile() +<a name="line.295"></a>
-<span class="sourceLineNo">296</span>          ", 95th percentile age="   + snapshot.get95thPercentile() +<a name="line.296"></a>
-<span class="sourceLineNo">297</span>          ", 98th percentile age="   + snapshot.get98thPercentile() +<a name="line.297"></a>
-<span class="sourceLineNo">298</span>          ", 99th percentile age="   + snapshot.get99thPercentile() +<a name="line.298"></a>
-<span class="sourceLineNo">299</span>          ", 99.9th percentile age=" + snapshot.get99thPercentile();<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">250</span>    private NavigableMap&lt;String, NavigableSet&lt;CachedBlock&gt;&gt; cachedBlockByFile = new ConcurrentSkipListMap&lt;&gt;();<a name="line.250"></a>
+<span class="sourceLineNo">251</span>    FastLongHistogram hist = new FastLongHistogram();<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>     * @param cb<a name="line.254"></a>
+<span class="sourceLineNo">255</span>     * @return True if full.... if we won't be adding any more.<a name="line.255"></a>
+<span class="sourceLineNo">256</span>     */<a name="line.256"></a>
+<span class="sourceLineNo">257</span>    public boolean update(final CachedBlock cb) {<a name="line.257"></a>
+<span class="sourceLineNo">258</span>      if (isFull()) return true;<a name="line.258"></a>
+<span class="sourceLineNo">259</span>      NavigableSet&lt;CachedBlock&gt; set = this.cachedBlockByFile.get(cb.getFilename());<a name="line.259"></a>
+<span class="sourceLineNo">260</span>      if (set == null) {<a name="line.260"></a>
+<span class="sourceLineNo">261</span>        set = new ConcurrentSkipListSet&lt;&gt;();<a name="line.261"></a>
+<span class="sourceLineNo">262</span>        this.cachedBlockByFile.put(cb.getFilename(), set);<a name="line.262"></a>
+<span class="sourceLineNo">263</span>      }<a name="line.263"></a>
+<span class="sourceLineNo">264</span>      set.add(cb);<a name="line.264"></a>
+<span class="sourceLineNo">265</span>      this.size += cb.getSize();<a name="line.265"></a>
+<span class="sourceLineNo">266</span>      this.count++;<a name="line.266"></a>
+<span class="sourceLineNo">267</span>      BlockType bt = cb.getBlockType();<a name="line.267"></a>
+<span class="sourceLineNo">268</span>      if (bt != null &amp;&amp; bt.isData()) {<a name="line.268"></a>
+<span class="sourceLineNo">269</span>        this.dataBlockCount++;<a name="line.269"></a>
+<span class="sourceLineNo">270</span>        this.dataSize += cb.getSize();<a name="line.270"></a>
+<span class="sourceLineNo">271</span>      }<a name="line.271"></a>
+<span class="sourceLineNo">272</span>      long age = (this.now - cb.getCachedTime())/NANOS_PER_SECOND;<a name="line.272"></a>
+<span class="sourceLineNo">273</span>      this.hist.add(age, 1);<a name="line.273"></a>
+<span class="sourceLineNo">274</span>      return false;<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>     * @return True if full; i.e. there are more items in the cache but we only loaded up<a name="line.278"></a>
+<span class="sourceLineNo">279</span>     * the maximum set in configuration &lt;code&gt;hbase.ui.blockcache.by.file.max&lt;/code&gt;<a name="line.279"></a>
+<span class="sourceLineNo">280</span>     * (Default: DEFAULT_MAX).<a name="line.280"></a>
+<span class="sourceLineNo">281</span>     */<a name="line.281"></a>
+<span class="sourceLineNo">282</span>    public boolean isFull() {<a name="line.282"></a>
+<span class="sourceLineNo">283</span>      return this.count &gt;= this.max;<a name="line.283"></a>
+<span class="sourceLineNo">284</span>    }<a name="line.284"></a>
+<span class="sourceLineNo">285</span><a name="line.285"></a>
+<span class="sourceLineNo">286</span>    public NavigableMap&lt;String, NavigableSet&lt;CachedBlock&gt;&gt; getCachedBlockStatsByFile() {<a name="line.286"></a>
+<span class="sourceLineNo">287</span>      return this.cachedBlockByFile;<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>    /**<a name="line.290"></a>
+<span class="sourceLineNo">291</span>     * @return count of blocks in the cache<a name="line.291"></a>
+<span class="sourceLineNo">292</span>     */<a name="line.292"></a>
+<span class="sourceLineNo">293</span>    public int getCount() {<a name="line.293"></a>
+<span class="sourceLineNo">294</span>      return count;<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 int getDataCount() {<a name="line.297"></a>
+<span class="sourceLineNo">298</span>      return dataBlockCount;<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>     * @return size of blocks in the cache<a name="line.302"></a>
+<span class="sourceLineNo">303</span>     */<a name="line.303"></a>
+<span class="sourceLineNo">304</span>    public long getSize() {<a name="line.304"></a>
+<span class="sourceLineNo">305</span>      return size;<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>     * @return Size of data.<a name="line.309"></a>
+<span class="sourceLineNo">310</span>     */<a name="line.310"></a>
+<span class="sourceLineNo">311</span>    public long getDataSize() {<a name="line.311"></a>
+<span class="sourceLineNo">312</span>      return dataSize;<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>    public AgeSnapshot getAgeInCacheSnapshot() {<a name="line.315"></a>
+<span class="sourceLineNo">316</span>      return new AgeSnapshot(this.hist);<a name="line.316"></a>
+<span class="sourceLineNo">317</span>    }<a name="line.317"></a>
+<span class="sourceLineNo">318</span><a name="line.318"></a>
+<span class="sourceLineNo">319</span>    @Override<a name="line.319"></a>
+<span class="sourceLineNo">320</span>    public String toString() {<a name="line.320"></a>
+<span class="sourceLineNo">321</span>      AgeSnapshot snapshot = getAgeInCacheSnapshot();<a name="line.321"></a>
+<span class="sourceLineNo">322</span>      return "count=" + count + ", dataBlockCount=" + dataBlockCount + ", size=" + size +<a name="line.322"></a>
+<span class="sourceLineNo">323</span>          ", dataSize=" + getDataSize() +<a name="line.323"></a>
+<span class="sourceLineNo">324</span>          ", mean age=" + snapshot.getMean() +<a name="line.324"></a>
+<span class="sourceLineNo">325</span>          ", min age=" + snapshot.getMin() +<a name="line.325"></a>
+<span class="sourceLineNo">326</span>          ", max age=" + snapshot.getMax() +<a name="line.326"></a>
+<span class="sourceLineNo">327</span>          ", 75th percentile age="   + snapshot.get75thPercentile() +<a name="line.327"></a>
+<span class="sourceLineNo">328</span>          ", 95th percentile age="   + snapshot.get95thPercentile() +<a name="line.328"></a>
+<span class="sourceLineNo">329</span>          ", 98th percentile age="   + snapshot.get98thPercentile() +<a name="line.329"></a>
+<span class="sourceLineNo">330</span>          ", 99th percentile age="   + snapshot.get99thPercentile() +<a name="line.330"></a>
+<span class="sourceLineNo">331</span>          ", 99.9th percentile age=" + snapshot.get99thPercentile();<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>
 
 
 


[13/50] hbase-site git commit: Published site at 26babcf013de696b899d76a3c39434b794440d8d.

Posted by gi...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html
----------------------------------------------------------------------
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html b/devapidocs/src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html
index cabb570..90f3b1e 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html
@@ -107,660 +107,661 @@
 <span class="sourceLineNo">099</span><a name="line.99"></a>
 <span class="sourceLineNo">100</span>  private Cell lastPeekedCell = null;<a name="line.100"></a>
 <span class="sourceLineNo">101</span><a name="line.101"></a>
-<span class="sourceLineNo">102</span>  /**<a name="line.102"></a>
-<span class="sourceLineNo">103</span>   * Tracks the relevant server side metrics during scans. null when metrics should not be tracked<a name="line.103"></a>
-<span class="sourceLineNo">104</span>   */<a name="line.104"></a>
-<span class="sourceLineNo">105</span>  final ServerSideScanMetrics metrics;<a name="line.105"></a>
-<span class="sourceLineNo">106</span><a name="line.106"></a>
-<span class="sourceLineNo">107</span>  ScannerContext(boolean keepProgress, LimitFields limitsToCopy, boolean trackMetrics) {<a name="line.107"></a>
-<span class="sourceLineNo">108</span>    this.limits = new LimitFields();<a name="line.108"></a>
-<span class="sourceLineNo">109</span>    if (limitsToCopy != null) {<a name="line.109"></a>
-<span class="sourceLineNo">110</span>      this.limits.copy(limitsToCopy);<a name="line.110"></a>
-<span class="sourceLineNo">111</span>    }<a name="line.111"></a>
+<span class="sourceLineNo">102</span>  // Set this to true will have the same behavior with reaching the time limit.<a name="line.102"></a>
+<span class="sourceLineNo">103</span>  // This is used when you want to make the current RSRpcService.scan returns immediately. For<a name="line.103"></a>
+<span class="sourceLineNo">104</span>  // example, when we want to switch from pread to stream, we can only do it after the rpc call is<a name="line.104"></a>
+<span class="sourceLineNo">105</span>  // returned.<a name="line.105"></a>
+<span class="sourceLineNo">106</span>  private boolean returnImmediately;<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>   * Tracks the relevant server side metrics during scans. null when metrics should not be tracked<a name="line.109"></a>
+<span class="sourceLineNo">110</span>   */<a name="line.110"></a>
+<span class="sourceLineNo">111</span>  final ServerSideScanMetrics metrics;<a name="line.111"></a>
 <span class="sourceLineNo">112</span><a name="line.112"></a>
-<span class="sourceLineNo">113</span>    // Progress fields are initialized to 0<a name="line.113"></a>
-<span class="sourceLineNo">114</span>    progress = new ProgressFields(0, 0, 0);<a name="line.114"></a>
-<span class="sourceLineNo">115</span><a name="line.115"></a>
-<span class="sourceLineNo">116</span>    this.keepProgress = keepProgress;<a name="line.116"></a>
-<span class="sourceLineNo">117</span>    this.scannerState = DEFAULT_STATE;<a name="line.117"></a>
-<span class="sourceLineNo">118</span>    this.metrics = trackMetrics ? new ServerSideScanMetrics() : null;<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>  boolean isTrackingMetrics() {<a name="line.121"></a>
-<span class="sourceLineNo">122</span>    return this.metrics != null;<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>   * Get the metrics instance. Should only be called after a call to {@link #isTrackingMetrics()}<a name="line.126"></a>
-<span class="sourceLineNo">127</span>   * has been made to confirm that metrics are indeed being tracked.<a name="line.127"></a>
-<span class="sourceLineNo">128</span>   * @return {@link ServerSideScanMetrics} instance that is tracking metrics for this scan<a name="line.128"></a>
-<span class="sourceLineNo">129</span>   */<a name="line.129"></a>
-<span class="sourceLineNo">130</span>  ServerSideScanMetrics getMetrics() {<a name="line.130"></a>
-<span class="sourceLineNo">131</span>    assert isTrackingMetrics();<a name="line.131"></a>
-<span class="sourceLineNo">132</span>    return this.metrics;<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>   * @return true if the progress tracked so far in this instance will be considered during an<a name="line.136"></a>
-<span class="sourceLineNo">137</span>   *         invocation of {@link InternalScanner#next(java.util.List)} or<a name="line.137"></a>
-<span class="sourceLineNo">138</span>   *         {@link RegionScanner#next(java.util.List)}. false when the progress tracked so far<a name="line.138"></a>
-<span class="sourceLineNo">139</span>   *         should not be considered and should instead be wiped away via {@link #clearProgress()}<a name="line.139"></a>
-<span class="sourceLineNo">140</span>   */<a name="line.140"></a>
-<span class="sourceLineNo">141</span>  boolean getKeepProgress() {<a name="line.141"></a>
-<span class="sourceLineNo">142</span>    return keepProgress;<a name="line.142"></a>
-<span class="sourceLineNo">143</span>  }<a name="line.143"></a>
-<span class="sourceLineNo">144</span><a name="line.144"></a>
-<span class="sourceLineNo">145</span>  void setKeepProgress(boolean keepProgress) {<a name="line.145"></a>
-<span class="sourceLineNo">146</span>    this.keepProgress = keepProgress;<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>   * Progress towards the batch limit has been made. Increment internal tracking of batch progress<a name="line.150"></a>
-<span class="sourceLineNo">151</span>   */<a name="line.151"></a>
-<span class="sourceLineNo">152</span>  void incrementBatchProgress(int batch) {<a name="line.152"></a>
-<span class="sourceLineNo">153</span>    int currentBatch = progress.getBatch();<a name="line.153"></a>
-<span class="sourceLineNo">154</span>    progress.setBatch(currentBatch + batch);<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>   * Progress towards the size limit has been made. Increment internal tracking of size progress<a name="line.158"></a>
-<span class="sourceLineNo">159</span>   */<a name="line.159"></a>
-<span class="sourceLineNo">160</span>  void incrementSizeProgress(long dataSize, long heapSize) {<a name="line.160"></a>
-<span class="sourceLineNo">161</span>    long curDataSize = progress.getDataSize();<a name="line.161"></a>
-<span class="sourceLineNo">162</span>    progress.setDataSize(curDataSize + dataSize);<a name="line.162"></a>
-<span class="sourceLineNo">163</span>    long curHeapSize = progress.getHeapSize();<a name="line.163"></a>
-<span class="sourceLineNo">164</span>    progress.setHeapSize(curHeapSize + heapSize);<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>  int getBatchProgress() {<a name="line.167"></a>
-<span class="sourceLineNo">168</span>    return progress.getBatch();<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>  long getDataSizeProgress() {<a name="line.171"></a>
-<span class="sourceLineNo">172</span>    return progress.getDataSize();<a name="line.172"></a>
-<span class="sourceLineNo">173</span>  }<a name="line.173"></a>
-<span class="sourceLineNo">174</span><a name="line.174"></a>
-<span class="sourceLineNo">175</span>  long getHeapSizeProgress() {<a name="line.175"></a>
-<span class="sourceLineNo">176</span>    return progress.getHeapSize();<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>  void setProgress(int batchProgress, long sizeProgress, long heapSizeProgress) {<a name="line.179"></a>
-<span class="sourceLineNo">180</span>    setBatchProgress(batchProgress);<a name="line.180"></a>
-<span class="sourceLineNo">181</span>    setSizeProgress(sizeProgress, heapSizeProgress);<a name="line.181"></a>
-<span class="sourceLineNo">182</span>  }<a name="line.182"></a>
-<span class="sourceLineNo">183</span><a name="line.183"></a>
-<span class="sourceLineNo">184</span>  void setSizeProgress(long dataSizeProgress, long heapSizeProgress) {<a name="line.184"></a>
-<span class="sourceLineNo">185</span>    progress.setDataSize(dataSizeProgress);<a name="line.185"></a>
-<span class="sourceLineNo">186</span>    progress.setHeapSize(heapSizeProgress);<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>  void setBatchProgress(int batchProgress) {<a name="line.189"></a>
-<span class="sourceLineNo">190</span>    progress.setBatch(batchProgress);<a name="line.190"></a>
-<span class="sourceLineNo">191</span>  }<a name="line.191"></a>
-<span class="sourceLineNo">192</span><a name="line.192"></a>
-<span class="sourceLineNo">193</span>  /**<a name="line.193"></a>
-<span class="sourceLineNo">194</span>   * Clear away any progress that has been made so far. All progress fields are reset to initial<a name="line.194"></a>
-<span class="sourceLineNo">195</span>   * values<a name="line.195"></a>
-<span class="sourceLineNo">196</span>   */<a name="line.196"></a>
-<span class="sourceLineNo">197</span>  void clearProgress() {<a name="line.197"></a>
-<span class="sourceLineNo">198</span>    progress.setFields(0, 0, 0);<a name="line.198"></a>
-<span class="sourceLineNo">199</span>  }<a name="line.199"></a>
-<span class="sourceLineNo">200</span><a name="line.200"></a>
-<span class="sourceLineNo">201</span>  /**<a name="line.201"></a>
-<span class="sourceLineNo">202</span>   * Note that this is not a typical setter. This setter returns the {@link NextState} that was<a name="line.202"></a>
-<span class="sourceLineNo">203</span>   * passed in so that methods can be invoked against the new state. Furthermore, this pattern<a name="line.203"></a>
-<span class="sourceLineNo">204</span>   * allows the {@link NoLimitScannerContext} to cleanly override this setter and simply return the<a name="line.204"></a>
-<span class="sourceLineNo">205</span>   * new state, thus preserving the immutability of {@link NoLimitScannerContext}<a name="line.205"></a>
-<span class="sourceLineNo">206</span>   * @param state<a name="line.206"></a>
-<span class="sourceLineNo">207</span>   * @return The state that was passed in.<a name="line.207"></a>
-<span class="sourceLineNo">208</span>   */<a name="line.208"></a>
-<span class="sourceLineNo">209</span>  NextState setScannerState(NextState state) {<a name="line.209"></a>
-<span class="sourceLineNo">210</span>    if (!NextState.isValidState(state)) {<a name="line.210"></a>
-<span class="sourceLineNo">211</span>      throw new IllegalArgumentException("Cannot set to invalid state: " + state);<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>    this.scannerState = state;<a name="line.214"></a>
-<span class="sourceLineNo">215</span>    return state;<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>  /**<a name="line.218"></a>
-<span class="sourceLineNo">219</span>   * @return true when we have more cells for the current row. This usually because we have reached<a name="line.219"></a>
-<span class="sourceLineNo">220</span>   *         a limit in the middle of a row<a name="line.220"></a>
-<span class="sourceLineNo">221</span>   */<a name="line.221"></a>
-<span class="sourceLineNo">222</span>  boolean mayHaveMoreCellsInRow() {<a name="line.222"></a>
-<span class="sourceLineNo">223</span>    return scannerState == NextState.SIZE_LIMIT_REACHED_MID_ROW ||<a name="line.223"></a>
-<span class="sourceLineNo">224</span>        scannerState == NextState.TIME_LIMIT_REACHED_MID_ROW ||<a name="line.224"></a>
-<span class="sourceLineNo">225</span>        scannerState == NextState.BATCH_LIMIT_REACHED;<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>  /**<a name="line.228"></a>
-<span class="sourceLineNo">229</span>   * @param checkerScope<a name="line.229"></a>
-<span class="sourceLineNo">230</span>   * @return true if the batch limit can be enforced in the checker's scope<a name="line.230"></a>
-<span class="sourceLineNo">231</span>   */<a name="line.231"></a>
-<span class="sourceLineNo">232</span>  boolean hasBatchLimit(LimitScope checkerScope) {<a name="line.232"></a>
-<span class="sourceLineNo">233</span>    return limits.canEnforceBatchLimitFromScope(checkerScope) &amp;&amp; limits.getBatch() &gt; 0;<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>   * @param checkerScope<a name="line.237"></a>
-<span class="sourceLineNo">238</span>   * @return true if the size limit can be enforced in the checker's scope<a name="line.238"></a>
-<span class="sourceLineNo">239</span>   */<a name="line.239"></a>
-<span class="sourceLineNo">240</span>  boolean hasSizeLimit(LimitScope checkerScope) {<a name="line.240"></a>
-<span class="sourceLineNo">241</span>    return limits.canEnforceSizeLimitFromScope(checkerScope)<a name="line.241"></a>
-<span class="sourceLineNo">242</span>        &amp;&amp; (limits.getDataSize() &gt; 0 || limits.getHeapSize() &gt; 0);<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>  /**<a name="line.245"></a>
-<span class="sourceLineNo">246</span>   * @param checkerScope<a name="line.246"></a>
-<span class="sourceLineNo">247</span>   * @return true if the time limit can be enforced in the checker's scope<a name="line.247"></a>
-<span class="sourceLineNo">248</span>   */<a name="line.248"></a>
-<span class="sourceLineNo">249</span>  boolean hasTimeLimit(LimitScope checkerScope) {<a name="line.249"></a>
-<span class="sourceLineNo">250</span>    return limits.canEnforceTimeLimitFromScope(checkerScope) &amp;&amp; limits.getTime() &gt; 0;<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>   * @param checkerScope<a name="line.254"></a>
-<span class="sourceLineNo">255</span>   * @return true if any limit can be enforced within the checker's scope<a name="line.255"></a>
-<span class="sourceLineNo">256</span>   */<a name="line.256"></a>
-<span class="sourceLineNo">257</span>  boolean hasAnyLimit(LimitScope checkerScope) {<a name="line.257"></a>
-<span class="sourceLineNo">258</span>    return hasBatchLimit(checkerScope) || hasSizeLimit(checkerScope) || hasTimeLimit(checkerScope);<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>  /**<a name="line.261"></a>
-<span class="sourceLineNo">262</span>   * @param scope The scope in which the size limit will be enforced<a name="line.262"></a>
+<span class="sourceLineNo">113</span>  ScannerContext(boolean keepProgress, LimitFields limitsToCopy, boolean trackMetrics) {<a name="line.113"></a>
+<span class="sourceLineNo">114</span>    this.limits = new LimitFields();<a name="line.114"></a>
+<span class="sourceLineNo">115</span>    if (limitsToCopy != null) {<a name="line.115"></a>
+<span class="sourceLineNo">116</span>      this.limits.copy(limitsToCopy);<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>    // Progress fields are initialized to 0<a name="line.119"></a>
+<span class="sourceLineNo">120</span>    progress = new ProgressFields(0, 0, 0);<a name="line.120"></a>
+<span class="sourceLineNo">121</span><a name="line.121"></a>
+<span class="sourceLineNo">122</span>    this.keepProgress = keepProgress;<a name="line.122"></a>
+<span class="sourceLineNo">123</span>    this.scannerState = DEFAULT_STATE;<a name="line.123"></a>
+<span class="sourceLineNo">124</span>    this.metrics = trackMetrics ? new ServerSideScanMetrics() : null;<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>  boolean isTrackingMetrics() {<a name="line.127"></a>
+<span class="sourceLineNo">128</span>    return this.metrics != null;<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>   * Get the metrics instance. Should only be called after a call to {@link #isTrackingMetrics()}<a name="line.132"></a>
+<span class="sourceLineNo">133</span>   * has been made to confirm that metrics are indeed being tracked.<a name="line.133"></a>
+<span class="sourceLineNo">134</span>   * @return {@link ServerSideScanMetrics} instance that is tracking metrics for this scan<a name="line.134"></a>
+<span class="sourceLineNo">135</span>   */<a name="line.135"></a>
+<span class="sourceLineNo">136</span>  ServerSideScanMetrics getMetrics() {<a name="line.136"></a>
+<span class="sourceLineNo">137</span>    assert isTrackingMetrics();<a name="line.137"></a>
+<span class="sourceLineNo">138</span>    return this.metrics;<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>   * @return true if the progress tracked so far in this instance will be considered during an<a name="line.142"></a>
+<span class="sourceLineNo">143</span>   *         invocation of {@link InternalScanner#next(java.util.List)} or<a name="line.143"></a>
+<span class="sourceLineNo">144</span>   *         {@link RegionScanner#next(java.util.List)}. false when the progress tracked so far<a name="line.144"></a>
+<span class="sourceLineNo">145</span>   *         should not be considered and should instead be wiped away via {@link #clearProgress()}<a name="line.145"></a>
+<span class="sourceLineNo">146</span>   */<a name="line.146"></a>
+<span class="sourceLineNo">147</span>  boolean getKeepProgress() {<a name="line.147"></a>
+<span class="sourceLineNo">148</span>    return keepProgress;<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>  void setKeepProgress(boolean keepProgress) {<a name="line.151"></a>
+<span class="sourceLineNo">152</span>    this.keepProgress = keepProgress;<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>   * Progress towards the batch limit has been made. Increment internal tracking of batch progress<a name="line.156"></a>
+<span class="sourceLineNo">157</span>   */<a name="line.157"></a>
+<span class="sourceLineNo">158</span>  void incrementBatchProgress(int batch) {<a name="line.158"></a>
+<span class="sourceLineNo">159</span>    int currentBatch = progress.getBatch();<a name="line.159"></a>
+<span class="sourceLineNo">160</span>    progress.setBatch(currentBatch + batch);<a name="line.160"></a>
+<span class="sourceLineNo">161</span>  }<a name="line.161"></a>
+<span class="sourceLineNo">162</span><a name="line.162"></a>
+<span class="sourceLineNo">163</span>  /**<a name="line.163"></a>
+<span class="sourceLineNo">164</span>   * Progress towards the size limit has been made. Increment internal tracking of size progress<a name="line.164"></a>
+<span class="sourceLineNo">165</span>   */<a name="line.165"></a>
+<span class="sourceLineNo">166</span>  void incrementSizeProgress(long dataSize, long heapSize) {<a name="line.166"></a>
+<span class="sourceLineNo">167</span>    long curDataSize = progress.getDataSize();<a name="line.167"></a>
+<span class="sourceLineNo">168</span>    progress.setDataSize(curDataSize + dataSize);<a name="line.168"></a>
+<span class="sourceLineNo">169</span>    long curHeapSize = progress.getHeapSize();<a name="line.169"></a>
+<span class="sourceLineNo">170</span>    progress.setHeapSize(curHeapSize + heapSize);<a name="line.170"></a>
+<span class="sourceLineNo">171</span>  }<a name="line.171"></a>
+<span class="sourceLineNo">172</span><a name="line.172"></a>
+<span class="sourceLineNo">173</span>  int getBatchProgress() {<a name="line.173"></a>
+<span class="sourceLineNo">174</span>    return progress.getBatch();<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>  long getDataSizeProgress() {<a name="line.177"></a>
+<span class="sourceLineNo">178</span>    return progress.getDataSize();<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>  long getHeapSizeProgress() {<a name="line.181"></a>
+<span class="sourceLineNo">182</span>    return progress.getHeapSize();<a name="line.182"></a>
+<span class="sourceLineNo">183</span>  }<a name="line.183"></a>
+<span class="sourceLineNo">184</span><a name="line.184"></a>
+<span class="sourceLineNo">185</span>  void setProgress(int batchProgress, long sizeProgress, long heapSizeProgress) {<a name="line.185"></a>
+<span class="sourceLineNo">186</span>    setBatchProgress(batchProgress);<a name="line.186"></a>
+<span class="sourceLineNo">187</span>    setSizeProgress(sizeProgress, heapSizeProgress);<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>  void setSizeProgress(long dataSizeProgress, long heapSizeProgress) {<a name="line.190"></a>
+<span class="sourceLineNo">191</span>    progress.setDataSize(dataSizeProgress);<a name="line.191"></a>
+<span class="sourceLineNo">192</span>    progress.setHeapSize(heapSizeProgress);<a name="line.192"></a>
+<span class="sourceLineNo">193</span>  }<a name="line.193"></a>
+<span class="sourceLineNo">194</span><a name="line.194"></a>
+<span class="sourceLineNo">195</span>  void setBatchProgress(int batchProgress) {<a name="line.195"></a>
+<span class="sourceLineNo">196</span>    progress.setBatch(batchProgress);<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>   * Clear away any progress that has been made so far. All progress fields are reset to initial<a name="line.200"></a>
+<span class="sourceLineNo">201</span>   * values<a name="line.201"></a>
+<span class="sourceLineNo">202</span>   */<a name="line.202"></a>
+<span class="sourceLineNo">203</span>  void clearProgress() {<a name="line.203"></a>
+<span class="sourceLineNo">204</span>    progress.setFields(0, 0, 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>  /**<a name="line.207"></a>
+<span class="sourceLineNo">208</span>   * Note that this is not a typical setter. This setter returns the {@link NextState} that was<a name="line.208"></a>
+<span class="sourceLineNo">209</span>   * passed in so that methods can be invoked against the new state. Furthermore, this pattern<a name="line.209"></a>
+<span class="sourceLineNo">210</span>   * allows the {@link NoLimitScannerContext} to cleanly override this setter and simply return the<a name="line.210"></a>
+<span class="sourceLineNo">211</span>   * new state, thus preserving the immutability of {@link NoLimitScannerContext}<a name="line.211"></a>
+<span class="sourceLineNo">212</span>   * @param state<a name="line.212"></a>
+<span class="sourceLineNo">213</span>   * @return The state that was passed in.<a name="line.213"></a>
+<span class="sourceLineNo">214</span>   */<a name="line.214"></a>
+<span class="sourceLineNo">215</span>  NextState setScannerState(NextState state) {<a name="line.215"></a>
+<span class="sourceLineNo">216</span>    if (!NextState.isValidState(state)) {<a name="line.216"></a>
+<span class="sourceLineNo">217</span>      throw new IllegalArgumentException("Cannot set to invalid state: " + state);<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>    this.scannerState = state;<a name="line.220"></a>
+<span class="sourceLineNo">221</span>    return state;<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>  /**<a name="line.224"></a>
+<span class="sourceLineNo">225</span>   * @return true when we have more cells for the current row. This usually because we have reached<a name="line.225"></a>
+<span class="sourceLineNo">226</span>   *         a limit in the middle of a row<a name="line.226"></a>
+<span class="sourceLineNo">227</span>   */<a name="line.227"></a>
+<span class="sourceLineNo">228</span>  boolean mayHaveMoreCellsInRow() {<a name="line.228"></a>
+<span class="sourceLineNo">229</span>    return scannerState == NextState.SIZE_LIMIT_REACHED_MID_ROW ||<a name="line.229"></a>
+<span class="sourceLineNo">230</span>        scannerState == NextState.TIME_LIMIT_REACHED_MID_ROW ||<a name="line.230"></a>
+<span class="sourceLineNo">231</span>        scannerState == NextState.BATCH_LIMIT_REACHED;<a name="line.231"></a>
+<span class="sourceLineNo">232</span>  }<a name="line.232"></a>
+<span class="sourceLineNo">233</span><a name="line.233"></a>
+<span class="sourceLineNo">234</span>  /**<a name="line.234"></a>
+<span class="sourceLineNo">235</span>   * @param checkerScope<a name="line.235"></a>
+<span class="sourceLineNo">236</span>   * @return true if the batch limit can be enforced in the checker's scope<a name="line.236"></a>
+<span class="sourceLineNo">237</span>   */<a name="line.237"></a>
+<span class="sourceLineNo">238</span>  boolean hasBatchLimit(LimitScope checkerScope) {<a name="line.238"></a>
+<span class="sourceLineNo">239</span>    return limits.canEnforceBatchLimitFromScope(checkerScope) &amp;&amp; limits.getBatch() &gt; 0;<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>   * @param checkerScope<a name="line.243"></a>
+<span class="sourceLineNo">244</span>   * @return true if the size limit can be enforced in the checker's scope<a name="line.244"></a>
+<span class="sourceLineNo">245</span>   */<a name="line.245"></a>
+<span class="sourceLineNo">246</span>  boolean hasSizeLimit(LimitScope checkerScope) {<a name="line.246"></a>
+<span class="sourceLineNo">247</span>    return limits.canEnforceSizeLimitFromScope(checkerScope)<a name="line.247"></a>
+<span class="sourceLineNo">248</span>        &amp;&amp; (limits.getDataSize() &gt; 0 || limits.getHeapSize() &gt; 0);<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>
+<span class="sourceLineNo">252</span>   * @param checkerScope<a name="line.252"></a>
+<span class="sourceLineNo">253</span>   * @return true if the time limit can be enforced in the checker's scope<a name="line.253"></a>
+<span class="sourceLineNo">254</span>   */<a name="line.254"></a>
+<span class="sourceLineNo">255</span>  boolean hasTimeLimit(LimitScope checkerScope) {<a name="line.255"></a>
+<span class="sourceLineNo">256</span>    return limits.canEnforceTimeLimitFromScope(checkerScope) &amp;&amp;<a name="line.256"></a>
+<span class="sourceLineNo">257</span>      (limits.getTime() &gt; 0 || returnImmediately);<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>   * @param checkerScope<a name="line.261"></a>
+<span class="sourceLineNo">262</span>   * @return true if any limit can be enforced within the checker's scope<a name="line.262"></a>
 <span class="sourceLineNo">263</span>   */<a name="line.263"></a>
-<span class="sourceLineNo">264</span>  void setSizeLimitScope(LimitScope scope) {<a name="line.264"></a>
-<span class="sourceLineNo">265</span>    limits.setSizeScope(scope);<a name="line.265"></a>
+<span class="sourceLineNo">264</span>  boolean hasAnyLimit(LimitScope checkerScope) {<a name="line.264"></a>
+<span class="sourceLineNo">265</span>    return hasBatchLimit(checkerScope) || hasSizeLimit(checkerScope) || hasTimeLimit(checkerScope);<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>  /**<a name="line.268"></a>
-<span class="sourceLineNo">269</span>   * @param scope The scope in which the time limit will be enforced<a name="line.269"></a>
+<span class="sourceLineNo">269</span>   * @param scope The scope in which the size limit will be enforced<a name="line.269"></a>
 <span class="sourceLineNo">270</span>   */<a name="line.270"></a>
-<span class="sourceLineNo">271</span>  void setTimeLimitScope(LimitScope scope) {<a name="line.271"></a>
-<span class="sourceLineNo">272</span>    limits.setTimeScope(scope);<a name="line.272"></a>
+<span class="sourceLineNo">271</span>  void setSizeLimitScope(LimitScope scope) {<a name="line.271"></a>
+<span class="sourceLineNo">272</span>    limits.setSizeScope(scope);<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>  int getBatchLimit() {<a name="line.275"></a>
-<span class="sourceLineNo">276</span>    return limits.getBatch();<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>  long getDataSizeLimit() {<a name="line.279"></a>
-<span class="sourceLineNo">280</span>    return limits.getDataSize();<a name="line.280"></a>
-<span class="sourceLineNo">281</span>  }<a name="line.281"></a>
-<span class="sourceLineNo">282</span><a name="line.282"></a>
-<span class="sourceLineNo">283</span>  long getTimeLimit() {<a name="line.283"></a>
-<span class="sourceLineNo">284</span>    return limits.getTime();<a name="line.284"></a>
-<span class="sourceLineNo">285</span>  }<a name="line.285"></a>
-<span class="sourceLineNo">286</span><a name="line.286"></a>
-<span class="sourceLineNo">287</span>  /**<a name="line.287"></a>
-<span class="sourceLineNo">288</span>   * @param checkerScope The scope that the limit is being checked from<a name="line.288"></a>
-<span class="sourceLineNo">289</span>   * @return true when the limit is enforceable from the checker's scope and it has been reached<a name="line.289"></a>
-<span class="sourceLineNo">290</span>   */<a name="line.290"></a>
-<span class="sourceLineNo">291</span>  boolean checkBatchLimit(LimitScope checkerScope) {<a name="line.291"></a>
-<span class="sourceLineNo">292</span>    return hasBatchLimit(checkerScope) &amp;&amp; progress.getBatch() &gt;= limits.getBatch();<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>  /**<a name="line.295"></a>
-<span class="sourceLineNo">296</span>   * @param checkerScope The scope that the limit is being checked from<a name="line.296"></a>
-<span class="sourceLineNo">297</span>   * @return true when the limit is enforceable from the checker's scope and it has been reached<a name="line.297"></a>
-<span class="sourceLineNo">298</span>   */<a name="line.298"></a>
-<span class="sourceLineNo">299</span>  boolean checkSizeLimit(LimitScope checkerScope) {<a name="line.299"></a>
-<span class="sourceLineNo">300</span>    return hasSizeLimit(checkerScope) &amp;&amp; (progress.getDataSize() &gt;= limits.getDataSize()<a name="line.300"></a>
-<span class="sourceLineNo">301</span>        || progress.getHeapSize() &gt;= limits.getHeapSize());<a name="line.301"></a>
-<span class="sourceLineNo">302</span>  }<a name="line.302"></a>
-<span class="sourceLineNo">303</span><a name="line.303"></a>
-<span class="sourceLineNo">304</span>  /**<a name="line.304"></a>
-<span class="sourceLineNo">305</span>   * @param checkerScope The scope that the limit is being checked from. The time limit is always<a name="line.305"></a>
-<span class="sourceLineNo">306</span>   *          checked against {@link System#currentTimeMillis()}<a name="line.306"></a>
-<span class="sourceLineNo">307</span>   * @return true when the limit is enforceable from the checker's scope and it has been reached<a name="line.307"></a>
-<span class="sourceLineNo">308</span>   */<a name="line.308"></a>
-<span class="sourceLineNo">309</span>  boolean checkTimeLimit(LimitScope checkerScope) {<a name="line.309"></a>
-<span class="sourceLineNo">310</span>    return hasTimeLimit(checkerScope) &amp;&amp; (System.currentTimeMillis() &gt;= limits.getTime());<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>   * @param checkerScope The scope that the limits are being checked from<a name="line.314"></a>
-<span class="sourceLineNo">315</span>   * @return true when some limit is enforceable from the checker's scope and it has been reached<a name="line.315"></a>
-<span class="sourceLineNo">316</span>   */<a name="line.316"></a>
-<span class="sourceLineNo">317</span>  boolean checkAnyLimitReached(LimitScope checkerScope) {<a name="line.317"></a>
-<span class="sourceLineNo">318</span>    return checkSizeLimit(checkerScope) || checkBatchLimit(checkerScope)<a name="line.318"></a>
-<span class="sourceLineNo">319</span>        || checkTimeLimit(checkerScope);<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>  Cell getLastPeekedCell() {<a name="line.322"></a>
-<span class="sourceLineNo">323</span>    return lastPeekedCell;<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>  void setLastPeekedCell(Cell lastPeekedCell) {<a name="line.326"></a>
-<span class="sourceLineNo">327</span>    this.lastPeekedCell = lastPeekedCell;<a name="line.327"></a>
+<span class="sourceLineNo">275</span>  /**<a name="line.275"></a>
+<span class="sourceLineNo">276</span>   * @param scope The scope in which the time limit will be enforced<a name="line.276"></a>
+<span class="sourceLineNo">277</span>   */<a name="line.277"></a>
+<span class="sourceLineNo">278</span>  void setTimeLimitScope(LimitScope scope) {<a name="line.278"></a>
+<span class="sourceLineNo">279</span>    limits.setTimeScope(scope);<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>  int getBatchLimit() {<a name="line.282"></a>
+<span class="sourceLineNo">283</span>    return limits.getBatch();<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>  long getDataSizeLimit() {<a name="line.286"></a>
+<span class="sourceLineNo">287</span>    return limits.getDataSize();<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>  long getTimeLimit() {<a name="line.290"></a>
+<span class="sourceLineNo">291</span>    return limits.getTime();<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>   * @param checkerScope The scope that the limit is being checked from<a name="line.295"></a>
+<span class="sourceLineNo">296</span>   * @return true when the limit is enforceable from the checker's scope and it has been reached<a name="line.296"></a>
+<span class="sourceLineNo">297</span>   */<a name="line.297"></a>
+<span class="sourceLineNo">298</span>  boolean checkBatchLimit(LimitScope checkerScope) {<a name="line.298"></a>
+<span class="sourceLineNo">299</span>    return hasBatchLimit(checkerScope) &amp;&amp; progress.getBatch() &gt;= limits.getBatch();<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 checkerScope The scope that the limit is being checked from<a name="line.303"></a>
+<span class="sourceLineNo">304</span>   * @return true when the limit is enforceable from the checker's scope and it has been reached<a name="line.304"></a>
+<span class="sourceLineNo">305</span>   */<a name="line.305"></a>
+<span class="sourceLineNo">306</span>  boolean checkSizeLimit(LimitScope checkerScope) {<a name="line.306"></a>
+<span class="sourceLineNo">307</span>    return hasSizeLimit(checkerScope) &amp;&amp; (progress.getDataSize() &gt;= limits.getDataSize()<a name="line.307"></a>
+<span class="sourceLineNo">308</span>        || progress.getHeapSize() &gt;= limits.getHeapSize());<a name="line.308"></a>
+<span class="sourceLineNo">309</span>  }<a name="line.309"></a>
+<span class="sourceLineNo">310</span><a name="line.310"></a>
+<span class="sourceLineNo">311</span>  /**<a name="line.311"></a>
+<span class="sourceLineNo">312</span>   * @param checkerScope The scope that the limit is being checked from. The time limit is always<a name="line.312"></a>
+<span class="sourceLineNo">313</span>   *          checked against {@link System#currentTimeMillis()}<a name="line.313"></a>
+<span class="sourceLineNo">314</span>   * @return true when the limit is enforceable from the checker's scope and it has been reached<a name="line.314"></a>
+<span class="sourceLineNo">315</span>   */<a name="line.315"></a>
+<span class="sourceLineNo">316</span>  boolean checkTimeLimit(LimitScope checkerScope) {<a name="line.316"></a>
+<span class="sourceLineNo">317</span>    return hasTimeLimit(checkerScope) &amp;&amp;<a name="line.317"></a>
+<span class="sourceLineNo">318</span>      (returnImmediately || System.currentTimeMillis() &gt;= limits.getTime());<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>   * @param checkerScope The scope that the limits are being checked from<a name="line.322"></a>
+<span class="sourceLineNo">323</span>   * @return true when some limit is enforceable from the checker's scope and it has been reached<a name="line.323"></a>
+<span class="sourceLineNo">324</span>   */<a name="line.324"></a>
+<span class="sourceLineNo">325</span>  boolean checkAnyLimitReached(LimitScope checkerScope) {<a name="line.325"></a>
+<span class="sourceLineNo">326</span>    return checkSizeLimit(checkerScope) || checkBatchLimit(checkerScope)<a name="line.326"></a>
+<span class="sourceLineNo">327</span>        || checkTimeLimit(checkerScope);<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>  @Override<a name="line.330"></a>
-<span class="sourceLineNo">331</span>  public String toString() {<a name="line.331"></a>
-<span class="sourceLineNo">332</span>    StringBuilder sb = new StringBuilder();<a name="line.332"></a>
-<span class="sourceLineNo">333</span>    sb.append("{");<a name="line.333"></a>
-<span class="sourceLineNo">334</span><a name="line.334"></a>
-<span class="sourceLineNo">335</span>    sb.append("limits:");<a name="line.335"></a>
-<span class="sourceLineNo">336</span>    sb.append(limits);<a name="line.336"></a>
+<span class="sourceLineNo">330</span>  Cell getLastPeekedCell() {<a name="line.330"></a>
+<span class="sourceLineNo">331</span>    return lastPeekedCell;<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>  void setLastPeekedCell(Cell lastPeekedCell) {<a name="line.334"></a>
+<span class="sourceLineNo">335</span>    this.lastPeekedCell = lastPeekedCell;<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>    sb.append(", progress:");<a name="line.338"></a>
-<span class="sourceLineNo">339</span>    sb.append(progress);<a name="line.339"></a>
-<span class="sourceLineNo">340</span><a name="line.340"></a>
-<span class="sourceLineNo">341</span>    sb.append(", keepProgress:");<a name="line.341"></a>
-<span class="sourceLineNo">342</span>    sb.append(keepProgress);<a name="line.342"></a>
-<span class="sourceLineNo">343</span><a name="line.343"></a>
-<span class="sourceLineNo">344</span>    sb.append(", state:");<a name="line.344"></a>
-<span class="sourceLineNo">345</span>    sb.append(scannerState);<a name="line.345"></a>
+<span class="sourceLineNo">338</span>  void returnImmediately() {<a name="line.338"></a>
+<span class="sourceLineNo">339</span>    this.returnImmediately = true;<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>  @Override<a name="line.342"></a>
+<span class="sourceLineNo">343</span>  public String toString() {<a name="line.343"></a>
+<span class="sourceLineNo">344</span>    StringBuilder sb = new StringBuilder();<a name="line.344"></a>
+<span class="sourceLineNo">345</span>    sb.append("{");<a name="line.345"></a>
 <span class="sourceLineNo">346</span><a name="line.346"></a>
-<span class="sourceLineNo">347</span>    sb.append("}");<a name="line.347"></a>
-<span class="sourceLineNo">348</span>    return sb.toString();<a name="line.348"></a>
-<span class="sourceLineNo">349</span>  }<a name="line.349"></a>
-<span class="sourceLineNo">350</span><a name="line.350"></a>
-<span class="sourceLineNo">351</span>  public static Builder newBuilder() {<a name="line.351"></a>
-<span class="sourceLineNo">352</span>    return new Builder();<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 static Builder newBuilder(boolean keepProgress) {<a name="line.355"></a>
-<span class="sourceLineNo">356</span>    return new Builder(keepProgress);<a name="line.356"></a>
-<span class="sourceLineNo">357</span>  }<a name="line.357"></a>
+<span class="sourceLineNo">347</span>    sb.append("limits:");<a name="line.347"></a>
+<span class="sourceLineNo">348</span>    sb.append(limits);<a name="line.348"></a>
+<span class="sourceLineNo">349</span><a name="line.349"></a>
+<span class="sourceLineNo">350</span>    sb.append(", progress:");<a name="line.350"></a>
+<span class="sourceLineNo">351</span>    sb.append(progress);<a name="line.351"></a>
+<span class="sourceLineNo">352</span><a name="line.352"></a>
+<span class="sourceLineNo">353</span>    sb.append(", keepProgress:");<a name="line.353"></a>
+<span class="sourceLineNo">354</span>    sb.append(keepProgress);<a name="line.354"></a>
+<span class="sourceLineNo">355</span><a name="line.355"></a>
+<span class="sourceLineNo">356</span>    sb.append(", state:");<a name="line.356"></a>
+<span class="sourceLineNo">357</span>    sb.append(scannerState);<a name="line.357"></a>
 <span class="sourceLineNo">358</span><a name="line.358"></a>
-<span class="sourceLineNo">359</span>  public static final class Builder {<a name="line.359"></a>
-<span class="sourceLineNo">360</span>    boolean keepProgress = DEFAULT_KEEP_PROGRESS;<a name="line.360"></a>
-<span class="sourceLineNo">361</span>    boolean trackMetrics = false;<a name="line.361"></a>
-<span class="sourceLineNo">362</span>    LimitFields limits = new LimitFields();<a name="line.362"></a>
-<span class="sourceLineNo">363</span><a name="line.363"></a>
-<span class="sourceLineNo">364</span>    private Builder() {<a name="line.364"></a>
-<span class="sourceLineNo">365</span>    }<a name="line.365"></a>
+<span class="sourceLineNo">359</span>    sb.append("}");<a name="line.359"></a>
+<span class="sourceLineNo">360</span>    return sb.toString();<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 static Builder newBuilder() {<a name="line.363"></a>
+<span class="sourceLineNo">364</span>    return new Builder();<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>    private Builder(boolean keepProgress) {<a name="line.367"></a>
-<span class="sourceLineNo">368</span>      this.keepProgress = keepProgress;<a name="line.368"></a>
-<span class="sourceLineNo">369</span>    }<a name="line.369"></a>
+<span class="sourceLineNo">367</span>  public static Builder newBuilder(boolean keepProgress) {<a name="line.367"></a>
+<span class="sourceLineNo">368</span>    return new Builder(keepProgress);<a name="line.368"></a>
+<span class="sourceLineNo">369</span>  }<a name="line.369"></a>
 <span class="sourceLineNo">370</span><a name="line.370"></a>
-<span class="sourceLineNo">371</span>    public Builder setKeepProgress(boolean keepProgress) {<a name="line.371"></a>
-<span class="sourceLineNo">372</span>      this.keepProgress = keepProgress;<a name="line.372"></a>
-<span class="sourceLineNo">373</span>      return this;<a name="line.373"></a>
-<span class="sourceLineNo">374</span>    }<a name="line.374"></a>
+<span class="sourceLineNo">371</span>  public static final class Builder {<a name="line.371"></a>
+<span class="sourceLineNo">372</span>    boolean keepProgress = DEFAULT_KEEP_PROGRESS;<a name="line.372"></a>
+<span class="sourceLineNo">373</span>    boolean trackMetrics = false;<a name="line.373"></a>
+<span class="sourceLineNo">374</span>    LimitFields limits = new LimitFields();<a name="line.374"></a>
 <span class="sourceLineNo">375</span><a name="line.375"></a>
-<span class="sourceLineNo">376</span>    public Builder setTrackMetrics(boolean trackMetrics) {<a name="line.376"></a>
-<span class="sourceLineNo">377</span>      this.trackMetrics = trackMetrics;<a name="line.377"></a>
-<span class="sourceLineNo">378</span>      return this;<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 Builder setSizeLimit(LimitScope sizeScope, long dataSizeLimit, long heapSizeLimit) {<a name="line.381"></a>
-<span class="sourceLineNo">382</span>      limits.setDataSize(dataSizeLimit);<a name="line.382"></a>
-<span class="sourceLineNo">383</span>      limits.setHeapSize(heapSizeLimit);<a name="line.383"></a>
-<span class="sourceLineNo">384</span>      limits.setSizeScope(sizeScope);<a name="line.384"></a>
+<span class="sourceLineNo">376</span>    private Builder() {<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>    private Builder(boolean keepProgress) {<a name="line.379"></a>
+<span class="sourceLineNo">380</span>      this.keepProgress = keepProgress;<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>    public Builder setKeepProgress(boolean keepProgress) {<a name="line.383"></a>
+<span class="sourceLineNo">384</span>      this.keepProgress = keepProgress;<a name="line.384"></a>
 <span class="sourceLineNo">385</span>      return this;<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 Builder setTimeLimit(LimitScope timeScope, long timeLimit) {<a name="line.388"></a>
-<span class="sourceLineNo">389</span>      limits.setTime(timeLimit);<a name="line.389"></a>
-<span class="sourceLineNo">390</span>      limits.setTimeScope(timeScope);<a name="line.390"></a>
-<span class="sourceLineNo">391</span>      return this;<a name="line.391"></a>
-<span class="sourceLineNo">392</span>    }<a name="line.392"></a>
-<span class="sourceLineNo">393</span><a name="line.393"></a>
-<span class="sourceLineNo">394</span>    public Builder setBatchLimit(int batchLimit) {<a name="line.394"></a>
-<span class="sourceLineNo">395</span>      limits.setBatch(batchLimit);<a name="line.395"></a>
-<span class="sourceLineNo">396</span>      return this;<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>    public ScannerContext build() {<a name="line.399"></a>
-<span class="sourceLineNo">400</span>      return new ScannerContext(keepProgress, limits, trackMetrics);<a name="line.400"></a>
-<span class="sourceLineNo">401</span>    }<a name="line.401"></a>
-<span class="sourceLineNo">402</span>  }<a name="line.402"></a>
-<span class="sourceLineNo">403</span><a name="line.403"></a>
-<span class="sourceLineNo">404</span>  /**<a name="line.404"></a>
-<span class="sourceLineNo">405</span>   * The possible states a scanner may be in following a call to {@link InternalScanner#next(List)}<a name="line.405"></a>
-<span class="sourceLineNo">406</span>   */<a name="line.406"></a>
-<span class="sourceLineNo">407</span>  public enum NextState {<a name="line.407"></a>
-<span class="sourceLineNo">408</span>    MORE_VALUES(true, false),<a name="line.408"></a>
-<span class="sourceLineNo">409</span>    NO_MORE_VALUES(false, false),<a name="line.409"></a>
-<span class="sourceLineNo">410</span>    SIZE_LIMIT_REACHED(true, true),<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>     * Special case of size limit reached to indicate that the size limit was reached in the middle<a name="line.413"></a>
-<span class="sourceLineNo">414</span>     * of a row and thus a partial results was formed<a name="line.414"></a>
-<span class="sourceLineNo">415</span>     */<a name="line.415"></a>
-<span class="sourceLineNo">416</span>    SIZE_LIMIT_REACHED_MID_ROW(true, true),<a name="line.416"></a>
-<span class="sourceLineNo">417</span>    TIME_LIMIT_REACHED(true, true),<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>     * Special case of time limit reached to indicate that the time limit was reached in the middle<a name="line.420"></a>
-<span class="sourceLineNo">421</span>     * of a row and thus a partial results was formed<a name="line.421"></a>
-<span class="sourceLineNo">422</span>     */<a name="line.422"></a>
-<span class="sourceLineNo">423</span>    TIME_LIMIT_REACHED_MID_ROW(true, true),<a name="line.423"></a>
-<span class="sourceLineNo">424</span>    BATCH_LIMIT_REACHED(true, true);<a name="line.424"></a>
-<span class="sourceLineNo">425</span><a name="line.425"></a>
-<span class="sourceLineNo">426</span>    private final boolean moreValues;<a name="line.426"></a>
-<span class="sourceLineNo">427</span>    private final boolean limitReached;<a name="line.427"></a>
-<span class="sourceLineNo">428</span><a name="line.428"></a>
-<span class="sourceLineNo">429</span>    private NextState(boolean moreValues, boolean limitReached) {<a name="line.429"></a>
-<span class="sourceLineNo">430</span>      this.moreValues = moreValues;<a name="line.430"></a>
-<span class="sourceLineNo">431</span>      this.limitReached = limitReached;<a name="line.431"></a>
-<span class="sourceLineNo">432</span>    }<a name="line.432"></a>
-<span class="sourceLineNo">433</span><a name="line.433"></a>
-<span class="sourceLineNo">434</span>    /**<a name="line.434"></a>
-<span class="sourceLineNo">435</span>     * @return true when the state indicates that more values may follow those that have been<a name="line.435"></a>
-<span class="sourceLineNo">436</span>     *         returned<a name="line.436"></a>
-<span class="sourceLineNo">437</span>     */<a name="line.437"></a>
-<span class="sourceLineNo">438</span>    public boolean hasMoreValues() {<a name="line.438"></a>
-<span class="sourceLineNo">439</span>      return this.moreValues;<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>     * @return true when the state indicates that a limit has been reached and scan should stop<a name="line.443"></a>
-<span class="sourceLineNo">444</span>     */<a name="line.444"></a>
-<span class="sourceLineNo">445</span>    public boolean limitReached() {<a name="line.445"></a>
-<span class="sourceLineNo">446</span>      return this.limitReached;<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>    public static boolean isValidState(NextState state) {<a name="line.449"></a>
-<span class="sourceLineNo">450</span>      return state != null;<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>    public static boolean hasMoreValues(NextState state) {<a name="line.453"></a>
-<span class="sourceLineNo">454</span>      return isValidState(state) &amp;&amp; state.hasMoreValues();<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>  /**<a name="line.458"></a>
-<span class="sourceLineNo">459</span>   * The various scopes where a limit can be enforced. Used to differentiate when a limit should be<a name="line.459"></a>
-<span class="sourceLineNo">460</span>   * enforced or not.<a name="line.460"></a>
-<span class="sourceLineNo">461</span>   */<a name="line.461"></a>
-<span class="sourceLineNo">462</span>  public enum LimitScope {<a name="line.462"></a>
-<span class="sourceLineNo">463</span>    /**<a name="line.463"></a>
-<span class="sourceLineNo">464</span>     * Enforcing a limit between rows means that the limit will not be considered until all the<a name="line.464"></a>
-<span class="sourceLineNo">465</span>     * cells for a particular row have been retrieved<a name="line.465"></a>
-<span class="sourceLineNo">466</span>     */<a name="line.466"></a>
-<span class="sourceLineNo">467</span>    BETWEEN_ROWS(0),<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>     * Enforcing a limit between cells means that the limit will be considered after each full cell<a name="line.470"></a>
-<span class="sourceLineNo">471</span>     * has been retrieved<a name="line.471"></a>
-<span class="sourceLineNo">472</span>     */<a name="line.472"></a>
-<span class="sourceLineNo">473</span>    BETWEEN_CELLS(1);<a name="line.473"></a>
-<span class="sourceLineNo">474</span><a name="line.474"></a>
+<span class="sourceLineNo">388</span>    public Builder setTrackMetrics(boolean trackMetrics) {<a name="line.388"></a>
+<span class="sourceLineNo">389</span>      this.trackMetrics = trackMetrics;<a name="line.389"></a>
+<span class="sourceLineNo">390</span>      return this;<a name="line.390"></a>
+<span class="sourceLineNo">391</span>    }<a name="line.391"></a>
+<span class="sourceLineNo">392</span><a name="line.392"></a>
+<span class="sourceLineNo">393</span>    public Builder setSizeLimit(LimitScope sizeScope, long dataSizeLimit, long heapSizeLimit) {<a name="line.393"></a>
+<span class="sourceLineNo">394</span>      limits.setDataSize(dataSizeLimit);<a name="line.394"></a>
+<span class="sourceLineNo">395</span>      limits.setHeapSize(heapSizeLimit);<a name="line.395"></a>
+<span class="sourceLineNo">396</span>      limits.setSizeScope(sizeScope);<a name="line.396"></a>
+<span class="sourceLineNo">397</span>      return this;<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>    public Builder setTimeLimit(LimitScope timeScope, long timeLimit) {<a name="line.400"></a>
+<span class="sourceLineNo">401</span>      limits.setTime(timeLimit);<a name="line.401"></a>
+<span class="sourceLineNo">402</span>      limits.setTimeScope(timeScope);<a name="line.402"></a>
+<span class="sourceLineNo">403</span>      return this;<a name="line.403"></a>
+<span class="sourceLineNo">404</span>    }<a name="line.404"></a>
+<span class="sourceLineNo">405</span><a name="line.405"></a>
+<span class="sourceLineNo">406</span>    public Builder setBatchLimit(int batchLimit) {<a name="line.406"></a>
+<span class="sourceLineNo">407</span>      limits.setBatch(batchLimit);<a name="line.407"></a>
+<span class="sourceLineNo">408</span>      return this;<a name="line.408"></a>
+<span class="sourceLineNo">409</span>    }<a name="line.409"></a>
+<span class="sourceLineNo">410</span><a name="line.410"></a>
+<span class="sourceLineNo">411</span>    public ScannerContext build() {<a name="line.411"></a>
+<span class="sourceLineNo">412</span>      return new ScannerContext(keepProgress, limits, trackMetrics);<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><a name="line.415"></a>
+<span class="sourceLineNo">416</span>  /**<a name="line.416"></a>
+<span class="sourceLineNo">417</span>   * The possible states a scanner may be in following a call to {@link InternalScanner#next(List)}<a name="line.417"></a>
+<span class="sourceLineNo">418</span>   */<a name="line.418"></a>
+<span class="sourceLineNo">419</span>  public enum NextState {<a name="line.419"></a>
+<span class="sourceLineNo">420</span>    MORE_VALUES(true, false),<a name="line.420"></a>
+<span class="sourceLineNo">421</span>    NO_MORE_VALUES(false, false),<a name="line.421"></a>
+<span class="sourceLineNo">422</span>    SIZE_LIMIT_REACHED(true, true),<a name="line.422"></a>
+<span class="sourceLineNo">423</span><a name="line.423"></a>
+<span class="sourceLineNo">424</span>    /**<a name="line.424"></a>
+<span class="sourceLineNo">425</span>     * Special case of size limit reached to indicate that the size limit was reached in the middle<a name="line.425"></a>
+<span class="sourceLineNo">426</span>     * of a row and thus a partial results was formed<a name="line.426"></a>
+<span class="sourceLineNo">427</span>     */<a name="line.427"></a>
+<span class="sourceLineNo">428</span>    SIZE_LIMIT_REACHED_MID_ROW(true, true),<a name="line.428"></a>
+<span class="sourceLineNo">429</span>    TIME_LIMIT_REACHED(true, true),<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>     * Special case of time limit reached to indicate that the time limit was reached in the middle<a name="line.432"></a>
+<span class="sourceLineNo">433</span>     * of a row and thus a partial results was formed<a name="line.433"></a>
+<span class="sourceLineNo">434</span>     */<a name="line.434"></a>
+<span class="sourceLineNo">435</span>    TIME_LIMIT_REACHED_MID_ROW(true, true),<a name="line.435"></a>
+<span class="sourceLineNo">436</span>    BATCH_LIMIT_REACHED(true, true);<a name="line.436"></a>
+<span class="sourceLineNo">437</span><a name="line.437"></a>
+<span class="sourceLineNo">438</span>    private final boolean moreValues;<a name="line.438"></a>
+<span class="sourceLineNo">439</span>    private final boolean limitReached;<a name="line.439"></a>
+<span class="sourceLineNo">440</span><a name="line.440"></a>
+<span class="sourceLineNo">441</span>    private NextState(boolean moreValues, boolean limitReached) {<a name="line.441"></a>
+<span class="sourceLineNo">442</span>      this.moreValues = moreValues;<a name="line.442"></a>
+<span class="sourceLineNo">443</span>      this.limitReached = limitReached;<a name="line.443"></a>
+<span class="sourceLineNo">444</span>    }<a name="line.444"></a>
+<span class="sourceLineNo">445</span><a name="line.445"></a>
+<span class="sourceLineNo">446</span>    /**<a name="line.446"></a>
+<span class="sourceLineNo">447</span>     * @return true when the state indicates that more values may follow those that have been<a name="line.447"></a>
+<span class="sourceLineNo">448</span>     *         returned<a name="line.448"></a>
+<span class="sourceLineNo">449</span>     */<a name="line.449"></a>
+<span class="sourceLineNo">450</span>    public boolean hasMoreValues() {<a name="line.450"></a>
+<span class="sourceLineNo">451</span>      return this.moreValues;<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>     * @return true when the state indicates that a limit has been reached and scan should stop<a name="line.455"></a>
+<span class="sourceLineNo">456</span>     */<a name="line.456"></a>
+<span class="sourceLineNo">457</span>    public boolean limitReached() {<a name="line.457"></a>
+<span class="sourceLineNo">458</span>      return this.limitReached;<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>    public static boolean isValidState(NextState state) {<a name="line.461"></a>
+<span class="sourceLineNo">462</span>      return state != 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>    public static boolean hasMoreValues(NextState state) {<a name="line.465"></a>
+<span class="sourceLineNo">466</span>      return isValidState(state) &amp;&amp; state.hasMoreValues();<a name="line.466"></a>
+<span class="sourceLineNo">467</span>    }<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>   * The various scopes where a limit can be enforced. Used to differentiate when a limit should be<a name="line.471"></a>
+<span class="sourceLineNo">472</span>   * enforced or not.<a name="line.472"></a>
+<span class="sourceLineNo">473</span>   */<a name="line.473"></a>
+<span class="sourceLineNo">474</span>  public enum LimitScope {<a name="line.474"></a>
 <span class="sourceLineNo">475</span>    /**<a name="line.475"></a>
-<span class="sourceLineNo">476</span>     * When enforcing a limit, we must check that the scope is appropriate for enforcement.<a name="line.476"></a>
-<span class="sourceLineNo">477</span>     * &lt;p&gt;<a name="line.477"></a>
-<span class="sourceLineNo">478</span>     * To communicate this concept, each scope has a depth. A limit will be enforced if the depth of<a name="line.478"></a>
-<span class="sourceLineNo">479</span>     * the checker's scope is less than or equal to the limit's scope. This means that when checking<a name="line.479"></a>
-<span class="sourceLineNo">480</span>     * limits, the checker must know their own scope (i.e. are they checking the limits between<a name="line.480"></a>
-<span class="sourceLineNo">481</span>     * rows, between cells, etc...)<a name="line.481"></a>
-<span class="sourceLineNo">482</span>     */<a name="line.482"></a>
-<span class="sourceLineNo">483</span>    final int depth;<a name="line.483"></a>
-<span class="sourceLineNo">484</span><a name="line.484"></a>
-<span class="sourceLineNo">485</span>    LimitScope(int depth) {<a name="line.485"></a>
-<span class="sourceLineNo">486</span>      this.depth = depth;<a name="line.486"></a>
-<span class="sourceLineNo">487</span>    }<a name="line.487"></a>
-<span class="sourceLineNo">488</span><a name="line.488"></a>
-<span class="sourceLineNo">489</span>    final int depth() {<a name="line.489"></a>
-<span class="sourceLineNo">490</span>      return depth;<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>     * @param checkerScope The scope in which the limit is being checked<a name="line.494"></a>
-<span class="sourceLineNo">495</span>     * @return true when the checker is in a scope that indicates the limit can be enforced. Limits<a name="line.495"></a>
-<span class="sourceLineNo">496</span>     *         can be enforced from "higher or equal" scopes (i.e. the checker's scope is at a<a name="line.496"></a>
-<span class="sourceLineNo">497</span>     *         lesser depth than the limit)<a name="line.497"></a>
-<span class="sourceLineNo">498</span>     */<a name="line.498"></a>
-<span class="sourceLineNo">499</span>    boolean canEnforceLimitFromScope(LimitScope checkerScope) {<a name="line.499"></a>
-<span class="sourceLineNo">500</span>      return checkerScope != null &amp;&amp; checkerScope.depth() &lt;= depth;<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><a name="line.503"></a>
-<span class="sourceLineNo">504</span>  /**<a name="line.504"></a>
-<span class="sourceLineNo">505</span>   * The different fields that can be used as limits in calls to<a name="line.505"></a>
-<span class="sourceLineNo">506</span>   * {@link InternalScanner#next(java.util.List)} and {@link RegionScanner#next(java.util.List)}<a name="line.506"></a>
-<span class="sourceLineNo">507</span>   */<a name="line.507"></a>
-<span class="sourceLineNo">508</span>  private static class LimitFields {<a name="line.508"></a>
-<span class="sourceLineNo">509</span>    /**<a name="line.509"></a>
-<span class="sourceLineNo">510</span>     * Default values of the limit fields. Defined such that if a field does NOT change from its<a name="line.510"></a>
-<span class="sourceLineNo">511</span>     * default, it will not be enforced<a name="line.511"></a>
-<span class="sourceLineNo">512</span>     */<a name="line.512"></a>
-<span class="sourceLineNo">513</span>    private static int DEFAULT_BATCH = -1;<a name="line.513"></a>
-<span class="sourceLineNo">514</span>    private static long DEFAULT_SIZE = -1L;<a name="line.514"></a>
-<span class="sourceLineNo">515</span>    private static long DEFAULT_TIME = -1L;<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>     * Default scope that is assigned to a limit if a scope is not specified.<a name="line.518"></a>
-<span class="sourceLineNo">519</span>     */<a name="line.519"></a>
-<span class="sourceLineNo">520</span>    private static final LimitScope DEFAULT_SCOPE = LimitScope.BETWEEN_ROWS;<a name="line.520"></a>
-<span class="sourceLineNo">521</span><a name="line.521"></a>
-<span class="sourceLineNo">522</span>    // The batch limit will always be enforced between cells, thus, there isn't a field to hold the<a name="line.522"></a>
-<span class="sourceLineNo">523</span>    // batch scope<a name="line.523"></a>
-<span class="sourceLineNo">524</span>    int batch = DEFAULT_BATCH;<a name="line.524"></a>
-<span class="sourceLineNo">525</span><a name="line.525"></a>
-<span class="sourceLineNo">526</span>    LimitScope sizeScope = DEFAULT_SCOPE;<a name="line.526"></a>
-<span class="sourceLineNo">527</span>    // The sum of cell data sizes(key + value). The Cell data might be in on heap or off heap area.<a name="line.527"></a>
-<span class="sourceLineNo">528</span>    long dataSize = DEFAULT_SIZE;<a name="line.528"></a>
-<span class="sourceLineNo">529</span>    // The sum of heap space occupied by all tracked cells. This includes Cell POJO's overhead as<a name="line.529"></a>
-<span class="sourceLineNo">530</span>    // such AND data cells of Cells which are in on heap area.<a name="line.530"></a>
-<span class="sourceLineNo">531</span>    long heapSize = DEFAULT_SIZE;<a name="line.531"></a>
-<span class="sourceLineNo">532</span><a name="line.532"></a>
-<span class="sourceLineNo">533</span>    LimitScope timeScope = DEFAULT_SCOPE;<a name="line.533"></a>
-<span class="sourceLineNo">534</span>    long time = DEFAULT_TIME;<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>     * Fields keep their default values.<a name="line.537"></a>
-<span class="sourceLineNo">538</span>     */<a name="line.538"></a>
-<span class="sourceLineNo">539</span>    LimitFields() {<a name="line.539"></a>
-<span class="sourceLineNo">540</span>    }<a name="line.540"></a>
-<span class="sourceLineNo">541</span><a name="line.541"></a>
-<span class="sourceLineNo">542</span>    LimitFields(int batch, LimitScope sizeScope, long size, long heapSize, LimitScope timeScope,<a name="line.542"></a>
-<span class="sourceLineNo">543</span>        long time) {<a name="line.543"></a>
-<span class="sourceLineNo">544</span>      setFields(batch, sizeScope, size, heapSize, timeScope, time);<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>    void copy(LimitFields limitsToCopy) {<a name="line.547"></a>
-<span class="sourceLineNo">548</span>      if (limitsToCopy != null) {<a name="line.548"></a>
-<span class="sourceLineNo">549</span>        setFields(limitsToCopy.getBatch(), limitsToCopy.getSizeScope(), limitsToCopy.getDataSize(),<a name="line.549"></a>
-<span class="sourceLineNo">550</span>            limitsToCopy.getHeapSize(), limitsToCopy.getTimeScope(), limitsToCopy.getTime());<a name="line.550"></a>
-<span class="sourceLineNo">551</span>      }<a name="line.551"></a>
+<span class="sourceLineNo">476</span>     * Enforcing a limit between rows means that the limit will not be considered until all the<a name="line.476"></a>
+<span class="sourceLineNo">477</span>     * cells for a particular row have been retrieved<a name="line.477"></a>
+<span class="sourceLineNo">478</span>     */<a name="line.478"></a>
+<span class="sourceLineNo">479</span>    BETWEEN_ROWS(0),<a name="line.479"></a>
+<span class="sourceLineNo">480</span><a name="line.480"></a>
+<span class="sourceLineNo">481</span>    /**<a name="line.481"></a>
+<span class="sourceLineNo">482</span>     * Enforcing a limit between cells means that the limit will be considered after each full cell<a name="line.482"></a>
+<span class="sourceLineNo">483</span>     * has been retrieved<a name="line.483"></a>
+<span class="sourceLineNo">484</span>     */<a name="line.484"></a>
+<span class="sourceLineNo">485</span>    BETWEEN_CELLS(1);<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>     * When enforcing a limit, we must check that the scope is appropriate for enforcement.<a name="line.488"></a>
+<span class="sourceLineNo">489</span>     * &lt;p&gt;<a name="line.489"></a>
+<span class="sourceLineNo">490</span>     * To communicate this concept, each scope has a depth. A limit will be enforced if the depth of<a name="line.490"></a>
+<span class="sourceLineNo">491</span>     * the checker's scope is less than or equal to the limit's scope. This means that when checking<a name="line.491"></a>
+<span class="sourceLineNo">492</span>     * limits, the checker must know their own scope (i.e. are they checking the limits between<a name="line.492"></a>
+<span class="sourceLineNo">493</span>     * rows, between cells, etc...)<a name="line.493"></a>
+<span class="sourceLineNo">494</span>     */<a name="line.494"></a>
+<span class="sourceLineNo">495</span>    final int depth;<a name="line.495"></a>
+<span class="sourceLineNo">496</span><a name="line.496"></a>
+<span class="sourceLineNo">497</span>    LimitScope(int depth) {<a name="line.497"></a>
+<span class="sourceLineNo">498</span>      this.depth = depth;<a name="line.498"></a>
+<span class="sourceLineNo">499</span>    }<a name="line.499"></a>
+<span class="sourceLineNo">500</span><a name="line.500"></a>
+<span class="sourceLineNo">501</span>    final int depth() {<a name="line.501"></a>
+<span class="sourceLineNo">502</span>      return depth;<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>    /**<a name="line.505"></a>
+<span class="sourceLineNo">506</span>     * @param checkerScope The scope in which the limit is being checked<a name="line.506"></a>
+<span class="sourceLineNo">507</span>     * @return true when the checker is in a scope that indicates the limit can be enforced. Limits<a name="line.507"></a>
+<span class="sourceLineNo">508</span>     *         can be enforced from "higher or equal" scopes (i.e. the checker's scope is at a<a name="line.508"></a>
+<span class="sourceLineNo">509</span>     *         lesser depth than the limit)<a name="line.509"></a>
+<span class="sourceLineNo">510</span>     */<a name="line.510"></a>
+<span class="sourceLineNo">511</span>    boolean canEnforceLimitFromScope(LimitScope checkerScope) {<a name="line.511"></a>
+<span class="sourceLineNo">512</span>      return checkerScope != null &amp;&amp; checkerScope.depth() &lt;= depth;<a name="line.512"></a>
+<span class="sourceLineNo">513</span>    }<a name="line.513"></a>
+<span class="sourceLineNo">514</span>  }<a name="line.514"></a>
+<span class="sourceLineNo">515</span><a name="line.515"></a>
+<span class="sourceLineNo">516</span>  /**<a name="line.516"></a>
+<span class="sourceLineNo">517</span>   * The different fields that can be used as limits in calls to<a name="line.517"></a>
+<span class="sourceLineNo">518</span>   * {@link InternalScanner#next(java.util.List)} and {@link RegionScanner#next(java.util.List)}<a name="line.518"></a>
+<span class="sourceLineNo">519</span>   */<a name="line.519"></a>
+<span class="sourceLineNo">520</span>  private static class LimitFields {<a name="line.520"></a>
+<span class="sourceLineNo">521</span>    /**<a name="line.521"></a>
+<span class="sourceLineNo">522</span>     * Default values of the limit fields. Defined such that if a field does NOT change from its<a name="line.522"></a>
+<span class="sourceLineNo">523</span>     * default, it will not be enforced<a name="line.523"></a>
+<span class="sourceLineNo">524</span>     */<a name="line.524"></a>
+<span class="sourceLineNo">525</span>    private static int DEFAULT_BATCH = -1;<a name="line.525"></a>
+<span class="sourceLineNo">526</span>    private static long DEFAULT_SIZE = -1L;<a name="line.526"></a>
+<span class="sourceLineNo">527</span>    private static long DEFAULT_TIME = -1L;<a name="line.527"></a>
+<span class="sourceLineNo">528</span><a name="line.528"></a>
+<span class="sourceLineNo">529</span>    /**<a name="line.529"></a>
+<span class="sourceLineNo">530</span>     * Default scope that is assigned to a limit if a scope is not specified.<a name="line.530"></a>
+<span class="sourceLineNo">531</span>     */<a name="line.531"></a>
+<span class="sourceLineNo">532</span>    private static final LimitScope DEFAULT_SCOPE = LimitScope.BETWEEN_ROWS;<a name="line.532"></a>
+<span class="sourceLineNo">533</span><a name="line.533"></a>
+<span class="sourceLineNo">534</span>    // The batch limit will always be enforced between cells, thus, there isn't a field to hold the<a name="line.534"></a>
+<span class="sourceLineNo">535</span>    // batch scope<a name="line.535"></a>
+<span class="sourceLineNo">536</span>    int batch = DEFAULT_BATCH;<a name="line.536"></a>
+<span class="sourceLineNo">537</span><a name="line.537"></a>
+<span class="sourceLineNo">538</span>    LimitScope sizeScope = DEFAULT_SCOPE;<a name="line.538"></a>
+<span class="sourceLineNo">539</span>    // The sum of cell data sizes(key + value). The Cell data might be in on heap or off heap area.<a name="line.539"></a>
+<span class="sourceLineNo">540</span>    long dataSize = DEFAULT_SIZE;<a name="line.540"></a>
+<span class="sourceLineNo">541</span>    // The sum of heap space occupied by all tracked cells. This includes Cell POJO's overhead as<a name="line.541"></a>
+<span class="sourceLineNo">542</span>    // such AND data cells of Cells which are in on heap area.<a name="line.542"></a>
+<span class="sourceLineNo">543</span>    long heapSize = DEFAULT_SIZE;<a name="line.543"></a>
+<span class="sourceLineNo">544</span><a name="line.544"></a>
+<span class="sourceLineNo">545</span>    LimitScope timeScope = DEFAULT_SCOPE;<a name="line.545"></a>
+<span class="sourceLineNo">546</span>    long time = DEFAULT_TIME;<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>     * Fields keep their default values.<a name="line.549"></a>
+<span class="sourceLineNo">550</span>     */<a name="line.550"></a>
+<span class="sourceLineNo">551</span>    LimitFields() {<a name="line.551"></a>
 <span class="sourceLineNo">552</span>    }<a name="line.552"></a>
 <span class="sourceLineNo">553</span><a name="line.553"></a>
-<span class="sourceLineNo">554</span>    /**<a name="line.554"></a>
-<span class="sourceLineNo">555</span>     * Set all fields together.<a name="line.555"></a>
-<span class="sourceLineNo">556</span>     */<a name="line.556"></a>
-<span class="sourceLineNo">557</span>    void setFields(int batch, LimitScope sizeScope, long dataSize, long heapSize,<a name="line.557"></a>
-<span class="sourceLineNo">558</span>        LimitScope timeScope, long time) {<a name="line.558"></a>
-<span class="sourceLineNo">559</span>      setBatch(batch);<a name="line.559"></a>
-<span class="sourceLineNo">560</span>      setSizeScope(sizeScope);<a name="line.560"></a>
-<span class="sourceLineNo">561</span>      setDataSize(dataSize);<a name="line.561"></a>
-<span class="sourceLineNo">562</span>      setHeapSize(heapSize);<a name="line.562"></a>
-<span class="sourceLineNo">563</span>      setTimeScope(timeScope);<a name="line.563"></a>
-<span class="sourceLineNo">564</span>      setTime(time);<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>    int getBatch() {<a name="line.567"></a>
-<span class="sourceLineNo">568</span>      return this.batch;<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>    void setBatch(int batch) {<a name="line.571"></a>
-<span class="sourceLineNo">572</span>      this.batch = batch;<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>    /**<a name="line.575"></a>
-<span class="sourceLineNo">576</span>     * @param checkerScope<a name="line.576"></a>
-<span class="sourceLineNo">577</span>     * @return true when the limit can be enforced from the scope of the checker<a name="line.577"></a>
-<span class="sourceLineNo">578</span>     */<a name="line.578"></a>
-<span class="sourceLineNo">579</span>    boolean canEnforceBatchLimitFromScope(LimitScope checkerScope) {<a name="line.579"></a>
-<span class="sourceLineNo">580</span>      return LimitScope.BETWEEN_CELLS.canEnforceLimitFromScope(checkerScope);<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>    long getDataSize() {<a name="line.583"></a>
-<span class="sourceLineNo">584</span>      return this.dataSize;<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>    long getHeapSize() {<a name="line.587"></a>
-<span class="sourceLineNo">588</span>      return this.heapSize;<a name="line.588"></a>
-<span class="sourceLineNo">589</span>    }<a name="line.589"></a>
-<span class="sourceLineNo">590</span><a name="line.590"></a>
-<span class="sourceLineNo">591</span>    void setDataSize(long dataSize) {<a name="line.591"></a>
-<span class="sourceLineNo">592</span>      this.dataSize = dataSize;<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>    void setHeapSize(long heapSize) {<a name="line.595"></a>
-<span class="sourceLineNo">596</span>      this.heapSize = heapSize;<a name="line.596"></a>
-<span class="sourceLineNo">597</span>    }<a name="line.597"></a>
-<span class="sourceLineNo">598</span><a name="line.598"></a>
-<span class="sourceLineNo">599</span>    /**<a name="line.599"></a>
-<span class="sourceLineNo">600</span>     * @return {@link LimitScope} indicating scope in which the size limit is enforced<a name="line.600"></a>
-<span class="sourceLineNo">601</span>     */<a name="line.601"></a>
-<span class="sourceLineNo">602</span>    LimitScope getSizeScope() {<a name="line.602"></a>
-<span class="sourceLineNo">603</span>      return this.sizeScope;<a name="line.603"></a>
+<span class="sourceLineNo">554</span>    void copy(LimitFields limitsToCopy) {<a name="line.554"></a>
+<span class="sourceLineNo">555</span>      if (limitsToCopy != null) {<a name="line.555"></a>
+<span class="sourceLineNo">556</span>        setFields(limitsToCopy.getBatch(), limitsToCopy.getSizeScope(), limitsToCopy.getDataSize(),<a name="line.556"></a>
+<span class="sourceLineNo">557</span>            limitsToCopy.getHeapSize(), limitsToCopy.getTimeScope(), limitsToCopy.getTime());<a name="line.557"></a>
+<span class="sourceLineNo">558</span>      }<a name="line.558"></a>
+<span class="sourceLineNo">559</span>    }<a name="line.559"></a>
+<span class="sourceLineNo">560</span><a name="line.560"></a>
+<span class="sourceLineNo">561</span>    /**<a name="line.561"></a>
+<span class="sourceLineNo">562</span>     * Set all fields together.<a name="line.562"></a>
+<span class="sourceLineNo">563</span>     */<a name="line.563"></a>
+<span class="sourceLineNo">564</span>    void setFields(int batch, LimitScope sizeScope, long dataSize, long heapSize,<a name="line.564"></a>
+<span class="sourceLineNo">565</span>        LimitScope timeScope, long time) {<a name="line.565"></a>
+<span class="sourceLineNo">566</span>      setBatch(batch);<a name="line.566"></a>
+<span class="sourceLineNo">567</span>      setSizeScope(sizeScope);<a name="line.567"></a>
+<span class="sourceLineNo">568</span>      setDataSize(dataSize);<a name="line.568"></a>
+<span class="sourceLineNo">569</span>      setHeapSize(heapSize);<a name="line.569"></a>
+<span class="sourceLineNo">570</span>      setTimeScope(timeScope);<a name="line.570"></a>
+<span class="sourceLineNo">571</span>      setTime(time);<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>    int getBatch() {<a name="line.574"></a>
+<span class="sourceLineNo">575</span>      return this.batch;<a name="line.575"></a>
+<span class="sourceLineNo">576</span>    }<a name="line.576"></a>
+<span class="sourceLineNo">577</span><a name="line.577"></a>
+<span class="sourceLineNo">578</span>    void setBatch(int batch) {<a name="line.578"></a>
+<span class="sourceLineNo">579</span>      this.batch = batch;<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

<TRUNCATED>

[09/50] hbase-site git commit: Published site at 26babcf013de696b899d76a3c39434b794440d8d.

Posted by gi...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextColFilter.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextColFilter.html b/testdevapidocs/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextColFilter.html
new file mode 100644
index 0000000..a2bd2f4
--- /dev/null
+++ b/testdevapidocs/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextColFilter.html
@@ -0,0 +1,337 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!-- NewPage -->
+<html lang="en">
+<head>
+<!-- Generated by javadoc -->
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>TestSwitchToStreamRead.MatchLastRowCellNextColFilter (Apache HBase 3.0.0-SNAPSHOT Test API)</title>
+<link rel="stylesheet" type="text/css" href="../../../../../stylesheet.css" title="Style">
+<script type="text/javascript" src="../../../../../script.js"></script>
+</head>
+<body>
+<script type="text/javascript"><!--
+    try {
+        if (location.href.indexOf('is-external=true') == -1) {
+            parent.document.title="TestSwitchToStreamRead.MatchLastRowCellNextColFilter (Apache HBase 3.0.0-SNAPSHOT Test API)";
+        }
+    }
+    catch(err) {
+    }
+//-->
+var methods = {"i0":10};
+var tabs = {65535:["t0","All Methods"],2:["t2","Instance Methods"],8:["t4","Concrete Methods"]};
+var altColor = "altColor";
+var rowColor = "rowColor";
+var tableTab = "tableTab";
+var activeTableTab = "activeTableTab";
+</script>
+<noscript>
+<div>JavaScript is disabled on your browser.</div>
+</noscript>
+<!-- ========= START OF TOP NAVBAR ======= -->
+<div class="topNav"><a name="navbar.top">
+<!--   -->
+</a>
+<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
+<a name="navbar.top.firstrow">
+<!--   -->
+</a>
+<ul class="navList" title="Navigation">
+<li><a href="../../../../../overview-summary.html">Overview</a></li>
+<li><a href="package-summary.html">Package</a></li>
+<li class="navBarCell1Rev">Class</li>
+<li><a href="class-use/TestSwitchToStreamRead.MatchLastRowCellNextColFilter.html">Use</a></li>
+<li><a href="package-tree.html">Tree</a></li>
+<li><a href="../../../../../deprecated-list.html">Deprecated</a></li>
+<li><a href="../../../../../index-all.html">Index</a></li>
+<li><a href="../../../../../help-doc.html">Help</a></li>
+</ul>
+</div>
+<div class="subNav">
+<ul class="navList">
+<li><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html" title="class in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">Prev&nbsp;Class</span></a></li>
+<li><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextRowFilter.html" title="class in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">Next&nbsp;Class</span></a></li>
+</ul>
+<ul class="navList">
+<li><a href="../../../../../index.html?org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextColFilter.html" target="_top">Frames</a></li>
+<li><a href="TestSwitchToStreamRead.MatchLastRowCellNextColFilter.html" target="_top">No&nbsp;Frames</a></li>
+</ul>
+<ul class="navList" id="allclasses_navbar_top">
+<li><a href="../../../../../allclasses-noframe.html">All&nbsp;Classes</a></li>
+</ul>
+<div>
+<script type="text/javascript"><!--
+  allClassesLink = document.getElementById("allclasses_navbar_top");
+  if(window==top) {
+    allClassesLink.style.display = "block";
+  }
+  else {
+    allClassesLink.style.display = "none";
+  }
+  //-->
+</script>
+</div>
+<div>
+<ul class="subNavList">
+<li>Summary:&nbsp;</li>
+<li><a href="#nested.classes.inherited.from.class.org.apache.hadoop.hbase.filter.Filter">Nested</a>&nbsp;|&nbsp;</li>
+<li><a href="#fields.inherited.from.class.org.apache.hadoop.hbase.filter.Filter">Field</a>&nbsp;|&nbsp;</li>
+<li><a href="#constructor.summary">Constr</a>&nbsp;|&nbsp;</li>
+<li><a href="#method.summary">Method</a></li>
+</ul>
+<ul class="subNavList">
+<li>Detail:&nbsp;</li>
+<li>Field&nbsp;|&nbsp;</li>
+<li><a href="#constructor.detail">Constr</a>&nbsp;|&nbsp;</li>
+<li><a href="#method.detail">Method</a></li>
+</ul>
+</div>
+<a name="skip.navbar.top">
+<!--   -->
+</a></div>
+<!-- ========= END OF TOP NAVBAR ========= -->
+<!-- ======== START OF CLASS DATA ======== -->
+<div class="header">
+<div class="subTitle">org.apache.hadoop.hbase.regionserver</div>
+<h2 title="Class TestSwitchToStreamRead.MatchLastRowCellNextColFilter" class="title">Class TestSwitchToStreamRead.MatchLastRowCellNextColFilter</h2>
+</div>
+<div class="contentContainer">
+<ul class="inheritance">
+<li><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true" title="class or interface in java.lang">java.lang.Object</a></li>
+<li>
+<ul class="inheritance">
+<li>org.apache.hadoop.hbase.filter.Filter</li>
+<li>
+<ul class="inheritance">
+<li>org.apache.hadoop.hbase.filter.FilterBase</li>
+<li>
+<ul class="inheritance">
+<li>org.apache.hadoop.hbase.regionserver.TestSwitchToStreamRead.MatchLastRowCellNextColFilter</li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+<div class="description">
+<ul class="blockList">
+<li class="blockList">
+<dl>
+<dt>Enclosing class:</dt>
+<dd><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html" title="class in org.apache.hadoop.hbase.regionserver">TestSwitchToStreamRead</a></dd>
+</dl>
+<hr>
+<br>
+<pre>public static final class <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html#line.198">TestSwitchToStreamRead.MatchLastRowCellNextColFilter</a>
+extends org.apache.hadoop.hbase.filter.FilterBase</pre>
+</li>
+</ul>
+</div>
+<div class="summary">
+<ul class="blockList">
+<li class="blockList">
+<!-- ======== NESTED CLASS SUMMARY ======== -->
+<ul class="blockList">
+<li class="blockList"><a name="nested.class.summary">
+<!--   -->
+</a>
+<h3>Nested Class Summary</h3>
+<ul class="blockList">
+<li class="blockList"><a name="nested.classes.inherited.from.class.org.apache.hadoop.hbase.filter.Filter">
+<!--   -->
+</a>
+<h3>Nested classes/interfaces inherited from class&nbsp;org.apache.hadoop.hbase.filter.Filter</h3>
+<code>org.apache.hadoop.hbase.filter.Filter.ReturnCode</code></li>
+</ul>
+</li>
+</ul>
+<!-- =========== FIELD SUMMARY =========== -->
+<ul class="blockList">
+<li class="blockList"><a name="field.summary">
+<!--   -->
+</a>
+<h3>Field Summary</h3>
+<ul class="blockList">
+<li class="blockList"><a name="fields.inherited.from.class.org.apache.hadoop.hbase.filter.Filter">
+<!--   -->
+</a>
+<h3>Fields inherited from class&nbsp;org.apache.hadoop.hbase.filter.Filter</h3>
+<code>reversed</code></li>
+</ul>
+</li>
+</ul>
+<!-- ======== CONSTRUCTOR SUMMARY ======== -->
+<ul class="blockList">
+<li class="blockList"><a name="constructor.summary">
+<!--   -->
+</a>
+<h3>Constructor Summary</h3>
+<table class="memberSummary" border="0" cellpadding="3" cellspacing="0" summary="Constructor Summary table, listing constructors, and an explanation">
+<caption><span>Constructors</span><span class="tabEnd">&nbsp;</span></caption>
+<tr>
+<th class="colOne" scope="col">Constructor and Description</th>
+</tr>
+<tr class="altColor">
+<td class="colOne"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextColFilter.html#MatchLastRowCellNextColFilter--">MatchLastRowCellNextColFilter</a></span>()</code>&nbsp;</td>
+</tr>
+</table>
+</li>
+</ul>
+<!-- ========== METHOD SUMMARY =========== -->
+<ul class="blockList">
+<li class="blockList"><a name="method.summary">
+<!--   -->
+</a>
+<h3>Method Summary</h3>
+<table class="memberSummary" border="0" cellpadding="3" cellspacing="0" summary="Method Summary table, listing methods, and an explanation">
+<caption><span id="t0" class="activeTableTab"><span>All Methods</span><span class="tabEnd">&nbsp;</span></span><span id="t2" class="tableTab"><span><a href="javascript:show(2);">Instance Methods</a></span><span class="tabEnd">&nbsp;</span></span><span id="t4" class="tableTab"><span><a href="javascript:show(8);">Concrete Methods</a></span><span class="tabEnd">&nbsp;</span></span></caption>
+<tr>
+<th class="colFirst" scope="col">Modifier and Type</th>
+<th class="colLast" scope="col">Method and Description</th>
+</tr>
+<tr id="i0" class="altColor">
+<td class="colFirst"><code>org.apache.hadoop.hbase.filter.Filter.ReturnCode</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextColFilter.html#filterCell-org.apache.hadoop.hbase.Cell-">filterCell</a></span>(org.apache.hadoop.hbase.Cell&nbsp;c)</code>&nbsp;</td>
+</tr>
+</table>
+<ul class="blockList">
+<li class="blockList"><a name="methods.inherited.from.class.org.apache.hadoop.hbase.filter.FilterBase">
+<!--   -->
+</a>
+<h3>Methods inherited from class&nbsp;org.apache.hadoop.hbase.filter.FilterBase</h3>
+<code>createFilterFromArguments, filterAllRemaining, filterRow, filterRowCells, filterRowKey, filterRowKey, getNextCellHint, hasFilterRow, isFamilyEssential, reset, toByteArray, toString, transformCell</code></li>
+</ul>
+<ul class="blockList">
+<li class="blockList"><a name="methods.inherited.from.class.org.apache.hadoop.hbase.filter.Filter">
+<!--   -->
+</a>
+<h3>Methods inherited from class&nbsp;org.apache.hadoop.hbase.filter.Filter</h3>
+<code>filterKeyValue, isReversed, parseFrom, setReversed</code></li>
+</ul>
+<ul class="blockList">
+<li class="blockList"><a name="methods.inherited.from.class.java.lang.Object">
+<!--   -->
+</a>
+<h3>Methods inherited from class&nbsp;java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true" title="class or interface in java.lang">Object</a></h3>
+<code><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true#clone--" title="class or interface in java.lang">clone</a>, <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true#equals-java.lang.Object-" title="class or interface in java.lang">equals</a>, <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true#finalize--" title="class or interface in java.lang">finalize</a>, <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true#getClass--" title="class or interface in java.lang">getClass</a>, <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true#hashCode--" title="class or interface in java.lang">hashCode</a>, <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true#notify--" title="class or interface in java.lang">notify</a>, <a href="https://docs.oracle.com/javase/8/docs/api/ja
 va/lang/Object.html?is-external=true#notifyAll--" title="class or interface in java.lang">notifyAll</a>, <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true#wait--" title="class or interface in java.lang">wait</a>, <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true#wait-long-" title="class or interface in java.lang">wait</a>, <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true#wait-long-int-" title="class or interface in java.lang">wait</a></code></li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+</div>
+<div class="details">
+<ul class="blockList">
+<li class="blockList">
+<!-- ========= CONSTRUCTOR DETAIL ======== -->
+<ul class="blockList">
+<li class="blockList"><a name="constructor.detail">
+<!--   -->
+</a>
+<h3>Constructor Detail</h3>
+<a name="MatchLastRowCellNextColFilter--">
+<!--   -->
+</a>
+<ul class="blockListLast">
+<li class="blockList">
+<h4>MatchLastRowCellNextColFilter</h4>
+<pre>public&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextColFilter.html#line.198">MatchLastRowCellNextColFilter</a>()</pre>
+</li>
+</ul>
+</li>
+</ul>
+<!-- ============ METHOD DETAIL ========== -->
+<ul class="blockList">
+<li class="blockList"><a name="method.detail">
+<!--   -->
+</a>
+<h3>Method Detail</h3>
+<a name="filterCell-org.apache.hadoop.hbase.Cell-">
+<!--   -->
+</a>
+<ul class="blockListLast">
+<li class="blockList">
+<h4>filterCell</h4>
+<pre>public&nbsp;org.apache.hadoop.hbase.filter.Filter.ReturnCode&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextColFilter.html#line.201">filterCell</a>(org.apache.hadoop.hbase.Cell&nbsp;c)
+                                                            throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
+<dl>
+<dt><span class="overrideSpecifyLabel">Overrides:</span></dt>
+<dd><code>filterCell</code>&nbsp;in class&nbsp;<code>org.apache.hadoop.hbase.filter.Filter</code></dd>
+<dt><span class="throwsLabel">Throws:</span></dt>
+<dd><code><a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></code></dd>
+</dl>
+</li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+</div>
+</div>
+<!-- ========= END OF CLASS DATA ========= -->
+<!-- ======= START OF BOTTOM NAVBAR ====== -->
+<div class="bottomNav"><a name="navbar.bottom">
+<!--   -->
+</a>
+<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
+<a name="navbar.bottom.firstrow">
+<!--   -->
+</a>
+<ul class="navList" title="Navigation">
+<li><a href="../../../../../overview-summary.html">Overview</a></li>
+<li><a href="package-summary.html">Package</a></li>
+<li class="navBarCell1Rev">Class</li>
+<li><a href="class-use/TestSwitchToStreamRead.MatchLastRowCellNextColFilter.html">Use</a></li>
+<li><a href="package-tree.html">Tree</a></li>
+<li><a href="../../../../../deprecated-list.html">Deprecated</a></li>
+<li><a href="../../../../../index-all.html">Index</a></li>
+<li><a href="../../../../../help-doc.html">Help</a></li>
+</ul>
+</div>
+<div class="subNav">
+<ul class="navList">
+<li><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html" title="class in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">Prev&nbsp;Class</span></a></li>
+<li><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextRowFilter.html" title="class in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">Next&nbsp;Class</span></a></li>
+</ul>
+<ul class="navList">
+<li><a href="../../../../../index.html?org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextColFilter.html" target="_top">Frames</a></li>
+<li><a href="TestSwitchToStreamRead.MatchLastRowCellNextColFilter.html" target="_top">No&nbsp;Frames</a></li>
+</ul>
+<ul class="navList" id="allclasses_navbar_bottom">
+<li><a href="../../../../../allclasses-noframe.html">All&nbsp;Classes</a></li>
+</ul>
+<div>
+<script type="text/javascript"><!--
+  allClassesLink = document.getElementById("allclasses_navbar_bottom");
+  if(window==top) {
+    allClassesLink.style.display = "block";
+  }
+  else {
+    allClassesLink.style.display = "none";
+  }
+  //-->
+</script>
+</div>
+<div>
+<ul class="subNavList">
+<li>Summary:&nbsp;</li>
+<li><a href="#nested.classes.inherited.from.class.org.apache.hadoop.hbase.filter.Filter">Nested</a>&nbsp;|&nbsp;</li>
+<li><a href="#fields.inherited.from.class.org.apache.hadoop.hbase.filter.Filter">Field</a>&nbsp;|&nbsp;</li>
+<li><a href="#constructor.summary">Constr</a>&nbsp;|&nbsp;</li>
+<li><a href="#method.summary">Method</a></li>
+</ul>
+<ul class="subNavList">
+<li>Detail:&nbsp;</li>
+<li>Field&nbsp;|&nbsp;</li>
+<li><a href="#constructor.detail">Constr</a>&nbsp;|&nbsp;</li>
+<li><a href="#method.detail">Method</a></li>
+</ul>
+</div>
+<a name="skip.navbar.bottom">
+<!--   -->
+</a></div>
+<!-- ======== END OF BOTTOM NAVBAR ======= -->
+<p class="legalCopy"><small>Copyright &#169; 2007&#x2013;2018 <a href="https://www.apache.org/">The Apache Software Foundation</a>. All rights reserved.</small></p>
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextRowFilter.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextRowFilter.html b/testdevapidocs/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextRowFilter.html
new file mode 100644
index 0000000..709a28e
--- /dev/null
+++ b/testdevapidocs/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextRowFilter.html
@@ -0,0 +1,337 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!-- NewPage -->
+<html lang="en">
+<head>
+<!-- Generated by javadoc -->
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>TestSwitchToStreamRead.MatchLastRowCellNextRowFilter (Apache HBase 3.0.0-SNAPSHOT Test API)</title>
+<link rel="stylesheet" type="text/css" href="../../../../../stylesheet.css" title="Style">
+<script type="text/javascript" src="../../../../../script.js"></script>
+</head>
+<body>
+<script type="text/javascript"><!--
+    try {
+        if (location.href.indexOf('is-external=true') == -1) {
+            parent.document.title="TestSwitchToStreamRead.MatchLastRowCellNextRowFilter (Apache HBase 3.0.0-SNAPSHOT Test API)";
+        }
+    }
+    catch(err) {
+    }
+//-->
+var methods = {"i0":10};
+var tabs = {65535:["t0","All Methods"],2:["t2","Instance Methods"],8:["t4","Concrete Methods"]};
+var altColor = "altColor";
+var rowColor = "rowColor";
+var tableTab = "tableTab";
+var activeTableTab = "activeTableTab";
+</script>
+<noscript>
+<div>JavaScript is disabled on your browser.</div>
+</noscript>
+<!-- ========= START OF TOP NAVBAR ======= -->
+<div class="topNav"><a name="navbar.top">
+<!--   -->
+</a>
+<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
+<a name="navbar.top.firstrow">
+<!--   -->
+</a>
+<ul class="navList" title="Navigation">
+<li><a href="../../../../../overview-summary.html">Overview</a></li>
+<li><a href="package-summary.html">Package</a></li>
+<li class="navBarCell1Rev">Class</li>
+<li><a href="class-use/TestSwitchToStreamRead.MatchLastRowCellNextRowFilter.html">Use</a></li>
+<li><a href="package-tree.html">Tree</a></li>
+<li><a href="../../../../../deprecated-list.html">Deprecated</a></li>
+<li><a href="../../../../../index-all.html">Index</a></li>
+<li><a href="../../../../../help-doc.html">Help</a></li>
+</ul>
+</div>
+<div class="subNav">
+<ul class="navList">
+<li><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextColFilter.html" title="class in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">Prev&nbsp;Class</span></a></li>
+<li><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html" title="class in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">Next&nbsp;Class</span></a></li>
+</ul>
+<ul class="navList">
+<li><a href="../../../../../index.html?org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextRowFilter.html" target="_top">Frames</a></li>
+<li><a href="TestSwitchToStreamRead.MatchLastRowCellNextRowFilter.html" target="_top">No&nbsp;Frames</a></li>
+</ul>
+<ul class="navList" id="allclasses_navbar_top">
+<li><a href="../../../../../allclasses-noframe.html">All&nbsp;Classes</a></li>
+</ul>
+<div>
+<script type="text/javascript"><!--
+  allClassesLink = document.getElementById("allclasses_navbar_top");
+  if(window==top) {
+    allClassesLink.style.display = "block";
+  }
+  else {
+    allClassesLink.style.display = "none";
+  }
+  //-->
+</script>
+</div>
+<div>
+<ul class="subNavList">
+<li>Summary:&nbsp;</li>
+<li><a href="#nested.classes.inherited.from.class.org.apache.hadoop.hbase.filter.Filter">Nested</a>&nbsp;|&nbsp;</li>
+<li><a href="#fields.inherited.from.class.org.apache.hadoop.hbase.filter.Filter">Field</a>&nbsp;|&nbsp;</li>
+<li><a href="#constructor.summary">Constr</a>&nbsp;|&nbsp;</li>
+<li><a href="#method.summary">Method</a></li>
+</ul>
+<ul class="subNavList">
+<li>Detail:&nbsp;</li>
+<li>Field&nbsp;|&nbsp;</li>
+<li><a href="#constructor.detail">Constr</a>&nbsp;|&nbsp;</li>
+<li><a href="#method.detail">Method</a></li>
+</ul>
+</div>
+<a name="skip.navbar.top">
+<!--   -->
+</a></div>
+<!-- ========= END OF TOP NAVBAR ========= -->
+<!-- ======== START OF CLASS DATA ======== -->
+<div class="header">
+<div class="subTitle">org.apache.hadoop.hbase.regionserver</div>
+<h2 title="Class TestSwitchToStreamRead.MatchLastRowCellNextRowFilter" class="title">Class TestSwitchToStreamRead.MatchLastRowCellNextRowFilter</h2>
+</div>
+<div class="contentContainer">
+<ul class="inheritance">
+<li><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true" title="class or interface in java.lang">java.lang.Object</a></li>
+<li>
+<ul class="inheritance">
+<li>org.apache.hadoop.hbase.filter.Filter</li>
+<li>
+<ul class="inheritance">
+<li>org.apache.hadoop.hbase.filter.FilterBase</li>
+<li>
+<ul class="inheritance">
+<li>org.apache.hadoop.hbase.regionserver.TestSwitchToStreamRead.MatchLastRowCellNextRowFilter</li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+<div class="description">
+<ul class="blockList">
+<li class="blockList">
+<dl>
+<dt>Enclosing class:</dt>
+<dd><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html" title="class in org.apache.hadoop.hbase.regionserver">TestSwitchToStreamRead</a></dd>
+</dl>
+<hr>
+<br>
+<pre>public static final class <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html#line.215">TestSwitchToStreamRead.MatchLastRowCellNextRowFilter</a>
+extends org.apache.hadoop.hbase.filter.FilterBase</pre>
+</li>
+</ul>
+</div>
+<div class="summary">
+<ul class="blockList">
+<li class="blockList">
+<!-- ======== NESTED CLASS SUMMARY ======== -->
+<ul class="blockList">
+<li class="blockList"><a name="nested.class.summary">
+<!--   -->
+</a>
+<h3>Nested Class Summary</h3>
+<ul class="blockList">
+<li class="blockList"><a name="nested.classes.inherited.from.class.org.apache.hadoop.hbase.filter.Filter">
+<!--   -->
+</a>
+<h3>Nested classes/interfaces inherited from class&nbsp;org.apache.hadoop.hbase.filter.Filter</h3>
+<code>org.apache.hadoop.hbase.filter.Filter.ReturnCode</code></li>
+</ul>
+</li>
+</ul>
+<!-- =========== FIELD SUMMARY =========== -->
+<ul class="blockList">
+<li class="blockList"><a name="field.summary">
+<!--   -->
+</a>
+<h3>Field Summary</h3>
+<ul class="blockList">
+<li class="blockList"><a name="fields.inherited.from.class.org.apache.hadoop.hbase.filter.Filter">
+<!--   -->
+</a>
+<h3>Fields inherited from class&nbsp;org.apache.hadoop.hbase.filter.Filter</h3>
+<code>reversed</code></li>
+</ul>
+</li>
+</ul>
+<!-- ======== CONSTRUCTOR SUMMARY ======== -->
+<ul class="blockList">
+<li class="blockList"><a name="constructor.summary">
+<!--   -->
+</a>
+<h3>Constructor Summary</h3>
+<table class="memberSummary" border="0" cellpadding="3" cellspacing="0" summary="Constructor Summary table, listing constructors, and an explanation">
+<caption><span>Constructors</span><span class="tabEnd">&nbsp;</span></caption>
+<tr>
+<th class="colOne" scope="col">Constructor and Description</th>
+</tr>
+<tr class="altColor">
+<td class="colOne"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextRowFilter.html#MatchLastRowCellNextRowFilter--">MatchLastRowCellNextRowFilter</a></span>()</code>&nbsp;</td>
+</tr>
+</table>
+</li>
+</ul>
+<!-- ========== METHOD SUMMARY =========== -->
+<ul class="blockList">
+<li class="blockList"><a name="method.summary">
+<!--   -->
+</a>
+<h3>Method Summary</h3>
+<table class="memberSummary" border="0" cellpadding="3" cellspacing="0" summary="Method Summary table, listing methods, and an explanation">
+<caption><span id="t0" class="activeTableTab"><span>All Methods</span><span class="tabEnd">&nbsp;</span></span><span id="t2" class="tableTab"><span><a href="javascript:show(2);">Instance Methods</a></span><span class="tabEnd">&nbsp;</span></span><span id="t4" class="tableTab"><span><a href="javascript:show(8);">Concrete Methods</a></span><span class="tabEnd">&nbsp;</span></span></caption>
+<tr>
+<th class="colFirst" scope="col">Modifier and Type</th>
+<th class="colLast" scope="col">Method and Description</th>
+</tr>
+<tr id="i0" class="altColor">
+<td class="colFirst"><code>org.apache.hadoop.hbase.filter.Filter.ReturnCode</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextRowFilter.html#filterCell-org.apache.hadoop.hbase.Cell-">filterCell</a></span>(org.apache.hadoop.hbase.Cell&nbsp;c)</code>&nbsp;</td>
+</tr>
+</table>
+<ul class="blockList">
+<li class="blockList"><a name="methods.inherited.from.class.org.apache.hadoop.hbase.filter.FilterBase">
+<!--   -->
+</a>
+<h3>Methods inherited from class&nbsp;org.apache.hadoop.hbase.filter.FilterBase</h3>
+<code>createFilterFromArguments, filterAllRemaining, filterRow, filterRowCells, filterRowKey, filterRowKey, getNextCellHint, hasFilterRow, isFamilyEssential, reset, toByteArray, toString, transformCell</code></li>
+</ul>
+<ul class="blockList">
+<li class="blockList"><a name="methods.inherited.from.class.org.apache.hadoop.hbase.filter.Filter">
+<!--   -->
+</a>
+<h3>Methods inherited from class&nbsp;org.apache.hadoop.hbase.filter.Filter</h3>
+<code>filterKeyValue, isReversed, parseFrom, setReversed</code></li>
+</ul>
+<ul class="blockList">
+<li class="blockList"><a name="methods.inherited.from.class.java.lang.Object">
+<!--   -->
+</a>
+<h3>Methods inherited from class&nbsp;java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true" title="class or interface in java.lang">Object</a></h3>
+<code><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true#clone--" title="class or interface in java.lang">clone</a>, <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true#equals-java.lang.Object-" title="class or interface in java.lang">equals</a>, <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true#finalize--" title="class or interface in java.lang">finalize</a>, <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true#getClass--" title="class or interface in java.lang">getClass</a>, <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true#hashCode--" title="class or interface in java.lang">hashCode</a>, <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true#notify--" title="class or interface in java.lang">notify</a>, <a href="https://docs.oracle.com/javase/8/docs/api/ja
 va/lang/Object.html?is-external=true#notifyAll--" title="class or interface in java.lang">notifyAll</a>, <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true#wait--" title="class or interface in java.lang">wait</a>, <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true#wait-long-" title="class or interface in java.lang">wait</a>, <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true#wait-long-int-" title="class or interface in java.lang">wait</a></code></li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+</div>
+<div class="details">
+<ul class="blockList">
+<li class="blockList">
+<!-- ========= CONSTRUCTOR DETAIL ======== -->
+<ul class="blockList">
+<li class="blockList"><a name="constructor.detail">
+<!--   -->
+</a>
+<h3>Constructor Detail</h3>
+<a name="MatchLastRowCellNextRowFilter--">
+<!--   -->
+</a>
+<ul class="blockListLast">
+<li class="blockList">
+<h4>MatchLastRowCellNextRowFilter</h4>
+<pre>public&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextRowFilter.html#line.215">MatchLastRowCellNextRowFilter</a>()</pre>
+</li>
+</ul>
+</li>
+</ul>
+<!-- ============ METHOD DETAIL ========== -->
+<ul class="blockList">
+<li class="blockList"><a name="method.detail">
+<!--   -->
+</a>
+<h3>Method Detail</h3>
+<a name="filterCell-org.apache.hadoop.hbase.Cell-">
+<!--   -->
+</a>
+<ul class="blockListLast">
+<li class="blockList">
+<h4>filterCell</h4>
+<pre>public&nbsp;org.apache.hadoop.hbase.filter.Filter.ReturnCode&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextRowFilter.html#line.218">filterCell</a>(org.apache.hadoop.hbase.Cell&nbsp;c)
+                                                            throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
+<dl>
+<dt><span class="overrideSpecifyLabel">Overrides:</span></dt>
+<dd><code>filterCell</code>&nbsp;in class&nbsp;<code>org.apache.hadoop.hbase.filter.Filter</code></dd>
+<dt><span class="throwsLabel">Throws:</span></dt>
+<dd><code><a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></code></dd>
+</dl>
+</li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+</div>
+</div>
+<!-- ========= END OF CLASS DATA ========= -->
+<!-- ======= START OF BOTTOM NAVBAR ====== -->
+<div class="bottomNav"><a name="navbar.bottom">
+<!--   -->
+</a>
+<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
+<a name="navbar.bottom.firstrow">
+<!--   -->
+</a>
+<ul class="navList" title="Navigation">
+<li><a href="../../../../../overview-summary.html">Overview</a></li>
+<li><a href="package-summary.html">Package</a></li>
+<li class="navBarCell1Rev">Class</li>
+<li><a href="class-use/TestSwitchToStreamRead.MatchLastRowCellNextRowFilter.html">Use</a></li>
+<li><a href="package-tree.html">Tree</a></li>
+<li><a href="../../../../../deprecated-list.html">Deprecated</a></li>
+<li><a href="../../../../../index-all.html">Index</a></li>
+<li><a href="../../../../../help-doc.html">Help</a></li>
+</ul>
+</div>
+<div class="subNav">
+<ul class="navList">
+<li><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextColFilter.html" title="class in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">Prev&nbsp;Class</span></a></li>
+<li><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html" title="class in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">Next&nbsp;Class</span></a></li>
+</ul>
+<ul class="navList">
+<li><a href="../../../../../index.html?org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextRowFilter.html" target="_top">Frames</a></li>
+<li><a href="TestSwitchToStreamRead.MatchLastRowCellNextRowFilter.html" target="_top">No&nbsp;Frames</a></li>
+</ul>
+<ul class="navList" id="allclasses_navbar_bottom">
+<li><a href="../../../../../allclasses-noframe.html">All&nbsp;Classes</a></li>
+</ul>
+<div>
+<script type="text/javascript"><!--
+  allClassesLink = document.getElementById("allclasses_navbar_bottom");
+  if(window==top) {
+    allClassesLink.style.display = "block";
+  }
+  else {
+    allClassesLink.style.display = "none";
+  }
+  //-->
+</script>
+</div>
+<div>
+<ul class="subNavList">
+<li>Summary:&nbsp;</li>
+<li><a href="#nested.classes.inherited.from.class.org.apache.hadoop.hbase.filter.Filter">Nested</a>&nbsp;|&nbsp;</li>
+<li><a href="#fields.inherited.from.class.org.apache.hadoop.hbase.filter.Filter">Field</a>&nbsp;|&nbsp;</li>
+<li><a href="#constructor.summary">Constr</a>&nbsp;|&nbsp;</li>
+<li><a href="#method.summary">Method</a></li>
+</ul>
+<ul class="subNavList">
+<li>Detail:&nbsp;</li>
+<li>Field&nbsp;|&nbsp;</li>
+<li><a href="#constructor.detail">Constr</a>&nbsp;|&nbsp;</li>
+<li><a href="#method.detail">Method</a></li>
+</ul>
+</div>
+<a name="skip.navbar.bottom">
+<!--   -->
+</a></div>
+<!-- ======== END OF BOTTOM NAVBAR ======= -->
+<p class="legalCopy"><small>Copyright &#169; 2007&#x2013;2018 <a href="https://www.apache.org/">The Apache Software Foundation</a>. All rights reserved.</small></p>
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html b/testdevapidocs/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html
new file mode 100644
index 0000000..78e1919
--- /dev/null
+++ b/testdevapidocs/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html
@@ -0,0 +1,422 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!-- NewPage -->
+<html lang="en">
+<head>
+<!-- Generated by javadoc -->
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>TestSwitchToStreamRead.MatchLastRowFilterRowFilter (Apache HBase 3.0.0-SNAPSHOT Test API)</title>
+<link rel="stylesheet" type="text/css" href="../../../../../stylesheet.css" title="Style">
+<script type="text/javascript" src="../../../../../script.js"></script>
+</head>
+<body>
+<script type="text/javascript"><!--
+    try {
+        if (location.href.indexOf('is-external=true') == -1) {
+            parent.document.title="TestSwitchToStreamRead.MatchLastRowFilterRowFilter (Apache HBase 3.0.0-SNAPSHOT Test API)";
+        }
+    }
+    catch(err) {
+    }
+//-->
+var methods = {"i0":10,"i1":10,"i2":10,"i3":10};
+var tabs = {65535:["t0","All Methods"],2:["t2","Instance Methods"],8:["t4","Concrete Methods"]};
+var altColor = "altColor";
+var rowColor = "rowColor";
+var tableTab = "tableTab";
+var activeTableTab = "activeTableTab";
+</script>
+<noscript>
+<div>JavaScript is disabled on your browser.</div>
+</noscript>
+<!-- ========= START OF TOP NAVBAR ======= -->
+<div class="topNav"><a name="navbar.top">
+<!--   -->
+</a>
+<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
+<a name="navbar.top.firstrow">
+<!--   -->
+</a>
+<ul class="navList" title="Navigation">
+<li><a href="../../../../../overview-summary.html">Overview</a></li>
+<li><a href="package-summary.html">Package</a></li>
+<li class="navBarCell1Rev">Class</li>
+<li><a href="class-use/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html">Use</a></li>
+<li><a href="package-tree.html">Tree</a></li>
+<li><a href="../../../../../deprecated-list.html">Deprecated</a></li>
+<li><a href="../../../../../index-all.html">Index</a></li>
+<li><a href="../../../../../help-doc.html">Help</a></li>
+</ul>
+</div>
+<div class="subNav">
+<ul class="navList">
+<li><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextRowFilter.html" title="class in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">Prev&nbsp;Class</span></a></li>
+<li><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowKeyFilter.html" title="class in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">Next&nbsp;Class</span></a></li>
+</ul>
+<ul class="navList">
+<li><a href="../../../../../index.html?org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html" target="_top">Frames</a></li>
+<li><a href="TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html" target="_top">No&nbsp;Frames</a></li>
+</ul>
+<ul class="navList" id="allclasses_navbar_top">
+<li><a href="../../../../../allclasses-noframe.html">All&nbsp;Classes</a></li>
+</ul>
+<div>
+<script type="text/javascript"><!--
+  allClassesLink = document.getElementById("allclasses_navbar_top");
+  if(window==top) {
+    allClassesLink.style.display = "block";
+  }
+  else {
+    allClassesLink.style.display = "none";
+  }
+  //-->
+</script>
+</div>
+<div>
+<ul class="subNavList">
+<li>Summary:&nbsp;</li>
+<li><a href="#nested.classes.inherited.from.class.org.apache.hadoop.hbase.filter.Filter">Nested</a>&nbsp;|&nbsp;</li>
+<li><a href="#field.summary">Field</a>&nbsp;|&nbsp;</li>
+<li><a href="#constructor.summary">Constr</a>&nbsp;|&nbsp;</li>
+<li><a href="#method.summary">Method</a></li>
+</ul>
+<ul class="subNavList">
+<li>Detail:&nbsp;</li>
+<li><a href="#field.detail">Field</a>&nbsp;|&nbsp;</li>
+<li><a href="#constructor.detail">Constr</a>&nbsp;|&nbsp;</li>
+<li><a href="#method.detail">Method</a></li>
+</ul>
+</div>
+<a name="skip.navbar.top">
+<!--   -->
+</a></div>
+<!-- ========= END OF TOP NAVBAR ========= -->
+<!-- ======== START OF CLASS DATA ======== -->
+<div class="header">
+<div class="subTitle">org.apache.hadoop.hbase.regionserver</div>
+<h2 title="Class TestSwitchToStreamRead.MatchLastRowFilterRowFilter" class="title">Class TestSwitchToStreamRead.MatchLastRowFilterRowFilter</h2>
+</div>
+<div class="contentContainer">
+<ul class="inheritance">
+<li><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true" title="class or interface in java.lang">java.lang.Object</a></li>
+<li>
+<ul class="inheritance">
+<li>org.apache.hadoop.hbase.filter.Filter</li>
+<li>
+<ul class="inheritance">
+<li>org.apache.hadoop.hbase.filter.FilterBase</li>
+<li>
+<ul class="inheritance">
+<li>org.apache.hadoop.hbase.regionserver.TestSwitchToStreamRead.MatchLastRowFilterRowFilter</li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+<div class="description">
+<ul class="blockList">
+<li class="blockList">
+<dl>
+<dt>Enclosing class:</dt>
+<dd><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html" title="class in org.apache.hadoop.hbase.regionserver">TestSwitchToStreamRead</a></dd>
+</dl>
+<hr>
+<br>
+<pre>public static final class <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html#line.232">TestSwitchToStreamRead.MatchLastRowFilterRowFilter</a>
+extends org.apache.hadoop.hbase.filter.FilterBase</pre>
+</li>
+</ul>
+</div>
+<div class="summary">
+<ul class="blockList">
+<li class="blockList">
+<!-- ======== NESTED CLASS SUMMARY ======== -->
+<ul class="blockList">
+<li class="blockList"><a name="nested.class.summary">
+<!--   -->
+</a>
+<h3>Nested Class Summary</h3>
+<ul class="blockList">
+<li class="blockList"><a name="nested.classes.inherited.from.class.org.apache.hadoop.hbase.filter.Filter">
+<!--   -->
+</a>
+<h3>Nested classes/interfaces inherited from class&nbsp;org.apache.hadoop.hbase.filter.Filter</h3>
+<code>org.apache.hadoop.hbase.filter.Filter.ReturnCode</code></li>
+</ul>
+</li>
+</ul>
+<!-- =========== FIELD SUMMARY =========== -->
+<ul class="blockList">
+<li class="blockList"><a name="field.summary">
+<!--   -->
+</a>
+<h3>Field Summary</h3>
+<table class="memberSummary" border="0" cellpadding="3" cellspacing="0" summary="Field Summary table, listing fields, and an explanation">
+<caption><span>Fields</span><span class="tabEnd">&nbsp;</span></caption>
+<tr>
+<th class="colFirst" scope="col">Modifier and Type</th>
+<th class="colLast" scope="col">Field and Description</th>
+</tr>
+<tr class="altColor">
+<td class="colFirst"><code>private boolean</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html#exclude">exclude</a></span></code>&nbsp;</td>
+</tr>
+</table>
+<ul class="blockList">
+<li class="blockList"><a name="fields.inherited.from.class.org.apache.hadoop.hbase.filter.Filter">
+<!--   -->
+</a>
+<h3>Fields inherited from class&nbsp;org.apache.hadoop.hbase.filter.Filter</h3>
+<code>reversed</code></li>
+</ul>
+</li>
+</ul>
+<!-- ======== CONSTRUCTOR SUMMARY ======== -->
+<ul class="blockList">
+<li class="blockList"><a name="constructor.summary">
+<!--   -->
+</a>
+<h3>Constructor Summary</h3>
+<table class="memberSummary" border="0" cellpadding="3" cellspacing="0" summary="Constructor Summary table, listing constructors, and an explanation">
+<caption><span>Constructors</span><span class="tabEnd">&nbsp;</span></caption>
+<tr>
+<th class="colOne" scope="col">Constructor and Description</th>
+</tr>
+<tr class="altColor">
+<td class="colOne"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html#MatchLastRowFilterRowFilter--">MatchLastRowFilterRowFilter</a></span>()</code>&nbsp;</td>
+</tr>
+</table>
+</li>
+</ul>
+<!-- ========== METHOD SUMMARY =========== -->
+<ul class="blockList">
+<li class="blockList"><a name="method.summary">
+<!--   -->
+</a>
+<h3>Method Summary</h3>
+<table class="memberSummary" border="0" cellpadding="3" cellspacing="0" summary="Method Summary table, listing methods, and an explanation">
+<caption><span id="t0" class="activeTableTab"><span>All Methods</span><span class="tabEnd">&nbsp;</span></span><span id="t2" class="tableTab"><span><a href="javascript:show(2);">Instance Methods</a></span><span class="tabEnd">&nbsp;</span></span><span id="t4" class="tableTab"><span><a href="javascript:show(8);">Concrete Methods</a></span><span class="tabEnd">&nbsp;</span></span></caption>
+<tr>
+<th class="colFirst" scope="col">Modifier and Type</th>
+<th class="colLast" scope="col">Method and Description</th>
+</tr>
+<tr id="i0" class="altColor">
+<td class="colFirst"><code>boolean</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html#filterRow--">filterRow</a></span>()</code>&nbsp;</td>
+</tr>
+<tr id="i1" class="rowColor">
+<td class="colFirst"><code>void</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html#filterRowCells-java.util.List-">filterRowCells</a></span>(<a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html?is-external=true" title="class or interface in java.util">List</a>&lt;org.apache.hadoop.hbase.Cell&gt;&nbsp;kvs)</code>&nbsp;</td>
+</tr>
+<tr id="i2" class="altColor">
+<td class="colFirst"><code>boolean</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html#hasFilterRow--">hasFilterRow</a></span>()</code>&nbsp;</td>
+</tr>
+<tr id="i3" class="rowColor">
+<td class="colFirst"><code>void</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html#reset--">reset</a></span>()</code>&nbsp;</td>
+</tr>
+</table>
+<ul class="blockList">
+<li class="blockList"><a name="methods.inherited.from.class.org.apache.hadoop.hbase.filter.FilterBase">
+<!--   -->
+</a>
+<h3>Methods inherited from class&nbsp;org.apache.hadoop.hbase.filter.FilterBase</h3>
+<code>createFilterFromArguments, filterAllRemaining, filterRowKey, filterRowKey, getNextCellHint, isFamilyEssential, toByteArray, toString, transformCell</code></li>
+</ul>
+<ul class="blockList">
+<li class="blockList"><a name="methods.inherited.from.class.org.apache.hadoop.hbase.filter.Filter">
+<!--   -->
+</a>
+<h3>Methods inherited from class&nbsp;org.apache.hadoop.hbase.filter.Filter</h3>
+<code>filterCell, filterKeyValue, isReversed, parseFrom, setReversed</code></li>
+</ul>
+<ul class="blockList">
+<li class="blockList"><a name="methods.inherited.from.class.java.lang.Object">
+<!--   -->
+</a>
+<h3>Methods inherited from class&nbsp;java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true" title="class or interface in java.lang">Object</a></h3>
+<code><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true#clone--" title="class or interface in java.lang">clone</a>, <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true#equals-java.lang.Object-" title="class or interface in java.lang">equals</a>, <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true#finalize--" title="class or interface in java.lang">finalize</a>, <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true#getClass--" title="class or interface in java.lang">getClass</a>, <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true#hashCode--" title="class or interface in java.lang">hashCode</a>, <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true#notify--" title="class or interface in java.lang">notify</a>, <a href="https://docs.oracle.com/javase/8/docs/api/ja
 va/lang/Object.html?is-external=true#notifyAll--" title="class or interface in java.lang">notifyAll</a>, <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true#wait--" title="class or interface in java.lang">wait</a>, <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true#wait-long-" title="class or interface in java.lang">wait</a>, <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true#wait-long-int-" title="class or interface in java.lang">wait</a></code></li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+</div>
+<div class="details">
+<ul class="blockList">
+<li class="blockList">
+<!-- ============ FIELD DETAIL =========== -->
+<ul class="blockList">
+<li class="blockList"><a name="field.detail">
+<!--   -->
+</a>
+<h3>Field Detail</h3>
+<a name="exclude">
+<!--   -->
+</a>
+<ul class="blockListLast">
+<li class="blockList">
+<h4>exclude</h4>
+<pre>private&nbsp;boolean <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html#line.234">exclude</a></pre>
+</li>
+</ul>
+</li>
+</ul>
+<!-- ========= CONSTRUCTOR DETAIL ======== -->
+<ul class="blockList">
+<li class="blockList"><a name="constructor.detail">
+<!--   -->
+</a>
+<h3>Constructor Detail</h3>
+<a name="MatchLastRowFilterRowFilter--">
+<!--   -->
+</a>
+<ul class="blockListLast">
+<li class="blockList">
+<h4>MatchLastRowFilterRowFilter</h4>
+<pre>public&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html#line.232">MatchLastRowFilterRowFilter</a>()</pre>
+</li>
+</ul>
+</li>
+</ul>
+<!-- ============ METHOD DETAIL ========== -->
+<ul class="blockList">
+<li class="blockList"><a name="method.detail">
+<!--   -->
+</a>
+<h3>Method Detail</h3>
+<a name="filterRowCells-java.util.List-">
+<!--   -->
+</a>
+<ul class="blockList">
+<li class="blockList">
+<h4>filterRowCells</h4>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html#line.237">filterRowCells</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html?is-external=true" title="class or interface in java.util">List</a>&lt;org.apache.hadoop.hbase.Cell&gt;&nbsp;kvs)
+                    throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
+<dl>
+<dt><span class="overrideSpecifyLabel">Overrides:</span></dt>
+<dd><code>filterRowCells</code>&nbsp;in class&nbsp;<code>org.apache.hadoop.hbase.filter.FilterBase</code></dd>
+<dt><span class="throwsLabel">Throws:</span></dt>
+<dd><code><a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></code></dd>
+</dl>
+</li>
+</ul>
+<a name="reset--">
+<!--   -->
+</a>
+<ul class="blockList">
+<li class="blockList">
+<h4>reset</h4>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html#line.243">reset</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="overrideSpecifyLabel">Overrides:</span></dt>
+<dd><code>reset</code>&nbsp;in class&nbsp;<code>org.apache.hadoop.hbase.filter.FilterBase</code></dd>
+<dt><span class="throwsLabel">Throws:</span></dt>
+<dd><code><a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></code></dd>
+</dl>
+</li>
+</ul>
+<a name="filterRow--">
+<!--   -->
+</a>
+<ul class="blockList">
+<li class="blockList">
+<h4>filterRow</h4>
+<pre>public&nbsp;boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html#line.248">filterRow</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="overrideSpecifyLabel">Overrides:</span></dt>
+<dd><code>filterRow</code>&nbsp;in class&nbsp;<code>org.apache.hadoop.hbase.filter.FilterBase</code></dd>
+<dt><span class="throwsLabel">Throws:</span></dt>
+<dd><code><a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></code></dd>
+</dl>
+</li>
+</ul>
+<a name="hasFilterRow--">
+<!--   -->
+</a>
+<ul class="blockListLast">
+<li class="blockList">
+<h4>hasFilterRow</h4>
+<pre>public&nbsp;boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html#line.253">hasFilterRow</a>()</pre>
+<dl>
+<dt><span class="overrideSpecifyLabel">Overrides:</span></dt>
+<dd><code>hasFilterRow</code>&nbsp;in class&nbsp;<code>org.apache.hadoop.hbase.filter.FilterBase</code></dd>
+</dl>
+</li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+</div>
+</div>
+<!-- ========= END OF CLASS DATA ========= -->
+<!-- ======= START OF BOTTOM NAVBAR ====== -->
+<div class="bottomNav"><a name="navbar.bottom">
+<!--   -->
+</a>
+<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
+<a name="navbar.bottom.firstrow">
+<!--   -->
+</a>
+<ul class="navList" title="Navigation">
+<li><a href="../../../../../overview-summary.html">Overview</a></li>
+<li><a href="package-summary.html">Package</a></li>
+<li class="navBarCell1Rev">Class</li>
+<li><a href="class-use/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html">Use</a></li>
+<li><a href="package-tree.html">Tree</a></li>
+<li><a href="../../../../../deprecated-list.html">Deprecated</a></li>
+<li><a href="../../../../../index-all.html">Index</a></li>
+<li><a href="../../../../../help-doc.html">Help</a></li>
+</ul>
+</div>
+<div class="subNav">
+<ul class="navList">
+<li><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextRowFilter.html" title="class in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">Prev&nbsp;Class</span></a></li>
+<li><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowKeyFilter.html" title="class in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">Next&nbsp;Class</span></a></li>
+</ul>
+<ul class="navList">
+<li><a href="../../../../../index.html?org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html" target="_top">Frames</a></li>
+<li><a href="TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html" target="_top">No&nbsp;Frames</a></li>
+</ul>
+<ul class="navList" id="allclasses_navbar_bottom">
+<li><a href="../../../../../allclasses-noframe.html">All&nbsp;Classes</a></li>
+</ul>
+<div>
+<script type="text/javascript"><!--
+  allClassesLink = document.getElementById("allclasses_navbar_bottom");
+  if(window==top) {
+    allClassesLink.style.display = "block";
+  }
+  else {
+    allClassesLink.style.display = "none";
+  }
+  //-->
+</script>
+</div>
+<div>
+<ul class="subNavList">
+<li>Summary:&nbsp;</li>
+<li><a href="#nested.classes.inherited.from.class.org.apache.hadoop.hbase.filter.Filter">Nested</a>&nbsp;|&nbsp;</li>
+<li><a href="#field.summary">Field</a>&nbsp;|&nbsp;</li>
+<li><a href="#constructor.summary">Constr</a>&nbsp;|&nbsp;</li>
+<li><a href="#method.summary">Method</a></li>
+</ul>
+<ul class="subNavList">
+<li>Detail:&nbsp;</li>
+<li><a href="#field.detail">Field</a>&nbsp;|&nbsp;</li>
+<li><a href="#constructor.detail">Constr</a>&nbsp;|&nbsp;</li>
+<li><a href="#method.detail">Method</a></li>
+</ul>
+</div>
+<a name="skip.navbar.bottom">
+<!--   -->
+</a></div>
+<!-- ======== END OF BOTTOM NAVBAR ======= -->
+<p class="legalCopy"><small>Copyright &#169; 2007&#x2013;2018 <a href="https://www.apache.org/">The Apache Software Foundation</a>. All rights reserved.</small></p>
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowKeyFilter.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowKeyFilter.html b/testdevapidocs/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowKeyFilter.html
new file mode 100644
index 0000000..846d1a9
--- /dev/null
+++ b/testdevapidocs/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowKeyFilter.html
@@ -0,0 +1,337 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!-- NewPage -->
+<html lang="en">
+<head>
+<!-- Generated by javadoc -->
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>TestSwitchToStreamRead.MatchLastRowKeyFilter (Apache HBase 3.0.0-SNAPSHOT Test API)</title>
+<link rel="stylesheet" type="text/css" href="../../../../../stylesheet.css" title="Style">
+<script type="text/javascript" src="../../../../../script.js"></script>
+</head>
+<body>
+<script type="text/javascript"><!--
+    try {
+        if (location.href.indexOf('is-external=true') == -1) {
+            parent.document.title="TestSwitchToStreamRead.MatchLastRowKeyFilter (Apache HBase 3.0.0-SNAPSHOT Test API)";
+        }
+    }
+    catch(err) {
+    }
+//-->
+var methods = {"i0":10};
+var tabs = {65535:["t0","All Methods"],2:["t2","Instance Methods"],8:["t4","Concrete Methods"]};
+var altColor = "altColor";
+var rowColor = "rowColor";
+var tableTab = "tableTab";
+var activeTableTab = "activeTableTab";
+</script>
+<noscript>
+<div>JavaScript is disabled on your browser.</div>
+</noscript>
+<!-- ========= START OF TOP NAVBAR ======= -->
+<div class="topNav"><a name="navbar.top">
+<!--   -->
+</a>
+<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
+<a name="navbar.top.firstrow">
+<!--   -->
+</a>
+<ul class="navList" title="Navigation">
+<li><a href="../../../../../overview-summary.html">Overview</a></li>
+<li><a href="package-summary.html">Package</a></li>
+<li class="navBarCell1Rev">Class</li>
+<li><a href="class-use/TestSwitchToStreamRead.MatchLastRowKeyFilter.html">Use</a></li>
+<li><a href="package-tree.html">Tree</a></li>
+<li><a href="../../../../../deprecated-list.html">Deprecated</a></li>
+<li><a href="../../../../../index-all.html">Index</a></li>
+<li><a href="../../../../../help-doc.html">Help</a></li>
+</ul>
+</div>
+<div class="subNav">
+<ul class="navList">
+<li><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html" title="class in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">Prev&nbsp;Class</span></a></li>
+<li><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSyncTimeRangeTracker.html" title="class in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">Next&nbsp;Class</span></a></li>
+</ul>
+<ul class="navList">
+<li><a href="../../../../../index.html?org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowKeyFilter.html" target="_top">Frames</a></li>
+<li><a href="TestSwitchToStreamRead.MatchLastRowKeyFilter.html" target="_top">No&nbsp;Frames</a></li>
+</ul>
+<ul class="navList" id="allclasses_navbar_top">
+<li><a href="../../../../../allclasses-noframe.html">All&nbsp;Classes</a></li>
+</ul>
+<div>
+<script type="text/javascript"><!--
+  allClassesLink = document.getElementById("allclasses_navbar_top");
+  if(window==top) {
+    allClassesLink.style.display = "block";
+  }
+  else {
+    allClassesLink.style.display = "none";
+  }
+  //-->
+</script>
+</div>
+<div>
+<ul class="subNavList">
+<li>Summary:&nbsp;</li>
+<li><a href="#nested.classes.inherited.from.class.org.apache.hadoop.hbase.filter.Filter">Nested</a>&nbsp;|&nbsp;</li>
+<li><a href="#fields.inherited.from.class.org.apache.hadoop.hbase.filter.Filter">Field</a>&nbsp;|&nbsp;</li>
+<li><a href="#constructor.summary">Constr</a>&nbsp;|&nbsp;</li>
+<li><a href="#method.summary">Method</a></li>
+</ul>
+<ul class="subNavList">
+<li>Detail:&nbsp;</li>
+<li>Field&nbsp;|&nbsp;</li>
+<li><a href="#constructor.detail">Constr</a>&nbsp;|&nbsp;</li>
+<li><a href="#method.detail">Method</a></li>
+</ul>
+</div>
+<a name="skip.navbar.top">
+<!--   -->
+</a></div>
+<!-- ========= END OF TOP NAVBAR ========= -->
+<!-- ======== START OF CLASS DATA ======== -->
+<div class="header">
+<div class="subTitle">org.apache.hadoop.hbase.regionserver</div>
+<h2 title="Class TestSwitchToStreamRead.MatchLastRowKeyFilter" class="title">Class TestSwitchToStreamRead.MatchLastRowKeyFilter</h2>
+</div>
+<div class="contentContainer">
+<ul class="inheritance">
+<li><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true" title="class or interface in java.lang">java.lang.Object</a></li>
+<li>
+<ul class="inheritance">
+<li>org.apache.hadoop.hbase.filter.Filter</li>
+<li>
+<ul class="inheritance">
+<li>org.apache.hadoop.hbase.filter.FilterBase</li>
+<li>
+<ul class="inheritance">
+<li>org.apache.hadoop.hbase.regionserver.TestSwitchToStreamRead.MatchLastRowKeyFilter</li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+<div class="description">
+<ul class="blockList">
+<li class="blockList">
+<dl>
+<dt>Enclosing class:</dt>
+<dd><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html" title="class in org.apache.hadoop.hbase.regionserver">TestSwitchToStreamRead</a></dd>
+</dl>
+<hr>
+<br>
+<pre>public static final class <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html#line.142">TestSwitchToStreamRead.MatchLastRowKeyFilter</a>
+extends org.apache.hadoop.hbase.filter.FilterBase</pre>
+</li>
+</ul>
+</div>
+<div class="summary">
+<ul class="blockList">
+<li class="blockList">
+<!-- ======== NESTED CLASS SUMMARY ======== -->
+<ul class="blockList">
+<li class="blockList"><a name="nested.class.summary">
+<!--   -->
+</a>
+<h3>Nested Class Summary</h3>
+<ul class="blockList">
+<li class="blockList"><a name="nested.classes.inherited.from.class.org.apache.hadoop.hbase.filter.Filter">
+<!--   -->
+</a>
+<h3>Nested classes/interfaces inherited from class&nbsp;org.apache.hadoop.hbase.filter.Filter</h3>
+<code>org.apache.hadoop.hbase.filter.Filter.ReturnCode</code></li>
+</ul>
+</li>
+</ul>
+<!-- =========== FIELD SUMMARY =========== -->
+<ul class="blockList">
+<li class="blockList"><a name="field.summary">
+<!--   -->
+</a>
+<h3>Field Summary</h3>
+<ul class="blockList">
+<li class="blockList"><a name="fields.inherited.from.class.org.apache.hadoop.hbase.filter.Filter">
+<!--   -->
+</a>
+<h3>Fields inherited from class&nbsp;org.apache.hadoop.hbase.filter.Filter</h3>
+<code>reversed</code></li>
+</ul>
+</li>
+</ul>
+<!-- ======== CONSTRUCTOR SUMMARY ======== -->
+<ul class="blockList">
+<li class="blockList"><a name="constructor.summary">
+<!--   -->
+</a>
+<h3>Constructor Summary</h3>
+<table class="memberSummary" border="0" cellpadding="3" cellspacing="0" summary="Constructor Summary table, listing constructors, and an explanation">
+<caption><span>Constructors</span><span class="tabEnd">&nbsp;</span></caption>
+<tr>
+<th class="colOne" scope="col">Constructor and Description</th>
+</tr>
+<tr class="altColor">
+<td class="colOne"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowKeyFilter.html#MatchLastRowKeyFilter--">MatchLastRowKeyFilter</a></span>()</code>&nbsp;</td>
+</tr>
+</table>
+</li>
+</ul>
+<!-- ========== METHOD SUMMARY =========== -->
+<ul class="blockList">
+<li class="blockList"><a name="method.summary">
+<!--   -->
+</a>
+<h3>Method Summary</h3>
+<table class="memberSummary" border="0" cellpadding="3" cellspacing="0" summary="Method Summary table, listing methods, and an explanation">
+<caption><span id="t0" class="activeTableTab"><span>All Methods</span><span class="tabEnd">&nbsp;</span></span><span id="t2" class="tableTab"><span><a href="javascript:show(2);">Instance Methods</a></span><span class="tabEnd">&nbsp;</span></span><span id="t4" class="tableTab"><span><a href="javascript:show(8);">Concrete Methods</a></span><span class="tabEnd">&nbsp;</span></span></caption>
+<tr>
+<th class="colFirst" scope="col">Modifier and Type</th>
+<th class="colLast" scope="col">Method and Description</th>
+</tr>
+<tr id="i0" class="altColor">
+<td class="colFirst"><code>boolean</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowKeyFilter.html#filterRowKey-org.apache.hadoop.hbase.Cell-">filterRowKey</a></span>(org.apache.hadoop.hbase.Cell&nbsp;cell)</code>&nbsp;</td>
+</tr>
+</table>
+<ul class="blockList">
+<li class="blockList"><a name="methods.inherited.from.class.org.apache.hadoop.hbase.filter.FilterBase">
+<!--   -->
+</a>
+<h3>Methods inherited from class&nbsp;org.apache.hadoop.hbase.filter.FilterBase</h3>
+<code>createFilterFromArguments, filterAllRemaining, filterRow, filterRowCells, filterRowKey, getNextCellHint, hasFilterRow, isFamilyEssential, reset, toByteArray, toString, transformCell</code></li>
+</ul>
+<ul class="blockList">
+<li class="blockList"><a name="methods.inherited.from.class.org.apache.hadoop.hbase.filter.Filter">
+<!--   -->
+</a>
+<h3>Methods inherited from class&nbsp;org.apache.hadoop.hbase.filter.Filter</h3>
+<code>filterCell, filterKeyValue, isReversed, parseFrom, setReversed</code></li>
+</ul>
+<ul class="blockList">
+<li class="blockList"><a name="methods.inherited.from.class.java.lang.Object">
+<!--   -->
+</a>
+<h3>Methods inherited from class&nbsp;java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true" title="class or interface in java.lang">Object</a></h3>
+<code><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true#clone--" title="class or interface in java.lang">clone</a>, <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true#equals-java.lang.Object-" title="class or interface in java.lang">equals</a>, <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true#finalize--" title="class or interface in java.lang">finalize</a>, <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true#getClass--" title="class or interface in java.lang">getClass</a>, <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true#hashCode--" title="class or interface in java.lang">hashCode</a>, <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true#notify--" title="class or interface in java.lang">notify</a>, <a href="https://docs.oracle.com/javase/8/docs/api/ja
 va/lang/Object.html?is-external=true#notifyAll--" title="class or interface in java.lang">notifyAll</a>, <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true#wait--" title="class or interface in java.lang">wait</a>, <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true#wait-long-" title="class or interface in java.lang">wait</a>, <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true#wait-long-int-" title="class or interface in java.lang">wait</a></code></li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+</div>
+<div class="details">
+<ul class="blockList">
+<li class="blockList">
+<!-- ========= CONSTRUCTOR DETAIL ======== -->
+<ul class="blockList">
+<li class="blockList"><a name="constructor.detail">
+<!--   -->
+</a>
+<h3>Constructor Detail</h3>
+<a name="MatchLastRowKeyFilter--">
+<!--   -->
+</a>
+<ul class="blockListLast">
+<li class="blockList">
+<h4>MatchLastRowKeyFilter</h4>
+<pre>public&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowKeyFilter.html#line.142">MatchLastRowKeyFilter</a>()</pre>
+</li>
+</ul>
+</li>
+</ul>
+<!-- ============ METHOD DETAIL ========== -->
+<ul class="blockList">
+<li class="blockList"><a name="method.detail">
+<!--   -->
+</a>
+<h3>Method Detail</h3>
+<a name="filterRowKey-org.apache.hadoop.hbase.Cell-">
+<!--   -->
+</a>
+<ul class="blockListLast">
+<li class="blockList">
+<h4>filterRowKey</h4>
+<pre>public&nbsp;boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowKeyFilter.html#line.145">filterRowKey</a>(org.apache.hadoop.hbase.Cell&nbsp;cell)
+                     throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
+<dl>
+<dt><span class="overrideSpecifyLabel">Overrides:</span></dt>
+<dd><code>filterRowKey</code>&nbsp;in class&nbsp;<code>org.apache.hadoop.hbase.filter.FilterBase</code></dd>
+<dt><span class="throwsLabel">Throws:</span></dt>
+<dd><code><a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></code></dd>
+</dl>
+</li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+</div>
+</div>
+<!-- ========= END OF CLASS DATA ========= -->
+<!-- ======= START OF BOTTOM NAVBAR ====== -->
+<div class="bottomNav"><a name="navbar.bottom">
+<!--   -->
+</a>
+<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
+<a name="navbar.bottom.firstrow">
+<!--   -->
+</a>
+<ul class="navList" title="Navigation">
+<li><a href="../../../../../overview-summary.html">Overview</a></li>
+<li><a href="package-summary.html">Package</a></li>
+<li class="navBarCell1Rev">Class</li>
+<li><a href="class-use/TestSwitchToStreamRead.MatchLastRowKeyFilter.html">Use</a></li>
+<li><a href="package-tree.html">Tree</a></li>
+<li><a href="../../../../../deprecated-list.html">Deprecated</a></li>
+<li><a href="../../../../../index-all.html">Index</a></li>
+<li><a href="../../../../../help-doc.html">Help</a></li>
+</ul>
+</div>
+<div class="subNav">
+<ul class="navList">
+<li><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html" title="class in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">Prev&nbsp;Class</span></a></li>
+<li><a href="../../../../../org/apache/hadoop/hbase/regionserver/TestSyncTimeRangeTracker.html" title="class in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">Next&nbsp;Class</span></a></li>
+</ul>
+<ul class="navList">
+<li><a href="../../../../../index.html?org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowKeyFilter.html" target="_top">Frames</a></li>
+<li><a href="TestSwitchToStreamRead.MatchLastRowKeyFilter.html" target="_top">No&nbsp;Frames</a></li>
+</ul>
+<ul class="navList" id="allclasses_navbar_bottom">
+<li><a href="../../../../../allclasses-noframe.html">All&nbsp;Classes</a></li>
+</ul>
+<div>
+<script type="text/javascript"><!--
+  allClassesLink = document.getElementById("allclasses_navbar_bottom");
+  if(window==top) {
+    allClassesLink.style.display = "block";
+  }
+  else {
+    allClassesLink.style.display = "none";
+  }
+  //-->
+</script>
+</div>
+<div>
+<ul class="subNavList">
+<li>Summary:&nbsp;</li>
+<li><a href="#nested.classes.inherited.from.class.org.apache.hadoop.hbase.filter.Filter">Nested</a>&nbsp;|&nbsp;</li>
+<li><a href="#fields.inherited.from.class.org.apache.hadoop.hbase.filter.Filter">Field</a>&nbsp;|&nbsp;</li>
+<li><a href="#constructor.summary">Constr</a>&nbsp;|&nbsp;</li>
+<li><a href="#method.summary">Method</a></li>
+</ul>
+<ul class="subNavList">
+<li>Detail:&nbsp;</li>
+<li>Field&nbsp;|&nbsp;</li>
+<li><a href="#constructor.detail">Constr</a>&nbsp;|&nbsp;</li>
+<li><a href="#method.detail">Method</a></li>
+</ul>
+</div>
+<a name="skip.navbar.bottom">
+<!--   -->
+</a></div>
+<!-- ======== END OF BOTTOM NAVBAR ======= -->
+<p class="legalCopy"><small>Copyright &#169; 2007&#x2013;2018 <a href="https://www.apache.org/">The Apache Software Foundation</a>. All rights reserved.</small></p>
+</body>
+</html>


[46/50] hbase-site git commit: Published site at 26babcf013de696b899d76a3c39434b794440d8d.

Posted by gi...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html b/devapidocs/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html
index 03041e5..8d21f22 100644
--- a/devapidocs/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html
+++ b/devapidocs/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html
@@ -1265,7 +1265,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Resizable
 <ul class="blockListLast">
 <li class="blockList">
 <h4>CACHE_FIXED_OVERHEAD</h4>
-<pre>public static final&nbsp;long <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.980">CACHE_FIXED_OVERHEAD</a></pre>
+<pre>public static final&nbsp;long <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.985">CACHE_FIXED_OVERHEAD</a></pre>
 </li>
 </ul>
 </li>
@@ -1422,7 +1422,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Resizable
 <ul class="blockList">
 <li class="blockList">
 <h4>assertCounterSanity</h4>
-<pre>private static&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.429">assertCounterSanity</a>(long&nbsp;mapSize,
+<pre>private static&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.434">assertCounterSanity</a>(long&nbsp;mapSize,
                                         long&nbsp;counterVal)</pre>
 <div class="block">Sanity-checking for parity between actual block cache content and metrics.
  Intended only for use with TRACE level logging and -ea JVM.</div>
@@ -1434,7 +1434,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Resizable
 <ul class="blockList">
 <li class="blockList">
 <h4>cacheBlock</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.452">cacheBlock</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a>&nbsp;cacheKey,
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.457">cacheBlock</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a>&nbsp;cacheKey,
                        <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html" title="interface in org.apache.hadoop.hbase.io.hfile">Cacheable</a>&nbsp;buf)</pre>
 <div class="block">Cache the block with the specified name and buffer.
  <p></div>
@@ -1453,7 +1453,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Resizable
 <ul class="blockList">
 <li class="blockList">
 <h4>updateSizeMetrics</h4>
-<pre>private&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.461">updateSizeMetrics</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/LruCachedBlock.html" title="class in org.apache.hadoop.hbase.io.hfile">LruCachedBlock</a>&nbsp;cb,
+<pre>private&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.466">updateSizeMetrics</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/LruCachedBlock.html" title="class in org.apache.hadoop.hbase.io.hfile">LruCachedBlock</a>&nbsp;cb,
                                boolean&nbsp;evict)</pre>
 <div class="block">Helper function that updates the local size counter and also updates any
  per-cf or per-blocktype metrics it can discern from given
@@ -1466,7 +1466,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Resizable
 <ul class="blockList">
 <li class="blockList">
 <h4>getBlock</h4>
-<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html" title="interface in org.apache.hadoop.hbase.io.hfile">Cacheable</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.486">getBlock</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a>&nbsp;cacheKey,
+<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html" title="interface in org.apache.hadoop.hbase.io.hfile">Cacheable</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.491">getBlock</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a>&nbsp;cacheKey,
                           boolean&nbsp;caching,
                           boolean&nbsp;repeat,
                           boolean&nbsp;updateCacheMetrics)</pre>
@@ -1492,7 +1492,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Resizable
 <ul class="blockList">
 <li class="blockList">
 <h4>containsBlock</h4>
-<pre>public&nbsp;boolean&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.520">containsBlock</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a>&nbsp;cacheKey)</pre>
+<pre>public&nbsp;boolean&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.525">containsBlock</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a>&nbsp;cacheKey)</pre>
 <div class="block">Whether the cache contains block with specified cacheKey</div>
 <dl>
 <dt><span class="returnLabel">Returns:</span></dt>
@@ -1506,7 +1506,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Resizable
 <ul class="blockList">
 <li class="blockList">
 <h4>evictBlock</h4>
-<pre>public&nbsp;boolean&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.525">evictBlock</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a>&nbsp;cacheKey)</pre>
+<pre>public&nbsp;boolean&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.530">evictBlock</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a>&nbsp;cacheKey)</pre>
 <div class="block"><span class="descfrmTypeLabel">Description copied from interface:&nbsp;<code><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCache.html#evictBlock-org.apache.hadoop.hbase.io.hfile.BlockCacheKey-">BlockCache</a></code></span></div>
 <div class="block">Evict block from cache.</div>
 <dl>
@@ -1525,7 +1525,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Resizable
 <ul class="blockList">
 <li class="blockList">
 <h4>evictBlocksByHfileName</h4>
-<pre>public&nbsp;int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.541">evictBlocksByHfileName</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;hfileName)</pre>
+<pre>public&nbsp;int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.546">evictBlocksByHfileName</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;hfileName)</pre>
 <div class="block">Evicts all blocks for a specific HFile. This is an
  expensive operation implemented as a linear-time search through all blocks
  in the cache. Ideally this should be a search in a log-access-time map.
@@ -1546,7 +1546,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Resizable
 <ul class="blockList">
 <li class="blockList">
 <h4>evictBlock</h4>
-<pre>protected&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.563">evictBlock</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/LruCachedBlock.html" title="class in org.apache.hadoop.hbase.io.hfile">LruCachedBlock</a>&nbsp;block,
+<pre>protected&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.568">evictBlock</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/LruCachedBlock.html" title="class in org.apache.hadoop.hbase.io.hfile">LruCachedBlock</a>&nbsp;block,
                           boolean&nbsp;evictedByEvictionProcess)</pre>
 <div class="block">Evict the block, and it will be cached by the victim handler if exists &amp;&amp;
  block may be read again later</div>
@@ -1565,7 +1565,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Resizable
 <ul class="blockList">
 <li class="blockList">
 <h4>runEviction</h4>
-<pre>private&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.591">runEviction</a>()</pre>
+<pre>private&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.596">runEviction</a>()</pre>
 <div class="block">Multi-threaded call to run the eviction process.</div>
 </li>
 </ul>
@@ -1575,7 +1575,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Resizable
 <ul class="blockList">
 <li class="blockList">
 <h4>isEvictionInProgress</h4>
-<pre>boolean&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.600">isEvictionInProgress</a>()</pre>
+<pre>boolean&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.605">isEvictionInProgress</a>()</pre>
 </li>
 </ul>
 <a name="getOverhead--">
@@ -1584,7 +1584,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Resizable
 <ul class="blockList">
 <li class="blockList">
 <h4>getOverhead</h4>
-<pre>long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.605">getOverhead</a>()</pre>
+<pre>long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.610">getOverhead</a>()</pre>
 </li>
 </ul>
 <a name="evict--">
@@ -1593,7 +1593,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Resizable
 <ul class="blockList">
 <li class="blockList">
 <h4>evict</h4>
-<pre>void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.612">evict</a>()</pre>
+<pre>void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.617">evict</a>()</pre>
 <div class="block">Eviction method.</div>
 </li>
 </ul>
@@ -1603,7 +1603,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Resizable
 <ul class="blockList">
 <li class="blockList">
 <h4>toString</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/io/hfile/LruBlockCache.html#line.731">toString</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/io/hfile/LruBlockCache.html#line.736">toString</a>()</pre>
 <dl>
 <dt><span class="overrideSpecifyLabel">Overrides:</span></dt>
 <dd><code><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true#toString--" title="class or interface in java.lang">toString</a></code>&nbsp;in class&nbsp;<code><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></code></dd>
@@ -1616,7 +1616,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Resizable
 <ul class="blockList">
 <li class="blockList">
 <h4>getMaxSize</h4>
-<pre>public&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.833">getMaxSize</a>()</pre>
+<pre>public&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.838">getMaxSize</a>()</pre>
 <div class="block">Get the maximum size of this cache.</div>
 <dl>
 <dt><span class="overrideSpecifyLabel">Specified by:</span></dt>
@@ -1632,7 +1632,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Resizable
 <ul class="blockList">
 <li class="blockList">
 <h4>getCurrentSize</h4>
-<pre>public&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.838">getCurrentSize</a>()</pre>
+<pre>public&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.843">getCurrentSize</a>()</pre>
 <div class="block"><span class="descfrmTypeLabel">Description copied from interface:&nbsp;<code><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCache.html#getCurrentSize--">BlockCache</a></code></span></div>
 <div class="block">Returns the occupied size of the block cache, in bytes.</div>
 <dl>
@@ -1649,7 +1649,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Resizable
 <ul class="blockList">
 <li class="blockList">
 <h4>getCurrentDataSize</h4>
-<pre>public&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.843">getCurrentDataSize</a>()</pre>
+<pre>public&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.848">getCurrentDataSize</a>()</pre>
 <div class="block"><span class="descfrmTypeLabel">Description copied from interface:&nbsp;<code><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCache.html#getCurrentDataSize--">BlockCache</a></code></span></div>
 <div class="block">Returns the occupied size of data blocks, in bytes.</div>
 <dl>
@@ -1666,7 +1666,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Resizable
 <ul class="blockList">
 <li class="blockList">
 <h4>getFreeSize</h4>
-<pre>public&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.848">getFreeSize</a>()</pre>
+<pre>public&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.853">getFreeSize</a>()</pre>
 <div class="block"><span class="descfrmTypeLabel">Description copied from interface:&nbsp;<code><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCache.html#getFreeSize--">BlockCache</a></code></span></div>
 <div class="block">Returns the free size of the block cache, in bytes.</div>
 <dl>
@@ -1683,7 +1683,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Resizable
 <ul class="blockList">
 <li class="blockList">
 <h4>size</h4>
-<pre>public&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.853">size</a>()</pre>
+<pre>public&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.858">size</a>()</pre>
 <div class="block"><span class="descfrmTypeLabel">Description copied from interface:&nbsp;<code><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCache.html#size--">BlockCache</a></code></span></div>
 <div class="block">Returns the total size of the block cache, in bytes.</div>
 <dl>
@@ -1700,7 +1700,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Resizable
 <ul class="blockList">
 <li class="blockList">
 <h4>getBlockCount</h4>
-<pre>public&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.858">getBlockCount</a>()</pre>
+<pre>public&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.863">getBlockCount</a>()</pre>
 <div class="block"><span class="descfrmTypeLabel">Description copied from interface:&nbsp;<code><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCache.html#getBlockCount--">BlockCache</a></code></span></div>
 <div class="block">Returns the number of blocks currently cached in the block cache.</div>
 <dl>
@@ -1717,7 +1717,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Resizable
 <ul class="blockList">
 <li class="blockList">
 <h4>getDataBlockCount</h4>
-<pre>public&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.863">getDataBlockCount</a>()</pre>
+<pre>public&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.868">getDataBlockCount</a>()</pre>
 <div class="block"><span class="descfrmTypeLabel">Description copied from interface:&nbsp;<code><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCache.html#getDataBlockCount--">BlockCache</a></code></span></div>
 <div class="block">Returns the number of data blocks currently cached in the block cache.</div>
 <dl>
@@ -1734,7 +1734,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Resizable
 <ul class="blockList">
 <li class="blockList">
 <h4>getEvictionThread</h4>
-<pre><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/LruBlockCache.EvictionThread.html" title="class in org.apache.hadoop.hbase.io.hfile">LruBlockCache.EvictionThread</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.867">getEvictionThread</a>()</pre>
+<pre><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/LruBlockCache.EvictionThread.html" title="class in org.apache.hadoop.hbase.io.hfile">LruBlockCache.EvictionThread</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.872">getEvictionThread</a>()</pre>
 </li>
 </ul>
 <a name="logStats--">
@@ -1743,7 +1743,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Resizable
 <ul class="blockList">
 <li class="blockList">
 <h4>logStats</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.948">logStats</a>()</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.953">logStats</a>()</pre>
 </li>
 </ul>
 <a name="getStats--">
@@ -1752,7 +1752,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Resizable
 <ul class="blockList">
 <li class="blockList">
 <h4>getStats</h4>
-<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/CacheStats.html" title="class in org.apache.hadoop.hbase.io.hfile">CacheStats</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.976">getStats</a>()</pre>
+<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/CacheStats.html" title="class in org.apache.hadoop.hbase.io.hfile">CacheStats</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.981">getStats</a>()</pre>
 <div class="block">Get counter statistics for this cache.
 
  <p>Includes: total accesses, hits, misses, evicted blocks, and runs
@@ -1771,7 +1771,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Resizable
 <ul class="blockList">
 <li class="blockList">
 <h4>heapSize</h4>
-<pre>public&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.986">heapSize</a>()</pre>
+<pre>public&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.991">heapSize</a>()</pre>
 <dl>
 <dt><span class="overrideSpecifyLabel">Specified by:</span></dt>
 <dd><code><a href="../../../../../../org/apache/hadoop/hbase/io/HeapSize.html#heapSize--">heapSize</a></code>&nbsp;in interface&nbsp;<code><a href="../../../../../../org/apache/hadoop/hbase/io/HeapSize.html" title="interface in org.apache.hadoop.hbase.io">HeapSize</a></code></dd>
@@ -1787,7 +1787,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Resizable
 <ul class="blockList">
 <li class="blockList">
 <h4>calculateOverhead</h4>
-<pre>private static&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.990">calculateOverhead</a>(long&nbsp;maxSize,
+<pre>private static&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.995">calculateOverhead</a>(long&nbsp;maxSize,
                                       long&nbsp;blockSize,
                                       int&nbsp;concurrency)</pre>
 </li>
@@ -1798,7 +1798,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Resizable
 <ul class="blockList">
 <li class="blockList">
 <h4>iterator</h4>
-<pre>public&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/Iterator.html?is-external=true" title="class or interface in java.util">Iterator</a>&lt;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/CachedBlock.html" title="interface in org.apache.hadoop.hbase.io.hfile">CachedBlock</a>&gt;&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.998">iterator</a>()</pre>
+<pre>public&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/Iterator.html?is-external=true" title="class or interface in java.util">Iterator</a>&lt;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/CachedBlock.html" title="interface in org.apache.hadoop.hbase.io.hfile">CachedBlock</a>&gt;&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.1003">iterator</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/Iterable.html?is-external=true#iterator--" title="class or interface in java.lang">iterator</a></code>&nbsp;in interface&nbsp;<code><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Iterable.html?is-external=true" title="class or interface in java.lang">Iterable</a>&lt;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/CachedBlock.html" title="interface in org.apache.hadoop.hbase.io.hfile">CachedBlock</a>&gt;</code></dd>
@@ -1815,7 +1815,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Resizable
 <ul class="blockList">
 <li class="blockList">
 <h4>acceptableSize</h4>
-<pre>long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.1086">acceptableSize</a>()</pre>
+<pre>long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.1091">acceptableSize</a>()</pre>
 </li>
 </ul>
 <a name="minSize--">
@@ -1824,7 +1824,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Resizable
 <ul class="blockList">
 <li class="blockList">
 <h4>minSize</h4>
-<pre>private&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.1089">minSize</a>()</pre>
+<pre>private&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.1094">minSize</a>()</pre>
 </li>
 </ul>
 <a name="singleSize--">
@@ -1833,7 +1833,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Resizable
 <ul class="blockList">
 <li class="blockList">
 <h4>singleSize</h4>
-<pre>private&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.1092">singleSize</a>()</pre>
+<pre>private&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.1097">singleSize</a>()</pre>
 </li>
 </ul>
 <a name="multiSize--">
@@ -1842,7 +1842,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Resizable
 <ul class="blockList">
 <li class="blockList">
 <h4>multiSize</h4>
-<pre>private&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.1095">multiSize</a>()</pre>
+<pre>private&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.1100">multiSize</a>()</pre>
 </li>
 </ul>
 <a name="memorySize--">
@@ -1851,7 +1851,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Resizable
 <ul class="blockList">
 <li class="blockList">
 <h4>memorySize</h4>
-<pre>private&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.1098">memorySize</a>()</pre>
+<pre>private&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.1103">memorySize</a>()</pre>
 </li>
 </ul>
 <a name="shutdown--">
@@ -1860,7 +1860,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Resizable
 <ul class="blockList">
 <li class="blockList">
 <h4>shutdown</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.1103">shutdown</a>()</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.1108">shutdown</a>()</pre>
 <div class="block"><span class="descfrmTypeLabel">Description copied from interface:&nbsp;<code><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCache.html#shutdown--">BlockCache</a></code></span></div>
 <div class="block">Shutdown the cache.</div>
 <dl>
@@ -1875,7 +1875,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Resizable
 <ul class="blockList">
 <li class="blockList">
 <h4>clearCache</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.1129">clearCache</a>()</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.1134">clearCache</a>()</pre>
 <div class="block">Clears the cache. Used in tests.</div>
 </li>
 </ul>
@@ -1885,7 +1885,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Resizable
 <ul class="blockList">
 <li class="blockList">
 <h4>getCachedFileNamesForTest</h4>
-<pre><a href="https://docs.oracle.com/javase/8/docs/api/java/util/SortedSet.html?is-external=true" title="class or interface in java.util">SortedSet</a>&lt;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&gt;&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.1140">getCachedFileNamesForTest</a>()</pre>
+<pre><a href="https://docs.oracle.com/javase/8/docs/api/java/util/SortedSet.html?is-external=true" title="class or interface in java.util">SortedSet</a>&lt;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&gt;&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.1145">getCachedFileNamesForTest</a>()</pre>
 <div class="block">Used in testing. May be very inefficient.</div>
 <dl>
 <dt><span class="returnLabel">Returns:</span></dt>
@@ -1899,7 +1899,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Resizable
 <ul class="blockList">
 <li class="blockList">
 <h4>getBlockTypeCountsForTest</h4>
-<pre><a href="https://docs.oracle.com/javase/8/docs/api/java/util/Map.html?is-external=true" title="class or interface in java.util">Map</a>&lt;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockType.html" title="enum in org.apache.hadoop.hbase.io.hfile">BlockType</a>,<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html?is-external=true" title="class or interface in java.lang">Integer</a>&gt;&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.1149">getBlockTypeCountsForTest</a>()</pre>
+<pre><a href="https://docs.oracle.com/javase/8/docs/api/java/util/Map.html?is-external=true" title="class or interface in java.util">Map</a>&lt;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockType.html" title="enum in org.apache.hadoop.hbase.io.hfile">BlockType</a>,<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html?is-external=true" title="class or interface in java.lang">Integer</a>&gt;&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.1154">getBlockTypeCountsForTest</a>()</pre>
 </li>
 </ul>
 <a name="getEncodingCountsForTest--">
@@ -1908,7 +1908,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Resizable
 <ul class="blockList">
 <li class="blockList">
 <h4>getEncodingCountsForTest</h4>
-<pre>public&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/Map.html?is-external=true" title="class or interface in java.util">Map</a>&lt;<a href="../../../../../../org/apache/hadoop/hbase/io/encoding/DataBlockEncoding.html" title="enum in org.apache.hadoop.hbase.io.encoding">DataBlockEncoding</a>,<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html?is-external=true" title="class or interface in java.lang">Integer</a>&gt;&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.1160">getEncodingCountsForTest</a>()</pre>
+<pre>public&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/Map.html?is-external=true" title="class or interface in java.util">Map</a>&lt;<a href="../../../../../../org/apache/hadoop/hbase/io/encoding/DataBlockEncoding.html" title="enum in org.apache.hadoop.hbase.io.encoding">DataBlockEncoding</a>,<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html?is-external=true" title="class or interface in java.lang">Integer</a>&gt;&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.1165">getEncodingCountsForTest</a>()</pre>
 </li>
 </ul>
 <a name="setVictimCache-org.apache.hadoop.hbase.io.hfile.BlockCache-">
@@ -1917,7 +1917,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Resizable
 <ul class="blockList">
 <li class="blockList">
 <h4>setVictimCache</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.1170">setVictimCache</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCache.html" title="interface in org.apache.hadoop.hbase.io.hfile">BlockCache</a>&nbsp;handler)</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.1175">setVictimCache</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCache.html" title="interface in org.apache.hadoop.hbase.io.hfile">BlockCache</a>&nbsp;handler)</pre>
 </li>
 </ul>
 <a name="getMapForTests--">
@@ -1926,7 +1926,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Resizable
 <ul class="blockList">
 <li class="blockList">
 <h4>getMapForTests</h4>
-<pre><a href="https://docs.oracle.com/javase/8/docs/api/java/util/Map.html?is-external=true" title="class or interface in java.util">Map</a>&lt;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a>,<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/LruCachedBlock.html" title="class in org.apache.hadoop.hbase.io.hfile">LruCachedBlock</a>&gt;&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.1176">getMapForTests</a>()</pre>
+<pre><a href="https://docs.oracle.com/javase/8/docs/api/java/util/Map.html?is-external=true" title="class or interface in java.util">Map</a>&lt;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a>,<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/LruCachedBlock.html" title="class in org.apache.hadoop.hbase.io.hfile">LruCachedBlock</a>&gt;&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.1181">getMapForTests</a>()</pre>
 </li>
 </ul>
 <a name="getBlockCaches--">
@@ -1935,7 +1935,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Resizable
 <ul class="blockListLast">
 <li class="blockList">
 <h4>getBlockCaches</h4>
-<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCache.html" title="interface in org.apache.hadoop.hbase.io.hfile">BlockCache</a>[]&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.1182">getBlockCaches</a>()</pre>
+<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCache.html" title="interface in org.apache.hadoop.hbase.io.hfile">BlockCache</a>[]&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.1187">getBlockCaches</a>()</pre>
 <dl>
 <dt><span class="overrideSpecifyLabel">Specified by:</span></dt>
 <dd><code><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCache.html#getBlockCaches--">getBlockCaches</a></code>&nbsp;in interface&nbsp;<code><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCache.html" title="interface in org.apache.hadoop.hbase.io.hfile">BlockCache</a></code></dd>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html b/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html
index b3c76d1..7e971fc 100644
--- a/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html
+++ b/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html
@@ -121,7 +121,7 @@ var activeTableTab = "activeTableTab";
 </dl>
 <hr>
 <br>
-<pre>static class <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1261">BucketCache.BucketEntry</a>
+<pre>static class <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1268">BucketCache.BucketEntry</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/io/Serializable.html?is-external=true" title="class or interface in java.io">Serializable</a></pre>
 <div class="block">Item in cache. We expect this to be where most memory goes. Java uses 8
@@ -304,7 +304,7 @@ implements <a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializab
 <ul class="blockList">
 <li class="blockList">
 <h4>serialVersionUID</h4>
-<pre>private static final&nbsp;long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html#line.1262">serialVersionUID</a></pre>
+<pre>private static final&nbsp;long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html#line.1269">serialVersionUID</a></pre>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
 <dd><a href="../../../../../../../constant-values.html#org.apache.hadoop.hbase.io.hfile.bucket.BucketCache.BucketEntry.serialVersionUID">Constant Field Values</a></dd>
@@ -317,7 +317,7 @@ implements <a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializab
 <ul class="blockList">
 <li class="blockList">
 <h4>COMPARATOR</h4>
-<pre>static final&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/Comparator.html?is-external=true" title="class or interface in java.util">Comparator</a>&lt;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketCache.BucketEntry</a>&gt; <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html#line.1265">COMPARATOR</a></pre>
+<pre>static final&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/Comparator.html?is-external=true" title="class or interface in java.util">Comparator</a>&lt;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketCache.BucketEntry</a>&gt; <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html#line.1272">COMPARATOR</a></pre>
 </li>
 </ul>
 <a name="offsetBase">
@@ -326,7 +326,7 @@ implements <a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializab
 <ul class="blockList">
 <li class="blockList">
 <h4>offsetBase</h4>
-<pre>private&nbsp;int <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html#line.1273">offsetBase</a></pre>
+<pre>private&nbsp;int <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html#line.1280">offsetBase</a></pre>
 </li>
 </ul>
 <a name="length">
@@ -335,7 +335,7 @@ implements <a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializab
 <ul class="blockList">
 <li class="blockList">
 <h4>length</h4>
-<pre>private&nbsp;int <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html#line.1274">length</a></pre>
+<pre>private&nbsp;int <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html#line.1281">length</a></pre>
 </li>
 </ul>
 <a name="offset1">
@@ -344,7 +344,7 @@ implements <a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializab
 <ul class="blockList">
 <li class="blockList">
 <h4>offset1</h4>
-<pre>private&nbsp;byte <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html#line.1275">offset1</a></pre>
+<pre>private&nbsp;byte <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html#line.1282">offset1</a></pre>
 </li>
 </ul>
 <a name="deserialiserIndex">
@@ -353,7 +353,7 @@ implements <a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializab
 <ul class="blockList">
 <li class="blockList">
 <h4>deserialiserIndex</h4>
-<pre>byte <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html#line.1276">deserialiserIndex</a></pre>
+<pre>byte <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html#line.1283">deserialiserIndex</a></pre>
 </li>
 </ul>
 <a name="accessCounter">
@@ -362,7 +362,7 @@ implements <a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializab
 <ul class="blockList">
 <li class="blockList">
 <h4>accessCounter</h4>
-<pre>private volatile&nbsp;long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html#line.1277">accessCounter</a></pre>
+<pre>private volatile&nbsp;long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html#line.1284">accessCounter</a></pre>
 </li>
 </ul>
 <a name="priority">
@@ -371,7 +371,7 @@ implements <a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializab
 <ul class="blockList">
 <li class="blockList">
 <h4>priority</h4>
-<pre>private&nbsp;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockPriority.html" title="enum in org.apache.hadoop.hbase.io.hfile">BlockPriority</a> <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html#line.1278">priority</a></pre>
+<pre>private&nbsp;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockPriority.html" title="enum in org.apache.hadoop.hbase.io.hfile">BlockPriority</a> <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html#line.1285">priority</a></pre>
 </li>
 </ul>
 <a name="cachedTime">
@@ -380,7 +380,7 @@ implements <a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializab
 <ul class="blockListLast">
 <li class="blockList">
 <h4>cachedTime</h4>
-<pre>private final&nbsp;long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html#line.1283">cachedTime</a></pre>
+<pre>private final&nbsp;long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html#line.1290">cachedTime</a></pre>
 <div class="block">Time this block was cached.  Presumes we are created just before we are added to the cache.</div>
 </li>
 </ul>
@@ -398,7 +398,7 @@ implements <a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializab
 <ul class="blockListLast">
 <li class="blockList">
 <h4>BucketEntry</h4>
-<pre><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html#line.1285">BucketEntry</a>(long&nbsp;offset,
+<pre><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html#line.1292">BucketEntry</a>(long&nbsp;offset,
             int&nbsp;length,
             long&nbsp;accessCounter,
             boolean&nbsp;inMemory)</pre>
@@ -418,7 +418,7 @@ implements <a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializab
 <ul class="blockList">
 <li class="blockList">
 <h4>offset</h4>
-<pre>long&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html#line.1296">offset</a>()</pre>
+<pre>long&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html#line.1303">offset</a>()</pre>
 </li>
 </ul>
 <a name="setOffset-long-">
@@ -427,7 +427,7 @@ implements <a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializab
 <ul class="blockList">
 <li class="blockList">
 <h4>setOffset</h4>
-<pre>private&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html#line.1302">setOffset</a>(long&nbsp;value)</pre>
+<pre>private&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html#line.1309">setOffset</a>(long&nbsp;value)</pre>
 </li>
 </ul>
 <a name="getLength--">
@@ -436,7 +436,7 @@ implements <a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializab
 <ul class="blockList">
 <li class="blockList">
 <h4>getLength</h4>
-<pre>public&nbsp;int&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html#line.1309">getLength</a>()</pre>
+<pre>public&nbsp;int&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html#line.1316">getLength</a>()</pre>
 </li>
 </ul>
 <a name="deserializerReference-org.apache.hadoop.hbase.io.hfile.bucket.UniqueIndexMap-">
@@ -445,7 +445,7 @@ implements <a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializab
 <ul class="blockList">
 <li class="blockList">
 <h4>deserializerReference</h4>
-<pre>protected&nbsp;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/CacheableDeserializer.html" title="interface in org.apache.hadoop.hbase.io.hfile">CacheableDeserializer</a>&lt;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html" title="interface in org.apache.hadoop.hbase.io.hfile">Cacheable</a>&gt;&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html#line.1313">deserializerReference</a>(<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/UniqueIndexMap.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">UniqueIndexMap</a>&lt;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html?is-external=true" title="class or interface in java.lang">Integer</a>&gt;&nbsp;deserialiserMap)</pre>
+<pre>protected&nbsp;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/CacheableDeserializer.html" title="interface in org.apache.hadoop.hbase.io.hfile">CacheableDeserializer</a>&lt;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html" title="interface in org.apache.hadoop.hbase.io.hfile">Cacheable</a>&gt;&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html#line.1320">deserializerReference</a>(<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/UniqueIndexMap.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">UniqueIndexMap</a>&lt;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html?is-external=true" title="class or interface in java.lang">Integer</a>&gt;&nbsp;deserialiserMap)</pre>
 </li>
 </ul>
 <a name="setDeserialiserReference-org.apache.hadoop.hbase.io.hfile.CacheableDeserializer-org.apache.hadoop.hbase.io.hfile.bucket.UniqueIndexMap-">
@@ -454,7 +454,7 @@ implements <a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializab
 <ul class="blockList">
 <li class="blockList">
 <h4>setDeserialiserReference</h4>
-<pre>protected&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html#line.1319">setDeserialiserReference</a>(<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/CacheableDeserializer.html" title="interface in org.apache.hadoop.hbase.io.hfile">CacheableDeserializer</a>&lt;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html" title="interface in org.apache.hadoop.hbase.io.hfile">Cacheable</a>&gt;&nbsp;deserializer,
+<pre>protected&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html#line.1326">setDeserialiserReference</a>(<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/CacheableDeserializer.html" title="interface in org.apache.hadoop.hbase.io.hfile">CacheableDeserializer</a>&lt;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html" title="interface in org.apache.hadoop.hbase.io.hfile">Cacheable</a>&gt;&nbsp;deserializer,
                                         <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/UniqueIndexMap.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">UniqueIndexMap</a>&lt;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html?is-external=true" title="class or interface in java.lang">Integer</a>&gt;&nbsp;deserialiserMap)</pre>
 </li>
 </ul>
@@ -464,7 +464,7 @@ implements <a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializab
 <ul class="blockList">
 <li class="blockList">
 <h4>access</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html#line.1329">access</a>(long&nbsp;accessCounter)</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html#line.1336">access</a>(long&nbsp;accessCounter)</pre>
 <div class="block">Block has been accessed. Update its local access counter.</div>
 </li>
 </ul>
@@ -474,7 +474,7 @@ implements <a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializab
 <ul class="blockList">
 <li class="blockList">
 <h4>getPriority</h4>
-<pre>public&nbsp;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockPriority.html" title="enum in org.apache.hadoop.hbase.io.hfile">BlockPriority</a>&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html#line.1336">getPriority</a>()</pre>
+<pre>public&nbsp;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockPriority.html" title="enum in org.apache.hadoop.hbase.io.hfile">BlockPriority</a>&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html#line.1343">getPriority</a>()</pre>
 </li>
 </ul>
 <a name="getCachedTime--">
@@ -483,7 +483,7 @@ implements <a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializab
 <ul class="blockList">
 <li class="blockList">
 <h4>getCachedTime</h4>
-<pre>public&nbsp;long&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html#line.1340">getCachedTime</a>()</pre>
+<pre>public&nbsp;long&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html#line.1347">getCachedTime</a>()</pre>
 </li>
 </ul>
 <a name="getRefCount--">
@@ -492,7 +492,7 @@ implements <a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializab
 <ul class="blockList">
 <li class="blockList">
 <h4>getRefCount</h4>
-<pre>protected&nbsp;int&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html#line.1344">getRefCount</a>()</pre>
+<pre>protected&nbsp;int&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html#line.1351">getRefCount</a>()</pre>
 </li>
 </ul>
 <a name="incrementRefCountAndGet--">
@@ -501,7 +501,7 @@ implements <a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializab
 <ul class="blockList">
 <li class="blockList">
 <h4>incrementRefCountAndGet</h4>
-<pre>protected&nbsp;int&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html#line.1348">incrementRefCountAndGet</a>()</pre>
+<pre>protected&nbsp;int&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html#line.1355">incrementRefCountAndGet</a>()</pre>
 </li>
 </ul>
 <a name="decrementRefCountAndGet--">
@@ -510,7 +510,7 @@ implements <a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializab
 <ul class="blockList">
 <li class="blockList">
 <h4>decrementRefCountAndGet</h4>
-<pre>protected&nbsp;int&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html#line.1352">decrementRefCountAndGet</a>()</pre>
+<pre>protected&nbsp;int&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html#line.1359">decrementRefCountAndGet</a>()</pre>
 </li>
 </ul>
 <a name="isMarkedForEvict--">
@@ -519,7 +519,7 @@ implements <a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializab
 <ul class="blockList">
 <li class="blockList">
 <h4>isMarkedForEvict</h4>
-<pre>protected&nbsp;boolean&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html#line.1356">isMarkedForEvict</a>()</pre>
+<pre>protected&nbsp;boolean&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html#line.1363">isMarkedForEvict</a>()</pre>
 </li>
 </ul>
 <a name="markForEvict--">
@@ -528,7 +528,7 @@ implements <a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializab
 <ul class="blockListLast">
 <li class="blockList">
 <h4>markForEvict</h4>
-<pre>protected&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html#line.1360">markForEvict</a>()</pre>
+<pre>protected&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html#line.1367">markForEvict</a>()</pre>
 </li>
 </ul>
 </li>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntryGroup.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntryGroup.html b/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntryGroup.html
index 7dcd9db..ff22089 100644
--- a/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntryGroup.html
+++ b/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntryGroup.html
@@ -113,7 +113,7 @@ var activeTableTab = "activeTableTab";
 </dl>
 <hr>
 <br>
-<pre>private class <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1408">BucketCache.BucketEntryGroup</a>
+<pre>private class <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1415">BucketCache.BucketEntryGroup</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">Used to group bucket entries into priority buckets. There will be a
  BucketEntryGroup for each priority (single, multi, memory). Once bucketed,
@@ -227,7 +227,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>queue</h4>
-<pre>private&nbsp;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/CachedEntryQueue.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">CachedEntryQueue</a> <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntryGroup.html#line.1410">queue</a></pre>
+<pre>private&nbsp;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/CachedEntryQueue.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">CachedEntryQueue</a> <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntryGroup.html#line.1417">queue</a></pre>
 </li>
 </ul>
 <a name="totalSize">
@@ -236,7 +236,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>totalSize</h4>
-<pre>private&nbsp;long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntryGroup.html#line.1411">totalSize</a></pre>
+<pre>private&nbsp;long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntryGroup.html#line.1418">totalSize</a></pre>
 </li>
 </ul>
 <a name="bucketSize">
@@ -245,7 +245,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>bucketSize</h4>
-<pre>private&nbsp;long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntryGroup.html#line.1412">bucketSize</a></pre>
+<pre>private&nbsp;long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntryGroup.html#line.1419">bucketSize</a></pre>
 </li>
 </ul>
 </li>
@@ -262,7 +262,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>BucketEntryGroup</h4>
-<pre>public&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntryGroup.html#line.1414">BucketEntryGroup</a>(long&nbsp;bytesToFree,
+<pre>public&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntryGroup.html#line.1421">BucketEntryGroup</a>(long&nbsp;bytesToFree,
                         long&nbsp;blockSize,
                         long&nbsp;bucketSize)</pre>
 </li>
@@ -281,7 +281,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>add</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntryGroup.html#line.1420">add</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/util/Map.Entry.html?is-external=true" title="class or interface in java.util">Map.Entry</a>&lt;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a>,<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketCache.BucketEntry</a>&gt;&nbsp;block)</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntryGroup.html#line.1427">add</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/util/Map.Entry.html?is-external=true" title="class or interface in java.util">Map.Entry</a>&lt;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a>,<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketCache.BucketEntry</a>&gt;&nbsp;block)</pre>
 </li>
 </ul>
 <a name="free-long-">
@@ -290,7 +290,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>free</h4>
-<pre>public&nbsp;long&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntryGroup.html#line.1425">free</a>(long&nbsp;toFree)</pre>
+<pre>public&nbsp;long&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntryGroup.html#line.1432">free</a>(long&nbsp;toFree)</pre>
 </li>
 </ul>
 <a name="overflow--">
@@ -299,7 +299,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>overflow</h4>
-<pre>public&nbsp;long&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntryGroup.html#line.1441">overflow</a>()</pre>
+<pre>public&nbsp;long&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntryGroup.html#line.1448">overflow</a>()</pre>
 </li>
 </ul>
 <a name="totalSize--">
@@ -308,7 +308,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>totalSize</h4>
-<pre>public&nbsp;long&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntryGroup.html#line.1445">totalSize</a>()</pre>
+<pre>public&nbsp;long&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntryGroup.html#line.1452">totalSize</a>()</pre>
 </li>
 </ul>
 </li>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html b/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html
index 35484b0..f272ea1 100644
--- a/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html
+++ b/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html
@@ -113,7 +113,7 @@ var activeTableTab = "activeTableTab";
 </dl>
 <hr>
 <br>
-<pre>static class <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1454">BucketCache.RAMQueueEntry</a>
+<pre>static class <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1461">BucketCache.RAMQueueEntry</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">Block Entry stored in the memory with key,data and so on</div>
 </li>
@@ -232,7 +232,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>key</h4>
-<pre>private&nbsp;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a> <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html#line.1455">key</a></pre>
+<pre>private&nbsp;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a> <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html#line.1462">key</a></pre>
 </li>
 </ul>
 <a name="data">
@@ -241,7 +241,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>data</h4>
-<pre>private&nbsp;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html" title="interface in org.apache.hadoop.hbase.io.hfile">Cacheable</a> <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html#line.1456">data</a></pre>
+<pre>private&nbsp;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html" title="interface in org.apache.hadoop.hbase.io.hfile">Cacheable</a> <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html#line.1463">data</a></pre>
 </li>
 </ul>
 <a name="accessCounter">
@@ -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>accessCounter</h4>
-<pre>private&nbsp;long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html#line.1457">accessCounter</a></pre>
+<pre>private&nbsp;long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html#line.1464">accessCounter</a></pre>
 </li>
 </ul>
 <a name="inMemory">
@@ -259,7 +259,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>inMemory</h4>
-<pre>private&nbsp;boolean <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html#line.1458">inMemory</a></pre>
+<pre>private&nbsp;boolean <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html#line.1465">inMemory</a></pre>
 </li>
 </ul>
 </li>
@@ -276,7 +276,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>RAMQueueEntry</h4>
-<pre>public&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html#line.1460">RAMQueueEntry</a>(<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a>&nbsp;bck,
+<pre>public&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html#line.1467">RAMQueueEntry</a>(<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a>&nbsp;bck,
                      <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html" title="interface in org.apache.hadoop.hbase.io.hfile">Cacheable</a>&nbsp;data,
                      long&nbsp;accessCounter,
                      boolean&nbsp;inMemory)</pre>
@@ -296,7 +296,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getData</h4>
-<pre>public&nbsp;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html" title="interface in org.apache.hadoop.hbase.io.hfile">Cacheable</a>&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html#line.1468">getData</a>()</pre>
+<pre>public&nbsp;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html" title="interface in org.apache.hadoop.hbase.io.hfile">Cacheable</a>&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html#line.1475">getData</a>()</pre>
 </li>
 </ul>
 <a name="getKey--">
@@ -305,7 +305,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getKey</h4>
-<pre>public&nbsp;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a>&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html#line.1472">getKey</a>()</pre>
+<pre>public&nbsp;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a>&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html#line.1479">getKey</a>()</pre>
 </li>
 </ul>
 <a name="access-long-">
@@ -314,7 +314,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>access</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html#line.1476">access</a>(long&nbsp;accessCounter)</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html#line.1483">access</a>(long&nbsp;accessCounter)</pre>
 </li>
 </ul>
 <a name="writeToCache-org.apache.hadoop.hbase.io.hfile.bucket.IOEngine-org.apache.hadoop.hbase.io.hfile.bucket.BucketAllocator-org.apache.hadoop.hbase.io.hfile.bucket.UniqueIndexMap-java.util.concurrent.atomic.LongAdder-">
@@ -323,7 +323,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>writeToCache</h4>
-<pre>public&nbsp;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketCache.BucketEntry</a>&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html#line.1480">writeToCache</a>(<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/IOEngine.html" title="interface in org.apache.hadoop.hbase.io.hfile.bucket">IOEngine</a>&nbsp;ioEngine,
+<pre>public&nbsp;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketCache.BucketEntry</a>&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html#line.1487">writeToCache</a>(<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/IOEngine.html" title="interface in org.apache.hadoop.hbase.io.hfile.bucket">IOEngine</a>&nbsp;ioEngine,
                                             <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketAllocator</a>&nbsp;bucketAllocator,
                                             <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/UniqueIndexMap.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">UniqueIndexMap</a>&lt;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html?is-external=true" title="class or interface in java.lang">Integer</a>&gt;&nbsp;deserialiserMap,
                                             <a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/LongAdder.html?is-external=true" title="class or interface in java.util.concurrent.atomic">LongAdder</a>&nbsp;realCacheSize)

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.SharedMemoryBucketEntry.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.SharedMemoryBucketEntry.html b/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.SharedMemoryBucketEntry.html
index 55d623b..2e0f11c 100644
--- a/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.SharedMemoryBucketEntry.html
+++ b/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.SharedMemoryBucketEntry.html
@@ -122,7 +122,7 @@ var activeTableTab = "activeTableTab";
 </dl>
 <hr>
 <br>
-<pre>static class <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1365">BucketCache.SharedMemoryBucketEntry</a>
+<pre>static class <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1372">BucketCache.SharedMemoryBucketEntry</a>
 extends <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketCache.BucketEntry</a></pre>
 </li>
 </ul>
@@ -251,7 +251,7 @@ extends <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/Bu
 <ul class="blockList">
 <li class="blockList">
 <h4>serialVersionUID</h4>
-<pre>private static final&nbsp;long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.SharedMemoryBucketEntry.html#line.1366">serialVersionUID</a></pre>
+<pre>private static final&nbsp;long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.SharedMemoryBucketEntry.html#line.1373">serialVersionUID</a></pre>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
 <dd><a href="../../../../../../../constant-values.html#org.apache.hadoop.hbase.io.hfile.bucket.BucketCache.SharedMemoryBucketEntry.serialVersionUID">Constant Field Values</a></dd>
@@ -264,7 +264,7 @@ extends <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/Bu
 <ul class="blockList">
 <li class="blockList">
 <h4>markedForEvict</h4>
-<pre>private volatile&nbsp;boolean <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.SharedMemoryBucketEntry.html#line.1369">markedForEvict</a></pre>
+<pre>private volatile&nbsp;boolean <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.SharedMemoryBucketEntry.html#line.1376">markedForEvict</a></pre>
 </li>
 </ul>
 <a name="refCount">
@@ -273,7 +273,7 @@ extends <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/Bu
 <ul class="blockListLast">
 <li class="blockList">
 <h4>refCount</h4>
-<pre>private&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/AtomicInteger.html?is-external=true" title="class or interface in java.util.concurrent.atomic">AtomicInteger</a> <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.SharedMemoryBucketEntry.html#line.1370">refCount</a></pre>
+<pre>private&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/AtomicInteger.html?is-external=true" title="class or interface in java.util.concurrent.atomic">AtomicInteger</a> <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.SharedMemoryBucketEntry.html#line.1377">refCount</a></pre>
 </li>
 </ul>
 </li>
@@ -290,7 +290,7 @@ extends <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/Bu
 <ul class="blockListLast">
 <li class="blockList">
 <h4>SharedMemoryBucketEntry</h4>
-<pre><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.SharedMemoryBucketEntry.html#line.1372">SharedMemoryBucketEntry</a>(long&nbsp;offset,
+<pre><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.SharedMemoryBucketEntry.html#line.1379">SharedMemoryBucketEntry</a>(long&nbsp;offset,
                         int&nbsp;length,
                         long&nbsp;accessCounter,
                         boolean&nbsp;inMemory)</pre>
@@ -310,7 +310,7 @@ extends <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/Bu
 <ul class="blockList">
 <li class="blockList">
 <h4>getRefCount</h4>
-<pre>protected&nbsp;int&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.SharedMemoryBucketEntry.html#line.1377">getRefCount</a>()</pre>
+<pre>protected&nbsp;int&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.SharedMemoryBucketEntry.html#line.1384">getRefCount</a>()</pre>
 <dl>
 <dt><span class="overrideSpecifyLabel">Overrides:</span></dt>
 <dd><code><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html#getRefCount--">getRefCount</a></code>&nbsp;in class&nbsp;<code><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketCache.BucketEntry</a></code></dd>
@@ -323,7 +323,7 @@ extends <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/Bu
 <ul class="blockList">
 <li class="blockList">
 <h4>incrementRefCountAndGet</h4>
-<pre>protected&nbsp;int&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.SharedMemoryBucketEntry.html#line.1382">incrementRefCountAndGet</a>()</pre>
+<pre>protected&nbsp;int&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.SharedMemoryBucketEntry.html#line.1389">incrementRefCountAndGet</a>()</pre>
 <dl>
 <dt><span class="overrideSpecifyLabel">Overrides:</span></dt>
 <dd><code><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html#incrementRefCountAndGet--">incrementRefCountAndGet</a></code>&nbsp;in class&nbsp;<code><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketCache.BucketEntry</a></code></dd>
@@ -336,7 +336,7 @@ extends <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/Bu
 <ul class="blockList">
 <li class="blockList">
 <h4>decrementRefCountAndGet</h4>
-<pre>protected&nbsp;int&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.SharedMemoryBucketEntry.html#line.1387">decrementRefCountAndGet</a>()</pre>
+<pre>protected&nbsp;int&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.SharedMemoryBucketEntry.html#line.1394">decrementRefCountAndGet</a>()</pre>
 <dl>
 <dt><span class="overrideSpecifyLabel">Overrides:</span></dt>
 <dd><code><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html#decrementRefCountAndGet--">decrementRefCountAndGet</a></code>&nbsp;in class&nbsp;<code><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketCache.BucketEntry</a></code></dd>
@@ -349,7 +349,7 @@ extends <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/Bu
 <ul class="blockList">
 <li class="blockList">
 <h4>isMarkedForEvict</h4>
-<pre>protected&nbsp;boolean&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.SharedMemoryBucketEntry.html#line.1392">isMarkedForEvict</a>()</pre>
+<pre>protected&nbsp;boolean&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.SharedMemoryBucketEntry.html#line.1399">isMarkedForEvict</a>()</pre>
 <dl>
 <dt><span class="overrideSpecifyLabel">Overrides:</span></dt>
 <dd><code><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html#isMarkedForEvict--">isMarkedForEvict</a></code>&nbsp;in class&nbsp;<code><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketCache.BucketEntry</a></code></dd>
@@ -362,7 +362,7 @@ extends <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/Bu
 <ul class="blockListLast">
 <li class="blockList">
 <h4>markForEvict</h4>
-<pre>protected&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.SharedMemoryBucketEntry.html#line.1397">markForEvict</a>()</pre>
+<pre>protected&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.SharedMemoryBucketEntry.html#line.1404">markForEvict</a>()</pre>
 <dl>
 <dt><span class="overrideSpecifyLabel">Overrides:</span></dt>
 <dd><code><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html#markForEvict--">markForEvict</a></code>&nbsp;in class&nbsp;<code><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketCache.BucketEntry</a></code></dd>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.StatisticsThread.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.StatisticsThread.html b/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.StatisticsThread.html
index 896f6bb..c4d7746 100644
--- a/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.StatisticsThread.html
+++ b/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.StatisticsThread.html
@@ -122,7 +122,7 @@ var activeTableTab = "activeTableTab";
 </dl>
 <hr>
 <br>
-<pre>private static class <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.647">BucketCache.StatisticsThread</a>
+<pre>private static class <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.654">BucketCache.StatisticsThread</a>
 extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html?is-external=true" title="class or interface in java.lang">Thread</a></pre>
 </li>
 </ul>
@@ -239,7 +239,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>bucketCache</h4>
-<pre>private final&nbsp;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketCache</a> <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.StatisticsThread.html#line.648">bucketCache</a></pre>
+<pre>private final&nbsp;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketCache</a> <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.StatisticsThread.html#line.655">bucketCache</a></pre>
 </li>
 </ul>
 </li>
@@ -256,7 +256,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>StatisticsThread</h4>
-<pre>public&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.StatisticsThread.html#line.650">StatisticsThread</a>(<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketCache</a>&nbsp;bucketCache)</pre>
+<pre>public&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.StatisticsThread.html#line.657">StatisticsThread</a>(<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketCache</a>&nbsp;bucketCache)</pre>
 </li>
 </ul>
 </li>
@@ -273,7 +273,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>run</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.StatisticsThread.html#line.657">run</a>()</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.StatisticsThread.html#line.664">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>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.WriterThread.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.WriterThread.html b/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.WriterThread.html
index c9a62cb..568bd54 100644
--- a/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.WriterThread.html
+++ b/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.WriterThread.html
@@ -122,7 +122,7 @@ var activeTableTab = "activeTableTab";
 </dl>
 <hr>
 <br>
-<pre>class <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.894">BucketCache.WriterThread</a>
+<pre>class <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.901">BucketCache.WriterThread</a>
 extends <a href="../../../../../../../org/apache/hadoop/hbase/util/HasThread.html" title="class in org.apache.hadoop.hbase.util">HasThread</a></pre>
 </li>
 </ul>
@@ -231,7 +231,7 @@ extends <a href="../../../../../../../org/apache/hadoop/hbase/util/HasThread.htm
 <ul class="blockList">
 <li class="blockList">
 <h4>inputQueue</h4>
-<pre>private final&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/BlockingQueue.html?is-external=true" title="class or interface in java.util.concurrent">BlockingQueue</a>&lt;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketCache.RAMQueueEntry</a>&gt; <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.WriterThread.html#line.895">inputQueue</a></pre>
+<pre>private final&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/BlockingQueue.html?is-external=true" title="class or interface in java.util.concurrent">BlockingQueue</a>&lt;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketCache.RAMQueueEntry</a>&gt; <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.WriterThread.html#line.902">inputQueue</a></pre>
 </li>
 </ul>
 <a name="writerEnabled">
@@ -240,7 +240,7 @@ extends <a href="../../../../../../../org/apache/hadoop/hbase/util/HasThread.htm
 <ul class="blockListLast">
 <li class="blockList">
 <h4>writerEnabled</h4>
-<pre>private volatile&nbsp;boolean <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.WriterThread.html#line.896">writerEnabled</a></pre>
+<pre>private volatile&nbsp;boolean <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.WriterThread.html#line.903">writerEnabled</a></pre>
 </li>
 </ul>
 </li>
@@ -257,7 +257,7 @@ extends <a href="../../../../../../../org/apache/hadoop/hbase/util/HasThread.htm
 <ul class="blockListLast">
 <li class="blockList">
 <h4>WriterThread</h4>
-<pre><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.WriterThread.html#line.898">WriterThread</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/BlockingQueue.html?is-external=true" title="class or interface in java.util.concurrent">BlockingQueue</a>&lt;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketCache.RAMQueueEntry</a>&gt;&nbsp;queue)</pre>
+<pre><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.WriterThread.html#line.905">WriterThread</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/BlockingQueue.html?is-external=true" title="class or interface in java.util.concurrent">BlockingQueue</a>&lt;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketCache.RAMQueueEntry</a>&gt;&nbsp;queue)</pre>
 </li>
 </ul>
 </li>
@@ -274,7 +274,7 @@ extends <a href="../../../../../../../org/apache/hadoop/hbase/util/HasThread.htm
 <ul class="blockList">
 <li class="blockList">
 <h4>disableWriter</h4>
-<pre>void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.WriterThread.html#line.905">disableWriter</a>()</pre>
+<pre>void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.WriterThread.html#line.912">disableWriter</a>()</pre>
 </li>
 </ul>
 <a name="run--">
@@ -283,7 +283,7 @@ extends <a href="../../../../../../../org/apache/hadoop/hbase/util/HasThread.htm
 <ul class="blockList">
 <li class="blockList">
 <h4>run</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.WriterThread.html#line.910">run</a>()</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.WriterThread.html#line.917">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>
@@ -298,7 +298,7 @@ extends <a href="../../../../../../../org/apache/hadoop/hbase/util/HasThread.htm
 <ul class="blockListLast">
 <li class="blockList">
 <h4>doDrain</h4>
-<pre>void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.WriterThread.html#line.941">doDrain</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html?is-external=true" title="class or interface in java.util">List</a>&lt;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketCache.RAMQueueEntry</a>&gt;&nbsp;entries)
+<pre>void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.WriterThread.html#line.948">doDrain</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html?is-external=true" title="class or interface in java.util">List</a>&lt;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketCache.RAMQueueEntry</a>&gt;&nbsp;entries)
       throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/InterruptedException.html?is-external=true" title="class or interface in java.lang">InterruptedException</a></pre>
 <div class="block">Flush the entries in ramCache to IOEngine and add bucket entry to backingMap.
  Process all that are passed in even if failure being sure to remove from ramCache else we'll


[37/50] hbase-site git commit: Published site at 26babcf013de696b899d76a3c39434b794440d8d.

Posted by gi...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReader.html
----------------------------------------------------------------------
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReader.html b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReader.html
index 97ceefd..b7b4236 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReader.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReader.html
@@ -103,8 +103,8 @@
 <span class="sourceLineNo">095</span> * Caches cache whole blocks with trailing checksums if any. We then tag on some metadata, the<a name="line.95"></a>
 <span class="sourceLineNo">096</span> * content of BLOCK_METADATA_SPACE which will be flag on if we are doing 'hbase'<a name="line.96"></a>
 <span class="sourceLineNo">097</span> * checksums and then the offset into the file which is needed when we re-make a cache key<a name="line.97"></a>
-<span class="sourceLineNo">098</span> * when we return the block to the cache as 'done'. See {@link Cacheable#serialize(ByteBuffer)} and<a name="line.98"></a>
-<span class="sourceLineNo">099</span> * {@link Cacheable#getDeserializer()}.<a name="line.99"></a>
+<span class="sourceLineNo">098</span> * when we return the block to the cache as 'done'.<a name="line.98"></a>
+<span class="sourceLineNo">099</span> * See {@link Cacheable#serialize(ByteBuffer, boolean)} and {@link Cacheable#getDeserializer()}.<a name="line.99"></a>
 <span class="sourceLineNo">100</span> *<a name="line.100"></a>
 <span class="sourceLineNo">101</span> * &lt;p&gt;TODO: Should we cache the checksums? Down in Writer#getBlockForCaching(CacheConfig) where<a name="line.101"></a>
 <span class="sourceLineNo">102</span> * we make a block to cache-on-write, there is an attempt at turning off checksums. This is not the<a name="line.102"></a>
@@ -333,1579 +333,1579 @@
 <span class="sourceLineNo">325</span>   * Creates a new {@link HFile} block from the given fields. This constructor<a name="line.325"></a>
 <span class="sourceLineNo">326</span>   * is used only while writing blocks and caching,<a name="line.326"></a>
 <span class="sourceLineNo">327</span>   * and is sitting in a byte buffer and we want to stuff the block into cache.<a name="line.327"></a>
-<span class="sourceLineNo">328</span>   * See {@link Writer#getBlockForCaching(CacheConfig)}.<a name="line.328"></a>
-<span class="sourceLineNo">329</span>   *<a name="line.329"></a>
-<span class="sourceLineNo">330</span>   * &lt;p&gt;TODO: The caller presumes no checksumming<a name="line.330"></a>
-<span class="sourceLineNo">331</span>   * required of this block instance since going into cache; checksum already verified on<a name="line.331"></a>
-<span class="sourceLineNo">332</span>   * underlying block data pulled in from filesystem. Is that correct? What if cache is SSD?<a name="line.332"></a>
-<span class="sourceLineNo">333</span>   *<a name="line.333"></a>
-<span class="sourceLineNo">334</span>   * @param blockType the type of this block, see {@link BlockType}<a name="line.334"></a>
-<span class="sourceLineNo">335</span>   * @param onDiskSizeWithoutHeader see {@link #onDiskSizeWithoutHeader}<a name="line.335"></a>
-<span class="sourceLineNo">336</span>   * @param uncompressedSizeWithoutHeader see {@link #uncompressedSizeWithoutHeader}<a name="line.336"></a>
-<span class="sourceLineNo">337</span>   * @param prevBlockOffset see {@link #prevBlockOffset}<a name="line.337"></a>
-<span class="sourceLineNo">338</span>   * @param b block header ({@link HConstants#HFILEBLOCK_HEADER_SIZE} bytes)<a name="line.338"></a>
-<span class="sourceLineNo">339</span>   * @param fillHeader when true, write the first 4 header fields into passed buffer.<a name="line.339"></a>
-<span class="sourceLineNo">340</span>   * @param offset the file offset the block was read from<a name="line.340"></a>
-<span class="sourceLineNo">341</span>   * @param onDiskDataSizeWithHeader see {@link #onDiskDataSizeWithHeader}<a name="line.341"></a>
-<span class="sourceLineNo">342</span>   * @param fileContext HFile meta data<a name="line.342"></a>
-<span class="sourceLineNo">343</span>   */<a name="line.343"></a>
-<span class="sourceLineNo">344</span>  HFileBlock(BlockType blockType, int onDiskSizeWithoutHeader, int uncompressedSizeWithoutHeader,<a name="line.344"></a>
-<span class="sourceLineNo">345</span>      long prevBlockOffset, ByteBuffer b, boolean fillHeader, long offset,<a name="line.345"></a>
-<span class="sourceLineNo">346</span>      final int nextBlockOnDiskSize, int onDiskDataSizeWithHeader, HFileContext fileContext) {<a name="line.346"></a>
-<span class="sourceLineNo">347</span>    init(blockType, onDiskSizeWithoutHeader, uncompressedSizeWithoutHeader,<a name="line.347"></a>
-<span class="sourceLineNo">348</span>        prevBlockOffset, offset, onDiskDataSizeWithHeader, nextBlockOnDiskSize, fileContext);<a name="line.348"></a>
-<span class="sourceLineNo">349</span>    this.buf = new SingleByteBuff(b);<a name="line.349"></a>
-<span class="sourceLineNo">350</span>    if (fillHeader) {<a name="line.350"></a>
-<span class="sourceLineNo">351</span>      overwriteHeader();<a name="line.351"></a>
-<span class="sourceLineNo">352</span>    }<a name="line.352"></a>
-<span class="sourceLineNo">353</span>    this.buf.rewind();<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>  /**<a name="line.356"></a>
-<span class="sourceLineNo">357</span>   * Creates a block from an existing buffer starting with a header. Rewinds<a name="line.357"></a>
-<span class="sourceLineNo">358</span>   * and takes ownership of the buffer. By definition of rewind, ignores the<a name="line.358"></a>
-<span class="sourceLineNo">359</span>   * buffer position, but if you slice the buffer beforehand, it will rewind<a name="line.359"></a>
-<span class="sourceLineNo">360</span>   * to that point.<a name="line.360"></a>
-<span class="sourceLineNo">361</span>   * @param buf Has header, content, and trailing checksums if present.<a name="line.361"></a>
-<span class="sourceLineNo">362</span>   */<a name="line.362"></a>
-<span class="sourceLineNo">363</span>  HFileBlock(ByteBuff buf, boolean usesHBaseChecksum, MemoryType memType, final long offset,<a name="line.363"></a>
-<span class="sourceLineNo">364</span>      final int nextBlockOnDiskSize, HFileContext fileContext) throws IOException {<a name="line.364"></a>
-<span class="sourceLineNo">365</span>    buf.rewind();<a name="line.365"></a>
-<span class="sourceLineNo">366</span>    final BlockType blockType = BlockType.read(buf);<a name="line.366"></a>
-<span class="sourceLineNo">367</span>    final int onDiskSizeWithoutHeader = buf.getInt(Header.ON_DISK_SIZE_WITHOUT_HEADER_INDEX);<a name="line.367"></a>
-<span class="sourceLineNo">368</span>    final int uncompressedSizeWithoutHeader =<a name="line.368"></a>
-<span class="sourceLineNo">369</span>        buf.getInt(Header.UNCOMPRESSED_SIZE_WITHOUT_HEADER_INDEX);<a name="line.369"></a>
-<span class="sourceLineNo">370</span>    final long prevBlockOffset = buf.getLong(Header.PREV_BLOCK_OFFSET_INDEX);<a name="line.370"></a>
-<span class="sourceLineNo">371</span>    // This constructor is called when we deserialize a block from cache and when we read a block in<a name="line.371"></a>
-<span class="sourceLineNo">372</span>    // from the fs. fileCache is null when deserialized from cache so need to make up one.<a name="line.372"></a>
-<span class="sourceLineNo">373</span>    HFileContextBuilder fileContextBuilder = fileContext != null?<a name="line.373"></a>
-<span class="sourceLineNo">374</span>        new HFileContextBuilder(fileContext): new HFileContextBuilder();<a name="line.374"></a>
-<span class="sourceLineNo">375</span>    fileContextBuilder.withHBaseCheckSum(usesHBaseChecksum);<a name="line.375"></a>
-<span class="sourceLineNo">376</span>    int onDiskDataSizeWithHeader;<a name="line.376"></a>
-<span class="sourceLineNo">377</span>    if (usesHBaseChecksum) {<a name="line.377"></a>
-<span class="sourceLineNo">378</span>      byte checksumType = buf.get(Header.CHECKSUM_TYPE_INDEX);<a name="line.378"></a>
-<span class="sourceLineNo">379</span>      int bytesPerChecksum = buf.getInt(Header.BYTES_PER_CHECKSUM_INDEX);<a name="line.379"></a>
-<span class="sourceLineNo">380</span>      onDiskDataSizeWithHeader = buf.getInt(Header.ON_DISK_DATA_SIZE_WITH_HEADER_INDEX);<a name="line.380"></a>
-<span class="sourceLineNo">381</span>      // Use the checksum type and bytes per checksum from header, not from filecontext.<a name="line.381"></a>
-<span class="sourceLineNo">382</span>      fileContextBuilder.withChecksumType(ChecksumType.codeToType(checksumType));<a name="line.382"></a>
-<span class="sourceLineNo">383</span>      fileContextBuilder.withBytesPerCheckSum(bytesPerChecksum);<a name="line.383"></a>
-<span class="sourceLineNo">384</span>    } else {<a name="line.384"></a>
-<span class="sourceLineNo">385</span>      fileContextBuilder.withChecksumType(ChecksumType.NULL);<a name="line.385"></a>
-<span class="sourceLineNo">386</span>      fileContextBuilder.withBytesPerCheckSum(0);<a name="line.386"></a>
-<span class="sourceLineNo">387</span>      // Need to fix onDiskDataSizeWithHeader; there are not checksums after-block-data<a name="line.387"></a>
-<span class="sourceLineNo">388</span>      onDiskDataSizeWithHeader = onDiskSizeWithoutHeader + headerSize(usesHBaseChecksum);<a name="line.388"></a>
-<span class="sourceLineNo">389</span>    }<a name="line.389"></a>
-<span class="sourceLineNo">390</span>    fileContext = fileContextBuilder.build();<a name="line.390"></a>
-<span class="sourceLineNo">391</span>    assert usesHBaseChecksum == fileContext.isUseHBaseChecksum();<a name="line.391"></a>
-<span class="sourceLineNo">392</span>    init(blockType, onDiskSizeWithoutHeader, uncompressedSizeWithoutHeader,<a name="line.392"></a>
-<span class="sourceLineNo">393</span>        prevBlockOffset, offset, onDiskDataSizeWithHeader, nextBlockOnDiskSize, fileContext);<a name="line.393"></a>
-<span class="sourceLineNo">394</span>    this.memType = memType;<a name="line.394"></a>
-<span class="sourceLineNo">395</span>    this.offset = offset;<a name="line.395"></a>
-<span class="sourceLineNo">396</span>    this.buf = buf;<a name="line.396"></a>
-<span class="sourceLineNo">397</span>    this.buf.rewind();<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>  /**<a name="line.400"></a>
-<span class="sourceLineNo">401</span>   * Called from constructors.<a name="line.401"></a>
-<span class="sourceLineNo">402</span>   */<a name="line.402"></a>
-<span class="sourceLineNo">403</span>  private void init(BlockType blockType, int onDiskSizeWithoutHeader,<a name="line.403"></a>
-<span class="sourceLineNo">404</span>      int uncompressedSizeWithoutHeader, long prevBlockOffset,<a name="line.404"></a>
-<span class="sourceLineNo">405</span>      long offset, int onDiskDataSizeWithHeader, final int nextBlockOnDiskSize,<a name="line.405"></a>
-<span class="sourceLineNo">406</span>      HFileContext fileContext) {<a name="line.406"></a>
-<span class="sourceLineNo">407</span>    this.blockType = blockType;<a name="line.407"></a>
-<span class="sourceLineNo">408</span>    this.onDiskSizeWithoutHeader = onDiskSizeWithoutHeader;<a name="line.408"></a>
-<span class="sourceLineNo">409</span>    this.uncompressedSizeWithoutHeader = uncompressedSizeWithoutHeader;<a name="line.409"></a>
-<span class="sourceLineNo">410</span>    this.prevBlockOffset = prevBlockOffset;<a name="line.410"></a>
-<span class="sourceLineNo">411</span>    this.offset = offset;<a name="line.411"></a>
-<span class="sourceLineNo">412</span>    this.onDiskDataSizeWithHeader = onDiskDataSizeWithHeader;<a name="line.412"></a>
-<span class="sourceLineNo">413</span>    this.nextBlockOnDiskSize = nextBlockOnDiskSize;<a name="line.413"></a>
-<span class="sourceLineNo">414</span>    this.fileContext = fileContext;<a name="line.414"></a>
-<span class="sourceLineNo">415</span>  }<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">418</span>   * Parse total on disk size including header and checksum.<a name="line.418"></a>
-<span class="sourceLineNo">419</span>   * @param headerBuf Header ByteBuffer. Presumed exact size of header.<a name="line.419"></a>
-<span class="sourceLineNo">420</span>   * @param verifyChecksum true if checksum verification is in use.<a name="line.420"></a>
-<span class="sourceLineNo">421</span>   * @return Size of the block with header included.<a name="line.421"></a>
-<span class="sourceLineNo">422</span>   */<a name="line.422"></a>
-<span class="sourceLineNo">423</span>  private static int getOnDiskSizeWithHeader(final ByteBuffer headerBuf,<a name="line.423"></a>
-<span class="sourceLineNo">424</span>      boolean verifyChecksum) {<a name="line.424"></a>
-<span class="sourceLineNo">425</span>    return headerBuf.getInt(Header.ON_DISK_SIZE_WITHOUT_HEADER_INDEX) +<a name="line.425"></a>
-<span class="sourceLineNo">426</span>      headerSize(verifyChecksum);<a name="line.426"></a>
-<span class="sourceLineNo">427</span>  }<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>   * @return the on-disk size of the next block (including the header size and any checksums if<a name="line.430"></a>
-<span class="sourceLineNo">431</span>   * present) read by peeking into the next block's header; use as a hint when doing<a name="line.431"></a>
-<span class="sourceLineNo">432</span>   * a read of the next block when scanning or running over a file.<a name="line.432"></a>
-<span class="sourceLineNo">433</span>   */<a name="line.433"></a>
-<span class="sourceLineNo">434</span>  int getNextBlockOnDiskSize() {<a name="line.434"></a>
-<span class="sourceLineNo">435</span>    return nextBlockOnDiskSize;<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>  @Override<a name="line.438"></a>
-<span class="sourceLineNo">439</span>  public BlockType getBlockType() {<a name="line.439"></a>
-<span class="sourceLineNo">440</span>    return blockType;<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>  /** @return get data block encoding id that was used to encode this block */<a name="line.443"></a>
-<span class="sourceLineNo">444</span>  short getDataBlockEncodingId() {<a name="line.444"></a>
-<span class="sourceLineNo">445</span>    if (blockType != BlockType.ENCODED_DATA) {<a name="line.445"></a>
-<span class="sourceLineNo">446</span>      throw new IllegalArgumentException("Querying encoder ID of a block " +<a name="line.446"></a>
-<span class="sourceLineNo">447</span>          "of type other than " + BlockType.ENCODED_DATA + ": " + blockType);<a name="line.447"></a>
-<span class="sourceLineNo">448</span>    }<a name="line.448"></a>
-<span class="sourceLineNo">449</span>    return buf.getShort(headerSize());<a name="line.449"></a>
-<span class="sourceLineNo">450</span>  }<a name="line.450"></a>
-<span class="sourceLineNo">451</span><a name="line.451"></a>
-<span class="sourceLineNo">452</span>  /**<a name="line.452"></a>
-<span class="sourceLineNo">453</span>   * @return the on-disk size of header + data part + checksum.<a name="line.453"></a>
-<span class="sourceLineNo">454</span>   */<a name="line.454"></a>
-<span class="sourceLineNo">455</span>  public int getOnDiskSizeWithHeader() {<a name="line.455"></a>
-<span class="sourceLineNo">456</span>    return onDiskSizeWithoutHeader + headerSize();<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>   * @return the on-disk size of the data part + checksum (header excluded).<a name="line.460"></a>
-<span class="sourceLineNo">461</span>   */<a name="line.461"></a>
-<span class="sourceLineNo">462</span>  int getOnDiskSizeWithoutHeader() {<a name="line.462"></a>
-<span class="sourceLineNo">463</span>    return onDiskSizeWithoutHeader;<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>  /**<a name="line.466"></a>
-<span class="sourceLineNo">467</span>   * @return the uncompressed size of data part (header and checksum excluded).<a name="line.467"></a>
-<span class="sourceLineNo">468</span>   */<a name="line.468"></a>
-<span class="sourceLineNo">469</span>   int getUncompressedSizeWithoutHeader() {<a name="line.469"></a>
-<span class="sourceLineNo">470</span>    return uncompressedSizeWithoutHeader;<a name="line.470"></a>
-<span class="sourceLineNo">471</span>  }<a name="line.471"></a>
-<span class="sourceLineNo">472</span><a name="line.472"></a>
-<span class="sourceLineNo">473</span>  /**<a name="line.473"></a>
-<span class="sourceLineNo">474</span>   * @return the offset of the previous block of the same type in the file, or<a name="line.474"></a>
-<span class="sourceLineNo">475</span>   *         -1 if unknown<a name="line.475"></a>
-<span class="sourceLineNo">476</span>   */<a name="line.476"></a>
-<span class="sourceLineNo">477</span>  long getPrevBlockOffset() {<a name="line.477"></a>
-<span class="sourceLineNo">478</span>    return prevBlockOffset;<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>   * Rewinds {@code buf} and writes first 4 header fields. {@code buf} position<a name="line.482"></a>
-<span class="sourceLineNo">483</span>   * is modified as side-effect.<a name="line.483"></a>
-<span class="sourceLineNo">484</span>   */<a name="line.484"></a>
-<span class="sourceLineNo">485</span>  private void overwriteHeader() {<a name="line.485"></a>
-<span class="sourceLineNo">486</span>    buf.rewind();<a name="line.486"></a>
-<span class="sourceLineNo">487</span>    blockType.write(buf);<a name="line.487"></a>
-<span class="sourceLineNo">488</span>    buf.putInt(onDiskSizeWithoutHeader);<a name="line.488"></a>
-<span class="sourceLineNo">489</span>    buf.putInt(uncompressedSizeWithoutHeader);<a name="line.489"></a>
-<span class="sourceLineNo">490</span>    buf.putLong(prevBlockOffset);<a name="line.490"></a>
-<span class="sourceLineNo">491</span>    if (this.fileContext.isUseHBaseChecksum()) {<a name="line.491"></a>
-<span class="sourceLineNo">492</span>      buf.put(fileContext.getChecksumType().getCode());<a name="line.492"></a>
-<span class="sourceLineNo">493</span>      buf.putInt(fileContext.getBytesPerChecksum());<a name="line.493"></a>
-<span class="sourceLineNo">494</span>      buf.putInt(onDiskDataSizeWithHeader);<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>  /**<a name="line.498"></a>
-<span class="sourceLineNo">499</span>   * Returns a buffer that does not include the header or checksum.<a name="line.499"></a>
-<span class="sourceLineNo">500</span>   *<a name="line.500"></a>
-<span class="sourceLineNo">501</span>   * @return the buffer with header skipped and checksum omitted.<a name="line.501"></a>
-<span class="sourceLineNo">502</span>   */<a name="line.502"></a>
-<span class="sourceLineNo">503</span>  public ByteBuff getBufferWithoutHeader() {<a name="line.503"></a>
-<span class="sourceLineNo">504</span>    ByteBuff dup = getBufferReadOnly();<a name="line.504"></a>
-<span class="sourceLineNo">505</span>    // Now set it up so Buffer spans content only -- no header or no checksums.<a name="line.505"></a>
-<span class="sourceLineNo">506</span>    return dup.position(headerSize()).limit(buf.limit() - totalChecksumBytes()).slice();<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 a read-only duplicate of the buffer this block stores internally ready to be read.<a name="line.510"></a>
-<span class="sourceLineNo">511</span>   * Clients must not modify the buffer object though they may set position and limit on the<a name="line.511"></a>
-<span class="sourceLineNo">512</span>   * returned buffer since we pass back a duplicate. This method has to be public because it is used<a name="line.512"></a>
-<span class="sourceLineNo">513</span>   * in {@link CompoundBloomFilter} to avoid object creation on every Bloom<a name="line.513"></a>
-<span class="sourceLineNo">514</span>   * filter lookup, but has to be used with caution. Buffer holds header, block content,<a name="line.514"></a>
-<span class="sourceLineNo">515</span>   * and any follow-on checksums if present.<a name="line.515"></a>
-<span class="sourceLineNo">516</span>   *<a name="line.516"></a>
-<span class="sourceLineNo">517</span>   * @return the buffer of this block for read-only operations<a name="line.517"></a>
-<span class="sourceLineNo">518</span>   */<a name="line.518"></a>
-<span class="sourceLineNo">519</span>  public ByteBuff getBufferReadOnly() {<a name="line.519"></a>
-<span class="sourceLineNo">520</span>    // TODO: ByteBuf does not support asReadOnlyBuffer(). Fix.<a name="line.520"></a>
-<span class="sourceLineNo">521</span>    ByteBuff dup = this.buf.duplicate();<a name="line.521"></a>
-<span class="sourceLineNo">522</span>    assert dup.position() == 0;<a name="line.522"></a>
-<span class="sourceLineNo">523</span>    return dup;<a name="line.523"></a>
-<span class="sourceLineNo">524</span>  }<a name="line.524"></a>
-<span class="sourceLineNo">525</span><a name="line.525"></a>
-<span class="sourceLineNo">526</span>  @VisibleForTesting<a name="line.526"></a>
-<span class="sourceLineNo">527</span>  private void sanityCheckAssertion(long valueFromBuf, long valueFromField,<a name="line.527"></a>
-<span class="sourceLineNo">528</span>      String fieldName) throws IOException {<a name="line.528"></a>
-<span class="sourceLineNo">529</span>    if (valueFromBuf != valueFromField) {<a name="line.529"></a>
-<span class="sourceLineNo">530</span>      throw new AssertionError(fieldName + " in the buffer (" + valueFromBuf<a name="line.530"></a>
-<span class="sourceLineNo">531</span>          + ") is different from that in the field (" + valueFromField + ")");<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>  @VisibleForTesting<a name="line.535"></a>
-<span class="sourceLineNo">536</span>  private void sanityCheckAssertion(BlockType valueFromBuf, BlockType valueFromField)<a name="line.536"></a>
-<span class="sourceLineNo">537</span>      throws IOException {<a name="line.537"></a>
-<span class="sourceLineNo">538</span>    if (valueFromBuf != valueFromField) {<a name="line.538"></a>
-<span class="sourceLineNo">539</span>      throw new IOException("Block type stored in the buffer: " +<a name="line.539"></a>
-<span class="sourceLineNo">540</span>        valueFromBuf + ", block type field: " + valueFromField);<a name="line.540"></a>
-<span class="sourceLineNo">541</span>    }<a name="line.541"></a>
-<span class="sourceLineNo">542</span>  }<a name="line.542"></a>
-<span class="sourceLineNo">543</span><a name="line.543"></a>
-<span class="sourceLineNo">544</span>  /**<a name="line.544"></a>
-<span class="sourceLineNo">545</span>   * Checks if the block is internally consistent, i.e. the first<a name="line.545"></a>
-<span class="sourceLineNo">546</span>   * {@link HConstants#HFILEBLOCK_HEADER_SIZE} bytes of the buffer contain a<a name="line.546"></a>
-<span class="sourceLineNo">547</span>   * valid header consistent with the fields. Assumes a packed block structure.<a name="line.547"></a>
-<span class="sourceLineNo">548</span>   * This function is primary for testing and debugging, and is not<a name="line.548"></a>
-<span class="sourceLineNo">549</span>   * thread-safe, because it alters the internal buffer pointer.<a name="line.549"></a>
-<span class="sourceLineNo">550</span>   * Used by tests only.<a name="line.550"></a>
-<span class="sourceLineNo">551</span>   */<a name="line.551"></a>
-<span class="sourceLineNo">552</span>  @VisibleForTesting<a name="line.552"></a>
-<span class="sourceLineNo">553</span>  void sanityCheck() throws IOException {<a name="line.553"></a>
-<span class="sourceLineNo">554</span>    // Duplicate so no side-effects<a name="line.554"></a>
-<span class="sourceLineNo">555</span>    ByteBuff dup = this.buf.duplicate().rewind();<a name="line.555"></a>
-<span class="sourceLineNo">556</span>    sanityCheckAssertion(BlockType.read(dup), blockType);<a name="line.556"></a>
-<span class="sourceLineNo">557</span><a name="line.557"></a>
-<span class="sourceLineNo">558</span>    sanityCheckAssertion(dup.getInt(), onDiskSizeWithoutHeader, "onDiskSizeWithoutHeader");<a name="line.558"></a>
-<span class="sourceLineNo">559</span><a name="line.559"></a>
-<span class="sourceLineNo">560</span>    sanityCheckAssertion(dup.getInt(), uncompressedSizeWithoutHeader,<a name="line.560"></a>
-<span class="sourceLineNo">561</span>        "uncompressedSizeWithoutHeader");<a name="line.561"></a>
-<span class="sourceLineNo">562</span><a name="line.562"></a>
-<span class="sourceLineNo">563</span>    sanityCheckAssertion(dup.getLong(), prevBlockOffset, "prevBlockOffset");<a name="line.563"></a>
-<span class="sourceLineNo">564</span>    if (this.fileContext.isUseHBaseChecksum()) {<a name="line.564"></a>
-<span class="sourceLineNo">565</span>      sanityCheckAssertion(dup.get(), this.fileContext.getChecksumType().getCode(), "checksumType");<a name="line.565"></a>
-<span class="sourceLineNo">566</span>      sanityCheckAssertion(dup.getInt(), this.fileContext.getBytesPerChecksum(),<a name="line.566"></a>
-<span class="sourceLineNo">567</span>          "bytesPerChecksum");<a name="line.567"></a>
-<span class="sourceLineNo">568</span>      sanityCheckAssertion(dup.getInt(), onDiskDataSizeWithHeader, "onDiskDataSizeWithHeader");<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>    int cksumBytes = totalChecksumBytes();<a name="line.571"></a>
-<span class="sourceLineNo">572</span>    int expectedBufLimit = onDiskDataSizeWithHeader + cksumBytes;<a name="line.572"></a>
-<span class="sourceLineNo">573</span>    if (dup.limit() != expectedBufLimit) {<a name="line.573"></a>
-<span class="sourceLineNo">574</span>      throw new AssertionError("Expected limit " + expectedBufLimit + ", got " + dup.limit());<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>    // We might optionally allocate HFILEBLOCK_HEADER_SIZE more bytes to read the next<a name="line.577"></a>
-<span class="sourceLineNo">578</span>    // block's header, so there are two sensible values for buffer capacity.<a name="line.578"></a>
-<span class="sourceLineNo">579</span>    int hdrSize = headerSize();<a name="line.579"></a>
-<span class="sourceLineNo">580</span>    if (dup.capacity() != expectedBufLimit &amp;&amp; dup.capacity() != expectedBufLimit + hdrSize) {<a name="line.580"></a>
-<span class="sourceLineNo">581</span>      throw new AssertionError("Invalid buffer capacity: " + dup.capacity() +<a name="line.581"></a>
-<span class="sourceLineNo">582</span>          ", expected " + expectedBufLimit + " or " + (expectedBufLimit + hdrSize));<a name="line.582"></a>
-<span class="sourceLineNo">583</span>    }<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>  @Override<a name="line.586"></a>
-<span class="sourceLineNo">587</span>  public String toString() {<a name="line.587"></a>
-<span class="sourceLineNo">588</span>    StringBuilder sb = new StringBuilder()<a name="line.588"></a>
-<span class="sourceLineNo">589</span>      .append("[")<a name="line.589"></a>
-<span class="sourceLineNo">590</span>      .append("blockType=").append(blockType)<a name="line.590"></a>
-<span class="sourceLineNo">591</span>      .append(", fileOffset=").append(offset)<a name="line.591"></a>
-<span class="sourceLineNo">592</span>      .append(", headerSize=").append(headerSize())<a name="line.592"></a>
-<span class="sourceLineNo">593</span>      .append(", onDiskSizeWithoutHeader=").append(onDiskSizeWithoutHeader)<a name="line.593"></a>
-<span class="sourceLineNo">594</span>      .append(", uncompressedSizeWithoutHeader=").append(uncompressedSizeWithoutHeader)<a name="line.594"></a>
-<span class="sourceLineNo">595</span>      .append(", prevBlockOffset=").append(prevBlockOffset)<a name="line.595"></a>
-<span class="sourceLineNo">596</span>      .append(", isUseHBaseChecksum=").append(fileContext.isUseHBaseChecksum());<a name="line.596"></a>
-<span class="sourceLineNo">597</span>    if (fileContext.isUseHBaseChecksum()) {<a name="line.597"></a>
-<span class="sourceLineNo">598</span>      sb.append(", checksumType=").append(ChecksumType.codeToType(this.buf.get(24)))<a name="line.598"></a>
-<span class="sourceLineNo">599</span>        .append(", bytesPerChecksum=").append(this.buf.getInt(24 + 1))<a name="line.599"></a>
-<span class="sourceLineNo">600</span>        .append(", onDiskDataSizeWithHeader=").append(onDiskDataSizeWithHeader);<a name="line.600"></a>
-<span class="sourceLineNo">601</span>    } else {<a name="line.601"></a>
-<span class="sourceLineNo">602</span>      sb.append(", onDiskDataSizeWithHeader=").append(onDiskDataSizeWithHeader)<a name="line.602"></a>
-<span class="sourceLineNo">603</span>        .append("(").append(onDiskSizeWithoutHeader)<a name="line.603"></a>
-<span class="sourceLineNo">604</span>        .append("+").append(HConstants.HFILEBLOCK_HEADER_SIZE_NO_CHECKSUM).append(")");<a name="line.604"></a>
-<span class="sourceLineNo">605</span>    }<a name="line.605"></a>
-<span class="sourceLineNo">606</span>    String dataBegin = null;<a name="line.606"></a>
-<span class="sourceLineNo">607</span>    if (buf.hasArray()) {<a name="line.607"></a>
-<span class="sourceLineNo">608</span>      dataBegin = Bytes.toStringBinary(buf.array(), buf.arrayOffset() + headerSize(),<a name="line.608"></a>
-<span class="sourceLineNo">609</span>          Math.min(32, buf.limit() - buf.arrayOffset() - headerSize()));<a name="line.609"></a>
-<span class="sourceLineNo">610</span>    } else {<a name="line.610"></a>
-<span class="sourceLineNo">611</span>      ByteBuff bufWithoutHeader = getBufferWithoutHeader();<a name="line.611"></a>
-<span class="sourceLineNo">612</span>      byte[] dataBeginBytes = new byte[Math.min(32,<a name="line.612"></a>
-<span class="sourceLineNo">613</span>          bufWithoutHeader.limit() - bufWithoutHeader.position())];<a name="line.613"></a>
-<span class="sourceLineNo">614</span>      bufWithoutHeader.get(dataBeginBytes);<a name="line.614"></a>
-<span class="sourceLineNo">615</span>      dataBegin = Bytes.toStringBinary(dataBeginBytes);<a name="line.615"></a>
-<span class="sourceLineNo">616</span>    }<a name="line.616"></a>
-<span class="sourceLineNo">617</span>    sb.append(", getOnDiskSizeWithHeader=").append(getOnDiskSizeWithHeader())<a name="line.617"></a>
-<span class="sourceLineNo">618</span>      .append(", totalChecksumBytes=").append(totalChecksumBytes())<a name="line.618"></a>
-<span class="sourceLineNo">619</span>      .append(", isUnpacked=").append(isUnpacked())<a name="line.619"></a>
-<span class="sourceLineNo">620</span>      .append(", buf=[").append(buf).append("]")<a name="line.620"></a>
-<span class="sourceLineNo">621</span>      .append(", dataBeginsWith=").append(dataBegin)<a name="line.621"></a>
-<span class="sourceLineNo">622</span>      .append(", fileContext=").append(fileContext)<a name="line.622"></a>
-<span class="sourceLineNo">623</span>      .append("]");<a name="line.623"></a>
-<span class="sourceLineNo">624</span>    return sb.toString();<a name="line.624"></a>
-<span class="sourceLineNo">625</span>  }<a name="line.625"></a>
-<span class="sourceLineNo">626</span><a name="line.626"></a>
-<span class="sourceLineNo">627</span>  /**<a name="line.627"></a>
-<span class="sourceLineNo">628</span>   * Retrieves the decompressed/decrypted view of this block. An encoded block remains in its<a name="line.628"></a>
-<span class="sourceLineNo">629</span>   * encoded structure. Internal structures are shared between instances where applicable.<a name="line.629"></a>
-<span class="sourceLineNo">630</span>   */<a name="line.630"></a>
-<span class="sourceLineNo">631</span>  HFileBlock unpack(HFileContext fileContext, FSReader reader) throws IOException {<a name="line.631"></a>
-<span class="sourceLineNo">632</span>    if (!fileContext.isCompressedOrEncrypted()) {<a name="line.632"></a>
-<span class="sourceLineNo">633</span>      // TODO: cannot use our own fileContext here because HFileBlock(ByteBuffer, boolean),<a name="line.633"></a>
-<span class="sourceLineNo">634</span>      // which is used for block serialization to L2 cache, does not preserve encoding and<a name="line.634"></a>
-<span class="sourceLineNo">635</span>      // encryption details.<a name="line.635"></a>
-<span class="sourceLineNo">636</span>      return this;<a name="line.636"></a>
-<span class="sourceLineNo">637</span>    }<a name="line.637"></a>
-<span class="sourceLineNo">638</span><a name="line.638"></a>
-<span class="sourceLineNo">639</span>    HFileBlock unpacked = new HFileBlock(this);<a name="line.639"></a>
-<span class="sourceLineNo">640</span>    unpacked.allocateBuffer(); // allocates space for the decompressed block<a name="line.640"></a>
-<span class="sourceLineNo">641</span><a name="line.641"></a>
-<span class="sourceLineNo">642</span>    HFileBlockDecodingContext ctx = blockType == BlockType.ENCODED_DATA ?<a name="line.642"></a>
-<span class="sourceLineNo">643</span>      reader.getBlockDecodingContext() : reader.getDefaultBlockDecodingContext();<a name="line.643"></a>
-<span class="sourceLineNo">644</span><a name="line.644"></a>
-<span class="sourceLineNo">645</span>    ByteBuff dup = this.buf.duplicate();<a name="line.645"></a>
-<span class="sourceLineNo">646</span>    dup.position(this.headerSize());<a name="line.646"></a>
-<span class="sourceLineNo">647</span>    dup = dup.slice();<a name="line.647"></a>
-<span class="sourceLineNo">648</span>    ctx.prepareDecoding(unpacked.getOnDiskSizeWithoutHeader(),<a name="line.648"></a>
-<span class="sourceLineNo">649</span>      unpacked.getUncompressedSizeWithoutHeader(), unpacked.getBufferWithoutHeader(),<a name="line.649"></a>
-<span class="sourceLineNo">650</span>      dup);<a name="line.650"></a>
-<span class="sourceLineNo">651</span>    return unpacked;<a name="line.651"></a>
-<span class="sourceLineNo">652</span>  }<a name="line.652"></a>
-<span class="sourceLineNo">653</span><a name="line.653"></a>
-<span class="sourceLineNo">654</span>  /**<a name="line.654"></a>
-<span class="sourceLineNo">655</span>   * Always allocates a new buffer of the correct size. Copies header bytes<a name="line.655"></a>
-<span class="sourceLineNo">656</span>   * from the existing buffer. Does not change header fields.<a name="line.656"></a>
-<span class="sourceLineNo">657</span>   * Reserve room to keep checksum bytes too.<a name="line.657"></a>
-<span class="sourceLineNo">658</span>   */<a name="line.658"></a>
-<span class="sourceLineNo">659</span>  private void allocateBuffer() {<a name="line.659"></a>
-<span class="sourceLineNo">660</span>    int cksumBytes = totalChecksumBytes();<a name="line.660"></a>
-<span class="sourceLineNo">661</span>    int headerSize = headerSize();<a name="line.661"></a>
-<span class="sourceLineNo">662</span>    int capacityNeeded = headerSize + uncompressedSizeWithoutHeader + cksumBytes;<a name="line.662"></a>
-<span class="sourceLineNo">663</span><a name="line.663"></a>
-<span class="sourceLineNo">664</span>    // TODO we need consider allocating offheap here?<a name="line.664"></a>
-<span class="sourceLineNo">665</span>    ByteBuffer newBuf = ByteBuffer.allocate(capacityNeeded);<a name="line.665"></a>
-<span class="sourceLineNo">666</span><a name="line.666"></a>
-<span class="sourceLineNo">667</span>    // Copy header bytes into newBuf.<a name="line.667"></a>
-<span class="sourceLineNo">668</span>    // newBuf is HBB so no issue in calling array()<a name="line.668"></a>
-<span class="sourceLineNo">669</span>    buf.position(0);<a name="line.669"></a>
-<span class="sourceLineNo">670</span>    buf.get(newBuf.array(), newBuf.arrayOffset(), headerSize);<a name="line.670"></a>
-<span class="sourceLineNo">671</span><a name="line.671"></a>
-<span class="sourceLineNo">672</span>    buf = new SingleByteBuff(newBuf);<a name="line.672"></a>
-<span class="sourceLineNo">673</span>    // set limit to exclude next block's header<a name="line.673"></a>
-<span class="sourceLineNo">674</span>    buf.limit(headerSize + uncompressedSizeWithoutHeader + cksumBytes);<a name="line.674"></a>
-<span class="sourceLineNo">675</span>  }<a name="line.675"></a>
-<span class="sourceLineNo">676</span><a name="line.676"></a>
-<span class="sourceLineNo">677</span>  /**<a name="line.677"></a>
-<span class="sourceLineNo">678</span>   * Return true when this block's buffer has been unpacked, false otherwise. Note this is a<a name="line.678"></a>
-<span class="sourceLineNo">679</span>   * calculated heuristic, not tracked attribute of the block.<a name="line.679"></a>
-<span class="sourceLineNo">680</span>   */<a name="line.680"></a>
-<span class="sourceLineNo">681</span>  public boolean isUnpacked() {<a name="line.681"></a>
-<span class="sourceLineNo">682</span>    final int cksumBytes = totalChecksumBytes();<a name="line.682"></a>
-<span class="sourceLineNo">683</span>    final int headerSize = headerSize();<a name="line.683"></a>
-<span class="sourceLineNo">684</span>    final int expectedCapacity = headerSize + uncompressedSizeWithoutHeader + cksumBytes;<a name="line.684"></a>
-<span class="sourceLineNo">685</span>    final int bufCapacity = buf.capacity();<a name="line.685"></a>
-<span class="sourceLineNo">686</span>    return bufCapacity == expectedCapacity || bufCapacity == expectedCapacity + headerSize;<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>  /** An additional sanity-check in case no compression or encryption is being used. */<a name="line.689"></a>
-<span class="sourceLineNo">690</span>  @VisibleForTesting<a name="line.690"></a>
-<span class="sourceLineNo">691</span>  void sanityCheckUncompressedSize() throws IOException {<a name="line.691"></a>
-<span class="sourceLineNo">692</span>    if (onDiskSizeWithoutHeader != uncompressedSizeWithoutHeader + totalChecksumBytes()) {<a name="line.692"></a>
-<span class="sourceLineNo">693</span>      throw new IOException("Using no compression but "<a name="line.693"></a>
-<span class="sourceLineNo">694</span>          + "onDiskSizeWithoutHeader=" + onDiskSizeWithoutHeader + ", "<a name="line.694"></a>
-<span class="sourceLineNo">695</span>          + "uncompressedSizeWithoutHeader=" + uncompressedSizeWithoutHeader<a name="line.695"></a>
-<span class="sourceLineNo">696</span>          + ", numChecksumbytes=" + totalChecksumBytes());<a name="line.696"></a>
-<span class="sourceLineNo">697</span>    }<a name="line.697"></a>
-<span class="sourceLineNo">698</span>  }<a name="line.698"></a>
-<span class="sourceLineNo">699</span><a name="line.699"></a>
-<span class="sourceLineNo">700</span>  /**<a name="line.700"></a>
-<span class="sourceLineNo">701</span>   * Cannot be {@link #UNSET}. Must be a legitimate value. Used re-making the {@link BlockCacheKey} when<a name="line.701"></a>
-<span class="sourceLineNo">702</span>   * block is returned to the cache.<a name="line.702"></a>
-<span class="sourceLineNo">703</span>   * @return the offset of this block in the file it was read from<a name="line.703"></a>
-<span class="sourceLineNo">704</span>   */<a name="line.704"></a>
-<span class="sourceLineNo">705</span>  long getOffset() {<a name="line.705"></a>
-<span class="sourceLineNo">706</span>    if (offset &lt; 0) {<a name="line.706"></a>
-<span class="sourceLineNo">707</span>      throw new IllegalStateException("HFile block offset not initialized properly");<a name="line.707"></a>
-<span class="sourceLineNo">708</span>    }<a name="line.708"></a>
-<span class="sourceLineNo">709</span>    return offset;<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>   * @return a byte stream reading the data + checksum of this block<a name="line.713"></a>
-<span class="sourceLineNo">714</span>   */<a name="line.714"></a>
-<span class="sourceLineNo">715</span>  DataInputStream getByteStream() {<a name="line.715"></a>
-<span class="sourceLineNo">716</span>    ByteBuff dup = this.buf.duplicate();<a name="line.716"></a>
-<span class="sourceLineNo">717</span>    dup.position(this.headerSize());<a name="line.717"></a>
-<span class="sourceLineNo">718</span>    return new DataInputStream(new ByteBuffInputStream(dup));<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>
-<span class="sourceLineNo">721</span>  @Override<a name="line.721"></a>
-<span class="sourceLineNo">722</span>  public long heapSize() {<a name="line.722"></a>
-<span class="sourceLineNo">723</span>    long size = ClassSize.align(<a name="line.723"></a>
-<span class="sourceLineNo">724</span>        ClassSize.OBJECT +<a name="line.724"></a>
-<span class="sourceLineNo">725</span>        // Block type, multi byte buffer, MemoryType and meta references<a name="line.725"></a>
-<span class="sourceLineNo">726</span>        4 * ClassSize.REFERENCE +<a name="line.726"></a>
-<span class="sourceLineNo">727</span>        // On-disk size, uncompressed size, and next block's on-disk size<a name="line.727"></a>
-<span class="sourceLineNo">728</span>        // bytePerChecksum and onDiskDataSize<a name="line.728"></a>
-<span class="sourceLineNo">729</span>        4 * Bytes.SIZEOF_INT +<a name="line.729"></a>
-<span class="sourceLineNo">730</span>        // This and previous block offset<a name="line.730"></a>
-<span class="sourceLineNo">731</span>        2 * Bytes.SIZEOF_LONG +<a name="line.731"></a>
-<span class="sourceLineNo">732</span>        // Heap size of the meta object. meta will be always not null.<a name="line.732"></a>
-<span class="sourceLineNo">733</span>        fileContext.heapSize()<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>    if (buf != null) {<a name="line.736"></a>
-<span class="sourceLineNo">737</span>      // Deep overhead of the byte buffer. Needs to be aligned separately.<a name="line.737"></a>
-<span class="sourceLineNo">738</span>      size += ClassSize.align(buf.capacity() + MULTI_BYTE_BUFFER_HEAP_SIZE);<a name="line.738"></a>
-<span class="sourceLineNo">739</span>    }<a name="line.739"></a>
-<span class="sourceLineNo">740</span><a name="line.740"></a>
-<span class="sourceLineNo">741</span>    return ClassSize.align(size);<a name="line.741"></a>
-<span class="sourceLineNo">742</span>  }<a name="line.742"></a>
-<span class="sourceLineNo">743</span><a name="line.743"></a>
-<span class="sourceLineNo">744</span>  /**<a name="line.744"></a>
-<span class="sourceLineNo">745</span>   * Read from an input stream at least &lt;code&gt;necessaryLen&lt;/code&gt; and if possible,<a name="line.745"></a>
-<span class="sourceLineNo">746</span>   * &lt;code&gt;extraLen&lt;/code&gt; also if available. Analogous to<a name="line.746"></a>
-<span class="sourceLineNo">747</span>   * {@link IOUtils#readFully(InputStream, byte[], int, int)}, but specifies a<a name="line.747"></a>
-<span class="sourceLineNo">748</span>   * number of "extra" bytes to also optionally read.<a name="line.748"></a>
-<span class="sourceLineNo">749</span>   *<a name="line.749"></a>
-<span class="sourceLineNo">750</span>   * @param in the input stream to read from<a name="line.750"></a>
-<span class="sourceLineNo">751</span>   * @param buf the buffer to read into<a name="line.751"></a>
-<span class="sourceLineNo">752</span>   * @param bufOffset the destination offset in the buffer<a name="line.752"></a>
-<span class="sourceLineNo">753</span>   * @param necessaryLen the number of bytes that are absolutely necessary to read<a name="line.753"></a>
-<span class="sourceLineNo">754</span>   * @param extraLen the number of extra bytes that would be nice to read<a name="line.754"></a>
-<span class="sourceLineNo">755</span>   * @return true if succeeded reading the extra bytes<a name="line.755"></a>
-<span class="sourceLineNo">756</span>   * @throws IOException if failed to read the necessary bytes<a name="line.756"></a>
-<span class="sourceLineNo">757</span>   */<a name="line.757"></a>
-<span class="sourceLineNo">758</span>  static boolean readWithExtra(InputStream in, byte[] buf,<a name="line.758"></a>
-<span class="sourceLineNo">759</span>      int bufOffset, int necessaryLen, int extraLen) throws IOException {<a name="line.759"></a>
-<span class="sourceLineNo">760</span>    int bytesRemaining = necessaryLen + extraLen;<a name="line.760"></a>
-<span class="sourceLineNo">761</span>    while (bytesRemaining &gt; 0) {<a name="line.761"></a>
-<span class="sourceLineNo">762</span>      int ret = in.read(buf, bufOffset, bytesRemaining);<a name="line.762"></a>
-<span class="sourceLineNo">763</span>      if (ret == -1 &amp;&amp; bytesRemaining &lt;= extraLen) {<a name="line.763"></a>
-<span class="sourceLineNo">764</span>        // We could not read the "extra data", but that is OK.<a name="line.764"></a>
-<span class="sourceLineNo">765</span>        break;<a name="line.765"></a>
-<span class="sourceLineNo">766</span>      }<a name="line.766"></a>
-<span class="sourceLineNo">767</span>      if (ret &lt; 0) {<a name="line.767"></a>
-<span class="sourceLineNo">768</span>        throw new IOException("Premature EOF from inputStream (read "<a name="line.768"></a>
-<span class="sourceLineNo">769</span>            + "returned " + ret + ", was trying to read " + necessaryLen<a name="line.769"></a>
-<span class="sourceLineNo">770</span>            + " necessary bytes and " + extraLen + " extra bytes, "<a name="line.770"></a>
-<span class="sourceLineNo">771</span>            + "successfully read "<a name="line.771"></a>
-<span class="sourceLineNo">772</span>            + (necessaryLen + extraLen - bytesRemaining));<a name="line.772"></a>
-<span class="sourceLineNo">773</span>      }<a name="line.773"></a>
-<span class="sourceLineNo">774</span>      bufOffset += ret;<a name="line.774"></a>
-<span class="sourceLineNo">775</span>      bytesRemaining -= ret;<a name="line.775"></a>
-<span class="sourceLineNo">776</span>    }<a name="line.776"></a>
-<span class="sourceLineNo">777</span>    return bytesRemaining &lt;= 0;<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>   * Read from an input stream at least &lt;code&gt;necessaryLen&lt;/code&gt; and if possible,<a name="line.781"></a>
-<span class="sourceLineNo">782</span>   * &lt;code&gt;extraLen&lt;/code&gt; also if available. Analogous to<a name="line.782"></a>
-<span class="sourceLineNo">783</span>   * {@link IOUtils#readFully(InputStream, byte[], int, int)}, but uses<a name="line.783"></a>
-<span class="sourceLineNo">784</span>   * positional read and specifies a number of "extra" bytes that would be<a name="line.784"></a>
-<span class="sourceLineNo">785</span>   * desirable but not absolutely necessary to read.<a name="line.785"></a>
-<span class="sourceLineNo">786</span>   *<a name="line.786"></a>
-<span class="sourceLineNo">787</span>   * @param in the input stream to read from<a name="line.787"></a>
-<span class="sourceLineNo">788</span>   * @param position the position within the stream from which to start reading<a name="line.788"></a>
-<span class="sourceLineNo">789</span>   * @param buf the buffer to read into<a name="line.789"></a>
-<span class="sourceLineNo">790</span>   * @param bufOffset the destination offset in the buffer<a name="line.790"></a>
-<span class="sourceLineNo">791</span>   * @param necessaryLen the number of bytes that are absolutely necessary to<a name="line.791"></a>
-<span class="sourceLineNo">792</span>   *     read<a name="line.792"></a>
-<span class="sourceLineNo">793</span>   * @param extraLen the number of extra bytes that would be nice to read<a name="line.793"></a>
-<span class="sourceLineNo">794</span>   * @return true if and only if extraLen is &gt; 0 and reading those extra bytes<a name="line.794"></a>
-<span class="sourceLineNo">795</span>   *     was successful<a name="line.795"></a>
-<span class="sourceLineNo">796</span>   * @throws IOException if failed to read the necessary bytes<a name="line.796"></a>
-<span class="sourceLineNo">797</span>   */<a name="line.797"></a>
-<span class="sourceLineNo">798</span>  @VisibleForTesting<a name="line.798"></a>
-<span class="sourceLineNo">799</span>  static boolean positionalReadWithExtra(FSDataInputStream in,<a name="line.799"></a>
-<span class="sourceLineNo">800</span>      long position, byte[] buf, int bufOffset, int necessaryLen, int extraLen)<a name="line.800"></a>
-<span class="sourceLineNo">801</span>      throws IOException {<a name="line.801"></a>
-<span class="sourceLineNo">802</span>    int bytesRemaining = necessaryLen + extraLen;<a name="line.802"></a>
-<span class="sourceLineNo">803</span>    int bytesRead = 0;<a name="line.803"></a>
-<span class="sourceLineNo">804</span>    while (bytesRead &lt; necessaryLen) {<a name="line.804"></a>
-<span class="sourceLineNo">805</span>      int ret = in.read(position, buf, bufOffset, bytesRemaining);<a name="line.805"></a>
-<span class="sourceLineNo">806</span>      if (ret &lt; 0) {<a name="line.806"></a>
-<span class="sourceLineNo">807</span>        throw new IOException("Premature EOF from inputStream (positional read "<a name="line.807"></a>
-<span class="sourceLineNo">808</span>            + "returned " + ret + ", was trying to read " + necessaryLen<a name="line.808"></a>
-<span class="sourceLineNo">809</span>            + " necessary bytes and " + extraLen + " extra bytes, "<a name="line.809"></a>
-<span class="sourceLineNo">810</span>            + "successfully read " + bytesRead);<a name="line.810"></a>
-<span class="sourceLineNo">811</span>      }<a name="line.811"></a>
-<span class="sourceLineNo">812</span>      position += ret;<a name="line.812"></a>
-<span class="sourceLineNo">813</span>      bufOffset += ret;<a name="line.813"></a>
-<span class="sourceLineNo">814</span>      bytesRemaining -= ret;<a name="line.814"></a>
-<span class="sourceLineNo">815</span>      bytesRead += ret;<a name="line.815"></a>
-<span class="sourceLineNo">816</span>    }<a name="line.816"></a>
-<span class="sourceLineNo">817</span>    return bytesRead != necessaryLen &amp;&amp; bytesRemaining &lt;= 0;<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>   * Unified version 2 {@link HFile} block writer. The intended usage pattern<a name="line.821"></a>
-<span class="sourceLineNo">822</span>   * is as follows:<a name="line.822"></a>
-<span class="sourceLineNo">823</span>   * &lt;ol&gt;<a name="line.823"></a>
-<span class="sourceLineNo">824</span>   * &lt;li&gt;Construct an {@link HFileBlock.Writer}, providing a compression algorithm.<a name="line.824"></a>
-<span class="sourceLineNo">825</span>   * &lt;li&gt;Call {@link Writer#startWriting} and get a data stream to write to.<a name="line.825"></a>
-<span class="sourceLineNo">826</span>   * &lt;li&gt;Write your data into the stream.<a name="line.826"></a>
-<span class="sourceLineNo">827</span>   * &lt;li&gt;Call Writer#writeHeaderAndData(FSDataOutputStream) as many times as you need to.<a name="line.827"></a>
-<span class="sourceLineNo">828</span>   * store the serialized block into an external stream.<a name="line.828"></a>
-<span class="sourceLineNo">829</span>   * &lt;li&gt;Repeat to write more blocks.<a name="line.829"></a>
-<span class="sourceLineNo">830</span>   * &lt;/ol&gt;<a name="line.830"></a>
-<span class="sourceLineNo">831</span>   * &lt;p&gt;<a name="line.831"></a>
-<span class="sourceLineNo">832</span>   */<a name="line.832"></a>
-<span class="sourceLineNo">833</span>  static class Writer {<a name="line.833"></a>
-<span class="sourceLineNo">834</span>    private enum State {<a name="line.834"></a>
-<span class="sourceLineNo">835</span>      INIT,<a name="line.835"></a>
-<span class="sourceLineNo">836</span>      WRITING,<a name="line.836"></a>
-<span class="sourceLineNo">837</span>      BLOCK_READY<a name="line.837"></a>
-<span class="sourceLineNo">838</span>    }<a name="line.838"></a>
-<span class="sourceLineNo">839</span><a name="line.839"></a>
-<span class="sourceLineNo">840</span>    /** Writer state. Used to ensure the correct usage protocol. */<a name="line.840"></a>
-<span class="sourceLineNo">841</span>    private State state = State.INIT;<a name="line.841"></a>
-<span class="sourceLineNo">842</span><a name="line.842"></a>
-<span class="sourceLineNo">843</span>    /** Data block encoder used for data blocks */<a name="line.843"></a>
-<span class="sourceLineNo">844</span>    private final HFileDataBlockEncoder dataBlockEncoder;<a name="line.844"></a>
-<span class="sourceLineNo">845</span><a name="line.845"></a>
-<span class="sourceLineNo">846</span>    private HFileBlockEncodingContext dataBlockEncodingCtx;<a name="line.846"></a>
+<span class="sourceLineNo">328</span>   *<a name="line.328"></a>
+<span class="sourceLineNo">329</span>   * &lt;p&gt;TODO: The caller presumes no checksumming<a name="line.329"></a>
+<span class="sourceLineNo">330</span>   * required of this block instance since going into cache; checksum already verified on<a name="line.330"></a>
+<span class="sourceLineNo">331</span>   * underlying block data pulled in from filesystem. Is that correct? What if cache is SSD?<a name="line.331"></a>
+<span class="sourceLineNo">332</span>   *<a name="line.332"></a>
+<span class="sourceLineNo">333</span>   * @param blockType the type of this block, see {@link BlockType}<a name="line.333"></a>
+<span class="sourceLineNo">334</span>   * @param onDiskSizeWithoutHeader see {@link #onDiskSizeWithoutHeader}<a name="line.334"></a>
+<span class="sourceLineNo">335</span>   * @param uncompressedSizeWithoutHeader see {@link #uncompressedSizeWithoutHeader}<a name="line.335"></a>
+<span class="sourceLineNo">336</span>   * @param prevBlockOffset see {@link #prevBlockOffset}<a name="line.336"></a>
+<span class="sourceLineNo">337</span>   * @param b block header ({@link HConstants#HFILEBLOCK_HEADER_SIZE} bytes)<a name="line.337"></a>
+<span class="sourceLineNo">338</span>   * @param fillHeader when true, write the first 4 header fields into passed buffer.<a name="line.338"></a>
+<span class="sourceLineNo">339</span>   * @param offset the file offset the block was read from<a name="line.339"></a>
+<span class="sourceLineNo">340</span>   * @param onDiskDataSizeWithHeader see {@link #onDiskDataSizeWithHeader}<a name="line.340"></a>
+<span class="sourceLineNo">341</span>   * @param fileContext HFile meta data<a name="line.341"></a>
+<span class="sourceLineNo">342</span>   */<a name="line.342"></a>
+<span class="sourceLineNo">343</span>  @VisibleForTesting<a name="line.343"></a>
+<span class="sourceLineNo">344</span>  public HFileBlock(BlockType blockType, int onDiskSizeWithoutHeader,<a name="line.344"></a>
+<span class="sourceLineNo">345</span>      int uncompressedSizeWithoutHeader, long prevBlockOffset, ByteBuffer b, boolean fillHeader,<a name="line.345"></a>
+<span class="sourceLineNo">346</span>      long offset, final int nextBlockOnDiskSize, int onDiskDataSizeWithHeader,<a name="line.346"></a>
+<span class="sourceLineNo">347</span>      HFileContext fileContext) {<a name="line.347"></a>
+<span class="sourceLineNo">348</span>    init(blockType, onDiskSizeWithoutHeader, uncompressedSizeWithoutHeader,<a name="line.348"></a>
+<span class="sourceLineNo">349</span>        prevBlockOffset, offset, onDiskDataSizeWithHeader, nextBlockOnDiskSize, fileContext);<a name="line.349"></a>
+<span class="sourceLineNo">350</span>    this.buf = new SingleByteBuff(b);<a name="line.350"></a>
+<span class="sourceLineNo">351</span>    if (fillHeader) {<a name="line.351"></a>
+<span class="sourceLineNo">352</span>      overwriteHeader();<a name="line.352"></a>
+<span class="sourceLineNo">353</span>    }<a name="line.353"></a>
+<span class="sourceLineNo">354</span>    this.buf.rewind();<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">357</span>  /**<a name="line.357"></a>
+<span class="sourceLineNo">358</span>   * Creates a block from an existing buffer starting with a header. Rewinds<a name="line.358"></a>
+<span class="sourceLineNo">359</span>   * and takes ownership of the buffer. By definition of rewind, ignores the<a name="line.359"></a>
+<span class="sourceLineNo">360</span>   * buffer position, but if you slice the buffer beforehand, it will rewind<a name="line.360"></a>
+<span class="sourceLineNo">361</span>   * to that point.<a name="line.361"></a>
+<span class="sourceLineNo">362</span>   * @param buf Has header, content, and trailing checksums if present.<a name="line.362"></a>
+<span class="sourceLineNo">363</span>   */<a name="line.363"></a>
+<span class="sourceLineNo">364</span>  HFileBlock(ByteBuff buf, boolean usesHBaseChecksum, MemoryType memType, final long offset,<a name="line.364"></a>
+<span class="sourceLineNo">365</span>      final int nextBlockOnDiskSize, HFileContext fileContext) throws IOException {<a name="line.365"></a>
+<span class="sourceLineNo">366</span>    buf.rewind();<a name="line.366"></a>
+<span class="sourceLineNo">367</span>    final BlockType blockType = BlockType.read(buf);<a name="line.367"></a>
+<span class="sourceLineNo">368</span>    final int onDiskSizeWithoutHeader = buf.getInt(Header.ON_DISK_SIZE_WITHOUT_HEADER_INDEX);<a name="line.368"></a>
+<span class="sourceLineNo">369</span>    final int uncompressedSizeWithoutHeader =<a name="line.369"></a>
+<span class="sourceLineNo">370</span>        buf.getInt(Header.UNCOMPRESSED_SIZE_WITHOUT_HEADER_INDEX);<a name="line.370"></a>
+<span class="sourceLineNo">371</span>    final long prevBlockOffset = buf.getLong(Header.PREV_BLOCK_OFFSET_INDEX);<a name="line.371"></a>
+<span class="sourceLineNo">372</span>    // This constructor is called when we deserialize a block from cache and when we read a block in<a name="line.372"></a>
+<span class="sourceLineNo">373</span>    // from the fs. fileCache is null when deserialized from cache so need to make up one.<a name="line.373"></a>
+<span class="sourceLineNo">374</span>    HFileContextBuilder fileContextBuilder = fileContext != null?<a name="line.374"></a>
+<span class="sourceLineNo">375</span>        new HFileContextBuilder(fileContext): new HFileContextBuilder();<a name="line.375"></a>
+<span class="sourceLineNo">376</span>    fileContextBuilder.withHBaseCheckSum(usesHBaseChecksum);<a name="line.376"></a>
+<span class="sourceLineNo">377</span>    int onDiskDataSizeWithHeader;<a name="line.377"></a>
+<span class="sourceLineNo">378</span>    if (usesHBaseChecksum) {<a name="line.378"></a>
+<span class="sourceLineNo">379</span>      byte checksumType = buf.get(Header.CHECKSUM_TYPE_INDEX);<a name="line.379"></a>
+<span class="sourceLineNo">380</span>      int bytesPerChecksum = buf.getInt(Header.BYTES_PER_CHECKSUM_INDEX);<a name="line.380"></a>
+<span class="sourceLineNo">381</span>      onDiskDataSizeWithHeader = buf.getInt(Header.ON_DISK_DATA_SIZE_WITH_HEADER_INDEX);<a name="line.381"></a>
+<span class="sourceLineNo">382</span>      // Use the checksum type and bytes per checksum from header, not from filecontext.<a name="line.382"></a>
+<span class="sourceLineNo">383</span>      fileContextBuilder.withChecksumType(ChecksumType.codeToType(checksumType));<a name="line.383"></a>
+<span class="sourceLineNo">384</span>      fileContextBuilder.withBytesPerCheckSum(bytesPerChecksum);<a name="line.384"></a>
+<span class="sourceLineNo">385</span>    } else {<a name="line.385"></a>
+<span class="sourceLineNo">386</span>      fileContextBuilder.withChecksumType(ChecksumType.NULL);<a name="line.386"></a>
+<span class="sourceLineNo">387</span>      fileContextBuilder.withBytesPerCheckSum(0);<a name="line.387"></a>
+<span class="sourceLineNo">388</span>      // Need to fix onDiskDataSizeWithHeader; there are not checksums after-block-data<a name="line.388"></a>
+<span class="sourceLineNo">389</span>      onDiskDataSizeWithHeader = onDiskSizeWithoutHeader + headerSize(usesHBaseChecksum);<a name="line.389"></a>
+<span class="sourceLineNo">390</span>    }<a name="line.390"></a>
+<span class="sourceLineNo">391</span>    fileContext = fileContextBuilder.build();<a name="line.391"></a>
+<span class="sourceLineNo">392</span>    assert usesHBaseChecksum == fileContext.isUseHBaseChecksum();<a name="line.392"></a>
+<span class="sourceLineNo">393</span>    init(blockType, onDiskSizeWithoutHeader, uncompressedSizeWithoutHeader,<a name="line.393"></a>
+<span class="sourceLineNo">394</span>        prevBlockOffset, offset, onDiskDataSizeWithHeader, nextBlockOnDiskSize, fileContext);<a name="line.394"></a>
+<span class="sourceLineNo">395</span>    this.memType = memType;<a name="line.395"></a>
+<span class="sourceLineNo">396</span>    this.offset = offset;<a name="line.396"></a>
+<span class="sourceLineNo">397</span>    this.buf = buf;<a name="line.397"></a>
+<span class="sourceLineNo">398</span>    this.buf.rewind();<a name="line.398"></a>
+<span class="sourceLineNo">399</span>  }<a name="line.399"></a>
+<span class="sourceLineNo">400</span><a name="line.400"></a>
+<span class="sourceLineNo">401</span>  /**<a name="line.401"></a>
+<span class="sourceLineNo">402</span>   * Called from constructors.<a name="line.402"></a>
+<span class="sourceLineNo">403</span>   */<a name="line.403"></a>
+<span class="sourceLineNo">404</span>  private void init(BlockType blockType, int onDiskSizeWithoutHeader,<a name="line.404"></a>
+<span class="sourceLineNo">405</span>      int uncompressedSizeWithoutHeader, long prevBlockOffset,<a name="line.405"></a>
+<span class="sourceLineNo">406</span>      long offset, int onDiskDataSizeWithHeader, final int nextBlockOnDiskSize,<a name="line.406"></a>
+<span class="sourceLineNo">407</span>      HFileContext fileContext) {<a name="line.407"></a>
+<span class="sourceLineNo">408</span>    this.blockType = blockType;<a name="line.408"></a>
+<span class="sourceLineNo">409</span>    this.onDiskSizeWithoutHeader = onDiskSizeWithoutHeader;<a name="line.409"></a>
+<span class="sourceLineNo">410</span>    this.uncompressedSizeWithoutHeader = uncompressedSizeWithoutHeader;<a name="line.410"></a>
+<span class="sourceLineNo">411</span>    this.prevBlockOffset = prevBlockOffset;<a name="line.411"></a>
+<span class="sourceLineNo">412</span>    this.offset = offset;<a name="line.412"></a>
+<span class="sourceLineNo">413</span>    this.onDiskDataSizeWithHeader = onDiskDataSizeWithHeader;<a name="line.413"></a>
+<span class="sourceLineNo">414</span>    this.nextBlockOnDiskSize = nextBlockOnDiskSize;<a name="line.414"></a>
+<span class="sourceLineNo">415</span>    this.fileContext = fileContext;<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">418</span>  /**<a name="line.418"></a>
+<span class="sourceLineNo">419</span>   * Parse total on disk size including header and checksum.<a name="line.419"></a>
+<span class="sourceLineNo">420</span>   * @param headerBuf Header ByteBuffer. Presumed exact size of header.<a name="line.420"></a>
+<span class="sourceLineNo">421</span>   * @param verifyChecksum true if checksum verification is in use.<a name="line.421"></a>
+<span class="sourceLineNo">422</span>   * @return Size of the block with header included.<a name="line.422"></a>
+<span class="sourceLineNo">423</span>   */<a name="line.423"></a>
+<span class="sourceLineNo">424</span>  private static int getOnDiskSizeWithHeader(final ByteBuffer headerBuf,<a name="line.424"></a>
+<span class="sourceLineNo">425</span>      boolean verifyChecksum) {<a name="line.425"></a>
+<span class="sourceLineNo">426</span>    return headerBuf.getInt(Header.ON_DISK_SIZE_WITHOUT_HEADER_INDEX) +<a name="line.426"></a>
+<span class="sourceLineNo">427</span>      headerSize(verifyChecksum);<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>   * @return the on-disk size of the next block (including the header size and any checksums if<a name="line.431"></a>
+<span class="sourceLineNo">432</span>   * present) read by peeking into the next block's header; use as a hint when doing<a name="line.432"></a>
+<span class="sourceLineNo">433</span>   * a read of the next block when scanning or running over a file.<a name="line.433"></a>
+<span class="sourceLineNo">434</span>   */<a name="line.434"></a>
+<span class="sourceLineNo">435</span>  int getNextBlockOnDiskSize() {<a name="line.435"></a>
+<span class="sourceLineNo">436</span>    return nextBlockOnDiskSize;<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>  @Override<a name="line.439"></a>
+<span class="sourceLineNo">440</span>  public BlockType getBlockType() {<a name="line.440"></a>
+<span class="sourceLineNo">441</span>    return blockType;<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>  /** @return get data block encoding id that was used to encode this block */<a name="line.444"></a>
+<span class="sourceLineNo">445</span>  short getDataBlockEncodingId() {<a name="line.445"></a>
+<span class="sourceLineNo">446</span>    if (blockType != BlockType.ENCODED_DATA) {<a name="line.446"></a>
+<span class="sourceLineNo">447</span>      throw new IllegalArgumentException("Querying encoder ID of a block " +<a name="line.447"></a>
+<span class="sourceLineNo">448</span>          "of type other than " + BlockType.ENCODED_DATA + ": " + blockType);<a name="line.448"></a>
+<span class="sourceLineNo">449</span>    }<a name="line.449"></a>
+<span class="sourceLineNo">450</span>    return buf.getShort(headerSize());<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>   * @return the on-disk size of header + data part + checksum.<a name="line.454"></a>
+<span class="sourceLineNo">455</span>   */<a name="line.455"></a>
+<span class="sourceLineNo">456</span>  public int getOnDiskSizeWithHeader() {<a name="line.456"></a>
+<span class="sourceLineNo">457</span>    return onDiskSizeWithoutHeader + headerSize();<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>   * @return the on-disk size of the data part + checksum (header excluded).<a name="line.461"></a>
+<span class="sourceLineNo">462</span>   */<a name="line.462"></a>
+<span class="sourceLineNo">463</span>  int getOnDiskSizeWithoutHeader() {<a name="line.463"></a>
+<span class="sourceLineNo">464</span>    return onDiskSizeWithoutHeader;<a name="line.464"></a>
+<span class="sourceLineNo">465</span>  }<a name="line.465"></a>
+<span class="sourceLineNo">466</span><a name="line.466"></a>
+<span class="sourceLineNo">467</span>  /**<a name="line.467"></a>
+<span class="sourceLineNo">468</span>   * @return the uncompressed size of data part (header and checksum excluded).<a name="line.468"></a>
+<span class="sourceLineNo">469</span>   */<a name="line.469"></a>
+<span class="sourceLineNo">470</span>   int getUncompressedSizeWithoutHeader() {<a name="line.470"></a>
+<span class="sourceLineNo">471</span>    return uncompressedSizeWithoutHeader;<a name="line.471"></a>
+<span class="sourceLineNo">472</span>  }<a name="line.472"></a>
+<span class="sourceLineNo">473</span><a name="line.473"></a>
+<span class="sourceLineNo">474</span>  /**<a name="line.474"></a>
+<span class="sourceLineNo">475</span>   * @return the offset of the previous block of the same type in the file, or<a name="line.475"></a>
+<span class="sourceLineNo">476</span>   *         -1 if unknown<a name="line.476"></a>
+<span class="sourceLineNo">477</span>   */<a name="line.477"></a>
+<span class="sourceLineNo">478</span>  long getPrevBlockOffset() {<a name="line.478"></a>
+<span class="sourceLineNo">479</span>    return prevBlockOffset;<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>   * Rewinds {@code buf} and writes first 4 header fields. {@code buf} position<a name="line.483"></a>
+<span class="sourceLineNo">484</span>   * is modified as side-effect.<a name="line.484"></a>
+<span class="sourceLineNo">485</span>   */<a name="line.485"></a>
+<span class="sourceLineNo">486</span>  private void overwriteHeader() {<a name="line.486"></a>
+<span class="sourceLineNo">487</span>    buf.rewind();<a name="line.487"></a>
+<span class="sourceLineNo">488</span>    blockType.write(buf);<a name="line.488"></a>
+<span class="sourceLineNo">489</span>    buf.putInt(onDiskSizeWithoutHeader);<a name="line.489"></a>
+<span class="sourceLineNo">490</span>    buf.putInt(uncompressedSizeWithoutHeader);<a name="line.490"></a>
+<span class="sourceLineNo">491</span>    buf.putLong(prevBlockOffset);<a name="line.491"></a>
+<span class="sourceLineNo">492</span>    if (this.fileContext.isUseHBaseChecksum()) {<a name="line.492"></a>
+<span class="sourceLineNo">493</span>      buf.put(fileContext.getChecksumType().getCode());<a name="line.493"></a>
+<span class="sourceLineNo">494</span>      buf.putInt(fileContext.getBytesPerChecksum());<a name="line.494"></a>
+<span class="sourceLineNo">495</span>      buf.putInt(onDiskDataSizeWithHeader);<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><a name="line.498"></a>
+<span class="sourceLineNo">499</span>  /**<a name="line.499"></a>
+<span class="sourceLineNo">500</span>   * Returns a buffer that does not include the header or checksum.<a name="line.500"></a>
+<span class="sourceLineNo">501</span>   *<a name="line.501"></a>
+<span class="sourceLineNo">502</span>   * @return the buffer with header skipped and checksum omitted.<a name="line.502"></a>
+<span class="sourceLineNo">503</span>   */<a name="line.503"></a>
+<span class="sourceLineNo">504</span>  public ByteBuff getBufferWithoutHeader() {<a name="line.504"></a>
+<span class="sourceLineNo">505</span>    ByteBuff dup = getBufferReadOnly();<a name="line.505"></a>
+<span class="sourceLineNo">506</span>    // Now set it up so Buffer spans content only -- no header or no checksums.<a name="line.506"></a>
+<span class="sourceLineNo">507</span>    return dup.position(headerSize()).limit(buf.limit() - totalChecksumBytes()).slice();<a name="line.507"></a>
+<span class="sourceLineNo">508</span>  }<a name="line.508"></a>
+<span class="sourceLineNo">509</span><a name="line.509"></a>
+<span class="sourceLineNo">510</span>  /**<a name="line.510"></a>
+<span class="sourceLineNo">511</span>   * Returns a read-only duplicate of the buffer this block stores internally ready to be read.<a name="line.511"></a>
+<span class="sourceLineNo">512</span>   * Clients must not modify the buffer object though they may set position and limit on the<a name="line.512"></a>
+<span class="sourceLineNo">513</span>   * returned buffer since we pass back a duplicate. This method has to be public because it is used<a name="line.513"></a>
+<span class="sourceLineNo">514</span>   * in {@link CompoundBloomFilter} to avoid object creation on every Bloom<a name="line.514"></a>
+<span class="sourceLineNo">515</span>   * filter lookup, but has to be used with caution. Buffer holds header, block content,<a name="line.515"></a>
+<span class="sourceLineNo">516</span>   * and any follow-on checksums if present.<a name="line.516"></a>
+<span class="sourceLineNo">517</span>   *<a name="line.517"></a>
+<span class="sourceLineNo">518</span>   * @return the buffer of this block for read-only operations<a name="line.518"></a>
+<span class="sourceLineNo">519</span>   */<a name="line.519"></a>
+<span class="sourceLineNo">520</span>  public ByteBuff getBufferReadOnly() {<a name="line.520"></a>
+<span class="sourceLineNo">521</span>    // TODO: ByteBuf does not support asReadOnlyBuffer(). Fix.<a name="line.521"></a>
+<span class="sourceLineNo">522</span>    ByteBuff dup = this.buf.duplicate();<a name="line.522"></a>
+<span class="sourceLineNo">523</span>    assert dup.position() == 0;<a name="line.523"></a>
+<span class="sourceLineNo">524</span>    return dup;<a name="line.524"></a>
+<span class="sourceLineNo">525</span>  }<a name="line.525"></a>
+<span class="sourceLineNo">526</span><a name="line.526"></a>
+<span class="sourceLineNo">527</span>  @VisibleForTesting<a name="line.527"></a>
+<span class="sourceLineNo">528</span>  private void sanityCheckAssertion(long valueFromBuf, long valueFromField,<a name="line.528"></a>
+<span class="sourceLineNo">529</span>      String fieldName) throws IOException {<a name="line.529"></a>
+<span class="sourceLineNo">530</span>    if (valueFromBuf != valueFromField) {<a name="line.530"></a>
+<span class="sourceLineNo">531</span>      throw new AssertionError(fieldName + " in the buffer (" + valueFromBuf<a name="line.531"></a>
+<span class="sourceLineNo">532</span>          + ") is different from that in the field (" + valueFromField + ")");<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>  @VisibleForTesting<a name="line.536"></a>
+<span class="sourceLineNo">537</span>  private void sanityCheckAssertion(BlockType valueFromBuf, BlockType valueFromField)<a name="line.537"></a>
+<span class="sourceLineNo">538</span>      throws IOException {<a name="line.538"></a>
+<span class="sourceLineNo">539</span>    if (valueFromBuf != valueFromField) {<a name="line.539"></a>
+<span class="sourceLineNo">540</span>      throw new IOException("Block type stored in the buffer: " +<a name="line.540"></a>
+<span class="sourceLineNo">541</span>        valueFromBuf + ", block type field: " + valueFromField);<a name="line.541"></a>
+<span class="sourceLineNo">542</span>    }<a name="line.542"></a>
+<span class="sourceLineNo">543</span>  }<a name="line.543"></a>
+<span class="sourceLineNo">544</span><a name="line.544"></a>
+<span class="sourceLineNo">545</span>  /**<a name="line.545"></a>
+<span class="sourceLineNo">546</span>   * Checks if the block is internally consistent, i.e. the first<a name="line.546"></a>
+<span class="sourceLineNo">547</span>   * {@link HConstants#HFILEBLOCK_HEADER_SIZE} bytes of the buffer contain a<a name="line.547"></a>
+<span class="sourceLineNo">548</span>   * valid header consistent with the fields. Assumes a packed block structure.<a name="line.548"></a>
+<span class="sourceLineNo">549</span>   * This function is primary for testing and debugging, and is not<a name="line.549"></a>
+<span class="sourceLineNo">550</span>   * thread-safe, because it alters the internal buffer pointer.<a name="line.550"></a>
+<span class="sourceLineNo">551</span>   * Used by tests only.<a name="line.551"></a>
+<span class="sourceLineNo">552</span>   */<a name="line.552"></a>
+<span class="sourceLineNo">553</span>  @VisibleForTesting<a name="line.553"></a>
+<span class="sourceLineNo">554</span>  void sanityCheck() throws IOException {<a name="line.554"></a>
+<span class="sourceLineNo">555</span>    // Duplicate so no side-effects<a name="line.555"></a>
+<span class="sourceLineNo">556</span>    ByteBuff dup = this.buf.duplicate().rewind();<a name="line.556"></a>
+<span class="sourceLineNo">557</span>    sanityCheckAssertion(BlockType.read(dup), blockType);<a name="line.557"></a>
+<span class="sourceLineNo">558</span><a name="line.558"></a>
+<span class="sourceLineNo">559</span>    sanityCheckAssertion(dup.getInt(), onDiskSizeWithoutHeader, "onDiskSizeWithoutHeader");<a name="line.559"></a>
+<span class="sourceLineNo">560</span><a name="line.560"></a>
+<span class="sourceLineNo">561</span>    sanityCheckAssertion(dup.getInt(), uncompressedSizeWithoutHeader,<a name="line.561"></a>
+<span class="sourceLineNo">562</span>        "uncompressedSizeWithoutHeader");<a name="line.562"></a>
+<span class="sourceLineNo">563</span><a name="line.563"></a>
+<span class="sourceLineNo">564</span>    sanityCheckAssertion(dup.getLong(), prevBlockOffset, "prevBlockOffset");<a name="line.564"></a>
+<span class="sourceLineNo">565</span>    if (this.fileContext.isUseHBaseChecksum()) {<a name="line.565"></a>
+<span class="sourceLineNo">566</span>      sanityCheckAssertion(dup.get(), this.fileContext.getChecksumType().getCode(), "checksumType");<a name="line.566"></a>
+<span class="sourceLineNo">567</span>      sanityCheckAssertion(dup.getInt(), this.fileContext.getBytesPerChecksum(),<a name="line.567"></a>
+<span class="sourceLineNo">568</span>          "bytesPerChecksum");<a name="line.568"></a>
+<span class="sourceLineNo">569</span>      sanityCheckAssertion(dup.getInt(), onDiskDataSizeWithHeader, "onDiskDataSizeWithHeader");<a name="line.569"></a>
+<span class="sourceLineNo">570</span>    }<a name="line.570"></a>
+<span class="sourceLineNo">571</span><a name="line.571"></a>
+<span class="sourceLineNo">572</span>    int cksumBytes = totalChecksumBytes();<a name="line.572"></a>
+<span class="sourceLineNo">573</span>    int expectedBufLimit = onDiskDataSizeWithHeader + cksumBytes;<a name="line.573"></a>
+<span class="sourceLineNo">574</span>    if (dup.limit() != expectedBufLimit) {<a name="line.574"></a>
+<span class="sourceLineNo">575</span>      throw new AssertionError("Expected limit " + expectedBufLimit + ", got " + dup.limit());<a name="line.575"></a>
+<span class="sourceLineNo">576</span>    }<a name="line.576"></a>
+<span class="sourceLineNo">577</span><a name="line.577"></a>
+<span class="sourceLineNo">578</span>    // We might optionally allocate HFILEBLOCK_HEADER_SIZE more bytes to read the next<a name="line.578"></a>
+<span class="sourceLineNo">579</span>    // block's header, so there are two sensible values for buffer capacity.<a name="line.579"></a>
+<span class="sourceLineNo">580</span>    int hdrSize = headerSize();<a name="line.580"></a>
+<span class="sourceLineNo">581</span>    if (dup.capacity() != expectedBufLimit &amp;&amp; dup.capacity() != expectedBufLimit + hdrSize) {<a name="line.581"></a>
+<span class="sourceLineNo">582</span>      throw new AssertionError("Invalid buffer capacity: " + dup.capacity() +<a name="line.582"></a>
+<span class="sourceLineNo">583</span>          ", expected " + expectedBufLimit + " or " + (expectedBufLimit + hdrSize));<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>  @Override<a name="line.587"></a>
+<span class="sourceLineNo">588</span>  public String toString() {<a name="line.588"></a>
+<span class="sourceLineNo">589</span>    StringBuilder sb = new StringBuilder()<a name="line.589"></a>
+<span class="sourceLineNo">590</span>      .append("[")<a name="line.590"></a>
+<span class="sourceLineNo">591</span>      .append("blockType=").append(blockType)<a name="line.591"></a>
+<span class="sourceLineNo">592</span>      .append(", fileOffset=").append(offset)<a name="line.592"></a>
+<span class="sourceLineNo">593</span>      .append(", headerSize=").append(headerSize())<a name="line.593"></a>
+<span class="sourceLineNo">594</span>      .append(", onDiskSizeWithoutHeader=").append(onDiskSizeWithoutHeader)<a name="line.594"></a>
+<span class="sourceLineNo">595</span>      .append(", uncompressedSizeWithoutHeader=").append(uncompressedSizeWithoutHeader)<a name="line.595"></a>
+<span class="sourceLineNo">596</span>      .append(", prevBlockOffset=").append(prevBlockOffset)<a name="line.596"></a>
+<span class="sourceLineNo">597</span>      .append(", isUseHBaseChecksum=").append(fileContext.isUseHBaseChecksum());<a name="line.597"></a>
+<span class="sourceLineNo">598</span>    if (fileContext.isUseHBaseChecksum()) {<a name="line.598"></a>
+<span class="sourceLineNo">599</span>      sb.append(", checksumType=").append(ChecksumType.codeToType(this.buf.get(24)))<a name="line.599"></a>
+<span class="sourceLineNo">600</span>        .append(", bytesPerChecksum=").append(this.buf.getInt(24 + 1))<a name="line.600"></a>
+<span class="sourceLineNo">601</span>        .append(", onDiskDataSizeWithHeader=").append(onDiskDataSizeWithHeader);<a name="line.601"></a>
+<span class="sourceLineNo">602</span>    } else {<a name="line.602"></a>
+<span class="sourceLineNo">603</span>      sb.append(", onDiskDataSizeWithHeader=").append(onDiskDataSizeWithHeader)<a name="line.603"></a>
+<span class="sourceLineNo">604</span>        .append("(").append(onDiskSizeWithoutHeader)<a name="line.604"></a>
+<span class="sourceLineNo">605</span>        .append("+").append(HConstants.HFILEBLOCK_HEADER_SIZE_NO_CHECKSUM).append(")");<a name="line.605"></a>
+<span class="sourceLineNo">606</span>    }<a name="line.606"></a>
+<span class="sourceLineNo">607</span>    String dataBegin = null;<a name="line.607"></a>
+<span class="sourceLineNo">608</span>    if (buf.hasArray()) {<a name="line.608"></a>
+<span class="sourceLineNo">609</span>      dataBegin = Bytes.toStringBinary(buf.array(), buf.arrayOffset() + headerSize(),<a name="line.609"></a>
+<span class="sourceLineNo">610</span>          Math.min(32, buf.limit() - buf.arrayOffset() - headerSize()));<a name="line.610"></a>
+<span class="sourceLineNo">611</span>    } else {<a name="line.611"></a>
+<span class="sourceLineNo">612</span>      ByteBuff bufWithoutHeader = getBufferWithoutHeader();<a name="line.612"></a>
+<span class="sourceLineNo">613</span>      byte[] dataBeginBytes = new byte[Math.min(32,<a name="line.613"></a>
+<span class="sourceLineNo">614</span>          bufWithoutHeader.limit() - bufWithoutHeader.position())];<a name="line.614"></a>
+<span class="sourceLineNo">615</span>      bufWithoutHeader.get(dataBeginBytes);<a name="line.615"></a>
+<span class="sourceLineNo">616</span>      dataBegin = Bytes.toStringBinary(dataBeginBytes);<a name="line.616"></a>
+<span class="sourceLineNo">617</span>    }<a name="line.617"></a>
+<span class="sourceLineNo">618</span>    sb.append(", getOnDiskSizeWithHeader=").append(getOnDiskSizeWithHeader())<a name="line.618"></a>
+<span class="sourceLineNo">619</span>      .append(", totalChecksumBytes=").append(totalChecksumBytes())<a name="line.619"></a>
+<span class="sourceLineNo">620</span>      .append(", isUnpacked=").append(isUnpacked())<a name="line.620"></a>
+<span class="sourceLineNo">621</span>      .append(", buf=[").append(buf).append("]")<a name="line.621"></a>
+<span class="sourceLineNo">622</span>      .append(", dataBeginsWith=").append(dataBegin)<a name="line.622"></a>
+<span class="sourceLineNo">623</span>      .append(", fileContext=").append(fileContext)<a name="line.623"></a>
+<span class="sourceLineNo">624</span>      .append(", nextBlockOnDiskSize=").append(nextBlockOnDiskSize)<a name="line.624"></a>
+<span class="sourceLineNo">625</span>      .append("]");<a name="line.625"></a>
+<span class="sourceLineNo">626</span>    return sb.toString();<a name="line.626"></a>
+<span class="sourceLineNo">627</span>  }<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>   * Retrieves the decompressed/decrypted view of this block. An encoded block remains in its<a name="line.630"></a>
+<span class="sourceLineNo">631</span>   * encoded structure. Internal structures are shared between instances where applicable.<a name="line.631"></a>
+<span class="sourceLineNo">632</span>   */<a name="line.632"></a>
+<span class="sourceLineNo">633</span>  HFileBlock unpack(HFileContext fileContext, FSReader reader) throws IOException {<a name="line.633"></a>
+<span class="sourceLineNo">634</span>    if (!fileContext.isCompressedOrEncrypted()) {<a name="line.634"></a>
+<span class="sourceLineNo">635</span>      // TODO: cannot use our own fileContext here because HFileBlock(ByteBuffer, boolean),<a name="line.635"></a>
+<span class="sourceLineNo">636</span>      // which is used for block serialization to L2 cache, does not preserve encoding and<a name="line.636"></a>
+<span class="sourceLineNo">637</span>      // encryption details.<a name="line.637"></a>
+<span class="sourceLineNo">638</span>      return this;<a name="line.638"></a>
+<span class="sourceLineNo">639</span>    }<a name="line.639"></a>
+<span class="sourceLineNo">640</span><a name="line.640"></a>
+<span class="sourceLineNo">641</span>    HFileBlock unpacked = new HFileBlock(this);<a name="line.641"></a>
+<span class="sourceLineNo">642</span>    unpacked.allocateBuffer(); // allocates space for the decompressed block<a name="line.642"></a>
+<span class="sourceLineNo">643</span><a name="line.643"></a>
+<span class="sourceLineNo">644</span>    HFileBlockDecodingContext ctx = blockType == BlockType.ENCODED_DATA ?<a name="line.644"></a>
+<span class="sourceLineNo">645</span>      reader.getBlockDecodingContext() : reader.getDefaultBlockDecodingContext();<a name="line.645"></a>
+<span class="sourceLineNo">646</span><a name="line.646"></a>
+<span class="sourceLineNo">647</span>    ByteBuff dup = this.buf.duplicate();<a name="line.647"></a>
+<span class="sourceLineNo">648</span>    dup.position(this.headerSize());<a name="line.648"></a>
+<span class="sourceLineNo">649</span>    dup = dup.slice();<a name="line.649"></a>
+<span class="sourceLineNo">650</span>    ctx.prepareDecoding(unpacked.getOnDis

<TRUNCATED>

[21/50] hbase-site git commit: Published site at 26babcf013de696b899d76a3c39434b794440d8d.

Posted by gi...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.StatisticsThread.html
----------------------------------------------------------------------
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.StatisticsThread.html b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.StatisticsThread.html
index e8070ca..8cb24b3 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.StatisticsThread.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.StatisticsThread.html
@@ -433,1254 +433,1261 @@
 <span class="sourceLineNo">425</span>      return;<a name="line.425"></a>
 <span class="sourceLineNo">426</span>    }<a name="line.426"></a>
 <span class="sourceLineNo">427</span><a name="line.427"></a>
-<span class="sourceLineNo">428</span>    if (backingMap.containsKey(cacheKey)) {<a name="line.428"></a>
+<span class="sourceLineNo">428</span>    if (backingMap.containsKey(cacheKey) || ramCache.containsKey(cacheKey)) {<a name="line.428"></a>
 <span class="sourceLineNo">429</span>      Cacheable existingBlock = getBlock(cacheKey, false, false, false);<a name="line.429"></a>
-<span class="sourceLineNo">430</span>      try {<a name="line.430"></a>
-<span class="sourceLineNo">431</span>        if (BlockCacheUtil.compareCacheBlock(cachedItem, existingBlock) != 0) {<a name="line.431"></a>
-<span class="sourceLineNo">432</span>          throw new RuntimeException("Cached block contents differ, which should not have happened."<a name="line.432"></a>
-<span class="sourceLineNo">433</span>              + "cacheKey:" + cacheKey);<a name="line.433"></a>
-<span class="sourceLineNo">434</span>        }<a name="line.434"></a>
-<span class="sourceLineNo">435</span>        String msg = "Caching an already cached block: " + cacheKey;<a name="line.435"></a>
-<span class="sourceLineNo">436</span>        msg += ". This is harmless and can happen in rare cases (see HBASE-8547)";<a name="line.436"></a>
-<span class="sourceLineNo">437</span>        LOG.warn(msg);<a name="line.437"></a>
-<span class="sourceLineNo">438</span>      } finally {<a name="line.438"></a>
-<span class="sourceLineNo">439</span>        // return the block since we need to decrement the count<a name="line.439"></a>
-<span class="sourceLineNo">440</span>        returnBlock(cacheKey, existingBlock);<a name="line.440"></a>
-<span class="sourceLineNo">441</span>      }<a name="line.441"></a>
-<span class="sourceLineNo">442</span>      return;<a name="line.442"></a>
-<span class="sourceLineNo">443</span>    }<a name="line.443"></a>
-<span class="sourceLineNo">444</span><a name="line.444"></a>
-<span class="sourceLineNo">445</span>    /*<a name="line.445"></a>
-<span class="sourceLineNo">446</span>     * Stuff the entry into the RAM cache so it can get drained to the persistent store<a name="line.446"></a>
-<span class="sourceLineNo">447</span>     */<a name="line.447"></a>
-<span class="sourceLineNo">448</span>    RAMQueueEntry re =<a name="line.448"></a>
-<span class="sourceLineNo">449</span>        new RAMQueueEntry(cacheKey, cachedItem, accessCount.incrementAndGet(), inMemory);<a name="line.449"></a>
-<span class="sourceLineNo">450</span>    if (ramCache.putIfAbsent(cacheKey, re) != null) {<a name="line.450"></a>
-<span class="sourceLineNo">451</span>      return;<a name="line.451"></a>
-<span class="sourceLineNo">452</span>    }<a name="line.452"></a>
-<span class="sourceLineNo">453</span>    int queueNum = (cacheKey.hashCode() &amp; 0x7FFFFFFF) % writerQueues.size();<a name="line.453"></a>
-<span class="sourceLineNo">454</span>    BlockingQueue&lt;RAMQueueEntry&gt; bq = writerQueues.get(queueNum);<a name="line.454"></a>
-<span class="sourceLineNo">455</span>    boolean successfulAddition = false;<a name="line.455"></a>
-<span class="sourceLineNo">456</span>    if (wait) {<a name="line.456"></a>
-<span class="sourceLineNo">457</span>      try {<a name="line.457"></a>
-<span class="sourceLineNo">458</span>        successfulAddition = bq.offer(re, DEFAULT_CACHE_WAIT_TIME, TimeUnit.MILLISECONDS);<a name="line.458"></a>
-<span class="sourceLineNo">459</span>      } catch (InterruptedException e) {<a name="line.459"></a>
-<span class="sourceLineNo">460</span>        Thread.currentThread().interrupt();<a name="line.460"></a>
-<span class="sourceLineNo">461</span>      }<a name="line.461"></a>
-<span class="sourceLineNo">462</span>    } else {<a name="line.462"></a>
-<span class="sourceLineNo">463</span>      successfulAddition = bq.offer(re);<a name="line.463"></a>
-<span class="sourceLineNo">464</span>    }<a name="line.464"></a>
-<span class="sourceLineNo">465</span>    if (!successfulAddition) {<a name="line.465"></a>
-<span class="sourceLineNo">466</span>      ramCache.remove(cacheKey);<a name="line.466"></a>
-<span class="sourceLineNo">467</span>      cacheStats.failInsert();<a name="line.467"></a>
-<span class="sourceLineNo">468</span>    } else {<a name="line.468"></a>
-<span class="sourceLineNo">469</span>      this.blockNumber.increment();<a name="line.469"></a>
-<span class="sourceLineNo">470</span>      this.heapSize.add(cachedItem.heapSize());<a name="line.470"></a>
-<span class="sourceLineNo">471</span>      blocksByHFile.add(cacheKey);<a name="line.471"></a>
-<span class="sourceLineNo">472</span>    }<a name="line.472"></a>
-<span class="sourceLineNo">473</span>  }<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>   * Get the buffer of the block with the specified key.<a name="line.476"></a>
-<span class="sourceLineNo">477</span>   * @param key block's cache key<a name="line.477"></a>
-<span class="sourceLineNo">478</span>   * @param caching true if the caller caches blocks on cache misses<a name="line.478"></a>
-<span class="sourceLineNo">479</span>   * @param repeat Whether this is a repeat lookup for the same block<a name="line.479"></a>
-<span class="sourceLineNo">480</span>   * @param updateCacheMetrics Whether we should update cache metrics or not<a name="line.480"></a>
-<span class="sourceLineNo">481</span>   * @return buffer of specified cache key, or null if not in cache<a name="line.481"></a>
-<span class="sourceLineNo">482</span>   */<a name="line.482"></a>
-<span class="sourceLineNo">483</span>  @Override<a name="line.483"></a>
-<span class="sourceLineNo">484</span>  public Cacheable getBlock(BlockCacheKey key, boolean caching, boolean repeat,<a name="line.484"></a>
-<span class="sourceLineNo">485</span>      boolean updateCacheMetrics) {<a name="line.485"></a>
-<span class="sourceLineNo">486</span>    if (!cacheEnabled) {<a name="line.486"></a>
-<span class="sourceLineNo">487</span>      return null;<a name="line.487"></a>
-<span class="sourceLineNo">488</span>    }<a name="line.488"></a>
-<span class="sourceLineNo">489</span>    RAMQueueEntry re = ramCache.get(key);<a name="line.489"></a>
-<span class="sourceLineNo">490</span>    if (re != null) {<a name="line.490"></a>
-<span class="sourceLineNo">491</span>      if (updateCacheMetrics) {<a name="line.491"></a>
-<span class="sourceLineNo">492</span>        cacheStats.hit(caching, key.isPrimary(), key.getBlockType());<a name="line.492"></a>
-<span class="sourceLineNo">493</span>      }<a name="line.493"></a>
-<span class="sourceLineNo">494</span>      re.access(accessCount.incrementAndGet());<a name="line.494"></a>
-<span class="sourceLineNo">495</span>      return re.getData();<a name="line.495"></a>
-<span class="sourceLineNo">496</span>    }<a name="line.496"></a>
-<span class="sourceLineNo">497</span>    BucketEntry bucketEntry = backingMap.get(key);<a name="line.497"></a>
-<span class="sourceLineNo">498</span>    if (bucketEntry != null) {<a name="line.498"></a>
-<span class="sourceLineNo">499</span>      long start = System.nanoTime();<a name="line.499"></a>
-<span class="sourceLineNo">500</span>      ReentrantReadWriteLock lock = offsetLock.getLock(bucketEntry.offset());<a name="line.500"></a>
-<span class="sourceLineNo">501</span>      try {<a name="line.501"></a>
-<span class="sourceLineNo">502</span>        lock.readLock().lock();<a name="line.502"></a>
-<span class="sourceLineNo">503</span>        // We can not read here even if backingMap does contain the given key because its offset<a name="line.503"></a>
-<span class="sourceLineNo">504</span>        // maybe changed. If we lock BlockCacheKey instead of offset, then we can only check<a name="line.504"></a>
-<span class="sourceLineNo">505</span>        // existence here.<a name="line.505"></a>
-<span class="sourceLineNo">506</span>        if (bucketEntry.equals(backingMap.get(key))) {<a name="line.506"></a>
-<span class="sourceLineNo">507</span>          // TODO : change this area - should be removed after server cells and<a name="line.507"></a>
-<span class="sourceLineNo">508</span>          // 12295 are available<a name="line.508"></a>
-<span class="sourceLineNo">509</span>          int len = bucketEntry.getLength();<a name="line.509"></a>
-<span class="sourceLineNo">510</span>          if (LOG.isTraceEnabled()) {<a name="line.510"></a>
-<span class="sourceLineNo">511</span>            LOG.trace("Read offset=" + bucketEntry.offset() + ", len=" + len);<a name="line.511"></a>
-<span class="sourceLineNo">512</span>          }<a name="line.512"></a>
-<span class="sourceLineNo">513</span>          Cacheable cachedBlock = ioEngine.read(bucketEntry.offset(), len,<a name="line.513"></a>
-<span class="sourceLineNo">514</span>              bucketEntry.deserializerReference(this.deserialiserMap));<a name="line.514"></a>
-<span class="sourceLineNo">515</span>          long timeTaken = System.nanoTime() - start;<a name="line.515"></a>
-<span class="sourceLineNo">516</span>          if (updateCacheMetrics) {<a name="line.516"></a>
-<span class="sourceLineNo">517</span>            cacheStats.hit(caching, key.isPrimary(), key.getBlockType());<a name="line.517"></a>
-<span class="sourceLineNo">518</span>            cacheStats.ioHit(timeTaken);<a name="line.518"></a>
+<span class="sourceLineNo">430</span><a name="line.430"></a>
+<span class="sourceLineNo">431</span>      try {<a name="line.431"></a>
+<span class="sourceLineNo">432</span>        int comparison = BlockCacheUtil.validateBlockAddition(existingBlock, cachedItem, cacheKey);<a name="line.432"></a>
+<span class="sourceLineNo">433</span>        if (comparison != 0) {<a name="line.433"></a>
+<span class="sourceLineNo">434</span>          if (comparison &lt; 0) {<a name="line.434"></a>
+<span class="sourceLineNo">435</span>            LOG.warn("Cached block contents differ by nextBlockOnDiskSize. Keeping cached block.");<a name="line.435"></a>
+<span class="sourceLineNo">436</span>            return;<a name="line.436"></a>
+<span class="sourceLineNo">437</span>          } else {<a name="line.437"></a>
+<span class="sourceLineNo">438</span>            LOG.warn("Cached block contents differ by nextBlockOnDiskSize. Caching new block.");<a name="line.438"></a>
+<span class="sourceLineNo">439</span>          }<a name="line.439"></a>
+<span class="sourceLineNo">440</span>        } else {<a name="line.440"></a>
+<span class="sourceLineNo">441</span>          String msg = "Caching an already cached block: " + cacheKey;<a name="line.441"></a>
+<span class="sourceLineNo">442</span>          msg += ". This is harmless and can happen in rare cases (see HBASE-8547)";<a name="line.442"></a>
+<span class="sourceLineNo">443</span>          LOG.warn(msg);<a name="line.443"></a>
+<span class="sourceLineNo">444</span>          return;<a name="line.444"></a>
+<span class="sourceLineNo">445</span>        }<a name="line.445"></a>
+<span class="sourceLineNo">446</span>      } finally {<a name="line.446"></a>
+<span class="sourceLineNo">447</span>        // return the block since we need to decrement the count<a name="line.447"></a>
+<span class="sourceLineNo">448</span>        returnBlock(cacheKey, existingBlock);<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><a name="line.451"></a>
+<span class="sourceLineNo">452</span>    /*<a name="line.452"></a>
+<span class="sourceLineNo">453</span>     * Stuff the entry into the RAM cache so it can get drained to the persistent store<a name="line.453"></a>
+<span class="sourceLineNo">454</span>     */<a name="line.454"></a>
+<span class="sourceLineNo">455</span>    RAMQueueEntry re =<a name="line.455"></a>
+<span class="sourceLineNo">456</span>        new RAMQueueEntry(cacheKey, cachedItem, accessCount.incrementAndGet(), inMemory);<a name="line.456"></a>
+<span class="sourceLineNo">457</span>    if (ramCache.putIfAbsent(cacheKey, re) != null) {<a name="line.457"></a>
+<span class="sourceLineNo">458</span>      return;<a name="line.458"></a>
+<span class="sourceLineNo">459</span>    }<a name="line.459"></a>
+<span class="sourceLineNo">460</span>    int queueNum = (cacheKey.hashCode() &amp; 0x7FFFFFFF) % writerQueues.size();<a name="line.460"></a>
+<span class="sourceLineNo">461</span>    BlockingQueue&lt;RAMQueueEntry&gt; bq = writerQueues.get(queueNum);<a name="line.461"></a>
+<span class="sourceLineNo">462</span>    boolean successfulAddition = false;<a name="line.462"></a>
+<span class="sourceLineNo">463</span>    if (wait) {<a name="line.463"></a>
+<span class="sourceLineNo">464</span>      try {<a name="line.464"></a>
+<span class="sourceLineNo">465</span>        successfulAddition = bq.offer(re, DEFAULT_CACHE_WAIT_TIME, TimeUnit.MILLISECONDS);<a name="line.465"></a>
+<span class="sourceLineNo">466</span>      } catch (InterruptedException e) {<a name="line.466"></a>
+<span class="sourceLineNo">467</span>        Thread.currentThread().interrupt();<a name="line.467"></a>
+<span class="sourceLineNo">468</span>      }<a name="line.468"></a>
+<span class="sourceLineNo">469</span>    } else {<a name="line.469"></a>
+<span class="sourceLineNo">470</span>      successfulAddition = bq.offer(re);<a name="line.470"></a>
+<span class="sourceLineNo">471</span>    }<a name="line.471"></a>
+<span class="sourceLineNo">472</span>    if (!successfulAddition) {<a name="line.472"></a>
+<span class="sourceLineNo">473</span>      ramCache.remove(cacheKey);<a name="line.473"></a>
+<span class="sourceLineNo">474</span>      cacheStats.failInsert();<a name="line.474"></a>
+<span class="sourceLineNo">475</span>    } else {<a name="line.475"></a>
+<span class="sourceLineNo">476</span>      this.blockNumber.increment();<a name="line.476"></a>
+<span class="sourceLineNo">477</span>      this.heapSize.add(cachedItem.heapSize());<a name="line.477"></a>
+<span class="sourceLineNo">478</span>      blocksByHFile.add(cacheKey);<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>  /**<a name="line.482"></a>
+<span class="sourceLineNo">483</span>   * Get the buffer of the block with the specified key.<a name="line.483"></a>
+<span class="sourceLineNo">484</span>   * @param key block's cache key<a name="line.484"></a>
+<span class="sourceLineNo">485</span>   * @param caching true if the caller caches blocks on cache misses<a name="line.485"></a>
+<span class="sourceLineNo">486</span>   * @param repeat Whether this is a repeat lookup for the same block<a name="line.486"></a>
+<span class="sourceLineNo">487</span>   * @param updateCacheMetrics Whether we should update cache metrics or not<a name="line.487"></a>
+<span class="sourceLineNo">488</span>   * @return buffer of specified cache key, or null if not in cache<a name="line.488"></a>
+<span class="sourceLineNo">489</span>   */<a name="line.489"></a>
+<span class="sourceLineNo">490</span>  @Override<a name="line.490"></a>
+<span class="sourceLineNo">491</span>  public Cacheable getBlock(BlockCacheKey key, boolean caching, boolean repeat,<a name="line.491"></a>
+<span class="sourceLineNo">492</span>      boolean updateCacheMetrics) {<a name="line.492"></a>
+<span class="sourceLineNo">493</span>    if (!cacheEnabled) {<a name="line.493"></a>
+<span class="sourceLineNo">494</span>      return null;<a name="line.494"></a>
+<span class="sourceLineNo">495</span>    }<a name="line.495"></a>
+<span class="sourceLineNo">496</span>    RAMQueueEntry re = ramCache.get(key);<a name="line.496"></a>
+<span class="sourceLineNo">497</span>    if (re != null) {<a name="line.497"></a>
+<span class="sourceLineNo">498</span>      if (updateCacheMetrics) {<a name="line.498"></a>
+<span class="sourceLineNo">499</span>        cacheStats.hit(caching, key.isPrimary(), key.getBlockType());<a name="line.499"></a>
+<span class="sourceLineNo">500</span>      }<a name="line.500"></a>
+<span class="sourceLineNo">501</span>      re.access(accessCount.incrementAndGet());<a name="line.501"></a>
+<span class="sourceLineNo">502</span>      return re.getData();<a name="line.502"></a>
+<span class="sourceLineNo">503</span>    }<a name="line.503"></a>
+<span class="sourceLineNo">504</span>    BucketEntry bucketEntry = backingMap.get(key);<a name="line.504"></a>
+<span class="sourceLineNo">505</span>    if (bucketEntry != null) {<a name="line.505"></a>
+<span class="sourceLineNo">506</span>      long start = System.nanoTime();<a name="line.506"></a>
+<span class="sourceLineNo">507</span>      ReentrantReadWriteLock lock = offsetLock.getLock(bucketEntry.offset());<a name="line.507"></a>
+<span class="sourceLineNo">508</span>      try {<a name="line.508"></a>
+<span class="sourceLineNo">509</span>        lock.readLock().lock();<a name="line.509"></a>
+<span class="sourceLineNo">510</span>        // We can not read here even if backingMap does contain the given key because its offset<a name="line.510"></a>
+<span class="sourceLineNo">511</span>        // maybe changed. If we lock BlockCacheKey instead of offset, then we can only check<a name="line.511"></a>
+<span class="sourceLineNo">512</span>        // existence here.<a name="line.512"></a>
+<span class="sourceLineNo">513</span>        if (bucketEntry.equals(backingMap.get(key))) {<a name="line.513"></a>
+<span class="sourceLineNo">514</span>          // TODO : change this area - should be removed after server cells and<a name="line.514"></a>
+<span class="sourceLineNo">515</span>          // 12295 are available<a name="line.515"></a>
+<span class="sourceLineNo">516</span>          int len = bucketEntry.getLength();<a name="line.516"></a>
+<span class="sourceLineNo">517</span>          if (LOG.isTraceEnabled()) {<a name="line.517"></a>
+<span class="sourceLineNo">518</span>            LOG.trace("Read offset=" + bucketEntry.offset() + ", len=" + len);<a name="line.518"></a>
 <span class="sourceLineNo">519</span>          }<a name="line.519"></a>
-<span class="sourceLineNo">520</span>          if (cachedBlock.getMemoryType() == MemoryType.SHARED) {<a name="line.520"></a>
-<span class="sourceLineNo">521</span>            bucketEntry.incrementRefCountAndGet();<a name="line.521"></a>
-<span class="sourceLineNo">522</span>          }<a name="line.522"></a>
-<span class="sourceLineNo">523</span>          bucketEntry.access(accessCount.incrementAndGet());<a name="line.523"></a>
-<span class="sourceLineNo">524</span>          if (this.ioErrorStartTime &gt; 0) {<a name="line.524"></a>
-<span class="sourceLineNo">525</span>            ioErrorStartTime = -1;<a name="line.525"></a>
+<span class="sourceLineNo">520</span>          Cacheable cachedBlock = ioEngine.read(bucketEntry.offset(), len,<a name="line.520"></a>
+<span class="sourceLineNo">521</span>              bucketEntry.deserializerReference(this.deserialiserMap));<a name="line.521"></a>
+<span class="sourceLineNo">522</span>          long timeTaken = System.nanoTime() - start;<a name="line.522"></a>
+<span class="sourceLineNo">523</span>          if (updateCacheMetrics) {<a name="line.523"></a>
+<span class="sourceLineNo">524</span>            cacheStats.hit(caching, key.isPrimary(), key.getBlockType());<a name="line.524"></a>
+<span class="sourceLineNo">525</span>            cacheStats.ioHit(timeTaken);<a name="line.525"></a>
 <span class="sourceLineNo">526</span>          }<a name="line.526"></a>
-<span class="sourceLineNo">527</span>          return cachedBlock;<a name="line.527"></a>
-<span class="sourceLineNo">528</span>        }<a name="line.528"></a>
-<span class="sourceLineNo">529</span>      } catch (IOException ioex) {<a name="line.529"></a>
-<span class="sourceLineNo">530</span>        LOG.error("Failed reading block " + key + " from bucket cache", ioex);<a name="line.530"></a>
-<span class="sourceLineNo">531</span>        checkIOErrorIsTolerated();<a name="line.531"></a>
-<span class="sourceLineNo">532</span>      } finally {<a name="line.532"></a>
-<span class="sourceLineNo">533</span>        lock.readLock().unlock();<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>    if (!repeat &amp;&amp; updateCacheMetrics) {<a name="line.536"></a>
-<span class="sourceLineNo">537</span>      cacheStats.miss(caching, key.isPrimary(), key.getBlockType());<a name="line.537"></a>
-<span class="sourceLineNo">538</span>    }<a name="line.538"></a>
-<span class="sourceLineNo">539</span>    return null;<a name="line.539"></a>
-<span class="sourceLineNo">540</span>  }<a name="line.540"></a>
-<span class="sourceLineNo">541</span><a name="line.541"></a>
-<span class="sourceLineNo">542</span>  @VisibleForTesting<a name="line.542"></a>
-<span class="sourceLineNo">543</span>  void blockEvicted(BlockCacheKey cacheKey, BucketEntry bucketEntry, boolean decrementBlockNumber) {<a name="line.543"></a>
-<span class="sourceLineNo">544</span>    bucketAllocator.freeBlock(bucketEntry.offset());<a name="line.544"></a>
-<span class="sourceLineNo">545</span>    realCacheSize.add(-1 * bucketEntry.getLength());<a name="line.545"></a>
-<span class="sourceLineNo">546</span>    blocksByHFile.remove(cacheKey);<a name="line.546"></a>
-<span class="sourceLineNo">547</span>    if (decrementBlockNumber) {<a name="line.547"></a>
-<span class="sourceLineNo">548</span>      this.blockNumber.decrement();<a name="line.548"></a>
-<span class="sourceLineNo">549</span>    }<a name="line.549"></a>
-<span class="sourceLineNo">550</span>  }<a name="line.550"></a>
-<span class="sourceLineNo">551</span><a name="line.551"></a>
-<span class="sourceLineNo">552</span>  @Override<a name="line.552"></a>
-<span class="sourceLineNo">553</span>  public boolean evictBlock(BlockCacheKey cacheKey) {<a name="line.553"></a>
-<span class="sourceLineNo">554</span>    return evictBlock(cacheKey, true);<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>  // does not check for the ref count. Just tries to evict it if found in the<a name="line.557"></a>
-<span class="sourceLineNo">558</span>  // bucket map<a name="line.558"></a>
-<span class="sourceLineNo">559</span>  private boolean forceEvict(BlockCacheKey cacheKey) {<a name="line.559"></a>
-<span class="sourceLineNo">560</span>    if (!cacheEnabled) {<a name="line.560"></a>
-<span class="sourceLineNo">561</span>      return false;<a name="line.561"></a>
-<span class="sourceLineNo">562</span>    }<a name="line.562"></a>
-<span class="sourceLineNo">563</span>    RAMQueueEntry removedBlock = checkRamCache(cacheKey);<a name="line.563"></a>
-<span class="sourceLineNo">564</span>    BucketEntry bucketEntry = backingMap.get(cacheKey);<a name="line.564"></a>
-<span class="sourceLineNo">565</span>    if (bucketEntry == null) {<a name="line.565"></a>
-<span class="sourceLineNo">566</span>      if (removedBlock != null) {<a name="line.566"></a>
-<span class="sourceLineNo">567</span>        cacheStats.evicted(0, cacheKey.isPrimary());<a name="line.567"></a>
-<span class="sourceLineNo">568</span>        return true;<a name="line.568"></a>
-<span class="sourceLineNo">569</span>      } else {<a name="line.569"></a>
-<span class="sourceLineNo">570</span>        return false;<a name="line.570"></a>
-<span class="sourceLineNo">571</span>      }<a name="line.571"></a>
-<span class="sourceLineNo">572</span>    }<a name="line.572"></a>
-<span class="sourceLineNo">573</span>    ReentrantReadWriteLock lock = offsetLock.getLock(bucketEntry.offset());<a name="line.573"></a>
-<span class="sourceLineNo">574</span>    try {<a name="line.574"></a>
-<span class="sourceLineNo">575</span>      lock.writeLock().lock();<a name="line.575"></a>
-<span class="sourceLineNo">576</span>      if (backingMap.remove(cacheKey, bucketEntry)) {<a name="line.576"></a>
-<span class="sourceLineNo">577</span>        blockEvicted(cacheKey, bucketEntry, removedBlock == null);<a name="line.577"></a>
-<span class="sourceLineNo">578</span>      } else {<a name="line.578"></a>
-<span class="sourceLineNo">579</span>        return false;<a name="line.579"></a>
-<span class="sourceLineNo">580</span>      }<a name="line.580"></a>
-<span class="sourceLineNo">581</span>    } finally {<a name="line.581"></a>
-<span class="sourceLineNo">582</span>      lock.writeLock().unlock();<a name="line.582"></a>
-<span class="sourceLineNo">583</span>    }<a name="line.583"></a>
-<span class="sourceLineNo">584</span>    cacheStats.evicted(bucketEntry.getCachedTime(), cacheKey.isPrimary());<a name="line.584"></a>
-<span class="sourceLineNo">585</span>    return true;<a name="line.585"></a>
-<span class="sourceLineNo">586</span>  }<a name="line.586"></a>
-<span class="sourceLineNo">587</span><a name="line.587"></a>
-<span class="sourceLineNo">588</span>  private RAMQueueEntry checkRamCache(BlockCacheKey cacheKey) {<a name="line.588"></a>
-<span class="sourceLineNo">589</span>    RAMQueueEntry removedBlock = ramCache.remove(cacheKey);<a name="line.589"></a>
-<span class="sourceLineNo">590</span>    if (removedBlock != null) {<a name="line.590"></a>
-<span class="sourceLineNo">591</span>      this.blockNumber.decrement();<a name="line.591"></a>
-<span class="sourceLineNo">592</span>      this.heapSize.add(-1 * removedBlock.getData().heapSize());<a name="line.592"></a>
-<span class="sourceLineNo">593</span>    }<a name="line.593"></a>
-<span class="sourceLineNo">594</span>    return removedBlock;<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>  public boolean evictBlock(BlockCacheKey cacheKey, boolean deletedBlock) {<a name="line.597"></a>
-<span class="sourceLineNo">598</span>    if (!cacheEnabled) {<a name="line.598"></a>
-<span class="sourceLineNo">599</span>      return false;<a name="line.599"></a>
+<span class="sourceLineNo">527</span>          if (cachedBlock.getMemoryType() == MemoryType.SHARED) {<a name="line.527"></a>
+<span class="sourceLineNo">528</span>            bucketEntry.incrementRefCountAndGet();<a name="line.528"></a>
+<span class="sourceLineNo">529</span>          }<a name="line.529"></a>
+<span class="sourceLineNo">530</span>          bucketEntry.access(accessCount.incrementAndGet());<a name="line.530"></a>
+<span class="sourceLineNo">531</span>          if (this.ioErrorStartTime &gt; 0) {<a name="line.531"></a>
+<span class="sourceLineNo">532</span>            ioErrorStartTime = -1;<a name="line.532"></a>
+<span class="sourceLineNo">533</span>          }<a name="line.533"></a>
+<span class="sourceLineNo">534</span>          return cachedBlock;<a name="line.534"></a>
+<span class="sourceLineNo">535</span>        }<a name="line.535"></a>
+<span class="sourceLineNo">536</span>      } catch (IOException ioex) {<a name="line.536"></a>
+<span class="sourceLineNo">537</span>        LOG.error("Failed reading block " + key + " from bucket cache", ioex);<a name="line.537"></a>
+<span class="sourceLineNo">538</span>        checkIOErrorIsTolerated();<a name="line.538"></a>
+<span class="sourceLineNo">539</span>      } finally {<a name="line.539"></a>
+<span class="sourceLineNo">540</span>        lock.readLock().unlock();<a name="line.540"></a>
+<span class="sourceLineNo">541</span>      }<a name="line.541"></a>
+<span class="sourceLineNo">542</span>    }<a name="line.542"></a>
+<span class="sourceLineNo">543</span>    if (!repeat &amp;&amp; updateCacheMetrics) {<a name="line.543"></a>
+<span class="sourceLineNo">544</span>      cacheStats.miss(caching, key.isPrimary(), key.getBlockType());<a name="line.544"></a>
+<span class="sourceLineNo">545</span>    }<a name="line.545"></a>
+<span class="sourceLineNo">546</span>    return null;<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>  @VisibleForTesting<a name="line.549"></a>
+<span class="sourceLineNo">550</span>  void blockEvicted(BlockCacheKey cacheKey, BucketEntry bucketEntry, boolean decrementBlockNumber) {<a name="line.550"></a>
+<span class="sourceLineNo">551</span>    bucketAllocator.freeBlock(bucketEntry.offset());<a name="line.551"></a>
+<span class="sourceLineNo">552</span>    realCacheSize.add(-1 * bucketEntry.getLength());<a name="line.552"></a>
+<span class="sourceLineNo">553</span>    blocksByHFile.remove(cacheKey);<a name="line.553"></a>
+<span class="sourceLineNo">554</span>    if (decrementBlockNumber) {<a name="line.554"></a>
+<span class="sourceLineNo">555</span>      this.blockNumber.decrement();<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>  @Override<a name="line.559"></a>
+<span class="sourceLineNo">560</span>  public boolean evictBlock(BlockCacheKey cacheKey) {<a name="line.560"></a>
+<span class="sourceLineNo">561</span>    return evictBlock(cacheKey, true);<a name="line.561"></a>
+<span class="sourceLineNo">562</span>  }<a name="line.562"></a>
+<span class="sourceLineNo">563</span><a name="line.563"></a>
+<span class="sourceLineNo">564</span>  // does not check for the ref count. Just tries to evict it if found in the<a name="line.564"></a>
+<span class="sourceLineNo">565</span>  // bucket map<a name="line.565"></a>
+<span class="sourceLineNo">566</span>  private boolean forceEvict(BlockCacheKey cacheKey) {<a name="line.566"></a>
+<span class="sourceLineNo">567</span>    if (!cacheEnabled) {<a name="line.567"></a>
+<span class="sourceLineNo">568</span>      return false;<a name="line.568"></a>
+<span class="sourceLineNo">569</span>    }<a name="line.569"></a>
+<span class="sourceLineNo">570</span>    RAMQueueEntry removedBlock = checkRamCache(cacheKey);<a name="line.570"></a>
+<span class="sourceLineNo">571</span>    BucketEntry bucketEntry = backingMap.get(cacheKey);<a name="line.571"></a>
+<span class="sourceLineNo">572</span>    if (bucketEntry == null) {<a name="line.572"></a>
+<span class="sourceLineNo">573</span>      if (removedBlock != null) {<a name="line.573"></a>
+<span class="sourceLineNo">574</span>        cacheStats.evicted(0, cacheKey.isPrimary());<a name="line.574"></a>
+<span class="sourceLineNo">575</span>        return true;<a name="line.575"></a>
+<span class="sourceLineNo">576</span>      } else {<a name="line.576"></a>
+<span class="sourceLineNo">577</span>        return false;<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>    ReentrantReadWriteLock lock = offsetLock.getLock(bucketEntry.offset());<a name="line.580"></a>
+<span class="sourceLineNo">581</span>    try {<a name="line.581"></a>
+<span class="sourceLineNo">582</span>      lock.writeLock().lock();<a name="line.582"></a>
+<span class="sourceLineNo">583</span>      if (backingMap.remove(cacheKey, bucketEntry)) {<a name="line.583"></a>
+<span class="sourceLineNo">584</span>        blockEvicted(cacheKey, bucketEntry, removedBlock == null);<a name="line.584"></a>
+<span class="sourceLineNo">585</span>      } else {<a name="line.585"></a>
+<span class="sourceLineNo">586</span>        return false;<a name="line.586"></a>
+<span class="sourceLineNo">587</span>      }<a name="line.587"></a>
+<span class="sourceLineNo">588</span>    } finally {<a name="line.588"></a>
+<span class="sourceLineNo">589</span>      lock.writeLock().unlock();<a name="line.589"></a>
+<span class="sourceLineNo">590</span>    }<a name="line.590"></a>
+<span class="sourceLineNo">591</span>    cacheStats.evicted(bucketEntry.getCachedTime(), cacheKey.isPrimary());<a name="line.591"></a>
+<span class="sourceLineNo">592</span>    return true;<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>  private RAMQueueEntry checkRamCache(BlockCacheKey cacheKey) {<a name="line.595"></a>
+<span class="sourceLineNo">596</span>    RAMQueueEntry removedBlock = ramCache.remove(cacheKey);<a name="line.596"></a>
+<span class="sourceLineNo">597</span>    if (removedBlock != null) {<a name="line.597"></a>
+<span class="sourceLineNo">598</span>      this.blockNumber.decrement();<a name="line.598"></a>
+<span class="sourceLineNo">599</span>      this.heapSize.add(-1 * removedBlock.getData().heapSize());<a name="line.599"></a>
 <span class="sourceLineNo">600</span>    }<a name="line.600"></a>
-<span class="sourceLineNo">601</span>    RAMQueueEntry removedBlock = checkRamCache(cacheKey);<a name="line.601"></a>
-<span class="sourceLineNo">602</span>    BucketEntry bucketEntry = backingMap.get(cacheKey);<a name="line.602"></a>
-<span class="sourceLineNo">603</span>    if (bucketEntry == null) {<a name="line.603"></a>
-<span class="sourceLineNo">604</span>      if (removedBlock != null) {<a name="line.604"></a>
-<span class="sourceLineNo">605</span>        cacheStats.evicted(0, cacheKey.isPrimary());<a name="line.605"></a>
-<span class="sourceLineNo">606</span>        return true;<a name="line.606"></a>
-<span class="sourceLineNo">607</span>      } else {<a name="line.607"></a>
-<span class="sourceLineNo">608</span>        return false;<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>    ReentrantReadWriteLock lock = offsetLock.getLock(bucketEntry.offset());<a name="line.611"></a>
-<span class="sourceLineNo">612</span>    try {<a name="line.612"></a>
-<span class="sourceLineNo">613</span>      lock.writeLock().lock();<a name="line.613"></a>
-<span class="sourceLineNo">614</span>      int refCount = bucketEntry.getRefCount();<a name="line.614"></a>
-<span class="sourceLineNo">615</span>      if (refCount == 0) {<a name="line.615"></a>
-<span class="sourceLineNo">616</span>        if (backingMap.remove(cacheKey, bucketEntry)) {<a name="line.616"></a>
-<span class="sourceLineNo">617</span>          blockEvicted(cacheKey, bucketEntry, removedBlock == null);<a name="line.617"></a>
-<span class="sourceLineNo">618</span>        } else {<a name="line.618"></a>
-<span class="sourceLineNo">619</span>          return false;<a name="line.619"></a>
-<span class="sourceLineNo">620</span>        }<a name="line.620"></a>
-<span class="sourceLineNo">621</span>      } else {<a name="line.621"></a>
-<span class="sourceLineNo">622</span>        if(!deletedBlock) {<a name="line.622"></a>
-<span class="sourceLineNo">623</span>          if (LOG.isDebugEnabled()) {<a name="line.623"></a>
-<span class="sourceLineNo">624</span>            LOG.debug("This block " + cacheKey + " is still referred by " + refCount<a name="line.624"></a>
-<span class="sourceLineNo">625</span>                + " readers. Can not be freed now");<a name="line.625"></a>
-<span class="sourceLineNo">626</span>          }<a name="line.626"></a>
-<span class="sourceLineNo">627</span>          return false;<a name="line.627"></a>
-<span class="sourceLineNo">628</span>        } else {<a name="line.628"></a>
-<span class="sourceLineNo">629</span>          if (LOG.isDebugEnabled()) {<a name="line.629"></a>
-<span class="sourceLineNo">630</span>            LOG.debug("This block " + cacheKey + " is still referred by " + refCount<a name="line.630"></a>
-<span class="sourceLineNo">631</span>                + " readers. Can not be freed now. Hence will mark this"<a name="line.631"></a>
-<span class="sourceLineNo">632</span>                + " for evicting at a later point");<a name="line.632"></a>
+<span class="sourceLineNo">601</span>    return removedBlock;<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>  public boolean evictBlock(BlockCacheKey cacheKey, boolean deletedBlock) {<a name="line.604"></a>
+<span class="sourceLineNo">605</span>    if (!cacheEnabled) {<a name="line.605"></a>
+<span class="sourceLineNo">606</span>      return false;<a name="line.606"></a>
+<span class="sourceLineNo">607</span>    }<a name="line.607"></a>
+<span class="sourceLineNo">608</span>    RAMQueueEntry removedBlock = checkRamCache(cacheKey);<a name="line.608"></a>
+<span class="sourceLineNo">609</span>    BucketEntry bucketEntry = backingMap.get(cacheKey);<a name="line.609"></a>
+<span class="sourceLineNo">610</span>    if (bucketEntry == null) {<a name="line.610"></a>
+<span class="sourceLineNo">611</span>      if (removedBlock != null) {<a name="line.611"></a>
+<span class="sourceLineNo">612</span>        cacheStats.evicted(0, cacheKey.isPrimary());<a name="line.612"></a>
+<span class="sourceLineNo">613</span>        return true;<a name="line.613"></a>
+<span class="sourceLineNo">614</span>      } else {<a name="line.614"></a>
+<span class="sourceLineNo">615</span>        return false;<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>    ReentrantReadWriteLock lock = offsetLock.getLock(bucketEntry.offset());<a name="line.618"></a>
+<span class="sourceLineNo">619</span>    try {<a name="line.619"></a>
+<span class="sourceLineNo">620</span>      lock.writeLock().lock();<a name="line.620"></a>
+<span class="sourceLineNo">621</span>      int refCount = bucketEntry.getRefCount();<a name="line.621"></a>
+<span class="sourceLineNo">622</span>      if (refCount == 0) {<a name="line.622"></a>
+<span class="sourceLineNo">623</span>        if (backingMap.remove(cacheKey, bucketEntry)) {<a name="line.623"></a>
+<span class="sourceLineNo">624</span>          blockEvicted(cacheKey, bucketEntry, removedBlock == null);<a name="line.624"></a>
+<span class="sourceLineNo">625</span>        } else {<a name="line.625"></a>
+<span class="sourceLineNo">626</span>          return false;<a name="line.626"></a>
+<span class="sourceLineNo">627</span>        }<a name="line.627"></a>
+<span class="sourceLineNo">628</span>      } else {<a name="line.628"></a>
+<span class="sourceLineNo">629</span>        if(!deletedBlock) {<a name="line.629"></a>
+<span class="sourceLineNo">630</span>          if (LOG.isDebugEnabled()) {<a name="line.630"></a>
+<span class="sourceLineNo">631</span>            LOG.debug("This block " + cacheKey + " is still referred by " + refCount<a name="line.631"></a>
+<span class="sourceLineNo">632</span>                + " readers. Can not be freed now");<a name="line.632"></a>
 <span class="sourceLineNo">633</span>          }<a name="line.633"></a>
-<span class="sourceLineNo">634</span>          bucketEntry.markForEvict();<a name="line.634"></a>
-<span class="sourceLineNo">635</span>        }<a name="line.635"></a>
-<span class="sourceLineNo">636</span>      }<a name="line.636"></a>
-<span class="sourceLineNo">637</span>    } finally {<a name="line.637"></a>
-<span class="sourceLineNo">638</span>      lock.writeLock().unlock();<a name="line.638"></a>
-<span class="sourceLineNo">639</span>    }<a name="line.639"></a>
-<span class="sourceLineNo">640</span>    cacheStats.evicted(bucketEntry.getCachedTime(), cacheKey.isPrimary());<a name="line.640"></a>
-<span class="sourceLineNo">641</span>    return true;<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>   * Statistics thread.  Periodically output cache statistics to the log.<a name="line.645"></a>
-<span class="sourceLineNo">646</span>   */<a name="line.646"></a>
-<span class="sourceLineNo">647</span>  private static class StatisticsThread extends Thread {<a name="line.647"></a>
-<span class="sourceLineNo">648</span>    private final BucketCache bucketCache;<a name="line.648"></a>
-<span class="sourceLineNo">649</span><a name="line.649"></a>
-<span class="sourceLineNo">650</span>    public StatisticsThread(BucketCache bucketCache) {<a name="line.650"></a>
-<span class="sourceLineNo">651</span>      super("BucketCacheStatsThread");<a name="line.651"></a>
-<span class="sourceLineNo">652</span>      setDaemon(true);<a name="line.652"></a>
-<span class="sourceLineNo">653</span>      this.bucketCache = bucketCache;<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 void run() {<a name="line.657"></a>
-<span class="sourceLineNo">658</span>      bucketCache.logStats();<a name="line.658"></a>
-<span class="sourceLineNo">659</span>    }<a name="line.659"></a>
-<span class="sourceLineNo">660</span>  }<a name="line.660"></a>
-<span class="sourceLineNo">661</span><a name="line.661"></a>
-<span class="sourceLineNo">662</span>  public void logStats() {<a name="line.662"></a>
-<span class="sourceLineNo">663</span>    long totalSize = bucketAllocator.getTotalSize();<a name="line.663"></a>
-<span class="sourceLineNo">664</span>    long usedSize = bucketAllocator.getUsedSize();<a name="line.664"></a>
-<span class="sourceLineNo">665</span>    long freeSize = totalSize - usedSize;<a name="line.665"></a>
-<span class="sourceLineNo">666</span>    long cacheSize = getRealCacheSize();<a name="line.666"></a>
-<span class="sourceLineNo">667</span>    LOG.info("failedBlockAdditions=" + cacheStats.getFailedInserts() + ", " +<a name="line.667"></a>
-<span class="sourceLineNo">668</span>        "totalSize=" + StringUtils.byteDesc(totalSize) + ", " +<a name="line.668"></a>
-<span class="sourceLineNo">669</span>        "freeSize=" + StringUtils.byteDesc(freeSize) + ", " +<a name="line.669"></a>
-<span class="sourceLineNo">670</span>        "usedSize=" + StringUtils.byteDesc(usedSize) +", " +<a name="line.670"></a>
-<span class="sourceLineNo">671</span>        "cacheSize=" + StringUtils.byteDesc(cacheSize) +", " +<a name="line.671"></a>
-<span class="sourceLineNo">672</span>        "accesses=" + cacheStats.getRequestCount() + ", " +<a name="line.672"></a>
-<span class="sourceLineNo">673</span>        "hits=" + cacheStats.getHitCount() + ", " +<a name="line.673"></a>
-<span class="sourceLineNo">674</span>        "IOhitsPerSecond=" + cacheStats.getIOHitsPerSecond() + ", " +<a name="line.674"></a>
-<span class="sourceLineNo">675</span>        "IOTimePerHit=" + String.format("%.2f", cacheStats.getIOTimePerHit())+ ", " +<a name="line.675"></a>
-<span class="sourceLineNo">676</span>        "hitRatio=" + (cacheStats.getHitCount() == 0 ? "0," :<a name="line.676"></a>
-<span class="sourceLineNo">677</span>          (StringUtils.formatPercent(cacheStats.getHitRatio(), 2)+ ", ")) +<a name="line.677"></a>
-<span class="sourceLineNo">678</span>        "cachingAccesses=" + cacheStats.getRequestCachingCount() + ", " +<a name="line.678"></a>
-<span class="sourceLineNo">679</span>        "cachingHits=" + cacheStats.getHitCachingCount() + ", " +<a name="line.679"></a>
-<span class="sourceLineNo">680</span>        "cachingHitsRatio=" +(cacheStats.getHitCachingCount() == 0 ? "0," :<a name="line.680"></a>
-<span class="sourceLineNo">681</span>          (StringUtils.formatPercent(cacheStats.getHitCachingRatio(), 2)+ ", ")) +<a name="line.681"></a>
-<span class="sourceLineNo">682</span>        "evictions=" + cacheStats.getEvictionCount() + ", " +<a name="line.682"></a>
-<span class="sourceLineNo">683</span>        "evicted=" + cacheStats.getEvictedCount() + ", " +<a name="line.683"></a>
-<span class="sourceLineNo">684</span>        "evictedPerRun=" + cacheStats.evictedPerEviction());<a name="line.684"></a>
-<span class="sourceLineNo">685</span>    cacheStats.reset();<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>  public long getRealCacheSize() {<a name="line.688"></a>
-<span class="sourceLineNo">689</span>    return this.realCacheSize.sum();<a name="line.689"></a>
-<span class="sourceLineNo">690</span>  }<a name="line.690"></a>
-<span class="sourceLineNo">691</span><a name="line.691"></a>
-<span class="sourceLineNo">692</span>  private long acceptableSize() {<a name="line.692"></a>
-<span class="sourceLineNo">693</span>    return (long) Math.floor(bucketAllocator.getTotalSize() * acceptableFactor);<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>  @VisibleForTesting<a name="line.696"></a>
-<span class="sourceLineNo">697</span>  long getPartitionSize(float partitionFactor) {<a name="line.697"></a>
-<span class="sourceLineNo">698</span>    return (long) Math.floor(bucketAllocator.getTotalSize() * partitionFactor * minFactor);<a name="line.698"></a>
-<span class="sourceLineNo">699</span>  }<a name="line.699"></a>
-<span class="sourceLineNo">700</span><a name="line.700"></a>
-<span class="sourceLineNo">701</span>  /**<a name="line.701"></a>
-<span class="sourceLineNo">702</span>   * Return the count of bucketSizeinfos still need free space<a name="line.702"></a>
-<span class="sourceLineNo">703</span>   */<a name="line.703"></a>
-<span class="sourceLineNo">704</span>  private int bucketSizesAboveThresholdCount(float minFactor) {<a name="line.704"></a>
-<span class="sourceLineNo">705</span>    BucketAllocator.IndexStatistics[] stats = bucketAllocator.getIndexStatistics();<a name="line.705"></a>
-<span class="sourceLineNo">706</span>    int fullCount = 0;<a name="line.706"></a>
-<span class="sourceLineNo">707</span>    for (int i = 0; i &lt; stats.length; i++) {<a name="line.707"></a>
-<span class="sourceLineNo">708</span>      long freeGoal = (long) Math.floor(stats[i].totalCount() * (1 - minFactor));<a name="line.708"></a>
-<span class="sourceLineNo">709</span>      freeGoal = Math.max(freeGoal, 1);<a name="line.709"></a>
-<span class="sourceLineNo">710</span>      if (stats[i].freeCount() &lt; freeGoal) {<a name="line.710"></a>
-<span class="sourceLineNo">711</span>        fullCount++;<a name="line.711"></a>
-<span class="sourceLineNo">712</span>      }<a name="line.712"></a>
-<span class="sourceLineNo">713</span>    }<a name="line.713"></a>
-<span class="sourceLineNo">714</span>    return fullCount;<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">717</span>  /**<a name="line.717"></a>
-<span class="sourceLineNo">718</span>   * This method will find the buckets that are minimally occupied<a name="line.718"></a>
-<span class="sourceLineNo">719</span>   * and are not reference counted and will free them completely<a name="line.719"></a>
-<span class="sourceLineNo">720</span>   * without any constraint on the access times of the elements,<a name="line.720"></a>
-<span class="sourceLineNo">721</span>   * and as a process will completely free at most the number of buckets<a name="line.721"></a>
-<span class="sourceLineNo">722</span>   * passed, sometimes it might not due to changing refCounts<a name="line.722"></a>
-<span class="sourceLineNo">723</span>   *<a name="line.723"></a>
-<span class="sourceLineNo">724</span>   * @param completelyFreeBucketsNeeded number of buckets to free<a name="line.724"></a>
-<span class="sourceLineNo">725</span>   **/<a name="line.725"></a>
-<span class="sourceLineNo">726</span>  private void freeEntireBuckets(int completelyFreeBucketsNeeded) {<a name="line.726"></a>
-<span class="sourceLineNo">727</span>    if (completelyFreeBucketsNeeded != 0) {<a name="line.727"></a>
-<span class="sourceLineNo">728</span>      // First we will build a set where the offsets are reference counted, usually<a name="line.728"></a>
-<span class="sourceLineNo">729</span>      // this set is small around O(Handler Count) unless something else is wrong<a name="line.729"></a>
-<span class="sourceLineNo">730</span>      Set&lt;Integer&gt; inUseBuckets = new HashSet&lt;Integer&gt;();<a name="line.730"></a>
-<span class="sourceLineNo">731</span>      for (BucketEntry entry : backingMap.values()) {<a name="line.731"></a>
-<span class="sourceLineNo">732</span>        if (entry.getRefCount() != 0) {<a name="line.732"></a>
-<span class="sourceLineNo">733</span>          inUseBuckets.add(bucketAllocator.getBucketIndex(entry.offset()));<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><a name="line.736"></a>
-<span class="sourceLineNo">737</span>      Set&lt;Integer&gt; candidateBuckets = bucketAllocator.getLeastFilledBuckets(<a name="line.737"></a>
-<span class="sourceLineNo">738</span>          inUseBuckets, completelyFreeBucketsNeeded);<a name="line.738"></a>
-<span class="sourceLineNo">739</span>      for (Map.Entry&lt;BlockCacheKey, BucketEntry&gt; entry : backingMap.entrySet()) {<a name="line.739"></a>
-<span class="sourceLineNo">740</span>        if (candidateBuckets.contains(bucketAllocator<a name="line.740"></a>
-<span class="sourceLineNo">741</span>            .getBucketIndex(entry.getValue().offset()))) {<a name="line.741"></a>
-<span class="sourceLineNo">742</span>          evictBlock(entry.getKey(), false);<a name="line.742"></a>
-<span class="sourceLineNo">743</span>        }<a name="line.743"></a>
-<span class="sourceLineNo">744</span>      }<a name="line.744"></a>
-<span class="sourceLineNo">745</span>    }<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>  /**<a name="line.748"></a>
-<span class="sourceLineNo">749</span>   * Free the space if the used size reaches acceptableSize() or one size block<a name="line.749"></a>
-<span class="sourceLineNo">750</span>   * couldn't be allocated. When freeing the space, we use the LRU algorithm and<a name="line.750"></a>
-<span class="sourceLineNo">751</span>   * ensure there must be some blocks evicted<a name="line.751"></a>
-<span class="sourceLineNo">752</span>   * @param why Why we are being called<a name="line.752"></a>
-<span class="sourceLineNo">753</span>   */<a name="line.753"></a>
-<span class="sourceLineNo">754</span>  private void freeSpace(final String why) {<a name="line.754"></a>
-<span class="sourceLineNo">755</span>    // Ensure only one freeSpace progress at a time<a name="line.755"></a>
-<span class="sourceLineNo">756</span>    if (!freeSpaceLock.tryLock()) {<a name="line.756"></a>
-<span class="sourceLineNo">757</span>      return;<a name="line.757"></a>
-<span class="sourceLineNo">758</span>    }<a name="line.758"></a>
-<span class="sourceLineNo">759</span>    try {<a name="line.759"></a>
-<span class="sourceLineNo">760</span>      freeInProgress = true;<a name="line.760"></a>
-<span class="sourceLineNo">761</span>      long bytesToFreeWithoutExtra = 0;<a name="line.761"></a>
-<span class="sourceLineNo">762</span>      // Calculate free byte for each bucketSizeinfo<a name="line.762"></a>
-<span class="sourceLineNo">763</span>      StringBuilder msgBuffer = LOG.isDebugEnabled()? new StringBuilder(): null;<a name="line.763"></a>
-<span class="sourceLineNo">764</span>      BucketAllocator.IndexStatistics[] stats = bucketAllocator.getIndexStatistics();<a name="line.764"></a>
-<span class="sourceLineNo">765</span>      long[] bytesToFreeForBucket = new long[stats.length];<a name="line.765"></a>
-<span class="sourceLineNo">766</span>      for (int i = 0; i &lt; stats.length; i++) {<a name="line.766"></a>
-<span class="sourceLineNo">767</span>        bytesToFreeForBucket[i] = 0;<a name="line.767"></a>
-<span class="sourceLineNo">768</span>        long freeGoal = (long) Math.floor(stats[i].totalCount() * (1 - minFactor));<a name="line.768"></a>
-<span class="sourceLineNo">769</span>        freeGoal = Math.max(freeGoal, 1);<a name="line.769"></a>
-<span class="sourceLineNo">770</span>        if (stats[i].freeCount() &lt; freeGoal) {<a name="line.770"></a>
-<span class="sourceLineNo">771</span>          bytesToFreeForBucket[i] = stats[i].itemSize() * (freeGoal - stats[i].freeCount());<a name="line.771"></a>
-<span class="sourceLineNo">772</span>          bytesToFreeWithoutExtra += bytesToFreeForBucket[i];<a name="line.772"></a>
-<span class="sourceLineNo">773</span>          if (msgBuffer != null) {<a name="line.773"></a>
-<span class="sourceLineNo">774</span>            msgBuffer.append("Free for bucketSize(" + stats[i].itemSize() + ")="<a name="line.774"></a>
-<span class="sourceLineNo">775</span>              + StringUtils.byteDesc(bytesToFreeForBucket[i]) + ", ");<a name="line.775"></a>
-<span class="sourceLineNo">776</span>          }<a name="line.776"></a>
-<span class="sourceLineNo">777</span>        }<a name="line.777"></a>
-<span class="sourceLineNo">778</span>      }<a name="line.778"></a>
-<span class="sourceLineNo">779</span>      if (msgBuffer != null) {<a name="line.779"></a>
-<span class="sourceLineNo">780</span>        msgBuffer.append("Free for total=" + StringUtils.byteDesc(bytesToFreeWithoutExtra) + ", ");<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>      if (bytesToFreeWithoutExtra &lt;= 0) {<a name="line.783"></a>
-<span class="sourceLineNo">784</span>        return;<a name="line.784"></a>
+<span class="sourceLineNo">634</span>          return false;<a name="line.634"></a>
+<span class="sourceLineNo">635</span>        } else {<a name="line.635"></a>
+<span class="sourceLineNo">636</span>          if (LOG.isDebugEnabled()) {<a name="line.636"></a>
+<span class="sourceLineNo">637</span>            LOG.debug("This block " + cacheKey + " is still referred by " + refCount<a name="line.637"></a>
+<span class="sourceLineNo">638</span>                + " readers. Can not be freed now. Hence will mark this"<a name="line.638"></a>
+<span class="sourceLineNo">639</span>                + " for evicting at a later point");<a name="line.639"></a>
+<span class="sourceLineNo">640</span>          }<a name="line.640"></a>
+<span class="sourceLineNo">641</span>          bucketEntry.markForEvict();<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>    } finally {<a name="line.644"></a>
+<span class="sourceLineNo">645</span>      lock.writeLock().unlock();<a name="line.645"></a>
+<span class="sourceLineNo">646</span>    }<a name="line.646"></a>
+<span class="sourceLineNo">647</span>    cacheStats.evicted(bucketEntry.getCachedTime(), cacheKey.isPrimary());<a name="line.647"></a>
+<span class="sourceLineNo">648</span>    return true;<a name="line.648"></a>
+<span class="sourceLineNo">649</span>  }<a name="line.649"></a>
+<span class="sourceLineNo">650</span><a name="line.650"></a>
+<span class="sourceLineNo">651</span>  /*<a name="line.651"></a>
+<span class="sourceLineNo">652</span>   * Statistics thread.  Periodically output cache statistics to the log.<a name="line.652"></a>
+<span class="sourceLineNo">653</span>   */<a name="line.653"></a>
+<span class="sourceLineNo">654</span>  private static class StatisticsThread extends Thread {<a name="line.654"></a>
+<span class="sourceLineNo">655</span>    private final BucketCache bucketCache;<a name="line.655"></a>
+<span class="sourceLineNo">656</span><a name="line.656"></a>
+<span class="sourceLineNo">657</span>    public StatisticsThread(BucketCache bucketCache) {<a name="line.657"></a>
+<span class="sourceLineNo">658</span>      super("BucketCacheStatsThread");<a name="line.658"></a>
+<span class="sourceLineNo">659</span>      setDaemon(true);<a name="line.659"></a>
+<span class="sourceLineNo">660</span>      this.bucketCache = bucketCache;<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>    @Override<a name="line.663"></a>
+<span class="sourceLineNo">664</span>    public void run() {<a name="line.664"></a>
+<span class="sourceLineNo">665</span>      bucketCache.logStats();<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>  public void logStats() {<a name="line.669"></a>
+<span class="sourceLineNo">670</span>    long totalSize = bucketAllocator.getTotalSize();<a name="line.670"></a>
+<span class="sourceLineNo">671</span>    long usedSize = bucketAllocator.getUsedSize();<a name="line.671"></a>
+<span class="sourceLineNo">672</span>    long freeSize = totalSize - usedSize;<a name="line.672"></a>
+<span class="sourceLineNo">673</span>    long cacheSize = getRealCacheSize();<a name="line.673"></a>
+<span class="sourceLineNo">674</span>    LOG.info("failedBlockAdditions=" + cacheStats.getFailedInserts() + ", " +<a name="line.674"></a>
+<span class="sourceLineNo">675</span>        "totalSize=" + StringUtils.byteDesc(totalSize) + ", " +<a name="line.675"></a>
+<span class="sourceLineNo">676</span>        "freeSize=" + StringUtils.byteDesc(freeSize) + ", " +<a name="line.676"></a>
+<span class="sourceLineNo">677</span>        "usedSize=" + StringUtils.byteDesc(usedSize) +", " +<a name="line.677"></a>
+<span class="sourceLineNo">678</span>        "cacheSize=" + StringUtils.byteDesc(cacheSize) +", " +<a name="line.678"></a>
+<span class="sourceLineNo">679</span>        "accesses=" + cacheStats.getRequestCount() + ", " +<a name="line.679"></a>
+<span class="sourceLineNo">680</span>        "hits=" + cacheStats.getHitCount() + ", " +<a name="line.680"></a>
+<span class="sourceLineNo">681</span>        "IOhitsPerSecond=" + cacheStats.getIOHitsPerSecond() + ", " +<a name="line.681"></a>
+<span class="sourceLineNo">682</span>        "IOTimePerHit=" + String.format("%.2f", cacheStats.getIOTimePerHit())+ ", " +<a name="line.682"></a>
+<span class="sourceLineNo">683</span>        "hitRatio=" + (cacheStats.getHitCount() == 0 ? "0," :<a name="line.683"></a>
+<span class="sourceLineNo">684</span>          (StringUtils.formatPercent(cacheStats.getHitRatio(), 2)+ ", ")) +<a name="line.684"></a>
+<span class="sourceLineNo">685</span>        "cachingAccesses=" + cacheStats.getRequestCachingCount() + ", " +<a name="line.685"></a>
+<span class="sourceLineNo">686</span>        "cachingHits=" + cacheStats.getHitCachingCount() + ", " +<a name="line.686"></a>
+<span class="sourceLineNo">687</span>        "cachingHitsRatio=" +(cacheStats.getHitCachingCount() == 0 ? "0," :<a name="line.687"></a>
+<span class="sourceLineNo">688</span>          (StringUtils.formatPercent(cacheStats.getHitCachingRatio(), 2)+ ", ")) +<a name="line.688"></a>
+<span class="sourceLineNo">689</span>        "evictions=" + cacheStats.getEvictionCount() + ", " +<a name="line.689"></a>
+<span class="sourceLineNo">690</span>        "evicted=" + cacheStats.getEvictedCount() + ", " +<a name="line.690"></a>
+<span class="sourceLineNo">691</span>        "evictedPerRun=" + cacheStats.evictedPerEviction());<a name="line.691"></a>
+<span class="sourceLineNo">692</span>    cacheStats.reset();<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>  public long getRealCacheSize() {<a name="line.695"></a>
+<span class="sourceLineNo">696</span>    return this.realCacheSize.sum();<a name="line.696"></a>
+<span class="sourceLineNo">697</span>  }<a name="line.697"></a>
+<span class="sourceLineNo">698</span><a name="line.698"></a>
+<span class="sourceLineNo">699</span>  private long acceptableSize() {<a name="line.699"></a>
+<span class="sourceLineNo">700</span>    return (long) Math.floor(bucketAllocator.getTotalSize() * acceptableFactor);<a name="line.700"></a>
+<span class="sourceLineNo">701</span>  }<a name="line.701"></a>
+<span class="sourceLineNo">702</span><a name="line.702"></a>
+<span class="sourceLineNo">703</span>  @VisibleForTesting<a name="line.703"></a>
+<span class="sourceLineNo">704</span>  long getPartitionSize(float partitionFactor) {<a name="line.704"></a>
+<span class="sourceLineNo">705</span>    return (long) Math.floor(bucketAllocator.getTotalSize() * partitionFactor * minFactor);<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>   * Return the count of bucketSizeinfos still need free space<a name="line.709"></a>
+<span class="sourceLineNo">710</span>   */<a name="line.710"></a>
+<span class="sourceLineNo">711</span>  private int bucketSizesAboveThresholdCount(float minFactor) {<a name="line.711"></a>
+<span class="sourceLineNo">712</span>    BucketAllocator.IndexStatistics[] stats = bucketAllocator.getIndexStatistics();<a name="line.712"></a>
+<span class="sourceLineNo">713</span>    int fullCount = 0;<a name="line.713"></a>
+<span class="sourceLineNo">714</span>    for (int i = 0; i &lt; stats.length; i++) {<a name="line.714"></a>
+<span class="sourceLineNo">715</span>      long freeGoal = (long) Math.floor(stats[i].totalCount() * (1 - minFactor));<a name="line.715"></a>
+<span class="sourceLineNo">716</span>      freeGoal = Math.max(freeGoal, 1);<a name="line.716"></a>
+<span class="sourceLineNo">717</span>      if (stats[i].freeCount() &lt; freeGoal) {<a name="line.717"></a>
+<span class="sourceLineNo">718</span>        fullCount++;<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>
+<span class="sourceLineNo">721</span>    return fullCount;<a name="line.721"></a>
+<span class="sourceLineNo">722</span>  }<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>   * This method will find the buckets that are minimally occupied<a name="line.725"></a>
+<span class="sourceLineNo">726</span>   * and are not reference counted and will free them completely<a name="line.726"></a>
+<span class="sourceLineNo">727</span>   * without any constraint on the access times of the elements,<a name="line.727"></a>
+<span class="sourceLineNo">728</span>   * and as a process will completely free at most the number of buckets<a name="line.728"></a>
+<span class="sourceLineNo">729</span>   * passed, sometimes it might not due to changing refCounts<a name="line.729"></a>
+<span class="sourceLineNo">730</span>   *<a name="line.730"></a>
+<span class="sourceLineNo">731</span>   * @param completelyFreeBucketsNeeded number of buckets to free<a name="line.731"></a>
+<span class="sourceLineNo">732</span>   **/<a name="line.732"></a>
+<span class="sourceLineNo">733</span>  private void freeEntireBuckets(int completelyFreeBucketsNeeded) {<a name="line.733"></a>
+<span class="sourceLineNo">734</span>    if (completelyFreeBucketsNeeded != 0) {<a name="line.734"></a>
+<span class="sourceLineNo">735</span>      // First we will build a set where the offsets are reference counted, usually<a name="line.735"></a>
+<span class="sourceLineNo">736</span>      // this set is small around O(Handler Count) unless something else is wrong<a name="line.736"></a>
+<span class="sourceLineNo">737</span>      Set&lt;Integer&gt; inUseBuckets = new HashSet&lt;Integer&gt;();<a name="line.737"></a>
+<span class="sourceLineNo">738</span>      for (BucketEntry entry : backingMap.values()) {<a name="line.738"></a>
+<span class="sourceLineNo">739</span>        if (entry.getRefCount() != 0) {<a name="line.739"></a>
+<span class="sourceLineNo">740</span>          inUseBuckets.add(bucketAllocator.getBucketIndex(entry.offset()));<a name="line.740"></a>
+<span class="sourceLineNo">741</span>        }<a name="line.741"></a>
+<span class="sourceLineNo">742</span>      }<a name="line.742"></a>
+<span class="sourceLineNo">743</span><a name="line.743"></a>
+<span class="sourceLineNo">744</span>      Set&lt;Integer&gt; candidateBuckets = bucketAllocator.getLeastFilledBuckets(<a name="line.744"></a>
+<span class="sourceLineNo">745</span>          inUseBuckets, completelyFreeBucketsNeeded);<a name="line.745"></a>
+<span class="sourceLineNo">746</span>      for (Map.Entry&lt;BlockCacheKey, BucketEntry&gt; entry : backingMap.entrySet()) {<a name="line.746"></a>
+<span class="sourceLineNo">747</span>        if (candidateBuckets.contains(bucketAllocator<a name="line.747"></a>
+<span class="sourceLineNo">748</span>            .getBucketIndex(entry.getValue().offset()))) {<a name="line.748"></a>
+<span class="sourceLineNo">749</span>          evictBlock(entry.getKey(), false);<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>  }<a name="line.753"></a>
+<span class="sourceLineNo">754</span><a name="line.754"></a>
+<span class="sourceLineNo">755</span>  /**<a name="line.755"></a>
+<span class="sourceLineNo">756</span>   * Free the space if the used size reaches acceptableSize() or one size block<a name="line.756"></a>
+<span class="sourceLineNo">757</span>   * couldn't be allocated. When freeing the space, we use the LRU algorithm and<a name="line.757"></a>
+<span class="sourceLineNo">758</span>   * ensure there must be some blocks evicted<a name="line.758"></a>
+<span class="sourceLineNo">759</span>   * @param why Why we are being called<a name="line.759"></a>
+<span class="sourceLineNo">760</span>   */<a name="line.760"></a>
+<span class="sourceLineNo">761</span>  private void freeSpace(final String why) {<a name="line.761"></a>
+<span class="sourceLineNo">762</span>    // Ensure only one freeSpace progress at a time<a name="line.762"></a>
+<span class="sourceLineNo">763</span>    if (!freeSpaceLock.tryLock()) {<a name="line.763"></a>
+<span class="sourceLineNo">764</span>      return;<a name="line.764"></a>
+<span class="sourceLineNo">765</span>    }<a name="line.765"></a>
+<span class="sourceLineNo">766</span>    try {<a name="line.766"></a>
+<span class="sourceLineNo">767</span>      freeInProgress = true;<a name="line.767"></a>
+<span class="sourceLineNo">768</span>      long bytesToFreeWithoutExtra = 0;<a name="line.768"></a>
+<span class="sourceLineNo">769</span>      // Calculate free byte for each bucketSizeinfo<a name="line.769"></a>
+<span class="sourceLineNo">770</span>      StringBuilder msgBuffer = LOG.isDebugEnabled()? new StringBuilder(): null;<a name="line.770"></a>
+<span class="sourceLineNo">771</span>      BucketAllocator.IndexStatistics[] stats = bucketAllocator.getIndexStatistics();<a name="line.771"></a>
+<span class="sourceLineNo">772</span>      long[] bytesToFreeForBucket = new long[stats.length];<a name="line.772"></a>
+<span class="sourceLineNo">773</span>      for (int i = 0; i &lt; stats.length; i++) {<a name="line.773"></a>
+<span class="sourceLineNo">774</span>        bytesToFreeForBucket[i] = 0;<a name="line.774"></a>
+<span class="sourceLineNo">775</span>        long freeGoal = (long) Math.floor(stats[i].totalCount() * (1 - minFactor));<a name="line.775"></a>
+<span class="sourceLineNo">776</span>        freeGoal = Math.max(freeGoal, 1);<a name="line.776"></a>
+<span class="sourceLineNo">777</span>        if (stats[i].freeCount() &lt; freeGoal) {<a name="line.777"></a>
+<span class="sourceLineNo">778</span>          bytesToFreeForBucket[i] = stats[i].itemSize() * (freeGoal - stats[i].freeCount());<a name="line.778"></a>
+<span class="sourceLineNo">779</span>          bytesToFreeWithoutExtra += bytesToFreeForBucket[i];<a name="line.779"></a>
+<span class="sourceLineNo">780</span>          if (msgBuffer != null) {<a name="line.780"></a>
+<span class="sourceLineNo">781</span>            msgBuffer.append("Free for bucketSize(" + stats[i].itemSize() + ")="<a name="line.781"></a>
+<span class="sourceLineNo">782</span>              + StringUtils.byteDesc(bytesToFreeForBucket[i]) + ", ");<a name="line.782"></a>
+<span class="sourceLineNo">783</span>          }<a name="line.783"></a>
+<span class="sourceLineNo">784</span>        }<a name="line.784"></a>
 <span class="sourceLineNo">785</span>      }<a name="line.785"></a>
-<span class="sourceLineNo">786</span>      long currentSize = bucketAllocator.getUsedSize();<a name="line.786"></a>
-<span class="sourceLineNo">787</span>      long totalSize = bucketAllocator.getTotalSize();<a name="line.787"></a>
-<span class="sourceLineNo">788</span>      if (LOG.isDebugEnabled() &amp;&amp; msgBuffer != null) {<a name="line.788"></a>
-<span class="sourceLineNo">789</span>        LOG.debug("Free started because \"" + why + "\"; " + msgBuffer.toString() +<a name="line.789"></a>
-<span class="sourceLineNo">790</span>          " of current used=" + StringUtils.byteDesc(currentSize) + ", actual cacheSize=" +<a name="line.790"></a>
-<span class="sourceLineNo">791</span>          StringUtils.byteDesc(realCacheSize.sum()) + ", total=" + StringUtils.byteDesc(totalSize));<a name="line.791"></a>
+<span class="sourceLineNo">786</span>      if (msgBuffer != null) {<a name="line.786"></a>
+<span class="sourceLineNo">787</span>        msgBuffer.append("Free for total=" + StringUtils.byteDesc(bytesToFreeWithoutExtra) + ", ");<a name="line.787"></a>
+<span class="sourceLineNo">788</span>      }<a name="line.788"></a>
+<span class="sourceLineNo">789</span><a name="line.789"></a>
+<span class="sourceLineNo">790</span>      if (bytesToFreeWithoutExtra &lt;= 0) {<a name="line.790"></a>
+<span class="sourceLineNo">791</span>        return;<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>
-<span class="sourceLineNo">794</span>      long bytesToFreeWithExtra = (long) Math.floor(bytesToFreeWithoutExtra<a name="line.794"></a>
-<span class="sourceLineNo">795</span>          * (1 + extraFreeFactor));<a name="line.795"></a>
-<span class="sourceLineNo">796</span><a name="line.796"></a>
-<span class="sourceLineNo">797</span>      // Instantiate priority buckets<a name="line.797"></a>
-<span class="sourceLineNo">798</span>      BucketEntryGroup bucketSingle = new BucketEntryGroup(bytesToFreeWithExtra,<a name="line.798"></a>
-<span class="sourceLineNo">799</span>          blockSize, getPartitionSize(singleFactor));<a name="line.799"></a>
-<span class="sourceLineNo">800</span>      BucketEntryGroup bucketMulti = new BucketEntryGroup(bytesToFreeWithExtra,<a name="line.800"></a>
-<span class="sourceLineNo">801</span>          blockSize, getPartitionSize(multiFactor));<a name="line.801"></a>
-<span class="sourceLineNo">802</span>      BucketEntryGroup bucketMemory = new BucketEntryGroup(bytesToFreeWithExtra,<a name="line.802"></a>
-<span class="sourceLineNo">803</span>          blockSize, getPartitionSize(memoryFactor));<a name="line.803"></a>
-<span class="sourceLineNo">804</span><a name="line.804"></a>
-<span class="sourceLineNo">805</span>      // Scan entire map putting bucket entry into appropriate bucket entry<a name="line.805"></a>
-<span class="sourceLineNo">806</span>      // group<a name="line.806"></a>
-<span class="sourceLineNo">807</span>      for (Map.Entry&lt;BlockCacheKey, BucketEntry&gt; bucketEntryWithKey : backingMap.entrySet()) {<a name="line.807"></a>
-<span class="sourceLineNo">808</span>        switch (bucketEntryWithKey.getValue().getPriority()) {<a name="line.808"></a>
-<span class="sourceLineNo">809</span>          case SINGLE: {<a name="line.809"></a>
-<span class="sourceLineNo">810</span>            bucketSingle.add(bucketEntryWithKey);<a name="line.810"></a>
-<span class="sourceLineNo">811</span>            break;<a name="line.811"></a>
-<span class="sourceLineNo">812</span>          }<a name="line.812"></a>
-<span class="sourceLineNo">813</span>          case MULTI: {<a name="line.813"></a>
-<span class="sourceLineNo">814</span>            bucketMulti.add(bucketEntryWithKey);<a name="line.814"></a>
-<span class="sourceLineNo">815</span>            break;<a name="line.815"></a>
-<span class="sourceLineNo">816</span>          }<a name="line.816"></a>
-<span class="sourceLineNo">817</span>          case MEMORY: {<a name="line.817"></a>
-<span class="sourceLineNo">818</span>            bucketMemory.add(bucketEntryWithKey);<a name="line.818"></a>
-<span class="sourceLineNo">819</span>            break;<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><a name="line.823"></a>
-<span class="sourceLineNo">824</span>      PriorityQueue&lt;BucketEntryGroup&gt; bucketQueue = new PriorityQueue&lt;&gt;(3,<a name="line.824"></a>
-<span class="sourceLineNo">825</span>          Comparator.comparingLong(BucketEntryGroup::overflow));<a name="line.825"></a>
-<span class="sourceLineNo">826</span><a name="line.826"></a>
-<span class="sourceLineNo">827</span>      bucketQueue.add(bucketSingle);<a name="line.827"></a>
-<span class="sourceLineNo">828</span>      bucketQueue.add(bucketMulti);<a name="line.828"></a>
-<span class="sourceLineNo">829</span>      bucketQueue.add(bucketMemory);<a name="line.829"></a>
+<span class="sourceLineNo">793</span>      long currentSize = bucketAllocator.getUsedSize();<a name="line.793"></a>
+<span class="sourceLineNo">794</span>      long totalSize = bucketAllocator.getTotalSize();<a name="line.794"></a>
+<span class="sourceLineNo">795</span>      if (LOG.isDebugEnabled() &amp;&amp; msgBuffer != null) {<a name="line.795"></a>
+<span class="sourceLineNo">796</span>        LOG.debug("Free started because \"" + why + "\"; " + msgBuffer.toString() +<a name="line.796"></a>
+<span class="sourceLineNo">797</span>          " of current used=" + StringUtils.byteDesc(currentSize) + ", actual cacheSize=" +<a name="line.797"></a>
+<span class="sourceLineNo">798</span>          StringUtils.byteDesc(realCacheSize.sum()) + ", total=" + StringUtils.byteDesc(totalSize));<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>      long bytesToFreeWithExtra = (long) Math.floor(bytesToFreeWithoutExtra<a name="line.801"></a>
+<span class="sourceLineNo">802</span>          * (1 + extraFreeFactor));<a name="line.802"></a>
+<span class="sourceLineNo">803</span><a name="line.803"></a>
+<span class="sourceLineNo">804</span>      // Instantiate priority buckets<a name="line.804"></a>
+<span class="sourceLineNo">805</span>      BucketEntryGroup bucketSingle = new BucketEntryGroup(bytesToFreeWithExtra,<a name="line.805"></a>
+<span class="sourceLineNo">806</span>          blockSize, getPartitionSize(singleFactor));<a name="line.806"></a>
+<span class="sourceLineNo">807</span>      BucketEntryGroup bucketMulti = new BucketEntryGroup(bytesToFreeWithExtra,<a name="line.807"></a>
+<span class="sourceLineNo">808</span>          blockSize, getPartitionSize(multiFactor));<a name="line.808"></a>
+<span class="sourceLineNo">809</span>      BucketEntryGroup bucketMemory = new BucketEntryGroup(bytesToFreeWithExtra,<a name="line.809"></a>
+<span class="sourceLineNo">810</span>          blockSize, getPartitionSize(memoryFactor));<a name="line.810"></a>
+<span class="sourceLineNo">811</span><a name="line.811"></a>
+<span class="sourceLineNo">812</span>      // Scan entire map putting bucket entry into appropriate bucket entry<a name="line.812"></a>
+<span class="sourceLineNo">813</span>      // group<a name="line.813"></a>
+<span class="sourceLineNo">814</span>      for (Map.Entry&lt;BlockCacheKey, BucketEntry&gt; bucketEntryWithKey : backingMap.entrySet()) {<a name="line.814"></a>
+<span class="sourceLineNo">815</span>        switch (bucketEntryWithKey.getValue().getPriority()) {<a name="line.815"></a>
+<span class="sourceLineNo">816</span>          case SINGLE: {<a name="line.816"></a>
+<span class="sourceLineNo">817</span>            bucketSingle.add(bucketEntryWithKey);<a name="line.817"></a>
+<span class="sourceLineNo">818</span>            break;<a name="line.818"></a>
+<span class="sourceLineNo">819</span>          }<a name="line.819"></a>
+<span class="sourceLineNo">820</span>          case MULTI: {<a name="line.820"></a>
+<span class="sourceLineNo">821</span>            bucketMulti.add(bucketEntryWithKey);<a name="line.821"></a>
+<span class="sourceLineNo">822</span>            break;<a name="line.822"></a>
+<span class="sourceLineNo">823</span>          }<a name="line.823"></a>
+<span class="sourceLineNo">824</span>          case MEMORY: {<a name="line.824"></a>
+<span class="sourceLineNo">825</span>            bucketMemory.add(bucketEntryWithKey);<a name="line.825"></a>
+<span class="sourceLineNo">826</span>            break;<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">830</span><a name="line.830"></a>
-<span class="sourceLineNo">831</span>      int remainingBuckets = 3;<a name="line.831"></a>
-<span class="sourceLineNo">832</span>      long bytesFreed = 0;<a name="line.832"></a>
+<span class="sourceLineNo">831</span>      PriorityQueue&lt;BucketEntryGroup&gt; bucketQueue = new PriorityQueue&lt;&gt;(3,<a name="line.831"></a>
+<span class="sourceLineNo">832</span>          Comparator.comparingLong(BucketEntryGroup::overflow));<a name="line.832"></a>
 <span class="sourceLineNo">833</span><a name="line.833"></a>
-<span class="sourceLineNo">834</span>      BucketEntryGroup bucketGroup;<a name="line.834"></a>
-<span class="sourceLineNo">835</span>      while ((bucketGroup = bucketQueue.poll()) != null) {<a name="line.835"></a>
-<span class="sourceLineNo">836</span>        long overflow = bucketGroup.overflow();<a name="line.836"></a>
-<span class="sourceLineNo">837</span>        if (overflow &gt; 0) {<a name="line.837"></a>
-<span class="sourceLineNo">838</span>          long bucketBytesToFree = Math.min(overflow,<a name="line.838"></a>
-<span class="sourceLineNo">839</span>              (bytesToFreeWithoutExtra - bytesFreed) / remainingBuckets);<a name="line.839"></a>
-<span class="sourceLineNo">840</span>          bytesFreed += bucketGroup.free(bucketBytesToFree);<a name="line.840"></a>
-<span class="sourceLineNo">841</span>        }<a name="line.841"></a>
-<span class="sourceLineNo">842</span>        remainingBuckets--;<a name="line.842"></a>
-<span class="sourceLineNo">843</span>      }<a name="line.843"></a>
-<span class="sourceLineNo">844</span><a name="line.844"></a>
-<span class="sourceLineNo">845</span>      // Check and free if there are buckets that still need freeing of space<a name="line.845"></a>
-<span class="sourceLineNo">846</span>      if (bucketSizesAboveThresholdCount(minFactor) &gt; 0) {<a name="line.846"></a>
-<span class="sourceLineNo">847</span>        bucketQueue.clear();<a name="line.847"></a>
-<span class="sourceLineNo">848</span>        remainingBuckets = 3;<a name="line.848"></a>
-<span class="sourceLineNo">849</span><a name="line.849"></a>
-<span class="sourceLineNo">850</span>        bucketQueue.add(bucketSingle);<a name="line.850"></a>
-<span class="sourceLineNo">851</span>        bucketQueue.add(bucketMulti);<a name="line.851"></a>
-<span class="sourceLineNo">852</span>        bucketQueue.add(bucketMemory);<a name="line.852"></a>
-<span class="sourceLineNo">853</span><a name="line.853"></a>
-<span class="sourceLineNo">854</span>        while ((bucketGroup = bucketQueue.poll()) != null) {<a name="line.854"></a>
-<span class="sourceLineNo">855</span>          long bucketBytesToFree = (bytesToFreeWithExtra - bytesFreed) / remainingBuckets;<a name="line.855"></a>
-<span class="sourceLineNo">856</span>          bytesFreed += bucketGroup.free(bucketBytesToFree);<a name="line.856"></a>
-<span class="sourceLineNo">857</span>          remainingBuckets--;<a name="line.857"></a>
-<span class="sourceLineNo">858</span>        }<a name="line.858"></a>
-<span class="sourceLineNo">859</span>      }<a name="line.859"></a>
+<span class="sourceLineNo">834</span>      bucketQueue.add(bucketSingle);<a name="line.834"></a>
+<span class="sourceLineNo">835</span>      bucketQueue.add(bucketMulti);<a name="line.835"></a>
+<span class="sourceLineNo">836</span>      bucketQueue.add(bucketMemory);<a name="line.836"></a>
+<span class="sourceLineNo">837</span><a name="line.837"></a>
+<span class="sourceLineNo">838</span>      int remainingBuckets = 3;<a name="line.838"></a>
+<span class="sourceLineNo">839</span>      long bytesFreed = 0;<a name="line.839"></a>
+<span class="sourceLineNo">840</span><a name="line.840"></a>
+<span class="sourceLineNo">841</span>      BucketEntryGroup bucketGroup;<a name="line.841"></a>
+<span class="sourceLineNo">842</span>      while ((bucketGroup = bucketQueue.poll()) != null) {<a name="line.842"></a>
+<span class="sourceLineNo">843</span>        long overflow = bucketGroup.overflow();<a name="line.843"></a>
+<span class="sourceLineNo">844</span>        if (overflow &gt; 0) {<a name="line.844"></a>
+<span class="sourceLineNo">845</span>          long bucketBytesToFree = Math.min(overflow,<a name="line.845"></a>
+<span class="sourceLineNo">846</span>              (bytesToFreeWithoutExtra - bytesFreed) / remainingBuckets);<a name="line.846"></a>
+<span class="sourceLineNo">847</span>          bytesFreed += bucketGroup.free(bucketBytesToFree);<a name="line.847"></a>
+<span class="sourceLineNo">848</span>        }<a name="line.848"></a>
+<span class="sourceLineNo">849</span>        remainingBuckets--;<a name="line.849"></a>
+<span class="sourceLineNo">850</span>      }<a name="line.850"></a>
+<span class="sourceLineNo">851</span><a name="line.851"></a>
+<span class="sourceLineNo">852</span>      // Check and free if there are buckets that still need freeing of space<a name="line.852"></a>
+<span class="sourceLineNo">853</span>      if (bucketSizesAboveThresholdCount(minFactor) &gt; 0) {<a name="line.853"></a>
+<span class="sourceLineNo">854</span>        bucketQueue.clear();<a name="line.854"></a>
+<span class="sourceLineNo">855</span>        remainingBuckets = 3;<a name="line.855"></a>
+<span class="sourceLineNo">856</span><a name="line.856"></a>
+<span class="sourceLineNo">857</span>        bucketQueue.add(bucketSingle);<a name="line.857"></a>
+<span class="sourceLineNo">858</span>        bucketQueue.add(bucketMulti);<a name="line.858"></a>
+<span class="sourceLineNo">859</span>        bucketQueue.add(bucketMemory);<a name="line.859"></a>
 <span class="sourceLineNo">860</span><a name="line.860"></a>
-<span class="sourceLineNo">861</span>      // Even after the above free we might still need freeing because of the<a name="line.861"></a>
-<span class="sourceLineNo">862</span>      // De-fragmentation of the buckets (also called Slab Calcification problem), i.e<a name="line.862"></a>
-<span class="sourceLineNo">863</span>      // there might be some buckets where the occupancy is very sparse and thus are not<a name="line.863"></a>
-<span class="sourceLineNo">864</span>      // yielding the free for the other bucket sizes, the fix for this to evict some<a name="line.864"></a>
-<span class="sourceLineNo">865</span>      // of the buckets, we do this by evicting the buckets that are least fulled<a name="line.865"></a>
-<span class="sourceLineNo">866</span>      freeEntireBuckets(DEFAULT_FREE_ENTIRE_BLOCK_FACTOR *<a name="line.866"></a>
-<span class="sourceLineNo">867</span>          bucketSizesAboveThresholdCount(1.0f));<a name="line.867"></a>
-<span class="sourceLineNo">868</span><a name="line.868"></a>
-<span class="sourceLineNo">869</span>      if (LOG.isDebugEnabled()) {<a name="line.869"></a>
-<span class="sourceLineNo">870</span>        long single = bucketSingle.totalSize();<a name="line.870"></a>
-<span class="sourceLineNo">871</span>        long multi = bucketMulti.totalSize();<a name="line.871"></a>
-<span class="sourceLineNo">872</span>        long memory = bucketMemory.totalSize();<a name="line.872"></a>
-<span class="sourceLineNo">873</span>        if (LOG.isDebugEnabled()) {<a name="line.873"></a>
-<span class="sourceLineNo">874</span>          LOG.debug("Bucket cache free space completed; " + "freed="<a name="line.874"></a>
-<span class="sourceLineNo">875</span>            + StringUtils.byteDesc(bytesFreed) + ", " + "total="<a name="line.875"></a>
-<span class="sourceLineNo">876</span>            + StringUtils.byteDesc(totalSize) + ", " + "single="<a name="line.876"></a>
-<span class="sourceLineNo">877</span>            + StringUtils.byteDesc(single) + ", " + "multi="<a name="line.877"></a>
-<span class="sourceLineNo">878</span>            + StringUtils.byteDesc(multi) + ", " + "memory="<a name="line.878"></a>
-<span class="sourceLineNo">879</span>            + StringUtils.byteDesc(memory));<a name="line.879"></a>
-<span class="sourceLineNo">880</span>        }<a name="line.880"></a>
-<span class="sourceLineNo">881</span>      }<a name="line.881"></a>
-<span class="sourceLineNo">882</span><a name="line.882"></a>
-<span class="sourceLineNo">883</span>    } catch (Throwable t) {<a name="line.883"></a>
-<span class="sourceLineNo">884</span>      LOG.warn("Failed freeing space", t);<a name="line.884"></a>
-<span class="sourceLineNo">885</span>    } finally {<a name="line.885"></a>
-<span class="sourceLineNo">886</span>      cacheStats.evict();<a name="line.886"></a>
-<span class="sourceLineNo">887</span>      freeInProgress = false;<a name="line.887"></a>
-<span class="sourceLineNo">888</span>      freeSpaceLock.unlock();<a name="line.888"></a>
-<span class="sourceLineNo">889</span>    }<a name="line.889"></a>
-<span class="sourceLineNo">890</span>  }<a name="line.890"></a>
-<span class="sourceLineNo">891</span><a name="line.891"></a>
-<span class="sourceLineNo">892</span>  // This handles flushing the RAM cache to IOEngine.<a name="line.892"></a>
-<span class="sourceLineNo">893</span>  @VisibleForTesting<a name="line.893"></a>
-<span class="sourceLineNo">894</span>  class WriterThread extends HasThread {<a name="line.894"></a>
-<span class="sourceLineNo">895</span>    private final BlockingQueue&lt;RAMQueueEntry&gt; inputQueue;<a name="line.895"></a>
-<span class="sourceLineNo">896</span>    private volatile boolean writerEnabled = true;<a name="line.896"></a>
-<span class="sourceLineNo">897</span><a name="line.897"></a>
-<span class="sourceLineNo">898</span>    WriterThread(BlockingQueue&lt;RAMQueueEntry&gt; queue) {<a name="line.898"></a>
-<span class="sourceLineNo">899</span>      super("BucketCacheWriterThread");<a name="line

<TRUNCATED>

[18/50] hbase-site git commit: Published site at 26babcf013de696b899d76a3c39434b794440d8d.

Posted by gi...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.Builder.html
----------------------------------------------------------------------
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.Builder.html b/devapidocs/src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.Builder.html
index cabb570..90f3b1e 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.Builder.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.Builder.html
@@ -107,660 +107,661 @@
 <span class="sourceLineNo">099</span><a name="line.99"></a>
 <span class="sourceLineNo">100</span>  private Cell lastPeekedCell = null;<a name="line.100"></a>
 <span class="sourceLineNo">101</span><a name="line.101"></a>
-<span class="sourceLineNo">102</span>  /**<a name="line.102"></a>
-<span class="sourceLineNo">103</span>   * Tracks the relevant server side metrics during scans. null when metrics should not be tracked<a name="line.103"></a>
-<span class="sourceLineNo">104</span>   */<a name="line.104"></a>
-<span class="sourceLineNo">105</span>  final ServerSideScanMetrics metrics;<a name="line.105"></a>
-<span class="sourceLineNo">106</span><a name="line.106"></a>
-<span class="sourceLineNo">107</span>  ScannerContext(boolean keepProgress, LimitFields limitsToCopy, boolean trackMetrics) {<a name="line.107"></a>
-<span class="sourceLineNo">108</span>    this.limits = new LimitFields();<a name="line.108"></a>
-<span class="sourceLineNo">109</span>    if (limitsToCopy != null) {<a name="line.109"></a>
-<span class="sourceLineNo">110</span>      this.limits.copy(limitsToCopy);<a name="line.110"></a>
-<span class="sourceLineNo">111</span>    }<a name="line.111"></a>
+<span class="sourceLineNo">102</span>  // Set this to true will have the same behavior with reaching the time limit.<a name="line.102"></a>
+<span class="sourceLineNo">103</span>  // This is used when you want to make the current RSRpcService.scan returns immediately. For<a name="line.103"></a>
+<span class="sourceLineNo">104</span>  // example, when we want to switch from pread to stream, we can only do it after the rpc call is<a name="line.104"></a>
+<span class="sourceLineNo">105</span>  // returned.<a name="line.105"></a>
+<span class="sourceLineNo">106</span>  private boolean returnImmediately;<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>   * Tracks the relevant server side metrics during scans. null when metrics should not be tracked<a name="line.109"></a>
+<span class="sourceLineNo">110</span>   */<a name="line.110"></a>
+<span class="sourceLineNo">111</span>  final ServerSideScanMetrics metrics;<a name="line.111"></a>
 <span class="sourceLineNo">112</span><a name="line.112"></a>
-<span class="sourceLineNo">113</span>    // Progress fields are initialized to 0<a name="line.113"></a>
-<span class="sourceLineNo">114</span>    progress = new ProgressFields(0, 0, 0);<a name="line.114"></a>
-<span class="sourceLineNo">115</span><a name="line.115"></a>
-<span class="sourceLineNo">116</span>    this.keepProgress = keepProgress;<a name="line.116"></a>
-<span class="sourceLineNo">117</span>    this.scannerState = DEFAULT_STATE;<a name="line.117"></a>
-<span class="sourceLineNo">118</span>    this.metrics = trackMetrics ? new ServerSideScanMetrics() : null;<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>  boolean isTrackingMetrics() {<a name="line.121"></a>
-<span class="sourceLineNo">122</span>    return this.metrics != null;<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>   * Get the metrics instance. Should only be called after a call to {@link #isTrackingMetrics()}<a name="line.126"></a>
-<span class="sourceLineNo">127</span>   * has been made to confirm that metrics are indeed being tracked.<a name="line.127"></a>
-<span class="sourceLineNo">128</span>   * @return {@link ServerSideScanMetrics} instance that is tracking metrics for this scan<a name="line.128"></a>
-<span class="sourceLineNo">129</span>   */<a name="line.129"></a>
-<span class="sourceLineNo">130</span>  ServerSideScanMetrics getMetrics() {<a name="line.130"></a>
-<span class="sourceLineNo">131</span>    assert isTrackingMetrics();<a name="line.131"></a>
-<span class="sourceLineNo">132</span>    return this.metrics;<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>   * @return true if the progress tracked so far in this instance will be considered during an<a name="line.136"></a>
-<span class="sourceLineNo">137</span>   *         invocation of {@link InternalScanner#next(java.util.List)} or<a name="line.137"></a>
-<span class="sourceLineNo">138</span>   *         {@link RegionScanner#next(java.util.List)}. false when the progress tracked so far<a name="line.138"></a>
-<span class="sourceLineNo">139</span>   *         should not be considered and should instead be wiped away via {@link #clearProgress()}<a name="line.139"></a>
-<span class="sourceLineNo">140</span>   */<a name="line.140"></a>
-<span class="sourceLineNo">141</span>  boolean getKeepProgress() {<a name="line.141"></a>
-<span class="sourceLineNo">142</span>    return keepProgress;<a name="line.142"></a>
-<span class="sourceLineNo">143</span>  }<a name="line.143"></a>
-<span class="sourceLineNo">144</span><a name="line.144"></a>
-<span class="sourceLineNo">145</span>  void setKeepProgress(boolean keepProgress) {<a name="line.145"></a>
-<span class="sourceLineNo">146</span>    this.keepProgress = keepProgress;<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>   * Progress towards the batch limit has been made. Increment internal tracking of batch progress<a name="line.150"></a>
-<span class="sourceLineNo">151</span>   */<a name="line.151"></a>
-<span class="sourceLineNo">152</span>  void incrementBatchProgress(int batch) {<a name="line.152"></a>
-<span class="sourceLineNo">153</span>    int currentBatch = progress.getBatch();<a name="line.153"></a>
-<span class="sourceLineNo">154</span>    progress.setBatch(currentBatch + batch);<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>   * Progress towards the size limit has been made. Increment internal tracking of size progress<a name="line.158"></a>
-<span class="sourceLineNo">159</span>   */<a name="line.159"></a>
-<span class="sourceLineNo">160</span>  void incrementSizeProgress(long dataSize, long heapSize) {<a name="line.160"></a>
-<span class="sourceLineNo">161</span>    long curDataSize = progress.getDataSize();<a name="line.161"></a>
-<span class="sourceLineNo">162</span>    progress.setDataSize(curDataSize + dataSize);<a name="line.162"></a>
-<span class="sourceLineNo">163</span>    long curHeapSize = progress.getHeapSize();<a name="line.163"></a>
-<span class="sourceLineNo">164</span>    progress.setHeapSize(curHeapSize + heapSize);<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>  int getBatchProgress() {<a name="line.167"></a>
-<span class="sourceLineNo">168</span>    return progress.getBatch();<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>  long getDataSizeProgress() {<a name="line.171"></a>
-<span class="sourceLineNo">172</span>    return progress.getDataSize();<a name="line.172"></a>
-<span class="sourceLineNo">173</span>  }<a name="line.173"></a>
-<span class="sourceLineNo">174</span><a name="line.174"></a>
-<span class="sourceLineNo">175</span>  long getHeapSizeProgress() {<a name="line.175"></a>
-<span class="sourceLineNo">176</span>    return progress.getHeapSize();<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>  void setProgress(int batchProgress, long sizeProgress, long heapSizeProgress) {<a name="line.179"></a>
-<span class="sourceLineNo">180</span>    setBatchProgress(batchProgress);<a name="line.180"></a>
-<span class="sourceLineNo">181</span>    setSizeProgress(sizeProgress, heapSizeProgress);<a name="line.181"></a>
-<span class="sourceLineNo">182</span>  }<a name="line.182"></a>
-<span class="sourceLineNo">183</span><a name="line.183"></a>
-<span class="sourceLineNo">184</span>  void setSizeProgress(long dataSizeProgress, long heapSizeProgress) {<a name="line.184"></a>
-<span class="sourceLineNo">185</span>    progress.setDataSize(dataSizeProgress);<a name="line.185"></a>
-<span class="sourceLineNo">186</span>    progress.setHeapSize(heapSizeProgress);<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>  void setBatchProgress(int batchProgress) {<a name="line.189"></a>
-<span class="sourceLineNo">190</span>    progress.setBatch(batchProgress);<a name="line.190"></a>
-<span class="sourceLineNo">191</span>  }<a name="line.191"></a>
-<span class="sourceLineNo">192</span><a name="line.192"></a>
-<span class="sourceLineNo">193</span>  /**<a name="line.193"></a>
-<span class="sourceLineNo">194</span>   * Clear away any progress that has been made so far. All progress fields are reset to initial<a name="line.194"></a>
-<span class="sourceLineNo">195</span>   * values<a name="line.195"></a>
-<span class="sourceLineNo">196</span>   */<a name="line.196"></a>
-<span class="sourceLineNo">197</span>  void clearProgress() {<a name="line.197"></a>
-<span class="sourceLineNo">198</span>    progress.setFields(0, 0, 0);<a name="line.198"></a>
-<span class="sourceLineNo">199</span>  }<a name="line.199"></a>
-<span class="sourceLineNo">200</span><a name="line.200"></a>
-<span class="sourceLineNo">201</span>  /**<a name="line.201"></a>
-<span class="sourceLineNo">202</span>   * Note that this is not a typical setter. This setter returns the {@link NextState} that was<a name="line.202"></a>
-<span class="sourceLineNo">203</span>   * passed in so that methods can be invoked against the new state. Furthermore, this pattern<a name="line.203"></a>
-<span class="sourceLineNo">204</span>   * allows the {@link NoLimitScannerContext} to cleanly override this setter and simply return the<a name="line.204"></a>
-<span class="sourceLineNo">205</span>   * new state, thus preserving the immutability of {@link NoLimitScannerContext}<a name="line.205"></a>
-<span class="sourceLineNo">206</span>   * @param state<a name="line.206"></a>
-<span class="sourceLineNo">207</span>   * @return The state that was passed in.<a name="line.207"></a>
-<span class="sourceLineNo">208</span>   */<a name="line.208"></a>
-<span class="sourceLineNo">209</span>  NextState setScannerState(NextState state) {<a name="line.209"></a>
-<span class="sourceLineNo">210</span>    if (!NextState.isValidState(state)) {<a name="line.210"></a>
-<span class="sourceLineNo">211</span>      throw new IllegalArgumentException("Cannot set to invalid state: " + state);<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>    this.scannerState = state;<a name="line.214"></a>
-<span class="sourceLineNo">215</span>    return state;<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>  /**<a name="line.218"></a>
-<span class="sourceLineNo">219</span>   * @return true when we have more cells for the current row. This usually because we have reached<a name="line.219"></a>
-<span class="sourceLineNo">220</span>   *         a limit in the middle of a row<a name="line.220"></a>
-<span class="sourceLineNo">221</span>   */<a name="line.221"></a>
-<span class="sourceLineNo">222</span>  boolean mayHaveMoreCellsInRow() {<a name="line.222"></a>
-<span class="sourceLineNo">223</span>    return scannerState == NextState.SIZE_LIMIT_REACHED_MID_ROW ||<a name="line.223"></a>
-<span class="sourceLineNo">224</span>        scannerState == NextState.TIME_LIMIT_REACHED_MID_ROW ||<a name="line.224"></a>
-<span class="sourceLineNo">225</span>        scannerState == NextState.BATCH_LIMIT_REACHED;<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>  /**<a name="line.228"></a>
-<span class="sourceLineNo">229</span>   * @param checkerScope<a name="line.229"></a>
-<span class="sourceLineNo">230</span>   * @return true if the batch limit can be enforced in the checker's scope<a name="line.230"></a>
-<span class="sourceLineNo">231</span>   */<a name="line.231"></a>
-<span class="sourceLineNo">232</span>  boolean hasBatchLimit(LimitScope checkerScope) {<a name="line.232"></a>
-<span class="sourceLineNo">233</span>    return limits.canEnforceBatchLimitFromScope(checkerScope) &amp;&amp; limits.getBatch() &gt; 0;<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>   * @param checkerScope<a name="line.237"></a>
-<span class="sourceLineNo">238</span>   * @return true if the size limit can be enforced in the checker's scope<a name="line.238"></a>
-<span class="sourceLineNo">239</span>   */<a name="line.239"></a>
-<span class="sourceLineNo">240</span>  boolean hasSizeLimit(LimitScope checkerScope) {<a name="line.240"></a>
-<span class="sourceLineNo">241</span>    return limits.canEnforceSizeLimitFromScope(checkerScope)<a name="line.241"></a>
-<span class="sourceLineNo">242</span>        &amp;&amp; (limits.getDataSize() &gt; 0 || limits.getHeapSize() &gt; 0);<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>  /**<a name="line.245"></a>
-<span class="sourceLineNo">246</span>   * @param checkerScope<a name="line.246"></a>
-<span class="sourceLineNo">247</span>   * @return true if the time limit can be enforced in the checker's scope<a name="line.247"></a>
-<span class="sourceLineNo">248</span>   */<a name="line.248"></a>
-<span class="sourceLineNo">249</span>  boolean hasTimeLimit(LimitScope checkerScope) {<a name="line.249"></a>
-<span class="sourceLineNo">250</span>    return limits.canEnforceTimeLimitFromScope(checkerScope) &amp;&amp; limits.getTime() &gt; 0;<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>   * @param checkerScope<a name="line.254"></a>
-<span class="sourceLineNo">255</span>   * @return true if any limit can be enforced within the checker's scope<a name="line.255"></a>
-<span class="sourceLineNo">256</span>   */<a name="line.256"></a>
-<span class="sourceLineNo">257</span>  boolean hasAnyLimit(LimitScope checkerScope) {<a name="line.257"></a>
-<span class="sourceLineNo">258</span>    return hasBatchLimit(checkerScope) || hasSizeLimit(checkerScope) || hasTimeLimit(checkerScope);<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>  /**<a name="line.261"></a>
-<span class="sourceLineNo">262</span>   * @param scope The scope in which the size limit will be enforced<a name="line.262"></a>
+<span class="sourceLineNo">113</span>  ScannerContext(boolean keepProgress, LimitFields limitsToCopy, boolean trackMetrics) {<a name="line.113"></a>
+<span class="sourceLineNo">114</span>    this.limits = new LimitFields();<a name="line.114"></a>
+<span class="sourceLineNo">115</span>    if (limitsToCopy != null) {<a name="line.115"></a>
+<span class="sourceLineNo">116</span>      this.limits.copy(limitsToCopy);<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>    // Progress fields are initialized to 0<a name="line.119"></a>
+<span class="sourceLineNo">120</span>    progress = new ProgressFields(0, 0, 0);<a name="line.120"></a>
+<span class="sourceLineNo">121</span><a name="line.121"></a>
+<span class="sourceLineNo">122</span>    this.keepProgress = keepProgress;<a name="line.122"></a>
+<span class="sourceLineNo">123</span>    this.scannerState = DEFAULT_STATE;<a name="line.123"></a>
+<span class="sourceLineNo">124</span>    this.metrics = trackMetrics ? new ServerSideScanMetrics() : null;<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>  boolean isTrackingMetrics() {<a name="line.127"></a>
+<span class="sourceLineNo">128</span>    return this.metrics != null;<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>   * Get the metrics instance. Should only be called after a call to {@link #isTrackingMetrics()}<a name="line.132"></a>
+<span class="sourceLineNo">133</span>   * has been made to confirm that metrics are indeed being tracked.<a name="line.133"></a>
+<span class="sourceLineNo">134</span>   * @return {@link ServerSideScanMetrics} instance that is tracking metrics for this scan<a name="line.134"></a>
+<span class="sourceLineNo">135</span>   */<a name="line.135"></a>
+<span class="sourceLineNo">136</span>  ServerSideScanMetrics getMetrics() {<a name="line.136"></a>
+<span class="sourceLineNo">137</span>    assert isTrackingMetrics();<a name="line.137"></a>
+<span class="sourceLineNo">138</span>    return this.metrics;<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>   * @return true if the progress tracked so far in this instance will be considered during an<a name="line.142"></a>
+<span class="sourceLineNo">143</span>   *         invocation of {@link InternalScanner#next(java.util.List)} or<a name="line.143"></a>
+<span class="sourceLineNo">144</span>   *         {@link RegionScanner#next(java.util.List)}. false when the progress tracked so far<a name="line.144"></a>
+<span class="sourceLineNo">145</span>   *         should not be considered and should instead be wiped away via {@link #clearProgress()}<a name="line.145"></a>
+<span class="sourceLineNo">146</span>   */<a name="line.146"></a>
+<span class="sourceLineNo">147</span>  boolean getKeepProgress() {<a name="line.147"></a>
+<span class="sourceLineNo">148</span>    return keepProgress;<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>  void setKeepProgress(boolean keepProgress) {<a name="line.151"></a>
+<span class="sourceLineNo">152</span>    this.keepProgress = keepProgress;<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>   * Progress towards the batch limit has been made. Increment internal tracking of batch progress<a name="line.156"></a>
+<span class="sourceLineNo">157</span>   */<a name="line.157"></a>
+<span class="sourceLineNo">158</span>  void incrementBatchProgress(int batch) {<a name="line.158"></a>
+<span class="sourceLineNo">159</span>    int currentBatch = progress.getBatch();<a name="line.159"></a>
+<span class="sourceLineNo">160</span>    progress.setBatch(currentBatch + batch);<a name="line.160"></a>
+<span class="sourceLineNo">161</span>  }<a name="line.161"></a>
+<span class="sourceLineNo">162</span><a name="line.162"></a>
+<span class="sourceLineNo">163</span>  /**<a name="line.163"></a>
+<span class="sourceLineNo">164</span>   * Progress towards the size limit has been made. Increment internal tracking of size progress<a name="line.164"></a>
+<span class="sourceLineNo">165</span>   */<a name="line.165"></a>
+<span class="sourceLineNo">166</span>  void incrementSizeProgress(long dataSize, long heapSize) {<a name="line.166"></a>
+<span class="sourceLineNo">167</span>    long curDataSize = progress.getDataSize();<a name="line.167"></a>
+<span class="sourceLineNo">168</span>    progress.setDataSize(curDataSize + dataSize);<a name="line.168"></a>
+<span class="sourceLineNo">169</span>    long curHeapSize = progress.getHeapSize();<a name="line.169"></a>
+<span class="sourceLineNo">170</span>    progress.setHeapSize(curHeapSize + heapSize);<a name="line.170"></a>
+<span class="sourceLineNo">171</span>  }<a name="line.171"></a>
+<span class="sourceLineNo">172</span><a name="line.172"></a>
+<span class="sourceLineNo">173</span>  int getBatchProgress() {<a name="line.173"></a>
+<span class="sourceLineNo">174</span>    return progress.getBatch();<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>  long getDataSizeProgress() {<a name="line.177"></a>
+<span class="sourceLineNo">178</span>    return progress.getDataSize();<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>  long getHeapSizeProgress() {<a name="line.181"></a>
+<span class="sourceLineNo">182</span>    return progress.getHeapSize();<a name="line.182"></a>
+<span class="sourceLineNo">183</span>  }<a name="line.183"></a>
+<span class="sourceLineNo">184</span><a name="line.184"></a>
+<span class="sourceLineNo">185</span>  void setProgress(int batchProgress, long sizeProgress, long heapSizeProgress) {<a name="line.185"></a>
+<span class="sourceLineNo">186</span>    setBatchProgress(batchProgress);<a name="line.186"></a>
+<span class="sourceLineNo">187</span>    setSizeProgress(sizeProgress, heapSizeProgress);<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>  void setSizeProgress(long dataSizeProgress, long heapSizeProgress) {<a name="line.190"></a>
+<span class="sourceLineNo">191</span>    progress.setDataSize(dataSizeProgress);<a name="line.191"></a>
+<span class="sourceLineNo">192</span>    progress.setHeapSize(heapSizeProgress);<a name="line.192"></a>
+<span class="sourceLineNo">193</span>  }<a name="line.193"></a>
+<span class="sourceLineNo">194</span><a name="line.194"></a>
+<span class="sourceLineNo">195</span>  void setBatchProgress(int batchProgress) {<a name="line.195"></a>
+<span class="sourceLineNo">196</span>    progress.setBatch(batchProgress);<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>   * Clear away any progress that has been made so far. All progress fields are reset to initial<a name="line.200"></a>
+<span class="sourceLineNo">201</span>   * values<a name="line.201"></a>
+<span class="sourceLineNo">202</span>   */<a name="line.202"></a>
+<span class="sourceLineNo">203</span>  void clearProgress() {<a name="line.203"></a>
+<span class="sourceLineNo">204</span>    progress.setFields(0, 0, 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>  /**<a name="line.207"></a>
+<span class="sourceLineNo">208</span>   * Note that this is not a typical setter. This setter returns the {@link NextState} that was<a name="line.208"></a>
+<span class="sourceLineNo">209</span>   * passed in so that methods can be invoked against the new state. Furthermore, this pattern<a name="line.209"></a>
+<span class="sourceLineNo">210</span>   * allows the {@link NoLimitScannerContext} to cleanly override this setter and simply return the<a name="line.210"></a>
+<span class="sourceLineNo">211</span>   * new state, thus preserving the immutability of {@link NoLimitScannerContext}<a name="line.211"></a>
+<span class="sourceLineNo">212</span>   * @param state<a name="line.212"></a>
+<span class="sourceLineNo">213</span>   * @return The state that was passed in.<a name="line.213"></a>
+<span class="sourceLineNo">214</span>   */<a name="line.214"></a>
+<span class="sourceLineNo">215</span>  NextState setScannerState(NextState state) {<a name="line.215"></a>
+<span class="sourceLineNo">216</span>    if (!NextState.isValidState(state)) {<a name="line.216"></a>
+<span class="sourceLineNo">217</span>      throw new IllegalArgumentException("Cannot set to invalid state: " + state);<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>    this.scannerState = state;<a name="line.220"></a>
+<span class="sourceLineNo">221</span>    return state;<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>  /**<a name="line.224"></a>
+<span class="sourceLineNo">225</span>   * @return true when we have more cells for the current row. This usually because we have reached<a name="line.225"></a>
+<span class="sourceLineNo">226</span>   *         a limit in the middle of a row<a name="line.226"></a>
+<span class="sourceLineNo">227</span>   */<a name="line.227"></a>
+<span class="sourceLineNo">228</span>  boolean mayHaveMoreCellsInRow() {<a name="line.228"></a>
+<span class="sourceLineNo">229</span>    return scannerState == NextState.SIZE_LIMIT_REACHED_MID_ROW ||<a name="line.229"></a>
+<span class="sourceLineNo">230</span>        scannerState == NextState.TIME_LIMIT_REACHED_MID_ROW ||<a name="line.230"></a>
+<span class="sourceLineNo">231</span>        scannerState == NextState.BATCH_LIMIT_REACHED;<a name="line.231"></a>
+<span class="sourceLineNo">232</span>  }<a name="line.232"></a>
+<span class="sourceLineNo">233</span><a name="line.233"></a>
+<span class="sourceLineNo">234</span>  /**<a name="line.234"></a>
+<span class="sourceLineNo">235</span>   * @param checkerScope<a name="line.235"></a>
+<span class="sourceLineNo">236</span>   * @return true if the batch limit can be enforced in the checker's scope<a name="line.236"></a>
+<span class="sourceLineNo">237</span>   */<a name="line.237"></a>
+<span class="sourceLineNo">238</span>  boolean hasBatchLimit(LimitScope checkerScope) {<a name="line.238"></a>
+<span class="sourceLineNo">239</span>    return limits.canEnforceBatchLimitFromScope(checkerScope) &amp;&amp; limits.getBatch() &gt; 0;<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>   * @param checkerScope<a name="line.243"></a>
+<span class="sourceLineNo">244</span>   * @return true if the size limit can be enforced in the checker's scope<a name="line.244"></a>
+<span class="sourceLineNo">245</span>   */<a name="line.245"></a>
+<span class="sourceLineNo">246</span>  boolean hasSizeLimit(LimitScope checkerScope) {<a name="line.246"></a>
+<span class="sourceLineNo">247</span>    return limits.canEnforceSizeLimitFromScope(checkerScope)<a name="line.247"></a>
+<span class="sourceLineNo">248</span>        &amp;&amp; (limits.getDataSize() &gt; 0 || limits.getHeapSize() &gt; 0);<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>
+<span class="sourceLineNo">252</span>   * @param checkerScope<a name="line.252"></a>
+<span class="sourceLineNo">253</span>   * @return true if the time limit can be enforced in the checker's scope<a name="line.253"></a>
+<span class="sourceLineNo">254</span>   */<a name="line.254"></a>
+<span class="sourceLineNo">255</span>  boolean hasTimeLimit(LimitScope checkerScope) {<a name="line.255"></a>
+<span class="sourceLineNo">256</span>    return limits.canEnforceTimeLimitFromScope(checkerScope) &amp;&amp;<a name="line.256"></a>
+<span class="sourceLineNo">257</span>      (limits.getTime() &gt; 0 || returnImmediately);<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>   * @param checkerScope<a name="line.261"></a>
+<span class="sourceLineNo">262</span>   * @return true if any limit can be enforced within the checker's scope<a name="line.262"></a>
 <span class="sourceLineNo">263</span>   */<a name="line.263"></a>
-<span class="sourceLineNo">264</span>  void setSizeLimitScope(LimitScope scope) {<a name="line.264"></a>
-<span class="sourceLineNo">265</span>    limits.setSizeScope(scope);<a name="line.265"></a>
+<span class="sourceLineNo">264</span>  boolean hasAnyLimit(LimitScope checkerScope) {<a name="line.264"></a>
+<span class="sourceLineNo">265</span>    return hasBatchLimit(checkerScope) || hasSizeLimit(checkerScope) || hasTimeLimit(checkerScope);<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>  /**<a name="line.268"></a>
-<span class="sourceLineNo">269</span>   * @param scope The scope in which the time limit will be enforced<a name="line.269"></a>
+<span class="sourceLineNo">269</span>   * @param scope The scope in which the size limit will be enforced<a name="line.269"></a>
 <span class="sourceLineNo">270</span>   */<a name="line.270"></a>
-<span class="sourceLineNo">271</span>  void setTimeLimitScope(LimitScope scope) {<a name="line.271"></a>
-<span class="sourceLineNo">272</span>    limits.setTimeScope(scope);<a name="line.272"></a>
+<span class="sourceLineNo">271</span>  void setSizeLimitScope(LimitScope scope) {<a name="line.271"></a>
+<span class="sourceLineNo">272</span>    limits.setSizeScope(scope);<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>  int getBatchLimit() {<a name="line.275"></a>
-<span class="sourceLineNo">276</span>    return limits.getBatch();<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>  long getDataSizeLimit() {<a name="line.279"></a>
-<span class="sourceLineNo">280</span>    return limits.getDataSize();<a name="line.280"></a>
-<span class="sourceLineNo">281</span>  }<a name="line.281"></a>
-<span class="sourceLineNo">282</span><a name="line.282"></a>
-<span class="sourceLineNo">283</span>  long getTimeLimit() {<a name="line.283"></a>
-<span class="sourceLineNo">284</span>    return limits.getTime();<a name="line.284"></a>
-<span class="sourceLineNo">285</span>  }<a name="line.285"></a>
-<span class="sourceLineNo">286</span><a name="line.286"></a>
-<span class="sourceLineNo">287</span>  /**<a name="line.287"></a>
-<span class="sourceLineNo">288</span>   * @param checkerScope The scope that the limit is being checked from<a name="line.288"></a>
-<span class="sourceLineNo">289</span>   * @return true when the limit is enforceable from the checker's scope and it has been reached<a name="line.289"></a>
-<span class="sourceLineNo">290</span>   */<a name="line.290"></a>
-<span class="sourceLineNo">291</span>  boolean checkBatchLimit(LimitScope checkerScope) {<a name="line.291"></a>
-<span class="sourceLineNo">292</span>    return hasBatchLimit(checkerScope) &amp;&amp; progress.getBatch() &gt;= limits.getBatch();<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>  /**<a name="line.295"></a>
-<span class="sourceLineNo">296</span>   * @param checkerScope The scope that the limit is being checked from<a name="line.296"></a>
-<span class="sourceLineNo">297</span>   * @return true when the limit is enforceable from the checker's scope and it has been reached<a name="line.297"></a>
-<span class="sourceLineNo">298</span>   */<a name="line.298"></a>
-<span class="sourceLineNo">299</span>  boolean checkSizeLimit(LimitScope checkerScope) {<a name="line.299"></a>
-<span class="sourceLineNo">300</span>    return hasSizeLimit(checkerScope) &amp;&amp; (progress.getDataSize() &gt;= limits.getDataSize()<a name="line.300"></a>
-<span class="sourceLineNo">301</span>        || progress.getHeapSize() &gt;= limits.getHeapSize());<a name="line.301"></a>
-<span class="sourceLineNo">302</span>  }<a name="line.302"></a>
-<span class="sourceLineNo">303</span><a name="line.303"></a>
-<span class="sourceLineNo">304</span>  /**<a name="line.304"></a>
-<span class="sourceLineNo">305</span>   * @param checkerScope The scope that the limit is being checked from. The time limit is always<a name="line.305"></a>
-<span class="sourceLineNo">306</span>   *          checked against {@link System#currentTimeMillis()}<a name="line.306"></a>
-<span class="sourceLineNo">307</span>   * @return true when the limit is enforceable from the checker's scope and it has been reached<a name="line.307"></a>
-<span class="sourceLineNo">308</span>   */<a name="line.308"></a>
-<span class="sourceLineNo">309</span>  boolean checkTimeLimit(LimitScope checkerScope) {<a name="line.309"></a>
-<span class="sourceLineNo">310</span>    return hasTimeLimit(checkerScope) &amp;&amp; (System.currentTimeMillis() &gt;= limits.getTime());<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>   * @param checkerScope The scope that the limits are being checked from<a name="line.314"></a>
-<span class="sourceLineNo">315</span>   * @return true when some limit is enforceable from the checker's scope and it has been reached<a name="line.315"></a>
-<span class="sourceLineNo">316</span>   */<a name="line.316"></a>
-<span class="sourceLineNo">317</span>  boolean checkAnyLimitReached(LimitScope checkerScope) {<a name="line.317"></a>
-<span class="sourceLineNo">318</span>    return checkSizeLimit(checkerScope) || checkBatchLimit(checkerScope)<a name="line.318"></a>
-<span class="sourceLineNo">319</span>        || checkTimeLimit(checkerScope);<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>  Cell getLastPeekedCell() {<a name="line.322"></a>
-<span class="sourceLineNo">323</span>    return lastPeekedCell;<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>  void setLastPeekedCell(Cell lastPeekedCell) {<a name="line.326"></a>
-<span class="sourceLineNo">327</span>    this.lastPeekedCell = lastPeekedCell;<a name="line.327"></a>
+<span class="sourceLineNo">275</span>  /**<a name="line.275"></a>
+<span class="sourceLineNo">276</span>   * @param scope The scope in which the time limit will be enforced<a name="line.276"></a>
+<span class="sourceLineNo">277</span>   */<a name="line.277"></a>
+<span class="sourceLineNo">278</span>  void setTimeLimitScope(LimitScope scope) {<a name="line.278"></a>
+<span class="sourceLineNo">279</span>    limits.setTimeScope(scope);<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>  int getBatchLimit() {<a name="line.282"></a>
+<span class="sourceLineNo">283</span>    return limits.getBatch();<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>  long getDataSizeLimit() {<a name="line.286"></a>
+<span class="sourceLineNo">287</span>    return limits.getDataSize();<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>  long getTimeLimit() {<a name="line.290"></a>
+<span class="sourceLineNo">291</span>    return limits.getTime();<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>   * @param checkerScope The scope that the limit is being checked from<a name="line.295"></a>
+<span class="sourceLineNo">296</span>   * @return true when the limit is enforceable from the checker's scope and it has been reached<a name="line.296"></a>
+<span class="sourceLineNo">297</span>   */<a name="line.297"></a>
+<span class="sourceLineNo">298</span>  boolean checkBatchLimit(LimitScope checkerScope) {<a name="line.298"></a>
+<span class="sourceLineNo">299</span>    return hasBatchLimit(checkerScope) &amp;&amp; progress.getBatch() &gt;= limits.getBatch();<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 checkerScope The scope that the limit is being checked from<a name="line.303"></a>
+<span class="sourceLineNo">304</span>   * @return true when the limit is enforceable from the checker's scope and it has been reached<a name="line.304"></a>
+<span class="sourceLineNo">305</span>   */<a name="line.305"></a>
+<span class="sourceLineNo">306</span>  boolean checkSizeLimit(LimitScope checkerScope) {<a name="line.306"></a>
+<span class="sourceLineNo">307</span>    return hasSizeLimit(checkerScope) &amp;&amp; (progress.getDataSize() &gt;= limits.getDataSize()<a name="line.307"></a>
+<span class="sourceLineNo">308</span>        || progress.getHeapSize() &gt;= limits.getHeapSize());<a name="line.308"></a>
+<span class="sourceLineNo">309</span>  }<a name="line.309"></a>
+<span class="sourceLineNo">310</span><a name="line.310"></a>
+<span class="sourceLineNo">311</span>  /**<a name="line.311"></a>
+<span class="sourceLineNo">312</span>   * @param checkerScope The scope that the limit is being checked from. The time limit is always<a name="line.312"></a>
+<span class="sourceLineNo">313</span>   *          checked against {@link System#currentTimeMillis()}<a name="line.313"></a>
+<span class="sourceLineNo">314</span>   * @return true when the limit is enforceable from the checker's scope and it has been reached<a name="line.314"></a>
+<span class="sourceLineNo">315</span>   */<a name="line.315"></a>
+<span class="sourceLineNo">316</span>  boolean checkTimeLimit(LimitScope checkerScope) {<a name="line.316"></a>
+<span class="sourceLineNo">317</span>    return hasTimeLimit(checkerScope) &amp;&amp;<a name="line.317"></a>
+<span class="sourceLineNo">318</span>      (returnImmediately || System.currentTimeMillis() &gt;= limits.getTime());<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>   * @param checkerScope The scope that the limits are being checked from<a name="line.322"></a>
+<span class="sourceLineNo">323</span>   * @return true when some limit is enforceable from the checker's scope and it has been reached<a name="line.323"></a>
+<span class="sourceLineNo">324</span>   */<a name="line.324"></a>
+<span class="sourceLineNo">325</span>  boolean checkAnyLimitReached(LimitScope checkerScope) {<a name="line.325"></a>
+<span class="sourceLineNo">326</span>    return checkSizeLimit(checkerScope) || checkBatchLimit(checkerScope)<a name="line.326"></a>
+<span class="sourceLineNo">327</span>        || checkTimeLimit(checkerScope);<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>  @Override<a name="line.330"></a>
-<span class="sourceLineNo">331</span>  public String toString() {<a name="line.331"></a>
-<span class="sourceLineNo">332</span>    StringBuilder sb = new StringBuilder();<a name="line.332"></a>
-<span class="sourceLineNo">333</span>    sb.append("{");<a name="line.333"></a>
-<span class="sourceLineNo">334</span><a name="line.334"></a>
-<span class="sourceLineNo">335</span>    sb.append("limits:");<a name="line.335"></a>
-<span class="sourceLineNo">336</span>    sb.append(limits);<a name="line.336"></a>
+<span class="sourceLineNo">330</span>  Cell getLastPeekedCell() {<a name="line.330"></a>
+<span class="sourceLineNo">331</span>    return lastPeekedCell;<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>  void setLastPeekedCell(Cell lastPeekedCell) {<a name="line.334"></a>
+<span class="sourceLineNo">335</span>    this.lastPeekedCell = lastPeekedCell;<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>    sb.append(", progress:");<a name="line.338"></a>
-<span class="sourceLineNo">339</span>    sb.append(progress);<a name="line.339"></a>
-<span class="sourceLineNo">340</span><a name="line.340"></a>
-<span class="sourceLineNo">341</span>    sb.append(", keepProgress:");<a name="line.341"></a>
-<span class="sourceLineNo">342</span>    sb.append(keepProgress);<a name="line.342"></a>
-<span class="sourceLineNo">343</span><a name="line.343"></a>
-<span class="sourceLineNo">344</span>    sb.append(", state:");<a name="line.344"></a>
-<span class="sourceLineNo">345</span>    sb.append(scannerState);<a name="line.345"></a>
+<span class="sourceLineNo">338</span>  void returnImmediately() {<a name="line.338"></a>
+<span class="sourceLineNo">339</span>    this.returnImmediately = true;<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>  @Override<a name="line.342"></a>
+<span class="sourceLineNo">343</span>  public String toString() {<a name="line.343"></a>
+<span class="sourceLineNo">344</span>    StringBuilder sb = new StringBuilder();<a name="line.344"></a>
+<span class="sourceLineNo">345</span>    sb.append("{");<a name="line.345"></a>
 <span class="sourceLineNo">346</span><a name="line.346"></a>
-<span class="sourceLineNo">347</span>    sb.append("}");<a name="line.347"></a>
-<span class="sourceLineNo">348</span>    return sb.toString();<a name="line.348"></a>
-<span class="sourceLineNo">349</span>  }<a name="line.349"></a>
-<span class="sourceLineNo">350</span><a name="line.350"></a>
-<span class="sourceLineNo">351</span>  public static Builder newBuilder() {<a name="line.351"></a>
-<span class="sourceLineNo">352</span>    return new Builder();<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 static Builder newBuilder(boolean keepProgress) {<a name="line.355"></a>
-<span class="sourceLineNo">356</span>    return new Builder(keepProgress);<a name="line.356"></a>
-<span class="sourceLineNo">357</span>  }<a name="line.357"></a>
+<span class="sourceLineNo">347</span>    sb.append("limits:");<a name="line.347"></a>
+<span class="sourceLineNo">348</span>    sb.append(limits);<a name="line.348"></a>
+<span class="sourceLineNo">349</span><a name="line.349"></a>
+<span class="sourceLineNo">350</span>    sb.append(", progress:");<a name="line.350"></a>
+<span class="sourceLineNo">351</span>    sb.append(progress);<a name="line.351"></a>
+<span class="sourceLineNo">352</span><a name="line.352"></a>
+<span class="sourceLineNo">353</span>    sb.append(", keepProgress:");<a name="line.353"></a>
+<span class="sourceLineNo">354</span>    sb.append(keepProgress);<a name="line.354"></a>
+<span class="sourceLineNo">355</span><a name="line.355"></a>
+<span class="sourceLineNo">356</span>    sb.append(", state:");<a name="line.356"></a>
+<span class="sourceLineNo">357</span>    sb.append(scannerState);<a name="line.357"></a>
 <span class="sourceLineNo">358</span><a name="line.358"></a>
-<span class="sourceLineNo">359</span>  public static final class Builder {<a name="line.359"></a>
-<span class="sourceLineNo">360</span>    boolean keepProgress = DEFAULT_KEEP_PROGRESS;<a name="line.360"></a>
-<span class="sourceLineNo">361</span>    boolean trackMetrics = false;<a name="line.361"></a>
-<span class="sourceLineNo">362</span>    LimitFields limits = new LimitFields();<a name="line.362"></a>
-<span class="sourceLineNo">363</span><a name="line.363"></a>
-<span class="sourceLineNo">364</span>    private Builder() {<a name="line.364"></a>
-<span class="sourceLineNo">365</span>    }<a name="line.365"></a>
+<span class="sourceLineNo">359</span>    sb.append("}");<a name="line.359"></a>
+<span class="sourceLineNo">360</span>    return sb.toString();<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 static Builder newBuilder() {<a name="line.363"></a>
+<span class="sourceLineNo">364</span>    return new Builder();<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>    private Builder(boolean keepProgress) {<a name="line.367"></a>
-<span class="sourceLineNo">368</span>      this.keepProgress = keepProgress;<a name="line.368"></a>
-<span class="sourceLineNo">369</span>    }<a name="line.369"></a>
+<span class="sourceLineNo">367</span>  public static Builder newBuilder(boolean keepProgress) {<a name="line.367"></a>
+<span class="sourceLineNo">368</span>    return new Builder(keepProgress);<a name="line.368"></a>
+<span class="sourceLineNo">369</span>  }<a name="line.369"></a>
 <span class="sourceLineNo">370</span><a name="line.370"></a>
-<span class="sourceLineNo">371</span>    public Builder setKeepProgress(boolean keepProgress) {<a name="line.371"></a>
-<span class="sourceLineNo">372</span>      this.keepProgress = keepProgress;<a name="line.372"></a>
-<span class="sourceLineNo">373</span>      return this;<a name="line.373"></a>
-<span class="sourceLineNo">374</span>    }<a name="line.374"></a>
+<span class="sourceLineNo">371</span>  public static final class Builder {<a name="line.371"></a>
+<span class="sourceLineNo">372</span>    boolean keepProgress = DEFAULT_KEEP_PROGRESS;<a name="line.372"></a>
+<span class="sourceLineNo">373</span>    boolean trackMetrics = false;<a name="line.373"></a>
+<span class="sourceLineNo">374</span>    LimitFields limits = new LimitFields();<a name="line.374"></a>
 <span class="sourceLineNo">375</span><a name="line.375"></a>
-<span class="sourceLineNo">376</span>    public Builder setTrackMetrics(boolean trackMetrics) {<a name="line.376"></a>
-<span class="sourceLineNo">377</span>      this.trackMetrics = trackMetrics;<a name="line.377"></a>
-<span class="sourceLineNo">378</span>      return this;<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 Builder setSizeLimit(LimitScope sizeScope, long dataSizeLimit, long heapSizeLimit) {<a name="line.381"></a>
-<span class="sourceLineNo">382</span>      limits.setDataSize(dataSizeLimit);<a name="line.382"></a>
-<span class="sourceLineNo">383</span>      limits.setHeapSize(heapSizeLimit);<a name="line.383"></a>
-<span class="sourceLineNo">384</span>      limits.setSizeScope(sizeScope);<a name="line.384"></a>
+<span class="sourceLineNo">376</span>    private Builder() {<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>    private Builder(boolean keepProgress) {<a name="line.379"></a>
+<span class="sourceLineNo">380</span>      this.keepProgress = keepProgress;<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>    public Builder setKeepProgress(boolean keepProgress) {<a name="line.383"></a>
+<span class="sourceLineNo">384</span>      this.keepProgress = keepProgress;<a name="line.384"></a>
 <span class="sourceLineNo">385</span>      return this;<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 Builder setTimeLimit(LimitScope timeScope, long timeLimit) {<a name="line.388"></a>
-<span class="sourceLineNo">389</span>      limits.setTime(timeLimit);<a name="line.389"></a>
-<span class="sourceLineNo">390</span>      limits.setTimeScope(timeScope);<a name="line.390"></a>
-<span class="sourceLineNo">391</span>      return this;<a name="line.391"></a>
-<span class="sourceLineNo">392</span>    }<a name="line.392"></a>
-<span class="sourceLineNo">393</span><a name="line.393"></a>
-<span class="sourceLineNo">394</span>    public Builder setBatchLimit(int batchLimit) {<a name="line.394"></a>
-<span class="sourceLineNo">395</span>      limits.setBatch(batchLimit);<a name="line.395"></a>
-<span class="sourceLineNo">396</span>      return this;<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>    public ScannerContext build() {<a name="line.399"></a>
-<span class="sourceLineNo">400</span>      return new ScannerContext(keepProgress, limits, trackMetrics);<a name="line.400"></a>
-<span class="sourceLineNo">401</span>    }<a name="line.401"></a>
-<span class="sourceLineNo">402</span>  }<a name="line.402"></a>
-<span class="sourceLineNo">403</span><a name="line.403"></a>
-<span class="sourceLineNo">404</span>  /**<a name="line.404"></a>
-<span class="sourceLineNo">405</span>   * The possible states a scanner may be in following a call to {@link InternalScanner#next(List)}<a name="line.405"></a>
-<span class="sourceLineNo">406</span>   */<a name="line.406"></a>
-<span class="sourceLineNo">407</span>  public enum NextState {<a name="line.407"></a>
-<span class="sourceLineNo">408</span>    MORE_VALUES(true, false),<a name="line.408"></a>
-<span class="sourceLineNo">409</span>    NO_MORE_VALUES(false, false),<a name="line.409"></a>
-<span class="sourceLineNo">410</span>    SIZE_LIMIT_REACHED(true, true),<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>     * Special case of size limit reached to indicate that the size limit was reached in the middle<a name="line.413"></a>
-<span class="sourceLineNo">414</span>     * of a row and thus a partial results was formed<a name="line.414"></a>
-<span class="sourceLineNo">415</span>     */<a name="line.415"></a>
-<span class="sourceLineNo">416</span>    SIZE_LIMIT_REACHED_MID_ROW(true, true),<a name="line.416"></a>
-<span class="sourceLineNo">417</span>    TIME_LIMIT_REACHED(true, true),<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>     * Special case of time limit reached to indicate that the time limit was reached in the middle<a name="line.420"></a>
-<span class="sourceLineNo">421</span>     * of a row and thus a partial results was formed<a name="line.421"></a>
-<span class="sourceLineNo">422</span>     */<a name="line.422"></a>
-<span class="sourceLineNo">423</span>    TIME_LIMIT_REACHED_MID_ROW(true, true),<a name="line.423"></a>
-<span class="sourceLineNo">424</span>    BATCH_LIMIT_REACHED(true, true);<a name="line.424"></a>
-<span class="sourceLineNo">425</span><a name="line.425"></a>
-<span class="sourceLineNo">426</span>    private final boolean moreValues;<a name="line.426"></a>
-<span class="sourceLineNo">427</span>    private final boolean limitReached;<a name="line.427"></a>
-<span class="sourceLineNo">428</span><a name="line.428"></a>
-<span class="sourceLineNo">429</span>    private NextState(boolean moreValues, boolean limitReached) {<a name="line.429"></a>
-<span class="sourceLineNo">430</span>      this.moreValues = moreValues;<a name="line.430"></a>
-<span class="sourceLineNo">431</span>      this.limitReached = limitReached;<a name="line.431"></a>
-<span class="sourceLineNo">432</span>    }<a name="line.432"></a>
-<span class="sourceLineNo">433</span><a name="line.433"></a>
-<span class="sourceLineNo">434</span>    /**<a name="line.434"></a>
-<span class="sourceLineNo">435</span>     * @return true when the state indicates that more values may follow those that have been<a name="line.435"></a>
-<span class="sourceLineNo">436</span>     *         returned<a name="line.436"></a>
-<span class="sourceLineNo">437</span>     */<a name="line.437"></a>
-<span class="sourceLineNo">438</span>    public boolean hasMoreValues() {<a name="line.438"></a>
-<span class="sourceLineNo">439</span>      return this.moreValues;<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>     * @return true when the state indicates that a limit has been reached and scan should stop<a name="line.443"></a>
-<span class="sourceLineNo">444</span>     */<a name="line.444"></a>
-<span class="sourceLineNo">445</span>    public boolean limitReached() {<a name="line.445"></a>
-<span class="sourceLineNo">446</span>      return this.limitReached;<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>    public static boolean isValidState(NextState state) {<a name="line.449"></a>
-<span class="sourceLineNo">450</span>      return state != null;<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>    public static boolean hasMoreValues(NextState state) {<a name="line.453"></a>
-<span class="sourceLineNo">454</span>      return isValidState(state) &amp;&amp; state.hasMoreValues();<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>  /**<a name="line.458"></a>
-<span class="sourceLineNo">459</span>   * The various scopes where a limit can be enforced. Used to differentiate when a limit should be<a name="line.459"></a>
-<span class="sourceLineNo">460</span>   * enforced or not.<a name="line.460"></a>
-<span class="sourceLineNo">461</span>   */<a name="line.461"></a>
-<span class="sourceLineNo">462</span>  public enum LimitScope {<a name="line.462"></a>
-<span class="sourceLineNo">463</span>    /**<a name="line.463"></a>
-<span class="sourceLineNo">464</span>     * Enforcing a limit between rows means that the limit will not be considered until all the<a name="line.464"></a>
-<span class="sourceLineNo">465</span>     * cells for a particular row have been retrieved<a name="line.465"></a>
-<span class="sourceLineNo">466</span>     */<a name="line.466"></a>
-<span class="sourceLineNo">467</span>    BETWEEN_ROWS(0),<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>     * Enforcing a limit between cells means that the limit will be considered after each full cell<a name="line.470"></a>
-<span class="sourceLineNo">471</span>     * has been retrieved<a name="line.471"></a>
-<span class="sourceLineNo">472</span>     */<a name="line.472"></a>
-<span class="sourceLineNo">473</span>    BETWEEN_CELLS(1);<a name="line.473"></a>
-<span class="sourceLineNo">474</span><a name="line.474"></a>
+<span class="sourceLineNo">388</span>    public Builder setTrackMetrics(boolean trackMetrics) {<a name="line.388"></a>
+<span class="sourceLineNo">389</span>      this.trackMetrics = trackMetrics;<a name="line.389"></a>
+<span class="sourceLineNo">390</span>      return this;<a name="line.390"></a>
+<span class="sourceLineNo">391</span>    }<a name="line.391"></a>
+<span class="sourceLineNo">392</span><a name="line.392"></a>
+<span class="sourceLineNo">393</span>    public Builder setSizeLimit(LimitScope sizeScope, long dataSizeLimit, long heapSizeLimit) {<a name="line.393"></a>
+<span class="sourceLineNo">394</span>      limits.setDataSize(dataSizeLimit);<a name="line.394"></a>
+<span class="sourceLineNo">395</span>      limits.setHeapSize(heapSizeLimit);<a name="line.395"></a>
+<span class="sourceLineNo">396</span>      limits.setSizeScope(sizeScope);<a name="line.396"></a>
+<span class="sourceLineNo">397</span>      return this;<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>    public Builder setTimeLimit(LimitScope timeScope, long timeLimit) {<a name="line.400"></a>
+<span class="sourceLineNo">401</span>      limits.setTime(timeLimit);<a name="line.401"></a>
+<span class="sourceLineNo">402</span>      limits.setTimeScope(timeScope);<a name="line.402"></a>
+<span class="sourceLineNo">403</span>      return this;<a name="line.403"></a>
+<span class="sourceLineNo">404</span>    }<a name="line.404"></a>
+<span class="sourceLineNo">405</span><a name="line.405"></a>
+<span class="sourceLineNo">406</span>    public Builder setBatchLimit(int batchLimit) {<a name="line.406"></a>
+<span class="sourceLineNo">407</span>      limits.setBatch(batchLimit);<a name="line.407"></a>
+<span class="sourceLineNo">408</span>      return this;<a name="line.408"></a>
+<span class="sourceLineNo">409</span>    }<a name="line.409"></a>
+<span class="sourceLineNo">410</span><a name="line.410"></a>
+<span class="sourceLineNo">411</span>    public ScannerContext build() {<a name="line.411"></a>
+<span class="sourceLineNo">412</span>      return new ScannerContext(keepProgress, limits, trackMetrics);<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><a name="line.415"></a>
+<span class="sourceLineNo">416</span>  /**<a name="line.416"></a>
+<span class="sourceLineNo">417</span>   * The possible states a scanner may be in following a call to {@link InternalScanner#next(List)}<a name="line.417"></a>
+<span class="sourceLineNo">418</span>   */<a name="line.418"></a>
+<span class="sourceLineNo">419</span>  public enum NextState {<a name="line.419"></a>
+<span class="sourceLineNo">420</span>    MORE_VALUES(true, false),<a name="line.420"></a>
+<span class="sourceLineNo">421</span>    NO_MORE_VALUES(false, false),<a name="line.421"></a>
+<span class="sourceLineNo">422</span>    SIZE_LIMIT_REACHED(true, true),<a name="line.422"></a>
+<span class="sourceLineNo">423</span><a name="line.423"></a>
+<span class="sourceLineNo">424</span>    /**<a name="line.424"></a>
+<span class="sourceLineNo">425</span>     * Special case of size limit reached to indicate that the size limit was reached in the middle<a name="line.425"></a>
+<span class="sourceLineNo">426</span>     * of a row and thus a partial results was formed<a name="line.426"></a>
+<span class="sourceLineNo">427</span>     */<a name="line.427"></a>
+<span class="sourceLineNo">428</span>    SIZE_LIMIT_REACHED_MID_ROW(true, true),<a name="line.428"></a>
+<span class="sourceLineNo">429</span>    TIME_LIMIT_REACHED(true, true),<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>     * Special case of time limit reached to indicate that the time limit was reached in the middle<a name="line.432"></a>
+<span class="sourceLineNo">433</span>     * of a row and thus a partial results was formed<a name="line.433"></a>
+<span class="sourceLineNo">434</span>     */<a name="line.434"></a>
+<span class="sourceLineNo">435</span>    TIME_LIMIT_REACHED_MID_ROW(true, true),<a name="line.435"></a>
+<span class="sourceLineNo">436</span>    BATCH_LIMIT_REACHED(true, true);<a name="line.436"></a>
+<span class="sourceLineNo">437</span><a name="line.437"></a>
+<span class="sourceLineNo">438</span>    private final boolean moreValues;<a name="line.438"></a>
+<span class="sourceLineNo">439</span>    private final boolean limitReached;<a name="line.439"></a>
+<span class="sourceLineNo">440</span><a name="line.440"></a>
+<span class="sourceLineNo">441</span>    private NextState(boolean moreValues, boolean limitReached) {<a name="line.441"></a>
+<span class="sourceLineNo">442</span>      this.moreValues = moreValues;<a name="line.442"></a>
+<span class="sourceLineNo">443</span>      this.limitReached = limitReached;<a name="line.443"></a>
+<span class="sourceLineNo">444</span>    }<a name="line.444"></a>
+<span class="sourceLineNo">445</span><a name="line.445"></a>
+<span class="sourceLineNo">446</span>    /**<a name="line.446"></a>
+<span class="sourceLineNo">447</span>     * @return true when the state indicates that more values may follow those that have been<a name="line.447"></a>
+<span class="sourceLineNo">448</span>     *         returned<a name="line.448"></a>
+<span class="sourceLineNo">449</span>     */<a name="line.449"></a>
+<span class="sourceLineNo">450</span>    public boolean hasMoreValues() {<a name="line.450"></a>
+<span class="sourceLineNo">451</span>      return this.moreValues;<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>     * @return true when the state indicates that a limit has been reached and scan should stop<a name="line.455"></a>
+<span class="sourceLineNo">456</span>     */<a name="line.456"></a>
+<span class="sourceLineNo">457</span>    public boolean limitReached() {<a name="line.457"></a>
+<span class="sourceLineNo">458</span>      return this.limitReached;<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>    public static boolean isValidState(NextState state) {<a name="line.461"></a>
+<span class="sourceLineNo">462</span>      return state != 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>    public static boolean hasMoreValues(NextState state) {<a name="line.465"></a>
+<span class="sourceLineNo">466</span>      return isValidState(state) &amp;&amp; state.hasMoreValues();<a name="line.466"></a>
+<span class="sourceLineNo">467</span>    }<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>   * The various scopes where a limit can be enforced. Used to differentiate when a limit should be<a name="line.471"></a>
+<span class="sourceLineNo">472</span>   * enforced or not.<a name="line.472"></a>
+<span class="sourceLineNo">473</span>   */<a name="line.473"></a>
+<span class="sourceLineNo">474</span>  public enum LimitScope {<a name="line.474"></a>
 <span class="sourceLineNo">475</span>    /**<a name="line.475"></a>
-<span class="sourceLineNo">476</span>     * When enforcing a limit, we must check that the scope is appropriate for enforcement.<a name="line.476"></a>
-<span class="sourceLineNo">477</span>     * &lt;p&gt;<a name="line.477"></a>
-<span class="sourceLineNo">478</span>     * To communicate this concept, each scope has a depth. A limit will be enforced if the depth of<a name="line.478"></a>
-<span class="sourceLineNo">479</span>     * the checker's scope is less than or equal to the limit's scope. This means that when checking<a name="line.479"></a>
-<span class="sourceLineNo">480</span>     * limits, the checker must know their own scope (i.e. are they checking the limits between<a name="line.480"></a>
-<span class="sourceLineNo">481</span>     * rows, between cells, etc...)<a name="line.481"></a>
-<span class="sourceLineNo">482</span>     */<a name="line.482"></a>
-<span class="sourceLineNo">483</span>    final int depth;<a name="line.483"></a>
-<span class="sourceLineNo">484</span><a name="line.484"></a>
-<span class="sourceLineNo">485</span>    LimitScope(int depth) {<a name="line.485"></a>
-<span class="sourceLineNo">486</span>      this.depth = depth;<a name="line.486"></a>
-<span class="sourceLineNo">487</span>    }<a name="line.487"></a>
-<span class="sourceLineNo">488</span><a name="line.488"></a>
-<span class="sourceLineNo">489</span>    final int depth() {<a name="line.489"></a>
-<span class="sourceLineNo">490</span>      return depth;<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>     * @param checkerScope The scope in which the limit is being checked<a name="line.494"></a>
-<span class="sourceLineNo">495</span>     * @return true when the checker is in a scope that indicates the limit can be enforced. Limits<a name="line.495"></a>
-<span class="sourceLineNo">496</span>     *         can be enforced from "higher or equal" scopes (i.e. the checker's scope is at a<a name="line.496"></a>
-<span class="sourceLineNo">497</span>     *         lesser depth than the limit)<a name="line.497"></a>
-<span class="sourceLineNo">498</span>     */<a name="line.498"></a>
-<span class="sourceLineNo">499</span>    boolean canEnforceLimitFromScope(LimitScope checkerScope) {<a name="line.499"></a>
-<span class="sourceLineNo">500</span>      return checkerScope != null &amp;&amp; checkerScope.depth() &lt;= depth;<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><a name="line.503"></a>
-<span class="sourceLineNo">504</span>  /**<a name="line.504"></a>
-<span class="sourceLineNo">505</span>   * The different fields that can be used as limits in calls to<a name="line.505"></a>
-<span class="sourceLineNo">506</span>   * {@link InternalScanner#next(java.util.List)} and {@link RegionScanner#next(java.util.List)}<a name="line.506"></a>
-<span class="sourceLineNo">507</span>   */<a name="line.507"></a>
-<span class="sourceLineNo">508</span>  private static class LimitFields {<a name="line.508"></a>
-<span class="sourceLineNo">509</span>    /**<a name="line.509"></a>
-<span class="sourceLineNo">510</span>     * Default values of the limit fields. Defined such that if a field does NOT change from its<a name="line.510"></a>
-<span class="sourceLineNo">511</span>     * default, it will not be enforced<a name="line.511"></a>
-<span class="sourceLineNo">512</span>     */<a name="line.512"></a>
-<span class="sourceLineNo">513</span>    private static int DEFAULT_BATCH = -1;<a name="line.513"></a>
-<span class="sourceLineNo">514</span>    private static long DEFAULT_SIZE = -1L;<a name="line.514"></a>
-<span class="sourceLineNo">515</span>    private static long DEFAULT_TIME = -1L;<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>     * Default scope that is assigned to a limit if a scope is not specified.<a name="line.518"></a>
-<span class="sourceLineNo">519</span>     */<a name="line.519"></a>
-<span class="sourceLineNo">520</span>    private static final LimitScope DEFAULT_SCOPE = LimitScope.BETWEEN_ROWS;<a name="line.520"></a>
-<span class="sourceLineNo">521</span><a name="line.521"></a>
-<span class="sourceLineNo">522</span>    // The batch limit will always be enforced between cells, thus, there isn't a field to hold the<a name="line.522"></a>
-<span class="sourceLineNo">523</span>    // batch scope<a name="line.523"></a>
-<span class="sourceLineNo">524</span>    int batch = DEFAULT_BATCH;<a name="line.524"></a>
-<span class="sourceLineNo">525</span><a name="line.525"></a>
-<span class="sourceLineNo">526</span>    LimitScope sizeScope = DEFAULT_SCOPE;<a name="line.526"></a>
-<span class="sourceLineNo">527</span>    // The sum of cell data sizes(key + value). The Cell data might be in on heap or off heap area.<a name="line.527"></a>
-<span class="sourceLineNo">528</span>    long dataSize = DEFAULT_SIZE;<a name="line.528"></a>
-<span class="sourceLineNo">529</span>    // The sum of heap space occupied by all tracked cells. This includes Cell POJO's overhead as<a name="line.529"></a>
-<span class="sourceLineNo">530</span>    // such AND data cells of Cells which are in on heap area.<a name="line.530"></a>
-<span class="sourceLineNo">531</span>    long heapSize = DEFAULT_SIZE;<a name="line.531"></a>
-<span class="sourceLineNo">532</span><a name="line.532"></a>
-<span class="sourceLineNo">533</span>    LimitScope timeScope = DEFAULT_SCOPE;<a name="line.533"></a>
-<span class="sourceLineNo">534</span>    long time = DEFAULT_TIME;<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>     * Fields keep their default values.<a name="line.537"></a>
-<span class="sourceLineNo">538</span>     */<a name="line.538"></a>
-<span class="sourceLineNo">539</span>    LimitFields() {<a name="line.539"></a>
-<span class="sourceLineNo">540</span>    }<a name="line.540"></a>
-<span class="sourceLineNo">541</span><a name="line.541"></a>
-<span class="sourceLineNo">542</span>    LimitFields(int batch, LimitScope sizeScope, long size, long heapSize, LimitScope timeScope,<a name="line.542"></a>
-<span class="sourceLineNo">543</span>        long time) {<a name="line.543"></a>
-<span class="sourceLineNo">544</span>      setFields(batch, sizeScope, size, heapSize, timeScope, time);<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>    void copy(LimitFields limitsToCopy) {<a name="line.547"></a>
-<span class="sourceLineNo">548</span>      if (limitsToCopy != null) {<a name="line.548"></a>
-<span class="sourceLineNo">549</span>        setFields(limitsToCopy.getBatch(), limitsToCopy.getSizeScope(), limitsToCopy.getDataSize(),<a name="line.549"></a>
-<span class="sourceLineNo">550</span>            limitsToCopy.getHeapSize(), limitsToCopy.getTimeScope(), limitsToCopy.getTime());<a name="line.550"></a>
-<span class="sourceLineNo">551</span>      }<a name="line.551"></a>
+<span class="sourceLineNo">476</span>     * Enforcing a limit between rows means that the limit will not be considered until all the<a name="line.476"></a>
+<span class="sourceLineNo">477</span>     * cells for a particular row have been retrieved<a name="line.477"></a>
+<span class="sourceLineNo">478</span>     */<a name="line.478"></a>
+<span class="sourceLineNo">479</span>    BETWEEN_ROWS(0),<a name="line.479"></a>
+<span class="sourceLineNo">480</span><a name="line.480"></a>
+<span class="sourceLineNo">481</span>    /**<a name="line.481"></a>
+<span class="sourceLineNo">482</span>     * Enforcing a limit between cells means that the limit will be considered after each full cell<a name="line.482"></a>
+<span class="sourceLineNo">483</span>     * has been retrieved<a name="line.483"></a>
+<span class="sourceLineNo">484</span>     */<a name="line.484"></a>
+<span class="sourceLineNo">485</span>    BETWEEN_CELLS(1);<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>     * When enforcing a limit, we must check that the scope is appropriate for enforcement.<a name="line.488"></a>
+<span class="sourceLineNo">489</span>     * &lt;p&gt;<a name="line.489"></a>
+<span class="sourceLineNo">490</span>     * To communicate this concept, each scope has a depth. A limit will be enforced if the depth of<a name="line.490"></a>
+<span class="sourceLineNo">491</span>     * the checker's scope is less than or equal to the limit's scope. This means that when checking<a name="line.491"></a>
+<span class="sourceLineNo">492</span>     * limits, the checker must know their own scope (i.e. are they checking the limits between<a name="line.492"></a>
+<span class="sourceLineNo">493</span>     * rows, between cells, etc...)<a name="line.493"></a>
+<span class="sourceLineNo">494</span>     */<a name="line.494"></a>
+<span class="sourceLineNo">495</span>    final int depth;<a name="line.495"></a>
+<span class="sourceLineNo">496</span><a name="line.496"></a>
+<span class="sourceLineNo">497</span>    LimitScope(int depth) {<a name="line.497"></a>
+<span class="sourceLineNo">498</span>      this.depth = depth;<a name="line.498"></a>
+<span class="sourceLineNo">499</span>    }<a name="line.499"></a>
+<span class="sourceLineNo">500</span><a name="line.500"></a>
+<span class="sourceLineNo">501</span>    final int depth() {<a name="line.501"></a>
+<span class="sourceLineNo">502</span>      return depth;<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>    /**<a name="line.505"></a>
+<span class="sourceLineNo">506</span>     * @param checkerScope The scope in which the limit is being checked<a name="line.506"></a>
+<span class="sourceLineNo">507</span>     * @return true when the checker is in a scope that indicates the limit can be enforced. Limits<a name="line.507"></a>
+<span class="sourceLineNo">508</span>     *         can be enforced from "higher or equal" scopes (i.e. the checker's scope is at a<a name="line.508"></a>
+<span class="sourceLineNo">509</span>     *         lesser depth than the limit)<a name="line.509"></a>
+<span class="sourceLineNo">510</span>     */<a name="line.510"></a>
+<span class="sourceLineNo">511</span>    boolean canEnforceLimitFromScope(LimitScope checkerScope) {<a name="line.511"></a>
+<span class="sourceLineNo">512</span>      return checkerScope != null &amp;&amp; checkerScope.depth() &lt;= depth;<a name="line.512"></a>
+<span class="sourceLineNo">513</span>    }<a name="line.513"></a>
+<span class="sourceLineNo">514</span>  }<a name="line.514"></a>
+<span class="sourceLineNo">515</span><a name="line.515"></a>
+<span class="sourceLineNo">516</span>  /**<a name="line.516"></a>
+<span class="sourceLineNo">517</span>   * The different fields that can be used as limits in calls to<a name="line.517"></a>
+<span class="sourceLineNo">518</span>   * {@link InternalScanner#next(java.util.List)} and {@link RegionScanner#next(java.util.List)}<a name="line.518"></a>
+<span class="sourceLineNo">519</span>   */<a name="line.519"></a>
+<span class="sourceLineNo">520</span>  private static class LimitFields {<a name="line.520"></a>
+<span class="sourceLineNo">521</span>    /**<a name="line.521"></a>
+<span class="sourceLineNo">522</span>     * Default values of the limit fields. Defined such that if a field does NOT change from its<a name="line.522"></a>
+<span class="sourceLineNo">523</span>     * default, it will not be enforced<a name="line.523"></a>
+<span class="sourceLineNo">524</span>     */<a name="line.524"></a>
+<span class="sourceLineNo">525</span>    private static int DEFAULT_BATCH = -1;<a name="line.525"></a>
+<span class="sourceLineNo">526</span>    private static long DEFAULT_SIZE = -1L;<a name="line.526"></a>
+<span class="sourceLineNo">527</span>    private static long DEFAULT_TIME = -1L;<a name="line.527"></a>
+<span class="sourceLineNo">528</span><a name="line.528"></a>
+<span class="sourceLineNo">529</span>    /**<a name="line.529"></a>
+<span class="sourceLineNo">530</span>     * Default scope that is assigned to a limit if a scope is not specified.<a name="line.530"></a>
+<span class="sourceLineNo">531</span>     */<a name="line.531"></a>
+<span class="sourceLineNo">532</span>    private static final LimitScope DEFAULT_SCOPE = LimitScope.BETWEEN_ROWS;<a name="line.532"></a>
+<span class="sourceLineNo">533</span><a name="line.533"></a>
+<span class="sourceLineNo">534</span>    // The batch limit will always be enforced between cells, thus, there isn't a field to hold the<a name="line.534"></a>
+<span class="sourceLineNo">535</span>    // batch scope<a name="line.535"></a>
+<span class="sourceLineNo">536</span>    int batch = DEFAULT_BATCH;<a name="line.536"></a>
+<span class="sourceLineNo">537</span><a name="line.537"></a>
+<span class="sourceLineNo">538</span>    LimitScope sizeScope = DEFAULT_SCOPE;<a name="line.538"></a>
+<span class="sourceLineNo">539</span>    // The sum of cell data sizes(key + value). The Cell data might be in on heap or off heap area.<a name="line.539"></a>
+<span class="sourceLineNo">540</span>    long dataSize = DEFAULT_SIZE;<a name="line.540"></a>
+<span class="sourceLineNo">541</span>    // The sum of heap space occupied by all tracked cells. This includes Cell POJO's overhead as<a name="line.541"></a>
+<span class="sourceLineNo">542</span>    // such AND data cells of Cells which are in on heap area.<a name="line.542"></a>
+<span class="sourceLineNo">543</span>    long heapSize = DEFAULT_SIZE;<a name="line.543"></a>
+<span class="sourceLineNo">544</span><a name="line.544"></a>
+<span class="sourceLineNo">545</span>    LimitScope timeScope = DEFAULT_SCOPE;<a name="line.545"></a>
+<span class="sourceLineNo">546</span>    long time = DEFAULT_TIME;<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>     * Fields keep their default values.<a name="line.549"></a>
+<span class="sourceLineNo">550</span>     */<a name="line.550"></a>
+<span class="sourceLineNo">551</span>    LimitFields() {<a name="line.551"></a>
 <span class="sourceLineNo">552</span>    }<a name="line.552"></a>
 <span class="sourceLineNo">553</span><a name="line.553"></a>
-<span class="sourceLineNo">554</span>    /**<a name="line.554"></a>
-<span class="sourceLineNo">555</span>     * Set all fields together.<a name="line.555"></a>
-<span class="sourceLineNo">556</span>     */<a name="line.556"></a>
-<span class="sourceLineNo">557</span>    void setFields(int batch, LimitScope sizeScope, long dataSize, long heapSize,<a name="line.557"></a>
-<span class="sourceLineNo">558</span>        LimitScope timeScope, long time) {<a name="line.558"></a>
-<span class="sourceLineNo">559</span>      setBatch(batch);<a name="line.559"></a>
-<span class="sourceLineNo">560</span>      setSizeScope(sizeScope);<a name="line.560"></a>
-<span class="sourceLineNo">561</span>      setDataSize(dataSize);<a name="line.561"></a>
-<span class="sourceLineNo">562</span>      setHeapSize(heapSize);<a name="line.562"></a>
-<span class="sourceLineNo">563</span>      setTimeScope(timeScope);<a name="line.563"></a>
-<span class="sourceLineNo">564</span>      setTime(time);<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>    int getBatch() {<a name="line.567"></a>
-<span class="sourceLineNo">568</span>      return this.batch;<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>    void setBatch(int batch) {<a name="line.571"></a>
-<span class="sourceLineNo">572</span>      this.batch = batch;<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>    /**<a name="line.575"></a>
-<span class="sourceLineNo">576</span>     * @param checkerScope<a name="line.576"></a>
-<span class="sourceLineNo">577</span>     * @return true when the limit can be enforced from the scope of the checker<a name="line.577"></a>
-<span class="sourceLineNo">578</span>     */<a name="line.578"></a>
-<span class="sourceLineNo">579</span>    boolean canEnforceBatchLimitFromScope(LimitScope checkerScope) {<a name="line.579"></a>
-<span class="sourceLineNo">580</span>      return LimitScope.BETWEEN_CELLS.canEnforceLimitFromScope(checkerScope);<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>    long getDataSize() {<a name="line.583"></a>
-<span class="sourceLineNo">584</span>      return this.dataSize;<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>    long getHeapSize() {<a name="line.587"></a>
-<span class="sourceLineNo">588</span>      return this.heapSize;<a name="line.588"></a>
-<span class="sourceLineNo">589</span>    }<a name="line.589"></a>
-<span class="sourceLineNo">590</span><a name="line.590"></a>
-<span class="sourceLineNo">591</span>    void setDataSize(long dataSize) {<a name="line.591"></a>
-<span class="sourceLineNo">592</span>      this.dataSize = dataSize;<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>    void setHeapSize(long heapSize) {<a name="line.595"></a>
-<span class="sourceLineNo">596</span>      this.heapSize = heapSize;<a name="line.596"></a>
-<span class="sourceLineNo">597</span>    }<a name="line.597"></a>
-<span class="sourceLineNo">598</span><a name="line.598"></a>
-<span class="sourceLineNo">599</span>    /**<a name="line.599"></a>
-<span class="sourceLineNo">600</span>     * @return {@link LimitScope} indicating scope in which the size limit is enforced<a name="line.600"></a>
-<span class="sourceLineNo">601</span>     */<a name="line.601"></a>
-<span class="sourceLineNo">602</span>    LimitScope getSizeScope() {<a name="line.602"></a>
-<span class="sourceLineNo">603</span>      return this.sizeScope;<a name="line.603"></a>
+<span class="sourceLineNo">554</span>    void copy(LimitFields limitsToCopy) {<a name="line.554"></a>
+<span class="sourceLineNo">555</span>      if (limitsToCopy != null) {<a name="line.555"></a>
+<span class="sourceLineNo">556</span>        setFields(limitsToCopy.getBatch(), limitsToCopy.getSizeScope(), limitsToCopy.getDataSize(),<a name="line.556"></a>
+<span class="sourceLineNo">557</span>            limitsToCopy.getHeapSize(), limitsToCopy.getTimeScope(), limitsToCopy.getTime());<a name="line.557"></a>
+<span class="sourceLineNo">558</span>      }<a name="line.558"></a>
+<span class="sourceLineNo">559</span>    }<a name="line.559"></a>
+<span class="sourceLineNo">560</span><a name="line.560"></a>
+<span class="sourceLineNo">561</span>    /**<a name="line.561"></a>
+<span class="sourceLineNo">562</span>     * Set all fields together.<a name="line.562"></a>
+<span class="sourceLineNo">563</span>     */<a name="line.563"></a>
+<span class="sourceLineNo">564</span>    void setFields(int batch, LimitScope sizeScope, long dataSize, long heapSize,<a name="line.564"></a>
+<span class="sourceLineNo">565</span>        LimitScope timeScope, long time) {<a name="line.565"></a>
+<span class="sourceLineNo">566</span>      setBatch(batch);<a name="line.566"></a>
+<span class="sourceLineNo">567</span>      setSizeScope(sizeScope);<a name="line.567"></a>
+<span class="sourceLineNo">568</span>      setDataSize(dataSize);<a name="line.568"></a>
+<span class="sourceLineNo">569</span>      setHeapSize(heapSize);<a name="line.569"></a>
+<span class="sourceLineNo">570</span>      setTimeScope(timeScope);<a name="line.570"></a>
+<span class="sourceLineNo">571</span>      setTime(time);<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>    int getBatch() {<a name="line.574"></a>
+<span class="sourceLineNo">575</span>      return this.batch;<a name="line.575"></a>
+<span class="sourceLineNo">576</span>    }<a name="line.576"></a>
+<span class="sourceLineNo">577</span><a name="line.577"></a>
+<span class="sourceLineNo">578</span>    void setBatch(int batch) {<a name="line.578"></a>
+<span class="sourceLineNo">579</span>      this.batch = batch;<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>   

<TRUNCATED>

[35/50] hbase-site git commit: Published site at 26babcf013de696b899d76a3c39434b794440d8d.

Posted by gi...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Header.html
----------------------------------------------------------------------
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Header.html b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Header.html
index 97ceefd..b7b4236 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Header.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Header.html
@@ -103,8 +103,8 @@
 <span class="sourceLineNo">095</span> * Caches cache whole blocks with trailing checksums if any. We then tag on some metadata, the<a name="line.95"></a>
 <span class="sourceLineNo">096</span> * content of BLOCK_METADATA_SPACE which will be flag on if we are doing 'hbase'<a name="line.96"></a>
 <span class="sourceLineNo">097</span> * checksums and then the offset into the file which is needed when we re-make a cache key<a name="line.97"></a>
-<span class="sourceLineNo">098</span> * when we return the block to the cache as 'done'. See {@link Cacheable#serialize(ByteBuffer)} and<a name="line.98"></a>
-<span class="sourceLineNo">099</span> * {@link Cacheable#getDeserializer()}.<a name="line.99"></a>
+<span class="sourceLineNo">098</span> * when we return the block to the cache as 'done'.<a name="line.98"></a>
+<span class="sourceLineNo">099</span> * See {@link Cacheable#serialize(ByteBuffer, boolean)} and {@link Cacheable#getDeserializer()}.<a name="line.99"></a>
 <span class="sourceLineNo">100</span> *<a name="line.100"></a>
 <span class="sourceLineNo">101</span> * &lt;p&gt;TODO: Should we cache the checksums? Down in Writer#getBlockForCaching(CacheConfig) where<a name="line.101"></a>
 <span class="sourceLineNo">102</span> * we make a block to cache-on-write, there is an attempt at turning off checksums. This is not the<a name="line.102"></a>
@@ -333,1579 +333,1579 @@
 <span class="sourceLineNo">325</span>   * Creates a new {@link HFile} block from the given fields. This constructor<a name="line.325"></a>
 <span class="sourceLineNo">326</span>   * is used only while writing blocks and caching,<a name="line.326"></a>
 <span class="sourceLineNo">327</span>   * and is sitting in a byte buffer and we want to stuff the block into cache.<a name="line.327"></a>
-<span class="sourceLineNo">328</span>   * See {@link Writer#getBlockForCaching(CacheConfig)}.<a name="line.328"></a>
-<span class="sourceLineNo">329</span>   *<a name="line.329"></a>
-<span class="sourceLineNo">330</span>   * &lt;p&gt;TODO: The caller presumes no checksumming<a name="line.330"></a>
-<span class="sourceLineNo">331</span>   * required of this block instance since going into cache; checksum already verified on<a name="line.331"></a>
-<span class="sourceLineNo">332</span>   * underlying block data pulled in from filesystem. Is that correct? What if cache is SSD?<a name="line.332"></a>
-<span class="sourceLineNo">333</span>   *<a name="line.333"></a>
-<span class="sourceLineNo">334</span>   * @param blockType the type of this block, see {@link BlockType}<a name="line.334"></a>
-<span class="sourceLineNo">335</span>   * @param onDiskSizeWithoutHeader see {@link #onDiskSizeWithoutHeader}<a name="line.335"></a>
-<span class="sourceLineNo">336</span>   * @param uncompressedSizeWithoutHeader see {@link #uncompressedSizeWithoutHeader}<a name="line.336"></a>
-<span class="sourceLineNo">337</span>   * @param prevBlockOffset see {@link #prevBlockOffset}<a name="line.337"></a>
-<span class="sourceLineNo">338</span>   * @param b block header ({@link HConstants#HFILEBLOCK_HEADER_SIZE} bytes)<a name="line.338"></a>
-<span class="sourceLineNo">339</span>   * @param fillHeader when true, write the first 4 header fields into passed buffer.<a name="line.339"></a>
-<span class="sourceLineNo">340</span>   * @param offset the file offset the block was read from<a name="line.340"></a>
-<span class="sourceLineNo">341</span>   * @param onDiskDataSizeWithHeader see {@link #onDiskDataSizeWithHeader}<a name="line.341"></a>
-<span class="sourceLineNo">342</span>   * @param fileContext HFile meta data<a name="line.342"></a>
-<span class="sourceLineNo">343</span>   */<a name="line.343"></a>
-<span class="sourceLineNo">344</span>  HFileBlock(BlockType blockType, int onDiskSizeWithoutHeader, int uncompressedSizeWithoutHeader,<a name="line.344"></a>
-<span class="sourceLineNo">345</span>      long prevBlockOffset, ByteBuffer b, boolean fillHeader, long offset,<a name="line.345"></a>
-<span class="sourceLineNo">346</span>      final int nextBlockOnDiskSize, int onDiskDataSizeWithHeader, HFileContext fileContext) {<a name="line.346"></a>
-<span class="sourceLineNo">347</span>    init(blockType, onDiskSizeWithoutHeader, uncompressedSizeWithoutHeader,<a name="line.347"></a>
-<span class="sourceLineNo">348</span>        prevBlockOffset, offset, onDiskDataSizeWithHeader, nextBlockOnDiskSize, fileContext);<a name="line.348"></a>
-<span class="sourceLineNo">349</span>    this.buf = new SingleByteBuff(b);<a name="line.349"></a>
-<span class="sourceLineNo">350</span>    if (fillHeader) {<a name="line.350"></a>
-<span class="sourceLineNo">351</span>      overwriteHeader();<a name="line.351"></a>
-<span class="sourceLineNo">352</span>    }<a name="line.352"></a>
-<span class="sourceLineNo">353</span>    this.buf.rewind();<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>  /**<a name="line.356"></a>
-<span class="sourceLineNo">357</span>   * Creates a block from an existing buffer starting with a header. Rewinds<a name="line.357"></a>
-<span class="sourceLineNo">358</span>   * and takes ownership of the buffer. By definition of rewind, ignores the<a name="line.358"></a>
-<span class="sourceLineNo">359</span>   * buffer position, but if you slice the buffer beforehand, it will rewind<a name="line.359"></a>
-<span class="sourceLineNo">360</span>   * to that point.<a name="line.360"></a>
-<span class="sourceLineNo">361</span>   * @param buf Has header, content, and trailing checksums if present.<a name="line.361"></a>
-<span class="sourceLineNo">362</span>   */<a name="line.362"></a>
-<span class="sourceLineNo">363</span>  HFileBlock(ByteBuff buf, boolean usesHBaseChecksum, MemoryType memType, final long offset,<a name="line.363"></a>
-<span class="sourceLineNo">364</span>      final int nextBlockOnDiskSize, HFileContext fileContext) throws IOException {<a name="line.364"></a>
-<span class="sourceLineNo">365</span>    buf.rewind();<a name="line.365"></a>
-<span class="sourceLineNo">366</span>    final BlockType blockType = BlockType.read(buf);<a name="line.366"></a>
-<span class="sourceLineNo">367</span>    final int onDiskSizeWithoutHeader = buf.getInt(Header.ON_DISK_SIZE_WITHOUT_HEADER_INDEX);<a name="line.367"></a>
-<span class="sourceLineNo">368</span>    final int uncompressedSizeWithoutHeader =<a name="line.368"></a>
-<span class="sourceLineNo">369</span>        buf.getInt(Header.UNCOMPRESSED_SIZE_WITHOUT_HEADER_INDEX);<a name="line.369"></a>
-<span class="sourceLineNo">370</span>    final long prevBlockOffset = buf.getLong(Header.PREV_BLOCK_OFFSET_INDEX);<a name="line.370"></a>
-<span class="sourceLineNo">371</span>    // This constructor is called when we deserialize a block from cache and when we read a block in<a name="line.371"></a>
-<span class="sourceLineNo">372</span>    // from the fs. fileCache is null when deserialized from cache so need to make up one.<a name="line.372"></a>
-<span class="sourceLineNo">373</span>    HFileContextBuilder fileContextBuilder = fileContext != null?<a name="line.373"></a>
-<span class="sourceLineNo">374</span>        new HFileContextBuilder(fileContext): new HFileContextBuilder();<a name="line.374"></a>
-<span class="sourceLineNo">375</span>    fileContextBuilder.withHBaseCheckSum(usesHBaseChecksum);<a name="line.375"></a>
-<span class="sourceLineNo">376</span>    int onDiskDataSizeWithHeader;<a name="line.376"></a>
-<span class="sourceLineNo">377</span>    if (usesHBaseChecksum) {<a name="line.377"></a>
-<span class="sourceLineNo">378</span>      byte checksumType = buf.get(Header.CHECKSUM_TYPE_INDEX);<a name="line.378"></a>
-<span class="sourceLineNo">379</span>      int bytesPerChecksum = buf.getInt(Header.BYTES_PER_CHECKSUM_INDEX);<a name="line.379"></a>
-<span class="sourceLineNo">380</span>      onDiskDataSizeWithHeader = buf.getInt(Header.ON_DISK_DATA_SIZE_WITH_HEADER_INDEX);<a name="line.380"></a>
-<span class="sourceLineNo">381</span>      // Use the checksum type and bytes per checksum from header, not from filecontext.<a name="line.381"></a>
-<span class="sourceLineNo">382</span>      fileContextBuilder.withChecksumType(ChecksumType.codeToType(checksumType));<a name="line.382"></a>
-<span class="sourceLineNo">383</span>      fileContextBuilder.withBytesPerCheckSum(bytesPerChecksum);<a name="line.383"></a>
-<span class="sourceLineNo">384</span>    } else {<a name="line.384"></a>
-<span class="sourceLineNo">385</span>      fileContextBuilder.withChecksumType(ChecksumType.NULL);<a name="line.385"></a>
-<span class="sourceLineNo">386</span>      fileContextBuilder.withBytesPerCheckSum(0);<a name="line.386"></a>
-<span class="sourceLineNo">387</span>      // Need to fix onDiskDataSizeWithHeader; there are not checksums after-block-data<a name="line.387"></a>
-<span class="sourceLineNo">388</span>      onDiskDataSizeWithHeader = onDiskSizeWithoutHeader + headerSize(usesHBaseChecksum);<a name="line.388"></a>
-<span class="sourceLineNo">389</span>    }<a name="line.389"></a>
-<span class="sourceLineNo">390</span>    fileContext = fileContextBuilder.build();<a name="line.390"></a>
-<span class="sourceLineNo">391</span>    assert usesHBaseChecksum == fileContext.isUseHBaseChecksum();<a name="line.391"></a>
-<span class="sourceLineNo">392</span>    init(blockType, onDiskSizeWithoutHeader, uncompressedSizeWithoutHeader,<a name="line.392"></a>
-<span class="sourceLineNo">393</span>        prevBlockOffset, offset, onDiskDataSizeWithHeader, nextBlockOnDiskSize, fileContext);<a name="line.393"></a>
-<span class="sourceLineNo">394</span>    this.memType = memType;<a name="line.394"></a>
-<span class="sourceLineNo">395</span>    this.offset = offset;<a name="line.395"></a>
-<span class="sourceLineNo">396</span>    this.buf = buf;<a name="line.396"></a>
-<span class="sourceLineNo">397</span>    this.buf.rewind();<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>  /**<a name="line.400"></a>
-<span class="sourceLineNo">401</span>   * Called from constructors.<a name="line.401"></a>
-<span class="sourceLineNo">402</span>   */<a name="line.402"></a>
-<span class="sourceLineNo">403</span>  private void init(BlockType blockType, int onDiskSizeWithoutHeader,<a name="line.403"></a>
-<span class="sourceLineNo">404</span>      int uncompressedSizeWithoutHeader, long prevBlockOffset,<a name="line.404"></a>
-<span class="sourceLineNo">405</span>      long offset, int onDiskDataSizeWithHeader, final int nextBlockOnDiskSize,<a name="line.405"></a>
-<span class="sourceLineNo">406</span>      HFileContext fileContext) {<a name="line.406"></a>
-<span class="sourceLineNo">407</span>    this.blockType = blockType;<a name="line.407"></a>
-<span class="sourceLineNo">408</span>    this.onDiskSizeWithoutHeader = onDiskSizeWithoutHeader;<a name="line.408"></a>
-<span class="sourceLineNo">409</span>    this.uncompressedSizeWithoutHeader = uncompressedSizeWithoutHeader;<a name="line.409"></a>
-<span class="sourceLineNo">410</span>    this.prevBlockOffset = prevBlockOffset;<a name="line.410"></a>
-<span class="sourceLineNo">411</span>    this.offset = offset;<a name="line.411"></a>
-<span class="sourceLineNo">412</span>    this.onDiskDataSizeWithHeader = onDiskDataSizeWithHeader;<a name="line.412"></a>
-<span class="sourceLineNo">413</span>    this.nextBlockOnDiskSize = nextBlockOnDiskSize;<a name="line.413"></a>
-<span class="sourceLineNo">414</span>    this.fileContext = fileContext;<a name="line.414"></a>
-<span class="sourceLineNo">415</span>  }<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">418</span>   * Parse total on disk size including header and checksum.<a name="line.418"></a>
-<span class="sourceLineNo">419</span>   * @param headerBuf Header ByteBuffer. Presumed exact size of header.<a name="line.419"></a>
-<span class="sourceLineNo">420</span>   * @param verifyChecksum true if checksum verification is in use.<a name="line.420"></a>
-<span class="sourceLineNo">421</span>   * @return Size of the block with header included.<a name="line.421"></a>
-<span class="sourceLineNo">422</span>   */<a name="line.422"></a>
-<span class="sourceLineNo">423</span>  private static int getOnDiskSizeWithHeader(final ByteBuffer headerBuf,<a name="line.423"></a>
-<span class="sourceLineNo">424</span>      boolean verifyChecksum) {<a name="line.424"></a>
-<span class="sourceLineNo">425</span>    return headerBuf.getInt(Header.ON_DISK_SIZE_WITHOUT_HEADER_INDEX) +<a name="line.425"></a>
-<span class="sourceLineNo">426</span>      headerSize(verifyChecksum);<a name="line.426"></a>
-<span class="sourceLineNo">427</span>  }<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>   * @return the on-disk size of the next block (including the header size and any checksums if<a name="line.430"></a>
-<span class="sourceLineNo">431</span>   * present) read by peeking into the next block's header; use as a hint when doing<a name="line.431"></a>
-<span class="sourceLineNo">432</span>   * a read of the next block when scanning or running over a file.<a name="line.432"></a>
-<span class="sourceLineNo">433</span>   */<a name="line.433"></a>
-<span class="sourceLineNo">434</span>  int getNextBlockOnDiskSize() {<a name="line.434"></a>
-<span class="sourceLineNo">435</span>    return nextBlockOnDiskSize;<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>  @Override<a name="line.438"></a>
-<span class="sourceLineNo">439</span>  public BlockType getBlockType() {<a name="line.439"></a>
-<span class="sourceLineNo">440</span>    return blockType;<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>  /** @return get data block encoding id that was used to encode this block */<a name="line.443"></a>
-<span class="sourceLineNo">444</span>  short getDataBlockEncodingId() {<a name="line.444"></a>
-<span class="sourceLineNo">445</span>    if (blockType != BlockType.ENCODED_DATA) {<a name="line.445"></a>
-<span class="sourceLineNo">446</span>      throw new IllegalArgumentException("Querying encoder ID of a block " +<a name="line.446"></a>
-<span class="sourceLineNo">447</span>          "of type other than " + BlockType.ENCODED_DATA + ": " + blockType);<a name="line.447"></a>
-<span class="sourceLineNo">448</span>    }<a name="line.448"></a>
-<span class="sourceLineNo">449</span>    return buf.getShort(headerSize());<a name="line.449"></a>
-<span class="sourceLineNo">450</span>  }<a name="line.450"></a>
-<span class="sourceLineNo">451</span><a name="line.451"></a>
-<span class="sourceLineNo">452</span>  /**<a name="line.452"></a>
-<span class="sourceLineNo">453</span>   * @return the on-disk size of header + data part + checksum.<a name="line.453"></a>
-<span class="sourceLineNo">454</span>   */<a name="line.454"></a>
-<span class="sourceLineNo">455</span>  public int getOnDiskSizeWithHeader() {<a name="line.455"></a>
-<span class="sourceLineNo">456</span>    return onDiskSizeWithoutHeader + headerSize();<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>   * @return the on-disk size of the data part + checksum (header excluded).<a name="line.460"></a>
-<span class="sourceLineNo">461</span>   */<a name="line.461"></a>
-<span class="sourceLineNo">462</span>  int getOnDiskSizeWithoutHeader() {<a name="line.462"></a>
-<span class="sourceLineNo">463</span>    return onDiskSizeWithoutHeader;<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>  /**<a name="line.466"></a>
-<span class="sourceLineNo">467</span>   * @return the uncompressed size of data part (header and checksum excluded).<a name="line.467"></a>
-<span class="sourceLineNo">468</span>   */<a name="line.468"></a>
-<span class="sourceLineNo">469</span>   int getUncompressedSizeWithoutHeader() {<a name="line.469"></a>
-<span class="sourceLineNo">470</span>    return uncompressedSizeWithoutHeader;<a name="line.470"></a>
-<span class="sourceLineNo">471</span>  }<a name="line.471"></a>
-<span class="sourceLineNo">472</span><a name="line.472"></a>
-<span class="sourceLineNo">473</span>  /**<a name="line.473"></a>
-<span class="sourceLineNo">474</span>   * @return the offset of the previous block of the same type in the file, or<a name="line.474"></a>
-<span class="sourceLineNo">475</span>   *         -1 if unknown<a name="line.475"></a>
-<span class="sourceLineNo">476</span>   */<a name="line.476"></a>
-<span class="sourceLineNo">477</span>  long getPrevBlockOffset() {<a name="line.477"></a>
-<span class="sourceLineNo">478</span>    return prevBlockOffset;<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>   * Rewinds {@code buf} and writes first 4 header fields. {@code buf} position<a name="line.482"></a>
-<span class="sourceLineNo">483</span>   * is modified as side-effect.<a name="line.483"></a>
-<span class="sourceLineNo">484</span>   */<a name="line.484"></a>
-<span class="sourceLineNo">485</span>  private void overwriteHeader() {<a name="line.485"></a>
-<span class="sourceLineNo">486</span>    buf.rewind();<a name="line.486"></a>
-<span class="sourceLineNo">487</span>    blockType.write(buf);<a name="line.487"></a>
-<span class="sourceLineNo">488</span>    buf.putInt(onDiskSizeWithoutHeader);<a name="line.488"></a>
-<span class="sourceLineNo">489</span>    buf.putInt(uncompressedSizeWithoutHeader);<a name="line.489"></a>
-<span class="sourceLineNo">490</span>    buf.putLong(prevBlockOffset);<a name="line.490"></a>
-<span class="sourceLineNo">491</span>    if (this.fileContext.isUseHBaseChecksum()) {<a name="line.491"></a>
-<span class="sourceLineNo">492</span>      buf.put(fileContext.getChecksumType().getCode());<a name="line.492"></a>
-<span class="sourceLineNo">493</span>      buf.putInt(fileContext.getBytesPerChecksum());<a name="line.493"></a>
-<span class="sourceLineNo">494</span>      buf.putInt(onDiskDataSizeWithHeader);<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>  /**<a name="line.498"></a>
-<span class="sourceLineNo">499</span>   * Returns a buffer that does not include the header or checksum.<a name="line.499"></a>
-<span class="sourceLineNo">500</span>   *<a name="line.500"></a>
-<span class="sourceLineNo">501</span>   * @return the buffer with header skipped and checksum omitted.<a name="line.501"></a>
-<span class="sourceLineNo">502</span>   */<a name="line.502"></a>
-<span class="sourceLineNo">503</span>  public ByteBuff getBufferWithoutHeader() {<a name="line.503"></a>
-<span class="sourceLineNo">504</span>    ByteBuff dup = getBufferReadOnly();<a name="line.504"></a>
-<span class="sourceLineNo">505</span>    // Now set it up so Buffer spans content only -- no header or no checksums.<a name="line.505"></a>
-<span class="sourceLineNo">506</span>    return dup.position(headerSize()).limit(buf.limit() - totalChecksumBytes()).slice();<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 a read-only duplicate of the buffer this block stores internally ready to be read.<a name="line.510"></a>
-<span class="sourceLineNo">511</span>   * Clients must not modify the buffer object though they may set position and limit on the<a name="line.511"></a>
-<span class="sourceLineNo">512</span>   * returned buffer since we pass back a duplicate. This method has to be public because it is used<a name="line.512"></a>
-<span class="sourceLineNo">513</span>   * in {@link CompoundBloomFilter} to avoid object creation on every Bloom<a name="line.513"></a>
-<span class="sourceLineNo">514</span>   * filter lookup, but has to be used with caution. Buffer holds header, block content,<a name="line.514"></a>
-<span class="sourceLineNo">515</span>   * and any follow-on checksums if present.<a name="line.515"></a>
-<span class="sourceLineNo">516</span>   *<a name="line.516"></a>
-<span class="sourceLineNo">517</span>   * @return the buffer of this block for read-only operations<a name="line.517"></a>
-<span class="sourceLineNo">518</span>   */<a name="line.518"></a>
-<span class="sourceLineNo">519</span>  public ByteBuff getBufferReadOnly() {<a name="line.519"></a>
-<span class="sourceLineNo">520</span>    // TODO: ByteBuf does not support asReadOnlyBuffer(). Fix.<a name="line.520"></a>
-<span class="sourceLineNo">521</span>    ByteBuff dup = this.buf.duplicate();<a name="line.521"></a>
-<span class="sourceLineNo">522</span>    assert dup.position() == 0;<a name="line.522"></a>
-<span class="sourceLineNo">523</span>    return dup;<a name="line.523"></a>
-<span class="sourceLineNo">524</span>  }<a name="line.524"></a>
-<span class="sourceLineNo">525</span><a name="line.525"></a>
-<span class="sourceLineNo">526</span>  @VisibleForTesting<a name="line.526"></a>
-<span class="sourceLineNo">527</span>  private void sanityCheckAssertion(long valueFromBuf, long valueFromField,<a name="line.527"></a>
-<span class="sourceLineNo">528</span>      String fieldName) throws IOException {<a name="line.528"></a>
-<span class="sourceLineNo">529</span>    if (valueFromBuf != valueFromField) {<a name="line.529"></a>
-<span class="sourceLineNo">530</span>      throw new AssertionError(fieldName + " in the buffer (" + valueFromBuf<a name="line.530"></a>
-<span class="sourceLineNo">531</span>          + ") is different from that in the field (" + valueFromField + ")");<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>  @VisibleForTesting<a name="line.535"></a>
-<span class="sourceLineNo">536</span>  private void sanityCheckAssertion(BlockType valueFromBuf, BlockType valueFromField)<a name="line.536"></a>
-<span class="sourceLineNo">537</span>      throws IOException {<a name="line.537"></a>
-<span class="sourceLineNo">538</span>    if (valueFromBuf != valueFromField) {<a name="line.538"></a>
-<span class="sourceLineNo">539</span>      throw new IOException("Block type stored in the buffer: " +<a name="line.539"></a>
-<span class="sourceLineNo">540</span>        valueFromBuf + ", block type field: " + valueFromField);<a name="line.540"></a>
-<span class="sourceLineNo">541</span>    }<a name="line.541"></a>
-<span class="sourceLineNo">542</span>  }<a name="line.542"></a>
-<span class="sourceLineNo">543</span><a name="line.543"></a>
-<span class="sourceLineNo">544</span>  /**<a name="line.544"></a>
-<span class="sourceLineNo">545</span>   * Checks if the block is internally consistent, i.e. the first<a name="line.545"></a>
-<span class="sourceLineNo">546</span>   * {@link HConstants#HFILEBLOCK_HEADER_SIZE} bytes of the buffer contain a<a name="line.546"></a>
-<span class="sourceLineNo">547</span>   * valid header consistent with the fields. Assumes a packed block structure.<a name="line.547"></a>
-<span class="sourceLineNo">548</span>   * This function is primary for testing and debugging, and is not<a name="line.548"></a>
-<span class="sourceLineNo">549</span>   * thread-safe, because it alters the internal buffer pointer.<a name="line.549"></a>
-<span class="sourceLineNo">550</span>   * Used by tests only.<a name="line.550"></a>
-<span class="sourceLineNo">551</span>   */<a name="line.551"></a>
-<span class="sourceLineNo">552</span>  @VisibleForTesting<a name="line.552"></a>
-<span class="sourceLineNo">553</span>  void sanityCheck() throws IOException {<a name="line.553"></a>
-<span class="sourceLineNo">554</span>    // Duplicate so no side-effects<a name="line.554"></a>
-<span class="sourceLineNo">555</span>    ByteBuff dup = this.buf.duplicate().rewind();<a name="line.555"></a>
-<span class="sourceLineNo">556</span>    sanityCheckAssertion(BlockType.read(dup), blockType);<a name="line.556"></a>
-<span class="sourceLineNo">557</span><a name="line.557"></a>
-<span class="sourceLineNo">558</span>    sanityCheckAssertion(dup.getInt(), onDiskSizeWithoutHeader, "onDiskSizeWithoutHeader");<a name="line.558"></a>
-<span class="sourceLineNo">559</span><a name="line.559"></a>
-<span class="sourceLineNo">560</span>    sanityCheckAssertion(dup.getInt(), uncompressedSizeWithoutHeader,<a name="line.560"></a>
-<span class="sourceLineNo">561</span>        "uncompressedSizeWithoutHeader");<a name="line.561"></a>
-<span class="sourceLineNo">562</span><a name="line.562"></a>
-<span class="sourceLineNo">563</span>    sanityCheckAssertion(dup.getLong(), prevBlockOffset, "prevBlockOffset");<a name="line.563"></a>
-<span class="sourceLineNo">564</span>    if (this.fileContext.isUseHBaseChecksum()) {<a name="line.564"></a>
-<span class="sourceLineNo">565</span>      sanityCheckAssertion(dup.get(), this.fileContext.getChecksumType().getCode(), "checksumType");<a name="line.565"></a>
-<span class="sourceLineNo">566</span>      sanityCheckAssertion(dup.getInt(), this.fileContext.getBytesPerChecksum(),<a name="line.566"></a>
-<span class="sourceLineNo">567</span>          "bytesPerChecksum");<a name="line.567"></a>
-<span class="sourceLineNo">568</span>      sanityCheckAssertion(dup.getInt(), onDiskDataSizeWithHeader, "onDiskDataSizeWithHeader");<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>    int cksumBytes = totalChecksumBytes();<a name="line.571"></a>
-<span class="sourceLineNo">572</span>    int expectedBufLimit = onDiskDataSizeWithHeader + cksumBytes;<a name="line.572"></a>
-<span class="sourceLineNo">573</span>    if (dup.limit() != expectedBufLimit) {<a name="line.573"></a>
-<span class="sourceLineNo">574</span>      throw new AssertionError("Expected limit " + expectedBufLimit + ", got " + dup.limit());<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>    // We might optionally allocate HFILEBLOCK_HEADER_SIZE more bytes to read the next<a name="line.577"></a>
-<span class="sourceLineNo">578</span>    // block's header, so there are two sensible values for buffer capacity.<a name="line.578"></a>
-<span class="sourceLineNo">579</span>    int hdrSize = headerSize();<a name="line.579"></a>
-<span class="sourceLineNo">580</span>    if (dup.capacity() != expectedBufLimit &amp;&amp; dup.capacity() != expectedBufLimit + hdrSize) {<a name="line.580"></a>
-<span class="sourceLineNo">581</span>      throw new AssertionError("Invalid buffer capacity: " + dup.capacity() +<a name="line.581"></a>
-<span class="sourceLineNo">582</span>          ", expected " + expectedBufLimit + " or " + (expectedBufLimit + hdrSize));<a name="line.582"></a>
-<span class="sourceLineNo">583</span>    }<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>  @Override<a name="line.586"></a>
-<span class="sourceLineNo">587</span>  public String toString() {<a name="line.587"></a>
-<span class="sourceLineNo">588</span>    StringBuilder sb = new StringBuilder()<a name="line.588"></a>
-<span class="sourceLineNo">589</span>      .append("[")<a name="line.589"></a>
-<span class="sourceLineNo">590</span>      .append("blockType=").append(blockType)<a name="line.590"></a>
-<span class="sourceLineNo">591</span>      .append(", fileOffset=").append(offset)<a name="line.591"></a>
-<span class="sourceLineNo">592</span>      .append(", headerSize=").append(headerSize())<a name="line.592"></a>
-<span class="sourceLineNo">593</span>      .append(", onDiskSizeWithoutHeader=").append(onDiskSizeWithoutHeader)<a name="line.593"></a>
-<span class="sourceLineNo">594</span>      .append(", uncompressedSizeWithoutHeader=").append(uncompressedSizeWithoutHeader)<a name="line.594"></a>
-<span class="sourceLineNo">595</span>      .append(", prevBlockOffset=").append(prevBlockOffset)<a name="line.595"></a>
-<span class="sourceLineNo">596</span>      .append(", isUseHBaseChecksum=").append(fileContext.isUseHBaseChecksum());<a name="line.596"></a>
-<span class="sourceLineNo">597</span>    if (fileContext.isUseHBaseChecksum()) {<a name="line.597"></a>
-<span class="sourceLineNo">598</span>      sb.append(", checksumType=").append(ChecksumType.codeToType(this.buf.get(24)))<a name="line.598"></a>
-<span class="sourceLineNo">599</span>        .append(", bytesPerChecksum=").append(this.buf.getInt(24 + 1))<a name="line.599"></a>
-<span class="sourceLineNo">600</span>        .append(", onDiskDataSizeWithHeader=").append(onDiskDataSizeWithHeader);<a name="line.600"></a>
-<span class="sourceLineNo">601</span>    } else {<a name="line.601"></a>
-<span class="sourceLineNo">602</span>      sb.append(", onDiskDataSizeWithHeader=").append(onDiskDataSizeWithHeader)<a name="line.602"></a>
-<span class="sourceLineNo">603</span>        .append("(").append(onDiskSizeWithoutHeader)<a name="line.603"></a>
-<span class="sourceLineNo">604</span>        .append("+").append(HConstants.HFILEBLOCK_HEADER_SIZE_NO_CHECKSUM).append(")");<a name="line.604"></a>
-<span class="sourceLineNo">605</span>    }<a name="line.605"></a>
-<span class="sourceLineNo">606</span>    String dataBegin = null;<a name="line.606"></a>
-<span class="sourceLineNo">607</span>    if (buf.hasArray()) {<a name="line.607"></a>
-<span class="sourceLineNo">608</span>      dataBegin = Bytes.toStringBinary(buf.array(), buf.arrayOffset() + headerSize(),<a name="line.608"></a>
-<span class="sourceLineNo">609</span>          Math.min(32, buf.limit() - buf.arrayOffset() - headerSize()));<a name="line.609"></a>
-<span class="sourceLineNo">610</span>    } else {<a name="line.610"></a>
-<span class="sourceLineNo">611</span>      ByteBuff bufWithoutHeader = getBufferWithoutHeader();<a name="line.611"></a>
-<span class="sourceLineNo">612</span>      byte[] dataBeginBytes = new byte[Math.min(32,<a name="line.612"></a>
-<span class="sourceLineNo">613</span>          bufWithoutHeader.limit() - bufWithoutHeader.position())];<a name="line.613"></a>
-<span class="sourceLineNo">614</span>      bufWithoutHeader.get(dataBeginBytes);<a name="line.614"></a>
-<span class="sourceLineNo">615</span>      dataBegin = Bytes.toStringBinary(dataBeginBytes);<a name="line.615"></a>
-<span class="sourceLineNo">616</span>    }<a name="line.616"></a>
-<span class="sourceLineNo">617</span>    sb.append(", getOnDiskSizeWithHeader=").append(getOnDiskSizeWithHeader())<a name="line.617"></a>
-<span class="sourceLineNo">618</span>      .append(", totalChecksumBytes=").append(totalChecksumBytes())<a name="line.618"></a>
-<span class="sourceLineNo">619</span>      .append(", isUnpacked=").append(isUnpacked())<a name="line.619"></a>
-<span class="sourceLineNo">620</span>      .append(", buf=[").append(buf).append("]")<a name="line.620"></a>
-<span class="sourceLineNo">621</span>      .append(", dataBeginsWith=").append(dataBegin)<a name="line.621"></a>
-<span class="sourceLineNo">622</span>      .append(", fileContext=").append(fileContext)<a name="line.622"></a>
-<span class="sourceLineNo">623</span>      .append("]");<a name="line.623"></a>
-<span class="sourceLineNo">624</span>    return sb.toString();<a name="line.624"></a>
-<span class="sourceLineNo">625</span>  }<a name="line.625"></a>
-<span class="sourceLineNo">626</span><a name="line.626"></a>
-<span class="sourceLineNo">627</span>  /**<a name="line.627"></a>
-<span class="sourceLineNo">628</span>   * Retrieves the decompressed/decrypted view of this block. An encoded block remains in its<a name="line.628"></a>
-<span class="sourceLineNo">629</span>   * encoded structure. Internal structures are shared between instances where applicable.<a name="line.629"></a>
-<span class="sourceLineNo">630</span>   */<a name="line.630"></a>
-<span class="sourceLineNo">631</span>  HFileBlock unpack(HFileContext fileContext, FSReader reader) throws IOException {<a name="line.631"></a>
-<span class="sourceLineNo">632</span>    if (!fileContext.isCompressedOrEncrypted()) {<a name="line.632"></a>
-<span class="sourceLineNo">633</span>      // TODO: cannot use our own fileContext here because HFileBlock(ByteBuffer, boolean),<a name="line.633"></a>
-<span class="sourceLineNo">634</span>      // which is used for block serialization to L2 cache, does not preserve encoding and<a name="line.634"></a>
-<span class="sourceLineNo">635</span>      // encryption details.<a name="line.635"></a>
-<span class="sourceLineNo">636</span>      return this;<a name="line.636"></a>
-<span class="sourceLineNo">637</span>    }<a name="line.637"></a>
-<span class="sourceLineNo">638</span><a name="line.638"></a>
-<span class="sourceLineNo">639</span>    HFileBlock unpacked = new HFileBlock(this);<a name="line.639"></a>
-<span class="sourceLineNo">640</span>    unpacked.allocateBuffer(); // allocates space for the decompressed block<a name="line.640"></a>
-<span class="sourceLineNo">641</span><a name="line.641"></a>
-<span class="sourceLineNo">642</span>    HFileBlockDecodingContext ctx = blockType == BlockType.ENCODED_DATA ?<a name="line.642"></a>
-<span class="sourceLineNo">643</span>      reader.getBlockDecodingContext() : reader.getDefaultBlockDecodingContext();<a name="line.643"></a>
-<span class="sourceLineNo">644</span><a name="line.644"></a>
-<span class="sourceLineNo">645</span>    ByteBuff dup = this.buf.duplicate();<a name="line.645"></a>
-<span class="sourceLineNo">646</span>    dup.position(this.headerSize());<a name="line.646"></a>
-<span class="sourceLineNo">647</span>    dup = dup.slice();<a name="line.647"></a>
-<span class="sourceLineNo">648</span>    ctx.prepareDecoding(unpacked.getOnDiskSizeWithoutHeader(),<a name="line.648"></a>
-<span class="sourceLineNo">649</span>      unpacked.getUncompressedSizeWithoutHeader(), unpacked.getBufferWithoutHeader(),<a name="line.649"></a>
-<span class="sourceLineNo">650</span>      dup);<a name="line.650"></a>
-<span class="sourceLineNo">651</span>    return unpacked;<a name="line.651"></a>
-<span class="sourceLineNo">652</span>  }<a name="line.652"></a>
-<span class="sourceLineNo">653</span><a name="line.653"></a>
-<span class="sourceLineNo">654</span>  /**<a name="line.654"></a>
-<span class="sourceLineNo">655</span>   * Always allocates a new buffer of the correct size. Copies header bytes<a name="line.655"></a>
-<span class="sourceLineNo">656</span>   * from the existing buffer. Does not change header fields.<a name="line.656"></a>
-<span class="sourceLineNo">657</span>   * Reserve room to keep checksum bytes too.<a name="line.657"></a>
-<span class="sourceLineNo">658</span>   */<a name="line.658"></a>
-<span class="sourceLineNo">659</span>  private void allocateBuffer() {<a name="line.659"></a>
-<span class="sourceLineNo">660</span>    int cksumBytes = totalChecksumBytes();<a name="line.660"></a>
-<span class="sourceLineNo">661</span>    int headerSize = headerSize();<a name="line.661"></a>
-<span class="sourceLineNo">662</span>    int capacityNeeded = headerSize + uncompressedSizeWithoutHeader + cksumBytes;<a name="line.662"></a>
-<span class="sourceLineNo">663</span><a name="line.663"></a>
-<span class="sourceLineNo">664</span>    // TODO we need consider allocating offheap here?<a name="line.664"></a>
-<span class="sourceLineNo">665</span>    ByteBuffer newBuf = ByteBuffer.allocate(capacityNeeded);<a name="line.665"></a>
-<span class="sourceLineNo">666</span><a name="line.666"></a>
-<span class="sourceLineNo">667</span>    // Copy header bytes into newBuf.<a name="line.667"></a>
-<span class="sourceLineNo">668</span>    // newBuf is HBB so no issue in calling array()<a name="line.668"></a>
-<span class="sourceLineNo">669</span>    buf.position(0);<a name="line.669"></a>
-<span class="sourceLineNo">670</span>    buf.get(newBuf.array(), newBuf.arrayOffset(), headerSize);<a name="line.670"></a>
-<span class="sourceLineNo">671</span><a name="line.671"></a>
-<span class="sourceLineNo">672</span>    buf = new SingleByteBuff(newBuf);<a name="line.672"></a>
-<span class="sourceLineNo">673</span>    // set limit to exclude next block's header<a name="line.673"></a>
-<span class="sourceLineNo">674</span>    buf.limit(headerSize + uncompressedSizeWithoutHeader + cksumBytes);<a name="line.674"></a>
-<span class="sourceLineNo">675</span>  }<a name="line.675"></a>
-<span class="sourceLineNo">676</span><a name="line.676"></a>
-<span class="sourceLineNo">677</span>  /**<a name="line.677"></a>
-<span class="sourceLineNo">678</span>   * Return true when this block's buffer has been unpacked, false otherwise. Note this is a<a name="line.678"></a>
-<span class="sourceLineNo">679</span>   * calculated heuristic, not tracked attribute of the block.<a name="line.679"></a>
-<span class="sourceLineNo">680</span>   */<a name="line.680"></a>
-<span class="sourceLineNo">681</span>  public boolean isUnpacked() {<a name="line.681"></a>
-<span class="sourceLineNo">682</span>    final int cksumBytes = totalChecksumBytes();<a name="line.682"></a>
-<span class="sourceLineNo">683</span>    final int headerSize = headerSize();<a name="line.683"></a>
-<span class="sourceLineNo">684</span>    final int expectedCapacity = headerSize + uncompressedSizeWithoutHeader + cksumBytes;<a name="line.684"></a>
-<span class="sourceLineNo">685</span>    final int bufCapacity = buf.capacity();<a name="line.685"></a>
-<span class="sourceLineNo">686</span>    return bufCapacity == expectedCapacity || bufCapacity == expectedCapacity + headerSize;<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>  /** An additional sanity-check in case no compression or encryption is being used. */<a name="line.689"></a>
-<span class="sourceLineNo">690</span>  @VisibleForTesting<a name="line.690"></a>
-<span class="sourceLineNo">691</span>  void sanityCheckUncompressedSize() throws IOException {<a name="line.691"></a>
-<span class="sourceLineNo">692</span>    if (onDiskSizeWithoutHeader != uncompressedSizeWithoutHeader + totalChecksumBytes()) {<a name="line.692"></a>
-<span class="sourceLineNo">693</span>      throw new IOException("Using no compression but "<a name="line.693"></a>
-<span class="sourceLineNo">694</span>          + "onDiskSizeWithoutHeader=" + onDiskSizeWithoutHeader + ", "<a name="line.694"></a>
-<span class="sourceLineNo">695</span>          + "uncompressedSizeWithoutHeader=" + uncompressedSizeWithoutHeader<a name="line.695"></a>
-<span class="sourceLineNo">696</span>          + ", numChecksumbytes=" + totalChecksumBytes());<a name="line.696"></a>
-<span class="sourceLineNo">697</span>    }<a name="line.697"></a>
-<span class="sourceLineNo">698</span>  }<a name="line.698"></a>
-<span class="sourceLineNo">699</span><a name="line.699"></a>
-<span class="sourceLineNo">700</span>  /**<a name="line.700"></a>
-<span class="sourceLineNo">701</span>   * Cannot be {@link #UNSET}. Must be a legitimate value. Used re-making the {@link BlockCacheKey} when<a name="line.701"></a>
-<span class="sourceLineNo">702</span>   * block is returned to the cache.<a name="line.702"></a>
-<span class="sourceLineNo">703</span>   * @return the offset of this block in the file it was read from<a name="line.703"></a>
-<span class="sourceLineNo">704</span>   */<a name="line.704"></a>
-<span class="sourceLineNo">705</span>  long getOffset() {<a name="line.705"></a>
-<span class="sourceLineNo">706</span>    if (offset &lt; 0) {<a name="line.706"></a>
-<span class="sourceLineNo">707</span>      throw new IllegalStateException("HFile block offset not initialized properly");<a name="line.707"></a>
-<span class="sourceLineNo">708</span>    }<a name="line.708"></a>
-<span class="sourceLineNo">709</span>    return offset;<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>   * @return a byte stream reading the data + checksum of this block<a name="line.713"></a>
-<span class="sourceLineNo">714</span>   */<a name="line.714"></a>
-<span class="sourceLineNo">715</span>  DataInputStream getByteStream() {<a name="line.715"></a>
-<span class="sourceLineNo">716</span>    ByteBuff dup = this.buf.duplicate();<a name="line.716"></a>
-<span class="sourceLineNo">717</span>    dup.position(this.headerSize());<a name="line.717"></a>
-<span class="sourceLineNo">718</span>    return new DataInputStream(new ByteBuffInputStream(dup));<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>
-<span class="sourceLineNo">721</span>  @Override<a name="line.721"></a>
-<span class="sourceLineNo">722</span>  public long heapSize() {<a name="line.722"></a>
-<span class="sourceLineNo">723</span>    long size = ClassSize.align(<a name="line.723"></a>
-<span class="sourceLineNo">724</span>        ClassSize.OBJECT +<a name="line.724"></a>
-<span class="sourceLineNo">725</span>        // Block type, multi byte buffer, MemoryType and meta references<a name="line.725"></a>
-<span class="sourceLineNo">726</span>        4 * ClassSize.REFERENCE +<a name="line.726"></a>
-<span class="sourceLineNo">727</span>        // On-disk size, uncompressed size, and next block's on-disk size<a name="line.727"></a>
-<span class="sourceLineNo">728</span>        // bytePerChecksum and onDiskDataSize<a name="line.728"></a>
-<span class="sourceLineNo">729</span>        4 * Bytes.SIZEOF_INT +<a name="line.729"></a>
-<span class="sourceLineNo">730</span>        // This and previous block offset<a name="line.730"></a>
-<span class="sourceLineNo">731</span>        2 * Bytes.SIZEOF_LONG +<a name="line.731"></a>
-<span class="sourceLineNo">732</span>        // Heap size of the meta object. meta will be always not null.<a name="line.732"></a>
-<span class="sourceLineNo">733</span>        fileContext.heapSize()<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>    if (buf != null) {<a name="line.736"></a>
-<span class="sourceLineNo">737</span>      // Deep overhead of the byte buffer. Needs to be aligned separately.<a name="line.737"></a>
-<span class="sourceLineNo">738</span>      size += ClassSize.align(buf.capacity() + MULTI_BYTE_BUFFER_HEAP_SIZE);<a name="line.738"></a>
-<span class="sourceLineNo">739</span>    }<a name="line.739"></a>
-<span class="sourceLineNo">740</span><a name="line.740"></a>
-<span class="sourceLineNo">741</span>    return ClassSize.align(size);<a name="line.741"></a>
-<span class="sourceLineNo">742</span>  }<a name="line.742"></a>
-<span class="sourceLineNo">743</span><a name="line.743"></a>
-<span class="sourceLineNo">744</span>  /**<a name="line.744"></a>
-<span class="sourceLineNo">745</span>   * Read from an input stream at least &lt;code&gt;necessaryLen&lt;/code&gt; and if possible,<a name="line.745"></a>
-<span class="sourceLineNo">746</span>   * &lt;code&gt;extraLen&lt;/code&gt; also if available. Analogous to<a name="line.746"></a>
-<span class="sourceLineNo">747</span>   * {@link IOUtils#readFully(InputStream, byte[], int, int)}, but specifies a<a name="line.747"></a>
-<span class="sourceLineNo">748</span>   * number of "extra" bytes to also optionally read.<a name="line.748"></a>
-<span class="sourceLineNo">749</span>   *<a name="line.749"></a>
-<span class="sourceLineNo">750</span>   * @param in the input stream to read from<a name="line.750"></a>
-<span class="sourceLineNo">751</span>   * @param buf the buffer to read into<a name="line.751"></a>
-<span class="sourceLineNo">752</span>   * @param bufOffset the destination offset in the buffer<a name="line.752"></a>
-<span class="sourceLineNo">753</span>   * @param necessaryLen the number of bytes that are absolutely necessary to read<a name="line.753"></a>
-<span class="sourceLineNo">754</span>   * @param extraLen the number of extra bytes that would be nice to read<a name="line.754"></a>
-<span class="sourceLineNo">755</span>   * @return true if succeeded reading the extra bytes<a name="line.755"></a>
-<span class="sourceLineNo">756</span>   * @throws IOException if failed to read the necessary bytes<a name="line.756"></a>
-<span class="sourceLineNo">757</span>   */<a name="line.757"></a>
-<span class="sourceLineNo">758</span>  static boolean readWithExtra(InputStream in, byte[] buf,<a name="line.758"></a>
-<span class="sourceLineNo">759</span>      int bufOffset, int necessaryLen, int extraLen) throws IOException {<a name="line.759"></a>
-<span class="sourceLineNo">760</span>    int bytesRemaining = necessaryLen + extraLen;<a name="line.760"></a>
-<span class="sourceLineNo">761</span>    while (bytesRemaining &gt; 0) {<a name="line.761"></a>
-<span class="sourceLineNo">762</span>      int ret = in.read(buf, bufOffset, bytesRemaining);<a name="line.762"></a>
-<span class="sourceLineNo">763</span>      if (ret == -1 &amp;&amp; bytesRemaining &lt;= extraLen) {<a name="line.763"></a>
-<span class="sourceLineNo">764</span>        // We could not read the "extra data", but that is OK.<a name="line.764"></a>
-<span class="sourceLineNo">765</span>        break;<a name="line.765"></a>
-<span class="sourceLineNo">766</span>      }<a name="line.766"></a>
-<span class="sourceLineNo">767</span>      if (ret &lt; 0) {<a name="line.767"></a>
-<span class="sourceLineNo">768</span>        throw new IOException("Premature EOF from inputStream (read "<a name="line.768"></a>
-<span class="sourceLineNo">769</span>            + "returned " + ret + ", was trying to read " + necessaryLen<a name="line.769"></a>
-<span class="sourceLineNo">770</span>            + " necessary bytes and " + extraLen + " extra bytes, "<a name="line.770"></a>
-<span class="sourceLineNo">771</span>            + "successfully read "<a name="line.771"></a>
-<span class="sourceLineNo">772</span>            + (necessaryLen + extraLen - bytesRemaining));<a name="line.772"></a>
-<span class="sourceLineNo">773</span>      }<a name="line.773"></a>
-<span class="sourceLineNo">774</span>      bufOffset += ret;<a name="line.774"></a>
-<span class="sourceLineNo">775</span>      bytesRemaining -= ret;<a name="line.775"></a>
-<span class="sourceLineNo">776</span>    }<a name="line.776"></a>
-<span class="sourceLineNo">777</span>    return bytesRemaining &lt;= 0;<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>   * Read from an input stream at least &lt;code&gt;necessaryLen&lt;/code&gt; and if possible,<a name="line.781"></a>
-<span class="sourceLineNo">782</span>   * &lt;code&gt;extraLen&lt;/code&gt; also if available. Analogous to<a name="line.782"></a>
-<span class="sourceLineNo">783</span>   * {@link IOUtils#readFully(InputStream, byte[], int, int)}, but uses<a name="line.783"></a>
-<span class="sourceLineNo">784</span>   * positional read and specifies a number of "extra" bytes that would be<a name="line.784"></a>
-<span class="sourceLineNo">785</span>   * desirable but not absolutely necessary to read.<a name="line.785"></a>
-<span class="sourceLineNo">786</span>   *<a name="line.786"></a>
-<span class="sourceLineNo">787</span>   * @param in the input stream to read from<a name="line.787"></a>
-<span class="sourceLineNo">788</span>   * @param position the position within the stream from which to start reading<a name="line.788"></a>
-<span class="sourceLineNo">789</span>   * @param buf the buffer to read into<a name="line.789"></a>
-<span class="sourceLineNo">790</span>   * @param bufOffset the destination offset in the buffer<a name="line.790"></a>
-<span class="sourceLineNo">791</span>   * @param necessaryLen the number of bytes that are absolutely necessary to<a name="line.791"></a>
-<span class="sourceLineNo">792</span>   *     read<a name="line.792"></a>
-<span class="sourceLineNo">793</span>   * @param extraLen the number of extra bytes that would be nice to read<a name="line.793"></a>
-<span class="sourceLineNo">794</span>   * @return true if and only if extraLen is &gt; 0 and reading those extra bytes<a name="line.794"></a>
-<span class="sourceLineNo">795</span>   *     was successful<a name="line.795"></a>
-<span class="sourceLineNo">796</span>   * @throws IOException if failed to read the necessary bytes<a name="line.796"></a>
-<span class="sourceLineNo">797</span>   */<a name="line.797"></a>
-<span class="sourceLineNo">798</span>  @VisibleForTesting<a name="line.798"></a>
-<span class="sourceLineNo">799</span>  static boolean positionalReadWithExtra(FSDataInputStream in,<a name="line.799"></a>
-<span class="sourceLineNo">800</span>      long position, byte[] buf, int bufOffset, int necessaryLen, int extraLen)<a name="line.800"></a>
-<span class="sourceLineNo">801</span>      throws IOException {<a name="line.801"></a>
-<span class="sourceLineNo">802</span>    int bytesRemaining = necessaryLen + extraLen;<a name="line.802"></a>
-<span class="sourceLineNo">803</span>    int bytesRead = 0;<a name="line.803"></a>
-<span class="sourceLineNo">804</span>    while (bytesRead &lt; necessaryLen) {<a name="line.804"></a>
-<span class="sourceLineNo">805</span>      int ret = in.read(position, buf, bufOffset, bytesRemaining);<a name="line.805"></a>
-<span class="sourceLineNo">806</span>      if (ret &lt; 0) {<a name="line.806"></a>
-<span class="sourceLineNo">807</span>        throw new IOException("Premature EOF from inputStream (positional read "<a name="line.807"></a>
-<span class="sourceLineNo">808</span>            + "returned " + ret + ", was trying to read " + necessaryLen<a name="line.808"></a>
-<span class="sourceLineNo">809</span>            + " necessary bytes and " + extraLen + " extra bytes, "<a name="line.809"></a>
-<span class="sourceLineNo">810</span>            + "successfully read " + bytesRead);<a name="line.810"></a>
-<span class="sourceLineNo">811</span>      }<a name="line.811"></a>
-<span class="sourceLineNo">812</span>      position += ret;<a name="line.812"></a>
-<span class="sourceLineNo">813</span>      bufOffset += ret;<a name="line.813"></a>
-<span class="sourceLineNo">814</span>      bytesRemaining -= ret;<a name="line.814"></a>
-<span class="sourceLineNo">815</span>      bytesRead += ret;<a name="line.815"></a>
-<span class="sourceLineNo">816</span>    }<a name="line.816"></a>
-<span class="sourceLineNo">817</span>    return bytesRead != necessaryLen &amp;&amp; bytesRemaining &lt;= 0;<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>   * Unified version 2 {@link HFile} block writer. The intended usage pattern<a name="line.821"></a>
-<span class="sourceLineNo">822</span>   * is as follows:<a name="line.822"></a>
-<span class="sourceLineNo">823</span>   * &lt;ol&gt;<a name="line.823"></a>
-<span class="sourceLineNo">824</span>   * &lt;li&gt;Construct an {@link HFileBlock.Writer}, providing a compression algorithm.<a name="line.824"></a>
-<span class="sourceLineNo">825</span>   * &lt;li&gt;Call {@link Writer#startWriting} and get a data stream to write to.<a name="line.825"></a>
-<span class="sourceLineNo">826</span>   * &lt;li&gt;Write your data into the stream.<a name="line.826"></a>
-<span class="sourceLineNo">827</span>   * &lt;li&gt;Call Writer#writeHeaderAndData(FSDataOutputStream) as many times as you need to.<a name="line.827"></a>
-<span class="sourceLineNo">828</span>   * store the serialized block into an external stream.<a name="line.828"></a>
-<span class="sourceLineNo">829</span>   * &lt;li&gt;Repeat to write more blocks.<a name="line.829"></a>
-<span class="sourceLineNo">830</span>   * &lt;/ol&gt;<a name="line.830"></a>
-<span class="sourceLineNo">831</span>   * &lt;p&gt;<a name="line.831"></a>
-<span class="sourceLineNo">832</span>   */<a name="line.832"></a>
-<span class="sourceLineNo">833</span>  static class Writer {<a name="line.833"></a>
-<span class="sourceLineNo">834</span>    private enum State {<a name="line.834"></a>
-<span class="sourceLineNo">835</span>      INIT,<a name="line.835"></a>
-<span class="sourceLineNo">836</span>      WRITING,<a name="line.836"></a>
-<span class="sourceLineNo">837</span>      BLOCK_READY<a name="line.837"></a>
-<span class="sourceLineNo">838</span>    }<a name="line.838"></a>
-<span class="sourceLineNo">839</span><a name="line.839"></a>
-<span class="sourceLineNo">840</span>    /** Writer state. Used to ensure the correct usage protocol. */<a name="line.840"></a>
-<span class="sourceLineNo">841</span>    private State state = State.INIT;<a name="line.841"></a>
-<span class="sourceLineNo">842</span><a name="line.842"></a>
-<span class="sourceLineNo">843</span>    /** Data block encoder used for data blocks */<a name="line.843"></a>
-<span class="sourceLineNo">844</span>    private final HFileDataBlockEncoder dataBlockEncoder;<a name="line.844"></a>
-<span class="sourceLineNo">845</span><a name="line.845"></a>
-<span class="sourceLineNo">846</span>    private HFileBlockEncodingContext dataBlockEncodingCtx;<a name="line.846"></a>
+<span class="sourceLineNo">328</span>   *<a name="line.328"></a>
+<span class="sourceLineNo">329</span>   * &lt;p&gt;TODO: The caller presumes no checksumming<a name="line.329"></a>
+<span class="sourceLineNo">330</span>   * required of this block instance since going into cache; checksum already verified on<a name="line.330"></a>
+<span class="sourceLineNo">331</span>   * underlying block data pulled in from filesystem. Is that correct? What if cache is SSD?<a name="line.331"></a>
+<span class="sourceLineNo">332</span>   *<a name="line.332"></a>
+<span class="sourceLineNo">333</span>   * @param blockType the type of this block, see {@link BlockType}<a name="line.333"></a>
+<span class="sourceLineNo">334</span>   * @param onDiskSizeWithoutHeader see {@link #onDiskSizeWithoutHeader}<a name="line.334"></a>
+<span class="sourceLineNo">335</span>   * @param uncompressedSizeWithoutHeader see {@link #uncompressedSizeWithoutHeader}<a name="line.335"></a>
+<span class="sourceLineNo">336</span>   * @param prevBlockOffset see {@link #prevBlockOffset}<a name="line.336"></a>
+<span class="sourceLineNo">337</span>   * @param b block header ({@link HConstants#HFILEBLOCK_HEADER_SIZE} bytes)<a name="line.337"></a>
+<span class="sourceLineNo">338</span>   * @param fillHeader when true, write the first 4 header fields into passed buffer.<a name="line.338"></a>
+<span class="sourceLineNo">339</span>   * @param offset the file offset the block was read from<a name="line.339"></a>
+<span class="sourceLineNo">340</span>   * @param onDiskDataSizeWithHeader see {@link #onDiskDataSizeWithHeader}<a name="line.340"></a>
+<span class="sourceLineNo">341</span>   * @param fileContext HFile meta data<a name="line.341"></a>
+<span class="sourceLineNo">342</span>   */<a name="line.342"></a>
+<span class="sourceLineNo">343</span>  @VisibleForTesting<a name="line.343"></a>
+<span class="sourceLineNo">344</span>  public HFileBlock(BlockType blockType, int onDiskSizeWithoutHeader,<a name="line.344"></a>
+<span class="sourceLineNo">345</span>      int uncompressedSizeWithoutHeader, long prevBlockOffset, ByteBuffer b, boolean fillHeader,<a name="line.345"></a>
+<span class="sourceLineNo">346</span>      long offset, final int nextBlockOnDiskSize, int onDiskDataSizeWithHeader,<a name="line.346"></a>
+<span class="sourceLineNo">347</span>      HFileContext fileContext) {<a name="line.347"></a>
+<span class="sourceLineNo">348</span>    init(blockType, onDiskSizeWithoutHeader, uncompressedSizeWithoutHeader,<a name="line.348"></a>
+<span class="sourceLineNo">349</span>        prevBlockOffset, offset, onDiskDataSizeWithHeader, nextBlockOnDiskSize, fileContext);<a name="line.349"></a>
+<span class="sourceLineNo">350</span>    this.buf = new SingleByteBuff(b);<a name="line.350"></a>
+<span class="sourceLineNo">351</span>    if (fillHeader) {<a name="line.351"></a>
+<span class="sourceLineNo">352</span>      overwriteHeader();<a name="line.352"></a>
+<span class="sourceLineNo">353</span>    }<a name="line.353"></a>
+<span class="sourceLineNo">354</span>    this.buf.rewind();<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">357</span>  /**<a name="line.357"></a>
+<span class="sourceLineNo">358</span>   * Creates a block from an existing buffer starting with a header. Rewinds<a name="line.358"></a>
+<span class="sourceLineNo">359</span>   * and takes ownership of the buffer. By definition of rewind, ignores the<a name="line.359"></a>
+<span class="sourceLineNo">360</span>   * buffer position, but if you slice the buffer beforehand, it will rewind<a name="line.360"></a>
+<span class="sourceLineNo">361</span>   * to that point.<a name="line.361"></a>
+<span class="sourceLineNo">362</span>   * @param buf Has header, content, and trailing checksums if present.<a name="line.362"></a>
+<span class="sourceLineNo">363</span>   */<a name="line.363"></a>
+<span class="sourceLineNo">364</span>  HFileBlock(ByteBuff buf, boolean usesHBaseChecksum, MemoryType memType, final long offset,<a name="line.364"></a>
+<span class="sourceLineNo">365</span>      final int nextBlockOnDiskSize, HFileContext fileContext) throws IOException {<a name="line.365"></a>
+<span class="sourceLineNo">366</span>    buf.rewind();<a name="line.366"></a>
+<span class="sourceLineNo">367</span>    final BlockType blockType = BlockType.read(buf);<a name="line.367"></a>
+<span class="sourceLineNo">368</span>    final int onDiskSizeWithoutHeader = buf.getInt(Header.ON_DISK_SIZE_WITHOUT_HEADER_INDEX);<a name="line.368"></a>
+<span class="sourceLineNo">369</span>    final int uncompressedSizeWithoutHeader =<a name="line.369"></a>
+<span class="sourceLineNo">370</span>        buf.getInt(Header.UNCOMPRESSED_SIZE_WITHOUT_HEADER_INDEX);<a name="line.370"></a>
+<span class="sourceLineNo">371</span>    final long prevBlockOffset = buf.getLong(Header.PREV_BLOCK_OFFSET_INDEX);<a name="line.371"></a>
+<span class="sourceLineNo">372</span>    // This constructor is called when we deserialize a block from cache and when we read a block in<a name="line.372"></a>
+<span class="sourceLineNo">373</span>    // from the fs. fileCache is null when deserialized from cache so need to make up one.<a name="line.373"></a>
+<span class="sourceLineNo">374</span>    HFileContextBuilder fileContextBuilder = fileContext != null?<a name="line.374"></a>
+<span class="sourceLineNo">375</span>        new HFileContextBuilder(fileContext): new HFileContextBuilder();<a name="line.375"></a>
+<span class="sourceLineNo">376</span>    fileContextBuilder.withHBaseCheckSum(usesHBaseChecksum);<a name="line.376"></a>
+<span class="sourceLineNo">377</span>    int onDiskDataSizeWithHeader;<a name="line.377"></a>
+<span class="sourceLineNo">378</span>    if (usesHBaseChecksum) {<a name="line.378"></a>
+<span class="sourceLineNo">379</span>      byte checksumType = buf.get(Header.CHECKSUM_TYPE_INDEX);<a name="line.379"></a>
+<span class="sourceLineNo">380</span>      int bytesPerChecksum = buf.getInt(Header.BYTES_PER_CHECKSUM_INDEX);<a name="line.380"></a>
+<span class="sourceLineNo">381</span>      onDiskDataSizeWithHeader = buf.getInt(Header.ON_DISK_DATA_SIZE_WITH_HEADER_INDEX);<a name="line.381"></a>
+<span class="sourceLineNo">382</span>      // Use the checksum type and bytes per checksum from header, not from filecontext.<a name="line.382"></a>
+<span class="sourceLineNo">383</span>      fileContextBuilder.withChecksumType(ChecksumType.codeToType(checksumType));<a name="line.383"></a>
+<span class="sourceLineNo">384</span>      fileContextBuilder.withBytesPerCheckSum(bytesPerChecksum);<a name="line.384"></a>
+<span class="sourceLineNo">385</span>    } else {<a name="line.385"></a>
+<span class="sourceLineNo">386</span>      fileContextBuilder.withChecksumType(ChecksumType.NULL);<a name="line.386"></a>
+<span class="sourceLineNo">387</span>      fileContextBuilder.withBytesPerCheckSum(0);<a name="line.387"></a>
+<span class="sourceLineNo">388</span>      // Need to fix onDiskDataSizeWithHeader; there are not checksums after-block-data<a name="line.388"></a>
+<span class="sourceLineNo">389</span>      onDiskDataSizeWithHeader = onDiskSizeWithoutHeader + headerSize(usesHBaseChecksum);<a name="line.389"></a>
+<span class="sourceLineNo">390</span>    }<a name="line.390"></a>
+<span class="sourceLineNo">391</span>    fileContext = fileContextBuilder.build();<a name="line.391"></a>
+<span class="sourceLineNo">392</span>    assert usesHBaseChecksum == fileContext.isUseHBaseChecksum();<a name="line.392"></a>
+<span class="sourceLineNo">393</span>    init(blockType, onDiskSizeWithoutHeader, uncompressedSizeWithoutHeader,<a name="line.393"></a>
+<span class="sourceLineNo">394</span>        prevBlockOffset, offset, onDiskDataSizeWithHeader, nextBlockOnDiskSize, fileContext);<a name="line.394"></a>
+<span class="sourceLineNo">395</span>    this.memType = memType;<a name="line.395"></a>
+<span class="sourceLineNo">396</span>    this.offset = offset;<a name="line.396"></a>
+<span class="sourceLineNo">397</span>    this.buf = buf;<a name="line.397"></a>
+<span class="sourceLineNo">398</span>    this.buf.rewind();<a name="line.398"></a>
+<span class="sourceLineNo">399</span>  }<a name="line.399"></a>
+<span class="sourceLineNo">400</span><a name="line.400"></a>
+<span class="sourceLineNo">401</span>  /**<a name="line.401"></a>
+<span class="sourceLineNo">402</span>   * Called from constructors.<a name="line.402"></a>
+<span class="sourceLineNo">403</span>   */<a name="line.403"></a>
+<span class="sourceLineNo">404</span>  private void init(BlockType blockType, int onDiskSizeWithoutHeader,<a name="line.404"></a>
+<span class="sourceLineNo">405</span>      int uncompressedSizeWithoutHeader, long prevBlockOffset,<a name="line.405"></a>
+<span class="sourceLineNo">406</span>      long offset, int onDiskDataSizeWithHeader, final int nextBlockOnDiskSize,<a name="line.406"></a>
+<span class="sourceLineNo">407</span>      HFileContext fileContext) {<a name="line.407"></a>
+<span class="sourceLineNo">408</span>    this.blockType = blockType;<a name="line.408"></a>
+<span class="sourceLineNo">409</span>    this.onDiskSizeWithoutHeader = onDiskSizeWithoutHeader;<a name="line.409"></a>
+<span class="sourceLineNo">410</span>    this.uncompressedSizeWithoutHeader = uncompressedSizeWithoutHeader;<a name="line.410"></a>
+<span class="sourceLineNo">411</span>    this.prevBlockOffset = prevBlockOffset;<a name="line.411"></a>
+<span class="sourceLineNo">412</span>    this.offset = offset;<a name="line.412"></a>
+<span class="sourceLineNo">413</span>    this.onDiskDataSizeWithHeader = onDiskDataSizeWithHeader;<a name="line.413"></a>
+<span class="sourceLineNo">414</span>    this.nextBlockOnDiskSize = nextBlockOnDiskSize;<a name="line.414"></a>
+<span class="sourceLineNo">415</span>    this.fileContext = fileContext;<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">418</span>  /**<a name="line.418"></a>
+<span class="sourceLineNo">419</span>   * Parse total on disk size including header and checksum.<a name="line.419"></a>
+<span class="sourceLineNo">420</span>   * @param headerBuf Header ByteBuffer. Presumed exact size of header.<a name="line.420"></a>
+<span class="sourceLineNo">421</span>   * @param verifyChecksum true if checksum verification is in use.<a name="line.421"></a>
+<span class="sourceLineNo">422</span>   * @return Size of the block with header included.<a name="line.422"></a>
+<span class="sourceLineNo">423</span>   */<a name="line.423"></a>
+<span class="sourceLineNo">424</span>  private static int getOnDiskSizeWithHeader(final ByteBuffer headerBuf,<a name="line.424"></a>
+<span class="sourceLineNo">425</span>      boolean verifyChecksum) {<a name="line.425"></a>
+<span class="sourceLineNo">426</span>    return headerBuf.getInt(Header.ON_DISK_SIZE_WITHOUT_HEADER_INDEX) +<a name="line.426"></a>
+<span class="sourceLineNo">427</span>      headerSize(verifyChecksum);<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>   * @return the on-disk size of the next block (including the header size and any checksums if<a name="line.431"></a>
+<span class="sourceLineNo">432</span>   * present) read by peeking into the next block's header; use as a hint when doing<a name="line.432"></a>
+<span class="sourceLineNo">433</span>   * a read of the next block when scanning or running over a file.<a name="line.433"></a>
+<span class="sourceLineNo">434</span>   */<a name="line.434"></a>
+<span class="sourceLineNo">435</span>  int getNextBlockOnDiskSize() {<a name="line.435"></a>
+<span class="sourceLineNo">436</span>    return nextBlockOnDiskSize;<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>  @Override<a name="line.439"></a>
+<span class="sourceLineNo">440</span>  public BlockType getBlockType() {<a name="line.440"></a>
+<span class="sourceLineNo">441</span>    return blockType;<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>  /** @return get data block encoding id that was used to encode this block */<a name="line.444"></a>
+<span class="sourceLineNo">445</span>  short getDataBlockEncodingId() {<a name="line.445"></a>
+<span class="sourceLineNo">446</span>    if (blockType != BlockType.ENCODED_DATA) {<a name="line.446"></a>
+<span class="sourceLineNo">447</span>      throw new IllegalArgumentException("Querying encoder ID of a block " +<a name="line.447"></a>
+<span class="sourceLineNo">448</span>          "of type other than " + BlockType.ENCODED_DATA + ": " + blockType);<a name="line.448"></a>
+<span class="sourceLineNo">449</span>    }<a name="line.449"></a>
+<span class="sourceLineNo">450</span>    return buf.getShort(headerSize());<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>   * @return the on-disk size of header + data part + checksum.<a name="line.454"></a>
+<span class="sourceLineNo">455</span>   */<a name="line.455"></a>
+<span class="sourceLineNo">456</span>  public int getOnDiskSizeWithHeader() {<a name="line.456"></a>
+<span class="sourceLineNo">457</span>    return onDiskSizeWithoutHeader + headerSize();<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>   * @return the on-disk size of the data part + checksum (header excluded).<a name="line.461"></a>
+<span class="sourceLineNo">462</span>   */<a name="line.462"></a>
+<span class="sourceLineNo">463</span>  int getOnDiskSizeWithoutHeader() {<a name="line.463"></a>
+<span class="sourceLineNo">464</span>    return onDiskSizeWithoutHeader;<a name="line.464"></a>
+<span class="sourceLineNo">465</span>  }<a name="line.465"></a>
+<span class="sourceLineNo">466</span><a name="line.466"></a>
+<span class="sourceLineNo">467</span>  /**<a name="line.467"></a>
+<span class="sourceLineNo">468</span>   * @return the uncompressed size of data part (header and checksum excluded).<a name="line.468"></a>
+<span class="sourceLineNo">469</span>   */<a name="line.469"></a>
+<span class="sourceLineNo">470</span>   int getUncompressedSizeWithoutHeader() {<a name="line.470"></a>
+<span class="sourceLineNo">471</span>    return uncompressedSizeWithoutHeader;<a name="line.471"></a>
+<span class="sourceLineNo">472</span>  }<a name="line.472"></a>
+<span class="sourceLineNo">473</span><a name="line.473"></a>
+<span class="sourceLineNo">474</span>  /**<a name="line.474"></a>
+<span class="sourceLineNo">475</span>   * @return the offset of the previous block of the same type in the file, or<a name="line.475"></a>
+<span class="sourceLineNo">476</span>   *         -1 if unknown<a name="line.476"></a>
+<span class="sourceLineNo">477</span>   */<a name="line.477"></a>
+<span class="sourceLineNo">478</span>  long getPrevBlockOffset() {<a name="line.478"></a>
+<span class="sourceLineNo">479</span>    return prevBlockOffset;<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>   * Rewinds {@code buf} and writes first 4 header fields. {@code buf} position<a name="line.483"></a>
+<span class="sourceLineNo">484</span>   * is modified as side-effect.<a name="line.484"></a>
+<span class="sourceLineNo">485</span>   */<a name="line.485"></a>
+<span class="sourceLineNo">486</span>  private void overwriteHeader() {<a name="line.486"></a>
+<span class="sourceLineNo">487</span>    buf.rewind();<a name="line.487"></a>
+<span class="sourceLineNo">488</span>    blockType.write(buf);<a name="line.488"></a>
+<span class="sourceLineNo">489</span>    buf.putInt(onDiskSizeWithoutHeader);<a name="line.489"></a>
+<span class="sourceLineNo">490</span>    buf.putInt(uncompressedSizeWithoutHeader);<a name="line.490"></a>
+<span class="sourceLineNo">491</span>    buf.putLong(prevBlockOffset);<a name="line.491"></a>
+<span class="sourceLineNo">492</span>    if (this.fileContext.isUseHBaseChecksum()) {<a name="line.492"></a>
+<span class="sourceLineNo">493</span>      buf.put(fileContext.getChecksumType().getCode());<a name="line.493"></a>
+<span class="sourceLineNo">494</span>      buf.putInt(fileContext.getBytesPerChecksum());<a name="line.494"></a>
+<span class="sourceLineNo">495</span>      buf.putInt(onDiskDataSizeWithHeader);<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><a name="line.498"></a>
+<span class="sourceLineNo">499</span>  /**<a name="line.499"></a>
+<span class="sourceLineNo">500</span>   * Returns a buffer that does not include the header or checksum.<a name="line.500"></a>
+<span class="sourceLineNo">501</span>   *<a name="line.501"></a>
+<span class="sourceLineNo">502</span>   * @return the buffer with header skipped and checksum omitted.<a name="line.502"></a>
+<span class="sourceLineNo">503</span>   */<a name="line.503"></a>
+<span class="sourceLineNo">504</span>  public ByteBuff getBufferWithoutHeader() {<a name="line.504"></a>
+<span class="sourceLineNo">505</span>    ByteBuff dup = getBufferReadOnly();<a name="line.505"></a>
+<span class="sourceLineNo">506</span>    // Now set it up so Buffer spans content only -- no header or no checksums.<a name="line.506"></a>
+<span class="sourceLineNo">507</span>    return dup.position(headerSize()).limit(buf.limit() - totalChecksumBytes()).slice();<a name="line.507"></a>
+<span class="sourceLineNo">508</span>  }<a name="line.508"></a>
+<span class="sourceLineNo">509</span><a name="line.509"></a>
+<span class="sourceLineNo">510</span>  /**<a name="line.510"></a>
+<span class="sourceLineNo">511</span>   * Returns a read-only duplicate of the buffer this block stores internally ready to be read.<a name="line.511"></a>
+<span class="sourceLineNo">512</span>   * Clients must not modify the buffer object though they may set position and limit on the<a name="line.512"></a>
+<span class="sourceLineNo">513</span>   * returned buffer since we pass back a duplicate. This method has to be public because it is used<a name="line.513"></a>
+<span class="sourceLineNo">514</span>   * in {@link CompoundBloomFilter} to avoid object creation on every Bloom<a name="line.514"></a>
+<span class="sourceLineNo">515</span>   * filter lookup, but has to be used with caution. Buffer holds header, block content,<a name="line.515"></a>
+<span class="sourceLineNo">516</span>   * and any follow-on checksums if present.<a name="line.516"></a>
+<span class="sourceLineNo">517</span>   *<a name="line.517"></a>
+<span class="sourceLineNo">518</span>   * @return the buffer of this block for read-only operations<a name="line.518"></a>
+<span class="sourceLineNo">519</span>   */<a name="line.519"></a>
+<span class="sourceLineNo">520</span>  public ByteBuff getBufferReadOnly() {<a name="line.520"></a>
+<span class="sourceLineNo">521</span>    // TODO: ByteBuf does not support asReadOnlyBuffer(). Fix.<a name="line.521"></a>
+<span class="sourceLineNo">522</span>    ByteBuff dup = this.buf.duplicate();<a name="line.522"></a>
+<span class="sourceLineNo">523</span>    assert dup.position() == 0;<a name="line.523"></a>
+<span class="sourceLineNo">524</span>    return dup;<a name="line.524"></a>
+<span class="sourceLineNo">525</span>  }<a name="line.525"></a>
+<span class="sourceLineNo">526</span><a name="line.526"></a>
+<span class="sourceLineNo">527</span>  @VisibleForTesting<a name="line.527"></a>
+<span class="sourceLineNo">528</span>  private void sanityCheckAssertion(long valueFromBuf, long valueFromField,<a name="line.528"></a>
+<span class="sourceLineNo">529</span>      String fieldName) throws IOException {<a name="line.529"></a>
+<span class="sourceLineNo">530</span>    if (valueFromBuf != valueFromField) {<a name="line.530"></a>
+<span class="sourceLineNo">531</span>      throw new AssertionError(fieldName + " in the buffer (" + valueFromBuf<a name="line.531"></a>
+<span class="sourceLineNo">532</span>          + ") is different from that in the field (" + valueFromField + ")");<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>  @VisibleForTesting<a name="line.536"></a>
+<span class="sourceLineNo">537</span>  private void sanityCheckAssertion(BlockType valueFromBuf, BlockType valueFromField)<a name="line.537"></a>
+<span class="sourceLineNo">538</span>      throws IOException {<a name="line.538"></a>
+<span class="sourceLineNo">539</span>    if (valueFromBuf != valueFromField) {<a name="line.539"></a>
+<span class="sourceLineNo">540</span>      throw new IOException("Block type stored in the buffer: " +<a name="line.540"></a>
+<span class="sourceLineNo">541</span>        valueFromBuf + ", block type field: " + valueFromField);<a name="line.541"></a>
+<span class="sourceLineNo">542</span>    }<a name="line.542"></a>
+<span class="sourceLineNo">543</span>  }<a name="line.543"></a>
+<span class="sourceLineNo">544</span><a name="line.544"></a>
+<span class="sourceLineNo">545</span>  /**<a name="line.545"></a>
+<span class="sourceLineNo">546</span>   * Checks if the block is internally consistent, i.e. the first<a name="line.546"></a>
+<span class="sourceLineNo">547</span>   * {@link HConstants#HFILEBLOCK_HEADER_SIZE} bytes of the buffer contain a<a name="line.547"></a>
+<span class="sourceLineNo">548</span>   * valid header consistent with the fields. Assumes a packed block structure.<a name="line.548"></a>
+<span class="sourceLineNo">549</span>   * This function is primary for testing and debugging, and is not<a name="line.549"></a>
+<span class="sourceLineNo">550</span>   * thread-safe, because it alters the internal buffer pointer.<a name="line.550"></a>
+<span class="sourceLineNo">551</span>   * Used by tests only.<a name="line.551"></a>
+<span class="sourceLineNo">552</span>   */<a name="line.552"></a>
+<span class="sourceLineNo">553</span>  @VisibleForTesting<a name="line.553"></a>
+<span class="sourceLineNo">554</span>  void sanityCheck() throws IOException {<a name="line.554"></a>
+<span class="sourceLineNo">555</span>    // Duplicate so no side-effects<a name="line.555"></a>
+<span class="sourceLineNo">556</span>    ByteBuff dup = this.buf.duplicate().rewind();<a name="line.556"></a>
+<span class="sourceLineNo">557</span>    sanityCheckAssertion(BlockType.read(dup), blockType);<a name="line.557"></a>
+<span class="sourceLineNo">558</span><a name="line.558"></a>
+<span class="sourceLineNo">559</span>    sanityCheckAssertion(dup.getInt(), onDiskSizeWithoutHeader, "onDiskSizeWithoutHeader");<a name="line.559"></a>
+<span class="sourceLineNo">560</span><a name="line.560"></a>
+<span class="sourceLineNo">561</span>    sanityCheckAssertion(dup.getInt(), uncompressedSizeWithoutHeader,<a name="line.561"></a>
+<span class="sourceLineNo">562</span>        "uncompressedSizeWithoutHeader");<a name="line.562"></a>
+<span class="sourceLineNo">563</span><a name="line.563"></a>
+<span class="sourceLineNo">564</span>    sanityCheckAssertion(dup.getLong(), prevBlockOffset, "prevBlockOffset");<a name="line.564"></a>
+<span class="sourceLineNo">565</span>    if (this.fileContext.isUseHBaseChecksum()) {<a name="line.565"></a>
+<span class="sourceLineNo">566</span>      sanityCheckAssertion(dup.get(), this.fileContext.getChecksumType().getCode(), "checksumType");<a name="line.566"></a>
+<span class="sourceLineNo">567</span>      sanityCheckAssertion(dup.getInt(), this.fileContext.getBytesPerChecksum(),<a name="line.567"></a>
+<span class="sourceLineNo">568</span>          "bytesPerChecksum");<a name="line.568"></a>
+<span class="sourceLineNo">569</span>      sanityCheckAssertion(dup.getInt(), onDiskDataSizeWithHeader, "onDiskDataSizeWithHeader");<a name="line.569"></a>
+<span class="sourceLineNo">570</span>    }<a name="line.570"></a>
+<span class="sourceLineNo">571</span><a name="line.571"></a>
+<span class="sourceLineNo">572</span>    int cksumBytes = totalChecksumBytes();<a name="line.572"></a>
+<span class="sourceLineNo">573</span>    int expectedBufLimit = onDiskDataSizeWithHeader + cksumBytes;<a name="line.573"></a>
+<span class="sourceLineNo">574</span>    if (dup.limit() != expectedBufLimit) {<a name="line.574"></a>
+<span class="sourceLineNo">575</span>      throw new AssertionError("Expected limit " + expectedBufLimit + ", got " + dup.limit());<a name="line.575"></a>
+<span class="sourceLineNo">576</span>    }<a name="line.576"></a>
+<span class="sourceLineNo">577</span><a name="line.577"></a>
+<span class="sourceLineNo">578</span>    // We might optionally allocate HFILEBLOCK_HEADER_SIZE more bytes to read the next<a name="line.578"></a>
+<span class="sourceLineNo">579</span>    // block's header, so there are two sensible values for buffer capacity.<a name="line.579"></a>
+<span class="sourceLineNo">580</span>    int hdrSize = headerSize();<a name="line.580"></a>
+<span class="sourceLineNo">581</span>    if (dup.capacity() != expectedBufLimit &amp;&amp; dup.capacity() != expectedBufLimit + hdrSize) {<a name="line.581"></a>
+<span class="sourceLineNo">582</span>      throw new AssertionError("Invalid buffer capacity: " + dup.capacity() +<a name="line.582"></a>
+<span class="sourceLineNo">583</span>          ", expected " + expectedBufLimit + " or " + (expectedBufLimit + hdrSize));<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>  @Override<a name="line.587"></a>
+<span class="sourceLineNo">588</span>  public String toString() {<a name="line.588"></a>
+<span class="sourceLineNo">589</span>    StringBuilder sb = new StringBuilder()<a name="line.589"></a>
+<span class="sourceLineNo">590</span>      .append("[")<a name="line.590"></a>
+<span class="sourceLineNo">591</span>      .append("blockType=").append(blockType)<a name="line.591"></a>
+<span class="sourceLineNo">592</span>      .append(", fileOffset=").append(offset)<a name="line.592"></a>
+<span class="sourceLineNo">593</span>      .append(", headerSize=").append(headerSize())<a name="line.593"></a>
+<span class="sourceLineNo">594</span>      .append(", onDiskSizeWithoutHeader=").append(onDiskSizeWithoutHeader)<a name="line.594"></a>
+<span class="sourceLineNo">595</span>      .append(", uncompressedSizeWithoutHeader=").append(uncompressedSizeWithoutHeader)<a name="line.595"></a>
+<span class="sourceLineNo">596</span>      .append(", prevBlockOffset=").append(prevBlockOffset)<a name="line.596"></a>
+<span class="sourceLineNo">597</span>      .append(", isUseHBaseChecksum=").append(fileContext.isUseHBaseChecksum());<a name="line.597"></a>
+<span class="sourceLineNo">598</span>    if (fileContext.isUseHBaseChecksum()) {<a name="line.598"></a>
+<span class="sourceLineNo">599</span>      sb.append(", checksumType=").append(ChecksumType.codeToType(this.buf.get(24)))<a name="line.599"></a>
+<span class="sourceLineNo">600</span>        .append(", bytesPerChecksum=").append(this.buf.getInt(24 + 1))<a name="line.600"></a>
+<span class="sourceLineNo">601</span>        .append(", onDiskDataSizeWithHeader=").append(onDiskDataSizeWithHeader);<a name="line.601"></a>
+<span class="sourceLineNo">602</span>    } else {<a name="line.602"></a>
+<span class="sourceLineNo">603</span>      sb.append(", onDiskDataSizeWithHeader=").append(onDiskDataSizeWithHeader)<a name="line.603"></a>
+<span class="sourceLineNo">604</span>        .append("(").append(onDiskSizeWithoutHeader)<a name="line.604"></a>
+<span class="sourceLineNo">605</span>        .append("+").append(HConstants.HFILEBLOCK_HEADER_SIZE_NO_CHECKSUM).append(")");<a name="line.605"></a>
+<span class="sourceLineNo">606</span>    }<a name="line.606"></a>
+<span class="sourceLineNo">607</span>    String dataBegin = null;<a name="line.607"></a>
+<span class="sourceLineNo">608</span>    if (buf.hasArray()) {<a name="line.608"></a>
+<span class="sourceLineNo">609</span>      dataBegin = Bytes.toStringBinary(buf.array(), buf.arrayOffset() + headerSize(),<a name="line.609"></a>
+<span class="sourceLineNo">610</span>          Math.min(32, buf.limit() - buf.arrayOffset() - headerSize()));<a name="line.610"></a>
+<span class="sourceLineNo">611</span>    } else {<a name="line.611"></a>
+<span class="sourceLineNo">612</span>      ByteBuff bufWithoutHeader = getBufferWithoutHeader();<a name="line.612"></a>
+<span class="sourceLineNo">613</span>      byte[] dataBeginBytes = new byte[Math.min(32,<a name="line.613"></a>
+<span class="sourceLineNo">614</span>          bufWithoutHeader.limit() - bufWithoutHeader.position())];<a name="line.614"></a>
+<span class="sourceLineNo">615</span>      bufWithoutHeader.get(dataBeginBytes);<a name="line.615"></a>
+<span class="sourceLineNo">616</span>      dataBegin = Bytes.toStringBinary(dataBeginBytes);<a name="line.616"></a>
+<span class="sourceLineNo">617</span>    }<a name="line.617"></a>
+<span class="sourceLineNo">618</span>    sb.append(", getOnDiskSizeWithHeader=").append(getOnDiskSizeWithHeader())<a name="line.618"></a>
+<span class="sourceLineNo">619</span>      .append(", totalChecksumBytes=").append(totalChecksumBytes())<a name="line.619"></a>
+<span class="sourceLineNo">620</span>      .append(", isUnpacked=").append(isUnpacked())<a name="line.620"></a>
+<span class="sourceLineNo">621</span>      .append(", buf=[").append(buf).append("]")<a name="line.621"></a>
+<span class="sourceLineNo">622</span>      .append(", dataBeginsWith=").append(dataBegin)<a name="line.622"></a>
+<span class="sourceLineNo">623</span>      .append(", fileContext=").append(fileContext)<a name="line.623"></a>
+<span class="sourceLineNo">624</span>      .append(", nextBlockOnDiskSize=").append(nextBlockOnDiskSize)<a name="line.624"></a>
+<span class="sourceLineNo">625</span>      .append("]");<a name="line.625"></a>
+<span class="sourceLineNo">626</span>    return sb.toString();<a name="line.626"></a>
+<span class="sourceLineNo">627</span>  }<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>   * Retrieves the decompressed/decrypted view of this block. An encoded block remains in its<a name="line.630"></a>
+<span class="sourceLineNo">631</span>   * encoded structure. Internal structures are shared between instances where applicable.<a name="line.631"></a>
+<span class="sourceLineNo">632</span>   */<a name="line.632"></a>
+<span class="sourceLineNo">633</span>  HFileBlock unpack(HFileContext fileContext, FSReader reader) throws IOException {<a name="line.633"></a>
+<span class="sourceLineNo">634</span>    if (!fileContext.isCompressedOrEncrypted()) {<a name="line.634"></a>
+<span class="sourceLineNo">635</span>      // TODO: cannot use our own fileContext here because HFileBlock(ByteBuffer, boolean),<a name="line.635"></a>
+<span class="sourceLineNo">636</span>      // which is used for block serialization to L2 cache, does not preserve encoding and<a name="line.636"></a>
+<span class="sourceLineNo">637</span>      // encryption details.<a name="line.637"></a>
+<span class="sourceLineNo">638</span>      return this;<a name="line.638"></a>
+<span class="sourceLineNo">639</span>    }<a name="line.639"></a>
+<span class="sourceLineNo">640</span><a name="line.640"></a>
+<span class="sourceLineNo">641</span>    HFileBlock unpacked = new HFileBlock(this);<a name="line.641"></a>
+<span class="sourceLineNo">642</span>    unpacked.allocateBuffer(); // allocates space for the decompressed block<a name="line.642"></a>
+<span class="sourceLineNo">643</span><a name="line.643"></a>
+<span class="sourceLineNo">644</span>    HFileBlockDecodingContext ctx = blockType == BlockType.ENCODED_DATA ?<a name="line.644"></a>
+<span class="sourceLineNo">645</span>      reader.getBlockDecodingContext() : reader.getDefaultBlockDecodingContext();<a name="line.645"></a>
+<span class="sourceLineNo">646</span><a name="line.646"></a>
+<span class="sourceLineNo">647</span>    ByteBuff dup = this.buf.duplicate();<a name="line.647"></a>
+<span class="sourceLineNo">648</span>    dup.position(this.headerSize());<a name="line.648"></a>
+<span class="sourceLineNo">649</span>    dup = dup.slice();<a name="line.649"></a>
+<span class="sourceLineNo">650</span>    ctx.prepareDecoding(unpacked.getOnDiskSizeWitho

<TRUNCATED>

[05/50] hbase-site git commit: Published site at 26babcf013de696b899d76a3c39434b794440d8d.

Posted by gi...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html b/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html
index 1774db3..2ab8397 100644
--- a/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html
+++ b/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html
@@ -39,879 +39,933 @@
 <span class="sourceLineNo">031</span>import org.apache.hadoop.conf.Configuration;<a name="line.31"></a>
 <span class="sourceLineNo">032</span>import org.apache.hadoop.hbase.HBaseClassTestRule;<a name="line.32"></a>
 <span class="sourceLineNo">033</span>import org.apache.hadoop.hbase.HBaseConfiguration;<a name="line.33"></a>
-<span class="sourceLineNo">034</span>import org.apache.hadoop.hbase.Waiter;<a name="line.34"></a>
-<span class="sourceLineNo">035</span>import org.apache.hadoop.hbase.Waiter.ExplainingPredicate;<a name="line.35"></a>
-<span class="sourceLineNo">036</span>import org.apache.hadoop.hbase.io.HeapSize;<a name="line.36"></a>
-<span class="sourceLineNo">037</span>import org.apache.hadoop.hbase.io.hfile.LruBlockCache.EvictionThread;<a name="line.37"></a>
-<span class="sourceLineNo">038</span>import org.apache.hadoop.hbase.testclassification.IOTests;<a name="line.38"></a>
-<span class="sourceLineNo">039</span>import org.apache.hadoop.hbase.testclassification.SmallTests;<a name="line.39"></a>
-<span class="sourceLineNo">040</span>import org.apache.hadoop.hbase.util.ClassSize;<a name="line.40"></a>
-<span class="sourceLineNo">041</span>import org.junit.ClassRule;<a name="line.41"></a>
-<span class="sourceLineNo">042</span>import org.junit.Test;<a name="line.42"></a>
-<span class="sourceLineNo">043</span>import org.junit.experimental.categories.Category;<a name="line.43"></a>
-<span class="sourceLineNo">044</span><a name="line.44"></a>
-<span class="sourceLineNo">045</span>/**<a name="line.45"></a>
-<span class="sourceLineNo">046</span> * Tests the concurrent LruBlockCache.&lt;p&gt;<a name="line.46"></a>
-<span class="sourceLineNo">047</span> *<a name="line.47"></a>
-<span class="sourceLineNo">048</span> * Tests will ensure it grows and shrinks in size properly,<a name="line.48"></a>
-<span class="sourceLineNo">049</span> * evictions run when they're supposed to and do what they should,<a name="line.49"></a>
-<span class="sourceLineNo">050</span> * and that cached blocks are accessible when expected to be.<a name="line.50"></a>
-<span class="sourceLineNo">051</span> */<a name="line.51"></a>
-<span class="sourceLineNo">052</span>@Category({IOTests.class, SmallTests.class})<a name="line.52"></a>
-<span class="sourceLineNo">053</span>public class TestLruBlockCache {<a name="line.53"></a>
-<span class="sourceLineNo">054</span><a name="line.54"></a>
-<span class="sourceLineNo">055</span>  @ClassRule<a name="line.55"></a>
-<span class="sourceLineNo">056</span>  public static final HBaseClassTestRule CLASS_RULE =<a name="line.56"></a>
-<span class="sourceLineNo">057</span>      HBaseClassTestRule.forClass(TestLruBlockCache.class);<a name="line.57"></a>
-<span class="sourceLineNo">058</span><a name="line.58"></a>
-<span class="sourceLineNo">059</span>  @Test<a name="line.59"></a>
-<span class="sourceLineNo">060</span>  public void testCacheEvictionThreadSafe() throws Exception {<a name="line.60"></a>
-<span class="sourceLineNo">061</span>    long maxSize = 100000;<a name="line.61"></a>
-<span class="sourceLineNo">062</span>    int numBlocks = 9;<a name="line.62"></a>
-<span class="sourceLineNo">063</span>    int testRuns = 10;<a name="line.63"></a>
-<span class="sourceLineNo">064</span>    final long blockSize = calculateBlockSizeDefault(maxSize, numBlocks);<a name="line.64"></a>
-<span class="sourceLineNo">065</span>    assertTrue("calculateBlockSize appears broken.", blockSize * numBlocks &lt;= maxSize);<a name="line.65"></a>
-<span class="sourceLineNo">066</span><a name="line.66"></a>
-<span class="sourceLineNo">067</span>    final Configuration conf = HBaseConfiguration.create();<a name="line.67"></a>
-<span class="sourceLineNo">068</span>    final LruBlockCache cache = new LruBlockCache(maxSize, blockSize);<a name="line.68"></a>
-<span class="sourceLineNo">069</span>    EvictionThread evictionThread = cache.getEvictionThread();<a name="line.69"></a>
-<span class="sourceLineNo">070</span>    assertTrue(evictionThread != null);<a name="line.70"></a>
-<span class="sourceLineNo">071</span>    while (!evictionThread.isEnteringRun()) {<a name="line.71"></a>
-<span class="sourceLineNo">072</span>      Thread.sleep(1);<a name="line.72"></a>
-<span class="sourceLineNo">073</span>    }<a name="line.73"></a>
-<span class="sourceLineNo">074</span>    final String hfileName = "hfile";<a name="line.74"></a>
-<span class="sourceLineNo">075</span>    int threads = 10;<a name="line.75"></a>
-<span class="sourceLineNo">076</span>    final int blocksPerThread = 5 * numBlocks;<a name="line.76"></a>
-<span class="sourceLineNo">077</span>    for (int run = 0; run != testRuns; ++run) {<a name="line.77"></a>
-<span class="sourceLineNo">078</span>      final AtomicInteger blockCount = new AtomicInteger(0);<a name="line.78"></a>
-<span class="sourceLineNo">079</span>      ExecutorService service = Executors.newFixedThreadPool(threads);<a name="line.79"></a>
-<span class="sourceLineNo">080</span>      for (int i = 0; i != threads; ++i) {<a name="line.80"></a>
-<span class="sourceLineNo">081</span>        service.execute(new Runnable() {<a name="line.81"></a>
-<span class="sourceLineNo">082</span>          @Override<a name="line.82"></a>
-<span class="sourceLineNo">083</span>          public void run() {<a name="line.83"></a>
-<span class="sourceLineNo">084</span>            for (int blockIndex = 0; blockIndex &lt; blocksPerThread || (!cache.isEvictionInProgress()); ++blockIndex) {<a name="line.84"></a>
-<span class="sourceLineNo">085</span>              CachedItem block = new CachedItem(hfileName, (int) blockSize, blockCount.getAndIncrement());<a name="line.85"></a>
-<span class="sourceLineNo">086</span>              boolean inMemory = Math.random() &gt; 0.5;<a name="line.86"></a>
-<span class="sourceLineNo">087</span>              cache.cacheBlock(block.cacheKey, block, inMemory);<a name="line.87"></a>
-<span class="sourceLineNo">088</span>            }<a name="line.88"></a>
-<span class="sourceLineNo">089</span>            cache.evictBlocksByHfileName(hfileName);<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>      }<a name="line.92"></a>
-<span class="sourceLineNo">093</span>      service.shutdown();<a name="line.93"></a>
-<span class="sourceLineNo">094</span>      // The test may fail here if the evict thread frees the blocks too fast<a name="line.94"></a>
-<span class="sourceLineNo">095</span>      service.awaitTermination(10, TimeUnit.MINUTES);<a name="line.95"></a>
-<span class="sourceLineNo">096</span>      Waiter.waitFor(conf, 10000, 100, new ExplainingPredicate&lt;Exception&gt;() {<a name="line.96"></a>
-<span class="sourceLineNo">097</span>        @Override<a name="line.97"></a>
-<span class="sourceLineNo">098</span>        public boolean evaluate() throws Exception {<a name="line.98"></a>
-<span class="sourceLineNo">099</span>          return cache.getBlockCount() == 0;<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>        @Override<a name="line.102"></a>
-<span class="sourceLineNo">103</span>        public String explainFailure() throws Exception {<a name="line.103"></a>
-<span class="sourceLineNo">104</span>          return "Cache block count failed to return to 0";<a name="line.104"></a>
-<span class="sourceLineNo">105</span>        }<a name="line.105"></a>
-<span class="sourceLineNo">106</span>      });<a name="line.106"></a>
-<span class="sourceLineNo">107</span>      assertEquals(0, cache.getBlockCount());<a name="line.107"></a>
-<span class="sourceLineNo">108</span>      assertEquals(cache.getOverhead(), cache.getCurrentSize());<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>  @Test<a name="line.111"></a>
-<span class="sourceLineNo">112</span>  public void testBackgroundEvictionThread() throws Exception {<a name="line.112"></a>
-<span class="sourceLineNo">113</span>    long maxSize = 100000;<a name="line.113"></a>
-<span class="sourceLineNo">114</span>    int numBlocks = 9;<a name="line.114"></a>
-<span class="sourceLineNo">115</span>    long blockSize = calculateBlockSizeDefault(maxSize, numBlocks);<a name="line.115"></a>
-<span class="sourceLineNo">116</span>    assertTrue("calculateBlockSize appears broken.", blockSize * numBlocks &lt;= maxSize);<a name="line.116"></a>
-<span class="sourceLineNo">117</span><a name="line.117"></a>
-<span class="sourceLineNo">118</span>    LruBlockCache cache = new LruBlockCache(maxSize,blockSize);<a name="line.118"></a>
-<span class="sourceLineNo">119</span>    EvictionThread evictionThread = cache.getEvictionThread();<a name="line.119"></a>
-<span class="sourceLineNo">120</span>    assertTrue(evictionThread != null);<a name="line.120"></a>
-<span class="sourceLineNo">121</span><a name="line.121"></a>
-<span class="sourceLineNo">122</span>    CachedItem[] blocks = generateFixedBlocks(numBlocks + 1, blockSize, "block");<a name="line.122"></a>
-<span class="sourceLineNo">123</span><a name="line.123"></a>
-<span class="sourceLineNo">124</span>    // Make sure eviction thread has entered run method<a name="line.124"></a>
-<span class="sourceLineNo">125</span>    while (!evictionThread.isEnteringRun()) {<a name="line.125"></a>
-<span class="sourceLineNo">126</span>      Thread.sleep(1);<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>    // Add all the blocks<a name="line.129"></a>
-<span class="sourceLineNo">130</span>    for (CachedItem block : blocks) {<a name="line.130"></a>
-<span class="sourceLineNo">131</span>      cache.cacheBlock(block.cacheKey, block);<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>    // wait until at least one eviction has run<a name="line.134"></a>
-<span class="sourceLineNo">135</span>    int n = 0;<a name="line.135"></a>
-<span class="sourceLineNo">136</span>    while(cache.getStats().getEvictionCount() == 0) {<a name="line.136"></a>
-<span class="sourceLineNo">137</span>      Thread.sleep(200);<a name="line.137"></a>
-<span class="sourceLineNo">138</span>      assertTrue("Eviction never happened.", n++ &lt; 20);<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>    // let cache stabilize<a name="line.141"></a>
-<span class="sourceLineNo">142</span>    // On some systems, the cache will run multiple evictions before it attains<a name="line.142"></a>
-<span class="sourceLineNo">143</span>    // steady-state. For instance, after populating the cache with 10 blocks,<a name="line.143"></a>
-<span class="sourceLineNo">144</span>    // the first eviction evicts a single block and then a second eviction<a name="line.144"></a>
-<span class="sourceLineNo">145</span>    // evicts another. I think this is due to the delta between minSize and<a name="line.145"></a>
-<span class="sourceLineNo">146</span>    // acceptableSize, combined with variance between object overhead on<a name="line.146"></a>
-<span class="sourceLineNo">147</span>    // different environments.<a name="line.147"></a>
-<span class="sourceLineNo">148</span>    n = 0;<a name="line.148"></a>
-<span class="sourceLineNo">149</span>    for (long prevCnt = 0 /* &lt; number of blocks added */,<a name="line.149"></a>
-<span class="sourceLineNo">150</span>              curCnt = cache.getBlockCount();<a name="line.150"></a>
-<span class="sourceLineNo">151</span>        prevCnt != curCnt; prevCnt = curCnt, curCnt = cache.getBlockCount()) {<a name="line.151"></a>
-<span class="sourceLineNo">152</span>      Thread.sleep(200);<a name="line.152"></a>
-<span class="sourceLineNo">153</span>      assertTrue("Cache never stabilized.", n++ &lt; 20);<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>    long evictionCount = cache.getStats().getEvictionCount();<a name="line.156"></a>
-<span class="sourceLineNo">157</span>    assertTrue(evictionCount &gt;= 1);<a name="line.157"></a>
-<span class="sourceLineNo">158</span>    System.out.println("Background Evictions run: " + evictionCount);<a name="line.158"></a>
-<span class="sourceLineNo">159</span>  }<a name="line.159"></a>
-<span class="sourceLineNo">160</span><a name="line.160"></a>
-<span class="sourceLineNo">161</span>  @Test<a name="line.161"></a>
-<span class="sourceLineNo">162</span>  public void testCacheSimple() throws Exception {<a name="line.162"></a>
-<span class="sourceLineNo">163</span><a name="line.163"></a>
-<span class="sourceLineNo">164</span>    long maxSize = 1000000;<a name="line.164"></a>
-<span class="sourceLineNo">165</span>    long blockSize = calculateBlockSizeDefault(maxSize, 101);<a name="line.165"></a>
-<span class="sourceLineNo">166</span><a name="line.166"></a>
-<span class="sourceLineNo">167</span>    LruBlockCache cache = new LruBlockCache(maxSize, blockSize);<a name="line.167"></a>
-<span class="sourceLineNo">168</span><a name="line.168"></a>
-<span class="sourceLineNo">169</span>    CachedItem [] blocks = generateRandomBlocks(100, blockSize);<a name="line.169"></a>
-<span class="sourceLineNo">170</span><a name="line.170"></a>
-<span class="sourceLineNo">171</span>    long expectedCacheSize = cache.heapSize();<a name="line.171"></a>
-<span class="sourceLineNo">172</span><a name="line.172"></a>
-<span class="sourceLineNo">173</span>    // Confirm empty<a name="line.173"></a>
-<span class="sourceLineNo">174</span>    for (CachedItem block : blocks) {<a name="line.174"></a>
-<span class="sourceLineNo">175</span>      assertTrue(cache.getBlock(block.cacheKey, true, false, true) == null);<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>    // Add blocks<a name="line.178"></a>
-<span class="sourceLineNo">179</span>    for (CachedItem block : blocks) {<a name="line.179"></a>
-<span class="sourceLineNo">180</span>      cache.cacheBlock(block.cacheKey, block);<a name="line.180"></a>
-<span class="sourceLineNo">181</span>      expectedCacheSize += block.cacheBlockHeapSize();<a name="line.181"></a>
-<span class="sourceLineNo">182</span>    }<a name="line.182"></a>
-<span class="sourceLineNo">183</span><a name="line.183"></a>
-<span class="sourceLineNo">184</span>    // Verify correctly calculated cache heap size<a name="line.184"></a>
-<span class="sourceLineNo">185</span>    assertEquals(expectedCacheSize, cache.heapSize());<a name="line.185"></a>
-<span class="sourceLineNo">186</span><a name="line.186"></a>
-<span class="sourceLineNo">187</span>    // Check if all blocks are properly cached and retrieved<a name="line.187"></a>
-<span class="sourceLineNo">188</span>    for (CachedItem block : blocks) {<a name="line.188"></a>
-<span class="sourceLineNo">189</span>      HeapSize buf = cache.getBlock(block.cacheKey, true, false, true);<a name="line.189"></a>
-<span class="sourceLineNo">190</span>      assertTrue(buf != null);<a name="line.190"></a>
-<span class="sourceLineNo">191</span>      assertEquals(buf.heapSize(), block.heapSize());<a name="line.191"></a>
-<span class="sourceLineNo">192</span>    }<a name="line.192"></a>
-<span class="sourceLineNo">193</span><a name="line.193"></a>
-<span class="sourceLineNo">194</span>    // Re-add same blocks and ensure nothing has changed<a name="line.194"></a>
-<span class="sourceLineNo">195</span>    long expectedBlockCount = cache.getBlockCount();<a name="line.195"></a>
-<span class="sourceLineNo">196</span>    for (CachedItem block : blocks) {<a name="line.196"></a>
-<span class="sourceLineNo">197</span>      cache.cacheBlock(block.cacheKey, block);<a name="line.197"></a>
-<span class="sourceLineNo">198</span>    }<a name="line.198"></a>
-<span class="sourceLineNo">199</span>    assertEquals(<a name="line.199"></a>
-<span class="sourceLineNo">200</span>            "Cache should ignore cache requests for blocks already in cache",<a name="line.200"></a>
-<span class="sourceLineNo">201</span>            expectedBlockCount, cache.getBlockCount());<a name="line.201"></a>
-<span class="sourceLineNo">202</span><a name="line.202"></a>
-<span class="sourceLineNo">203</span>    // Verify correctly calculated cache heap size<a name="line.203"></a>
-<span class="sourceLineNo">204</span>    assertEquals(expectedCacheSize, cache.heapSize());<a name="line.204"></a>
-<span class="sourceLineNo">205</span><a name="line.205"></a>
-<span class="sourceLineNo">206</span>    // Check if all blocks are properly cached and retrieved<a name="line.206"></a>
-<span class="sourceLineNo">207</span>    for (CachedItem block : blocks) {<a name="line.207"></a>
-<span class="sourceLineNo">208</span>      HeapSize buf = cache.getBlock(block.cacheKey, true, false, true);<a name="line.208"></a>
-<span class="sourceLineNo">209</span>      assertTrue(buf != null);<a name="line.209"></a>
-<span class="sourceLineNo">210</span>      assertEquals(buf.heapSize(), block.heapSize());<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>    // Expect no evictions<a name="line.213"></a>
-<span class="sourceLineNo">214</span>    assertEquals(0, cache.getStats().getEvictionCount());<a name="line.214"></a>
-<span class="sourceLineNo">215</span>    Thread t = new LruBlockCache.StatisticsThread(cache);<a name="line.215"></a>
-<span class="sourceLineNo">216</span>    t.start();<a name="line.216"></a>
-<span class="sourceLineNo">217</span>    t.join();<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>  @Test<a name="line.220"></a>
-<span class="sourceLineNo">221</span>  public void testCacheEvictionSimple() throws Exception {<a name="line.221"></a>
-<span class="sourceLineNo">222</span><a name="line.222"></a>
-<span class="sourceLineNo">223</span>    long maxSize = 100000;<a name="line.223"></a>
-<span class="sourceLineNo">224</span>    long blockSize = calculateBlockSizeDefault(maxSize, 10);<a name="line.224"></a>
-<span class="sourceLineNo">225</span><a name="line.225"></a>
-<span class="sourceLineNo">226</span>    LruBlockCache cache = new LruBlockCache(maxSize,blockSize,false);<a name="line.226"></a>
-<span class="sourceLineNo">227</span><a name="line.227"></a>
-<span class="sourceLineNo">228</span>    CachedItem [] blocks = generateFixedBlocks(10, blockSize, "block");<a name="line.228"></a>
-<span class="sourceLineNo">229</span><a name="line.229"></a>
-<span class="sourceLineNo">230</span>    long expectedCacheSize = cache.heapSize();<a name="line.230"></a>
-<span class="sourceLineNo">231</span><a name="line.231"></a>
-<span class="sourceLineNo">232</span>    // Add all the blocks<a name="line.232"></a>
-<span class="sourceLineNo">233</span>    for (CachedItem block : blocks) {<a name="line.233"></a>
-<span class="sourceLineNo">234</span>      cache.cacheBlock(block.cacheKey, block);<a name="line.234"></a>
-<span class="sourceLineNo">235</span>      expectedCacheSize += block.cacheBlockHeapSize();<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>    // A single eviction run should have occurred<a name="line.238"></a>
-<span class="sourceLineNo">239</span>    assertEquals(1, cache.getStats().getEvictionCount());<a name="line.239"></a>
-<span class="sourceLineNo">240</span><a name="line.240"></a>
-<span class="sourceLineNo">241</span>    // Our expected size overruns acceptable limit<a name="line.241"></a>
-<span class="sourceLineNo">242</span>    assertTrue(expectedCacheSize &gt;<a name="line.242"></a>
-<span class="sourceLineNo">243</span>      (maxSize * LruBlockCache.DEFAULT_ACCEPTABLE_FACTOR));<a name="line.243"></a>
-<span class="sourceLineNo">244</span><a name="line.244"></a>
-<span class="sourceLineNo">245</span>    // But the cache did not grow beyond max<a name="line.245"></a>
-<span class="sourceLineNo">246</span>    assertTrue(cache.heapSize() &lt; maxSize);<a name="line.246"></a>
-<span class="sourceLineNo">247</span><a name="line.247"></a>
-<span class="sourceLineNo">248</span>    // And is still below the acceptable limit<a name="line.248"></a>
-<span class="sourceLineNo">249</span>    assertTrue(cache.heapSize() &lt;<a name="line.249"></a>
-<span class="sourceLineNo">250</span>        (maxSize * LruBlockCache.DEFAULT_ACCEPTABLE_FACTOR));<a name="line.250"></a>
-<span class="sourceLineNo">251</span><a name="line.251"></a>
-<span class="sourceLineNo">252</span>    // All blocks except block 0  should be in the cache<a name="line.252"></a>
-<span class="sourceLineNo">253</span>    assertTrue(cache.getBlock(blocks[0].cacheKey, true, false, true) == null);<a name="line.253"></a>
-<span class="sourceLineNo">254</span>    for(int i=1;i&lt;blocks.length;i++) {<a name="line.254"></a>
-<span class="sourceLineNo">255</span>      assertEquals(cache.getBlock(blocks[i].cacheKey, true, false, true),<a name="line.255"></a>
-<span class="sourceLineNo">256</span>          blocks[i]);<a name="line.256"></a>
-<span class="sourceLineNo">257</span>    }<a name="line.257"></a>
-<span class="sourceLineNo">258</span>  }<a name="line.258"></a>
-<span class="sourceLineNo">259</span><a name="line.259"></a>
-<span class="sourceLineNo">260</span>  @Test<a name="line.260"></a>
-<span class="sourceLineNo">261</span>  public void testCacheEvictionTwoPriorities() throws Exception {<a name="line.261"></a>
-<span class="sourceLineNo">262</span><a name="line.262"></a>
-<span class="sourceLineNo">263</span>    long maxSize = 100000;<a name="line.263"></a>
-<span class="sourceLineNo">264</span>    long blockSize = calculateBlockSizeDefault(maxSize, 10);<a name="line.264"></a>
-<span class="sourceLineNo">265</span><a name="line.265"></a>
-<span class="sourceLineNo">266</span>    LruBlockCache cache = new LruBlockCache(maxSize,blockSize,false);<a name="line.266"></a>
-<span class="sourceLineNo">267</span><a name="line.267"></a>
-<span class="sourceLineNo">268</span>    CachedItem [] singleBlocks = generateFixedBlocks(5, 10000, "single");<a name="line.268"></a>
-<span class="sourceLineNo">269</span>    CachedItem [] multiBlocks = generateFixedBlocks(5, 10000, "multi");<a name="line.269"></a>
-<span class="sourceLineNo">270</span><a name="line.270"></a>
-<span class="sourceLineNo">271</span>    long expectedCacheSize = cache.heapSize();<a name="line.271"></a>
-<span class="sourceLineNo">272</span><a name="line.272"></a>
-<span class="sourceLineNo">273</span>    // Add and get the multi blocks<a name="line.273"></a>
-<span class="sourceLineNo">274</span>    for (CachedItem block : multiBlocks) {<a name="line.274"></a>
-<span class="sourceLineNo">275</span>      cache.cacheBlock(block.cacheKey, block);<a name="line.275"></a>
-<span class="sourceLineNo">276</span>      expectedCacheSize += block.cacheBlockHeapSize();<a name="line.276"></a>
-<span class="sourceLineNo">277</span>      assertEquals(cache.getBlock(block.cacheKey, true, false, true), block);<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>    // Add the single blocks (no get)<a name="line.280"></a>
-<span class="sourceLineNo">281</span>    for (CachedItem block : singleBlocks) {<a name="line.281"></a>
-<span class="sourceLineNo">282</span>      cache.cacheBlock(block.cacheKey, block);<a name="line.282"></a>
-<span class="sourceLineNo">283</span>      expectedCacheSize += block.heapSize();<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>    // A single eviction run should have occurred<a name="line.286"></a>
-<span class="sourceLineNo">287</span>    assertEquals(1, cache.getStats().getEvictionCount());<a name="line.287"></a>
-<span class="sourceLineNo">288</span><a name="line.288"></a>
-<span class="sourceLineNo">289</span>    // We expect two entries evicted<a name="line.289"></a>
-<span class="sourceLineNo">290</span>    assertEquals(2, cache.getStats().getEvictedCount());<a name="line.290"></a>
-<span class="sourceLineNo">291</span><a name="line.291"></a>
-<span class="sourceLineNo">292</span>    // Our expected size overruns acceptable limit<a name="line.292"></a>
-<span class="sourceLineNo">293</span>    assertTrue(expectedCacheSize &gt;<a name="line.293"></a>
-<span class="sourceLineNo">294</span>      (maxSize * LruBlockCache.DEFAULT_ACCEPTABLE_FACTOR));<a name="line.294"></a>
-<span class="sourceLineNo">295</span><a name="line.295"></a>
-<span class="sourceLineNo">296</span>    // But the cache did not grow beyond max<a name="line.296"></a>
-<span class="sourceLineNo">297</span>    assertTrue(cache.heapSize() &lt;= maxSize);<a name="line.297"></a>
-<span class="sourceLineNo">298</span><a name="line.298"></a>
-<span class="sourceLineNo">299</span>    // And is now below the acceptable limit<a name="line.299"></a>
-<span class="sourceLineNo">300</span>    assertTrue(cache.heapSize() &lt;=<a name="line.300"></a>
-<span class="sourceLineNo">301</span>        (maxSize * LruBlockCache.DEFAULT_ACCEPTABLE_FACTOR));<a name="line.301"></a>
-<span class="sourceLineNo">302</span><a name="line.302"></a>
-<span class="sourceLineNo">303</span>    // We expect fairness across the two priorities.<a name="line.303"></a>
-<span class="sourceLineNo">304</span>    // This test makes multi go barely over its limit, in-memory<a name="line.304"></a>
-<span class="sourceLineNo">305</span>    // empty, and the rest in single.  Two single evictions and<a name="line.305"></a>
-<span class="sourceLineNo">306</span>    // one multi eviction expected.<a name="line.306"></a>
-<span class="sourceLineNo">307</span>    assertTrue(cache.getBlock(singleBlocks[0].cacheKey, true, false, true) == null);<a name="line.307"></a>
-<span class="sourceLineNo">308</span>    assertTrue(cache.getBlock(multiBlocks[0].cacheKey, true, false, true) == null);<a name="line.308"></a>
-<span class="sourceLineNo">309</span><a name="line.309"></a>
-<span class="sourceLineNo">310</span>    // And all others to be cached<a name="line.310"></a>
-<span class="sourceLineNo">311</span>    for(int i=1;i&lt;4;i++) {<a name="line.311"></a>
-<span class="sourceLineNo">312</span>      assertEquals(cache.getBlock(singleBlocks[i].cacheKey, true, false, true),<a name="line.312"></a>
-<span class="sourceLineNo">313</span>          singleBlocks[i]);<a name="line.313"></a>
-<span class="sourceLineNo">314</span>      assertEquals(cache.getBlock(multiBlocks[i].cacheKey, true, false, true),<a name="line.314"></a>
-<span class="sourceLineNo">315</span>          multiBlocks[i]);<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><a name="line.318"></a>
-<span class="sourceLineNo">319</span>  @Test<a name="line.319"></a>
-<span class="sourceLineNo">320</span>  public void testCacheEvictionThreePriorities() throws Exception {<a name="line.320"></a>
-<span class="sourceLineNo">321</span><a name="line.321"></a>
-<span class="sourceLineNo">322</span>    long maxSize = 100000;<a name="line.322"></a>
-<span class="sourceLineNo">323</span>    long blockSize = calculateBlockSize(maxSize, 10);<a name="line.323"></a>
-<span class="sourceLineNo">324</span><a name="line.324"></a>
-<span class="sourceLineNo">325</span>    LruBlockCache cache = new LruBlockCache(maxSize, blockSize, false,<a name="line.325"></a>
-<span class="sourceLineNo">326</span>        (int)Math.ceil(1.2*maxSize/blockSize),<a name="line.326"></a>
-<span class="sourceLineNo">327</span>        LruBlockCache.DEFAULT_LOAD_FACTOR,<a name="line.327"></a>
-<span class="sourceLineNo">328</span>        LruBlockCache.DEFAULT_CONCURRENCY_LEVEL,<a name="line.328"></a>
-<span class="sourceLineNo">329</span>        0.98f, // min<a name="line.329"></a>
-<span class="sourceLineNo">330</span>        0.99f, // acceptable<a name="line.330"></a>
-<span class="sourceLineNo">331</span>        0.33f, // single<a name="line.331"></a>
-<span class="sourceLineNo">332</span>        0.33f, // multi<a name="line.332"></a>
-<span class="sourceLineNo">333</span>        0.34f, // memory<a name="line.333"></a>
-<span class="sourceLineNo">334</span>        1.2f,  // limit<a name="line.334"></a>
-<span class="sourceLineNo">335</span>        false,<a name="line.335"></a>
-<span class="sourceLineNo">336</span>        16 * 1024 * 1024);<a name="line.336"></a>
-<span class="sourceLineNo">337</span><a name="line.337"></a>
-<span class="sourceLineNo">338</span>    CachedItem [] singleBlocks = generateFixedBlocks(5, blockSize, "single");<a name="line.338"></a>
-<span class="sourceLineNo">339</span>    CachedItem [] multiBlocks = generateFixedBlocks(5, blockSize, "multi");<a name="line.339"></a>
-<span class="sourceLineNo">340</span>    CachedItem [] memoryBlocks = generateFixedBlocks(5, blockSize, "memory");<a name="line.340"></a>
-<span class="sourceLineNo">341</span><a name="line.341"></a>
-<span class="sourceLineNo">342</span>    long expectedCacheSize = cache.heapSize();<a name="line.342"></a>
-<span class="sourceLineNo">343</span><a name="line.343"></a>
-<span class="sourceLineNo">344</span>    // Add 3 blocks from each priority<a name="line.344"></a>
-<span class="sourceLineNo">345</span>    for(int i=0;i&lt;3;i++) {<a name="line.345"></a>
-<span class="sourceLineNo">346</span><a name="line.346"></a>
-<span class="sourceLineNo">347</span>      // Just add single blocks<a name="line.347"></a>
-<span class="sourceLineNo">348</span>      cache.cacheBlock(singleBlocks[i].cacheKey, singleBlocks[i]);<a name="line.348"></a>
-<span class="sourceLineNo">349</span>      expectedCacheSize += singleBlocks[i].cacheBlockHeapSize();<a name="line.349"></a>
-<span class="sourceLineNo">350</span><a name="line.350"></a>
-<span class="sourceLineNo">351</span>      // Add and get multi blocks<a name="line.351"></a>
-<span class="sourceLineNo">352</span>      cache.cacheBlock(multiBlocks[i].cacheKey, multiBlocks[i]);<a name="line.352"></a>
-<span class="sourceLineNo">353</span>      expectedCacheSize += multiBlocks[i].cacheBlockHeapSize();<a name="line.353"></a>
-<span class="sourceLineNo">354</span>      cache.getBlock(multiBlocks[i].cacheKey, true, false, true);<a name="line.354"></a>
-<span class="sourceLineNo">355</span><a name="line.355"></a>
-<span class="sourceLineNo">356</span>      // Add memory blocks as such<a name="line.356"></a>
-<span class="sourceLineNo">357</span>      cache.cacheBlock(memoryBlocks[i].cacheKey, memoryBlocks[i], true);<a name="line.357"></a>
-<span class="sourceLineNo">358</span>      expectedCacheSize += memoryBlocks[i].cacheBlockHeapSize();<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>    // Do not expect any evictions yet<a name="line.362"></a>
-<span class="sourceLineNo">363</span>    assertEquals(0, cache.getStats().getEvictionCount());<a name="line.363"></a>
-<span class="sourceLineNo">364</span><a name="line.364"></a>
-<span class="sourceLineNo">365</span>    // Verify cache size<a name="line.365"></a>
-<span class="sourceLineNo">366</span>    assertEquals(expectedCacheSize, cache.heapSize());<a name="line.366"></a>
-<span class="sourceLineNo">367</span><a name="line.367"></a>
-<span class="sourceLineNo">368</span>    // Insert a single block, oldest single should be evicted<a name="line.368"></a>
-<span class="sourceLineNo">369</span>    cache.cacheBlock(singleBlocks[3].cacheKey, singleBlocks[3]);<a name="line.369"></a>
-<span class="sourceLineNo">370</span><a name="line.370"></a>
-<span class="sourceLineNo">371</span>    // Single eviction, one thing evicted<a name="line.371"></a>
-<span class="sourceLineNo">372</span>    assertEquals(1, cache.getStats().getEvictionCount());<a name="line.372"></a>
-<span class="sourceLineNo">373</span>    assertEquals(1, cache.getStats().getEvictedCount());<a name="line.373"></a>
-<span class="sourceLineNo">374</span><a name="line.374"></a>
-<span class="sourceLineNo">375</span>    // Verify oldest single block is the one evicted<a name="line.375"></a>
-<span class="sourceLineNo">376</span>    assertEquals(null, cache.getBlock(singleBlocks[0].cacheKey, true, false, true));<a name="line.376"></a>
-<span class="sourceLineNo">377</span><a name="line.377"></a>
-<span class="sourceLineNo">378</span>    // Change the oldest remaining single block to a multi<a name="line.378"></a>
-<span class="sourceLineNo">379</span>    cache.getBlock(singleBlocks[1].cacheKey, true, false, true);<a name="line.379"></a>
-<span class="sourceLineNo">380</span><a name="line.380"></a>
-<span class="sourceLineNo">381</span>    // Insert another single block<a name="line.381"></a>
-<span class="sourceLineNo">382</span>    cache.cacheBlock(singleBlocks[4].cacheKey, singleBlocks[4]);<a name="line.382"></a>
-<span class="sourceLineNo">383</span><a name="line.383"></a>
-<span class="sourceLineNo">384</span>    // Two evictions, two evicted.<a name="line.384"></a>
-<span class="sourceLineNo">385</span>    assertEquals(2, cache.getStats().getEvictionCount());<a name="line.385"></a>
-<span class="sourceLineNo">386</span>    assertEquals(2, cache.getStats().getEvictedCount());<a name="line.386"></a>
-<span class="sourceLineNo">387</span><a name="line.387"></a>
-<span class="sourceLineNo">388</span>    // Oldest multi block should be evicted now<a name="line.388"></a>
-<span class="sourceLineNo">389</span>    assertEquals(null, cache.getBlock(multiBlocks[0].cacheKey, true, false, true));<a name="line.389"></a>
-<span class="sourceLineNo">390</span><a name="line.390"></a>
-<span class="sourceLineNo">391</span>    // Insert another memory block<a name="line.391"></a>
-<span class="sourceLineNo">392</span>    cache.cacheBlock(memoryBlocks[3].cacheKey, memoryBlocks[3], true);<a name="line.392"></a>
-<span class="sourceLineNo">393</span><a name="line.393"></a>
-<span class="sourceLineNo">394</span>    // Three evictions, three evicted.<a name="line.394"></a>
-<span class="sourceLineNo">395</span>    assertEquals(3, cache.getStats().getEvictionCount());<a name="line.395"></a>
-<span class="sourceLineNo">396</span>    assertEquals(3, cache.getStats().getEvictedCount());<a name="line.396"></a>
-<span class="sourceLineNo">397</span><a name="line.397"></a>
-<span class="sourceLineNo">398</span>    // Oldest memory block should be evicted now<a name="line.398"></a>
-<span class="sourceLineNo">399</span>    assertEquals(null, cache.getBlock(memoryBlocks[0].cacheKey, true, false, true));<a name="line.399"></a>
-<span class="sourceLineNo">400</span><a name="line.400"></a>
-<span class="sourceLineNo">401</span>    // Add a block that is twice as big (should force two evictions)<a name="line.401"></a>
-<span class="sourceLineNo">402</span>    CachedItem [] bigBlocks = generateFixedBlocks(3, blockSize*3, "big");<a name="line.402"></a>
-<span class="sourceLineNo">403</span>    cache.cacheBlock(bigBlocks[0].cacheKey, bigBlocks[0]);<a name="line.403"></a>
-<span class="sourceLineNo">404</span><a name="line.404"></a>
-<span class="sourceLineNo">405</span>    // Four evictions, six evicted (inserted block 3X size, expect +3 evicted)<a name="line.405"></a>
-<span class="sourceLineNo">406</span>    assertEquals(4, cache.getStats().getEvictionCount());<a name="line.406"></a>
-<span class="sourceLineNo">407</span>    assertEquals(6, cache.getStats().getEvictedCount());<a name="line.407"></a>
-<span class="sourceLineNo">408</span><a name="line.408"></a>
-<span class="sourceLineNo">409</span>    // Expect three remaining singles to be evicted<a name="line.409"></a>
-<span class="sourceLineNo">410</span>    assertEquals(null, cache.getBlock(singleBlocks[2].cacheKey, true, false, true));<a name="line.410"></a>
-<span class="sourceLineNo">411</span>    assertEquals(null, cache.getBlock(singleBlocks[3].cacheKey, true, false, true));<a name="line.411"></a>
-<span class="sourceLineNo">412</span>    assertEquals(null, cache.getBlock(singleBlocks[4].cacheKey, true, false, true));<a name="line.412"></a>
-<span class="sourceLineNo">413</span><a name="line.413"></a>
-<span class="sourceLineNo">414</span>    // Make the big block a multi block<a name="line.414"></a>
-<span class="sourceLineNo">415</span>    cache.getBlock(bigBlocks[0].cacheKey, true, false, true);<a name="line.415"></a>
-<span class="sourceLineNo">416</span><a name="line.416"></a>
-<span class="sourceLineNo">417</span>    // Cache another single big block<a name="line.417"></a>
-<span class="sourceLineNo">418</span>    cache.cacheBlock(bigBlocks[1].cacheKey, bigBlocks[1]);<a name="line.418"></a>
-<span class="sourceLineNo">419</span><a name="line.419"></a>
-<span class="sourceLineNo">420</span>    // Five evictions, nine evicted (3 new)<a name="line.420"></a>
-<span class="sourceLineNo">421</span>    assertEquals(5, cache.getStats().getEvictionCount());<a name="line.421"></a>
-<span class="sourceLineNo">422</span>    assertEquals(9, cache.getStats().getEvictedCount());<a name="line.422"></a>
-<span class="sourceLineNo">423</span><a name="line.423"></a>
-<span class="sourceLineNo">424</span>    // Expect three remaining multis to be evicted<a name="line.424"></a>
-<span class="sourceLineNo">425</span>    assertEquals(null, cache.getBlock(singleBlocks[1].cacheKey, true, false, true));<a name="line.425"></a>
-<span class="sourceLineNo">426</span>    assertEquals(null, cache.getBlock(multiBlocks[1].cacheKey, true, false, true));<a name="line.426"></a>
-<span class="sourceLineNo">427</span>    assertEquals(null, cache.getBlock(multiBlocks[2].cacheKey, true, false, true));<a name="line.427"></a>
-<span class="sourceLineNo">428</span><a name="line.428"></a>
-<span class="sourceLineNo">429</span>    // Cache a big memory block<a name="line.429"></a>
-<span class="sourceLineNo">430</span>    cache.cacheBlock(bigBlocks[2].cacheKey, bigBlocks[2], true);<a name="line.430"></a>
-<span class="sourceLineNo">431</span><a name="line.431"></a>
-<span class="sourceLineNo">432</span>    // Six evictions, twelve evicted (3 new)<a name="line.432"></a>
-<span class="sourceLineNo">433</span>    assertEquals(6, cache.getStats().getEvictionCount());<a name="line.433"></a>
-<span class="sourceLineNo">434</span>    assertEquals(12, cache.getStats().getEvictedCount());<a name="line.434"></a>
-<span class="sourceLineNo">435</span><a name="line.435"></a>
-<span class="sourceLineNo">436</span>    // Expect three remaining in-memory to be evicted<a name="line.436"></a>
-<span class="sourceLineNo">437</span>    assertEquals(null, cache.getBlock(memoryBlocks[1].cacheKey, true, false, true));<a name="line.437"></a>
-<span class="sourceLineNo">438</span>    assertEquals(null, cache.getBlock(memoryBlocks[2].cacheKey, true, false, true));<a name="line.438"></a>
-<span class="sourceLineNo">439</span>    assertEquals(null, cache.getBlock(memoryBlocks[3].cacheKey, true, false, true));<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>  @Test<a name="line.442"></a>
-<span class="sourceLineNo">443</span>  public void testCacheEvictionInMemoryForceMode() throws Exception {<a name="line.443"></a>
-<span class="sourceLineNo">444</span>    long maxSize = 100000;<a name="line.444"></a>
-<span class="sourceLineNo">445</span>    long blockSize = calculateBlockSize(maxSize, 10);<a name="line.445"></a>
-<span class="sourceLineNo">446</span><a name="line.446"></a>
-<span class="sourceLineNo">447</span>    LruBlockCache cache = new LruBlockCache(maxSize, blockSize, false,<a name="line.447"></a>
-<span class="sourceLineNo">448</span>        (int)Math.ceil(1.2*maxSize/blockSize),<a name="line.448"></a>
-<span class="sourceLineNo">449</span>        LruBlockCache.DEFAULT_LOAD_FACTOR,<a name="line.449"></a>
-<span class="sourceLineNo">450</span>        LruBlockCache.DEFAULT_CONCURRENCY_LEVEL,<a name="line.450"></a>
-<span class="sourceLineNo">451</span>        0.98f, // min<a name="line.451"></a>
-<span class="sourceLineNo">452</span>        0.99f, // acceptable<a name="line.452"></a>
-<span class="sourceLineNo">453</span>        0.2f, // single<a name="line.453"></a>
-<span class="sourceLineNo">454</span>        0.3f, // multi<a name="line.454"></a>
-<span class="sourceLineNo">455</span>        0.5f, // memory<a name="line.455"></a>
-<span class="sourceLineNo">456</span>        1.2f, // limit<a name="line.456"></a>
-<span class="sourceLineNo">457</span>        true,<a name="line.457"></a>
-<span class="sourceLineNo">458</span>        16 * 1024 * 1024);<a name="line.458"></a>
-<span class="sourceLineNo">459</span><a name="line.459"></a>
-<span class="sourceLineNo">460</span>    CachedItem [] singleBlocks = generateFixedBlocks(10, blockSize, "single");<a name="line.460"></a>
-<span class="sourceLineNo">461</span>    CachedItem [] multiBlocks = generateFixedBlocks(10, blockSize, "multi");<a name="line.461"></a>
-<span class="sourceLineNo">462</span>    CachedItem [] memoryBlocks = generateFixedBlocks(10, blockSize, "memory");<a name="line.462"></a>
-<span class="sourceLineNo">463</span><a name="line.463"></a>
-<span class="sourceLineNo">464</span>    long expectedCacheSize = cache.heapSize();<a name="line.464"></a>
-<span class="sourceLineNo">465</span><a name="line.465"></a>
-<span class="sourceLineNo">466</span>    // 0. Add 5 single blocks and 4 multi blocks to make cache full, si:mu:me = 5:4:0<a name="line.466"></a>
-<span class="sourceLineNo">467</span>    for(int i = 0; i &lt; 4; i++) {<a name="line.467"></a>
-<span class="sourceLineNo">468</span>      // Just add single blocks<a name="line.468"></a>
-<span class="sourceLineNo">469</span>      cache.cacheBlock(singleBlocks[i].cacheKey, singleBlocks[i]);<a name="line.469"></a>
-<span class="sourceLineNo">470</span>      expectedCacheSize += singleBlocks[i].cacheBlockHeapSize();<a name="line.470"></a>
-<span class="sourceLineNo">471</span>      // Add and get multi blocks<a name="line.471"></a>
-<span class="sourceLineNo">472</span>      cache.cacheBlock(multiBlocks[i].cacheKey, multiBlocks[i]);<a name="line.472"></a>
-<span class="sourceLineNo">473</span>      expectedCacheSize += multiBlocks[i].cacheBlockHeapSize();<a name="line.473"></a>
-<span class="sourceLineNo">474</span>      cache.getBlock(multiBlocks[i].cacheKey, true, false, true);<a name="line.474"></a>
-<span class="sourceLineNo">475</span>    }<a name="line.475"></a>
-<span class="sourceLineNo">476</span>    // 5th single block<a name="line.476"></a>
-<span class="sourceLineNo">477</span>    cache.cacheBlock(singleBlocks[4].cacheKey, singleBlocks[4]);<a name="line.477"></a>
-<span class="sourceLineNo">478</span>    expectedCacheSize += singleBlocks[4].cacheBlockHeapSize();<a name="line.478"></a>
-<span class="sourceLineNo">479</span>    // Do not expect any evictions yet<a name="line.479"></a>
-<span class="sourceLineNo">480</span>    assertEquals(0, cache.getStats().getEvictionCount());<a name="line.480"></a>
-<span class="sourceLineNo">481</span>    // Verify cache size<a name="line.481"></a>
-<span class="sourceLineNo">482</span>    assertEquals(expectedCacheSize, cache.heapSize());<a name="line.482"></a>
-<span class="sourceLineNo">483</span><a name="line.483"></a>
-<span class="sourceLineNo">484</span>    // 1. Insert a memory block, oldest single should be evicted, si:mu:me = 4:4:1<a name="line.484"></a>
-<span class="sourceLineNo">485</span>    cache.cacheBlock(memoryBlocks[0].cacheKey, memoryBlocks[0], true);<a name="line.485"></a>
-<span class="sourceLineNo">486</span>    // Single eviction, one block evicted<a name="line.486"></a>
-<span class="sourceLineNo">487</span>    assertEquals(1, cache.getStats().getEvictionCount());<a name="line.487"></a>
-<span class="sourceLineNo">488</span>    assertEquals(1, cache.getStats().getEvictedCount());<a name="line.488"></a>
-<span class="sourceLineNo">489</span>    // Verify oldest single block (index = 0) is the one evicted<a name="line.489"></a>
-<span class="sourceLineNo">490</span>    assertEquals(null, cache.getBlock(singleBlocks[0].cacheKey, true, false, true));<a name="line.490"></a>
-<span class="sourceLineNo">491</span><a name="line.491"></a>
-<span class="sourceLineNo">492</span>    // 2. Insert another memory block, another single evicted, si:mu:me = 3:4:2<a name="line.492"></a>
-<span class="sourceLineNo">493</span>    cache.cacheBlock(memoryBlocks[1].cacheKey, memoryBlocks[1], true);<a name="line.493"></a>
-<span class="sourceLineNo">494</span>    // Two evictions, two evicted.<a name="line.494"></a>
-<span class="sourceLineNo">495</span>    assertEquals(2, cache.getStats().getEvictionCount());<a name="line.495"></a>
-<span class="sourceLineNo">496</span>    assertEquals(2, cache.getStats().getEvictedCount());<a name="line.496"></a>
-<span class="sourceLineNo">497</span>    // Current oldest single block (index = 1) should be evicted now<a name="line.497"></a>
-<span class="sourceLineNo">498</span>    assertEquals(null, cache.getBlock(singleBlocks[1].cacheKey, true, false, true));<a name="line.498"></a>
-<span class="sourceLineNo">499</span><a name="line.499"></a>
-<span class="sourceLineNo">500</span>    // 3. Insert 4 memory blocks, 2 single and 2 multi evicted, si:mu:me = 1:2:6<a name="line.500"></a>
-<span class="sourceLineNo">501</span>    cache.cacheBlock(memoryBlocks[2].cacheKey, memoryBlocks[2], true);<a name="line.501"></a>
-<span class="sourceLineNo">502</span>    cache.cacheBlock(memoryBlocks[3].cacheKey, memoryBlocks[3], true);<a name="line.502"></a>
-<span class="sourceLineNo">503</span>    cache.cacheBlock(memoryBlocks[4].cacheKey, memoryBlocks[4], true);<a name="line.503"></a>
-<span class="sourceLineNo">504</span>    cache.cacheBlock(memoryBlocks[5].cacheKey, memoryBlocks[5], true);<a name="line.504"></a>
-<span class="sourceLineNo">505</span>    // Three evictions, three evicted.<a name="line.505"></a>
-<span class="sourceLineNo">506</span>    assertEquals(6, cache.getStats().getEvictionCount());<a name="line.506"></a>
-<span class="sourceLineNo">507</span>    assertEquals(6, cache.getStats().getEvictedCount());<a name="line.507"></a>
-<span class="sourceLineNo">508</span>    // two oldest single blocks and two oldest multi blocks evicted<a name="line.508"></a>
-<span class="sourceLineNo">509</span>    assertEquals(null, cache.getBlock(singleBlocks[2].cacheKey, true, false, true));<a name="line.509"></a>
-<span class="sourceLineNo">510</span>    assertEquals(null, cache.getBlock(singleBlocks[3].cacheKey, true, false, true));<a name="line.510"></a>
-<span class="sourceLineNo">511</span>    assertEquals(null, cache.getBlock(multiBlocks[0].cacheKey, true, false, true));<a name="line.511"></a>
-<span class="sourceLineNo">512</span>    assertEquals(null, cache.getBlock(multiBlocks[1].cacheKey, true, false, true));<a name="line.512"></a>
-<span class="sourceLineNo">513</span><a name="line.513"></a>
-<span class="sourceLineNo">514</span>    // 4. Insert 3 memory blocks, the remaining 1 single and 2 multi evicted<a name="line.514"></a>
-<span class="sourceLineNo">515</span>    // si:mu:me = 0:0:9<a name="line.515"></a>
-<span class="sourceLineNo">516</span>    cache.cacheBlock(memoryBlocks[6].cacheKey, memoryBlocks[6], true);<a name="line.516"></a>
-<span class="sourceLineNo">517</span>    cache.cacheBlock(memoryBlocks[7].cacheKey, memoryBlocks[7], true);<a name="line.517"></a>
-<span class="sourceLineNo">518</span>    cache.cacheBlock(memoryBlocks[8].cacheKey, memoryBlocks[8], true);<a name="line.518"></a>
-<span class="sourceLineNo">519</span>    // Three evictions, three evicted.<a name="line.519"></a>
-<span class="sourceLineNo">520</span>    assertEquals(9, cache.getStats().getEvictionCount());<a name="line.520"></a>
-<span class="sourceLineNo">521</span>    assertEquals(9, cache.getStats().getEvictedCount());<a name="line.521"></a>
-<span class="sourceLineNo">522</span>    // one oldest single block and two oldest multi blocks evicted<a name="line.522"></a>
-<span class="sourceLineNo">523</span>    assertEquals(null, cache.getBlock(singleBlocks[4].cacheKey, true, false, true));<a name="line.523"></a>
-<span class="sourceLineNo">524</span>    assertEquals(null, cache.getBlock(multiBlocks[2].cacheKey, true, false, true));<a name="line.524"></a>
-<span class="sourceLineNo">525</span>    assertEquals(null, cache.getBlock(multiBlocks[3].cacheKey, true, false, true));<a name="line.525"></a>
-<span class="sourceLineNo">526</span><a name="line.526"></a>
-<span class="sourceLineNo">527</span>    // 5. Insert one memory block, the oldest memory evicted<a name="line.527"></a>
-<span class="sourceLineNo">528</span>    // si:mu:me = 0:0:9<a name="line.528"></a>
-<span class="sourceLineNo">529</span>    cache.cacheBlock(memoryBlocks[9].cacheKey, memoryBlocks[9], true);<a name="line.529"></a>
-<span class="sourceLineNo">530</span>    // one eviction, one evicted.<a name="line.530"></a>
-<span class="sourceLineNo">531</span>    assertEquals(10, cache.getStats().getEvictionCount());<a name="line.531"></a>
-<span class="sourceLineNo">532</span>    assertEquals(10, cache.getStats().getEvictedCount());<a name="line.532"></a>
-<span class="sourceLineNo">533</span>    // oldest memory block evicted<a name="line.533"></a>
-<span class="sourceLineNo">534</span>    assertEquals(null, cache.getBlock(memoryBlocks[0].cacheKey, true, false, true));<a name="line.534"></a>
-<span class="sourceLineNo">535</span><a name="line.535"></a>
-<span class="sourceLineNo">536</span>    // 6. Insert one new single block, itself evicted immediately since<a name="line.536"></a>
-<span class="sourceLineNo">537</span>    //    all blocks in cache are memory-type which have higher priority<a name="line.537"></a>
-<span class="sourceLineNo">538</span>    // si:mu:me = 0:0:9 (no change)<a name="line.538"></a>
-<span class="sourceLineNo">539</span>    cache.cacheBlock(singleBlocks[9].cacheKey, singleBlocks[9]);<a name="line.539"></a>
-<span class="sourceLineNo">540</span>    // one eviction, one evicted.<a name="line.540"></a>
-<span class="sourceLineNo">541</span>    assertEquals(11, cache.getStats().getEvictionCount());<a name="line.541"></a>
-<span class="sourceLineNo">542</span>    assertEquals(11, cache.getStats().getEvictedCount());<a name="line.542"></a>
-<span class="sourceLineNo">543</span>    // the single block just cached now evicted (can't evict memory)<a name="line.543"></a>
-<span class="sourceLineNo">544</span>    assertEquals(null, cache.getBlock(singleBlocks[9].cacheKey, true, false, true));<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>  // test scan resistance<a name="line.547"></a>
-<span class="sourceLineNo">548</span>  @Test<a name="line.548"></a>
-<span class="sourceLineNo">549</span>  public void testScanResistance() throws Exception {<a name="line.549"></a>
-<span class="sourceLineNo">550</span><a name="line.550"></a>
-<span class="sourceLineNo">551</span>    long maxSize = 100000;<a name="line.551"></a>
-<span class="sourceLineNo">552</span>    long blockSize = calculateBlockSize(maxSize, 10);<a name="line.552"></a>
-<span class="sourceLineNo">553</span><a name="line.553"></a>
-<span class="sourceLineNo">554</span>    LruBlockCache cache = new LruBlockCache(maxSize, blockSize, false,<a name="line.554"></a>
-<span class="sourceLineNo">555</span>        (int)Math.ceil(1.2*maxSize/blockSize),<a name="line.555"></a>
-<span class="sourceLineNo">556</span>        LruBlockCache.DEFAULT_LOAD_FACTOR,<a name="line.556"></a>
-<span class="sourceLineNo">557</span>        LruBlockCache.DEFAULT_CONCURRENCY_LEVEL,<a name="line.557"></a>
-<span class="sourceLineNo">558</span>        0.66f, // min<a name="line.558"></a>
-<span class="sourceLineNo">559</span>        0.99f, // acceptable<a name="line.559"></a>
-<span class="sourceLineNo">560</span>        0.33f, // single<a name="line.560"></a>
-<span class="sourceLineNo">561</span>        0.33f, // multi<a name="line.561"></a>
-<span class="sourceLineNo">562</span>        0.34f, // memory<a name="line.562"></a>
-<span class="sourceLineNo">563</span>        1.2f,  // limit<a name="line.563"></a>
-<span class="sourceLineNo">564</span>        false,<a name="line.564"></a>
-<span class="sourceLineNo">565</span>        16 * 1024 * 1024);<a name="line.565"></a>
-<span class="sourceLineNo">566</span><a name="line.566"></a>
-<span class="sourceLineNo">567</span>    CachedItem [] singleBlocks = generateFixedBlocks(20, blockSize, "single");<a name="line.567"></a>
-<span class="sourceLineNo">568</span>    CachedItem [] multiBlocks = generateFixedBlocks(5, blockSize, "multi");<a name="line.568"></a>
-<span class="sourceLineNo">569</span><a name="line.569"></a>
-<span class="sourceLineNo">570</span>    // Add 5 multi blocks<a name="line.570"></a>
-<span class="sourceLineNo">571</span>    for (CachedItem block : multiBlocks) {<a name="line.571"></a>
-<span class="sourceLineNo">572</span>      cache.cacheBlock(block.cacheKey, block);<a name="line.572"></a>
-<span class="sourceLineNo">573</span>      cache.getBlock(block.cacheKey, true, false, true);<a name="line.573"></a>
-<span class="sourceLineNo">574</span>    }<a name="line.574"></a>
-<span class="sourceLineNo">575</span><a name="line.575"></a>
-<span class="sourceLineNo">576</span>    // Add 5 single blocks<a name="line.576"></a>
-<span class="sourceLineNo">577</span>    for(int i=0;i&lt;5;i++) {<a name="line.577"></a>
-<span class="sourceLineNo">578</span>      cache.cacheBlock(singleBlocks[i].cacheKey, singleBlocks[i]);<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>    // An eviction ran<a name="line.581"></a>
-<span class="sourceLineNo">582</span>    assertEquals(1, cache.getStats().getEvictionCount());<a name="line.582"></a>
-<span class="sourceLineNo">583</span><a name="line.583"></a>
-<span class="sourceLineNo">584</span>    // To drop down to 2/3 capacity, we'll need to evict 4 blocks<a name="line.584"></a>
-<span class="sourceLineNo">585</span>    assertEquals(4, cache.getStats().getEvictedCount());<a name="line.585"></a>
-<span class="sourceLineNo">586</span><a name="line.586"></a>
-<span class="sourceLineNo">587</span>    // Should have been taken off equally from single and multi<a name="line.587"></a>
-<span class="sourceLineNo">588</span>    assertEquals(null, cache.getBlock(singleBlocks[0].cacheKey, true, false, true));<a name="line.588"></a>
-<span class="sourceLineNo">589</span>    assertEquals(null, cache.getBlock(singleBlocks[1].cacheKey, true, false, true));<a name="line.589"></a>
-<span class="sourceLineNo">590</span>    assertEquals(null, cache.getBlock(multiBlocks[0].cacheKey, true, false, true));<a name="line.590"></a>
-<span class="sourceLineNo">591</span>    assertEquals(null, cache.getBlock(multiBlocks[1].cacheKey, true, false, true));<a name="line.591"></a>
-<span class="sourceLineNo">592</span><a name="line.592"></a>
-<span class="sourceLineNo">593</span>    // Let's keep "scanning" by adding single blocks.  From here on we only<a name="line.593"></a>
-<span class="sourceLineNo">594</span>    // expect evictions from the single bucket.<a name="line.594"></a>
-<span class="sourceLineNo">595</span><a name="line.595"></a>
-<span class="sourceLineNo">596</span>    // Every time we reach 10 total blocks (every 4 inserts) we get 4 single<a name="line.596"></a>
-<span class="sourceLineNo">597</span>    // blocks evicted.  Inserting 13 blocks should yield 3 more evictions and<a name="line.597"></a>
-<span class="sourceLineNo">598</span>    // 12 more evicted.<a name="line.598"></a>
-<span class="sourceLineNo">599</span><a name="line.599"></a>
-<span class="sourceLineNo">600</span>    for(int i=5;i&lt;18;i++) {<a name="line.600"></a>
-<span class="sourceLineNo">601</span>      cache.cacheBlock(singleBlocks[i].cacheKey, singleBlocks[i]);<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>    // 4 total evictions, 16 total evicted<a name="line.604"></a>
-<span class="sourceLineNo">605</span>    assertEquals(4, cache.getStats().getEvictionCount());<a name="line.605"></a>
-<span class="sourceLineNo">606</span>    assertEquals(16, cache.getStats().getEvictedCount());<a name="line.606"></a>
-<span class="sourceLineNo">607</span><a name="line.607"></a>
-<span class="sourceLineNo">608</span>    // Should now have 7 total blocks<a name="line.608"></a>
-<span class="sourceLineNo">609</span>    assertEquals(7, cache.getBlockCount());<a name="line.609"></a>
-<span class="sourceLineNo">610</span><a name="line.610"></a>
-<span class="sourceLineNo">611</span>  }<a name="line.611"></a>
-<span class="sourceLineNo">612</span><a name="line.612"></a>
-<span class="sourceLineNo">613</span>  @Test<a name="line.613"></a>
-<span class="sourceLineNo">614</span>  public void testMaxBlockSize() throws Exception {<a name="line.614"></a>
-<span class="sourceLineNo">615</span>    long maxSize = 100000;<a name="line.615"></a>
-<span class="sourceLineNo">616</span>    long blockSize = calculateBlockSize(maxSize, 10);<a name="line.616"></a>
-<span class="sourceLineNo">617</span><a name="line.617"></a>
-<span class="sourceLineNo">618</span>    LruBlockCache cache = new LruBlockCache(maxSize, blockSize, false,<a name="line.618"></a>
-<span class="sourceLineNo">619</span>        (int)Math.ceil(1.2*maxSize/blockSize),<a name="line.619"></a>
-<span class="sourceLineNo">620</span>        LruBlockCache.DEFAULT_LOAD_FACTOR,<a name="line.620"></a>
-<span class="sourceLineNo">621</span>        LruBlockCache.DEFAULT_CONCURRENCY_LEVEL,<a name="line.621"></a>
-<span class="sourceLineNo">622</span>        0.66f, // min<a name="line.622"></a>
-<span class="sourceLineNo">623</span>        0.99f, // acceptable<a name="line.623"></a>
-<span class="sourceLineNo">624</span>        0.33f, // single<a name="line.624"></a>
-<span class="sourceLineNo">625</span>        0.33f, // multi<a name="line.625"></a>
-<span class="sourceLineNo">626</span>        0.34f, // memory<a name="line.626"></a>
-<span class="sourceLineNo">627</span>        1.2f,  // limit<a name="line.627"></a>
-<span class="sourceLineNo">628</span>        false,<a name="line.628"></a>
-<span class="sourceLineNo">629</span>        1024);<a name="line.629"></a>
-<span class="sourceLineNo">630</span>    CachedItem [] tooLong = generateFixedBlocks(10, 1024+5, "long");<a name="line.630"></a>
-<span class="sourceLineNo">631</span>    CachedItem [] small = generateFixedBlocks(15, 600, "small");<a name="line.631"></a>
-<span class="sourceLineNo">632</span><a name="line.632"></a>
+<span class="sourceLineNo">034</span>import org.apache.hadoop.hbase.HConstants;<a name="line.34"></a>
+<span class="sourceLineNo">035</span>import org.apache.hadoop.hbase.Waiter;<a name="line.35"></a>
+<span class="sourceLineNo">036</span>import org.apache.hadoop.hbase.Waiter.ExplainingPredicate;<a name="line.36"></a>
+<span class="sourceLineNo">037</span>import org.apache.hadoop.hbase.io.HeapSize;<a name="line.37"></a>
+<span class="sourceLineNo">038</span>import org.apache.hadoop.hbase.io.hfile.LruBlockCache.EvictionThread;<a name="line.38"></a>
+<span class="sourceLineNo">039</span>import org.apache.hadoop.hbase.testclassification.IOTests;<a name="line.39"></a>
+<span class="sourceLineNo">040</span>import org.apache.hadoop.hbase.testclassification.SmallTests;<a name="line.40"></a>
+<span class="sourceLineNo">041</span>import org.apache.hadoop.hbase.util.ClassSize;<a name="line.41"></a>
+<span class="sourceLineNo">042</span>import org.junit.ClassRule;<a name="line.42"></a>
+<span class="sourceLineNo">043</span>import org.junit.Test;<a name="line.43"></a>
+<span class="sourceLineNo">044</span>import org.junit.experimental.categories.Category;<a name="line.44"></a>
+<span class="sourceLineNo">045</span><a name="line.45"></a>
+<span class="sourceLineNo">046</span>/**<a name="line.46"></a>
+<span class="sourceLineNo">047</span> * Tests the concurrent LruBlockCache.&lt;p&gt;<a name="line.47"></a>
+<span class="sourceLineNo">048</span> *<a name="line.48"></a>
+<span class="sourceLineNo">049</span> * Tests will ensure it grows and shrinks in size properly,<a name="line.49"></a>
+<span class="sourceLineNo">050</span> * evictions run when they're supposed to and do what they should,<a name="line.50"></a>
+<span class="sourceLineNo">051</span> * and that cached blocks are accessible when expected to be.<a name="line.51"></a>
+<span class="sourceLineNo">052</span> */<a name="line.52"></a>
+<span class="sourceLineNo">053</span>@Category({IOTests.class, SmallTests.class})<a name="line.53"></a>
+<span class="sourceLineNo">054</span>public class TestLruBlockCache {<a name="line.54"></a>
+<span class="sourceLineNo">055</span><a name="line.55"></a>
+<span class="sourceLineNo">056</span>  @ClassRule<a name="line.56"></a>
+<span class="sourceLineNo">057</span>  public static final HBaseClassTestRule CLASS_RULE =<a name="line.57"></a>
+<span class="sourceLineNo">058</span>      HBaseClassTestRule.forClass(TestLruBlockCache.class);<a name="line.58"></a>
+<span class="sourceLineNo">059</span><a name="line.59"></a>
+<span class="sourceLineNo">060</span>  @Test<a name="line.60"></a>
+<span class="sourceLineNo">061</span>  public void testCacheEvictionThreadSafe() throws Exception {<a name="line.61"></a>
+<span class="sourceLineNo">062</span>    long maxSize = 100000;<a name="line.62"></a>
+<span class="sourceLineNo">063</span>    int numBlocks = 9;<a name="line.63"></a>
+<span class="sourceLineNo">064</span>    int testRuns = 10;<a name="line.64"></a>
+<span class="sourceLineNo">065</span>    final long blockSize = calculateBlockSizeDefault(maxSize, numBlocks);<a name="line.65"></a>
+<span class="sourceLineNo">066</span>    assertTrue("calculateBlockSize appears broken.", blockSize * numBlocks &lt;= maxSize);<a name="line.66"></a>
+<span class="sourceLineNo">067</span><a name="line.67"></a>
+<span class="sourceLineNo">068</span>    final Configuration conf = HBaseConfiguration.create();<a name="line.68"></a>
+<span class="sourceLineNo">069</span>    final LruBlockCache cache = new LruBlockCache(maxSize, blockSize);<a name="line.69"></a>
+<span class="sourceLineNo">070</span>    EvictionThread evictionThread = cache.getEvictionThread();<a name="line.70"></a>
+<span class="sourceLineNo">071</span>    assertTrue(evictionThread != null);<a name="line.71"></a>
+<span class="sourceLineNo">072</span>    while (!evictionThread.isEnteringRun()) {<a name="line.72"></a>
+<span class="sourceLineNo">073</span>      Thread.sleep(1);<a name="line.73"></a>
+<span class="sourceLineNo">074</span>    }<a name="line.74"></a>
+<span class="sourceLineNo">075</span>    final String hfileName = "hfile";<a name="line.75"></a>
+<span class="sourceLineNo">076</span>    int threads = 10;<a name="line.76"></a>
+<span class="sourceLineNo">077</span>    final int blocksPerThread = 5 * numBlocks;<a name="line.77"></a>
+<span class="sourceLineNo">078</span>    for (int run = 0; run != testRuns; ++run) {<a name="line.78"></a>
+<span class="sourceLineNo">079</span>      final AtomicInteger blockCount = new AtomicInteger(0);<a name="line.79"></a>
+<span class="sourceLineNo">080</span>      ExecutorService service = Executors.newFixedThreadPool(threads);<a name="line.80"></a>
+<span class="sourceLineNo">081</span>      for (int i = 0; i != threads; ++i) {<a name="line.81"></a>
+<span class="sourceLineNo">082</span>        service.execute(new Runnable() {<a name="line.82"></a>
+<span class="sourceLineNo">083</span>          @Override<a name="line.83"></a>
+<span class="sourceLineNo">084</span>          public void run() {<a name="line.84"></a>
+<span class="sourceLineNo">085</span>            for (int blockIndex = 0; blockIndex &lt; blocksPerThread || (!cache.isEvictionInProgress()); ++blockIndex) {<a name="line.85"></a>
+<span class="sourceLineNo">086</span>              CachedItem block = new CachedItem(hfileName, (int) blockSize, blockCount.getAndIncrement());<a name="line.86"></a>
+<span class="sourceLineNo">087</span>              boolean inMemory = Math.random() &gt; 0.5;<a name="line.87"></a>
+<span class="sourceLineNo">088</span>              cache.cacheBlock(block.cacheKey, block, inMemory);<a name="line.88"></a>
+<span class="sourceLineNo">089</span>            }<a name="line.89"></a>
+<span class="sourceLineNo">090</span>            cache.evictBlocksByHfileName(hfileName);<a name="line.90"></a>
+<span class="sourceLineNo">091</span>          }<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>      service.shutdown();<a name="line.94"></a>
+<span class="sourceLineNo">095</span>      // The test may fail here if the evict thread frees the blocks too fast<a name="line.95"></a>
+<span class="sourceLineNo">096</span>      service.awaitTermination(10, TimeUnit.MINUTES);<a name="line.96"></a>
+<span class="sourceLineNo">097</span>      Waiter.waitFor(conf, 10000, 100, new ExplainingPredicate&lt;Exception&gt;() {<a name="line.97"></a>
+<span class="sourceLineNo">098</span>        @Override<a name="line.98"></a>
+<span class="sourceLineNo">099</span>        public boolean evaluate() throws Exception {<a name="line.99"></a>
+<span class="sourceLineNo">100</span>          return cache.getBlockCount() == 0;<a name="line.100"></a>
+<span class="sourceLineNo">101</span>        }<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 String explainFailure() throws Exception {<a name="line.104"></a>
+<span class="sourceLineNo">105</span>          return "Cache block count failed to return to 0";<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>      assertEquals(0, cache.getBlockCount());<a name="line.108"></a>
+<span class="sourceLineNo">109</span>      assertEquals(cache.getOverhead(), cache.getCurrentSize());<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>  @Test<a name="line.112"></a>
+<span class="sourceLineNo">113</span>  public void testBackgroundEvictionThread() throws Exception {<a name="line.113"></a>
+<span class="sourceLineNo">114</span>    long maxSize = 100000;<a name="line.114"></a>
+<span class="sourceLineNo">115</span>    int numBlocks = 9;<a name="line.115"></a>
+<span class="sourceLineNo">116</span>    long blockSize = calculateBlockSizeDefault(maxSize, numBlocks);<a name="line.116"></a>
+<span class="sourceLineNo">117</span>    assertTrue("calculateBlockSize appears broken.", blockSize * numBlocks &lt;= maxSize);<a name="line.117"></a>
+<span class="sourceLineNo">118</span><a name="line.118"></a>
+<span class="sourceLineNo">119</span>    LruBlockCache cache = new LruBlockCache(maxSize,blockSize);<a name="line.119"></a>
+<span class="sourceLineNo">120</span>    EvictionThread evictionThread = cache.getEvictionThread();<a name="line.120"></a>
+<span class="sourceLineNo">121</span>    assertTrue(evictionThread != null);<a name="line.121"></a>
+<span class="sourceLineNo">122</span><a name="line.122"></a>
+<span class="sourceLineNo">123</span>    CachedItem[] blocks = generateFixedBlocks(numBlocks + 1, blockSize, "block");<a name="line.123"></a>
+<span class="sourceLineNo">124</span><a name="line.124"></a>
+<span class="sourceLineNo">125</span>    // Make sure eviction thread has entered run method<a name="line.125"></a>
+<span class="sourceLineNo">126</span>    while (!evictionThread.isEnteringRun()) {<a name="line.126"></a>
+<span class="sourceLineNo">127</span>      Thread.sleep(1);<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>    // Add all the blocks<a name="line.130"></a>
+<span class="sourceLineNo">131</span>    for (CachedItem block : blocks) {<a name="line.131"></a>
+<span class="sourceLineNo">132</span>      cache.cacheBlock(block.cacheKey, block);<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>    // wait until at least one eviction has run<a name="line.135"></a>
+<span class="sourceLineNo">136</span>    int n = 0;<a name="line.136"></a>
+<span class="sourceLineNo">137</span>    while(cache.getStats().getEvictionCount() == 0) {<a name="line.137"></a>
+<span class="sourceLineNo">138</span>      Thread.sleep(200);<a name="line.138"></a>
+<span class="sourceLineNo">139</span>      assertTrue("Eviction never happened.", n++ &lt; 20);<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>    // let cache stabilize<a name="line.142"></a>
+<span class="sourceLineNo">143</span>    // On some systems, the cache will run multiple evictions before it attains<a name="line.143"></a>
+<span class="sourceLineNo">144</span>    // steady-state. For instance, after populating the cache with 10 blocks,<a name="line.144"></a>
+<span class="sourceLineNo">145</span>    // the first eviction evicts a single block and then a second eviction<a name="line.145"></a>
+<span class="sourceLineNo">146</span>    // evicts another. I think this is due to the delta between minSize and<a name="line.146"></a>
+<span class="sourceLineNo">147</span>    // acceptableSize, combined with variance between object overhead on<a name="line.147"></a>
+<span class="sourceLineNo">148</span>    // different environments.<a name="line.148"></a>
+<span class="sourceLineNo">149</span>    n = 0;<a name="line.149"></a>
+<span class="sourceLineNo">150</span>    for (long prevCnt = 0 /* &lt; number of blocks added */,<a name="line.150"></a>
+<span class="sourceLineNo">151</span>              curCnt = cache.getBlockCount();<a name="line.151"></a>
+<span class="sourceLineNo">152</span>        prevCnt != curCnt; prevCnt = curCnt, curCnt = cache.getBlockCount()) {<a name="line.152"></a>
+<span class="sourceLineNo">153</span>      Thread.sleep(200);<a name="line.153"></a>
+<span class="sourceLineNo">154</span>      assertTrue("Cache never stabilized.", n++ &lt; 20);<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>    long evictionCount = cache.getStats().getEvictionCount();<a name="line.157"></a>
+<span class="sourceLineNo">158</span>    assertTrue(evictionCount &gt;= 1);<a name="line.158"></a>
+<span class="sourceLineNo">159</span>    System.out.println("Background Evictions run: " + evictionCount);<a name="line.159"></a>
+<span class="sourceLineNo">160</span>  }<a name="line.160"></a>
+<span class="sourceLineNo">161</span><a name="line.161"></a>
+<span class="sourceLineNo">162</span>  @Test<a name="line.162"></a>
+<span class="sourceLineNo">163</span>  public void testCacheSimple() throws Exception {<a name="line.163"></a>
+<span class="sourceLineNo">164</span><a name="line.164"></a>
+<span class="sourceLineNo">165</span>    long maxSize = 1000000;<a name="line.165"></a>
+<span class="sourceLineNo">166</span>    long blockSize = calculateBlockSizeDefault(maxSize, 101);<a name="line.166"></a>
+<span class="sourceLineNo">167</span><a name="line.167"></a>
+<span class="sourceLineNo">168</span>    LruBlockCache cache = new LruBlockCache(maxSize, blockSize);<a name="line.168"></a>
+<span class="sourceLineNo">169</span><a name="line.169"></a>
+<span class="sourceLineNo">170</span>    CachedItem [] blocks = generateRandomBlocks(100, blockSize);<a name="line.170"></a>
+<span class="sourceLineNo">171</span><a name="line.171"></a>
+<span class="sourceLineNo">172</span>    long expectedCacheSize = cache.heapSize();<a name="line.172"></a>
+<span class="sourceLineNo">173</span><a name="line.173"></a>
+<span class="sourceLineNo">174</span>    // Confirm empty<a name="line.174"></a>
+<span class="sourceLineNo">175</span>    for (CachedItem block : blocks) {<a name="line.175"></a>
+<span class="sourceLineNo">176</span>      assertTrue(cache.getBlock(block.cacheKey, true, false, true) == null);<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>    // Add blocks<a name="line.179"></a>
+<span class="sourceLineNo">180</span>    for (CachedItem block : blocks) {<a name="line.180"></a>
+<span class="sourceLineNo">181</span>      cache.cacheBlock(block.cacheKey, block);<a name="line.181"></a>
+<span class="sourceLineNo">182</span>      expectedCacheSize += block.cacheBlockHeapSize();<a name="line.182"></a>
+<span class="sourceLineNo">183</span>    }<a name="line.183"></a>
+<span class="sourceLineNo">184</span><a name="line.184"></a>
+<span class="sourceLineNo">185</span>    // Verify correctly calculated cache heap size<a name="line.185"></a>
+<span class="sourceLineNo">186</span>    assertEquals(expectedCacheSize, cache.heapSize());<a name="line.186"></a>
+<span class="sourceLineNo">187</span><a name="line.187"></a>
+<span class="sourceLineNo">188</span>    // Check if all blocks are properly cached and retrieved<a name="line.188"></a>
+<span class="sourceLineNo">189</span>    for (CachedItem block : blocks) {<a name="line.189"></a>
+<span class="sourceLineNo">190</span>      HeapSize buf = cache.getBlock(block.cacheKey, true, false, true);<a name="line.190"></a>
+<span class="sourceLineNo">191</span>      assertTrue(buf != null);<a name="line.191"></a>
+<span class="sourceLineNo">192</span>      assertEquals(buf.heapSize(), block.heapSize());<a name="line.192"></a>
+<span class="sourceLineNo">193</span>    }<a name="line.193"></a>
+<span class="sourceLineNo">194</span><a name="line.194"></a>
+<span class="sourceLineNo">195</span>    // Re-add same blocks and ensure nothing has changed<a name="line.195"></a>
+<span class="sourceLineNo">196</span>    long expectedBlockCount = cache.getBlockCount();<a name="line.196"></a>
+<span class="sourceLineNo">197</span>    for (CachedItem block : blocks) {<a name="line.197"></a>
+<span class="sourceLineNo">198</span>      cache.cacheBlock(block.cacheKey, block);<a name="line.198"></a>
+<span class="sourceLineNo">199</span>    }<a name="line.199"></a>
+<span class="sourceLineNo">200</span>    assertEquals(<a name="line.200"></a>
+<span class="sourceLineNo">201</span>            "Cache should ignore cache requests for blocks already in cache",<a name="line.201"></a>
+<span class="sourceLineNo">202</span>            expectedBlockCount, cache.getBlockCount());<a name="line.202"></a>
+<span class="sourceLineNo">203</span><a name="line.203"></a>
+<span class="sourceLineNo">204</span>    // Verify correctly calculated cache heap size<a name="line.204"></a>
+<span class="sourceLineNo">205</span>    assertEquals(expectedCacheSize, cache.heapSize());<a name="line.205"></a>
+<span class="sourceLineNo">206</span><a name="line.206"></a>
+<span class="sourceLineNo">207</span>    // Check if all blocks are properly cached and retrieved<a name="line.207"></a>
+<span class="sourceLineNo">208</span>    for (CachedItem block : blocks) {<a name="line.208"></a>
+<span class="sourceLineNo">209</span>      HeapSize buf = cache.getBlock(block.cacheKey, true, false, true);<a name="line.209"></a>
+<span class="sourceLineNo">210</span>      assertTrue(buf != null);<a name="line.210"></a>
+<span class="sourceLineNo">211</span>      assertEquals(buf.heapSize(), block.heapSize());<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>    // Expect no evictions<a name="line.214"></a>
+<span class="sourceLineNo">215</span>    assertEquals(0, cache.getStats().getEvictionCount());<a name="line.215"></a>
+<span class="sourceLineNo">216</span>    Thread t = new LruBlockCache.StatisticsThread(cache);<a name="line.216"></a>
+<span class="sourceLineNo">217</span>    t.start();<a name="line.217"></a>
+<span class="sourceLineNo">218</span>    t.join();<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>  @Test<a name="line.221"></a>
+<span class="sourceLineNo">222</span>  public void testCacheEvictionSimple() throws Exception {<a name="line.222"></a>
+<span class="sourceLineNo">223</span><a name="line.223"></a>
+<span class="sourceLineNo">224</span>    long maxSize = 100000;<a name="line.224"></a>
+<span class="sourceLineNo">225</span>    long blockSize = calculateBlockSizeDefault(maxSize, 10);<a name="line.225"></a>
+<span class="sourceLineNo">226</span><a name="line.226"></a>
+<span class="sourceLineNo">227</span>    LruBlockCache cache = new LruBlockCache(maxSize,blockSize,false);<a name="line.227"></a>
+<span class="sourceLineNo">228</span><a name="line.228"></a>
+<span class="sourceLineNo">229</span>    CachedItem [] blocks = generateFixedBlocks(10, blockSize, "block");<a name="line.229"></a>
+<span class="sourceLineNo">230</span><a name="line.230"></a>
+<span class="sourceLineNo">231</span>    long expectedCacheSize = cache.heapSize();<a name="line.231"></a>
+<span class="sourceLineNo">232</span><a name="line.232"></a>
+<span class="sourceLineNo">233</span>    // Add all the blocks<a name="line.233"></a>
+<span class="sourceLineNo">234</span>    for (CachedItem block : blocks) {<a name="line.234"></a>
+<span class="sourceLineNo">235</span>      cache.cacheBlock(block.cacheKey, block);<a name="line.235"></a>
+<span class="sourceLineNo">236</span>      expectedCacheSize += block.cacheBlockHeapSize();<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>    // A single eviction run should have occurred<a name="line.239"></a>
+<span class="sourceLineNo">240</span>    assertEquals(1, cache.getStats().getEvictionCount());<a name="line.240"></a>
+<span class="sourceLineNo">241</span><a name="line.241"></a>
+<span class="sourceLineNo">242</span>    // Our expected size overruns acceptable limit<a name="line.242"></a>
+<span class="sourceLineNo">243</span>    assertTrue(expectedCacheSize &gt;<a name="line.243"></a>
+<span class="sourceLineNo">244</span>      (maxSize * LruBlockCache.DEFAULT_ACCEPTABLE_FACTOR));<a name="line.244"></a>
+<span class="sourceLineNo">245</span><a name="line.245"></a>
+<span class="sourceLineNo">246</span>    // But the cache did not grow beyond max<a name="line.246"></a>
+<span class="sourceLineNo">247</span>    assertTrue(cache.heapSize() &lt; maxSize);<a name="line.247"></a>
+<span class="sourceLineNo">248</span><a name="line.248"></a>
+<span class="sourceLineNo">249</span>    // And is still below the acceptable limit<a name="line.249"></a>
+<span class="sourceLineNo">250</span>    assertTrue(cache.heapSize() &lt;<a name="line.250"></a>
+<span class="sourceLineNo">251</span>        (maxSize * LruBlockCache.DEFAULT_ACCEPTABLE_FACTOR));<a name="line.251"></a>
+<span class="sourceLineNo">252</span><a name="line.252"></a>
+<span class="sourceLineNo">253</span>    // All blocks except block 0  should be in the cache<a name="line.253"></a>
+<span class="sourceLineNo">254</span>    assertTrue(cache.getBlock(blocks[0].cacheKey, true, false, true) == null);<a name="line.254"></a>
+<span class="sourceLineNo">255</span>    for(int i=1;i&lt;blocks.length;i++) {<a name="line.255"></a>
+<span class="sourceLineNo">256</span>      assertEquals(cache.getBlock(blocks[i].cacheKey, true, false, true),<a name="line.256"></a>
+<span class="sourceLineNo">257</span>          blocks[i]);<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>  @Test<a name="line.261"></a>
+<span class="sourceLineNo">262</span>  public void testCacheEvictionTwoPriorities() throws Exception {<a name="line.262"></a>
+<span class="sourceLineNo">263</span><a name="line.263"></a>
+<span class="sourceLineNo">264</span>    long maxSize = 100000;<a name="line.264"></a>
+<span class="sourceLineNo">265</span>    long blockSize = calculateBlockSizeDefault(maxSize, 10);<a name="line.265"></a>
+<span class="sourceLineNo">266</span><a name="line.266"></a>
+<span class="sourceLineNo">267</span>    LruBlockCache cache = new LruBlockCache(maxSize,blockSize,false);<a name="line.267"></a>
+<span class="sourceLineNo">268</span><a name="line.268"></a>
+<span class="sourceLineNo">269</span>    CachedItem [] singleBlocks = generateFixedBlocks(5, 10000, "single");<a name="line.269"></a>
+<span class="sourceLineNo">270</span>    CachedItem [] multiBlocks = generateFixedBlocks(5, 10000, "multi");<a name="line.270"></a>
+<span class="sourceLineNo">271</span><a name="line.271"></a>
+<span class="sourceLineNo">272</span>    long expectedCacheSize = cache.heapSize();<a name="line.272"></a>
+<span class="sourceLineNo">273</span><a name="line.273"></a>
+<span class="sourceLineNo">274</span>    // Add and get the multi blocks<a name="line.274"></a>
+<span class="sourceLineNo">275</span>    for (CachedItem block : multiBlocks) {<a name="line.275"></a>
+<span class="sourceLineNo">276</span>      cache.cacheBlock(block.cacheKey, block);<a name="line.276"></a>
+<span class="sourceLineNo">277</span>      expectedCacheSize += block.cacheBlockHeapSize();<a name="line.277"></a>
+<span class="sourceLineNo">278</span>      assertEquals(cache.getBlock(block.cacheKey, true, false, true), block);<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>    // Add the single blocks (no get)<a name="line.281"></a>
+<span class="sourceLineNo">282</span>    for (CachedItem block : singleBlocks) {<a name="line.282"></a>
+<span class="sourceLineNo">283</span>      cache.cacheBlock(block.cacheKey, block);<a name="line.283"></a>
+<span class="sourceLineNo">284</span>      expectedCacheSize += block.heapSize();<a name="line.284"></a>
+<span class="sourceLineNo">285</span>    }<a name="line.285"></a>
+<span class="sourceLineNo">286</span><a name="line.286"></a>
+<span class="sourceLineNo">287</span>    // A single eviction run should have occurred<a name="line.287"></a>
+<span class="sourceLineNo">288</span>    assertEquals(1, cache.getStats().getEvictionCount());<a name="line.288"></a>
+<span class="sourceLineNo">289</span><a name="line.289"></a>
+<span class="sourceLineNo">290</span>    // We expect two entries evicted<a name="line.290"></a>
+<span class="sourceLineNo">291</span>    assertEquals(2, cache.getStats().getEvictedCount());<a name="line.291"></a>
+<span class="sourceLineNo">292</span><a name="line.292"></a>
+<span class="sourceLineNo">293</span>    // Our expected size overruns acceptable limit<a name="line.293"></a>
+<span class="sourceLineNo">294</span>    assertTrue(expectedCacheSize &gt;<a name="line.294"></a>
+<span class="sourceLineNo">295</span>      (maxSize * LruBlockCache.DEFAULT_ACCEPTABLE_FACTOR));<a name="line.295"></a>
+<span class="sourceLineNo">296</span><a name="line.296"></a>
+<span class="sourceLineNo">297</span>    // But the cache did not grow beyond max<a name="line.297"></a>
+<span class="sourceLineNo">298</span>    assertTrue(cache.heapSize() &lt;= maxSize);<a name="line.298"></a>
+<span class="sourceLineNo">299</span><a name="line.299"></a>
+<span class="sourceLineNo">300</span>    // And is now below the acceptable limit<a name="line.300"></a>
+<span class="sourceLineNo">301</span>    assertTrue(cache.heapSize() &lt;=<a name="line.301"></a>
+<span class="sourceLineNo">302</span>        (maxSize * LruBlockCache.DEFAULT_ACCEPTABLE_FACTOR));<a name="line.302"></a>
+<span class="sourceLineNo">303</span><a name="line.303"></a>
+<span class="sourceLineNo">304</span>    // We expect fairness across the two priorities.<a name="line.304"></a>
+<span class="sourceLineNo">305</span>    // This test makes multi go barely over its limit, in-memory<a name="line.305"></a>
+<span class="sourceLineNo">306</span>    // empty, and the rest in single.  Two single evictions and<a name="line.306"></a>
+<span class="sourceLineNo">307</span>    // one multi eviction expected.<a name="line.307"></a>
+<span class="sourceLineNo">308</span>    assertTrue(cache.getBlock(singleBlocks[0].cacheKey, true, false, true) == null);<a name="line.308"></a>
+<span class="sourceLineNo">309</span>    assertTrue(cache.getBlock(multiBlocks[0].cacheKey, true, false, true) == null);<a name="line.309"></a>
+<span class="sourceLineNo">310</span><a name="line.310"></a>
+<span class="sourceLineNo">311</span>    // And all others to be cached<a name="line.311"></a>
+<span class="sourceLineNo">312</span>    for(int i=1;i&lt;4;i++) {<a name="line.312"></a>
+<span class="sourceLineNo">313</span>      assertEquals(cache.getBlock(singleBlocks[i].cacheKey, true, false, true),<a name="line.313"></a>
+<span class="sourceLineNo">314</span>          singleBlocks[i]);<a name="line.314"></a>
+<span class="sourceLineNo">315</span>      assertEquals(cache.getBlock(multiBlocks[i].cacheKey, true, false, true),<a name="line.315"></a>
+<span class="sourceLineNo">316</span>          multiBlocks[i]);<a name="line.316"></a>
+<span class="sourceLineNo">317</span>    }<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>  @Test<a name="line.320"></a>
+<span class="sourceLineNo">321</span>  public void testCacheEvictionThreePriorities() throws Exception {<a name="line.321"></a>
+<span class="sourceLineNo">322</span><a name="line.322"></a>
+<span class="sourceLineNo">323</span>    long maxSize = 100000;<a name="line.323"></a>
+<span class="sourceLineNo">324</span>    long blockSize = calculateBlockSize(maxSize, 10);<a name="line.324"></a>
+<span class="sourceLineNo">325</span><a name="line.325"></a>
+<span class="sourceLineNo">326</span>    LruBlockCache cache = new LruBlockCache(maxSize, blockSize, false,<a name="line.326"></a>
+<span class="sourceLineNo">327</span>        (int)Math.ceil(1.2*maxSize/blockSize),<a name="line.327">

<TRUNCATED>

[48/50] hbase-site git commit: Published site at 26babcf013de696b899d76a3c39434b794440d8d.

Posted by gi...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html b/devapidocs/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html
index eca9c0e..ae13b31 100644
--- a/devapidocs/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html
+++ b/devapidocs/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html
@@ -117,7 +117,7 @@ var activeTableTab = "activeTableTab";
 </dl>
 <hr>
 <br>
-<pre>static class <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.1424">HFileBlock.FSReaderImpl</a>
+<pre>static class <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.1426">HFileBlock.FSReaderImpl</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="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReader.html" title="interface in org.apache.hadoop.hbase.io.hfile">HFileBlock.FSReader</a></pre>
 <div class="block">Reads version 2 HFile blocks from the filesystem.</div>
@@ -376,7 +376,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBloc
 <ul class="blockList">
 <li class="blockList">
 <h4>streamWrapper</h4>
-<pre>private&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/FSDataInputStreamWrapper.html" title="class in org.apache.hadoop.hbase.io">FSDataInputStreamWrapper</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1427">streamWrapper</a></pre>
+<pre>private&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/FSDataInputStreamWrapper.html" title="class in org.apache.hadoop.hbase.io">FSDataInputStreamWrapper</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1429">streamWrapper</a></pre>
 <div class="block">The file system stream of the underlying <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFile.html" title="class in org.apache.hadoop.hbase.io.hfile"><code>HFile</code></a> that
  does or doesn't do checksum validations in the filesystem</div>
 </li>
@@ -387,7 +387,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBloc
 <ul class="blockList">
 <li class="blockList">
 <h4>encodedBlockDecodingCtx</h4>
-<pre>private&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/encoding/HFileBlockDecodingContext.html" title="interface in org.apache.hadoop.hbase.io.encoding">HFileBlockDecodingContext</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1429">encodedBlockDecodingCtx</a></pre>
+<pre>private&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/encoding/HFileBlockDecodingContext.html" title="interface in org.apache.hadoop.hbase.io.encoding">HFileBlockDecodingContext</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1431">encodedBlockDecodingCtx</a></pre>
 </li>
 </ul>
 <a name="defaultDecodingCtx">
@@ -396,7 +396,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBloc
 <ul class="blockList">
 <li class="blockList">
 <h4>defaultDecodingCtx</h4>
-<pre>private final&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/encoding/HFileBlockDefaultDecodingContext.html" title="class in org.apache.hadoop.hbase.io.encoding">HFileBlockDefaultDecodingContext</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1432">defaultDecodingCtx</a></pre>
+<pre>private final&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/encoding/HFileBlockDefaultDecodingContext.html" title="class in org.apache.hadoop.hbase.io.encoding">HFileBlockDefaultDecodingContext</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1434">defaultDecodingCtx</a></pre>
 <div class="block">Default context used when BlockType != <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockType.html#ENCODED_DATA"><code>BlockType.ENCODED_DATA</code></a>.</div>
 </li>
 </ul>
@@ -406,7 +406,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBloc
 <ul class="blockList">
 <li class="blockList">
 <h4>prefetchedHeader</h4>
-<pre>private&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/AtomicReference.html?is-external=true" title="class or interface in java.util.concurrent.atomic">AtomicReference</a>&lt;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.PrefetchedHeader.html" title="class in org.apache.hadoop.hbase.io.hfile">HFileBlock.PrefetchedHeader</a>&gt; <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1440">prefetchedHeader</a></pre>
+<pre>private&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/AtomicReference.html?is-external=true" title="class or interface in java.util.concurrent.atomic">AtomicReference</a>&lt;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.PrefetchedHeader.html" title="class in org.apache.hadoop.hbase.io.hfile">HFileBlock.PrefetchedHeader</a>&gt; <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1442">prefetchedHeader</a></pre>
 <div class="block">Cache of the NEXT header after this. Check it is indeed next blocks header
  before using it. TODO: Review. This overread into next block to fetch
  next blocks header seems unnecessary given we usually get the block size
@@ -419,7 +419,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBloc
 <ul class="blockList">
 <li class="blockList">
 <h4>fileSize</h4>
-<pre>private&nbsp;long <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1443">fileSize</a></pre>
+<pre>private&nbsp;long <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1445">fileSize</a></pre>
 <div class="block">The size of the file we are reading from, or -1 if unknown.</div>
 </li>
 </ul>
@@ -429,7 +429,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBloc
 <ul class="blockList">
 <li class="blockList">
 <h4>hdrSize</h4>
-<pre>protected final&nbsp;int <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1447">hdrSize</a></pre>
+<pre>protected final&nbsp;int <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1449">hdrSize</a></pre>
 <div class="block">The size of the header</div>
 </li>
 </ul>
@@ -439,7 +439,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBloc
 <ul class="blockList">
 <li class="blockList">
 <h4>hfs</h4>
-<pre>private&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/fs/HFileSystem.html" title="class in org.apache.hadoop.hbase.fs">HFileSystem</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1450">hfs</a></pre>
+<pre>private&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/fs/HFileSystem.html" title="class in org.apache.hadoop.hbase.fs">HFileSystem</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1452">hfs</a></pre>
 <div class="block">The filesystem used to access data</div>
 </li>
 </ul>
@@ -449,7 +449,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBloc
 <ul class="blockList">
 <li class="blockList">
 <h4>fileContext</h4>
-<pre>private&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileContext.html" title="class in org.apache.hadoop.hbase.io.hfile">HFileContext</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1452">fileContext</a></pre>
+<pre>private&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileContext.html" title="class in org.apache.hadoop.hbase.io.hfile">HFileContext</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1454">fileContext</a></pre>
 </li>
 </ul>
 <a name="pathName">
@@ -458,7 +458,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBloc
 <ul class="blockList">
 <li class="blockList">
 <h4>pathName</h4>
-<pre>private&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1454">pathName</a></pre>
+<pre>private&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1456">pathName</a></pre>
 </li>
 </ul>
 <a name="streamLock">
@@ -467,7 +467,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBloc
 <ul class="blockListLast">
 <li class="blockList">
 <h4>streamLock</h4>
-<pre>private final&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/locks/Lock.html?is-external=true" title="class or interface in java.util.concurrent.locks">Lock</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1456">streamLock</a></pre>
+<pre>private final&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/locks/Lock.html?is-external=true" title="class or interface in java.util.concurrent.locks">Lock</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1458">streamLock</a></pre>
 </li>
 </ul>
 </li>
@@ -484,7 +484,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBloc
 <ul class="blockList">
 <li class="blockList">
 <h4>FSReaderImpl</h4>
-<pre><a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1458">FSReaderImpl</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/FSDataInputStreamWrapper.html" title="class in org.apache.hadoop.hbase.io">FSDataInputStreamWrapper</a>&nbsp;stream,
+<pre><a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1460">FSReaderImpl</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/FSDataInputStreamWrapper.html" title="class in org.apache.hadoop.hbase.io">FSDataInputStreamWrapper</a>&nbsp;stream,
              long&nbsp;fileSize,
              <a href="../../../../../../org/apache/hadoop/hbase/fs/HFileSystem.html" title="class in org.apache.hadoop.hbase.fs">HFileSystem</a>&nbsp;hfs,
              org.apache.hadoop.fs.Path&nbsp;path,
@@ -502,7 +502,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBloc
 <ul class="blockListLast">
 <li class="blockList">
 <h4>FSReaderImpl</h4>
-<pre><a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1479">FSReaderImpl</a>(org.apache.hadoop.fs.FSDataInputStream&nbsp;istream,
+<pre><a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1481">FSReaderImpl</a>(org.apache.hadoop.fs.FSDataInputStream&nbsp;istream,
              long&nbsp;fileSize,
              <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileContext.html" title="class in org.apache.hadoop.hbase.io.hfile">HFileContext</a>&nbsp;fileContext)
       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>
@@ -528,7 +528,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBloc
 <ul class="blockList">
 <li class="blockList">
 <h4>blockRange</h4>
-<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.BlockIterator.html" title="interface in org.apache.hadoop.hbase.io.hfile">HFileBlock.BlockIterator</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1485">blockRange</a>(long&nbsp;startOffset,
+<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.BlockIterator.html" title="interface in org.apache.hadoop.hbase.io.hfile">HFileBlock.BlockIterator</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1487">blockRange</a>(long&nbsp;startOffset,
                                            long&nbsp;endOffset)</pre>
 <div class="block"><span class="descfrmTypeLabel">Description copied from interface:&nbsp;<code><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReader.html#blockRange-long-long-">HFileBlock.FSReader</a></code></span></div>
 <div class="block">Creates a block iterator over the given portion of the <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFile.html" title="class in org.apache.hadoop.hbase.io.hfile"><code>HFile</code></a>.
@@ -553,7 +553,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBloc
 <ul class="blockList">
 <li class="blockList">
 <h4>readAtOffset</h4>
-<pre>protected&nbsp;int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1533">readAtOffset</a>(org.apache.hadoop.fs.FSDataInputStream&nbsp;istream,
+<pre>protected&nbsp;int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1535">readAtOffset</a>(org.apache.hadoop.fs.FSDataInputStream&nbsp;istream,
                            byte[]&nbsp;dest,
                            int&nbsp;destOffset,
                            int&nbsp;size,
@@ -587,7 +587,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBloc
 <ul class="blockList">
 <li class="blockList">
 <h4>readBlockData</h4>
-<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.html" title="class in org.apache.hadoop.hbase.io.hfile">HFileBlock</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1584">readBlockData</a>(long&nbsp;offset,
+<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.html" title="class in org.apache.hadoop.hbase.io.hfile">HFileBlock</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1586">readBlockData</a>(long&nbsp;offset,
                                 long&nbsp;onDiskSizeWithHeaderL,
                                 boolean&nbsp;pread,
                                 boolean&nbsp;updateMetrics)
@@ -616,7 +616,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBloc
 <ul class="blockList">
 <li class="blockList">
 <h4>checkAndGetSizeAsInt</h4>
-<pre>private static&nbsp;int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1653">checkAndGetSizeAsInt</a>(long&nbsp;onDiskSizeWithHeaderL,
+<pre>private static&nbsp;int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1655">checkAndGetSizeAsInt</a>(long&nbsp;onDiskSizeWithHeaderL,
                                         int&nbsp;hdrSize)
                                  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>
@@ -633,7 +633,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBloc
 <ul class="blockList">
 <li class="blockList">
 <h4>verifyOnDiskSizeMatchesHeader</h4>
-<pre>private&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1669">verifyOnDiskSizeMatchesHeader</a>(int&nbsp;passedIn,
+<pre>private&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1671">verifyOnDiskSizeMatchesHeader</a>(int&nbsp;passedIn,
                                            <a href="https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html?is-external=true" title="class or interface in java.nio">ByteBuffer</a>&nbsp;headerBuf,
                                            long&nbsp;offset,
                                            boolean&nbsp;verifyChecksum)
@@ -652,7 +652,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBloc
 <ul class="blockList">
 <li class="blockList">
 <h4>getCachedHeader</h4>
-<pre>private&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html?is-external=true" title="class or interface in java.nio">ByteBuffer</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1690">getCachedHeader</a>(long&nbsp;offset)</pre>
+<pre>private&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html?is-external=true" title="class or interface in java.nio">ByteBuffer</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1692">getCachedHeader</a>(long&nbsp;offset)</pre>
 <div class="block">Check atomic reference cache for this block's header. Cache only good if next
  read coming through is next in sequence in the block. We read next block's
  header on the tail of reading the previous block to save a seek. Otherwise,
@@ -673,7 +673,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBloc
 <ul class="blockList">
 <li class="blockList">
 <h4>cacheNextBlockHeader</h4>
-<pre>private&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1700">cacheNextBlockHeader</a>(long&nbsp;offset,
+<pre>private&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1702">cacheNextBlockHeader</a>(long&nbsp;offset,
                                   byte[]&nbsp;header,
                                   int&nbsp;headerOffset,
                                   int&nbsp;headerLength)</pre>
@@ -691,7 +691,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBloc
 <ul class="blockList">
 <li class="blockList">
 <h4>readBlockDataInternal</h4>
-<pre>protected&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.html" title="class in org.apache.hadoop.hbase.io.hfile">HFileBlock</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1723">readBlockDataInternal</a>(org.apache.hadoop.fs.FSDataInputStream&nbsp;is,
+<pre>protected&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.html" title="class in org.apache.hadoop.hbase.io.hfile">HFileBlock</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1725">readBlockDataInternal</a>(org.apache.hadoop.fs.FSDataInputStream&nbsp;is,
                                            long&nbsp;offset,
                                            long&nbsp;onDiskSizeWithHeaderL,
                                            boolean&nbsp;pread,
@@ -723,7 +723,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBloc
 <ul class="blockList">
 <li class="blockList">
 <h4>setIncludesMemStoreTS</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1811">setIncludesMemStoreTS</a>(boolean&nbsp;includesMemstoreTS)</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1813">setIncludesMemStoreTS</a>(boolean&nbsp;includesMemstoreTS)</pre>
 <dl>
 <dt><span class="overrideSpecifyLabel">Specified by:</span></dt>
 <dd><code><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReader.html#setIncludesMemStoreTS-boolean-">setIncludesMemStoreTS</a></code>&nbsp;in interface&nbsp;<code><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReader.html" title="interface in org.apache.hadoop.hbase.io.hfile">HFileBlock.FSReader</a></code></dd>
@@ -736,7 +736,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBloc
 <ul class="blockList">
 <li class="blockList">
 <h4>setDataBlockEncoder</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1816">setDataBlockEncoder</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileDataBlockEncoder.html" title="interface in org.apache.hadoop.hbase.io.hfile">HFileDataBlockEncoder</a>&nbsp;encoder)</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1818">setDataBlockEncoder</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileDataBlockEncoder.html" title="interface in org.apache.hadoop.hbase.io.hfile">HFileDataBlockEncoder</a>&nbsp;encoder)</pre>
 <dl>
 <dt><span class="overrideSpecifyLabel">Specified by:</span></dt>
 <dd><code><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReader.html#setDataBlockEncoder-org.apache.hadoop.hbase.io.hfile.HFileDataBlockEncoder-">setDataBlockEncoder</a></code>&nbsp;in interface&nbsp;<code><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReader.html" title="interface in org.apache.hadoop.hbase.io.hfile">HFileBlock.FSReader</a></code></dd>
@@ -749,7 +749,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBloc
 <ul class="blockList">
 <li class="blockList">
 <h4>getBlockDecodingContext</h4>
-<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/encoding/HFileBlockDecodingContext.html" title="interface in org.apache.hadoop.hbase.io.encoding">HFileBlockDecodingContext</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1821">getBlockDecodingContext</a>()</pre>
+<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/encoding/HFileBlockDecodingContext.html" title="interface in org.apache.hadoop.hbase.io.encoding">HFileBlockDecodingContext</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1823">getBlockDecodingContext</a>()</pre>
 <div class="block"><span class="descfrmTypeLabel">Description copied from interface:&nbsp;<code><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReader.html#getBlockDecodingContext--">HFileBlock.FSReader</a></code></span></div>
 <div class="block">Get a decoder for <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockType.html#ENCODED_DATA"><code>BlockType.ENCODED_DATA</code></a> blocks from this file.</div>
 <dl>
@@ -764,7 +764,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBloc
 <ul class="blockList">
 <li class="blockList">
 <h4>getDefaultBlockDecodingContext</h4>
-<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/encoding/HFileBlockDecodingContext.html" title="interface in org.apache.hadoop.hbase.io.encoding">HFileBlockDecodingContext</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1826">getDefaultBlockDecodingContext</a>()</pre>
+<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/encoding/HFileBlockDecodingContext.html" title="interface in org.apache.hadoop.hbase.io.encoding">HFileBlockDecodingContext</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1828">getDefaultBlockDecodingContext</a>()</pre>
 <div class="block"><span class="descfrmTypeLabel">Description copied from interface:&nbsp;<code><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReader.html#getDefaultBlockDecodingContext--">HFileBlock.FSReader</a></code></span></div>
 <div class="block">Get the default decoder for blocks from this file.</div>
 <dl>
@@ -779,7 +779,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBloc
 <ul class="blockList">
 <li class="blockList">
 <h4>validateChecksum</h4>
-<pre>private&nbsp;boolean&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1835">validateChecksum</a>(long&nbsp;offset,
+<pre>private&nbsp;boolean&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1837">validateChecksum</a>(long&nbsp;offset,
                                  <a href="https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html?is-external=true" title="class or interface in java.nio">ByteBuffer</a>&nbsp;data,
                                  int&nbsp;hdrSize)
                           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>
@@ -799,7 +799,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBloc
 <ul class="blockList">
 <li class="blockList">
 <h4>closeStreams</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1849">closeStreams</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1851">closeStreams</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"><span class="descfrmTypeLabel">Description copied from interface:&nbsp;<code><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReader.html#closeStreams--">HFileBlock.FSReader</a></code></span></div>
 <div class="block">Closes the backing streams</div>
@@ -817,7 +817,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBloc
 <ul class="blockList">
 <li class="blockList">
 <h4>unbufferStream</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1854">unbufferStream</a>()</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html#line.1856">unbufferStream</a>()</pre>
 <div class="block"><span class="descfrmTypeLabel">Description copied from interface:&nbsp;<code><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReader.html#unbufferStream--">HFileBlock.FSReader</a></code></span></div>
 <div class="block">To close the stream's socket. Note: This can be concurrently called from multiple threads and
  implementation should take care of thread safety.</div>
@@ -833,7 +833,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBloc
 <ul class="blockListLast">
 <li class="blockList">
 <h4>toString</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/io/hfile/HFileBlock.FSReaderImpl.html#line.1867">toString</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/io/hfile/HFileBlock.FSReaderImpl.html#line.1869">toString</a>()</pre>
 <dl>
 <dt><span class="overrideSpecifyLabel">Overrides:</span></dt>
 <dd><code><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true#toString--" title="class or interface in java.lang">toString</a></code>&nbsp;in class&nbsp;<code><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></code></dd>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/io/hfile/HFileBlock.PrefetchedHeader.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/io/hfile/HFileBlock.PrefetchedHeader.html b/devapidocs/org/apache/hadoop/hbase/io/hfile/HFileBlock.PrefetchedHeader.html
index 474d032..66ee7a3 100644
--- a/devapidocs/org/apache/hadoop/hbase/io/hfile/HFileBlock.PrefetchedHeader.html
+++ b/devapidocs/org/apache/hadoop/hbase/io/hfile/HFileBlock.PrefetchedHeader.html
@@ -113,7 +113,7 @@ var activeTableTab = "activeTableTab";
 </dl>
 <hr>
 <br>
-<pre>private static class <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.1410">HFileBlock.PrefetchedHeader</a>
+<pre>private static class <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.1412">HFileBlock.PrefetchedHeader</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">Data-structure to use caching the header of the NEXT block. Only works if next read
  that comes in here is next in sequence in this block.
@@ -217,7 +217,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>offset</h4>
-<pre>long <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.PrefetchedHeader.html#line.1411">offset</a></pre>
+<pre>long <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.PrefetchedHeader.html#line.1413">offset</a></pre>
 </li>
 </ul>
 <a name="header">
@@ -226,7 +226,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>header</h4>
-<pre>byte[] <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.PrefetchedHeader.html#line.1412">header</a></pre>
+<pre>byte[] <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.PrefetchedHeader.html#line.1414">header</a></pre>
 </li>
 </ul>
 <a name="buf">
@@ -235,7 +235,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>buf</h4>
-<pre>final&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html?is-external=true" title="class or interface in java.nio">ByteBuffer</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.PrefetchedHeader.html#line.1413">buf</a></pre>
+<pre>final&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html?is-external=true" title="class or interface in java.nio">ByteBuffer</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.PrefetchedHeader.html#line.1415">buf</a></pre>
 </li>
 </ul>
 </li>
@@ -252,7 +252,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>PrefetchedHeader</h4>
-<pre>private&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.PrefetchedHeader.html#line.1410">PrefetchedHeader</a>()</pre>
+<pre>private&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.PrefetchedHeader.html#line.1412">PrefetchedHeader</a>()</pre>
 </li>
 </ul>
 </li>
@@ -269,7 +269,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>toString</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/io/hfile/HFileBlock.PrefetchedHeader.html#line.1416">toString</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/io/hfile/HFileBlock.PrefetchedHeader.html#line.1418">toString</a>()</pre>
 <dl>
 <dt><span class="overrideSpecifyLabel">Overrides:</span></dt>
 <dd><code><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true#toString--" title="class or interface in java.lang">toString</a></code>&nbsp;in class&nbsp;<code><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></code></dd>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.State.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.State.html b/devapidocs/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.State.html
index 96c42eb..9b248ec 100644
--- a/devapidocs/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.State.html
+++ b/devapidocs/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.State.html
@@ -122,7 +122,7 @@ var activeTableTab = "activeTableTab";
 </dl>
 <hr>
 <br>
-<pre>private static enum <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.834">HFileBlock.Writer.State</a>
+<pre>private static enum <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.836">HFileBlock.Writer.State</a>
 extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang">Enum</a>&lt;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.State.html" title="enum in org.apache.hadoop.hbase.io.hfile">HFileBlock.Writer.State</a>&gt;</pre>
 </li>
 </ul>
@@ -213,7 +213,7 @@ the order they are declared.</div>
 <ul class="blockList">
 <li class="blockList">
 <h4>INIT</h4>
-<pre>public static final&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.State.html" title="enum in org.apache.hadoop.hbase.io.hfile">HFileBlock.Writer.State</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.State.html#line.835">INIT</a></pre>
+<pre>public static final&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.State.html" title="enum in org.apache.hadoop.hbase.io.hfile">HFileBlock.Writer.State</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.State.html#line.837">INIT</a></pre>
 </li>
 </ul>
 <a name="WRITING">
@@ -222,7 +222,7 @@ the order they are declared.</div>
 <ul class="blockList">
 <li class="blockList">
 <h4>WRITING</h4>
-<pre>public static final&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.State.html" title="enum in org.apache.hadoop.hbase.io.hfile">HFileBlock.Writer.State</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.State.html#line.836">WRITING</a></pre>
+<pre>public static final&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.State.html" title="enum in org.apache.hadoop.hbase.io.hfile">HFileBlock.Writer.State</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.State.html#line.838">WRITING</a></pre>
 </li>
 </ul>
 <a name="BLOCK_READY">
@@ -231,7 +231,7 @@ the order they are declared.</div>
 <ul class="blockListLast">
 <li class="blockList">
 <h4>BLOCK_READY</h4>
-<pre>public static final&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.State.html" title="enum in org.apache.hadoop.hbase.io.hfile">HFileBlock.Writer.State</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.State.html#line.837">BLOCK_READY</a></pre>
+<pre>public static final&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.State.html" title="enum in org.apache.hadoop.hbase.io.hfile">HFileBlock.Writer.State</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.State.html#line.839">BLOCK_READY</a></pre>
 </li>
 </ul>
 </li>
@@ -248,7 +248,7 @@ the order they are declared.</div>
 <ul class="blockList">
 <li class="blockList">
 <h4>values</h4>
-<pre>public static&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.State.html" title="enum in org.apache.hadoop.hbase.io.hfile">HFileBlock.Writer.State</a>[]&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.State.html#line.834">values</a>()</pre>
+<pre>public static&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.State.html" title="enum in org.apache.hadoop.hbase.io.hfile">HFileBlock.Writer.State</a>[]&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.State.html#line.836">values</a>()</pre>
 <div class="block">Returns an array containing the constants of this enum type, in
 the order they are declared.  This method may be used to iterate
 over the constants as follows:
@@ -268,7 +268,7 @@ for (HFileBlock.Writer.State c : HFileBlock.Writer.State.values())
 <ul class="blockListLast">
 <li class="blockList">
 <h4>valueOf</h4>
-<pre>public static&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.State.html" title="enum in org.apache.hadoop.hbase.io.hfile">HFileBlock.Writer.State</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.State.html#line.834">valueOf</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 static&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.State.html" title="enum in org.apache.hadoop.hbase.io.hfile">HFileBlock.Writer.State</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.State.html#line.836">valueOf</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">Returns the enum constant of this type with the specified name.
 The string must match <i>exactly</i> an identifier used to declare an
 enum constant in this type.  (Extraneous whitespace characters are 

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html b/devapidocs/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html
index 37f8712..6079b85 100644
--- a/devapidocs/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html
+++ b/devapidocs/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html
@@ -113,7 +113,7 @@ var activeTableTab = "activeTableTab";
 </dl>
 <hr>
 <br>
-<pre>static class <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.833">HFileBlock.Writer</a>
+<pre>static class <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.835">HFileBlock.Writer</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">Unified version 2 <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFile.html" title="class in org.apache.hadoop.hbase.io.hfile"><code>HFile</code></a> block writer. The intended usage pattern
  is as follows:
@@ -459,7 +459,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>state</h4>
-<pre>private&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.State.html" title="enum in org.apache.hadoop.hbase.io.hfile">HFileBlock.Writer.State</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.841">state</a></pre>
+<pre>private&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.State.html" title="enum in org.apache.hadoop.hbase.io.hfile">HFileBlock.Writer.State</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.843">state</a></pre>
 <div class="block">Writer state. Used to ensure the correct usage protocol.</div>
 </li>
 </ul>
@@ -469,7 +469,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>dataBlockEncoder</h4>
-<pre>private final&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileDataBlockEncoder.html" title="interface in org.apache.hadoop.hbase.io.hfile">HFileDataBlockEncoder</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.844">dataBlockEncoder</a></pre>
+<pre>private final&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileDataBlockEncoder.html" title="interface in org.apache.hadoop.hbase.io.hfile">HFileDataBlockEncoder</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.846">dataBlockEncoder</a></pre>
 <div class="block">Data block encoder used for data blocks</div>
 </li>
 </ul>
@@ -479,7 +479,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>dataBlockEncodingCtx</h4>
-<pre>private&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/encoding/HFileBlockEncodingContext.html" title="interface in org.apache.hadoop.hbase.io.encoding">HFileBlockEncodingContext</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.846">dataBlockEncodingCtx</a></pre>
+<pre>private&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/encoding/HFileBlockEncodingContext.html" title="interface in org.apache.hadoop.hbase.io.encoding">HFileBlockEncodingContext</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.848">dataBlockEncodingCtx</a></pre>
 </li>
 </ul>
 <a name="defaultBlockEncodingCtx">
@@ -488,7 +488,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>defaultBlockEncodingCtx</h4>
-<pre>private&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/encoding/HFileBlockDefaultEncodingContext.html" title="class in org.apache.hadoop.hbase.io.encoding">HFileBlockDefaultEncodingContext</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.849">defaultBlockEncodingCtx</a></pre>
+<pre>private&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/encoding/HFileBlockDefaultEncodingContext.html" title="class in org.apache.hadoop.hbase.io.encoding">HFileBlockDefaultEncodingContext</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.851">defaultBlockEncodingCtx</a></pre>
 <div class="block">block encoding context for non-data blocks</div>
 </li>
 </ul>
@@ -498,7 +498,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>baosInMemory</h4>
-<pre>private&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/ByteArrayOutputStream.html" title="class in org.apache.hadoop.hbase.io">ByteArrayOutputStream</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.857">baosInMemory</a></pre>
+<pre>private&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/ByteArrayOutputStream.html" title="class in org.apache.hadoop.hbase.io">ByteArrayOutputStream</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.859">baosInMemory</a></pre>
 <div class="block">The stream we use to accumulate data into a block in an uncompressed format.
  We reset this stream at the end of each block and reuse it. The
  header is written as the first <a href="../../../../../../org/apache/hadoop/hbase/HConstants.html#HFILEBLOCK_HEADER_SIZE"><code>HConstants.HFILEBLOCK_HEADER_SIZE</code></a> bytes into this
@@ -511,7 +511,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>blockType</h4>
-<pre>private&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockType.html" title="enum in org.apache.hadoop.hbase.io.hfile">BlockType</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.864">blockType</a></pre>
+<pre>private&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockType.html" title="enum in org.apache.hadoop.hbase.io.hfile">BlockType</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.866">blockType</a></pre>
 <div class="block">Current block type. Set in <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#startWriting-org.apache.hadoop.hbase.io.hfile.BlockType-"><code>startWriting(BlockType)</code></a>. Could be
  changed in <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#finishBlock--"><code>finishBlock()</code></a> from <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockType.html#DATA"><code>BlockType.DATA</code></a>
  to <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockType.html#ENCODED_DATA"><code>BlockType.ENCODED_DATA</code></a>.</div>
@@ -523,7 +523,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>userDataStream</h4>
-<pre>private&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/io/DataOutputStream.html?is-external=true" title="class or interface in java.io">DataOutputStream</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.870">userDataStream</a></pre>
+<pre>private&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/io/DataOutputStream.html?is-external=true" title="class or interface in java.io">DataOutputStream</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.872">userDataStream</a></pre>
 <div class="block">A stream that we write uncompressed bytes to, which compresses them and
  writes them to <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#baosInMemory"><code>baosInMemory</code></a>.</div>
 </li>
@@ -534,7 +534,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>unencodedDataSizeWritten</h4>
-<pre>private&nbsp;int <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.874">unencodedDataSizeWritten</a></pre>
+<pre>private&nbsp;int <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.876">unencodedDataSizeWritten</a></pre>
 </li>
 </ul>
 <a name="encodedDataSizeWritten">
@@ -543,7 +543,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>encodedDataSizeWritten</h4>
-<pre>private&nbsp;int <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.878">encodedDataSizeWritten</a></pre>
+<pre>private&nbsp;int <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.880">encodedDataSizeWritten</a></pre>
 </li>
 </ul>
 <a name="onDiskBlockBytesWithHeader">
@@ -552,7 +552,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>onDiskBlockBytesWithHeader</h4>
-<pre>private&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/ByteArrayOutputStream.html" title="class in org.apache.hadoop.hbase.io">ByteArrayOutputStream</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.885">onDiskBlockBytesWithHeader</a></pre>
+<pre>private&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/ByteArrayOutputStream.html" title="class in org.apache.hadoop.hbase.io">ByteArrayOutputStream</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.887">onDiskBlockBytesWithHeader</a></pre>
 <div class="block">Bytes to be written to the file system, including the header. Compressed
  if compression is turned on. It also includes the checksum data that
  immediately follows the block data. (header + data + checksums)</div>
@@ -564,7 +564,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>onDiskChecksum</h4>
-<pre>private&nbsp;byte[] <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.893">onDiskChecksum</a></pre>
+<pre>private&nbsp;byte[] <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.895">onDiskChecksum</a></pre>
 <div class="block">The size of the checksum data on disk. It is used only if data is
  not compressed. If data is compressed, then the checksums are already
  part of onDiskBytesWithHeader. If data is uncompressed, then this
@@ -577,7 +577,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>startOffset</h4>
-<pre>private&nbsp;long <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.899">startOffset</a></pre>
+<pre>private&nbsp;long <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.901">startOffset</a></pre>
 <div class="block">Current block's start offset in the <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFile.html" title="class in org.apache.hadoop.hbase.io.hfile"><code>HFile</code></a>. Set in
  <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#writeHeaderAndData-org.apache.hadoop.fs.FSDataOutputStream-"><code>writeHeaderAndData(FSDataOutputStream)</code></a>.</div>
 </li>
@@ -588,7 +588,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>prevOffsetByType</h4>
-<pre>private&nbsp;long[] <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.905">prevOffsetByType</a></pre>
+<pre>private&nbsp;long[] <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.907">prevOffsetByType</a></pre>
 <div class="block">Offset of previous block by block type. Updated when the next block is
  started.</div>
 </li>
@@ -599,7 +599,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>prevOffset</h4>
-<pre>private&nbsp;long <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.908">prevOffset</a></pre>
+<pre>private&nbsp;long <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.910">prevOffset</a></pre>
 <div class="block">The offset of the previous block of the same type</div>
 </li>
 </ul>
@@ -609,7 +609,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>fileContext</h4>
-<pre>private&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileContext.html" title="class in org.apache.hadoop.hbase.io.hfile">HFileContext</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.910">fileContext</a></pre>
+<pre>private&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileContext.html" title="class in org.apache.hadoop.hbase.io.hfile">HFileContext</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.912">fileContext</a></pre>
 <div class="block">Meta data that holds information about the hfileblock</div>
 </li>
 </ul>
@@ -627,7 +627,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>Writer</h4>
-<pre>public&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.915">Writer</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileDataBlockEncoder.html" title="interface in org.apache.hadoop.hbase.io.hfile">HFileDataBlockEncoder</a>&nbsp;dataBlockEncoder,
+<pre>public&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.917">Writer</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileDataBlockEncoder.html" title="interface in org.apache.hadoop.hbase.io.hfile">HFileDataBlockEncoder</a>&nbsp;dataBlockEncoder,
               <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileContext.html" title="class in org.apache.hadoop.hbase.io.hfile">HFileContext</a>&nbsp;fileContext)</pre>
 <dl>
 <dt><span class="paramLabel">Parameters:</span></dt>
@@ -649,7 +649,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>startWriting</h4>
-<pre><a href="https://docs.oracle.com/javase/8/docs/api/java/io/DataOutputStream.html?is-external=true" title="class or interface in java.io">DataOutputStream</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.945">startWriting</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockType.html" title="enum in org.apache.hadoop.hbase.io.hfile">BlockType</a>&nbsp;newBlockType)
+<pre><a href="https://docs.oracle.com/javase/8/docs/api/java/io/DataOutputStream.html?is-external=true" title="class or interface in java.io">DataOutputStream</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.947">startWriting</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockType.html" title="enum in org.apache.hadoop.hbase.io.hfile">BlockType</a>&nbsp;newBlockType)
                        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">Starts writing into the block. The previous block's data is discarded.</div>
 <dl>
@@ -666,7 +666,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>write</h4>
-<pre>void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.976">write</a>(<a href="../../../../../../org/apache/hadoop/hbase/Cell.html" title="interface in org.apache.hadoop.hbase">Cell</a>&nbsp;cell)
+<pre>void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.978">write</a>(<a href="../../../../../../org/apache/hadoop/hbase/Cell.html" title="interface in org.apache.hadoop.hbase">Cell</a>&nbsp;cell)
     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">Writes the Cell to this block</div>
 <dl>
@@ -683,7 +683,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getUserDataStream</h4>
-<pre><a href="https://docs.oracle.com/javase/8/docs/api/java/io/DataOutputStream.html?is-external=true" title="class or interface in java.io">DataOutputStream</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.991">getUserDataStream</a>()</pre>
+<pre><a href="https://docs.oracle.com/javase/8/docs/api/java/io/DataOutputStream.html?is-external=true" title="class or interface in java.io">DataOutputStream</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.993">getUserDataStream</a>()</pre>
 <div class="block">Returns the stream for the user to write to. The block writer takes care
  of handling compression and buffering for caching on write. Can only be
  called in the "writing" state.</div>
@@ -699,7 +699,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>ensureBlockReady</h4>
-<pre>void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.1000">ensureBlockReady</a>()
+<pre>void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.1002">ensureBlockReady</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">Transitions the block writer from the "writing" state to the "block
  ready" state.  Does nothing if a block is already finished.</div>
@@ -715,7 +715,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>finishBlock</h4>
-<pre>private&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.1018">finishBlock</a>()
+<pre>private&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.1020">finishBlock</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">Finish up writing of the block.
  Flushes the compressing stream (if using compression), fills out the header,
@@ -733,7 +733,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>putHeader</h4>
-<pre>private&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.1072">putHeader</a>(byte[]&nbsp;dest,
+<pre>private&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.1074">putHeader</a>(byte[]&nbsp;dest,
                        int&nbsp;offset,
                        int&nbsp;onDiskSize,
                        int&nbsp;uncompressedSize,
@@ -755,7 +755,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>putHeader</h4>
-<pre>private&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.1083">putHeader</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/ByteArrayOutputStream.html" title="class in org.apache.hadoop.hbase.io">ByteArrayOutputStream</a>&nbsp;dest,
+<pre>private&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.1085">putHeader</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/ByteArrayOutputStream.html" title="class in org.apache.hadoop.hbase.io">ByteArrayOutputStream</a>&nbsp;dest,
                        int&nbsp;onDiskSize,
                        int&nbsp;uncompressedSize,
                        int&nbsp;onDiskDataSize)</pre>
@@ -767,7 +767,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>writeHeaderAndData</h4>
-<pre>void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.1096">writeHeaderAndData</a>(org.apache.hadoop.fs.FSDataOutputStream&nbsp;out)
+<pre>void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.1098">writeHeaderAndData</a>(org.apache.hadoop.fs.FSDataOutputStream&nbsp;out)
                  throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
 <div class="block">Similar to <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#writeHeaderAndData-org.apache.hadoop.fs.FSDataOutputStream-"><code>writeHeaderAndData(FSDataOutputStream)</code></a>, but records
  the offset of this block so that it can be referenced in the next block
@@ -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>finishBlockAndWriteHeaderAndData</h4>
-<pre>protected&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.1117">finishBlockAndWriteHeaderAndData</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/io/DataOutputStream.html?is-external=true" title="class or interface in java.io">DataOutputStream</a>&nbsp;out)
+<pre>protected&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.1119">finishBlockAndWriteHeaderAndData</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/io/DataOutputStream.html?is-external=true" title="class or interface in java.io">DataOutputStream</a>&nbsp;out)
                                          throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
 <div class="block">Writes the header and the compressed data of this block (or uncompressed
  data when not using compression) into the given stream. Can be called in
@@ -806,7 +806,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getHeaderAndDataForTest</h4>
-<pre>byte[]&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.1136">getHeaderAndDataForTest</a>()
+<pre>byte[]&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.1138">getHeaderAndDataForTest</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">Returns the header or the compressed data (or uncompressed data when not
  using compression) as a byte array. Can be called in the "writing" state
@@ -827,7 +827,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>release</h4>
-<pre>void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.1153">release</a>()</pre>
+<pre>void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.1155">release</a>()</pre>
 <div class="block">Releases resources used by this writer.</div>
 </li>
 </ul>
@@ -837,7 +837,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getOnDiskSizeWithoutHeader</h4>
-<pre>int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.1172">getOnDiskSizeWithoutHeader</a>()</pre>
+<pre>int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.1174">getOnDiskSizeWithoutHeader</a>()</pre>
 <div class="block">Returns the on-disk size of the data portion of the block. This is the
  compressed size if compression is enabled. Can only be called in the
  "block ready" state. Header is not compressed, and its size is not
@@ -854,7 +854,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getOnDiskSizeWithHeader</h4>
-<pre>int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.1185">getOnDiskSizeWithHeader</a>()</pre>
+<pre>int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.1187">getOnDiskSizeWithHeader</a>()</pre>
 <div class="block">Returns the on-disk size of the block. Can only be called in the
  "block ready" state.</div>
 <dl>
@@ -870,7 +870,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getUncompressedSizeWithoutHeader</h4>
-<pre>int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.1193">getUncompressedSizeWithoutHeader</a>()</pre>
+<pre>int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.1195">getUncompressedSizeWithoutHeader</a>()</pre>
 <div class="block">The uncompressed size of the block data. Does not include header size.</div>
 </li>
 </ul>
@@ -880,7 +880,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getUncompressedSizeWithHeader</h4>
-<pre>int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.1201">getUncompressedSizeWithHeader</a>()</pre>
+<pre>int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.1203">getUncompressedSizeWithHeader</a>()</pre>
 <div class="block">The uncompressed size of the block data, including header size.</div>
 </li>
 </ul>
@@ -890,7 +890,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>isWriting</h4>
-<pre>boolean&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.1207">isWriting</a>()</pre>
+<pre>boolean&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.1209">isWriting</a>()</pre>
 <dl>
 <dt><span class="returnLabel">Returns:</span></dt>
 <dd>true if a block is being written</dd>
@@ -903,7 +903,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>encodedBlockSizeWritten</h4>
-<pre>public&nbsp;int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.1218">encodedBlockSizeWritten</a>()</pre>
+<pre>public&nbsp;int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.1220">encodedBlockSizeWritten</a>()</pre>
 <div class="block">Returns the number of bytes written into the current block so far, or
  zero if not writing the block at the moment. Note that this will return
  zero in the "block ready" state as well.</div>
@@ -919,7 +919,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>blockSizeWritten</h4>
-<pre>int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.1231">blockSizeWritten</a>()</pre>
+<pre>int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.1233">blockSizeWritten</a>()</pre>
 <div class="block">Returns the number of bytes written into the current block so far, or
  zero if not writing the block at the moment. Note that this will return
  zero in the "block ready" state as well.</div>
@@ -935,7 +935,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>cloneUncompressedBufferWithHeader</h4>
-<pre><a href="https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html?is-external=true" title="class or interface in java.nio">ByteBuffer</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.1245">cloneUncompressedBufferWithHeader</a>()</pre>
+<pre><a href="https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html?is-external=true" title="class or interface in java.nio">ByteBuffer</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.1247">cloneUncompressedBufferWithHeader</a>()</pre>
 <div class="block">Clones the header followed by the uncompressed data, even if using
  compression. This is needed for storing uncompressed blocks in the block
  cache. Can be called in the "writing" state or the "block ready" state.
@@ -952,7 +952,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>cloneOnDiskBufferWithHeader</h4>
-<pre>private&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html?is-external=true" title="class or interface in java.nio">ByteBuffer</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.1265">cloneOnDiskBufferWithHeader</a>()</pre>
+<pre>private&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html?is-external=true" title="class or interface in java.nio">ByteBuffer</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.1267">cloneOnDiskBufferWithHeader</a>()</pre>
 <div class="block">Clones the header followed by the on-disk (compressed/encoded/encrypted) data. This is
  needed for storing packed blocks in the block cache. Expects calling semantics identical to
  <code>#getUncompressedBufferWithHeader()</code>. Returns only the header and data,
@@ -969,7 +969,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>expectState</h4>
-<pre>private&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.1270">expectState</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.State.html" title="enum in org.apache.hadoop.hbase.io.hfile">HFileBlock.Writer.State</a>&nbsp;expectedState)</pre>
+<pre>private&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.1272">expectState</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.State.html" title="enum in org.apache.hadoop.hbase.io.hfile">HFileBlock.Writer.State</a>&nbsp;expectedState)</pre>
 </li>
 </ul>
 <a name="writeBlock-org.apache.hadoop.hbase.io.hfile.HFileBlock.BlockWritable-org.apache.hadoop.fs.FSDataOutputStream-">
@@ -978,7 +978,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>writeBlock</h4>
-<pre>void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.1287">writeBlock</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.BlockWritable.html" title="interface in org.apache.hadoop.hbase.io.hfile">HFileBlock.BlockWritable</a>&nbsp;bw,
+<pre>void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.1289">writeBlock</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.BlockWritable.html" title="interface in org.apache.hadoop.hbase.io.hfile">HFileBlock.BlockWritable</a>&nbsp;bw,
                 org.apache.hadoop.fs.FSDataOutputStream&nbsp;out)
          throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
 <div class="block">Takes the given <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.BlockWritable.html" title="interface in org.apache.hadoop.hbase.io.hfile"><code>HFileBlock.BlockWritable</code></a> instance, creates a new block of
@@ -1000,7 +1000,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>getBlockForCaching</h4>
-<pre><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.html" title="class in org.apache.hadoop.hbase.io.hfile">HFileBlock</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.1306">getBlockForCaching</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/CacheConfig.html" title="class in org.apache.hadoop.hbase.io.hfile">CacheConfig</a>&nbsp;cacheConf)</pre>
+<pre><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.html" title="class in org.apache.hadoop.hbase.io.hfile">HFileBlock</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#line.1308">getBlockForCaching</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/CacheConfig.html" title="class in org.apache.hadoop.hbase.io.hfile">CacheConfig</a>&nbsp;cacheConf)</pre>
 <div class="block">Creates a new HFileBlock. Checksums have already been validated, so
  the byte buffer passed into the constructor of this newly created
  block does not have checksum data even though the header minor


[30/50] hbase-site git commit: Published site at 26babcf013de696b899d76a3c39434b794440d8d.

Posted by gi...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.BlockBucket.html
----------------------------------------------------------------------
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.BlockBucket.html b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.BlockBucket.html
index f5747c6..b94ef5e 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.BlockBucket.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.BlockBucket.html
@@ -388,811 +388,816 @@
 <span class="sourceLineNo">380</span><a name="line.380"></a>
 <span class="sourceLineNo">381</span>    LruCachedBlock cb = map.get(cacheKey);<a name="line.381"></a>
 <span class="sourceLineNo">382</span>    if (cb != null) {<a name="line.382"></a>
-<span class="sourceLineNo">383</span>      // compare the contents, if they are not equal, we are in big trouble<a name="line.383"></a>
-<span class="sourceLineNo">384</span>      if (BlockCacheUtil.compareCacheBlock(buf, cb.getBuffer()) != 0) {<a name="line.384"></a>
-<span class="sourceLineNo">385</span>        throw new RuntimeException("Cached block contents differ, which should not have happened."<a name="line.385"></a>
-<span class="sourceLineNo">386</span>          + "cacheKey:" + cacheKey);<a name="line.386"></a>
-<span class="sourceLineNo">387</span>      }<a name="line.387"></a>
-<span class="sourceLineNo">388</span>      String msg = "Cached an already cached block: " + cacheKey + " cb:" + cb.getCacheKey();<a name="line.388"></a>
-<span class="sourceLineNo">389</span>      msg += ". This is harmless and can happen in rare cases (see HBASE-8547)";<a name="line.389"></a>
-<span class="sourceLineNo">390</span>      LOG.warn(msg);<a name="line.390"></a>
-<span class="sourceLineNo">391</span>      return;<a name="line.391"></a>
-<span class="sourceLineNo">392</span>    }<a name="line.392"></a>
-<span class="sourceLineNo">393</span>    long currentSize = size.get();<a name="line.393"></a>
-<span class="sourceLineNo">394</span>    long currentAcceptableSize = acceptableSize();<a name="line.394"></a>
-<span class="sourceLineNo">395</span>    long hardLimitSize = (long) (hardCapacityLimitFactor * currentAcceptableSize);<a name="line.395"></a>
-<span class="sourceLineNo">396</span>    if (currentSize &gt;= hardLimitSize) {<a name="line.396"></a>
-<span class="sourceLineNo">397</span>      stats.failInsert();<a name="line.397"></a>
-<span class="sourceLineNo">398</span>      if (LOG.isTraceEnabled()) {<a name="line.398"></a>
-<span class="sourceLineNo">399</span>        LOG.trace("LruBlockCache current size " + StringUtils.byteDesc(currentSize)<a name="line.399"></a>
-<span class="sourceLineNo">400</span>          + " has exceeded acceptable size " + StringUtils.byteDesc(currentAcceptableSize) + "."<a name="line.400"></a>
-<span class="sourceLineNo">401</span>          + " The hard limit size is " + StringUtils.byteDesc(hardLimitSize)<a name="line.401"></a>
-<span class="sourceLineNo">402</span>          + ", failed to put cacheKey:" + cacheKey + " into LruBlockCache.");<a name="line.402"></a>
-<span class="sourceLineNo">403</span>      }<a name="line.403"></a>
-<span class="sourceLineNo">404</span>      if (!evictionInProgress) {<a name="line.404"></a>
-<span class="sourceLineNo">405</span>        runEviction();<a name="line.405"></a>
-<span class="sourceLineNo">406</span>      }<a name="line.406"></a>
-<span class="sourceLineNo">407</span>      return;<a name="line.407"></a>
-<span class="sourceLineNo">408</span>    }<a name="line.408"></a>
-<span class="sourceLineNo">409</span>    cb = new LruCachedBlock(cacheKey, buf, count.incrementAndGet(), inMemory);<a name="line.409"></a>
-<span class="sourceLineNo">410</span>    long newSize = updateSizeMetrics(cb, false);<a name="line.410"></a>
-<span class="sourceLineNo">411</span>    map.put(cacheKey, cb);<a name="line.411"></a>
-<span class="sourceLineNo">412</span>    long val = elements.incrementAndGet();<a name="line.412"></a>
-<span class="sourceLineNo">413</span>    if (buf.getBlockType().isData()) {<a name="line.413"></a>
-<span class="sourceLineNo">414</span>       dataBlockElements.increment();<a name="line.414"></a>
-<span class="sourceLineNo">415</span>    }<a name="line.415"></a>
-<span class="sourceLineNo">416</span>    if (LOG.isTraceEnabled()) {<a name="line.416"></a>
-<span class="sourceLineNo">417</span>      long size = map.size();<a name="line.417"></a>
-<span class="sourceLineNo">418</span>      assertCounterSanity(size, val);<a name="line.418"></a>
-<span class="sourceLineNo">419</span>    }<a name="line.419"></a>
-<span class="sourceLineNo">420</span>    if (newSize &gt; currentAcceptableSize &amp;&amp; !evictionInProgress) {<a name="line.420"></a>
-<span class="sourceLineNo">421</span>      runEviction();<a name="line.421"></a>
-<span class="sourceLineNo">422</span>    }<a name="line.422"></a>
-<span class="sourceLineNo">423</span>  }<a name="line.423"></a>
-<span class="sourceLineNo">424</span><a name="line.424"></a>
-<span class="sourceLineNo">425</span>  /**<a name="line.425"></a>
-<span class="sourceLineNo">426</span>   * Sanity-checking for parity between actual block cache content and metrics.<a name="line.426"></a>
-<span class="sourceLineNo">427</span>   * Intended only for use with TRACE level logging and -ea JVM.<a name="line.427"></a>
-<span class="sourceLineNo">428</span>   */<a name="line.428"></a>
-<span class="sourceLineNo">429</span>  private static void assertCounterSanity(long mapSize, long counterVal) {<a name="line.429"></a>
-<span class="sourceLineNo">430</span>    if (counterVal &lt; 0) {<a name="line.430"></a>
-<span class="sourceLineNo">431</span>      LOG.trace("counterVal overflow. Assertions unreliable. counterVal=" + counterVal +<a name="line.431"></a>
-<span class="sourceLineNo">432</span>        ", mapSize=" + mapSize);<a name="line.432"></a>
-<span class="sourceLineNo">433</span>      return;<a name="line.433"></a>
-<span class="sourceLineNo">434</span>    }<a name="line.434"></a>
-<span class="sourceLineNo">435</span>    if (mapSize &lt; Integer.MAX_VALUE) {<a name="line.435"></a>
-<span class="sourceLineNo">436</span>      double pct_diff = Math.abs((((double) counterVal) / ((double) mapSize)) - 1.);<a name="line.436"></a>
-<span class="sourceLineNo">437</span>      if (pct_diff &gt; 0.05) {<a name="line.437"></a>
-<span class="sourceLineNo">438</span>        LOG.trace("delta between reported and actual size &gt; 5%. counterVal=" + counterVal +<a name="line.438"></a>
-<span class="sourceLineNo">439</span>          ", mapSize=" + mapSize);<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><a name="line.443"></a>
-<span class="sourceLineNo">444</span>  /**<a name="line.444"></a>
-<span class="sourceLineNo">445</span>   * Cache the block with the specified name and buffer.<a name="line.445"></a>
-<span class="sourceLineNo">446</span>   * &lt;p&gt;<a name="line.446"></a>
-<span class="sourceLineNo">447</span>   *<a name="line.447"></a>
-<span class="sourceLineNo">448</span>   * @param cacheKey block's cache key<a name="line.448"></a>
-<span class="sourceLineNo">449</span>   * @param buf      block buffer<a name="line.449"></a>
-<span class="sourceLineNo">450</span>   */<a name="line.450"></a>
-<span class="sourceLineNo">451</span>  @Override<a name="line.451"></a>
-<span class="sourceLineNo">452</span>  public void cacheBlock(BlockCacheKey cacheKey, Cacheable buf) {<a name="line.452"></a>
-<span class="sourceLineNo">453</span>    cacheBlock(cacheKey, buf, false);<a name="line.453"></a>
-<span class="sourceLineNo">454</span>  }<a name="line.454"></a>
-<span class="sourceLineNo">455</span><a name="line.455"></a>
-<span class="sourceLineNo">456</span>  /**<a name="line.456"></a>
-<span class="sourceLineNo">457</span>   * Helper function that updates the local size counter and also updates any<a name="line.457"></a>
-<span class="sourceLineNo">458</span>   * per-cf or per-blocktype metrics it can discern from given<a name="line.458"></a>
-<span class="sourceLineNo">459</span>   * {@link LruCachedBlock}<a name="line.459"></a>
-<span class="sourceLineNo">460</span>   */<a name="line.460"></a>
-<span class="sourceLineNo">461</span>  private long updateSizeMetrics(LruCachedBlock cb, boolean evict) {<a name="line.461"></a>
-<span class="sourceLineNo">462</span>    long heapsize = cb.heapSize();<a name="line.462"></a>
-<span class="sourceLineNo">463</span>    BlockType bt = cb.getBuffer().getBlockType();<a name="line.463"></a>
-<span class="sourceLineNo">464</span>    if (evict) {<a name="line.464"></a>
-<span class="sourceLineNo">465</span>      heapsize *= -1;<a name="line.465"></a>
-<span class="sourceLineNo">466</span>    }<a name="line.466"></a>
-<span class="sourceLineNo">467</span>    if (bt != null &amp;&amp; bt.isData()) {<a name="line.467"></a>
-<span class="sourceLineNo">468</span>       dataBlockSize.add(heapsize);<a name="line.468"></a>
-<span class="sourceLineNo">469</span>    }<a name="line.469"></a>
-<span class="sourceLineNo">470</span>    return size.addAndGet(heapsize);<a name="line.470"></a>
-<span class="sourceLineNo">471</span>  }<a name="line.471"></a>
-<span class="sourceLineNo">472</span><a name="line.472"></a>
-<span class="sourceLineNo">473</span>  /**<a name="line.473"></a>
-<span class="sourceLineNo">474</span>   * Get the buffer of the block with the specified name.<a name="line.474"></a>
-<span class="sourceLineNo">475</span>   *<a name="line.475"></a>
-<span class="sourceLineNo">476</span>   * @param cacheKey           block's cache key<a name="line.476"></a>
-<span class="sourceLineNo">477</span>   * @param caching            true if the caller caches blocks on cache misses<a name="line.477"></a>
-<span class="sourceLineNo">478</span>   * @param repeat             Whether this is a repeat lookup for the same block<a name="line.478"></a>
-<span class="sourceLineNo">479</span>   *                           (used to avoid double counting cache misses when doing double-check<a name="line.479"></a>
-<span class="sourceLineNo">480</span>   *                           locking)<a name="line.480"></a>
-<span class="sourceLineNo">481</span>   * @param updateCacheMetrics Whether to update cache metrics or not<a name="line.481"></a>
-<span class="sourceLineNo">482</span>   *<a name="line.482"></a>
-<span class="sourceLineNo">483</span>   * @return buffer of specified cache key, or null if not in cache<a name="line.483"></a>
-<span class="sourceLineNo">484</span>   */<a name="line.484"></a>
-<span class="sourceLineNo">485</span>  @Override<a name="line.485"></a>
-<span class="sourceLineNo">486</span>  public Cacheable getBlock(BlockCacheKey cacheKey, boolean caching, boolean repeat,<a name="line.486"></a>
-<span class="sourceLineNo">487</span>      boolean updateCacheMetrics) {<a name="line.487"></a>
-<span class="sourceLineNo">488</span>    LruCachedBlock cb = map.get(cacheKey);<a name="line.488"></a>
-<span class="sourceLineNo">489</span>    if (cb == null) {<a name="line.489"></a>
-<span class="sourceLineNo">490</span>      if (!repeat &amp;&amp; updateCacheMetrics) {<a name="line.490"></a>
-<span class="sourceLineNo">491</span>        stats.miss(caching, cacheKey.isPrimary(), cacheKey.getBlockType());<a name="line.491"></a>
-<span class="sourceLineNo">492</span>      }<a name="line.492"></a>
-<span class="sourceLineNo">493</span>      // If there is another block cache then try and read there.<a name="line.493"></a>
-<span class="sourceLineNo">494</span>      // However if this is a retry ( second time in double checked locking )<a name="line.494"></a>
-<span class="sourceLineNo">495</span>      // And it's already a miss then the l2 will also be a miss.<a name="line.495"></a>
-<span class="sourceLineNo">496</span>      if (victimHandler != null &amp;&amp; !repeat) {<a name="line.496"></a>
-<span class="sourceLineNo">497</span>        Cacheable result = victimHandler.getBlock(cacheKey, caching, repeat, updateCacheMetrics);<a name="line.497"></a>
-<span class="sourceLineNo">498</span><a name="line.498"></a>
-<span class="sourceLineNo">499</span>        // Promote this to L1.<a name="line.499"></a>
-<span class="sourceLineNo">500</span>        if (result != null &amp;&amp; caching) {<a name="line.500"></a>
-<span class="sourceLineNo">501</span>          if (result instanceof HFileBlock &amp;&amp; ((HFileBlock) result).usesSharedMemory()) {<a name="line.501"></a>
-<span class="sourceLineNo">502</span>            result = ((HFileBlock) result).deepClone();<a name="line.502"></a>
-<span class="sourceLineNo">503</span>          }<a name="line.503"></a>
-<span class="sourceLineNo">504</span>          cacheBlock(cacheKey, result, /* inMemory = */ false);<a name="line.504"></a>
-<span class="sourceLineNo">505</span>        }<a name="line.505"></a>
-<span class="sourceLineNo">506</span>        return result;<a name="line.506"></a>
-<span class="sourceLineNo">507</span>      }<a name="line.507"></a>
-<span class="sourceLineNo">508</span>      return null;<a name="line.508"></a>
-<span class="sourceLineNo">509</span>    }<a name="line.509"></a>
-<span class="sourceLineNo">510</span>    if (updateCacheMetrics) stats.hit(caching, cacheKey.isPrimary(), cacheKey.getBlockType());<a name="line.510"></a>
-<span class="sourceLineNo">511</span>    cb.access(count.incrementAndGet());<a name="line.511"></a>
-<span class="sourceLineNo">512</span>    return cb.getBuffer();<a name="line.512"></a>
-<span class="sourceLineNo">513</span>  }<a name="line.513"></a>
-<span class="sourceLineNo">514</span><a name="line.514"></a>
-<span class="sourceLineNo">515</span>  /**<a name="line.515"></a>
-<span class="sourceLineNo">516</span>   * Whether the cache contains block with specified cacheKey<a name="line.516"></a>
-<span class="sourceLineNo">517</span>   *<a name="line.517"></a>
-<span class="sourceLineNo">518</span>   * @return true if contains the block<a name="line.518"></a>
-<span class="sourceLineNo">519</span>   */<a name="line.519"></a>
-<span class="sourceLineNo">520</span>  public boolean containsBlock(BlockCacheKey cacheKey) {<a name="line.520"></a>
-<span class="sourceLineNo">521</span>    return map.containsKey(cacheKey);<a name="line.521"></a>
-<span class="sourceLineNo">522</span>  }<a name="line.522"></a>
-<span class="sourceLineNo">523</span><a name="line.523"></a>
-<span class="sourceLineNo">524</span>  @Override<a name="line.524"></a>
-<span class="sourceLineNo">525</span>  public boolean evictBlock(BlockCacheKey cacheKey) {<a name="line.525"></a>
-<span class="sourceLineNo">526</span>    LruCachedBlock cb = map.get(cacheKey);<a name="line.526"></a>
-<span class="sourceLineNo">527</span>    return cb != null &amp;&amp; evictBlock(cb, false) &gt; 0;<a name="line.527"></a>
-<span class="sourceLineNo">528</span>  }<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>   * Evicts all blocks for a specific HFile. This is an<a name="line.531"></a>
-<span class="sourceLineNo">532</span>   * expensive operation implemented as a linear-time search through all blocks<a name="line.532"></a>
-<span class="sourceLineNo">533</span>   * in the cache. Ideally this should be a search in a log-access-time map.<a name="line.533"></a>
-<span class="sourceLineNo">534</span>   *<a name="line.534"></a>
-<span class="sourceLineNo">535</span>   * &lt;p&gt;<a name="line.535"></a>
-<span class="sourceLineNo">536</span>   * This is used for evict-on-close to remove all blocks of a specific HFile.<a name="line.536"></a>
-<span class="sourceLineNo">537</span>   *<a name="line.537"></a>
-<span class="sourceLineNo">538</span>   * @return the number of blocks evicted<a name="line.538"></a>
-<span class="sourceLineNo">539</span>   */<a name="line.539"></a>
-<span class="sourceLineNo">540</span>  @Override<a name="line.540"></a>
-<span class="sourceLineNo">541</span>  public int evictBlocksByHfileName(String hfileName) {<a name="line.541"></a>
-<span class="sourceLineNo">542</span>    int numEvicted = 0;<a name="line.542"></a>
-<span class="sourceLineNo">543</span>    for (BlockCacheKey key : map.keySet()) {<a name="line.543"></a>
-<span class="sourceLineNo">544</span>      if (key.getHfileName().equals(hfileName)) {<a name="line.544"></a>
-<span class="sourceLineNo">545</span>        if (evictBlock(key))<a name="line.545"></a>
-<span class="sourceLineNo">546</span>          ++numEvicted;<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>    if (victimHandler != null) {<a name="line.549"></a>
-<span class="sourceLineNo">550</span>      numEvicted += victimHandler.evictBlocksByHfileName(hfileName);<a name="line.550"></a>
-<span class="sourceLineNo">551</span>    }<a name="line.551"></a>
-<span class="sourceLineNo">552</span>    return numEvicted;<a name="line.552"></a>
-<span class="sourceLineNo">553</span>  }<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>   * Evict the block, and it will be cached by the victim handler if exists &amp;amp;&amp;amp;<a name="line.556"></a>
-<span class="sourceLineNo">557</span>   * block may be read again later<a name="line.557"></a>
-<span class="sourceLineNo">558</span>   *<a name="line.558"></a>
-<span class="sourceLineNo">559</span>   * @param evictedByEvictionProcess true if the given block is evicted by<a name="line.559"></a>
-<span class="sourceLineNo">560</span>   *          EvictionThread<a name="line.560"></a>
-<span class="sourceLineNo">561</span>   * @return the heap size of evicted block<a name="line.561"></a>
-<span class="sourceLineNo">562</span>   */<a name="line.562"></a>
-<span class="sourceLineNo">563</span>  protected long evictBlock(LruCachedBlock block, boolean evictedByEvictionProcess) {<a name="line.563"></a>
-<span class="sourceLineNo">564</span>    boolean found = map.remove(block.getCacheKey()) != null;<a name="line.564"></a>
-<span class="sourceLineNo">565</span>    if (!found) {<a name="line.565"></a>
-<span class="sourceLineNo">566</span>      return 0;<a name="line.566"></a>
-<span class="sourceLineNo">567</span>    }<a name="line.567"></a>
-<span class="sourceLineNo">568</span>    updateSizeMetrics(block, true);<a name="line.568"></a>
-<span class="sourceLineNo">569</span>    long val = elements.decrementAndGet();<a name="line.569"></a>
-<span class="sourceLineNo">570</span>    if (LOG.isTraceEnabled()) {<a name="line.570"></a>
-<span class="sourceLineNo">571</span>      long size = map.size();<a name="line.571"></a>
-<span class="sourceLineNo">572</span>      assertCounterSanity(size, val);<a name="line.572"></a>
-<span class="sourceLineNo">573</span>    }<a name="line.573"></a>
-<span class="sourceLineNo">574</span>    if (block.getBuffer().getBlockType().isData()) {<a name="line.574"></a>
-<span class="sourceLineNo">575</span>       dataBlockElements.decrement();<a name="line.575"></a>
-<span class="sourceLineNo">576</span>    }<a name="line.576"></a>
-<span class="sourceLineNo">577</span>    if (evictedByEvictionProcess) {<a name="line.577"></a>
-<span class="sourceLineNo">578</span>      // When the eviction of the block happened because of invalidation of HFiles, no need to<a name="line.578"></a>
-<span class="sourceLineNo">579</span>      // update the stats counter.<a name="line.579"></a>
-<span class="sourceLineNo">580</span>      stats.evicted(block.getCachedTime(), block.getCacheKey().isPrimary());<a name="line.580"></a>
-<span class="sourceLineNo">581</span>      if (victimHandler != null) {<a name="line.581"></a>
-<span class="sourceLineNo">582</span>        victimHandler.cacheBlock(block.getCacheKey(), block.getBuffer());<a name="line.582"></a>
-<span class="sourceLineNo">583</span>      }<a name="line.583"></a>
-<span class="sourceLineNo">584</span>    }<a name="line.584"></a>
-<span class="sourceLineNo">585</span>    return block.heapSize();<a name="line.585"></a>
-<span class="sourceLineNo">586</span>  }<a name="line.586"></a>
-<span class="sourceLineNo">587</span><a name="line.587"></a>
-<span class="sourceLineNo">588</span>  /**<a name="line.588"></a>
-<span class="sourceLineNo">589</span>   * Multi-threaded call to run the eviction process.<a name="line.589"></a>
-<span class="sourceLineNo">590</span>   */<a name="line.590"></a>
-<span class="sourceLineNo">591</span>  private void runEviction() {<a name="line.591"></a>
-<span class="sourceLineNo">592</span>    if (evictionThread == null) {<a name="line.592"></a>
-<span class="sourceLineNo">593</span>      evict();<a name="line.593"></a>
-<span class="sourceLineNo">594</span>    } else {<a name="line.594"></a>
-<span class="sourceLineNo">595</span>      evictionThread.evict();<a name="line.595"></a>
-<span class="sourceLineNo">596</span>    }<a name="line.596"></a>
-<span class="sourceLineNo">597</span>  }<a name="line.597"></a>
-<span class="sourceLineNo">598</span><a name="line.598"></a>
-<span class="sourceLineNo">599</span>  @VisibleForTesting<a name="line.599"></a>
-<span class="sourceLineNo">600</span>  boolean isEvictionInProgress() {<a name="line.600"></a>
-<span class="sourceLineNo">601</span>    return evictionInProgress;<a name="line.601"></a>
+<span class="sourceLineNo">383</span>      int comparison = BlockCacheUtil.validateBlockAddition(cb.getBuffer(), buf, cacheKey);<a name="line.383"></a>
+<span class="sourceLineNo">384</span>      if (comparison != 0) {<a name="line.384"></a>
+<span class="sourceLineNo">385</span>        if (comparison &lt; 0) {<a name="line.385"></a>
+<span class="sourceLineNo">386</span>          LOG.warn("Cached block contents differ by nextBlockOnDiskSize. Keeping cached block.");<a name="line.386"></a>
+<span class="sourceLineNo">387</span>          return;<a name="line.387"></a>
+<span class="sourceLineNo">388</span>        } else {<a name="line.388"></a>
+<span class="sourceLineNo">389</span>          LOG.warn("Cached block contents differ by nextBlockOnDiskSize. Caching new block.");<a name="line.389"></a>
+<span class="sourceLineNo">390</span>        }<a name="line.390"></a>
+<span class="sourceLineNo">391</span>      } else {<a name="line.391"></a>
+<span class="sourceLineNo">392</span>        String msg = "Cached an already cached block: " + cacheKey + " cb:" + cb.getCacheKey();<a name="line.392"></a>
+<span class="sourceLineNo">393</span>        msg += ". This is harmless and can happen in rare cases (see HBASE-8547)";<a name="line.393"></a>
+<span class="sourceLineNo">394</span>        LOG.warn(msg);<a name="line.394"></a>
+<span class="sourceLineNo">395</span>        return;<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>    long currentSize = size.get();<a name="line.398"></a>
+<span class="sourceLineNo">399</span>    long currentAcceptableSize = acceptableSize();<a name="line.399"></a>
+<span class="sourceLineNo">400</span>    long hardLimitSize = (long) (hardCapacityLimitFactor * currentAcceptableSize);<a name="line.400"></a>
+<span class="sourceLineNo">401</span>    if (currentSize &gt;= hardLimitSize) {<a name="line.401"></a>
+<span class="sourceLineNo">402</span>      stats.failInsert();<a name="line.402"></a>
+<span class="sourceLineNo">403</span>      if (LOG.isTraceEnabled()) {<a name="line.403"></a>
+<span class="sourceLineNo">404</span>        LOG.trace("LruBlockCache current size " + StringUtils.byteDesc(currentSize)<a name="line.404"></a>
+<span class="sourceLineNo">405</span>          + " has exceeded acceptable size " + StringUtils.byteDesc(currentAcceptableSize) + "."<a name="line.405"></a>
+<span class="sourceLineNo">406</span>          + " The hard limit size is " + StringUtils.byteDesc(hardLimitSize)<a name="line.406"></a>
+<span class="sourceLineNo">407</span>          + ", failed to put cacheKey:" + cacheKey + " into LruBlockCache.");<a name="line.407"></a>
+<span class="sourceLineNo">408</span>      }<a name="line.408"></a>
+<span class="sourceLineNo">409</span>      if (!evictionInProgress) {<a name="line.409"></a>
+<span class="sourceLineNo">410</span>        runEviction();<a name="line.410"></a>
+<span class="sourceLineNo">411</span>      }<a name="line.411"></a>
+<span class="sourceLineNo">412</span>      return;<a name="line.412"></a>
+<span class="sourceLineNo">413</span>    }<a name="line.413"></a>
+<span class="sourceLineNo">414</span>    cb = new LruCachedBlock(cacheKey, buf, count.incrementAndGet(), inMemory);<a name="line.414"></a>
+<span class="sourceLineNo">415</span>    long newSize = updateSizeMetrics(cb, false);<a name="line.415"></a>
+<span class="sourceLineNo">416</span>    map.put(cacheKey, cb);<a name="line.416"></a>
+<span class="sourceLineNo">417</span>    long val = elements.incrementAndGet();<a name="line.417"></a>
+<span class="sourceLineNo">418</span>    if (buf.getBlockType().isData()) {<a name="line.418"></a>
+<span class="sourceLineNo">419</span>       dataBlockElements.increment();<a name="line.419"></a>
+<span class="sourceLineNo">420</span>    }<a name="line.420"></a>
+<span class="sourceLineNo">421</span>    if (LOG.isTraceEnabled()) {<a name="line.421"></a>
+<span class="sourceLineNo">422</span>      long size = map.size();<a name="line.422"></a>
+<span class="sourceLineNo">423</span>      assertCounterSanity(size, val);<a name="line.423"></a>
+<span class="sourceLineNo">424</span>    }<a name="line.424"></a>
+<span class="sourceLineNo">425</span>    if (newSize &gt; currentAcceptableSize &amp;&amp; !evictionInProgress) {<a name="line.425"></a>
+<span class="sourceLineNo">426</span>      runEviction();<a name="line.426"></a>
+<span class="sourceLineNo">427</span>    }<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>   * Sanity-checking for parity between actual block cache content and metrics.<a name="line.431"></a>
+<span class="sourceLineNo">432</span>   * Intended only for use with TRACE level logging and -ea JVM.<a name="line.432"></a>
+<span class="sourceLineNo">433</span>   */<a name="line.433"></a>
+<span class="sourceLineNo">434</span>  private static void assertCounterSanity(long mapSize, long counterVal) {<a name="line.434"></a>
+<span class="sourceLineNo">435</span>    if (counterVal &lt; 0) {<a name="line.435"></a>
+<span class="sourceLineNo">436</span>      LOG.trace("counterVal overflow. Assertions unreliable. counterVal=" + counterVal +<a name="line.436"></a>
+<span class="sourceLineNo">437</span>        ", mapSize=" + mapSize);<a name="line.437"></a>
+<span class="sourceLineNo">438</span>      return;<a name="line.438"></a>
+<span class="sourceLineNo">439</span>    }<a name="line.439"></a>
+<span class="sourceLineNo">440</span>    if (mapSize &lt; Integer.MAX_VALUE) {<a name="line.440"></a>
+<span class="sourceLineNo">441</span>      double pct_diff = Math.abs((((double) counterVal) / ((double) mapSize)) - 1.);<a name="line.441"></a>
+<span class="sourceLineNo">442</span>      if (pct_diff &gt; 0.05) {<a name="line.442"></a>
+<span class="sourceLineNo">443</span>        LOG.trace("delta between reported and actual size &gt; 5%. counterVal=" + counterVal +<a name="line.443"></a>
+<span class="sourceLineNo">444</span>          ", mapSize=" + mapSize);<a name="line.444"></a>
+<span class="sourceLineNo">445</span>      }<a name="line.445"></a>
+<span class="sourceLineNo">446</span>    }<a name="line.446"></a>
+<span class="sourceLineNo">447</span>  }<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>   * Cache the block with the specified name and buffer.<a name="line.450"></a>
+<span class="sourceLineNo">451</span>   * &lt;p&gt;<a name="line.451"></a>
+<span class="sourceLineNo">452</span>   *<a name="line.452"></a>
+<span class="sourceLineNo">453</span>   * @param cacheKey block's cache key<a name="line.453"></a>
+<span class="sourceLineNo">454</span>   * @param buf      block buffer<a name="line.454"></a>
+<span class="sourceLineNo">455</span>   */<a name="line.455"></a>
+<span class="sourceLineNo">456</span>  @Override<a name="line.456"></a>
+<span class="sourceLineNo">457</span>  public void cacheBlock(BlockCacheKey cacheKey, Cacheable buf) {<a name="line.457"></a>
+<span class="sourceLineNo">458</span>    cacheBlock(cacheKey, buf, false);<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>  /**<a name="line.461"></a>
+<span class="sourceLineNo">462</span>   * Helper function that updates the local size counter and also updates any<a name="line.462"></a>
+<span class="sourceLineNo">463</span>   * per-cf or per-blocktype metrics it can discern from given<a name="line.463"></a>
+<span class="sourceLineNo">464</span>   * {@link LruCachedBlock}<a name="line.464"></a>
+<span class="sourceLineNo">465</span>   */<a name="line.465"></a>
+<span class="sourceLineNo">466</span>  private long updateSizeMetrics(LruCachedBlock cb, boolean evict) {<a name="line.466"></a>
+<span class="sourceLineNo">467</span>    long heapsize = cb.heapSize();<a name="line.467"></a>
+<span class="sourceLineNo">468</span>    BlockType bt = cb.getBuffer().getBlockType();<a name="line.468"></a>
+<span class="sourceLineNo">469</span>    if (evict) {<a name="line.469"></a>
+<span class="sourceLineNo">470</span>      heapsize *= -1;<a name="line.470"></a>
+<span class="sourceLineNo">471</span>    }<a name="line.471"></a>
+<span class="sourceLineNo">472</span>    if (bt != null &amp;&amp; bt.isData()) {<a name="line.472"></a>
+<span class="sourceLineNo">473</span>       dataBlockSize.add(heapsize);<a name="line.473"></a>
+<span class="sourceLineNo">474</span>    }<a name="line.474"></a>
+<span class="sourceLineNo">475</span>    return size.addAndGet(heapsize);<a name="line.475"></a>
+<span class="sourceLineNo">476</span>  }<a name="line.476"></a>
+<span class="sourceLineNo">477</span><a name="line.477"></a>
+<span class="sourceLineNo">478</span>  /**<a name="line.478"></a>
+<span class="sourceLineNo">479</span>   * Get the buffer of the block with the specified name.<a name="line.479"></a>
+<span class="sourceLineNo">480</span>   *<a name="line.480"></a>
+<span class="sourceLineNo">481</span>   * @param cacheKey           block's cache key<a name="line.481"></a>
+<span class="sourceLineNo">482</span>   * @param caching            true if the caller caches blocks on cache misses<a name="line.482"></a>
+<span class="sourceLineNo">483</span>   * @param repeat             Whether this is a repeat lookup for the same block<a name="line.483"></a>
+<span class="sourceLineNo">484</span>   *                           (used to avoid double counting cache misses when doing double-check<a name="line.484"></a>
+<span class="sourceLineNo">485</span>   *                           locking)<a name="line.485"></a>
+<span class="sourceLineNo">486</span>   * @param updateCacheMetrics Whether to update cache metrics or not<a name="line.486"></a>
+<span class="sourceLineNo">487</span>   *<a name="line.487"></a>
+<span class="sourceLineNo">488</span>   * @return buffer of specified cache key, or null if not in cache<a name="line.488"></a>
+<span class="sourceLineNo">489</span>   */<a name="line.489"></a>
+<span class="sourceLineNo">490</span>  @Override<a name="line.490"></a>
+<span class="sourceLineNo">491</span>  public Cacheable getBlock(BlockCacheKey cacheKey, boolean caching, boolean repeat,<a name="line.491"></a>
+<span class="sourceLineNo">492</span>      boolean updateCacheMetrics) {<a name="line.492"></a>
+<span class="sourceLineNo">493</span>    LruCachedBlock cb = map.get(cacheKey);<a name="line.493"></a>
+<span class="sourceLineNo">494</span>    if (cb == null) {<a name="line.494"></a>
+<span class="sourceLineNo">495</span>      if (!repeat &amp;&amp; updateCacheMetrics) {<a name="line.495"></a>
+<span class="sourceLineNo">496</span>        stats.miss(caching, cacheKey.isPrimary(), cacheKey.getBlockType());<a name="line.496"></a>
+<span class="sourceLineNo">497</span>      }<a name="line.497"></a>
+<span class="sourceLineNo">498</span>      // If there is another block cache then try and read there.<a name="line.498"></a>
+<span class="sourceLineNo">499</span>      // However if this is a retry ( second time in double checked locking )<a name="line.499"></a>
+<span class="sourceLineNo">500</span>      // And it's already a miss then the l2 will also be a miss.<a name="line.500"></a>
+<span class="sourceLineNo">501</span>      if (victimHandler != null &amp;&amp; !repeat) {<a name="line.501"></a>
+<span class="sourceLineNo">502</span>        Cacheable result = victimHandler.getBlock(cacheKey, caching, repeat, updateCacheMetrics);<a name="line.502"></a>
+<span class="sourceLineNo">503</span><a name="line.503"></a>
+<span class="sourceLineNo">504</span>        // Promote this to L1.<a name="line.504"></a>
+<span class="sourceLineNo">505</span>        if (result != null &amp;&amp; caching) {<a name="line.505"></a>
+<span class="sourceLineNo">506</span>          if (result instanceof HFileBlock &amp;&amp; ((HFileBlock) result).usesSharedMemory()) {<a name="line.506"></a>
+<span class="sourceLineNo">507</span>            result = ((HFileBlock) result).deepClone();<a name="line.507"></a>
+<span class="sourceLineNo">508</span>          }<a name="line.508"></a>
+<span class="sourceLineNo">509</span>          cacheBlock(cacheKey, result, /* inMemory = */ false);<a name="line.509"></a>
+<span class="sourceLineNo">510</span>        }<a name="line.510"></a>
+<span class="sourceLineNo">511</span>        return result;<a name="line.511"></a>
+<span class="sourceLineNo">512</span>      }<a name="line.512"></a>
+<span class="sourceLineNo">513</span>      return null;<a name="line.513"></a>
+<span class="sourceLineNo">514</span>    }<a name="line.514"></a>
+<span class="sourceLineNo">515</span>    if (updateCacheMetrics) stats.hit(caching, cacheKey.isPrimary(), cacheKey.getBlockType());<a name="line.515"></a>
+<span class="sourceLineNo">516</span>    cb.access(count.incrementAndGet());<a name="line.516"></a>
+<span class="sourceLineNo">517</span>    return cb.getBuffer();<a name="line.517"></a>
+<span class="sourceLineNo">518</span>  }<a name="line.518"></a>
+<span class="sourceLineNo">519</span><a name="line.519"></a>
+<span class="sourceLineNo">520</span>  /**<a name="line.520"></a>
+<span class="sourceLineNo">521</span>   * Whether the cache contains block with specified cacheKey<a name="line.521"></a>
+<span class="sourceLineNo">522</span>   *<a name="line.522"></a>
+<span class="sourceLineNo">523</span>   * @return true if contains the block<a name="line.523"></a>
+<span class="sourceLineNo">524</span>   */<a name="line.524"></a>
+<span class="sourceLineNo">525</span>  public boolean containsBlock(BlockCacheKey cacheKey) {<a name="line.525"></a>
+<span class="sourceLineNo">526</span>    return map.containsKey(cacheKey);<a name="line.526"></a>
+<span class="sourceLineNo">527</span>  }<a name="line.527"></a>
+<span class="sourceLineNo">528</span><a name="line.528"></a>
+<span class="sourceLineNo">529</span>  @Override<a name="line.529"></a>
+<span class="sourceLineNo">530</span>  public boolean evictBlock(BlockCacheKey cacheKey) {<a name="line.530"></a>
+<span class="sourceLineNo">531</span>    LruCachedBlock cb = map.get(cacheKey);<a name="line.531"></a>
+<span class="sourceLineNo">532</span>    return cb != null &amp;&amp; evictBlock(cb, false) &gt; 0;<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>   * Evicts all blocks for a specific HFile. This is an<a name="line.536"></a>
+<span class="sourceLineNo">537</span>   * expensive operation implemented as a linear-time search through all blocks<a name="line.537"></a>
+<span class="sourceLineNo">538</span>   * in the cache. Ideally this should be a search in a log-access-time map.<a name="line.538"></a>
+<span class="sourceLineNo">539</span>   *<a name="line.539"></a>
+<span class="sourceLineNo">540</span>   * &lt;p&gt;<a name="line.540"></a>
+<span class="sourceLineNo">541</span>   * This is used for evict-on-close to remove all blocks of a specific HFile.<a name="line.541"></a>
+<span class="sourceLineNo">542</span>   *<a name="line.542"></a>
+<span class="sourceLineNo">543</span>   * @return the number of blocks evicted<a name="line.543"></a>
+<span class="sourceLineNo">544</span>   */<a name="line.544"></a>
+<span class="sourceLineNo">545</span>  @Override<a name="line.545"></a>
+<span class="sourceLineNo">546</span>  public int evictBlocksByHfileName(String hfileName) {<a name="line.546"></a>
+<span class="sourceLineNo">547</span>    int numEvicted = 0;<a name="line.547"></a>
+<span class="sourceLineNo">548</span>    for (BlockCacheKey key : map.keySet()) {<a name="line.548"></a>
+<span class="sourceLineNo">549</span>      if (key.getHfileName().equals(hfileName)) {<a name="line.549"></a>
+<span class="sourceLineNo">550</span>        if (evictBlock(key))<a name="line.550"></a>
+<span class="sourceLineNo">551</span>          ++numEvicted;<a name="line.551"></a>
+<span class="sourceLineNo">552</span>      }<a name="line.552"></a>
+<span class="sourceLineNo">553</span>    }<a name="line.553"></a>
+<span class="sourceLineNo">554</span>    if (victimHandler != null) {<a name="line.554"></a>
+<span class="sourceLineNo">555</span>      numEvicted += victimHandler.evictBlocksByHfileName(hfileName);<a name="line.555"></a>
+<span class="sourceLineNo">556</span>    }<a name="line.556"></a>
+<span class="sourceLineNo">557</span>    return numEvicted;<a name="line.557"></a>
+<span class="sourceLineNo">558</span>  }<a name="line.558"></a>
+<span class="sourceLineNo">559</span><a name="line.559"></a>
+<span class="sourceLineNo">560</span>  /**<a name="line.560"></a>
+<span class="sourceLineNo">561</span>   * Evict the block, and it will be cached by the victim handler if exists &amp;amp;&amp;amp;<a name="line.561"></a>
+<span class="sourceLineNo">562</span>   * block may be read again later<a name="line.562"></a>
+<span class="sourceLineNo">563</span>   *<a name="line.563"></a>
+<span class="sourceLineNo">564</span>   * @param evictedByEvictionProcess true if the given block is evicted by<a name="line.564"></a>
+<span class="sourceLineNo">565</span>   *          EvictionThread<a name="line.565"></a>
+<span class="sourceLineNo">566</span>   * @return the heap size of evicted block<a name="line.566"></a>
+<span class="sourceLineNo">567</span>   */<a name="line.567"></a>
+<span class="sourceLineNo">568</span>  protected long evictBlock(LruCachedBlock block, boolean evictedByEvictionProcess) {<a name="line.568"></a>
+<span class="sourceLineNo">569</span>    boolean found = map.remove(block.getCacheKey()) != null;<a name="line.569"></a>
+<span class="sourceLineNo">570</span>    if (!found) {<a name="line.570"></a>
+<span class="sourceLineNo">571</span>      return 0;<a name="line.571"></a>
+<span class="sourceLineNo">572</span>    }<a name="line.572"></a>
+<span class="sourceLineNo">573</span>    updateSizeMetrics(block, true);<a name="line.573"></a>
+<span class="sourceLineNo">574</span>    long val = elements.decrementAndGet();<a name="line.574"></a>
+<span class="sourceLineNo">575</span>    if (LOG.isTraceEnabled()) {<a name="line.575"></a>
+<span class="sourceLineNo">576</span>      long size = map.size();<a name="line.576"></a>
+<span class="sourceLineNo">577</span>      assertCounterSanity(size, val);<a name="line.577"></a>
+<span class="sourceLineNo">578</span>    }<a name="line.578"></a>
+<span class="sourceLineNo">579</span>    if (block.getBuffer().getBlockType().isData()) {<a name="line.579"></a>
+<span class="sourceLineNo">580</span>       dataBlockElements.decrement();<a name="line.580"></a>
+<span class="sourceLineNo">581</span>    }<a name="line.581"></a>
+<span class="sourceLineNo">582</span>    if (evictedByEvictionProcess) {<a name="line.582"></a>
+<span class="sourceLineNo">583</span>      // When the eviction of the block happened because of invalidation of HFiles, no need to<a name="line.583"></a>
+<span class="sourceLineNo">584</span>      // update the stats counter.<a name="line.584"></a>
+<span class="sourceLineNo">585</span>      stats.evicted(block.getCachedTime(), block.getCacheKey().isPrimary());<a name="line.585"></a>
+<span class="sourceLineNo">586</span>      if (victimHandler != null) {<a name="line.586"></a>
+<span class="sourceLineNo">587</span>        victimHandler.cacheBlock(block.getCacheKey(), block.getBuffer());<a name="line.587"></a>
+<span class="sourceLineNo">588</span>      }<a name="line.588"></a>
+<span class="sourceLineNo">589</span>    }<a name="line.589"></a>
+<span class="sourceLineNo">590</span>    return block.heapSize();<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>   * Multi-threaded call to run the eviction process.<a name="line.594"></a>
+<span class="sourceLineNo">595</span>   */<a name="line.595"></a>
+<span class="sourceLineNo">596</span>  private void runEviction() {<a name="line.596"></a>
+<span class="sourceLineNo">597</span>    if (evictionThread == null) {<a name="line.597"></a>
+<span class="sourceLineNo">598</span>      evict();<a name="line.598"></a>
+<span class="sourceLineNo">599</span>    } else {<a name="line.599"></a>
+<span class="sourceLineNo">600</span>      evictionThread.evict();<a name="line.600"></a>
+<span class="sourceLineNo">601</span>    }<a name="line.601"></a>
 <span class="sourceLineNo">602</span>  }<a name="line.602"></a>
 <span class="sourceLineNo">603</span><a name="line.603"></a>
 <span class="sourceLineNo">604</span>  @VisibleForTesting<a name="line.604"></a>
-<span class="sourceLineNo">605</span>  long getOverhead() {<a name="line.605"></a>
-<span class="sourceLineNo">606</span>    return overhead;<a name="line.606"></a>
+<span class="sourceLineNo">605</span>  boolean isEvictionInProgress() {<a name="line.605"></a>
+<span class="sourceLineNo">606</span>    return evictionInProgress;<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>   * Eviction method.<a name="line.610"></a>
-<span class="sourceLineNo">611</span>   */<a name="line.611"></a>
-<span class="sourceLineNo">612</span>  void evict() {<a name="line.612"></a>
+<span class="sourceLineNo">609</span>  @VisibleForTesting<a name="line.609"></a>
+<span class="sourceLineNo">610</span>  long getOverhead() {<a name="line.610"></a>
+<span class="sourceLineNo">611</span>    return overhead;<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>    // Ensure only one eviction at a time<a name="line.614"></a>
-<span class="sourceLineNo">615</span>    if(!evictionLock.tryLock()) return;<a name="line.615"></a>
-<span class="sourceLineNo">616</span><a name="line.616"></a>
-<span class="sourceLineNo">617</span>    try {<a name="line.617"></a>
-<span class="sourceLineNo">618</span>      evictionInProgress = true;<a name="line.618"></a>
-<span class="sourceLineNo">619</span>      long currentSize = this.size.get();<a name="line.619"></a>
-<span class="sourceLineNo">620</span>      long bytesToFree = currentSize - minSize();<a name="line.620"></a>
+<span class="sourceLineNo">614</span>  /**<a name="line.614"></a>
+<span class="sourceLineNo">615</span>   * Eviction method.<a name="line.615"></a>
+<span class="sourceLineNo">616</span>   */<a name="line.616"></a>
+<span class="sourceLineNo">617</span>  void evict() {<a name="line.617"></a>
+<span class="sourceLineNo">618</span><a name="line.618"></a>
+<span class="sourceLineNo">619</span>    // Ensure only one eviction at a time<a name="line.619"></a>
+<span class="sourceLineNo">620</span>    if(!evictionLock.tryLock()) return;<a name="line.620"></a>
 <span class="sourceLineNo">621</span><a name="line.621"></a>
-<span class="sourceLineNo">622</span>      if (LOG.isTraceEnabled()) {<a name="line.622"></a>
-<span class="sourceLineNo">623</span>        LOG.trace("Block cache LRU eviction started; Attempting to free " +<a name="line.623"></a>
-<span class="sourceLineNo">624</span>          StringUtils.byteDesc(bytesToFree) + " of total=" +<a name="line.624"></a>
-<span class="sourceLineNo">625</span>          StringUtils.byteDesc(currentSize));<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>      if (bytesToFree &lt;= 0) return;<a name="line.628"></a>
-<span class="sourceLineNo">629</span><a name="line.629"></a>
-<span class="sourceLineNo">630</span>      // Instantiate priority buckets<a name="line.630"></a>
-<span class="sourceLineNo">631</span>      BlockBucket bucketSingle = new BlockBucket("single", bytesToFree, blockSize, singleSize());<a name="line.631"></a>
-<span class="sourceLineNo">632</span>      BlockBucket bucketMulti = new BlockBucket("multi", bytesToFree, blockSize, multiSize());<a name="line.632"></a>
-<span class="sourceLineNo">633</span>      BlockBucket bucketMemory = new BlockBucket("memory", bytesToFree, blockSize, memorySize());<a name="line.633"></a>
+<span class="sourceLineNo">622</span>    try {<a name="line.622"></a>
+<span class="sourceLineNo">623</span>      evictionInProgress = true;<a name="line.623"></a>
+<span class="sourceLineNo">624</span>      long currentSize = this.size.get();<a name="line.624"></a>
+<span class="sourceLineNo">625</span>      long bytesToFree = currentSize - minSize();<a name="line.625"></a>
+<span class="sourceLineNo">626</span><a name="line.626"></a>
+<span class="sourceLineNo">627</span>      if (LOG.isTraceEnabled()) {<a name="line.627"></a>
+<span class="sourceLineNo">628</span>        LOG.trace("Block cache LRU eviction started; Attempting to free " +<a name="line.628"></a>
+<span class="sourceLineNo">629</span>          StringUtils.byteDesc(bytesToFree) + " of total=" +<a name="line.629"></a>
+<span class="sourceLineNo">630</span>          StringUtils.byteDesc(currentSize));<a name="line.630"></a>
+<span class="sourceLineNo">631</span>      }<a name="line.631"></a>
+<span class="sourceLineNo">632</span><a name="line.632"></a>
+<span class="sourceLineNo">633</span>      if (bytesToFree &lt;= 0) return;<a name="line.633"></a>
 <span class="sourceLineNo">634</span><a name="line.634"></a>
-<span class="sourceLineNo">635</span>      // Scan entire map putting into appropriate buckets<a name="line.635"></a>
-<span class="sourceLineNo">636</span>      for (LruCachedBlock cachedBlock : map.values()) {<a name="line.636"></a>
-<span class="sourceLineNo">637</span>        switch (cachedBlock.getPriority()) {<a name="line.637"></a>
-<span class="sourceLineNo">638</span>          case SINGLE: {<a name="line.638"></a>
-<span class="sourceLineNo">639</span>            bucketSingle.add(cachedBlock);<a name="line.639"></a>
-<span class="sourceLineNo">640</span>            break;<a name="line.640"></a>
-<span class="sourceLineNo">641</span>          }<a name="line.641"></a>
-<span class="sourceLineNo">642</span>          case MULTI: {<a name="line.642"></a>
-<span class="sourceLineNo">643</span>            bucketMulti.add(cachedBlock);<a name="line.643"></a>
-<span class="sourceLineNo">644</span>            break;<a name="line.644"></a>
-<span class="sourceLineNo">645</span>          }<a name="line.645"></a>
-<span class="sourceLineNo">646</span>          case MEMORY: {<a name="line.646"></a>
-<span class="sourceLineNo">647</span>            bucketMemory.add(cachedBlock);<a name="line.647"></a>
-<span class="sourceLineNo">648</span>            break;<a name="line.648"></a>
-<span class="sourceLineNo">649</span>          }<a name="line.649"></a>
-<span class="sourceLineNo">650</span>        }<a name="line.650"></a>
-<span class="sourceLineNo">651</span>      }<a name="line.651"></a>
-<span class="sourceLineNo">652</span><a name="line.652"></a>
-<span class="sourceLineNo">653</span>      long bytesFreed = 0;<a name="line.653"></a>
-<span class="sourceLineNo">654</span>      if (forceInMemory || memoryFactor &gt; 0.999f) {<a name="line.654"></a>
-<span class="sourceLineNo">655</span>        long s = bucketSingle.totalSize();<a name="line.655"></a>
-<span class="sourceLineNo">656</span>        long m = bucketMulti.totalSize();<a name="line.656"></a>
-<span class="sourceLineNo">657</span>        if (bytesToFree &gt; (s + m)) {<a name="line.657"></a>
-<span class="sourceLineNo">658</span>          // this means we need to evict blocks in memory bucket to make room,<a name="line.658"></a>
-<span class="sourceLineNo">659</span>          // so the single and multi buckets will be emptied<a name="line.659"></a>
-<span class="sourceLineNo">660</span>          bytesFreed = bucketSingle.free(s);<a name="line.660"></a>
-<span class="sourceLineNo">661</span>          bytesFreed += bucketMulti.free(m);<a name="line.661"></a>
-<span class="sourceLineNo">662</span>          if (LOG.isTraceEnabled()) {<a name="line.662"></a>
-<span class="sourceLineNo">663</span>            LOG.trace("freed " + StringUtils.byteDesc(bytesFreed) +<a name="line.663"></a>
-<span class="sourceLineNo">664</span>              " from single and multi buckets");<a name="line.664"></a>
-<span class="sourceLineNo">665</span>          }<a name="line.665"></a>
-<span class="sourceLineNo">666</span>          bytesFreed += bucketMemory.free(bytesToFree - bytesFreed);<a name="line.666"></a>
+<span class="sourceLineNo">635</span>      // Instantiate priority buckets<a name="line.635"></a>
+<span class="sourceLineNo">636</span>      BlockBucket bucketSingle = new BlockBucket("single", bytesToFree, blockSize, singleSize());<a name="line.636"></a>
+<span class="sourceLineNo">637</span>      BlockBucket bucketMulti = new BlockBucket("multi", bytesToFree, blockSize, multiSize());<a name="line.637"></a>
+<span class="sourceLineNo">638</span>      BlockBucket bucketMemory = new BlockBucket("memory", bytesToFree, blockSize, memorySize());<a name="line.638"></a>
+<span class="sourceLineNo">639</span><a name="line.639"></a>
+<span class="sourceLineNo">640</span>      // Scan entire map putting into appropriate buckets<a name="line.640"></a>
+<span class="sourceLineNo">641</span>      for (LruCachedBlock cachedBlock : map.values()) {<a name="line.641"></a>
+<span class="sourceLineNo">642</span>        switch (cachedBlock.getPriority()) {<a name="line.642"></a>
+<span class="sourceLineNo">643</span>          case SINGLE: {<a name="line.643"></a>
+<span class="sourceLineNo">644</span>            bucketSingle.add(cachedBlock);<a name="line.644"></a>
+<span class="sourceLineNo">645</span>            break;<a name="line.645"></a>
+<span class="sourceLineNo">646</span>          }<a name="line.646"></a>
+<span class="sourceLineNo">647</span>          case MULTI: {<a name="line.647"></a>
+<span class="sourceLineNo">648</span>            bucketMulti.add(cachedBlock);<a name="line.648"></a>
+<span class="sourceLineNo">649</span>            break;<a name="line.649"></a>
+<span class="sourceLineNo">650</span>          }<a name="line.650"></a>
+<span class="sourceLineNo">651</span>          case MEMORY: {<a name="line.651"></a>
+<span class="sourceLineNo">652</span>            bucketMemory.add(cachedBlock);<a name="line.652"></a>
+<span class="sourceLineNo">653</span>            break;<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>      }<a name="line.656"></a>
+<span class="sourceLineNo">657</span><a name="line.657"></a>
+<span class="sourceLineNo">658</span>      long bytesFreed = 0;<a name="line.658"></a>
+<span class="sourceLineNo">659</span>      if (forceInMemory || memoryFactor &gt; 0.999f) {<a name="line.659"></a>
+<span class="sourceLineNo">660</span>        long s = bucketSingle.totalSize();<a name="line.660"></a>
+<span class="sourceLineNo">661</span>        long m = bucketMulti.totalSize();<a name="line.661"></a>
+<span class="sourceLineNo">662</span>        if (bytesToFree &gt; (s + m)) {<a name="line.662"></a>
+<span class="sourceLineNo">663</span>          // this means we need to evict blocks in memory bucket to make room,<a name="line.663"></a>
+<span class="sourceLineNo">664</span>          // so the single and multi buckets will be emptied<a name="line.664"></a>
+<span class="sourceLineNo">665</span>          bytesFreed = bucketSingle.free(s);<a name="line.665"></a>
+<span class="sourceLineNo">666</span>          bytesFreed += bucketMulti.free(m);<a name="line.666"></a>
 <span class="sourceLineNo">667</span>          if (LOG.isTraceEnabled()) {<a name="line.667"></a>
 <span class="sourceLineNo">668</span>            LOG.trace("freed " + StringUtils.byteDesc(bytesFreed) +<a name="line.668"></a>
-<span class="sourceLineNo">669</span>              " total from all three buckets ");<a name="line.669"></a>
+<span class="sourceLineNo">669</span>              " from single and multi buckets");<a name="line.669"></a>
 <span class="sourceLineNo">670</span>          }<a name="line.670"></a>
-<span class="sourceLineNo">671</span>        } else {<a name="line.671"></a>
-<span class="sourceLineNo">672</span>          // this means no need to evict block in memory bucket,<a name="line.672"></a>
-<span class="sourceLineNo">673</span>          // and we try best to make the ratio between single-bucket and<a name="line.673"></a>
-<span class="sourceLineNo">674</span>          // multi-bucket is 1:2<a name="line.674"></a>
-<span class="sourceLineNo">675</span>          long bytesRemain = s + m - bytesToFree;<a name="line.675"></a>
-<span class="sourceLineNo">676</span>          if (3 * s &lt;= bytesRemain) {<a name="line.676"></a>
-<span class="sourceLineNo">677</span>            // single-bucket is small enough that no eviction happens for it<a name="line.677"></a>
-<span class="sourceLineNo">678</span>            // hence all eviction goes from multi-bucket<a name="line.678"></a>
-<span class="sourceLineNo">679</span>            bytesFreed = bucketMulti.free(bytesToFree);<a name="line.679"></a>
-<span class="sourceLineNo">680</span>          } else if (3 * m &lt;= 2 * bytesRemain) {<a name="line.680"></a>
-<span class="sourceLineNo">681</span>            // multi-bucket is small enough that no eviction happens for it<a name="line.681"></a>
-<span class="sourceLineNo">682</span>            // hence all eviction goes from single-bucket<a name="line.682"></a>
-<span class="sourceLineNo">683</span>            bytesFreed = bucketSingle.free(bytesToFree);<a name="line.683"></a>
-<span class="sourceLineNo">684</span>          } else {<a name="line.684"></a>
-<span class="sourceLineNo">685</span>            // both buckets need to evict some blocks<a name="line.685"></a>
-<span class="sourceLineNo">686</span>            bytesFreed = bucketSingle.free(s - bytesRemain / 3);<a name="line.686"></a>
-<span class="sourceLineNo">687</span>            if (bytesFreed &lt; bytesToFree) {<a name="line.687"></a>
-<span class="sourceLineNo">688</span>              bytesFreed += bucketMulti.free(bytesToFree - bytesFreed);<a name="line.688"></a>
-<span class="sourceLineNo">689</span>            }<a name="line.689"></a>
-<span class="sourceLineNo">690</span>          }<a name="line.690"></a>
-<span class="sourceLineNo">691</span>        }<a name="line.691"></a>
-<span class="sourceLineNo">692</span>      } else {<a name="line.692"></a>
-<span class="sourceLineNo">693</span>        PriorityQueue&lt;BlockBucket&gt; bucketQueue = new PriorityQueue&lt;&gt;(3);<a name="line.693"></a>
-<span class="sourceLineNo">694</span><a name="line.694"></a>
-<span class="sourceLineNo">695</span>        bucketQueue.add(bucketSingle);<a name="line.695"></a>
-<span class="sourceLineNo">696</span>        bucketQueue.add(bucketMulti);<a name="line.696"></a>
-<span class="sourceLineNo">697</span>        bucketQueue.add(bucketMemory);<a name="line.697"></a>
-<span class="sourceLineNo">698</span><a name="line.698"></a>
-<span class="sourceLineNo">699</span>        int remainingBuckets = 3;<a name="line.699"></a>
-<span class="sourceLineNo">700</span><a name="line.700"></a>
-<span class="sourceLineNo">701</span>        BlockBucket bucket;<a name="line.701"></a>
-<span class="sourceLineNo">702</span>        while ((bucket = bucketQueue.poll()) != null) {<a name="line.702"></a>
-<span class="sourceLineNo">703</span>          long overflow = bucket.overflow();<a name="line.703"></a>
-<span class="sourceLineNo">704</span>          if (overflow &gt; 0) {<a name="line.704"></a>
-<span class="sourceLineNo">705</span>            long bucketBytesToFree =<a name="line.705"></a>
-<span class="sourceLineNo">706</span>                Math.min(overflow, (bytesToFree - bytesFreed) / remainingBuckets);<a name="line.706"></a>
-<span class="sourceLineNo">707</span>            bytesFreed += bucket.free(bucketBytesToFree);<a name="line.707"></a>
-<span class="sourceLineNo">708</span>          }<a name="line.708"></a>
-<span class="sourceLineNo">709</span>          remainingBuckets--;<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>      if (LOG.isTraceEnabled()) {<a name="line.712"></a>
-<span class="sourceLineNo">713</span>        long single = bucketSingle.totalSize();<a name="line.713"></a>
-<span class="sourceLineNo">714</span>        long multi = bucketMulti.totalSize();<a name="line.714"></a>
-<span class="sourceLineNo">715</span>        long memory = bucketMemory.totalSize();<a name="line.715"></a>
-<span class="sourceLineNo">716</span>        LOG.trace("Block cache LRU eviction completed; " +<a name="line.716"></a>
-<span class="sourceLineNo">717</span>          "freed=" + StringUtils.byteDesc(bytesFreed) + ", " +<a name="line.717"></a>
-<span class="sourceLineNo">718</span>          "total=" + StringUtils.byteDesc(this.size.get()) + ", " +<a name="line.718"></a>
-<span class="sourceLineNo">719</span>          "single=" + StringUtils.byteDesc(single) + ", " +<a name="line.719"></a>
-<span class="sourceLineNo">720</span>          "multi=" + StringUtils.byteDesc(multi) + ", " +<a name="line.720"></a>
-<span class="sourceLineNo">721</span>          "memory=" + StringUtils.byteDesc(memory));<a name="line.721"></a>
-<span class="sourceLineNo">722</span>      }<a name="line.722"></a>
-<span class="sourceLineNo">723</span>    } finally {<a name="line.723"></a>
-<span class="sourceLineNo">724</span>      stats.evict();<a name="line.724"></a>
-<span class="sourceLineNo">725</span>      evictionInProgress = false;<a name="line.725"></a>
-<span class="sourceLineNo">726</span>      evictionLock.unlock();<a name="line.726"></a>
-<span class="sourceLineNo">727</span>    }<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>  @Override<a name="line.730"></a>
-<span class="sourceLineNo">731</span>  public String toString() {<a name="line.731"></a>
-<span class="sourceLineNo">732</span>    return MoreObjects.toStringHelper(this)<a name="line.732"></a>
-<span class="sourceLineNo">733</span>      .add("blockCount", getBlockCount())<a name="line.733"></a>
-<span class="sourceLineNo">734</span>      .add("currentSize", StringUtils.byteDesc(getCurrentSize()))<a name="line.734"></a>
-<span class="sourceLineNo">735</span>      .add("freeSize", StringUtils.byteDesc(getFreeSize()))<a name="line.735"></a>
-<span class="sourceLineNo">736</span>      .add("maxSize", StringUtils.byteDesc(getMaxSize()))<a name="line.736"></a>
-<span class="sourceLineNo">737</span>      .add("heapSize", StringUtils.byteDesc(heapSize()))<a name="line.737"></a>
-<span class="sourceLineNo">738</span>      .add("minSize", StringUtils.byteDesc(minSize()))<a name="line.738"></a>
-<span class="sourceLineNo">739</span>      .add("minFactor", minFactor)<a name="line.739"></a>
-<span class="sourceLineNo">740</span>      .add("multiSize", StringUtils.byteDesc(multiSize()))<a name="line.740"></a>
-<span class="sourceLineNo">741</span>      .add("multiFactor", multiFactor)<a name="line.741"></a>
-<span class="sourceLineNo">742</span>      .add("singleSize", StringUtils.byteDesc(singleSize()))<a name="line.742"></a>
-<span class="sourceLineNo">743</span>      .add("singleFactor", singleFactor)<a name="line.743"></a>
-<span class="sourceLineNo">744</span>      .toString();<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>  /**<a name="line.747"></a>
-<span class="sourceLineNo">748</span>   * Used to group blocks into priority buckets.  There will be a BlockBucket<a name="line.748"></a>
-<span class="sourceLineNo">749</span>   * for each priority (single, multi, memory).  Once bucketed, the eviction<a name="line.749"></a>
-<span class="sourceLineNo">750</span>   * algorithm takes the appropriate number of elements out of each according<a name="line.750"></a>
-<span class="sourceLineNo">751</span>   * to configuration parameters and their relatives sizes.<a name="line.751"></a>
-<span class="sourceLineNo">752</span>   */<a name="line.752"></a>
-<span class="sourceLineNo">753</span>  private class BlockBucket implements Comparable&lt;BlockBucket&gt; {<a name="line.753"></a>
-<span class="sourceLineNo">754</span><a name="line.754"></a>
-<span class="sourceLineNo">755</span>    private final String name;<a name="line.755"></a>
-<span class="sourceLineNo">756</span>    private LruCachedBlockQueue queue;<a name="line.756"></a>
-<span class="sourceLineNo">757</span>    private long totalSize = 0;<a name="line.757"></a>
-<span class="sourceLineNo">758</span>    private long bucketSize;<a name="line.758"></a>
+<span class="sourceLineNo">671</span>          bytesFreed += bucketMemory.free(bytesToFree - bytesFreed);<a name="line.671"></a>
+<span class="sourceLineNo">672</span>          if (LOG.isTraceEnabled()) {<a name="line.672"></a>
+<span class="sourceLineNo">673</span>            LOG.trace("freed " + StringUtils.byteDesc(bytesFreed) +<a name="line.673"></a>
+<span class="sourceLineNo">674</span>              " total from all three buckets ");<a name="line.674"></a>
+<span class="sourceLineNo">675</span>          }<a name="line.675"></a>
+<span class="sourceLineNo">676</span>        } else {<a name="line.676"></a>
+<span class="sourceLineNo">677</span>          // this means no need to evict block in memory bucket,<a name="line.677"></a>
+<span class="sourceLineNo">678</span>          // and we try best to make the ratio between single-bucket and<a name="line.678"></a>
+<span class="sourceLineNo">679</span>          // multi-bucket is 1:2<a name="line.679"></a>
+<span class="sourceLineNo">680</span>          long bytesRemain = s + m - bytesToFree;<a name="line.680"></a>
+<span class="sourceLineNo">681</span>          if (3 * s &lt;= bytesRemain) {<a name="line.681"></a>
+<span class="sourceLineNo">682</span>            // single-bucket is small enough that no eviction happens for it<a name="line.682"></a>
+<span class="sourceLineNo">683</span>            // hence all eviction goes from multi-bucket<a name="line.683"></a>
+<span class="sourceLineNo">684</span>            bytesFreed = bucketMulti.free(bytesToFree);<a name="line.684"></a>
+<span class="sourceLineNo">685</span>          } else if (3 * m &lt;= 2 * bytesRemain) {<a name="line.685"></a>
+<span class="sourceLineNo">686</span>            // multi-bucket is small enough that no eviction happens for it<a name="line.686"></a>
+<span class="sourceLineNo">687</span>            // hence all eviction goes from single-bucket<a name="line.687"></a>
+<span class="sourceLineNo">688</span>            bytesFreed = bucketSingle.free(bytesToFree);<a name="line.688"></a>
+<span class="sourceLineNo">689</span>          } else {<a name="line.689"></a>
+<span class="sourceLineNo">690</span>            // both buckets need to evict some blocks<a name="line.690"></a>
+<span class="sourceLineNo">691</span>            bytesFreed = bucketSingle.free(s - bytesRemain / 3);<a name="line.691"></a>
+<span class="sourceLineNo">692</span>            if (bytesFreed &lt; bytesToFree) {<a name="line.692"></a>
+<span class="sourceLineNo">693</span>              bytesFreed += bucketMulti.free(bytesToFree - bytesFreed);<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>        }<a name="line.696"></a>
+<span class="sourceLineNo">697</span>      } else {<a name="line.697"></a>
+<span class="sourceLineNo">698</span>        PriorityQueue&lt;BlockBucket&gt; bucketQueue = new PriorityQueue&lt;&gt;(3);<a name="line.698"></a>
+<span class="sourceLineNo">699</span><a name="line.699"></a>
+<span class="sourceLineNo">700</span>        bucketQueue.add(bucketSingle);<a name="line.700"></a>
+<span class="sourceLineNo">701</span>        bucketQueue.add(bucketMulti);<a name="line.701"></a>
+<span class="sourceLineNo">702</span>        bucketQueue.add(bucketMemory);<a name="line.702"></a>
+<span class="sourceLineNo">703</span><a name="line.703"></a>
+<span class="sourceLineNo">704</span>        int remainingBuckets = 3;<a name="line.704"></a>
+<span class="sourceLineNo">705</span><a name="line.705"></a>
+<span class="sourceLineNo">706</span>        BlockBucket bucket;<a name="line.706"></a>
+<span class="sourceLineNo">707</span>        while ((bucket = bucketQueue.poll()) != null) {<a name="line.707"></a>
+<span class="sourceLineNo">708</span>          long overflow = bucket.overflow();<a name="line.708"></a>
+<span class="sourceLineNo">709</span>          if (overflow &gt; 0) {<a name="line.709"></a>
+<span class="sourceLineNo">710</span>            long bucketBytesToFree =<a name="line.710"></a>
+<span class="sourceLineNo">711</span>                Math.min(overflow, (bytesToFree - bytesFreed) / remainingBuckets);<a name="line.711"></a>
+<span class="sourceLineNo">712</span>            bytesFreed += bucket.free(bucketBytesToFree);<a name="line.712"></a>
+<span class="sourceLineNo">713</span>          }<a name="line.713"></a>
+<span class="sourceLineNo">714</span>          remainingBuckets--;<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">717</span>      if (LOG.isTraceEnabled()) {<a name="line.717"></a>
+<span class="sourceLineNo">718</span>        long single = bucketSingle.totalSize();<a name="line.718"></a>
+<span class="sourceLineNo">719</span>        long multi = bucketMulti.totalSize();<a name="line.719"></a>
+<span class="sourceLineNo">720</span>        long memory = bucketMemory.totalSize();<a name="line.720"></a>
+<span class="sourceLineNo">721</span>        LOG.trace("Block cache LRU eviction completed; " +<a name="line.721"></a>
+<span class="sourceLineNo">722</span>          "freed=" + StringUtils.byteDesc(bytesFreed) + ", " +<a name="line.722"></a>
+<span class="sourceLineNo">723</span>          "total=" + StringUtils.byteDesc(this.size.get()) + ", " +<a name="line.723"></a>
+<span class="sourceLineNo">724</span>          "single=" + StringUtils.byteDesc(single) + ", " +<a name="line.724"></a>
+<span class="sourceLineNo">725</span>          "multi=" + StringUtils.byteDesc(multi) + ", " +<a name="line.725"></a>
+<span class="sourceLineNo">726</span>          "memory=" + StringUtils.byteDesc(memory));<a name="line.726"></a>
+<span class="sourceLineNo">727</span>      }<a name="line.727"></a>
+<span class="sourceLineNo">728</span>    } finally {<a name="line.728"></a>
+<span class="sourceLineNo">729</span>      stats.evict();<a name="line.729"></a>
+<span class="sourceLineNo">730</span>      evictionInProgress = false;<a name="line.730"></a>
+<span class="sourceLineNo">731</span>      evictionLock.unlock();<a name="line.731"></a>
+<span class="sourceLineNo">732</span>    }<a name="line.732"></a>
+<span class="sourceLineNo">733</span>  }<a name="line.733"></a>
+<span class="sourceLineNo">734</span><a name="line.734"></a>
+<span class="sourceLineNo">735</span>  @Override<a name="line.735"></a>
+<span class="sourceLineNo">736</span>  public String toString() {<a name="line.736"></a>
+<span class="sourceLineNo">737</span>    return MoreObjects.toStringHelper(this)<a name="line.737"></a>
+<span class="sourceLineNo">738</span>      .add("blockCount", getBlockCount())<a name="line.738"></a>
+<span class="sourceLineNo">739</span>      .add("currentSize", StringUtils.byteDesc(getCurrentSize()))<a name="line.739"></a>
+<span class="sourceLineNo">740</span>      .add("freeSize", StringUtils.byteDesc(getFreeSize()))<a name="line.740"></a>
+<span class="sourceLineNo">741</span>      .add("maxSize", StringUtils.byteDesc(getMaxSize()))<a name="line.741"></a>
+<span class="sourceLineNo">742</span>      .add("heapSize", StringUtils.byteDesc(heapSize()))<a name="line.742"></a>
+<span class="sourceLineNo">743</span>      .add("minSize", StringUtils.byteDesc(minSize()))<a name="line.743"></a>
+<span class="sourceLineNo">744</span>      .add("minFactor", minFactor)<a name="line.744"></a>
+<span class="sourceLineNo">745</span>      .add("multiSize", StringUtils.byteDesc(multiSize()))<a name="line.745"></a>
+<span class="sourceLineNo">746</span>      .add("multiFactor", multiFactor)<a name="line.746"></a>
+<span class="sourceLineNo">747</span>      .add("singleSize", StringUtils.byteDesc(singleSize()))<a name="line.747"></a>
+<span class="sourceLineNo">748</span>      .add("singleFactor", singleFactor)<a name="line.748"></a>
+<span class="sourceLineNo">749</span>      .toString();<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>   * Used to group blocks into priority buckets.  There will be a BlockBucket<a name="line.753"></a>
+<span class="sourceLineNo">754</span>   * for each priority (single, multi, memory).  Once bucketed, the eviction<a name="line.754"></a>
+<span class="sourceLineNo">755</span>   * algorithm takes the appropriate number of elements out of each according<a name="line.755"></a>
+<span class="sourceLineNo">756</span>   * to configuration parameters and their relatives sizes.<a name="line.756"></a>
+<span class="sourceLineNo">757</span>   */<a name="line.757"></a>
+<span class="sourceLineNo">758</span>  private class BlockBucket implements Comparable&lt;BlockBucket&gt; {<a name="line.758"></a>
 <span class="sourceLineNo">759</span><a name="line.759"></a>
-<span class="sourceLineNo">760</span>    public BlockBucket(String name, long bytesToFree, long blockSize, long bucketSize) {<a name="line.760"></a>
-<span class="sourceLineNo">761</span>      this.name = name;<a name="line.761"></a>
-<span class="sourceLineNo">762</span>      this.bucketSize = bucketSize;<a name="line.762"></a>
-<span class="sourceLineNo">763</span>      queue = new LruCachedBlockQueue(bytesToFree, blockSize);<a name="line.763"></a>
-<span class="sourceLineNo">764</span>      totalSize = 0;<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>    public void add(LruCachedBlock block) {<a name="line.767"></a>
-<span class="sourceLineNo">768</span>      totalSize += block.heapSize();<a name="line.768"></a>
-<span class="sourceLineNo">769</span>      queue.add(block);<a name="line.769"></a>
+<span class="sourceLineNo">760</span>    private final String name;<a name="line.760"></a>
+<span class="sourceLineNo">761</span>    private LruCachedBlockQueue queue;<a name="line.761"></a>
+<span class="sourceLineNo">762</span>    private long totalSize = 0;<a name="line.762"></a>
+<span class="sourceLineNo">763</span>    private long bucketSize;<a name="line.763"></a>
+<span class="sourceLineNo">764</span><a name="line.764"></a>
+<span class="sourceLineNo">765</span>    public BlockBucket(String name, long bytesToFree, long blockSize, long bucketSize) {<a name="line.765"></a>
+<span class="sourceLineNo">766</span>      this.name = name;<a name="line.766"></a>
+<span class="sourceLineNo">767</span>      this.bucketSize = bucketSize;<a name="line.767"></a>
+<span class="sourceLineNo">768</span>      queue = new LruCachedBlockQueue(bytesToFree, blockSize);<a name="line.768"></a>
+<span class="sourceLineNo">769</span>      totalSize = 0;<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>    public long free(long toFree) {<a name="line.772"></a>
-<span class="sourceLineNo">773</span>      if (LOG.isTraceEnabled()) {<a name="line.773"></a>
-<span class="sourceLineNo">774</span>        LOG.trace("freeing " + StringUtils.byteDesc(toFree) + " from " + this);<a name="line.774"></a>
-<span class="sourceLineNo">775</span>      }<a name="line.775"></a>
-<span class="sourceLineNo">776</span>      LruCachedBlock cb;<a name="line.776"></a>
-<span class="sourceLineNo">777</span>      long freedBytes = 0;<a name="line.777"></a>
-<span class="sourceLineNo">778</span>      while ((cb = queue.pollLast()) != null) {<a name="line.778"></a>
-<span class="sourceLineNo">779</span>        freedBytes += evictBlock(cb, true);<a name="line.779"></a>
-<span class="sourceLineNo">780</span>        if (freedBytes &gt;= toFree) {<a name="line.780"></a>
-<span class="sourceLineNo">781</span>          return freedBytes;<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>      if (LOG.isTraceEnabled()) {<a name="line.784"></a>
-<span class="sourceLineNo">785</span>        LOG.trace("freed " + StringUtils.byteDesc(freedBytes) + " from " + this);<a name="line.785"></a>
-<span class="sourceLineNo">786</span>      }<a name="line.786"></a>
-<span class="sourceLineNo">787</span>      return freedBytes;<a name="line.787"></a>
-<span class="sourceLineNo">788</span>    }<a name="line.788"></a>
-<span class="sourceLineNo">789</span><a name="line.789"></a>
-<span class="sourceLineNo">790</span>    public long overflow() {<a name="line.790"></a>
-<span class="sourceLineNo">791</span>      return totalSize - bucketSize;<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>
-<span class="sourceLineNo">794</span>    public long totalSize() {<a name="line.794"></a>
-<span class="sourceLineNo">795</span>      return totalSize;<a name="line.795"></a>
-<span class="sourceLineNo">796</span>    }<a name="line.796"></a>
-<span class="sourceLineNo">797</span><a name="line.797"></a>
-<span class="sourceLineNo">798</span>    @Override<a name="line.798"></a>
-<span class="sourceLineNo">799</span>    public int compareTo(BlockBucket that) {<a name="line.799"></a>
-<span class="sourceLineNo">800</span>      return Long.compare(this.overflow(), that.overflow());<a name="line.800"></a>
+<span class="sourceLineNo">772</span>    public void add(LruCachedBlock block) {<a name="line.772"></a>
+<span class="sourceLineNo">773</span>      totalSize += block.heapSize();<a name="line.773"></a>
+<span class="sourceLineNo">774</span>      queue.add(block);<a name="line.774"></a>
+<span class="sourceLineNo">775</span>    }<a name="line.775"></a>
+<span class="sourceLineNo">776</span><a name="line.776"></a>
+<span class="sourceLineNo">777</span>    public long free(long toFree) {<a name="line.777"></a>
+<span class="sourceLineNo">778</span>      if (LOG.isTraceEnabled()) {<a name="line.778"></a>
+<span class="sourceLineNo">779</span>        LOG.trace("freeing " + StringUtils.byteDesc(toFree) + " from " + this);<a name="line.779"></a>
+<span class="sourceLineNo">780</span>      }<a name="line.780"></a>
+<span class="sourceLineNo">781</span>      LruCachedBlock cb;<a name="line.781"></a>
+<span class="sourceLineNo">782</span>      long freedBytes = 0;<a name="line.782"></a>
+<span class="sourceLineNo">783</span>      while ((cb = queue.pollLast()) != null) {<a name="line.783"></a>
+<span class="sourceLineNo">784</span>        freedBytes += evictBlock(cb, true);<a name="line.784"></a>
+<span class="sourceLineNo">785</span>        if (freedBytes &gt;= toFree) {<a name="line.785"></a>
+<span class="sourceLineNo">786</span>          return freedBytes;<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>      if (LOG.isTraceEnabled()) {<a name="line.789"></a>
+<span class="sourceLineNo">790</span>        LOG.trace("freed " + StringUtils.byteDesc(freedBytes) + " from " + this);<a name="line.790"></a>
+<span class="sourceLineNo">791</span>      }<a name="line.791"></a>
+<span class="sourceLineNo">792</span>      return freedBytes;<a name="line.792"></a>
+<span class="sourceLineNo">793</span>    }<a name="line.793"></a>
+<span class="sourceLineNo">794</span><a name="line.794"></a>
+<span class="sourceLineNo">795</span>    public long overflow() {<a name="line.795"></a>
+<span class="sourceLineNo">796</span>      return totalSize - bucketSize;<a name="line.796"></a>
+<span class="sourceLineNo">797</span>    }<a name="line.797"></a>
+<span class="sourceLineNo">798</span><a name="line.798"></a>
+<span class="sourceLineNo">799</span>    public long totalSize() {<a name="line.799"></a>
+<span class="sourceLineNo">800</span>      return totalSize;<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>    @Override<a name="line.803"></a>
-<span class="sourceLineNo">804</span>    public boolean equals(Object that) {<a name="line.804"></a>
-<span class="sourceLineNo">805</span>      if (that == null || !(that instanceof BlockBucket)) {<a name="line.805"></a>
-<span class="sourceLineNo">806</span>        return false;<a name="line.806"></a>
-<span class="sourceLineNo">807</span>      }<a name="line.807"></a>
-<span class="sourceLineNo">808</span>      return compareTo((BlockBucket)that) == 0;<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>    @Override<a name="line.811"></a>
-<span class="sourceLineNo">812</span>    public int hashCode() {<a name="line.812"></a>
-<span class="sourceLineNo">813</span>      return Objects.hashCode(name, bucketSize, queue, totalSize);<a name="line.813"></a>
+<span class="sourceLineNo">804</span>    public int compareTo(BlockBucket that) {<a name="line.804"></a>
+<span class="sourceLineNo">805</span>      return Long.compare(this.overflow(), that.overflow());<a name="line.805"></a>
+<span class="sourceLineNo">806</span>    }<a name="line.806"></a>
+<span class="sourceLineNo">807</span><a name="line.807"></a>
+<span class="sourceLineNo">808</span>    @Override<a name="line.808"></a>
+<span class="sourceLineNo">809</span>    public boolean equals(Object that) {<a name="line.809"></a>
+<span class="sourceLineNo">810</span>      if (that == null || !(that instanceof BlockBucket)) {<a name="line.810"></a>
+<span class="sourceLineNo">811</span>        return false;<a name="line.811"></a>
+<span class="sourceLineNo">812</span>      }<a name="line.812"></a>
+<span class="sourceLineNo">813</span>      return compareTo((BlockBucket)that) == 0;<a name="line.813"></a>
 <span class="sourceLineNo">814</span>    }<a name="line.814"></a>
 <span class="sourceLineNo">815</span><a name="line.815"></a>
 <span class="sourceLineNo">816</span>    @Override<a name="line.816"></a>
-<span class="sourceLineNo">817</span>    public String toString() {<a name="line.817"></a>
-<span class="sourceLineNo">818</span>      return MoreObjects.toStringHelper(this)<a name="line.818"></a>
-<span class="sourceLineNo">819</span>        .add("name", name)<a name="line.819"></a>
-<span class="sourceLineNo">820</span>        .add("totalSize", StringUtils.byteDesc(totalSize))<a name="line.820"></a>
-<span class="sourceLineNo">821</span>        .add("bucketSize", StringUtils.byteDesc(bucketSize))<a name="line.821"></a>
-<span class="sourceLineNo">822</span>        .toString();<a name="line.822"></a>
-<span class="sourceLineNo">823</span>    }<a name="line.823"></a>
-<span class="sourceLineNo">824</span>  }<a name="line.824"></a>
-<span class="sourceLineNo">825</span><a name="line.825"></a>
-<span class="sourceLineNo">826</span>  /**<a name="line.826"></a>
-<span class="sourceLineNo">827</span>   * Get the maximum size of this cache.<a name="line.827"></a>
-<span class="sourceLineNo">828</span>   *<a name="line.828"></a>
-<span class="sourceLineNo">829</span>   * @return max size in bytes<a name="line.829"></a>
-<span class="sourceLineNo">830</span>   */<a name="line.830"></a>
-<span class="sourceLineNo">831</span><a name="line.831"></a>
-<span class="sourceLineNo">832</span>  @Override<a name="line.832"></a>
-<span class="sourceLineNo">833</span>  public long getMaxSize() {<a name="line.833"></a>
-<span class="sourceLineNo">834</span>    return this.maxSize;<a name="line.834"></a>
-<span class="sourceLineNo">835</span>  }<a name="line.835"></a>
+<span class="sourceLineNo">817</span>    public int hashCode() {<a name="line.817"></a>
+<span class="sourceLineNo">818</span>      return Objects.hashCode(name, bucketSize, queue, totalSize);<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>    @Override<a name="line.821"></a>
+<span class="sourceLineNo">822</span>    public String toString() {<a name="line.822"></a>
+<span class="sourceLineNo">823</span>      return MoreObjects.toStringHelper(this)<a name="line.823"></a>
+<span class="sourceLineNo">824</span>        .add("name", name)<a name="line.824"></a>
+<span class="sourceLineNo">825</span>        .add("totalSize", StringUtils.byteDesc(totalSize))<a name="line.825"></a>
+<span class="sourceLineNo">826</span>        .add("bucketSize", StringUtils.byteDesc(bucketSize))<a name="line.826"></a>
+<span class="sourceLineNo">827</span>        .toString();<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">830</span><a name="line.830"></a>
+<span class="sourceLineNo">831</span>  /**<a name="line.831"></a>
+<span class="sourceLineNo">832</span>   * Get the maximum size of this cache.<a name="line.832"></a>
+<span class="sourceLineNo">833</span>   *<a name="line.833"></a>
+<span class="sourceLineNo">834</span>   * @return max size in bytes<a name="line.834"></a>
+<span class="sourceLineNo">835</span>   */<a name="line.835"></a>
 <span class="sourceLineNo">836</span><a name="line.836"></a>
 <span class="sourceLineNo">837</span>  @Override<a name="line.837"></a>
-<span class="sourceLineNo">838</span>  public long getCurrentSize() {<a name="line.838"></a>
-<span class="sourceLineNo">839</span>    return this.size.get();<a name="line.839"></a>
+<span class="sourceLineNo">838</span>  public long getMaxSize() {<a name="line.838"></a>
+<span class="sourceLineNo">839</span>    return this.maxSize;<a name="line.839"></a>
 <span class="sourceLineNo">840</span>  }<a name="line.840"></a>
 <span class="sourceLineNo">841</span><a name="line.841"></a>
 <span class="sourceLineNo">842</span>  @Override<a name="line.842"></a>
-<span class="sourceLineNo">843</span>  public long getCurrentDataSize() {<a name="line.843"></a>
-<span class="sourceLineNo">844</span>    return this.dataBlockSize.sum();<a name="line.844"></a>
+<span class="sourceLineNo">843</span>  public long getCurrentSize() {<a name="line.843"></a>
+<span class="sourceLineNo">844</span>    return this.size.get();<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>  @Override<a name="line.847"></a>
-<span class="sourceLineNo">848</span>  public long getFreeSize() {<a name="line.848"></a>
-<span class="sourceLineNo">849</span>    return getMaxSize() - getCurrentSize();<a name="line.849"></a>
+<span class="sourceLineNo">848</span>  public long getCurrentDataSize() {<a name="line.848"></a>
+<span class="sourceLineNo">849</span>    return this.dataBlockSize.sum();<a name="line.849"></a>
 <span class="sourceLineNo">850</span>  }<a name="line.850"></a>
 <span class="sourceLineNo">851</span><a name="line.851"></a>
 <span class="sourceLineNo">852</span>  @Override<a name="line.852"></a>
-<span class="sourceLineNo">853</span>  public long size() {<a name="line.853"></a>
-<span class="sourceLineNo">854</span>    return getMaxSize();<a name="line.854"></a>
+<span class="sourceLineNo">853</span>  public long getFreeSize() {<a name="line.853"></a>
+<span class="sourceLineNo">854</span>    return getMaxSize() - getCurrentSize();<a name="line.854"></a>
 <span class="sourceLineNo">855</span>  }<a name="line.855"></a>
 <span class="sourceLineNo">856</span><a name="line.856"></a>
 <span class="sourceLineNo">857</span>  @Override<a name="line.857"></a>
-<span class="sourceLineNo">858</span>  public long getBlockCount() {<a name="line.858"></a>
-<span class="sourceLineNo">859</span>    return this.elements.get();<a name="line.859"></a>
+<span class="sourceLineNo">858</span>  public long size() {<a name="line.858"></a>
+<span class="sourceLineNo">859</span>    return getMaxSize();<a name="line.859"></a>
 <span class="sourceLineNo">860</span>  }<a name="line.860"></a>
 <span class="sourceLineNo">861</span><a name="line.861"></a>
 <span class="sourceLineNo">862</span>  @Override<a name="line.862"></a>
-<span class="sourceLineNo">863</span>  public long getDataBlockCount() {<a name="line.863"></a>
-<span class="sourceLineNo">864</span>    return this.dataBlockElements.sum();<a name="line.864"></a>
+<span class="sourceLineNo">863</span>  public long getBlockCount() {<a name="line.863"></a>
+<span class="sourceLineNo">864</span>    return this.elements.get();<a name="line.864"></a>
 <span class="sourceLineNo">865</span>  }<a name="line.865"></a>
 <span class="sourceLineNo">866</span><a name="line.866"></a>
-<span class="sourceLineNo">867</span>  EvictionThread getEvictionThread() {<a name="line.867"></a>
-<span class="sourceLineNo">868</span>    return this.evictionThread;<a name="line.868"></a>
-<span class="sourceLineNo">869</span>  }<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>   * Eviction thread.  Sits in waiting state until an eviction is triggered<a name="line.872"></a>
-<span class="sourceLineNo">873</span>   * when the cache size grows above the acceptable level.&lt;p&gt;<a

<TRUNCATED>

[07/50] hbase-site git commit: Published site at 26babcf013de696b899d76a3c39434b794440d8d.

Posted by gi...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestHFileBlock.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestHFileBlock.html b/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestHFileBlock.html
index 37f7b15..da0a780 100644
--- a/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestHFileBlock.html
+++ b/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/TestHFileBlock.html
@@ -476,7 +476,7 @@
 <span class="sourceLineNo">468</span>            // test serialized blocks<a name="line.468"></a>
 <span class="sourceLineNo">469</span>            for (boolean reuseBuffer : new boolean[] { false, true }) {<a name="line.469"></a>
 <span class="sourceLineNo">470</span>              ByteBuffer serialized = ByteBuffer.allocate(blockFromHFile.getSerializedLength());<a name="line.470"></a>
-<span class="sourceLineNo">471</span>              blockFromHFile.serialize(serialized);<a name="line.471"></a>
+<span class="sourceLineNo">471</span>              blockFromHFile.serialize(serialized, true);<a name="line.471"></a>
 <span class="sourceLineNo">472</span>              HFileBlock deserialized =<a name="line.472"></a>
 <span class="sourceLineNo">473</span>                  (HFileBlock) blockFromHFile.getDeserializer().deserialize(<a name="line.473"></a>
 <span class="sourceLineNo">474</span>                    new SingleByteBuff(serialized), reuseBuffer, MemoryType.EXCLUSIVE);<a name="line.474"></a>
@@ -866,7 +866,30 @@
 <span class="sourceLineNo">858</span>          block.heapSize());<a name="line.858"></a>
 <span class="sourceLineNo">859</span>    }<a name="line.859"></a>
 <span class="sourceLineNo">860</span>  }<a name="line.860"></a>
-<span class="sourceLineNo">861</span>}<a name="line.861"></a>
+<span class="sourceLineNo">861</span><a name="line.861"></a>
+<span class="sourceLineNo">862</span>  @Test<a name="line.862"></a>
+<span class="sourceLineNo">863</span>  public void testSerializeWithoutNextBlockMetadata() {<a name="line.863"></a>
+<span class="sourceLineNo">864</span>    int size = 100;<a name="line.864"></a>
+<span class="sourceLineNo">865</span>    int length = HConstants.HFILEBLOCK_HEADER_SIZE + size;<a name="line.865"></a>
+<span class="sourceLineNo">866</span>    byte[] byteArr = new byte[length];<a name="line.866"></a>
+<span class="sourceLineNo">867</span>    ByteBuffer buf = ByteBuffer.wrap(byteArr, 0, size);<a name="line.867"></a>
+<span class="sourceLineNo">868</span>    HFileContext meta = new HFileContextBuilder().build();<a name="line.868"></a>
+<span class="sourceLineNo">869</span>    HFileBlock blockWithNextBlockMetadata = new HFileBlock(BlockType.DATA, size, size, -1, buf,<a name="line.869"></a>
+<span class="sourceLineNo">870</span>        HFileBlock.FILL_HEADER, -1, 52, -1, meta);<a name="line.870"></a>
+<span class="sourceLineNo">871</span>    HFileBlock blockWithoutNextBlockMetadata = new HFileBlock(BlockType.DATA, size, size, -1, buf,<a name="line.871"></a>
+<span class="sourceLineNo">872</span>        HFileBlock.FILL_HEADER, -1, -1, -1, meta);<a name="line.872"></a>
+<span class="sourceLineNo">873</span>    ByteBuffer buff1 = ByteBuffer.allocate(length);<a name="line.873"></a>
+<span class="sourceLineNo">874</span>    ByteBuffer buff2 = ByteBuffer.allocate(length);<a name="line.874"></a>
+<span class="sourceLineNo">875</span>    blockWithNextBlockMetadata.serialize(buff1, true);<a name="line.875"></a>
+<span class="sourceLineNo">876</span>    blockWithoutNextBlockMetadata.serialize(buff2, true);<a name="line.876"></a>
+<span class="sourceLineNo">877</span>    assertNotEquals(buff1, buff2);<a name="line.877"></a>
+<span class="sourceLineNo">878</span>    buff1.clear();<a name="line.878"></a>
+<span class="sourceLineNo">879</span>    buff2.clear();<a name="line.879"></a>
+<span class="sourceLineNo">880</span>    blockWithNextBlockMetadata.serialize(buff1, false);<a name="line.880"></a>
+<span class="sourceLineNo">881</span>    blockWithoutNextBlockMetadata.serialize(buff2, false);<a name="line.881"></a>
+<span class="sourceLineNo">882</span>    assertEquals(buff1, buff2);<a name="line.882"></a>
+<span class="sourceLineNo">883</span>  }<a name="line.883"></a>
+<span class="sourceLineNo">884</span>}<a name="line.884"></a>
 
 
 


[03/50] hbase-site git commit: Published site at 26babcf013de696b899d76a3c39434b794440d8d.

Posted by gi...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html b/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html
index dd58cd9..01157c1 100644
--- a/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html
+++ b/testdevapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html
@@ -27,394 +27,433 @@
 <span class="sourceLineNo">019</span><a name="line.19"></a>
 <span class="sourceLineNo">020</span>import static org.junit.Assert.assertEquals;<a name="line.20"></a>
 <span class="sourceLineNo">021</span>import static org.junit.Assert.assertFalse;<a name="line.21"></a>
-<span class="sourceLineNo">022</span>import static org.junit.Assert.assertTrue;<a name="line.22"></a>
-<span class="sourceLineNo">023</span><a name="line.23"></a>
-<span class="sourceLineNo">024</span>import java.io.FileNotFoundException;<a name="line.24"></a>
-<span class="sourceLineNo">025</span>import java.io.IOException;<a name="line.25"></a>
-<span class="sourceLineNo">026</span>import java.util.ArrayList;<a name="line.26"></a>
-<span class="sourceLineNo">027</span>import java.util.Arrays;<a name="line.27"></a>
-<span class="sourceLineNo">028</span>import java.util.List;<a name="line.28"></a>
-<span class="sourceLineNo">029</span>import java.util.Map;<a name="line.29"></a>
-<span class="sourceLineNo">030</span>import java.util.Random;<a name="line.30"></a>
-<span class="sourceLineNo">031</span>import java.util.Set;<a name="line.31"></a>
-<span class="sourceLineNo">032</span>import java.util.concurrent.locks.ReentrantReadWriteLock;<a name="line.32"></a>
-<span class="sourceLineNo">033</span>import org.apache.hadoop.conf.Configuration;<a name="line.33"></a>
-<span class="sourceLineNo">034</span>import org.apache.hadoop.fs.Path;<a name="line.34"></a>
-<span class="sourceLineNo">035</span>import org.apache.hadoop.hbase.HBaseClassTestRule;<a name="line.35"></a>
-<span class="sourceLineNo">036</span>import org.apache.hadoop.hbase.HBaseConfiguration;<a name="line.36"></a>
-<span class="sourceLineNo">037</span>import org.apache.hadoop.hbase.HBaseTestingUtility;<a name="line.37"></a>
-<span class="sourceLineNo">038</span>import org.apache.hadoop.hbase.io.hfile.BlockCacheKey;<a name="line.38"></a>
-<span class="sourceLineNo">039</span>import org.apache.hadoop.hbase.io.hfile.CacheTestUtils;<a name="line.39"></a>
-<span class="sourceLineNo">040</span>import org.apache.hadoop.hbase.io.hfile.CacheTestUtils.HFileBlockPair;<a name="line.40"></a>
-<span class="sourceLineNo">041</span>import org.apache.hadoop.hbase.io.hfile.Cacheable;<a name="line.41"></a>
-<span class="sourceLineNo">042</span>import org.apache.hadoop.hbase.io.hfile.bucket.BucketAllocator.BucketSizeInfo;<a name="line.42"></a>
-<span class="sourceLineNo">043</span>import org.apache.hadoop.hbase.io.hfile.bucket.BucketAllocator.IndexStatistics;<a name="line.43"></a>
-<span class="sourceLineNo">044</span>import org.apache.hadoop.hbase.testclassification.IOTests;<a name="line.44"></a>
-<span class="sourceLineNo">045</span>import org.apache.hadoop.hbase.testclassification.MediumTests;<a name="line.45"></a>
-<span class="sourceLineNo">046</span>import org.junit.After;<a name="line.46"></a>
-<span class="sourceLineNo">047</span>import org.junit.Before;<a name="line.47"></a>
-<span class="sourceLineNo">048</span>import org.junit.ClassRule;<a name="line.48"></a>
-<span class="sourceLineNo">049</span>import org.junit.Test;<a name="line.49"></a>
-<span class="sourceLineNo">050</span>import org.junit.experimental.categories.Category;<a name="line.50"></a>
-<span class="sourceLineNo">051</span>import org.junit.runner.RunWith;<a name="line.51"></a>
-<span class="sourceLineNo">052</span>import org.junit.runners.Parameterized;<a name="line.52"></a>
-<span class="sourceLineNo">053</span><a name="line.53"></a>
-<span class="sourceLineNo">054</span>import org.apache.hbase.thirdparty.com.google.common.collect.ImmutableMap;<a name="line.54"></a>
-<span class="sourceLineNo">055</span><a name="line.55"></a>
-<span class="sourceLineNo">056</span>/**<a name="line.56"></a>
-<span class="sourceLineNo">057</span> * Basic test of BucketCache.Puts and gets.<a name="line.57"></a>
-<span class="sourceLineNo">058</span> * &lt;p&gt;<a name="line.58"></a>
-<span class="sourceLineNo">059</span> * Tests will ensure that blocks' data correctness under several threads concurrency<a name="line.59"></a>
-<span class="sourceLineNo">060</span> */<a name="line.60"></a>
-<span class="sourceLineNo">061</span>@RunWith(Parameterized.class)<a name="line.61"></a>
-<span class="sourceLineNo">062</span>@Category({ IOTests.class, MediumTests.class })<a name="line.62"></a>
-<span class="sourceLineNo">063</span>public class TestBucketCache {<a name="line.63"></a>
-<span class="sourceLineNo">064</span><a name="line.64"></a>
-<span class="sourceLineNo">065</span>  @ClassRule<a name="line.65"></a>
-<span class="sourceLineNo">066</span>  public static final HBaseClassTestRule CLASS_RULE =<a name="line.66"></a>
-<span class="sourceLineNo">067</span>      HBaseClassTestRule.forClass(TestBucketCache.class);<a name="line.67"></a>
-<span class="sourceLineNo">068</span><a name="line.68"></a>
-<span class="sourceLineNo">069</span>  private static final Random RAND = new Random();<a name="line.69"></a>
-<span class="sourceLineNo">070</span><a name="line.70"></a>
-<span class="sourceLineNo">071</span>  @Parameterized.Parameters(name = "{index}: blockSize={0}, bucketSizes={1}")<a name="line.71"></a>
-<span class="sourceLineNo">072</span>  public static Iterable&lt;Object[]&gt; data() {<a name="line.72"></a>
-<span class="sourceLineNo">073</span>    return Arrays.asList(new Object[][] {<a name="line.73"></a>
-<span class="sourceLineNo">074</span>        { 8192, null }, // TODO: why is 8k the default blocksize for these tests?<a name="line.74"></a>
-<span class="sourceLineNo">075</span>        {<a name="line.75"></a>
-<span class="sourceLineNo">076</span>            16 * 1024,<a name="line.76"></a>
-<span class="sourceLineNo">077</span>            new int[] { 2 * 1024 + 1024, 4 * 1024 + 1024, 8 * 1024 + 1024, 16 * 1024 + 1024,<a name="line.77"></a>
-<span class="sourceLineNo">078</span>                28 * 1024 + 1024, 32 * 1024 + 1024, 64 * 1024 + 1024, 96 * 1024 + 1024,<a name="line.78"></a>
-<span class="sourceLineNo">079</span>                128 * 1024 + 1024 } } });<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>  @Parameterized.Parameter(0)<a name="line.82"></a>
-<span class="sourceLineNo">083</span>  public int constructedBlockSize;<a name="line.83"></a>
-<span class="sourceLineNo">084</span><a name="line.84"></a>
-<span class="sourceLineNo">085</span>  @Parameterized.Parameter(1)<a name="line.85"></a>
-<span class="sourceLineNo">086</span>  public int[] constructedBlockSizes;<a name="line.86"></a>
-<span class="sourceLineNo">087</span><a name="line.87"></a>
-<span class="sourceLineNo">088</span>  BucketCache cache;<a name="line.88"></a>
-<span class="sourceLineNo">089</span>  final int CACHE_SIZE = 1000000;<a name="line.89"></a>
-<span class="sourceLineNo">090</span>  final int NUM_BLOCKS = 100;<a name="line.90"></a>
-<span class="sourceLineNo">091</span>  final int BLOCK_SIZE = CACHE_SIZE / NUM_BLOCKS;<a name="line.91"></a>
-<span class="sourceLineNo">092</span>  final int NUM_THREADS = 100;<a name="line.92"></a>
-<span class="sourceLineNo">093</span>  final int NUM_QUERIES = 10000;<a name="line.93"></a>
+<span class="sourceLineNo">022</span>import static org.junit.Assert.assertNull;<a name="line.22"></a>
+<span class="sourceLineNo">023</span>import static org.junit.Assert.assertTrue;<a name="line.23"></a>
+<span class="sourceLineNo">024</span><a name="line.24"></a>
+<span class="sourceLineNo">025</span>import java.io.FileNotFoundException;<a name="line.25"></a>
+<span class="sourceLineNo">026</span>import java.io.IOException;<a name="line.26"></a>
+<span class="sourceLineNo">027</span>import java.nio.ByteBuffer;<a name="line.27"></a>
+<span class="sourceLineNo">028</span>import java.util.ArrayList;<a name="line.28"></a>
+<span class="sourceLineNo">029</span>import java.util.Arrays;<a name="line.29"></a>
+<span class="sourceLineNo">030</span>import java.util.List;<a name="line.30"></a>
+<span class="sourceLineNo">031</span>import java.util.Map;<a name="line.31"></a>
+<span class="sourceLineNo">032</span>import java.util.Random;<a name="line.32"></a>
+<span class="sourceLineNo">033</span>import java.util.Set;<a name="line.33"></a>
+<span class="sourceLineNo">034</span>import java.util.concurrent.locks.ReentrantReadWriteLock;<a name="line.34"></a>
+<span class="sourceLineNo">035</span>import org.apache.hadoop.conf.Configuration;<a name="line.35"></a>
+<span class="sourceLineNo">036</span>import org.apache.hadoop.fs.Path;<a name="line.36"></a>
+<span class="sourceLineNo">037</span>import org.apache.hadoop.hbase.HBaseClassTestRule;<a name="line.37"></a>
+<span class="sourceLineNo">038</span>import org.apache.hadoop.hbase.HBaseConfiguration;<a name="line.38"></a>
+<span class="sourceLineNo">039</span>import org.apache.hadoop.hbase.HBaseTestingUtility;<a name="line.39"></a>
+<span class="sourceLineNo">040</span>import org.apache.hadoop.hbase.HConstants;<a name="line.40"></a>
+<span class="sourceLineNo">041</span>import org.apache.hadoop.hbase.io.hfile.BlockCacheKey;<a name="line.41"></a>
+<span class="sourceLineNo">042</span>import org.apache.hadoop.hbase.io.hfile.BlockType;<a name="line.42"></a>
+<span class="sourceLineNo">043</span>import org.apache.hadoop.hbase.io.hfile.CacheTestUtils;<a name="line.43"></a>
+<span class="sourceLineNo">044</span>import org.apache.hadoop.hbase.io.hfile.CacheTestUtils.HFileBlockPair;<a name="line.44"></a>
+<span class="sourceLineNo">045</span>import org.apache.hadoop.hbase.io.hfile.Cacheable;<a name="line.45"></a>
+<span class="sourceLineNo">046</span>import org.apache.hadoop.hbase.io.hfile.HFileBlock;<a name="line.46"></a>
+<span class="sourceLineNo">047</span>import org.apache.hadoop.hbase.io.hfile.HFileContext;<a name="line.47"></a>
+<span class="sourceLineNo">048</span>import org.apache.hadoop.hbase.io.hfile.HFileContextBuilder;<a name="line.48"></a>
+<span class="sourceLineNo">049</span>import org.apache.hadoop.hbase.io.hfile.bucket.BucketAllocator.BucketSizeInfo;<a name="line.49"></a>
+<span class="sourceLineNo">050</span>import org.apache.hadoop.hbase.io.hfile.bucket.BucketAllocator.IndexStatistics;<a name="line.50"></a>
+<span class="sourceLineNo">051</span>import org.apache.hadoop.hbase.testclassification.IOTests;<a name="line.51"></a>
+<span class="sourceLineNo">052</span>import org.apache.hadoop.hbase.testclassification.MediumTests;<a name="line.52"></a>
+<span class="sourceLineNo">053</span>import org.junit.After;<a name="line.53"></a>
+<span class="sourceLineNo">054</span>import org.junit.Before;<a name="line.54"></a>
+<span class="sourceLineNo">055</span>import org.junit.ClassRule;<a name="line.55"></a>
+<span class="sourceLineNo">056</span>import org.junit.Test;<a name="line.56"></a>
+<span class="sourceLineNo">057</span>import org.junit.experimental.categories.Category;<a name="line.57"></a>
+<span class="sourceLineNo">058</span>import org.junit.runner.RunWith;<a name="line.58"></a>
+<span class="sourceLineNo">059</span>import org.junit.runners.Parameterized;<a name="line.59"></a>
+<span class="sourceLineNo">060</span><a name="line.60"></a>
+<span class="sourceLineNo">061</span>import org.apache.hbase.thirdparty.com.google.common.collect.ImmutableMap;<a name="line.61"></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> * Basic test of BucketCache.Puts and gets.<a name="line.64"></a>
+<span class="sourceLineNo">065</span> * &lt;p&gt;<a name="line.65"></a>
+<span class="sourceLineNo">066</span> * Tests will ensure that blocks' data correctness under several threads concurrency<a name="line.66"></a>
+<span class="sourceLineNo">067</span> */<a name="line.67"></a>
+<span class="sourceLineNo">068</span>@RunWith(Parameterized.class)<a name="line.68"></a>
+<span class="sourceLineNo">069</span>@Category({ IOTests.class, MediumTests.class })<a name="line.69"></a>
+<span class="sourceLineNo">070</span>public class TestBucketCache {<a name="line.70"></a>
+<span class="sourceLineNo">071</span><a name="line.71"></a>
+<span class="sourceLineNo">072</span>  @ClassRule<a name="line.72"></a>
+<span class="sourceLineNo">073</span>  public static final HBaseClassTestRule CLASS_RULE =<a name="line.73"></a>
+<span class="sourceLineNo">074</span>      HBaseClassTestRule.forClass(TestBucketCache.class);<a name="line.74"></a>
+<span class="sourceLineNo">075</span><a name="line.75"></a>
+<span class="sourceLineNo">076</span>  private static final Random RAND = new Random();<a name="line.76"></a>
+<span class="sourceLineNo">077</span><a name="line.77"></a>
+<span class="sourceLineNo">078</span>  @Parameterized.Parameters(name = "{index}: blockSize={0}, bucketSizes={1}")<a name="line.78"></a>
+<span class="sourceLineNo">079</span>  public static Iterable&lt;Object[]&gt; data() {<a name="line.79"></a>
+<span class="sourceLineNo">080</span>    return Arrays.asList(new Object[][] {<a name="line.80"></a>
+<span class="sourceLineNo">081</span>        { 8192, null }, // TODO: why is 8k the default blocksize for these tests?<a name="line.81"></a>
+<span class="sourceLineNo">082</span>        {<a name="line.82"></a>
+<span class="sourceLineNo">083</span>            16 * 1024,<a name="line.83"></a>
+<span class="sourceLineNo">084</span>            new int[] { 2 * 1024 + 1024, 4 * 1024 + 1024, 8 * 1024 + 1024, 16 * 1024 + 1024,<a name="line.84"></a>
+<span class="sourceLineNo">085</span>                28 * 1024 + 1024, 32 * 1024 + 1024, 64 * 1024 + 1024, 96 * 1024 + 1024,<a name="line.85"></a>
+<span class="sourceLineNo">086</span>                128 * 1024 + 1024 } } });<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>  @Parameterized.Parameter(0)<a name="line.89"></a>
+<span class="sourceLineNo">090</span>  public int constructedBlockSize;<a name="line.90"></a>
+<span class="sourceLineNo">091</span><a name="line.91"></a>
+<span class="sourceLineNo">092</span>  @Parameterized.Parameter(1)<a name="line.92"></a>
+<span class="sourceLineNo">093</span>  public int[] constructedBlockSizes;<a name="line.93"></a>
 <span class="sourceLineNo">094</span><a name="line.94"></a>
-<span class="sourceLineNo">095</span>  final long capacitySize = 32 * 1024 * 1024;<a name="line.95"></a>
-<span class="sourceLineNo">096</span>  final int writeThreads = BucketCache.DEFAULT_WRITER_THREADS;<a name="line.96"></a>
-<span class="sourceLineNo">097</span>  final int writerQLen = BucketCache.DEFAULT_WRITER_QUEUE_ITEMS;<a name="line.97"></a>
-<span class="sourceLineNo">098</span>  String ioEngineName = "offheap";<a name="line.98"></a>
-<span class="sourceLineNo">099</span>  String persistencePath = null;<a name="line.99"></a>
-<span class="sourceLineNo">100</span><a name="line.100"></a>
-<span class="sourceLineNo">101</span>  private static class MockedBucketCache extends BucketCache {<a name="line.101"></a>
-<span class="sourceLineNo">102</span><a name="line.102"></a>
-<span class="sourceLineNo">103</span>    public MockedBucketCache(String ioEngineName, long capacity, int blockSize, int[] bucketSizes,<a name="line.103"></a>
-<span class="sourceLineNo">104</span>        int writerThreads, int writerQLen, String persistencePath) throws FileNotFoundException,<a name="line.104"></a>
-<span class="sourceLineNo">105</span>        IOException {<a name="line.105"></a>
-<span class="sourceLineNo">106</span>      super(ioEngineName, capacity, blockSize, bucketSizes, writerThreads, writerQLen,<a name="line.106"></a>
-<span class="sourceLineNo">107</span>          persistencePath);<a name="line.107"></a>
-<span class="sourceLineNo">108</span>      super.wait_when_cache = true;<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>    @Override<a name="line.111"></a>
-<span class="sourceLineNo">112</span>    public void cacheBlock(BlockCacheKey cacheKey, Cacheable buf, boolean inMemory) {<a name="line.112"></a>
-<span class="sourceLineNo">113</span>      if (super.getBlock(cacheKey, true, false, true) != null) {<a name="line.113"></a>
-<span class="sourceLineNo">114</span>        throw new RuntimeException("Cached an already cached block");<a name="line.114"></a>
-<span class="sourceLineNo">115</span>      }<a name="line.115"></a>
-<span class="sourceLineNo">116</span>      super.cacheBlock(cacheKey, buf, inMemory);<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>    @Override<a name="line.119"></a>
-<span class="sourceLineNo">120</span>    public void cacheBlock(BlockCacheKey cacheKey, Cacheable buf) {<a name="line.120"></a>
-<span class="sourceLineNo">121</span>      if (super.getBlock(cacheKey, true, false, true) != null) {<a name="line.121"></a>
-<span class="sourceLineNo">122</span>        throw new RuntimeException("Cached an already cached block");<a name="line.122"></a>
-<span class="sourceLineNo">123</span>      }<a name="line.123"></a>
-<span class="sourceLineNo">124</span>      super.cacheBlock(cacheKey, buf);<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><a name="line.127"></a>
-<span class="sourceLineNo">128</span>  @Before<a name="line.128"></a>
-<span class="sourceLineNo">129</span>  public void setup() throws FileNotFoundException, IOException {<a name="line.129"></a>
-<span class="sourceLineNo">130</span>    cache =<a name="line.130"></a>
-<span class="sourceLineNo">131</span>        new MockedBucketCache(ioEngineName, capacitySize, constructedBlockSize,<a name="line.131"></a>
-<span class="sourceLineNo">132</span>            constructedBlockSizes, writeThreads, writerQLen, persistencePath);<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>  @After<a name="line.135"></a>
-<span class="sourceLineNo">136</span>  public void tearDown() {<a name="line.136"></a>
-<span class="sourceLineNo">137</span>    cache.shutdown();<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>   * Return a random element from {@code a}.<a name="line.141"></a>
-<span class="sourceLineNo">142</span>   */<a name="line.142"></a>
-<span class="sourceLineNo">143</span>  private static &lt;T&gt; T randFrom(List&lt;T&gt; a) {<a name="line.143"></a>
-<span class="sourceLineNo">144</span>    return a.get(RAND.nextInt(a.size()));<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>  @Test<a name="line.147"></a>
-<span class="sourceLineNo">148</span>  public void testBucketAllocator() throws BucketAllocatorException {<a name="line.148"></a>
-<span class="sourceLineNo">149</span>    BucketAllocator mAllocator = cache.getAllocator();<a name="line.149"></a>
-<span class="sourceLineNo">150</span>    /*<a name="line.150"></a>
-<span class="sourceLineNo">151</span>     * Test the allocator first<a name="line.151"></a>
-<span class="sourceLineNo">152</span>     */<a name="line.152"></a>
-<span class="sourceLineNo">153</span>    final List&lt;Integer&gt; BLOCKSIZES = Arrays.asList(4 * 1024, 8 * 1024, 64 * 1024, 96 * 1024);<a name="line.153"></a>
-<span class="sourceLineNo">154</span><a name="line.154"></a>
-<span class="sourceLineNo">155</span>    boolean full = false;<a name="line.155"></a>
-<span class="sourceLineNo">156</span>    ArrayList&lt;Long&gt; allocations = new ArrayList&lt;&gt;();<a name="line.156"></a>
-<span class="sourceLineNo">157</span>    // Fill the allocated extents by choosing a random blocksize. Continues selecting blocks until<a name="line.157"></a>
-<span class="sourceLineNo">158</span>    // the cache is completely filled.<a name="line.158"></a>
-<span class="sourceLineNo">159</span>    List&lt;Integer&gt; tmp = new ArrayList&lt;&gt;(BLOCKSIZES);<a name="line.159"></a>
-<span class="sourceLineNo">160</span>    while (!full) {<a name="line.160"></a>
-<span class="sourceLineNo">161</span>      Integer blockSize = null;<a name="line.161"></a>
-<span class="sourceLineNo">162</span>      try {<a name="line.162"></a>
-<span class="sourceLineNo">163</span>        blockSize = randFrom(tmp);<a name="line.163"></a>
-<span class="sourceLineNo">164</span>        allocations.add(mAllocator.allocateBlock(blockSize));<a name="line.164"></a>
-<span class="sourceLineNo">165</span>      } catch (CacheFullException cfe) {<a name="line.165"></a>
-<span class="sourceLineNo">166</span>        tmp.remove(blockSize);<a name="line.166"></a>
-<span class="sourceLineNo">167</span>        if (tmp.isEmpty()) full = true;<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>    for (Integer blockSize : BLOCKSIZES) {<a name="line.171"></a>
-<span class="sourceLineNo">172</span>      BucketSizeInfo bucketSizeInfo = mAllocator.roundUpToBucketSizeInfo(blockSize);<a name="line.172"></a>
-<span class="sourceLineNo">173</span>      IndexStatistics indexStatistics = bucketSizeInfo.statistics();<a name="line.173"></a>
-<span class="sourceLineNo">174</span>      assertEquals("unexpected freeCount for " + bucketSizeInfo, 0, indexStatistics.freeCount());<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>    for (long offset : allocations) {<a name="line.177"></a>
-<span class="sourceLineNo">178</span>      assertEquals(mAllocator.sizeOfAllocation(offset), mAllocator.freeBlock(offset));<a name="line.178"></a>
-<span class="sourceLineNo">179</span>    }<a name="line.179"></a>
-<span class="sourceLineNo">180</span>    assertEquals(0, mAllocator.getUsedSize());<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>  @Test<a name="line.183"></a>
-<span class="sourceLineNo">184</span>  public void testCacheSimple() throws Exception {<a name="line.184"></a>
-<span class="sourceLineNo">185</span>    CacheTestUtils.testCacheSimple(cache, BLOCK_SIZE, NUM_QUERIES);<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>  @Test<a name="line.188"></a>
-<span class="sourceLineNo">189</span>  public void testCacheMultiThreadedSingleKey() throws Exception {<a name="line.189"></a>
-<span class="sourceLineNo">190</span>    CacheTestUtils.hammerSingleKey(cache, BLOCK_SIZE, 2 * NUM_THREADS, 2 * NUM_QUERIES);<a name="line.190"></a>
-<span class="sourceLineNo">191</span>  }<a name="line.191"></a>
-<span class="sourceLineNo">192</span><a name="line.192"></a>
-<span class="sourceLineNo">193</span>  @Test<a name="line.193"></a>
-<span class="sourceLineNo">194</span>  public void testHeapSizeChanges() throws Exception {<a name="line.194"></a>
-<span class="sourceLineNo">195</span>    cache.stopWriterThreads();<a name="line.195"></a>
-<span class="sourceLineNo">196</span>    CacheTestUtils.testHeapSizeChanges(cache, BLOCK_SIZE);<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>  // BucketCache.cacheBlock is async, it first adds block to ramCache and writeQueue, then writer<a name="line.199"></a>
-<span class="sourceLineNo">200</span>  // threads will flush it to the bucket and put reference entry in backingMap.<a name="line.200"></a>
-<span class="sourceLineNo">201</span>  private void cacheAndWaitUntilFlushedToBucket(BucketCache cache, BlockCacheKey cacheKey,<a name="line.201"></a>
-<span class="sourceLineNo">202</span>      Cacheable block) throws InterruptedException {<a name="line.202"></a>
-<span class="sourceLineNo">203</span>    cache.cacheBlock(cacheKey, block);<a name="line.203"></a>
-<span class="sourceLineNo">204</span>    while (!cache.backingMap.containsKey(cacheKey)) {<a name="line.204"></a>
-<span class="sourceLineNo">205</span>      Thread.sleep(100);<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><a name="line.208"></a>
-<span class="sourceLineNo">209</span>  @Test<a name="line.209"></a>
-<span class="sourceLineNo">210</span>  public void testMemoryLeak() throws Exception {<a name="line.210"></a>
-<span class="sourceLineNo">211</span>    final BlockCacheKey cacheKey = new BlockCacheKey("dummy", 1L);<a name="line.211"></a>
-<span class="sourceLineNo">212</span>    cacheAndWaitUntilFlushedToBucket(cache, cacheKey, new CacheTestUtils.ByteArrayCacheable(<a name="line.212"></a>
-<span class="sourceLineNo">213</span>        new byte[10]));<a name="line.213"></a>
-<span class="sourceLineNo">214</span>    long lockId = cache.backingMap.get(cacheKey).offset();<a name="line.214"></a>
-<span class="sourceLineNo">215</span>    ReentrantReadWriteLock lock = cache.offsetLock.getLock(lockId);<a name="line.215"></a>
-<span class="sourceLineNo">216</span>    lock.writeLock().lock();<a name="line.216"></a>
-<span class="sourceLineNo">217</span>    Thread evictThread = new Thread("evict-block") {<a name="line.217"></a>
-<span class="sourceLineNo">218</span><a name="line.218"></a>
-<span class="sourceLineNo">219</span>      @Override<a name="line.219"></a>
-<span class="sourceLineNo">220</span>      public void run() {<a name="line.220"></a>
-<span class="sourceLineNo">221</span>        cache.evictBlock(cacheKey);<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>    };<a name="line.224"></a>
-<span class="sourceLineNo">225</span>    evictThread.start();<a name="line.225"></a>
-<span class="sourceLineNo">226</span>    cache.offsetLock.waitForWaiters(lockId, 1);<a name="line.226"></a>
-<span class="sourceLineNo">227</span>    cache.blockEvicted(cacheKey, cache.backingMap.remove(cacheKey), true);<a name="line.227"></a>
-<span class="sourceLineNo">228</span>    cacheAndWaitUntilFlushedToBucket(cache, cacheKey, new CacheTestUtils.ByteArrayCacheable(<a name="line.228"></a>
-<span class="sourceLineNo">229</span>        new byte[10]));<a name="line.229"></a>
-<span class="sourceLineNo">230</span>    lock.writeLock().unlock();<a name="line.230"></a>
-<span class="sourceLineNo">231</span>    evictThread.join();<a name="line.231"></a>
-<span class="sourceLineNo">232</span>    assertEquals(1L, cache.getBlockCount());<a name="line.232"></a>
-<span class="sourceLineNo">233</span>    assertTrue(cache.getCurrentSize() &gt; 0L);<a name="line.233"></a>
-<span class="sourceLineNo">234</span>    assertTrue("We should have a block!", cache.iterator().hasNext());<a name="line.234"></a>
-<span class="sourceLineNo">235</span>  }<a name="line.235"></a>
-<span class="sourceLineNo">236</span><a name="line.236"></a>
-<span class="sourceLineNo">237</span>  @Test<a name="line.237"></a>
-<span class="sourceLineNo">238</span>  public void testRetrieveFromFile() throws Exception {<a name="line.238"></a>
-<span class="sourceLineNo">239</span>    HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();<a name="line.239"></a>
-<span class="sourceLineNo">240</span>    Path testDir = TEST_UTIL.getDataTestDir();<a name="line.240"></a>
-<span class="sourceLineNo">241</span>    TEST_UTIL.getTestFileSystem().mkdirs(testDir);<a name="line.241"></a>
-<span class="sourceLineNo">242</span><a name="line.242"></a>
-<span class="sourceLineNo">243</span>    BucketCache bucketCache = new BucketCache("file:" + testDir + "/bucket.cache", capacitySize,<a name="line.243"></a>
-<span class="sourceLineNo">244</span>        constructedBlockSize, constructedBlockSizes, writeThreads, writerQLen, testDir<a name="line.244"></a>
-<span class="sourceLineNo">245</span>            + "/bucket.persistence");<a name="line.245"></a>
-<span class="sourceLineNo">246</span>    long usedSize = bucketCache.getAllocator().getUsedSize();<a name="line.246"></a>
-<span class="sourceLineNo">247</span>    assertTrue(usedSize == 0);<a name="line.247"></a>
-<span class="sourceLineNo">248</span><a name="line.248"></a>
-<span class="sourceLineNo">249</span>    HFileBlockPair[] blocks = CacheTestUtils.generateHFileBlocks(constructedBlockSize, 1);<a name="line.249"></a>
-<span class="sourceLineNo">250</span>    // Add blocks<a name="line.250"></a>
-<span class="sourceLineNo">251</span>    for (HFileBlockPair block : blocks) {<a name="line.251"></a>
-<span class="sourceLineNo">252</span>      bucketCache.cacheBlock(block.getBlockName(), block.getBlock());<a name="line.252"></a>
-<span class="sourceLineNo">253</span>    }<a name="line.253"></a>
-<span class="sourceLineNo">254</span>    for (HFileBlockPair block : blocks) {<a name="line.254"></a>
-<span class="sourceLineNo">255</span>      cacheAndWaitUntilFlushedToBucket(bucketCache, block.getBlockName(), block.getBlock());<a name="line.255"></a>
-<span class="sourceLineNo">256</span>    }<a name="line.256"></a>
-<span class="sourceLineNo">257</span>    usedSize = bucketCache.getAllocator().getUsedSize();<a name="line.257"></a>
-<span class="sourceLineNo">258</span>    assertTrue(usedSize != 0);<a name="line.258"></a>
-<span class="sourceLineNo">259</span>    // persist cache to file<a name="line.259"></a>
-<span class="sourceLineNo">260</span>    bucketCache.shutdown();<a name="line.260"></a>
-<span class="sourceLineNo">261</span><a name="line.261"></a>
-<span class="sourceLineNo">262</span>    // restore cache from file<a name="line.262"></a>
-<span class="sourceLineNo">263</span>    bucketCache = new BucketCache("file:" + testDir + "/bucket.cache", capacitySize,<a name="line.263"></a>
-<span class="sourceLineNo">264</span>        constructedBlockSize, constructedBlockSizes, writeThreads, writerQLen, testDir<a name="line.264"></a>
-<span class="sourceLineNo">265</span>            + "/bucket.persistence");<a name="line.265"></a>
-<span class="sourceLineNo">266</span>    assertEquals(usedSize, bucketCache.getAllocator().getUsedSize());<a name="line.266"></a>
-<span class="sourceLineNo">267</span>    // persist cache to file<a name="line.267"></a>
-<span class="sourceLineNo">268</span>    bucketCache.shutdown();<a name="line.268"></a>
-<span class="sourceLineNo">269</span><a name="line.269"></a>
-<span class="sourceLineNo">270</span>    // reconfig buckets sizes, the biggest bucket is small than constructedBlockSize (8k or 16k)<a name="line.270"></a>
-<span class="sourceLineNo">271</span>    // so it can't restore cache from file<a name="line.271"></a>
-<span class="sourceLineNo">272</span>    int[] smallBucketSizes = new int[] { 2 * 1024 + 1024, 4 * 1024 + 1024 };<a name="line.272"></a>
-<span class="sourceLineNo">273</span>    bucketCache = new BucketCache("file:" + testDir + "/bucket.cache", capacitySize,<a name="line.273"></a>
-<span class="sourceLineNo">274</span>        constructedBlockSize, smallBucketSizes, writeThreads,<a name="line.274"></a>
-<span class="sourceLineNo">275</span>        writerQLen, testDir + "/bucket.persistence");<a name="line.275"></a>
-<span class="sourceLineNo">276</span>    assertEquals(0, bucketCache.getAllocator().getUsedSize());<a name="line.276"></a>
-<span class="sourceLineNo">277</span>    assertEquals(0, bucketCache.backingMap.size());<a name="line.277"></a>
-<span class="sourceLineNo">278</span><a name="line.278"></a>
-<span class="sourceLineNo">279</span>    TEST_UTIL.cleanupTestDir();<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>  @Test<a name="line.282"></a>
-<span class="sourceLineNo">283</span>  public void testBucketAllocatorLargeBuckets() throws BucketAllocatorException {<a name="line.283"></a>
-<span class="sourceLineNo">284</span>    long availableSpace = 20 * 1024L * 1024 * 1024;<a name="line.284"></a>
-<span class="sourceLineNo">285</span>    int[] bucketSizes = new int[]{1024, 1024 * 1024, 1024 * 1024 * 1024};<a name="line.285"></a>
-<span class="sourceLineNo">286</span>    BucketAllocator allocator = new BucketAllocator(availableSpace, bucketSizes);<a name="line.286"></a>
-<span class="sourceLineNo">287</span>    assertTrue(allocator.getBuckets().length &gt; 0);<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>  @Test<a name="line.290"></a>
-<span class="sourceLineNo">291</span>  public void testGetPartitionSize() throws IOException {<a name="line.291"></a>
-<span class="sourceLineNo">292</span>    //Test default values<a name="line.292"></a>
-<span class="sourceLineNo">293</span>    validateGetPartitionSize(cache, BucketCache.DEFAULT_SINGLE_FACTOR, BucketCache.DEFAULT_MIN_FACTOR);<a name="line.293"></a>
-<span class="sourceLineNo">294</span><a name="line.294"></a>
-<span class="sourceLineNo">295</span>    Configuration conf = HBaseConfiguration.create();<a name="line.295"></a>
-<span class="sourceLineNo">296</span>    conf.setFloat(BucketCache.MIN_FACTOR_CONFIG_NAME, 0.5f);<a name="line.296"></a>
-<span class="sourceLineNo">297</span>    conf.setFloat(BucketCache.SINGLE_FACTOR_CONFIG_NAME, 0.1f);<a name="line.297"></a>
-<span class="sourceLineNo">298</span>    conf.setFloat(BucketCache.MULTI_FACTOR_CONFIG_NAME, 0.7f);<a name="line.298"></a>
-<span class="sourceLineNo">299</span>    conf.setFloat(BucketCache.MEMORY_FACTOR_CONFIG_NAME, 0.2f);<a name="line.299"></a>
-<span class="sourceLineNo">300</span><a name="line.300"></a>
-<span class="sourceLineNo">301</span>    BucketCache cache = new BucketCache(ioEngineName, capacitySize, constructedBlockSize,<a name="line.301"></a>
-<span class="sourceLineNo">302</span>        constructedBlockSizes, writeThreads, writerQLen, persistencePath, 100, conf);<a name="line.302"></a>
-<span class="sourceLineNo">303</span><a name="line.303"></a>
-<span class="sourceLineNo">304</span>    validateGetPartitionSize(cache, 0.1f, 0.5f);<a name="line.304"></a>
-<span class="sourceLineNo">305</span>    validateGetPartitionSize(cache, 0.7f, 0.5f);<a name="line.305"></a>
-<span class="sourceLineNo">306</span>    validateGetPartitionSize(cache, 0.2f, 0.5f);<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>  @Test<a name="line.309"></a>
-<span class="sourceLineNo">310</span>  public void testValidBucketCacheConfigs() throws IOException {<a name="line.310"></a>
-<span class="sourceLineNo">311</span>    Configuration conf = HBaseConfiguration.create();<a name="line.311"></a>
-<span class="sourceLineNo">312</span>    conf.setFloat(BucketCache.ACCEPT_FACTOR_CONFIG_NAME, 0.9f);<a name="line.312"></a>
-<span class="sourceLineNo">313</span>    conf.setFloat(BucketCache.MIN_FACTOR_CONFIG_NAME, 0.5f);<a name="line.313"></a>
-<span class="sourceLineNo">314</span>    conf.setFloat(BucketCache.EXTRA_FREE_FACTOR_CONFIG_NAME, 0.5f);<a name="line.314"></a>
-<span class="sourceLineNo">315</span>    conf.setFloat(BucketCache.SINGLE_FACTOR_CONFIG_NAME, 0.1f);<a name="line.315"></a>
-<span class="sourceLineNo">316</span>    conf.setFloat(BucketCache.MULTI_FACTOR_CONFIG_NAME, 0.7f);<a name="line.316"></a>
-<span class="sourceLineNo">317</span>    conf.setFloat(BucketCache.MEMORY_FACTOR_CONFIG_NAME, 0.2f);<a name="line.317"></a>
-<span class="sourceLineNo">318</span><a name="line.318"></a>
-<span class="sourceLineNo">319</span>    BucketCache cache = new BucketCache(ioEngineName, capacitySize, constructedBlockSize,<a name="line.319"></a>
-<span class="sourceLineNo">320</span>        constructedBlockSizes, writeThreads, writerQLen, persistencePath, 100, conf);<a name="line.320"></a>
-<span class="sourceLineNo">321</span><a name="line.321"></a>
-<span class="sourceLineNo">322</span>    assertEquals(BucketCache.ACCEPT_FACTOR_CONFIG_NAME + " failed to propagate.", 0.9f,<a name="line.322"></a>
-<span class="sourceLineNo">323</span>        cache.getAcceptableFactor(), 0);<a name="line.323"></a>
-<span class="sourceLineNo">324</span>    assertEquals(BucketCache.MIN_FACTOR_CONFIG_NAME + " failed to propagate.", 0.5f,<a name="line.324"></a>
-<span class="sourceLineNo">325</span>        cache.getMinFactor(), 0);<a name="line.325"></a>
-<span class="sourceLineNo">326</span>    assertEquals(BucketCache.EXTRA_FREE_FACTOR_CONFIG_NAME + " failed to propagate.", 0.5f,<a name="line.326"></a>
-<span class="sourceLineNo">327</span>        cache.getExtraFreeFactor(), 0);<a name="line.327"></a>
-<span class="sourceLineNo">328</span>    assertEquals(BucketCache.SINGLE_FACTOR_CONFIG_NAME + " failed to propagate.", 0.1f,<a name="line.328"></a>
-<span class="sourceLineNo">329</span>        cache.getSingleFactor(), 0);<a name="line.329"></a>
-<span class="sourceLineNo">330</span>    assertEquals(BucketCache.MULTI_FACTOR_CONFIG_NAME + " failed to propagate.", 0.7f,<a name="line.330"></a>
-<span class="sourceLineNo">331</span>        cache.getMultiFactor(), 0);<a name="line.331"></a>
-<span class="sourceLineNo">332</span>    assertEquals(BucketCache.MEMORY_FACTOR_CONFIG_NAME + " failed to propagate.", 0.2f,<a name="line.332"></a>
-<span class="sourceLineNo">333</span>        cache.getMemoryFactor(), 0);<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>  @Test<a name="line.336"></a>
-<span class="sourceLineNo">337</span>  public void testInvalidAcceptFactorConfig() throws IOException {<a name="line.337"></a>
-<span class="sourceLineNo">338</span>    float[] configValues = {-1f, 0.2f, 0.86f, 1.05f};<a name="line.338"></a>
-<span class="sourceLineNo">339</span>    boolean[] expectedOutcomes = {false, false, true, false};<a name="line.339"></a>
-<span class="sourceLineNo">340</span>    Map&lt;String, float[]&gt; configMappings = ImmutableMap.of(BucketCache.ACCEPT_FACTOR_CONFIG_NAME, configValues);<a name="line.340"></a>
-<span class="sourceLineNo">341</span>    Configuration conf = HBaseConfiguration.create();<a name="line.341"></a>
-<span class="sourceLineNo">342</span>    checkConfigValues(conf, configMappings, expectedOutcomes);<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>  @Test<a name="line.345"></a>
-<span class="sourceLineNo">346</span>  public void testInvalidMinFactorConfig() throws IOException {<a name="line.346"></a>
-<span class="sourceLineNo">347</span>    float[] configValues = {-1f, 0f, 0.96f, 1.05f};<a name="line.347"></a>
-<span class="sourceLineNo">348</span>    //throws due to &lt;0, in expected range, minFactor &gt; acceptableFactor, &gt; 1.0<a name="line.348"></a>
-<span class="sourceLineNo">349</span>    boolean[] expectedOutcomes = {false, true, false, false};<a name="line.349"></a>
-<span class="sourceLineNo">350</span>    Map&lt;String, float[]&gt; configMappings = ImmutableMap<a name="line.350"></a>
-<span class="sourceLineNo">351</span>      .of(BucketCache.MIN_FACTOR_CONFIG_NAME, configValues);<a name="line.351"></a>
-<span class="sourceLineNo">352</span>    Configuration conf = HBaseConfiguration.create();<a name="line.352"></a>
-<span class="sourceLineNo">353</span>    checkConfigValues(conf, configMappings, expectedOutcomes);<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>  @Test<a name="line.356"></a>
-<span class="sourceLineNo">357</span>  public void testInvalidExtraFreeFactorConfig() throws IOException {<a name="line.357"></a>
-<span class="sourceLineNo">358</span>    float[] configValues = {-1f, 0f, 0.2f, 1.05f};<a name="line.358"></a>
-<span class="sourceLineNo">359</span>    //throws due to &lt;0, in expected range, in expected range, config can be &gt; 1.0<a name="line.359"></a>
-<span class="sourceLineNo">360</span>    boolean[] expectedOutcomes = {false, true, true, true};<a name="line.360"></a>
-<span class="sourceLineNo">361</span>    Map&lt;String, float[]&gt; configMappings = ImmutableMap.of(BucketCache.EXTRA_FREE_FACTOR_CONFIG_NAME, configValues);<a name="line.361"></a>
-<span class="sourceLineNo">362</span>    Configuration conf = HBaseConfiguration.create();<a name="line.362"></a>
-<span class="sourceLineNo">363</span>    checkConfigValues(conf, configMappings, expectedOutcomes);<a name="line.363"></a>
-<span class="sourceLineNo">364</span>  }<a name="line.364"></a>
-<span class="sourceLineNo">365</span><a name="line.365"></a>
-<span class="sourceLineNo">366</span>  @Test<a name="line.366"></a>
-<span class="sourceLineNo">367</span>  public void testInvalidCacheSplitFactorConfig() throws IOException {<a name="line.367"></a>
-<span class="sourceLineNo">368</span>    float[] singleFactorConfigValues = {0.2f, 0f, -0.2f, 1f};<a name="line.368"></a>
-<span class="sourceLineNo">369</span>    float[] multiFactorConfigValues = {0.4f, 0f, 1f, .05f};<a name="line.369"></a>
-<span class="sourceLineNo">370</span>    float[] memoryFactorConfigValues = {0.4f, 0f, 0.2f, .5f};<a name="line.370"></a>
-<span class="sourceLineNo">371</span>    // All configs add up to 1.0 and are between 0 and 1.0, configs don't add to 1.0, configs can't be negative, configs don't add to 1.0<a name="line.371"></a>
-<span class="sourceLineNo">372</span>    boolean[] expectedOutcomes = {true, false, false, false};<a name="line.372"></a>
-<span class="sourceLineNo">373</span>    Map&lt;String, float[]&gt; configMappings = ImmutableMap.of(BucketCache.SINGLE_FACTOR_CONFIG_NAME,<a name="line.373"></a>
-<span class="sourceLineNo">374</span>        singleFactorConfigValues, BucketCache.MULTI_FACTOR_CONFIG_NAME, multiFactorConfigValues,<a name="line.374"></a>
-<span class="sourceLineNo">375</span>        BucketCache.MEMORY_FACTOR_CONFIG_NAME, memoryFactorConfigValues);<a name="line.375"></a>
-<span class="sourceLineNo">376</span>    Configuration conf = HBaseConfiguration.create();<a name="line.376"></a>
-<span class="sourceLineNo">377</span>    checkConfigValues(conf, configMappings, expectedOutcomes);<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>  private void checkConfigValues(Configuration conf, Map&lt;String, float[]&gt; configMap, boolean[] expectSuccess) throws IOException {<a name="line.380"></a>
-<span class="sourceLineNo">381</span>    Set&lt;String&gt; configNames = configMap.keySet();<a name="line.381"></a>
-<span class="sourceLineNo">382</span>    for (int i = 0; i &lt; expectSuccess.length; i++) {<a name="line.382"></a>
-<span class="sourceLineNo">383</span>      try {<a name="line.383"></a>
-<span class="sourceLineNo">384</span>        for (String configName : configNames) {<a name="line.384"></a>
-<span class="sourceLineNo">385</span>          conf.setFloat(configName, configMap.get(configName)[i]);<a name="line.385"></a>
-<span class="sourceLineNo">386</span>        }<a name="line.386"></a>
-<span class="sourceLineNo">387</span>        BucketCache cache = new BucketCache(ioEngineName, capacitySize, constructedBlockSize,<a name="line.387"></a>
-<span class="sourceLineNo">388</span>            constructedBlockSizes, writeThreads, writerQLen, persistencePath, 100, conf);<a name="line.388"></a>
-<span class="sourceLineNo">389</span>        assertTrue("Created BucketCache and expected it to succeed: " + expectSuccess[i] + ", but it actually was: " + !expectSuccess[i], expectSuccess[i]);<a name="line.389"></a>
-<span class="sourceLineNo">390</span>      } catch (IllegalArgumentException e) {<a name="line.390"></a>
-<span class="sourceLineNo">391</span>        assertFalse("Created BucketCache and expected it to succeed: " + expectSuccess[i] + ", but it actually was: " + !expectSuccess[i], expectSuccess[i]);<a name="line.391"></a>
-<span class="sourceLineNo">392</span>      }<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>  private void validateGetPartitionSize(BucketCache bucketCache, float partitionFactor, float minFactor) {<a name="line.396"></a>
-<span class="sourceLineNo">397</span>    long expectedOutput = (long) Math.floor(bucketCache.getAllocator().getTotalSize() * partitionFactor * minFactor);<a name="line.397"></a>
-<span class="sourceLineNo">398</span>    assertEquals(expectedOutput, bucketCache.getPartitionSize(partitionFactor));<a name="line.398"></a>
-<span class="sourceLineNo">399</span>  }<a name="line.399"></a>
-<span class="sourceLineNo">400</span><a name="line.400"></a>
-<span class="sourceLineNo">401</span>  @Test<a name="line.401"></a>
-<span class="sourceLineNo">402</span>  public void testOffsetProducesPositiveOutput() {<a name="line.402"></a>
-<span class="sourceLineNo">403</span>    //This number is picked because it produces negative output if the values isn't ensured to be positive.<a name="line.403"></a>
-<span class="sourceLineNo">404</span>    //See HBASE-18757 for more information.<a name="line.404"></a>
-<span class="sourceLineNo">405</span>    long testValue = 549888460800L;<a name="line.405"></a>
-<span class="sourceLineNo">406</span>    BucketCache.BucketEntry bucketEntry = new BucketCache.BucketEntry(testValue, 10, 10L, true);<a name="line.406"></a>
-<span class="sourceLineNo">407</span>    assertEquals(testValue, bucketEntry.offset());<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">095</span>  BucketCache cache;<a name="line.95"></a>
+<span class="sourceLineNo">096</span>  final int CACHE_SIZE = 1000000;<a name="line.96"></a>
+<span class="sourceLineNo">097</span>  final int NUM_BLOCKS = 100;<a name="line.97"></a>
+<span class="sourceLineNo">098</span>  final int BLOCK_SIZE = CACHE_SIZE / NUM_BLOCKS;<a name="line.98"></a>
+<span class="sourceLineNo">099</span>  final int NUM_THREADS = 100;<a name="line.99"></a>
+<span class="sourceLineNo">100</span>  final int NUM_QUERIES = 10000;<a name="line.100"></a>
+<span class="sourceLineNo">101</span><a name="line.101"></a>
+<span class="sourceLineNo">102</span>  final long capacitySize = 32 * 1024 * 1024;<a name="line.102"></a>
+<span class="sourceLineNo">103</span>  final int writeThreads = BucketCache.DEFAULT_WRITER_THREADS;<a name="line.103"></a>
+<span class="sourceLineNo">104</span>  final int writerQLen = BucketCache.DEFAULT_WRITER_QUEUE_ITEMS;<a name="line.104"></a>
+<span class="sourceLineNo">105</span>  String ioEngineName = "offheap";<a name="line.105"></a>
+<span class="sourceLineNo">106</span>  String persistencePath = null;<a name="line.106"></a>
+<span class="sourceLineNo">107</span><a name="line.107"></a>
+<span class="sourceLineNo">108</span>  private static class MockedBucketCache extends BucketCache {<a name="line.108"></a>
+<span class="sourceLineNo">109</span><a name="line.109"></a>
+<span class="sourceLineNo">110</span>    public MockedBucketCache(String ioEngineName, long capacity, int blockSize, int[] bucketSizes,<a name="line.110"></a>
+<span class="sourceLineNo">111</span>        int writerThreads, int writerQLen, String persistencePath) throws FileNotFoundException,<a name="line.111"></a>
+<span class="sourceLineNo">112</span>        IOException {<a name="line.112"></a>
+<span class="sourceLineNo">113</span>      super(ioEngineName, capacity, blockSize, bucketSizes, writerThreads, writerQLen,<a name="line.113"></a>
+<span class="sourceLineNo">114</span>          persistencePath);<a name="line.114"></a>
+<span class="sourceLineNo">115</span>      super.wait_when_cache = true;<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>    @Override<a name="line.118"></a>
+<span class="sourceLineNo">119</span>    public void cacheBlock(BlockCacheKey cacheKey, Cacheable buf, boolean inMemory) {<a name="line.119"></a>
+<span class="sourceLineNo">120</span>      super.cacheBlock(cacheKey, buf, inMemory);<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>    @Override<a name="line.123"></a>
+<span class="sourceLineNo">124</span>    public void cacheBlock(BlockCacheKey cacheKey, Cacheable buf) {<a name="line.124"></a>
+<span class="sourceLineNo">125</span>      super.cacheBlock(cacheKey, buf);<a name="line.125"></a>
+<span class="sourceLineNo">126</span>    }<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>  @Before<a name="line.129"></a>
+<span class="sourceLineNo">130</span>  public void setup() throws FileNotFoundException, IOException {<a name="line.130"></a>
+<span class="sourceLineNo">131</span>    cache =<a name="line.131"></a>
+<span class="sourceLineNo">132</span>        new MockedBucketCache(ioEngineName, capacitySize, constructedBlockSize,<a name="line.132"></a>
+<span class="sourceLineNo">133</span>            constructedBlockSizes, writeThreads, writerQLen, persistencePath);<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>  @After<a name="line.136"></a>
+<span class="sourceLineNo">137</span>  public void tearDown() {<a name="line.137"></a>
+<span class="sourceLineNo">138</span>    cache.shutdown();<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>   * Return a random element from {@code a}.<a name="line.142"></a>
+<span class="sourceLineNo">143</span>   */<a name="line.143"></a>
+<span class="sourceLineNo">144</span>  private static &lt;T&gt; T randFrom(List&lt;T&gt; a) {<a name="line.144"></a>
+<span class="sourceLineNo">145</span>    return a.get(RAND.nextInt(a.size()));<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>  @Test<a name="line.148"></a>
+<span class="sourceLineNo">149</span>  public void testBucketAllocator() throws BucketAllocatorException {<a name="line.149"></a>
+<span class="sourceLineNo">150</span>    BucketAllocator mAllocator = cache.getAllocator();<a name="line.150"></a>
+<span class="sourceLineNo">151</span>    /*<a name="line.151"></a>
+<span class="sourceLineNo">152</span>     * Test the allocator first<a name="line.152"></a>
+<span class="sourceLineNo">153</span>     */<a name="line.153"></a>
+<span class="sourceLineNo">154</span>    final List&lt;Integer&gt; BLOCKSIZES = Arrays.asList(4 * 1024, 8 * 1024, 64 * 1024, 96 * 1024);<a name="line.154"></a>
+<span class="sourceLineNo">155</span><a name="line.155"></a>
+<span class="sourceLineNo">156</span>    boolean full = false;<a name="line.156"></a>
+<span class="sourceLineNo">157</span>    ArrayList&lt;Long&gt; allocations = new ArrayList&lt;&gt;();<a name="line.157"></a>
+<span class="sourceLineNo">158</span>    // Fill the allocated extents by choosing a random blocksize. Continues selecting blocks until<a name="line.158"></a>
+<span class="sourceLineNo">159</span>    // the cache is completely filled.<a name="line.159"></a>
+<span class="sourceLineNo">160</span>    List&lt;Integer&gt; tmp = new ArrayList&lt;&gt;(BLOCKSIZES);<a name="line.160"></a>
+<span class="sourceLineNo">161</span>    while (!full) {<a name="line.161"></a>
+<span class="sourceLineNo">162</span>      Integer blockSize = null;<a name="line.162"></a>
+<span class="sourceLineNo">163</span>      try {<a name="line.163"></a>
+<span class="sourceLineNo">164</span>        blockSize = randFrom(tmp);<a name="line.164"></a>
+<span class="sourceLineNo">165</span>        allocations.add(mAllocator.allocateBlock(blockSize));<a name="line.165"></a>
+<span class="sourceLineNo">166</span>      } catch (CacheFullException cfe) {<a name="line.166"></a>
+<span class="sourceLineNo">167</span>        tmp.remove(blockSize);<a name="line.167"></a>
+<span class="sourceLineNo">168</span>        if (tmp.isEmpty()) full = true;<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>    for (Integer blockSize : BLOCKSIZES) {<a name="line.172"></a>
+<span class="sourceLineNo">173</span>      BucketSizeInfo bucketSizeInfo = mAllocator.roundUpToBucketSizeInfo(blockSize);<a name="line.173"></a>
+<span class="sourceLineNo">174</span>      IndexStatistics indexStatistics = bucketSizeInfo.statistics();<a name="line.174"></a>
+<span class="sourceLineNo">175</span>      assertEquals("unexpected freeCount for " + bucketSizeInfo, 0, indexStatistics.freeCount());<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>    for (long offset : allocations) {<a name="line.178"></a>
+<span class="sourceLineNo">179</span>      assertEquals(mAllocator.sizeOfAllocation(offset), mAllocator.freeBlock(offset));<a name="line.179"></a>
+<span class="sourceLineNo">180</span>    }<a name="line.180"></a>
+<span class="sourceLineNo">181</span>    assertEquals(0, mAllocator.getUsedSize());<a name="line.181"></a>
+<span class="sourceLineNo">182</span>  }<a name="line.182"></a>
+<span class="sourceLineNo">183</span><a name="line.183"></a>
+<span class="sourceLineNo">184</span>  @Test<a name="line.184"></a>
+<span class="sourceLineNo">185</span>  public void testCacheSimple() throws Exception {<a name="line.185"></a>
+<span class="sourceLineNo">186</span>    CacheTestUtils.testCacheSimple(cache, BLOCK_SIZE, NUM_QUERIES);<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>  @Test<a name="line.189"></a>
+<span class="sourceLineNo">190</span>  public void testCacheMultiThreadedSingleKey() throws Exception {<a name="line.190"></a>
+<span class="sourceLineNo">191</span>    CacheTestUtils.hammerSingleKey(cache, BLOCK_SIZE, 2 * NUM_THREADS, 2 * NUM_QUERIES);<a name="line.191"></a>
+<span class="sourceLineNo">192</span>  }<a name="line.192"></a>
+<span class="sourceLineNo">193</span><a name="line.193"></a>
+<span class="sourceLineNo">194</span>  @Test<a name="line.194"></a>
+<span class="sourceLineNo">195</span>  public void testHeapSizeChanges() throws Exception {<a name="line.195"></a>
+<span class="sourceLineNo">196</span>    cache.stopWriterThreads();<a name="line.196"></a>
+<span class="sourceLineNo">197</span>    CacheTestUtils.testHeapSizeChanges(cache, BLOCK_SIZE);<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>  // BucketCache.cacheBlock is async, it first adds block to ramCache and writeQueue, then writer<a name="line.200"></a>
+<span class="sourceLineNo">201</span>  // threads will flush it to the bucket and put reference entry in backingMap.<a name="line.201"></a>
+<span class="sourceLineNo">202</span>  private void cacheAndWaitUntilFlushedToBucket(BucketCache cache, BlockCacheKey cacheKey,<a name="line.202"></a>
+<span class="sourceLineNo">203</span>      Cacheable block) throws InterruptedException {<a name="line.203"></a>
+<span class="sourceLineNo">204</span>    cache.cacheBlock(cacheKey, block);<a name="line.204"></a>
+<span class="sourceLineNo">205</span>    while (!cache.backingMap.containsKey(cacheKey)) {<a name="line.205"></a>
+<span class="sourceLineNo">206</span>      Thread.sleep(100);<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><a name="line.209"></a>
+<span class="sourceLineNo">210</span>  @Test<a name="line.210"></a>
+<span class="sourceLineNo">211</span>  public void testMemoryLeak() throws Exception {<a name="line.211"></a>
+<span class="sourceLineNo">212</span>    final BlockCacheKey cacheKey = new BlockCacheKey("dummy", 1L);<a name="line.212"></a>
+<span class="sourceLineNo">213</span>    cacheAndWaitUntilFlushedToBucket(cache, cacheKey, new CacheTestUtils.ByteArrayCacheable(<a name="line.213"></a>
+<span class="sourceLineNo">214</span>        new byte[10]));<a name="line.214"></a>
+<span class="sourceLineNo">215</span>    long lockId = cache.backingMap.get(cacheKey).offset();<a name="line.215"></a>
+<span class="sourceLineNo">216</span>    ReentrantReadWriteLock lock = cache.offsetLock.getLock(lockId);<a name="line.216"></a>
+<span class="sourceLineNo">217</span>    lock.writeLock().lock();<a name="line.217"></a>
+<span class="sourceLineNo">218</span>    Thread evictThread = new Thread("evict-block") {<a name="line.218"></a>
+<span class="sourceLineNo">219</span><a name="line.219"></a>
+<span class="sourceLineNo">220</span>      @Override<a name="line.220"></a>
+<span class="sourceLineNo">221</span>      public void run() {<a name="line.221"></a>
+<span class="sourceLineNo">222</span>        cache.evictBlock(cacheKey);<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>    };<a name="line.225"></a>
+<span class="sourceLineNo">226</span>    evictThread.start();<a name="line.226"></a>
+<span class="sourceLineNo">227</span>    cache.offsetLock.waitForWaiters(lockId, 1);<a name="line.227"></a>
+<span class="sourceLineNo">228</span>    cache.blockEvicted(cacheKey, cache.backingMap.remove(cacheKey), true);<a name="line.228"></a>
+<span class="sourceLineNo">229</span>    cacheAndWaitUntilFlushedToBucket(cache, cacheKey, new CacheTestUtils.ByteArrayCacheable(<a name="line.229"></a>
+<span class="sourceLineNo">230</span>        new byte[10]));<a name="line.230"></a>
+<span class="sourceLineNo">231</span>    lock.writeLock().unlock();<a name="line.231"></a>
+<span class="sourceLineNo">232</span>    evictThread.join();<a name="line.232"></a>
+<span class="sourceLineNo">233</span>    assertEquals(1L, cache.getBlockCount());<a name="line.233"></a>
+<span class="sourceLineNo">234</span>    assertTrue(cache.getCurrentSize() &gt; 0L);<a name="line.234"></a>
+<span class="sourceLineNo">235</span>    assertTrue("We should have a block!", cache.iterator().hasNext());<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>  @Test<a name="line.238"></a>
+<span class="sourceLineNo">239</span>  public void testRetrieveFromFile() throws Exception {<a name="line.239"></a>
+<span class="sourceLineNo">240</span>    HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();<a name="line.240"></a>
+<span class="sourceLineNo">241</span>    Path testDir = TEST_UTIL.getDataTestDir();<a name="line.241"></a>
+<span class="sourceLineNo">242</span>    TEST_UTIL.getTestFileSystem().mkdirs(testDir);<a name="line.242"></a>
+<span class="sourceLineNo">243</span><a name="line.243"></a>
+<span class="sourceLineNo">244</span>    BucketCache bucketCache = new BucketCache("file:" + testDir + "/bucket.cache", capacitySize,<a name="line.244"></a>
+<span class="sourceLineNo">245</span>        constructedBlockSize, constructedBlockSizes, writeThreads, writerQLen, testDir<a name="line.245"></a>
+<span class="sourceLineNo">246</span>            + "/bucket.persistence");<a name="line.246"></a>
+<span class="sourceLineNo">247</span>    long usedSize = bucketCache.getAllocator().getUsedSize();<a name="line.247"></a>
+<span class="sourceLineNo">248</span>    assertTrue(usedSize == 0);<a name="line.248"></a>
+<span class="sourceLineNo">249</span><a name="line.249"></a>
+<span class="sourceLineNo">250</span>    HFileBlockPair[] blocks = CacheTestUtils.generateHFileBlocks(constructedBlockSize, 1);<a name="line.250"></a>
+<span class="sourceLineNo">251</span>    // Add blocks<a name="line.251"></a>
+<span class="sourceLineNo">252</span>    for (HFileBlockPair block : blocks) {<a name="line.252"></a>
+<span class="sourceLineNo">253</span>      bucketCache.cacheBlock(block.getBlockName(), block.getBlock());<a name="line.253"></a>
+<span class="sourceLineNo">254</span>    }<a name="line.254"></a>
+<span class="sourceLineNo">255</span>    for (HFileBlockPair block : blocks) {<a name="line.255"></a>
+<span class="sourceLineNo">256</span>      cacheAndWaitUntilFlushedToBucket(bucketCache, block.getBlockName(), block.getBlock());<a name="line.256"></a>
+<span class="sourceLineNo">257</span>    }<a name="line.257"></a>
+<span class="sourceLineNo">258</span>    usedSize = bucketCache.getAllocator().getUsedSize();<a name="line.258"></a>
+<span class="sourceLineNo">259</span>    assertTrue(usedSize != 0);<a name="line.259"></a>
+<span class="sourceLineNo">260</span>    // persist cache to file<a name="line.260"></a>
+<span class="sourceLineNo">261</span>    bucketCache.shutdown();<a name="line.261"></a>
+<span class="sourceLineNo">262</span><a name="line.262"></a>
+<span class="sourceLineNo">263</span>    // restore cache from file<a name="line.263"></a>
+<span class="sourceLineNo">264</span>    bucketCache = new BucketCache("file:" + testDir + "/bucket.cache", capacitySize,<a name="line.264"></a>
+<span class="sourceLineNo">265</span>        constructedBlockSize, constructedBlockSizes, writeThreads, writerQLen, testDir<a name="line.265"></a>
+<span class="sourceLineNo">266</span>            + "/bucket.persistence");<a name="line.266"></a>
+<span class="sourceLineNo">267</span>    assertEquals(usedSize, bucketCache.getAllocator().getUsedSize());<a name="line.267"></a>
+<span class="sourceLineNo">268</span>    // persist cache to file<a name="line.268"></a>
+<span class="sourceLineNo">269</span>    bucketCache.shutdown();<a name="line.269"></a>
+<span class="sourceLineNo">270</span><a name="line.270"></a>
+<span class="sourceLineNo">271</span>    // reconfig buckets sizes, the biggest bucket is small than constructedBlockSize (8k or 16k)<a name="line.271"></a>
+<span class="sourceLineNo">272</span>    // so it can't restore cache from file<a name="line.272"></a>
+<span class="sourceLineNo">273</span>    int[] smallBucketSizes = new int[] { 2 * 1024 + 1024, 4 * 1024 + 1024 };<a name="line.273"></a>
+<span class="sourceLineNo">274</span>    bucketCache = new BucketCache("file:" + testDir + "/bucket.cache", capacitySize,<a name="line.274"></a>
+<span class="sourceLineNo">275</span>        constructedBlockSize, smallBucketSizes, writeThreads,<a name="line.275"></a>
+<span class="sourceLineNo">276</span>        writerQLen, testDir + "/bucket.persistence");<a name="line.276"></a>
+<span class="sourceLineNo">277</span>    assertEquals(0, bucketCache.getAllocator().getUsedSize());<a name="line.277"></a>
+<span class="sourceLineNo">278</span>    assertEquals(0, bucketCache.backingMap.size());<a name="line.278"></a>
+<span class="sourceLineNo">279</span><a name="line.279"></a>
+<span class="sourceLineNo">280</span>    TEST_UTIL.cleanupTestDir();<a name="line.280"></a>
+<span class="sourceLineNo">281</span>  }<a name="line.281"></a>
+<span class="sourceLineNo">282</span><a name="line.282"></a>
+<span class="sourceLineNo">283</span>  @Test<a name="line.283"></a>
+<span class="sourceLineNo">284</span>  public void testBucketAllocatorLargeBuckets() throws BucketAllocatorException {<a name="line.284"></a>
+<span class="sourceLineNo">285</span>    long availableSpace = 20 * 1024L * 1024 * 1024;<a name="line.285"></a>
+<span class="sourceLineNo">286</span>    int[] bucketSizes = new int[]{1024, 1024 * 1024, 1024 * 1024 * 1024};<a name="line.286"></a>
+<span class="sourceLineNo">287</span>    BucketAllocator allocator = new BucketAllocator(availableSpace, bucketSizes);<a name="line.287"></a>
+<span class="sourceLineNo">288</span>    assertTrue(allocator.getBuckets().length &gt; 0);<a name="line.288"></a>
+<span class="sourceLineNo">289</span>  }<a name="line.289"></a>
+<span class="sourceLineNo">290</span><a name="line.290"></a>
+<span class="sourceLineNo">291</span>  @Test<a name="line.291"></a>
+<span class="sourceLineNo">292</span>  public void testGetPartitionSize() throws IOException {<a name="line.292"></a>
+<span class="sourceLineNo">293</span>    //Test default values<a name="line.293"></a>
+<span class="sourceLineNo">294</span>    validateGetPartitionSize(cache, BucketCache.DEFAULT_SINGLE_FACTOR, BucketCache.DEFAULT_MIN_FACTOR);<a name="line.294"></a>
+<span class="sourceLineNo">295</span><a name="line.295"></a>
+<span class="sourceLineNo">296</span>    Configuration conf = HBaseConfiguration.create();<a name="line.296"></a>
+<span class="sourceLineNo">297</span>    conf.setFloat(BucketCache.MIN_FACTOR_CONFIG_NAME, 0.5f);<a name="line.297"></a>
+<span class="sourceLineNo">298</span>    conf.setFloat(BucketCache.SINGLE_FACTOR_CONFIG_NAME, 0.1f);<a name="line.298"></a>
+<span class="sourceLineNo">299</span>    conf.setFloat(BucketCache.MULTI_FACTOR_CONFIG_NAME, 0.7f);<a name="line.299"></a>
+<span class="sourceLineNo">300</span>    conf.setFloat(BucketCache.MEMORY_FACTOR_CONFIG_NAME, 0.2f);<a name="line.300"></a>
+<span class="sourceLineNo">301</span><a name="line.301"></a>
+<span class="sourceLineNo">302</span>    BucketCache cache = new BucketCache(ioEngineName, capacitySize, constructedBlockSize,<a name="line.302"></a>
+<span class="sourceLineNo">303</span>        constructedBlockSizes, writeThreads, writerQLen, persistencePath, 100, conf);<a name="line.303"></a>
+<span class="sourceLineNo">304</span><a name="line.304"></a>
+<span class="sourceLineNo">305</span>    validateGetPartitionSize(cache, 0.1f, 0.5f);<a name="line.305"></a>
+<span class="sourceLineNo">306</span>    validateGetPartitionSize(cache, 0.7f, 0.5f);<a name="line.306"></a>
+<span class="sourceLineNo">307</span>    validateGetPartitionSize(cache, 0.2f, 0.5f);<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>  @Test<a name="line.310"></a>
+<span class="sourceLineNo">311</span>  public void testValidBucketCacheConfigs() throws IOException {<a name="line.311"></a>
+<span class="sourceLineNo">312</span>    Configuration conf = HBaseConfiguration.create();<a name="line.312"></a>
+<span class="sourceLineNo">313</span>    conf.setFloat(BucketCache.ACCEPT_FACTOR_CONFIG_NAME, 0.9f);<a name="line.313"></a>
+<span class="sourceLineNo">314</span>    conf.setFloat(BucketCache.MIN_FACTOR_CONFIG_NAME, 0.5f);<a name="line.314"></a>
+<span class="sourceLineNo">315</span>    conf.setFloat(BucketCache.EXTRA_FREE_FACTOR_CONFIG_NAME, 0.5f);<a name="line.315"></a>
+<span class="sourceLineNo">316</span>    conf.setFloat(BucketCache.SINGLE_FACTOR_CONFIG_NAME, 0.1f);<a name="line.316"></a>
+<span class="sourceLineNo">317</span>    conf.setFloat(BucketCache.MULTI_FACTOR_CONFIG_NAME, 0.7f);<a name="line.317"></a>
+<span class="sourceLineNo">318</span>    conf.setFloat(BucketCache.MEMORY_FACTOR_CONFIG_NAME, 0.2f);<a name="line.318"></a>
+<span class="sourceLineNo">319</span><a name="line.319"></a>
+<span class="sourceLineNo">320</span>    BucketCache cache = new BucketCache(ioEngineName, capacitySize, constructedBlockSize,<a name="line.320"></a>
+<span class="sourceLineNo">321</span>        constructedBlockSizes, writeThreads, writerQLen, persistencePath, 100, conf);<a name="line.321"></a>
+<span class="sourceLineNo">322</span><a name="line.322"></a>
+<span class="sourceLineNo">323</span>    assertEquals(BucketCache.ACCEPT_FACTOR_CONFIG_NAME + " failed to propagate.", 0.9f,<a name="line.323"></a>
+<span class="sourceLineNo">324</span>        cache.getAcceptableFactor(), 0);<a name="line.324"></a>
+<span class="sourceLineNo">325</span>    assertEquals(BucketCache.MIN_FACTOR_CONFIG_NAME + " failed to propagate.", 0.5f,<a name="line.325"></a>
+<span class="sourceLineNo">326</span>        cache.getMinFactor(), 0);<a name="line.326"></a>
+<span class="sourceLineNo">327</span>    assertEquals(BucketCache.EXTRA_FREE_FACTOR_CONFIG_NAME + " failed to propagate.", 0.5f,<a name="line.327"></a>
+<span class="sourceLineNo">328</span>        cache.getExtraFreeFactor(), 0);<a name="line.328"></a>
+<span class="sourceLineNo">329</span>    assertEquals(BucketCache.SINGLE_FACTOR_CONFIG_NAME + " failed to propagate.", 0.1f,<a name="line.329"></a>
+<span class="sourceLineNo">330</span>        cache.getSingleFactor(), 0);<a name="line.330"></a>
+<span class="sourceLineNo">331</span>    assertEquals(BucketCache.MULTI_FACTOR_CONFIG_NAME + " failed to propagate.", 0.7f,<a name="line.331"></a>
+<span class="sourceLineNo">332</span>        cache.getMultiFactor(), 0);<a name="line.332"></a>
+<span class="sourceLineNo">333</span>    assertEquals(BucketCache.MEMORY_FACTOR_CONFIG_NAME + " failed to propagate.", 0.2f,<a name="line.333"></a>
+<span class="sourceLineNo">334</span>        cache.getMemoryFactor(), 0);<a name="line.334"></a>
+<span class="sourceLineNo">335</span>  }<a name="line.335"></a>
+<span class="sourceLineNo">336</span><a name="line.336"></a>
+<span class="sourceLineNo">337</span>  @Test<a name="line.337"></a>
+<span class="sourceLineNo">338</span>  public void testInvalidAcceptFactorConfig() throws IOException {<a name="line.338"></a>
+<span class="sourceLineNo">339</span>    float[] configValues = {-1f, 0.2f, 0.86f, 1.05f};<a name="line.339"></a>
+<span class="sourceLineNo">340</span>    boolean[] expectedOutcomes = {false, false, true, false};<a name="line.340"></a>
+<span class="sourceLineNo">341</span>    Map&lt;String, float[]&gt; configMappings = ImmutableMap.of(BucketCache.ACCEPT_FACTOR_CONFIG_NAME, configValues);<a name="line.341"></a>
+<span class="sourceLineNo">342</span>    Configuration conf = HBaseConfiguration.create();<a name="line.342"></a>
+<span class="sourceLineNo">343</span>    checkConfigValues(conf, configMappings, expectedOutcomes);<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>  @Test<a name="line.346"></a>
+<span class="sourceLineNo">347</span>  public void testInvalidMinFactorConfig() throws IOException {<a name="line.347"></a>
+<span class="sourceLineNo">348</span>    float[] configValues = {-1f, 0f, 0.96f, 1.05f};<a name="line.348"></a>
+<span class="sourceLineNo">349</span>    //throws due to &lt;0, in expected range, minFactor &gt; acceptableFactor, &gt; 1.0<a name="line.349"></a>
+<span class="sourceLineNo">350</span>    boolean[] expectedOutcomes = {false, true, false, false};<a name="line.350"></a>
+<span class="sourceLineNo">351</span>    Map&lt;String, float[]&gt; configMappings = ImmutableMap<a name="line.351"></a>
+<span class="sourceLineNo">352</span>      .of(BucketCache.MIN_FACTOR_CONFIG_NAME, configValues);<a name="line.352"></a>
+<span class="sourceLineNo">353</span>    Configuration conf = HBaseConfiguration.create();<a name="line.353"></a>
+<span class="sourceLineNo">354</span>    checkConfigValues(conf, configMappings, expectedOutcomes);<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">357</span>  @Test<a name="line.357"></a>
+<span class="sourceLineNo">358</span>  public void testInvalidExtraFreeFactorConfig() throws IOException {<a name="line.358"></a>
+<span class="sourceLineNo">359</span>    float[] configValues = {-1f, 0f, 0.2f, 1.05f};<a name="line.359"></a>
+<span class="sourceLineNo">360</span>    //throws due to &lt;0, in expected range, in expected range, config can be &gt; 1.0<a name="line.360"></a>
+<span class="sourceLineNo">361</span>    boolean[] expectedOutcomes = {false, true, true, true};<a name="line.361"></a>
+<span class="sourceLineNo">362</span>    Map&lt;String, float[]&gt; configMappings = ImmutableMap.of(BucketCache.EXTRA_FREE_FACTOR_CONFIG_NAME, configValues);<a name="line.362"></a>
+<span class="sourceLineNo">363</span>    Configuration conf = HBaseConfiguration.create();<a name="line.363"></a>
+<span class="sourceLineNo">364</span>    checkConfigValues(conf, configMappings, expectedOutcomes);<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>  @Test<a name="line.367"></a>
+<span class="sourceLineNo">368</span>  public void testInvalidCacheSplitFactorConfig() throws IOException {<a name="line.368"></a>
+<span class="sourceLineNo">369</span>    float[] singleFactorConfigValues = {0.2f, 0f, -0.2f, 1f};<a name="line.369"></a>
+<span class="sourceLineNo">370</span>    float[] multiFactorConfigValues = {0.4f, 0f, 1f, .05f};<a name="line.370"></a>
+<span class="sourceLineNo">371</span>    float[] memoryFactorConfigValues = {0.4f, 0f, 0.2f, .5f};<a name="line.371"></a>
+<span class="sourceLineNo">372</span>    // All configs add up to 1.0 and are between 0 and 1.0, configs don't add to 1.0, configs can't be negative, configs don't add to 1.0<a name="line.372"></a>
+<span class="sourceLineNo">373</span>    boolean[] expectedOutcomes = {true, false, false, false};<a name="line.373"></a>
+<span class="sourceLineNo">374</span>    Map&lt;String, float[]&gt; configMappings = ImmutableMap.of(BucketCache.SINGLE_FACTOR_CONFIG_NAME,<a name="line.374"></a>
+<span class="sourceLineNo">375</span>        singleFactorConfigValues, BucketCache.MULTI_FACTOR_CONFIG_NAME, multiFactorConfigValues,<a name="line.375"></a>
+<span class="sourceLineNo">376</span>        BucketCache.MEMORY_FACTOR_CONFIG_NAME, memoryFactorConfigValues);<a name="line.376"></a>
+<span class="sourceLineNo">377</span>    Configuration conf = HBaseConfiguration.create();<a name="line.377"></a>
+<span class="sourceLineNo">378</span>    checkConfigValues(conf, configMappings, expectedOutcomes);<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>  private void checkConfigValues(Configuration conf, Map&lt;String, float[]&gt; configMap, boolean[] expectSuccess) throws IOException {<a name="line.381"></a>
+<span class="sourceLineNo">382</span>    Set&lt;String&gt; configNames = configMap.keySet();<a name="line.382"></a>
+<span class="sourceLineNo">383</span>    for (int i = 0; i &lt; expectSuccess.length; i++) {<a name="line.383"></a>
+<span class="sourceLineNo">384</span>      try {<a name="line.384"></a>
+<span class="sourceLineNo">385</span>        for (String configName : configNames) {<a name="line.385"></a>
+<span class="sourceLineNo">386</span>          conf.setFloat(configName, configMap.get(configName)[i]);<a name="line.386"></a>
+<span class="sourceLineNo">387</span>        }<a name="line.387"></a>
+<span class="sourceLineNo">388</span>        BucketCache cache = new BucketCache(ioEngineName, capacitySize, constructedBlockSize,<a name="line.388"></a>
+<span class="sourceLineNo">389</span>            constructedBlockSizes, writeThreads, writerQLen, persistencePath, 100, conf);<a name="line.389"></a>
+<span class="sourceLineNo">390</span>        assertTrue("Created BucketCache and expected it to succeed: " + expectSuccess[i] + ", but it actually was: " + !expectSuccess[i], expectSuccess[i]);<a name="line.390"></a>
+<span class="sourceLineNo">391</span>      } catch (IllegalArgumentException e) {<a name="line.391"></a>
+<span class="sourceLineNo">392</span>        assertFalse("Created BucketCache and expected it to succeed: " + expectSuccess[i] + ", but it actually was: " + !expectSuccess[i], expectSuccess[i]);<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><a name="line.396"></a>
+<span class="sourceLineNo">397</span>  private void validateGetPartitionSize(BucketCache bucketCache, float partitionFactor, float minFactor) {<a name="line.397"></a>
+<span class="sourceLineNo">398</span>    long expectedOutput = (long) Math.floor(bucketCache.getAllocator().getTotalSize() * partitionFactor * minFactor);<a name="line.398"></a>
+<span class="sourceLineNo">399</span>    assertEquals(expectedOutput, bucketCache.getPartitionSize(partitionFactor));<a name="line.399"></a>
+<span class="sourceLineNo">400</span>  }<a name="line.400"></a>
+<span class="sourceLineNo">401</span><a name="line.401"></a>
+<span class="sourceLineNo">402</span>  @Test<a name="line.402"></a>
+<span class="sourceLineNo">403</span>  public void testOffsetProducesPositiveOutput() {<a name="line.403"></a>
+<span class="sourceLineNo">404</span>    //This number is picked because it produces negative output if the values isn't ensured to be positive.<a name="line.404"></a>
+<span class="sourceLineNo">405</span>    //See HBASE-18757 for more information.<a name="line.405"></a>
+<span class="sourceLineNo">406</span>    long testValue = 549888460800L;<a name="line.406"></a>
+<span class="sourceLineNo">407</span>    BucketCache.BucketEntry bucketEntry = new BucketCache.BucketEntry(testValue, 10, 10L, true);<a name="line.407"></a>
+<span class="sourceLineNo">408</span>    assertEquals(testValue, bucketEntry.offset());<a name="line.408"></a>
+<span class="sourceLineNo">409</span>  }<a name="line.409"></a>
+<span class="sourceLineNo">410</span><a name="line.410"></a>
+<span class="sourceLineNo">411</span>  @Test<a name="line.411"></a>
+<span class="sourceLineNo">412</span>  public void testCacheBlockNextBlockMetadataMissing() {<a name="line.412"></a>
+<span class="sourceLineNo">413</span>    int size = 100;<a name="line.413"></a>
+<span class="sourceLineNo">414</span>    int length = HConstants.HFILEBLOCK_HEADER_SIZE + size;<a name="line.414"></a>
+<span class="sourceLineNo">415</span>    byte[] byteArr = new byte[length];<a name="line.415"></a>
+<span class="sourceLineNo">416</span>    ByteBuffer buf = ByteBuffer.wrap(byteArr, 0, size);<a name="line.416"></a>
+<span class="sourceLineNo">417</span>    HFileContext meta = new HFileContextBuilder().build();<a name="line.417"></a>
+<span class="sourceLineNo">418</span>    HFileBlock blockWithNextBlockMetadata = new HFileBlock(BlockType.DATA, size, size, -1, buf,<a name="line.418"></a>
+<span class="sourceLineNo">419</span>        HFileBlock.FILL_HEADER, -1, 52, -1, meta);<a name="line.419"></a>
+<span class="sourceLineNo">420</span>    HFileBlock blockWithoutNextBlockMetadata = new HFileBlock(BlockType.DATA, size, size, -1, buf,<a name="line.420"></a>
+<span class="sourceLineNo">421</span>        HFileBlock.FILL_HEADER, -1, -1, -1, meta);<a name="line.421"></a>
+<span class="sourceLineNo">422</span><a name="line.422"></a>
+<span class="sourceLineNo">423</span>    BlockCacheKey key = new BlockCacheKey("key1", 0);<a name="line.423"></a>
+<span class="sourceLineNo">424</span>    ByteBuffer actualBuffer = ByteBuffer.allocate(length);<a name="line.424"></a>
+<span class="sourceLineNo">425</span>    ByteBuffer block1Buffer = ByteBuffer.allocate(length);<a name="line.425"></a>
+<span class="sourceLineNo">426</span>    ByteBuffer block2Buffer = ByteBuffer.allocate(length);<a name="line.426"></a>
+<span class="sourceLineNo">427</span>    blockWithNextBlockMetadata.serialize(block1Buffer, true);<a name="line.427"></a>
+<span class="sourceLineNo">428</span>    blockWithoutNextBlockMetadata.serialize(block2Buffer, true);<a name="line.428"></a>
+<span class="sourceLineNo">429</span><a name="line.429"></a>
+<span class="sourceLineNo">430</span>    //Add blockWithNextBlockMetadata, expect blockWithNextBlockMetadata back.<a name="line.430"></a>
+<span class="sourceLineNo">431</span>    CacheTestUtils.getBlockAndAssertEquals(cache, key, blockWithNextBlockMetadata, actualBuffer,<a name="line.431"></a>
+<span class="sourceLineNo">432</span>        block1Buffer);<a name="line.432"></a>
+<span class="sourceLineNo">433</span><a name="line.433"></a>
+<span class="sourceLineNo">434</span>    //Add blockWithoutNextBlockMetada, expect blockWithNextBlockMetadata back.<a name="line.434"></a>
+<span class="sourceLineNo">435</span>    CacheTestUtils.getBlockAndAssertEquals(cache, key, blockWithoutNextBlockMetadata, actualBuffer,<a name="line.435"></a>
+<span class="sourceLineNo">436</span>        block1Buffer);<a name="line.436"></a>
+<span class="sourceLineNo">437</span><a name="line.437"></a>
+<span class="sourceLineNo">438</span>    //Clear and add blockWithoutNextBlockMetadata<a name="line.438"></a>
+<span class="sourceLineNo">439</span>    cache.evictBlock(key);<a name="line.439"></a>
+<span class="sourceLineNo">440</span>    assertNull(cache.getBlock(key, false, false, false));<a name="line.440"></a>
+<span class="sourceLineNo">441</span>    CacheTestUtils.getBlockAndAssertEquals(cache, key, blockWithoutNextBlockMetadata, actualBuffer,<a name="line.441"></a>
+<span class="sourceLineNo">442</span>        block2Buffer);<a name="line.442"></a>
+<span class="sourceLineNo">443</span><a name="line.443"></a>
+<span class="sourceLineNo">444</span>    //Add blockWithNextBlockMetadata, expect blockWithNextBlockMetadata to replace.<a name="line.444"></a>
+<span class="sourceLineNo">445</span>    CacheTestUtils.getBlockAndAssertEquals(cache, key, blockWithNextBlockMetadata, actualBuffer,<a name="line.445"></a>
+<span class="sourceLineNo">446</span>        block1Buffer);<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>
 
 
 


[43/50] hbase-site git commit: Published site at 26babcf013de696b899d76a3c39434b794440d8d.

Posted by gi...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/regionserver/StoreScanner.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/regionserver/StoreScanner.html b/devapidocs/org/apache/hadoop/hbase/regionserver/StoreScanner.html
index 101b23a..8bdd840 100644
--- a/devapidocs/org/apache/hadoop/hbase/regionserver/StoreScanner.html
+++ b/devapidocs/org/apache/hadoop/hbase/regionserver/StoreScanner.html
@@ -1476,7 +1476,7 @@ implements <a href="../../../../../org/apache/hadoop/hbase/regionserver/KeyValue
 <ul class="blockList">
 <li class="blockList">
 <h4>needToReturn</h4>
-<pre>private&nbsp;<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.NextState</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/StoreScanner.html#line.714">needToReturn</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html?is-external=true" title="class or interface in java.util">List</a>&lt;<a href="../../../../../org/apache/hadoop/hbase/Cell.html" title="interface in org.apache.hadoop.hbase">Cell</a>&gt;&nbsp;outResult)</pre>
+<pre>private&nbsp;<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.NextState</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/StoreScanner.html#line.729">needToReturn</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html?is-external=true" title="class or interface in java.util">List</a>&lt;<a href="../../../../../org/apache/hadoop/hbase/Cell.html" title="interface in org.apache.hadoop.hbase">Cell</a>&gt;&nbsp;outResult)</pre>
 <div class="block">If the top cell won't be flushed into disk, the new top cell may be
  changed after #reopenAfterFlush. Because the older top cell only exist
  in the memstore scanner but the memstore scanner is replaced by hfile
@@ -1498,7 +1498,7 @@ implements <a href="../../../../../org/apache/hadoop/hbase/regionserver/KeyValue
 <ul class="blockList">
 <li class="blockList">
 <h4>seekOrSkipToNextRow</h4>
-<pre>private&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/StoreScanner.html#line.721">seekOrSkipToNextRow</a>(<a href="../../../../../org/apache/hadoop/hbase/Cell.html" title="interface in org.apache.hadoop.hbase">Cell</a>&nbsp;cell)
+<pre>private&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/StoreScanner.html#line.736">seekOrSkipToNextRow</a>(<a href="../../../../../org/apache/hadoop/hbase/Cell.html" title="interface in org.apache.hadoop.hbase">Cell</a>&nbsp;cell)
                           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>
@@ -1512,7 +1512,7 @@ implements <a href="../../../../../org/apache/hadoop/hbase/regionserver/KeyValue
 <ul class="blockList">
 <li class="blockList">
 <h4>seekOrSkipToNextColumn</h4>
-<pre>private&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/StoreScanner.html#line.732">seekOrSkipToNextColumn</a>(<a href="../../../../../org/apache/hadoop/hbase/Cell.html" title="interface in org.apache.hadoop.hbase">Cell</a>&nbsp;cell)
+<pre>private&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/StoreScanner.html#line.747">seekOrSkipToNextColumn</a>(<a href="../../../../../org/apache/hadoop/hbase/Cell.html" title="interface in org.apache.hadoop.hbase">Cell</a>&nbsp;cell)
                              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>
@@ -1526,7 +1526,7 @@ implements <a href="../../../../../org/apache/hadoop/hbase/regionserver/KeyValue
 <ul class="blockList">
 <li class="blockList">
 <h4>trySkipToNextRow</h4>
-<pre>protected&nbsp;boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/StoreScanner.html#line.788">trySkipToNextRow</a>(<a href="../../../../../org/apache/hadoop/hbase/Cell.html" title="interface in org.apache.hadoop.hbase">Cell</a>&nbsp;cell)
+<pre>protected&nbsp;boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/StoreScanner.html#line.803">trySkipToNextRow</a>(<a href="../../../../../org/apache/hadoop/hbase/Cell.html" title="interface in org.apache.hadoop.hbase">Cell</a>&nbsp;cell)
                             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">See if we should actually SEEK or rather just SKIP to the next Cell (see HBASE-13109).
  ScanQueryMatcher may issue SEEK hints, such as seek to next column, next row,
@@ -1589,7 +1589,7 @@ implements <a href="../../../../../org/apache/hadoop/hbase/regionserver/KeyValue
 <ul class="blockList">
 <li class="blockList">
 <h4>trySkipToNextColumn</h4>
-<pre>protected&nbsp;boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/StoreScanner.html#line.809">trySkipToNextColumn</a>(<a href="../../../../../org/apache/hadoop/hbase/Cell.html" title="interface in org.apache.hadoop.hbase">Cell</a>&nbsp;cell)
+<pre>protected&nbsp;boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/StoreScanner.html#line.824">trySkipToNextColumn</a>(<a href="../../../../../org/apache/hadoop/hbase/Cell.html" title="interface in org.apache.hadoop.hbase">Cell</a>&nbsp;cell)
                                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">See <a href="../../../../../org/apache/hadoop/hbase/regionserver/StoreScanner.html#trySkipToNextRow-org.apache.hadoop.hbase.Cell-"><code>trySkipToNextRow(Cell)</code></a></div>
 <dl>
@@ -1608,7 +1608,7 @@ implements <a href="../../../../../org/apache/hadoop/hbase/regionserver/KeyValue
 <ul class="blockList">
 <li class="blockList">
 <h4>getReadPoint</h4>
-<pre>public&nbsp;long&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/StoreScanner.html#line.831">getReadPoint</a>()</pre>
+<pre>public&nbsp;long&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/StoreScanner.html#line.846">getReadPoint</a>()</pre>
 <dl>
 <dt><span class="overrideSpecifyLabel">Specified by:</span></dt>
 <dd><code><a href="../../../../../org/apache/hadoop/hbase/regionserver/ChangedReadersObserver.html#getReadPoint--">getReadPoint</a></code>&nbsp;in interface&nbsp;<code><a href="../../../../../org/apache/hadoop/hbase/regionserver/ChangedReadersObserver.html" title="interface in org.apache.hadoop.hbase.regionserver">ChangedReadersObserver</a></code></dd>
@@ -1623,7 +1623,7 @@ implements <a href="../../../../../org/apache/hadoop/hbase/regionserver/KeyValue
 <ul class="blockList">
 <li class="blockList">
 <h4>clearAndClose</h4>
-<pre>private static&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/StoreScanner.html#line.835">clearAndClose</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html?is-external=true" title="class or interface in java.util">List</a>&lt;<a href="../../../../../org/apache/hadoop/hbase/regionserver/KeyValueScanner.html" title="interface in org.apache.hadoop.hbase.regionserver">KeyValueScanner</a>&gt;&nbsp;scanners)</pre>
+<pre>private static&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/StoreScanner.html#line.850">clearAndClose</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html?is-external=true" title="class or interface in java.util">List</a>&lt;<a href="../../../../../org/apache/hadoop/hbase/regionserver/KeyValueScanner.html" title="interface in org.apache.hadoop.hbase.regionserver">KeyValueScanner</a>&gt;&nbsp;scanners)</pre>
 </li>
 </ul>
 <a name="updateReaders-java.util.List-java.util.List-">
@@ -1632,7 +1632,7 @@ implements <a href="../../../../../org/apache/hadoop/hbase/regionserver/KeyValue
 <ul class="blockList">
 <li class="blockList">
 <h4>updateReaders</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/StoreScanner.html#line.844">updateReaders</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html?is-external=true" title="class or interface in java.util">List</a>&lt;<a href="../../../../../org/apache/hadoop/hbase/regionserver/HStoreFile.html" title="class in org.apache.hadoop.hbase.regionserver">HStoreFile</a>&gt;&nbsp;sfs,
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/StoreScanner.html#line.859">updateReaders</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html?is-external=true" title="class or interface in java.util">List</a>&lt;<a href="../../../../../org/apache/hadoop/hbase/regionserver/HStoreFile.html" title="class in org.apache.hadoop.hbase.regionserver">HStoreFile</a>&gt;&nbsp;sfs,
                           <a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html?is-external=true" title="class or interface in java.util">List</a>&lt;<a href="../../../../../org/apache/hadoop/hbase/regionserver/KeyValueScanner.html" title="interface in org.apache.hadoop.hbase.regionserver">KeyValueScanner</a>&gt;&nbsp;memStoreScanners)
                    throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
 <div class="block"><span class="descfrmTypeLabel">Description copied from interface:&nbsp;<code><a href="../../../../../org/apache/hadoop/hbase/regionserver/ChangedReadersObserver.html#updateReaders-java.util.List-java.util.List-">ChangedReadersObserver</a></code></span></div>
@@ -1654,7 +1654,7 @@ implements <a href="../../../../../org/apache/hadoop/hbase/regionserver/KeyValue
 <ul class="blockList">
 <li class="blockList">
 <h4>reopenAfterFlush</h4>
-<pre>protected final&nbsp;boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/StoreScanner.html#line.876">reopenAfterFlush</a>()
+<pre>protected final&nbsp;boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/StoreScanner.html#line.891">reopenAfterFlush</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="returnLabel">Returns:</span></dt>
@@ -1670,7 +1670,7 @@ implements <a href="../../../../../org/apache/hadoop/hbase/regionserver/KeyValue
 <ul class="blockList">
 <li class="blockList">
 <h4>resetQueryMatcher</h4>
-<pre>private&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/StoreScanner.html#line.923">resetQueryMatcher</a>(<a href="../../../../../org/apache/hadoop/hbase/Cell.html" title="interface in org.apache.hadoop.hbase">Cell</a>&nbsp;lastTopKey)</pre>
+<pre>private&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/StoreScanner.html#line.938">resetQueryMatcher</a>(<a href="../../../../../org/apache/hadoop/hbase/Cell.html" title="interface in org.apache.hadoop.hbase">Cell</a>&nbsp;lastTopKey)</pre>
 </li>
 </ul>
 <a name="checkScanOrder-org.apache.hadoop.hbase.Cell-org.apache.hadoop.hbase.Cell-org.apache.hadoop.hbase.CellComparator-">
@@ -1679,7 +1679,7 @@ implements <a href="../../../../../org/apache/hadoop/hbase/regionserver/KeyValue
 <ul class="blockList">
 <li class="blockList">
 <h4>checkScanOrder</h4>
-<pre>protected&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/StoreScanner.html#line.945">checkScanOrder</a>(<a href="../../../../../org/apache/hadoop/hbase/Cell.html" title="interface in org.apache.hadoop.hbase">Cell</a>&nbsp;prevKV,
+<pre>protected&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/StoreScanner.html#line.960">checkScanOrder</a>(<a href="../../../../../org/apache/hadoop/hbase/Cell.html" title="interface in org.apache.hadoop.hbase">Cell</a>&nbsp;prevKV,
                               <a href="../../../../../org/apache/hadoop/hbase/Cell.html" title="interface in org.apache.hadoop.hbase">Cell</a>&nbsp;kv,
                               <a href="../../../../../org/apache/hadoop/hbase/CellComparator.html" title="interface in org.apache.hadoop.hbase">CellComparator</a>&nbsp;comparator)
                        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>
@@ -1700,7 +1700,7 @@ implements <a href="../../../../../org/apache/hadoop/hbase/regionserver/KeyValue
 <ul class="blockList">
 <li class="blockList">
 <h4>seekToNextRow</h4>
-<pre>protected&nbsp;boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/StoreScanner.html#line.953">seekToNextRow</a>(<a href="../../../../../org/apache/hadoop/hbase/Cell.html" title="interface in org.apache.hadoop.hbase">Cell</a>&nbsp;c)
+<pre>protected&nbsp;boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/StoreScanner.html#line.968">seekToNextRow</a>(<a href="../../../../../org/apache/hadoop/hbase/Cell.html" title="interface in org.apache.hadoop.hbase">Cell</a>&nbsp;c)
                          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>
@@ -1714,7 +1714,7 @@ implements <a href="../../../../../org/apache/hadoop/hbase/regionserver/KeyValue
 <ul class="blockList">
 <li class="blockList">
 <h4>seekAsDirection</h4>
-<pre>protected&nbsp;boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/StoreScanner.html#line.963">seekAsDirection</a>(<a href="../../../../../org/apache/hadoop/hbase/Cell.html" title="interface in org.apache.hadoop.hbase">Cell</a>&nbsp;kv)
+<pre>protected&nbsp;boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/StoreScanner.html#line.978">seekAsDirection</a>(<a href="../../../../../org/apache/hadoop/hbase/Cell.html" title="interface in org.apache.hadoop.hbase">Cell</a>&nbsp;kv)
                            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">Do a reseek in a normal StoreScanner(scan forward)</div>
 <dl>
@@ -1733,7 +1733,7 @@ implements <a href="../../../../../org/apache/hadoop/hbase/regionserver/KeyValue
 <ul class="blockList">
 <li class="blockList">
 <h4>reseek</h4>
-<pre>public&nbsp;boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/StoreScanner.html#line.969">reseek</a>(<a href="../../../../../org/apache/hadoop/hbase/Cell.html" title="interface in org.apache.hadoop.hbase">Cell</a>&nbsp;kv)
+<pre>public&nbsp;boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/StoreScanner.html#line.984">reseek</a>(<a href="../../../../../org/apache/hadoop/hbase/Cell.html" title="interface in org.apache.hadoop.hbase">Cell</a>&nbsp;kv)
                throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
 <div class="block"><span class="descfrmTypeLabel">Description copied from interface:&nbsp;<code><a href="../../../../../org/apache/hadoop/hbase/regionserver/KeyValueScanner.html#reseek-org.apache.hadoop.hbase.Cell-">KeyValueScanner</a></code></span></div>
 <div class="block">Reseek the scanner at or after the specified KeyValue.
@@ -1758,7 +1758,7 @@ implements <a href="../../../../../org/apache/hadoop/hbase/regionserver/KeyValue
 <ul class="blockList">
 <li class="blockList">
 <h4>trySwitchToStreamRead</h4>
-<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/StoreScanner.html#line.980">trySwitchToStreamRead</a>()</pre>
+<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/StoreScanner.html#line.995">trySwitchToStreamRead</a>()</pre>
 </li>
 </ul>
 <a name="checkFlushed--">
@@ -1767,7 +1767,7 @@ implements <a href="../../../../../org/apache/hadoop/hbase/regionserver/KeyValue
 <ul class="blockList">
 <li class="blockList">
 <h4>checkFlushed</h4>
-<pre>protected final&nbsp;boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/StoreScanner.html#line.1030">checkFlushed</a>()</pre>
+<pre>protected final&nbsp;boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/StoreScanner.html#line.1045">checkFlushed</a>()</pre>
 </li>
 </ul>
 <a name="parallelSeek-java.util.List-org.apache.hadoop.hbase.Cell-">
@@ -1776,7 +1776,7 @@ implements <a href="../../../../../org/apache/hadoop/hbase/regionserver/KeyValue
 <ul class="blockList">
 <li class="blockList">
 <h4>parallelSeek</h4>
-<pre>private&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/StoreScanner.html#line.1056">parallelSeek</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html?is-external=true" title="class or interface in java.util">List</a>&lt;? extends <a href="../../../../../org/apache/hadoop/hbase/regionserver/KeyValueScanner.html" title="interface in org.apache.hadoop.hbase.regionserver">KeyValueScanner</a>&gt;&nbsp;scanners,
+<pre>private&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/StoreScanner.html#line.1071">parallelSeek</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html?is-external=true" title="class or interface in java.util">List</a>&lt;? extends <a href="../../../../../org/apache/hadoop/hbase/regionserver/KeyValueScanner.html" title="interface in org.apache.hadoop.hbase.regionserver">KeyValueScanner</a>&gt;&nbsp;scanners,
                           <a href="../../../../../org/apache/hadoop/hbase/Cell.html" title="interface in org.apache.hadoop.hbase">Cell</a>&nbsp;kv)
                    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">Seek storefiles in parallel to optimize IO latency as much as possible</div>
@@ -1795,7 +1795,7 @@ implements <a href="../../../../../org/apache/hadoop/hbase/regionserver/KeyValue
 <ul class="blockList">
 <li class="blockList">
 <h4>getAllScannersForTesting</h4>
-<pre><a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html?is-external=true" title="class or interface in java.util">List</a>&lt;<a href="../../../../../org/apache/hadoop/hbase/regionserver/KeyValueScanner.html" title="interface in org.apache.hadoop.hbase.regionserver">KeyValueScanner</a>&gt;&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/StoreScanner.html#line.1092">getAllScannersForTesting</a>()</pre>
+<pre><a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html?is-external=true" title="class or interface in java.util">List</a>&lt;<a href="../../../../../org/apache/hadoop/hbase/regionserver/KeyValueScanner.html" title="interface in org.apache.hadoop.hbase.regionserver">KeyValueScanner</a>&gt;&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/StoreScanner.html#line.1107">getAllScannersForTesting</a>()</pre>
 <div class="block">Used in testing.</div>
 <dl>
 <dt><span class="returnLabel">Returns:</span></dt>
@@ -1809,7 +1809,7 @@ implements <a href="../../../../../org/apache/hadoop/hbase/regionserver/KeyValue
 <ul class="blockList">
 <li class="blockList">
 <h4>enableLazySeekGlobally</h4>
-<pre>static&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/StoreScanner.html#line.1102">enableLazySeekGlobally</a>(boolean&nbsp;enable)</pre>
+<pre>static&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/StoreScanner.html#line.1117">enableLazySeekGlobally</a>(boolean&nbsp;enable)</pre>
 </li>
 </ul>
 <a name="getEstimatedNumberOfKvsScanned--">
@@ -1818,7 +1818,7 @@ implements <a href="../../../../../org/apache/hadoop/hbase/regionserver/KeyValue
 <ul class="blockList">
 <li class="blockList">
 <h4>getEstimatedNumberOfKvsScanned</h4>
-<pre>public&nbsp;long&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/StoreScanner.html#line.1109">getEstimatedNumberOfKvsScanned</a>()</pre>
+<pre>public&nbsp;long&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/StoreScanner.html#line.1124">getEstimatedNumberOfKvsScanned</a>()</pre>
 <dl>
 <dt><span class="returnLabel">Returns:</span></dt>
 <dd>The estimated number of KVs seen by this scanner (includes some skipped KVs).</dd>
@@ -1831,7 +1831,7 @@ implements <a href="../../../../../org/apache/hadoop/hbase/regionserver/KeyValue
 <ul class="blockList">
 <li class="blockList">
 <h4>getNextIndexedKey</h4>
-<pre>public&nbsp;<a href="../../../../../org/apache/hadoop/hbase/Cell.html" title="interface in org.apache.hadoop.hbase">Cell</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/StoreScanner.html#line.1114">getNextIndexedKey</a>()</pre>
+<pre>public&nbsp;<a href="../../../../../org/apache/hadoop/hbase/Cell.html" title="interface in org.apache.hadoop.hbase">Cell</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/StoreScanner.html#line.1129">getNextIndexedKey</a>()</pre>
 <dl>
 <dt><span class="overrideSpecifyLabel">Specified by:</span></dt>
 <dd><code><a href="../../../../../org/apache/hadoop/hbase/regionserver/KeyValueScanner.html#getNextIndexedKey--">getNextIndexedKey</a></code>&nbsp;in interface&nbsp;<code><a href="../../../../../org/apache/hadoop/hbase/regionserver/KeyValueScanner.html" title="interface in org.apache.hadoop.hbase.regionserver">KeyValueScanner</a></code></dd>
@@ -1850,7 +1850,7 @@ implements <a href="../../../../../org/apache/hadoop/hbase/regionserver/KeyValue
 <ul class="blockListLast">
 <li class="blockList">
 <h4>shipped</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/StoreScanner.html#line.1119">shipped</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/StoreScanner.html#line.1134">shipped</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"><span class="descfrmTypeLabel">Description copied from interface:&nbsp;<code><a href="../../../../../org/apache/hadoop/hbase/regionserver/Shipper.html#shipped--">Shipper</a></code></span></div>
 <div class="block">Called after a batch of rows scanned and set to be returned to client. Any in between cleanup

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/regionserver/class-use/ScannerContext.LimitScope.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/regionserver/class-use/ScannerContext.LimitScope.html b/devapidocs/org/apache/hadoop/hbase/regionserver/class-use/ScannerContext.LimitScope.html
index 30aa87f..1118c76 100644
--- a/devapidocs/org/apache/hadoop/hbase/regionserver/class-use/ScannerContext.LimitScope.html
+++ b/devapidocs/org/apache/hadoop/hbase/regionserver/class-use/ScannerContext.LimitScope.html
@@ -271,22 +271,6 @@ the order they are declared.</div>
 </tr>
 </tbody>
 </table>
-<table class="useSummary" border="0" cellpadding="3" cellspacing="0" summary="Use table, listing constructors, and an explanation">
-<caption><span>Constructors in <a href="../../../../../../org/apache/hadoop/hbase/regionserver/package-summary.html">org.apache.hadoop.hbase.regionserver</a> with parameters of type <a href="../../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a></span><span class="tabEnd">&nbsp;</span></caption>
-<tr>
-<th class="colOne" scope="col">Constructor and Description</th>
-</tr>
-<tbody>
-<tr class="altColor">
-<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#LimitFields-int-org.apache.hadoop.hbase.regionserver.ScannerContext.LimitScope-long-long-org.apache.hadoop.hbase.regionserver.ScannerContext.LimitScope-long-">LimitFields</a></span>(int&nbsp;batch,
-           <a href="../../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a>&nbsp;sizeScope,
-           long&nbsp;size,
-           long&nbsp;heapSize,
-           <a href="../../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a>&nbsp;timeScope,
-           long&nbsp;time)</code>&nbsp;</td>
-</tr>
-</tbody>
-</table>
 </li>
 </ul>
 </li>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/regionserver/package-tree.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/regionserver/package-tree.html b/devapidocs/org/apache/hadoop/hbase/regionserver/package-tree.html
index 55f2744..3c4e00b 100644
--- a/devapidocs/org/apache/hadoop/hbase/regionserver/package-tree.html
+++ b/devapidocs/org/apache/hadoop/hbase/regionserver/package-tree.html
@@ -704,19 +704,19 @@
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true" title="class or interface in java.io">Serializable</a>)
 <ul>
 <li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/MetricsRegionServerSourceFactoryImpl.FactoryStorage.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">MetricsRegionServerSourceFactoryImpl.FactoryStorage</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/ChunkCreator.ChunkType.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">ChunkCreator.ChunkType</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/DefaultHeapMemoryTuner.StepDirection.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">DefaultHeapMemoryTuner.StepDirection</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/Region.Operation.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">Region.Operation</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">ScannerContext.NextState</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/SplitLogWorker.TaskExecutor.Status.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">SplitLogWorker.TaskExecutor.Status</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/HRegion.FlushResult.Result.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">HRegion.FlushResult.Result</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/TimeRangeTracker.Type.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">TimeRangeTracker.Type</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/MemStoreCompactionStrategy.Action.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">MemStoreCompactionStrategy.Action</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScanType.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">ScanType</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">ScannerContext.LimitScope</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/DefaultHeapMemoryTuner.StepDirection.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">DefaultHeapMemoryTuner.StepDirection</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/FlushType.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">FlushType</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/BloomType.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">BloomType</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/CompactingMemStore.IndexType.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">CompactingMemStore.IndexType</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/MemStoreCompactionStrategy.Action.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">MemStoreCompactionStrategy.Action</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/ChunkCreator.ChunkType.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">ChunkCreator.ChunkType</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScanType.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">ScanType</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/HRegion.FlushResult.Result.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">HRegion.FlushResult.Result</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/TimeRangeTracker.Type.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">TimeRangeTracker.Type</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">ScannerContext.LimitScope</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/Region.Operation.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">Region.Operation</span></a></li>
 </ul>
 </li>
 </ul>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/regionserver/querymatcher/package-tree.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/regionserver/querymatcher/package-tree.html b/devapidocs/org/apache/hadoop/hbase/regionserver/querymatcher/package-tree.html
index 6851ee1..858ccf6 100644
--- a/devapidocs/org/apache/hadoop/hbase/regionserver/querymatcher/package-tree.html
+++ b/devapidocs/org/apache/hadoop/hbase/regionserver/querymatcher/package-tree.html
@@ -131,8 +131,8 @@
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true" title="class or interface in java.io">Serializable</a>)
 <ul>
 <li type="circle">org.apache.hadoop.hbase.regionserver.querymatcher.<a href="../../../../../../org/apache/hadoop/hbase/regionserver/querymatcher/DeleteTracker.DeleteResult.html" title="enum in org.apache.hadoop.hbase.regionserver.querymatcher"><span class="typeNameLink">DeleteTracker.DeleteResult</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.regionserver.querymatcher.<a href="../../../../../../org/apache/hadoop/hbase/regionserver/querymatcher/ScanQueryMatcher.MatchCode.html" title="enum in org.apache.hadoop.hbase.regionserver.querymatcher"><span class="typeNameLink">ScanQueryMatcher.MatchCode</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.regionserver.querymatcher.<a href="../../../../../../org/apache/hadoop/hbase/regionserver/querymatcher/StripeCompactionScanQueryMatcher.DropDeletesInOutput.html" title="enum in org.apache.hadoop.hbase.regionserver.querymatcher"><span class="typeNameLink">StripeCompactionScanQueryMatcher.DropDeletesInOutput</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.regionserver.querymatcher.<a href="../../../../../../org/apache/hadoop/hbase/regionserver/querymatcher/ScanQueryMatcher.MatchCode.html" title="enum in org.apache.hadoop.hbase.regionserver.querymatcher"><span class="typeNameLink">ScanQueryMatcher.MatchCode</span></a></li>
 </ul>
 </li>
 </ul>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/regionserver/wal/package-tree.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/regionserver/wal/package-tree.html b/devapidocs/org/apache/hadoop/hbase/regionserver/wal/package-tree.html
index f6fc79b..a4ab1b7 100644
--- a/devapidocs/org/apache/hadoop/hbase/regionserver/wal/package-tree.html
+++ b/devapidocs/org/apache/hadoop/hbase/regionserver/wal/package-tree.html
@@ -238,8 +238,8 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true" title="class or interface in java.io">Serializable</a>)
 <ul>
-<li type="circle">org.apache.hadoop.hbase.regionserver.wal.<a href="../../../../../../org/apache/hadoop/hbase/regionserver/wal/ProtobufLogReader.WALHdrResult.html" title="enum in org.apache.hadoop.hbase.regionserver.wal"><span class="typeNameLink">ProtobufLogReader.WALHdrResult</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.regionserver.wal.<a href="../../../../../../org/apache/hadoop/hbase/regionserver/wal/RingBufferTruck.Type.html" title="enum in org.apache.hadoop.hbase.regionserver.wal"><span class="typeNameLink">RingBufferTruck.Type</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.regionserver.wal.<a href="../../../../../../org/apache/hadoop/hbase/regionserver/wal/ProtobufLogReader.WALHdrResult.html" title="enum in org.apache.hadoop.hbase.regionserver.wal"><span class="typeNameLink">ProtobufLogReader.WALHdrResult</span></a></li>
 </ul>
 </li>
 </ul>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/replication/regionserver/package-tree.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/replication/regionserver/package-tree.html b/devapidocs/org/apache/hadoop/hbase/replication/regionserver/package-tree.html
index d1e114d..193a3a3032 100644
--- a/devapidocs/org/apache/hadoop/hbase/replication/regionserver/package-tree.html
+++ b/devapidocs/org/apache/hadoop/hbase/replication/regionserver/package-tree.html
@@ -198,8 +198,8 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true" title="class or interface in java.io">Serializable</a>)
 <ul>
-<li type="circle">org.apache.hadoop.hbase.replication.regionserver.<a href="../../../../../../org/apache/hadoop/hbase/replication/regionserver/MetricsReplicationSourceFactoryImpl.SourceHolder.html" title="enum in org.apache.hadoop.hbase.replication.regionserver"><span class="typeNameLink">MetricsReplicationSourceFactoryImpl.SourceHolder</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.replication.regionserver.<a href="../../../../../../org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.WorkerState.html" title="enum in org.apache.hadoop.hbase.replication.regionserver"><span class="typeNameLink">ReplicationSourceShipper.WorkerState</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.replication.regionserver.<a href="../../../../../../org/apache/hadoop/hbase/replication/regionserver/MetricsReplicationSourceFactoryImpl.SourceHolder.html" title="enum in org.apache.hadoop.hbase.replication.regionserver"><span class="typeNameLink">MetricsReplicationSourceFactoryImpl.SourceHolder</span></a></li>
 </ul>
 </li>
 </ul>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/rest/model/package-tree.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/rest/model/package-tree.html b/devapidocs/org/apache/hadoop/hbase/rest/model/package-tree.html
index c20ff47..034077c 100644
--- a/devapidocs/org/apache/hadoop/hbase/rest/model/package-tree.html
+++ b/devapidocs/org/apache/hadoop/hbase/rest/model/package-tree.html
@@ -110,8 +110,8 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true" title="class or interface in java.io">Serializable</a>)
 <ul>
-<li type="circle">org.apache.hadoop.hbase.rest.model.<a href="../../../../../../org/apache/hadoop/hbase/rest/model/ScannerModel.FilterModel.FilterType.html" title="enum in org.apache.hadoop.hbase.rest.model"><span class="typeNameLink">ScannerModel.FilterModel.FilterType</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.rest.model.<a href="../../../../../../org/apache/hadoop/hbase/rest/model/ScannerModel.FilterModel.ByteArrayComparableModel.ComparatorType.html" title="enum in org.apache.hadoop.hbase.rest.model"><span class="typeNameLink">ScannerModel.FilterModel.ByteArrayComparableModel.ComparatorType</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.rest.model.<a href="../../../../../../org/apache/hadoop/hbase/rest/model/ScannerModel.FilterModel.FilterType.html" title="enum in org.apache.hadoop.hbase.rest.model"><span class="typeNameLink">ScannerModel.FilterModel.FilterType</span></a></li>
 </ul>
 </li>
 </ul>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/security/access/package-tree.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/security/access/package-tree.html b/devapidocs/org/apache/hadoop/hbase/security/access/package-tree.html
index d9fa142..f6d74ff 100644
--- a/devapidocs/org/apache/hadoop/hbase/security/access/package-tree.html
+++ b/devapidocs/org/apache/hadoop/hbase/security/access/package-tree.html
@@ -137,9 +137,9 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true" title="class or interface in java.io">Serializable</a>)
 <ul>
-<li type="circle">org.apache.hadoop.hbase.security.access.<a href="../../../../../../org/apache/hadoop/hbase/security/access/AccessController.OpType.html" title="enum in org.apache.hadoop.hbase.security.access"><span class="typeNameLink">AccessController.OpType</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.security.access.<a href="../../../../../../org/apache/hadoop/hbase/security/access/Permission.Action.html" title="enum in org.apache.hadoop.hbase.security.access"><span class="typeNameLink">Permission.Action</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.security.access.<a href="../../../../../../org/apache/hadoop/hbase/security/access/AccessControlFilter.Strategy.html" title="enum in org.apache.hadoop.hbase.security.access"><span class="typeNameLink">AccessControlFilter.Strategy</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.security.access.<a href="../../../../../../org/apache/hadoop/hbase/security/access/AccessController.OpType.html" title="enum in org.apache.hadoop.hbase.security.access"><span class="typeNameLink">AccessController.OpType</span></a></li>
 </ul>
 </li>
 </ul>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/security/package-tree.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/security/package-tree.html b/devapidocs/org/apache/hadoop/hbase/security/package-tree.html
index 6ef281d..29d7634 100644
--- a/devapidocs/org/apache/hadoop/hbase/security/package-tree.html
+++ b/devapidocs/org/apache/hadoop/hbase/security/package-tree.html
@@ -191,8 +191,8 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true" title="class or interface in java.io">Serializable</a>)
 <ul>
-<li type="circle">org.apache.hadoop.hbase.security.<a href="../../../../../org/apache/hadoop/hbase/security/SaslUtil.QualityOfProtection.html" title="enum in org.apache.hadoop.hbase.security"><span class="typeNameLink">SaslUtil.QualityOfProtection</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.security.<a href="../../../../../org/apache/hadoop/hbase/security/SaslStatus.html" title="enum in org.apache.hadoop.hbase.security"><span class="typeNameLink">SaslStatus</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.security.<a href="../../../../../org/apache/hadoop/hbase/security/SaslUtil.QualityOfProtection.html" title="enum in org.apache.hadoop.hbase.security"><span class="typeNameLink">SaslUtil.QualityOfProtection</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.security.<a href="../../../../../org/apache/hadoop/hbase/security/AuthMethod.html" title="enum in org.apache.hadoop.hbase.security"><span class="typeNameLink">AuthMethod</span></a></li>
 </ul>
 </li>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/util/package-tree.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/util/package-tree.html b/devapidocs/org/apache/hadoop/hbase/util/package-tree.html
index 27cdffb..51f7d2b 100644
--- a/devapidocs/org/apache/hadoop/hbase/util/package-tree.html
+++ b/devapidocs/org/apache/hadoop/hbase/util/package-tree.html
@@ -532,14 +532,14 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true" title="class or interface in java.io">Serializable</a>)
 <ul>
-<li type="circle">org.apache.hadoop.hbase.util.<a href="../../../../../org/apache/hadoop/hbase/util/PrettyPrinter.Unit.html" title="enum in org.apache.hadoop.hbase.util"><span class="typeNameLink">PrettyPrinter.Unit</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.util.<a href="../../../../../org/apache/hadoop/hbase/util/Bytes.LexicographicalComparerHolder.UnsafeComparer.html" title="enum in org.apache.hadoop.hbase.util"><span class="typeNameLink">Bytes.LexicographicalComparerHolder.UnsafeComparer</span></a> (implements org.apache.hadoop.hbase.util.<a href="../../../../../org/apache/hadoop/hbase/util/Bytes.Comparer.html" title="interface in org.apache.hadoop.hbase.util">Bytes.Comparer</a>&lt;T&gt;)</li>
-<li type="circle">org.apache.hadoop.hbase.util.<a href="../../../../../org/apache/hadoop/hbase/util/Bytes.LexicographicalComparerHolder.PureJavaComparer.html" title="enum in org.apache.hadoop.hbase.util"><span class="typeNameLink">Bytes.LexicographicalComparerHolder.PureJavaComparer</span></a> (implements org.apache.hadoop.hbase.util.<a href="../../../../../org/apache/hadoop/hbase/util/Bytes.Comparer.html" title="interface in org.apache.hadoop.hbase.util">Bytes.Comparer</a>&lt;T&gt;)</li>
 <li type="circle">org.apache.hadoop.hbase.util.<a href="../../../../../org/apache/hadoop/hbase/util/ChecksumType.html" title="enum in org.apache.hadoop.hbase.util"><span class="typeNameLink">ChecksumType</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.util.<a href="../../../../../org/apache/hadoop/hbase/util/IdReadWriteLock.ReferenceType.html" title="enum in org.apache.hadoop.hbase.util"><span class="typeNameLink">IdReadWriteLock.ReferenceType</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.util.<a href="../../../../../org/apache/hadoop/hbase/util/Order.html" title="enum in org.apache.hadoop.hbase.util"><span class="typeNameLink">Order</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.util.<a href="../../../../../org/apache/hadoop/hbase/util/HBaseFsck.ErrorReporter.ERROR_CODE.html" title="enum in org.apache.hadoop.hbase.util"><span class="typeNameLink">HBaseFsck.ErrorReporter.ERROR_CODE</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.util.<a href="../../../../../org/apache/hadoop/hbase/util/IdReadWriteLock.ReferenceType.html" title="enum in org.apache.hadoop.hbase.util"><span class="typeNameLink">IdReadWriteLock.ReferenceType</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.util.<a href="../../../../../org/apache/hadoop/hbase/util/Bytes.LexicographicalComparerHolder.PureJavaComparer.html" title="enum in org.apache.hadoop.hbase.util"><span class="typeNameLink">Bytes.LexicographicalComparerHolder.PureJavaComparer</span></a> (implements org.apache.hadoop.hbase.util.<a href="../../../../../org/apache/hadoop/hbase/util/Bytes.Comparer.html" title="interface in org.apache.hadoop.hbase.util">Bytes.Comparer</a>&lt;T&gt;)</li>
 <li type="circle">org.apache.hadoop.hbase.util.<a href="../../../../../org/apache/hadoop/hbase/util/PoolMap.PoolType.html" title="enum in org.apache.hadoop.hbase.util"><span class="typeNameLink">PoolMap.PoolType</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.util.<a href="../../../../../org/apache/hadoop/hbase/util/HBaseFsck.ErrorReporter.ERROR_CODE.html" title="enum in org.apache.hadoop.hbase.util"><span class="typeNameLink">HBaseFsck.ErrorReporter.ERROR_CODE</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.util.<a href="../../../../../org/apache/hadoop/hbase/util/PrettyPrinter.Unit.html" title="enum in org.apache.hadoop.hbase.util"><span class="typeNameLink">PrettyPrinter.Unit</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.util.<a href="../../../../../org/apache/hadoop/hbase/util/Bytes.LexicographicalComparerHolder.UnsafeComparer.html" title="enum in org.apache.hadoop.hbase.util"><span class="typeNameLink">Bytes.LexicographicalComparerHolder.UnsafeComparer</span></a> (implements org.apache.hadoop.hbase.util.<a href="../../../../../org/apache/hadoop/hbase/util/Bytes.Comparer.html" title="interface in org.apache.hadoop.hbase.util">Bytes.Comparer</a>&lt;T&gt;)</li>
 </ul>
 </li>
 </ul>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/src-html/org/apache/hadoop/hbase/Version.html
----------------------------------------------------------------------
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/Version.html b/devapidocs/src-html/org/apache/hadoop/hbase/Version.html
index 8811596..e3ff3ce 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/Version.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/Version.html
@@ -16,11 +16,11 @@
 <span class="sourceLineNo">008</span>@InterfaceAudience.Private<a name="line.8"></a>
 <span class="sourceLineNo">009</span>public class Version {<a name="line.9"></a>
 <span class="sourceLineNo">010</span>  public static final String version = "3.0.0-SNAPSHOT";<a name="line.10"></a>
-<span class="sourceLineNo">011</span>  public static final String revision = "db04a9f9d910caf3976f8a86cdd8bacbafcd78e4";<a name="line.11"></a>
+<span class="sourceLineNo">011</span>  public static final String revision = "26babcf013de696b899d76a3c39434b794440d8d";<a name="line.11"></a>
 <span class="sourceLineNo">012</span>  public static final String user = "jenkins";<a name="line.12"></a>
-<span class="sourceLineNo">013</span>  public static final String date = "Mon May 14 14:39:07 UTC 2018";<a name="line.13"></a>
+<span class="sourceLineNo">013</span>  public static final String date = "Tue May 15 14:40:24 UTC 2018";<a name="line.13"></a>
 <span class="sourceLineNo">014</span>  public static final String url = "git://jenkins-websites1.apache.org/home/jenkins/jenkins-slave/workspace/hbase_generate_website/hbase";<a name="line.14"></a>
-<span class="sourceLineNo">015</span>  public static final String srcChecksum = "8e687f8e84d8f8e7032c526137add45a";<a name="line.15"></a>
+<span class="sourceLineNo">015</span>  public static final String srcChecksum = "ae490ceba5391b59f223517b4f11795d";<a name="line.15"></a>
 <span class="sourceLineNo">016</span>}<a name="line.16"></a>
 
 

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/src-html/org/apache/hadoop/hbase/client/RpcRetryingCallerWithReadReplicas.ReplicaRegionServerCallable.html
----------------------------------------------------------------------
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/client/RpcRetryingCallerWithReadReplicas.ReplicaRegionServerCallable.html b/devapidocs/src-html/org/apache/hadoop/hbase/client/RpcRetryingCallerWithReadReplicas.ReplicaRegionServerCallable.html
index a8bfe80..878793b 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/client/RpcRetryingCallerWithReadReplicas.ReplicaRegionServerCallable.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/client/RpcRetryingCallerWithReadReplicas.ReplicaRegionServerCallable.html
@@ -287,65 +287,66 @@
 <span class="sourceLineNo">279</span>      throws RetriesExhaustedException, DoNotRetryIOException {<a name="line.279"></a>
 <span class="sourceLineNo">280</span>    Throwable t = e.getCause();<a name="line.280"></a>
 <span class="sourceLineNo">281</span>    assert t != null; // That's what ExecutionException is about: holding an exception<a name="line.281"></a>
-<span class="sourceLineNo">282</span><a name="line.282"></a>
-<span class="sourceLineNo">283</span>    if (t instanceof RetriesExhaustedException) {<a name="line.283"></a>
-<span class="sourceLineNo">284</span>      throw (RetriesExhaustedException) t;<a name="line.284"></a>
-<span class="sourceLineNo">285</span>    }<a name="line.285"></a>
-<span class="sourceLineNo">286</span><a name="line.286"></a>
-<span class="sourceLineNo">287</span>    if (t instanceof DoNotRetryIOException) {<a name="line.287"></a>
-<span class="sourceLineNo">288</span>      throw (DoNotRetryIOException) t;<a name="line.288"></a>
-<span class="sourceLineNo">289</span>    }<a name="line.289"></a>
-<span class="sourceLineNo">290</span><a name="line.290"></a>
-<span class="sourceLineNo">291</span>    RetriesExhaustedException.ThrowableWithExtraContext qt =<a name="line.291"></a>
-<span class="sourceLineNo">292</span>        new RetriesExhaustedException.ThrowableWithExtraContext(t,<a name="line.292"></a>
-<span class="sourceLineNo">293</span>            EnvironmentEdgeManager.currentTime(), null);<a name="line.293"></a>
-<span class="sourceLineNo">294</span><a name="line.294"></a>
-<span class="sourceLineNo">295</span>    List&lt;RetriesExhaustedException.ThrowableWithExtraContext&gt; exceptions =<a name="line.295"></a>
-<span class="sourceLineNo">296</span>        Collections.singletonList(qt);<a name="line.296"></a>
-<span class="sourceLineNo">297</span><a name="line.297"></a>
-<span class="sourceLineNo">298</span>    throw new RetriesExhaustedException(retries, exceptions);<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>   * Creates the calls and submit them<a name="line.302"></a>
-<span class="sourceLineNo">303</span>   *<a name="line.303"></a>
-<span class="sourceLineNo">304</span>   * @param cs  - the completion service to use for submitting<a name="line.304"></a>
-<span class="sourceLineNo">305</span>   * @param rl  - the region locations<a name="line.305"></a>
-<span class="sourceLineNo">306</span>   * @param min - the id of the first replica, inclusive<a name="line.306"></a>
-<span class="sourceLineNo">307</span>   * @param max - the id of the last replica, inclusive.<a name="line.307"></a>
-<span class="sourceLineNo">308</span>   */<a name="line.308"></a>
-<span class="sourceLineNo">309</span>  private void addCallsForReplica(ResultBoundedCompletionService&lt;Result&gt; cs,<a name="line.309"></a>
-<span class="sourceLineNo">310</span>                                 RegionLocations rl, int min, int max) {<a name="line.310"></a>
-<span class="sourceLineNo">311</span>    for (int id = min; id &lt;= max; id++) {<a name="line.311"></a>
-<span class="sourceLineNo">312</span>      HRegionLocation hrl = rl.getRegionLocation(id);<a name="line.312"></a>
-<span class="sourceLineNo">313</span>      ReplicaRegionServerCallable callOnReplica = new ReplicaRegionServerCallable(id, hrl);<a name="line.313"></a>
-<span class="sourceLineNo">314</span>      cs.submit(callOnReplica, operationTimeout, id);<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>  static RegionLocations getRegionLocations(boolean useCache, int replicaId,<a name="line.318"></a>
-<span class="sourceLineNo">319</span>                 ClusterConnection cConnection, TableName tableName, byte[] row)<a name="line.319"></a>
-<span class="sourceLineNo">320</span>      throws RetriesExhaustedException, DoNotRetryIOException, InterruptedIOException {<a name="line.320"></a>
-<span class="sourceLineNo">321</span><a name="line.321"></a>
-<span class="sourceLineNo">322</span>    RegionLocations rl;<a name="line.322"></a>
-<span class="sourceLineNo">323</span>    try {<a name="line.323"></a>
-<span class="sourceLineNo">324</span>      if (useCache) {<a name="line.324"></a>
-<span class="sourceLineNo">325</span>        rl = cConnection.locateRegion(tableName, row, true, true, replicaId);<a name="line.325"></a>
-<span class="sourceLineNo">326</span>      } else {<a name="line.326"></a>
-<span class="sourceLineNo">327</span>        rl = cConnection.relocateRegion(tableName, row, replicaId);<a name="line.327"></a>
-<span class="sourceLineNo">328</span>      }<a name="line.328"></a>
-<span class="sourceLineNo">329</span>    } catch (DoNotRetryIOException | InterruptedIOException | RetriesExhaustedException e) {<a name="line.329"></a>
-<span class="sourceLineNo">330</span>      throw e;<a name="line.330"></a>
-<span class="sourceLineNo">331</span>    } catch (IOException e) {<a name="line.331"></a>
-<span class="sourceLineNo">332</span>      throw new RetriesExhaustedException("Can't get the location for replica " + replicaId, e);<a name="line.332"></a>
-<span class="sourceLineNo">333</span>    }<a name="line.333"></a>
-<span class="sourceLineNo">334</span>    if (rl == null) {<a name="line.334"></a>
-<span class="sourceLineNo">335</span>      throw new RetriesExhaustedException("Can't get the location for replica " + replicaId);<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>    return rl;<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>
+<span class="sourceLineNo">282</span>    t.printStackTrace();<a name="line.282"></a>
+<span class="sourceLineNo">283</span><a name="line.283"></a>
+<span class="sourceLineNo">284</span>    if (t instanceof RetriesExhaustedException) {<a name="line.284"></a>
+<span class="sourceLineNo">285</span>      throw (RetriesExhaustedException) t;<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>    if (t instanceof DoNotRetryIOException) {<a name="line.288"></a>
+<span class="sourceLineNo">289</span>      throw (DoNotRetryIOException) t;<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>    RetriesExhaustedException.ThrowableWithExtraContext qt =<a name="line.292"></a>
+<span class="sourceLineNo">293</span>        new RetriesExhaustedException.ThrowableWithExtraContext(t,<a name="line.293"></a>
+<span class="sourceLineNo">294</span>            EnvironmentEdgeManager.currentTime(), null);<a name="line.294"></a>
+<span class="sourceLineNo">295</span><a name="line.295"></a>
+<span class="sourceLineNo">296</span>    List&lt;RetriesExhaustedException.ThrowableWithExtraContext&gt; exceptions =<a name="line.296"></a>
+<span class="sourceLineNo">297</span>        Collections.singletonList(qt);<a name="line.297"></a>
+<span class="sourceLineNo">298</span><a name="line.298"></a>
+<span class="sourceLineNo">299</span>    throw new RetriesExhaustedException(retries, exceptions);<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>   * Creates the calls and submit them<a name="line.303"></a>
+<span class="sourceLineNo">304</span>   *<a name="line.304"></a>
+<span class="sourceLineNo">305</span>   * @param cs  - the completion service to use for submitting<a name="line.305"></a>
+<span class="sourceLineNo">306</span>   * @param rl  - the region locations<a name="line.306"></a>
+<span class="sourceLineNo">307</span>   * @param min - the id of the first replica, inclusive<a name="line.307"></a>
+<span class="sourceLineNo">308</span>   * @param max - the id of the last replica, inclusive.<a name="line.308"></a>
+<span class="sourceLineNo">309</span>   */<a name="line.309"></a>
+<span class="sourceLineNo">310</span>  private void addCallsForReplica(ResultBoundedCompletionService&lt;Result&gt; cs,<a name="line.310"></a>
+<span class="sourceLineNo">311</span>                                 RegionLocations rl, int min, int max) {<a name="line.311"></a>
+<span class="sourceLineNo">312</span>    for (int id = min; id &lt;= max; id++) {<a name="line.312"></a>
+<span class="sourceLineNo">313</span>      HRegionLocation hrl = rl.getRegionLocation(id);<a name="line.313"></a>
+<span class="sourceLineNo">314</span>      ReplicaRegionServerCallable callOnReplica = new ReplicaRegionServerCallable(id, hrl);<a name="line.314"></a>
+<span class="sourceLineNo">315</span>      cs.submit(callOnReplica, operationTimeout, id);<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><a name="line.318"></a>
+<span class="sourceLineNo">319</span>  static RegionLocations getRegionLocations(boolean useCache, int replicaId,<a name="line.319"></a>
+<span class="sourceLineNo">320</span>                 ClusterConnection cConnection, TableName tableName, byte[] row)<a name="line.320"></a>
+<span class="sourceLineNo">321</span>      throws RetriesExhaustedException, DoNotRetryIOException, InterruptedIOException {<a name="line.321"></a>
+<span class="sourceLineNo">322</span><a name="line.322"></a>
+<span class="sourceLineNo">323</span>    RegionLocations rl;<a name="line.323"></a>
+<span class="sourceLineNo">324</span>    try {<a name="line.324"></a>
+<span class="sourceLineNo">325</span>      if (useCache) {<a name="line.325"></a>
+<span class="sourceLineNo">326</span>        rl = cConnection.locateRegion(tableName, row, true, true, replicaId);<a name="line.326"></a>
+<span class="sourceLineNo">327</span>      } else {<a name="line.327"></a>
+<span class="sourceLineNo">328</span>        rl = cConnection.relocateRegion(tableName, row, replicaId);<a name="line.328"></a>
+<span class="sourceLineNo">329</span>      }<a name="line.329"></a>
+<span class="sourceLineNo">330</span>    } catch (DoNotRetryIOException | InterruptedIOException | RetriesExhaustedException e) {<a name="line.330"></a>
+<span class="sourceLineNo">331</span>      throw e;<a name="line.331"></a>
+<span class="sourceLineNo">332</span>    } catch (IOException e) {<a name="line.332"></a>
+<span class="sourceLineNo">333</span>      throw new RetriesExhaustedException("Can't get the location for replica " + replicaId, e);<a name="line.333"></a>
+<span class="sourceLineNo">334</span>    }<a name="line.334"></a>
+<span class="sourceLineNo">335</span>    if (rl == null) {<a name="line.335"></a>
+<span class="sourceLineNo">336</span>      throw new RetriesExhaustedException("Can't get the location for replica " + replicaId);<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>    return rl;<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>
 
 
 

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/src-html/org/apache/hadoop/hbase/client/RpcRetryingCallerWithReadReplicas.html
----------------------------------------------------------------------
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/client/RpcRetryingCallerWithReadReplicas.html b/devapidocs/src-html/org/apache/hadoop/hbase/client/RpcRetryingCallerWithReadReplicas.html
index a8bfe80..878793b 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/client/RpcRetryingCallerWithReadReplicas.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/client/RpcRetryingCallerWithReadReplicas.html
@@ -287,65 +287,66 @@
 <span class="sourceLineNo">279</span>      throws RetriesExhaustedException, DoNotRetryIOException {<a name="line.279"></a>
 <span class="sourceLineNo">280</span>    Throwable t = e.getCause();<a name="line.280"></a>
 <span class="sourceLineNo">281</span>    assert t != null; // That's what ExecutionException is about: holding an exception<a name="line.281"></a>
-<span class="sourceLineNo">282</span><a name="line.282"></a>
-<span class="sourceLineNo">283</span>    if (t instanceof RetriesExhaustedException) {<a name="line.283"></a>
-<span class="sourceLineNo">284</span>      throw (RetriesExhaustedException) t;<a name="line.284"></a>
-<span class="sourceLineNo">285</span>    }<a name="line.285"></a>
-<span class="sourceLineNo">286</span><a name="line.286"></a>
-<span class="sourceLineNo">287</span>    if (t instanceof DoNotRetryIOException) {<a name="line.287"></a>
-<span class="sourceLineNo">288</span>      throw (DoNotRetryIOException) t;<a name="line.288"></a>
-<span class="sourceLineNo">289</span>    }<a name="line.289"></a>
-<span class="sourceLineNo">290</span><a name="line.290"></a>
-<span class="sourceLineNo">291</span>    RetriesExhaustedException.ThrowableWithExtraContext qt =<a name="line.291"></a>
-<span class="sourceLineNo">292</span>        new RetriesExhaustedException.ThrowableWithExtraContext(t,<a name="line.292"></a>
-<span class="sourceLineNo">293</span>            EnvironmentEdgeManager.currentTime(), null);<a name="line.293"></a>
-<span class="sourceLineNo">294</span><a name="line.294"></a>
-<span class="sourceLineNo">295</span>    List&lt;RetriesExhaustedException.ThrowableWithExtraContext&gt; exceptions =<a name="line.295"></a>
-<span class="sourceLineNo">296</span>        Collections.singletonList(qt);<a name="line.296"></a>
-<span class="sourceLineNo">297</span><a name="line.297"></a>
-<span class="sourceLineNo">298</span>    throw new RetriesExhaustedException(retries, exceptions);<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>   * Creates the calls and submit them<a name="line.302"></a>
-<span class="sourceLineNo">303</span>   *<a name="line.303"></a>
-<span class="sourceLineNo">304</span>   * @param cs  - the completion service to use for submitting<a name="line.304"></a>
-<span class="sourceLineNo">305</span>   * @param rl  - the region locations<a name="line.305"></a>
-<span class="sourceLineNo">306</span>   * @param min - the id of the first replica, inclusive<a name="line.306"></a>
-<span class="sourceLineNo">307</span>   * @param max - the id of the last replica, inclusive.<a name="line.307"></a>
-<span class="sourceLineNo">308</span>   */<a name="line.308"></a>
-<span class="sourceLineNo">309</span>  private void addCallsForReplica(ResultBoundedCompletionService&lt;Result&gt; cs,<a name="line.309"></a>
-<span class="sourceLineNo">310</span>                                 RegionLocations rl, int min, int max) {<a name="line.310"></a>
-<span class="sourceLineNo">311</span>    for (int id = min; id &lt;= max; id++) {<a name="line.311"></a>
-<span class="sourceLineNo">312</span>      HRegionLocation hrl = rl.getRegionLocation(id);<a name="line.312"></a>
-<span class="sourceLineNo">313</span>      ReplicaRegionServerCallable callOnReplica = new ReplicaRegionServerCallable(id, hrl);<a name="line.313"></a>
-<span class="sourceLineNo">314</span>      cs.submit(callOnReplica, operationTimeout, id);<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>  static RegionLocations getRegionLocations(boolean useCache, int replicaId,<a name="line.318"></a>
-<span class="sourceLineNo">319</span>                 ClusterConnection cConnection, TableName tableName, byte[] row)<a name="line.319"></a>
-<span class="sourceLineNo">320</span>      throws RetriesExhaustedException, DoNotRetryIOException, InterruptedIOException {<a name="line.320"></a>
-<span class="sourceLineNo">321</span><a name="line.321"></a>
-<span class="sourceLineNo">322</span>    RegionLocations rl;<a name="line.322"></a>
-<span class="sourceLineNo">323</span>    try {<a name="line.323"></a>
-<span class="sourceLineNo">324</span>      if (useCache) {<a name="line.324"></a>
-<span class="sourceLineNo">325</span>        rl = cConnection.locateRegion(tableName, row, true, true, replicaId);<a name="line.325"></a>
-<span class="sourceLineNo">326</span>      } else {<a name="line.326"></a>
-<span class="sourceLineNo">327</span>        rl = cConnection.relocateRegion(tableName, row, replicaId);<a name="line.327"></a>
-<span class="sourceLineNo">328</span>      }<a name="line.328"></a>
-<span class="sourceLineNo">329</span>    } catch (DoNotRetryIOException | InterruptedIOException | RetriesExhaustedException e) {<a name="line.329"></a>
-<span class="sourceLineNo">330</span>      throw e;<a name="line.330"></a>
-<span class="sourceLineNo">331</span>    } catch (IOException e) {<a name="line.331"></a>
-<span class="sourceLineNo">332</span>      throw new RetriesExhaustedException("Can't get the location for replica " + replicaId, e);<a name="line.332"></a>
-<span class="sourceLineNo">333</span>    }<a name="line.333"></a>
-<span class="sourceLineNo">334</span>    if (rl == null) {<a name="line.334"></a>
-<span class="sourceLineNo">335</span>      throw new RetriesExhaustedException("Can't get the location for replica " + replicaId);<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>    return rl;<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>
+<span class="sourceLineNo">282</span>    t.printStackTrace();<a name="line.282"></a>
+<span class="sourceLineNo">283</span><a name="line.283"></a>
+<span class="sourceLineNo">284</span>    if (t instanceof RetriesExhaustedException) {<a name="line.284"></a>
+<span class="sourceLineNo">285</span>      throw (RetriesExhaustedException) t;<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>    if (t instanceof DoNotRetryIOException) {<a name="line.288"></a>
+<span class="sourceLineNo">289</span>      throw (DoNotRetryIOException) t;<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>    RetriesExhaustedException.ThrowableWithExtraContext qt =<a name="line.292"></a>
+<span class="sourceLineNo">293</span>        new RetriesExhaustedException.ThrowableWithExtraContext(t,<a name="line.293"></a>
+<span class="sourceLineNo">294</span>            EnvironmentEdgeManager.currentTime(), null);<a name="line.294"></a>
+<span class="sourceLineNo">295</span><a name="line.295"></a>
+<span class="sourceLineNo">296</span>    List&lt;RetriesExhaustedException.ThrowableWithExtraContext&gt; exceptions =<a name="line.296"></a>
+<span class="sourceLineNo">297</span>        Collections.singletonList(qt);<a name="line.297"></a>
+<span class="sourceLineNo">298</span><a name="line.298"></a>
+<span class="sourceLineNo">299</span>    throw new RetriesExhaustedException(retries, exceptions);<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>   * Creates the calls and submit them<a name="line.303"></a>
+<span class="sourceLineNo">304</span>   *<a name="line.304"></a>
+<span class="sourceLineNo">305</span>   * @param cs  - the completion service to use for submitting<a name="line.305"></a>
+<span class="sourceLineNo">306</span>   * @param rl  - the region locations<a name="line.306"></a>
+<span class="sourceLineNo">307</span>   * @param min - the id of the first replica, inclusive<a name="line.307"></a>
+<span class="sourceLineNo">308</span>   * @param max - the id of the last replica, inclusive.<a name="line.308"></a>
+<span class="sourceLineNo">309</span>   */<a name="line.309"></a>
+<span class="sourceLineNo">310</span>  private void addCallsForReplica(ResultBoundedCompletionService&lt;Result&gt; cs,<a name="line.310"></a>
+<span class="sourceLineNo">311</span>                                 RegionLocations rl, int min, int max) {<a name="line.311"></a>
+<span class="sourceLineNo">312</span>    for (int id = min; id &lt;= max; id++) {<a name="line.312"></a>
+<span class="sourceLineNo">313</span>      HRegionLocation hrl = rl.getRegionLocation(id);<a name="line.313"></a>
+<span class="sourceLineNo">314</span>      ReplicaRegionServerCallable callOnReplica = new ReplicaRegionServerCallable(id, hrl);<a name="line.314"></a>
+<span class="sourceLineNo">315</span>      cs.submit(callOnReplica, operationTimeout, id);<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><a name="line.318"></a>
+<span class="sourceLineNo">319</span>  static RegionLocations getRegionLocations(boolean useCache, int replicaId,<a name="line.319"></a>
+<span class="sourceLineNo">320</span>                 ClusterConnection cConnection, TableName tableName, byte[] row)<a name="line.320"></a>
+<span class="sourceLineNo">321</span>      throws RetriesExhaustedException, DoNotRetryIOException, InterruptedIOException {<a name="line.321"></a>
+<span class="sourceLineNo">322</span><a name="line.322"></a>
+<span class="sourceLineNo">323</span>    RegionLocations rl;<a name="line.323"></a>
+<span class="sourceLineNo">324</span>    try {<a name="line.324"></a>
+<span class="sourceLineNo">325</span>      if (useCache) {<a name="line.325"></a>
+<span class="sourceLineNo">326</span>        rl = cConnection.locateRegion(tableName, row, true, true, replicaId);<a name="line.326"></a>
+<span class="sourceLineNo">327</span>      } else {<a name="line.327"></a>
+<span class="sourceLineNo">328</span>        rl = cConnection.relocateRegion(tableName, row, replicaId);<a name="line.328"></a>
+<span class="sourceLineNo">329</span>      }<a name="line.329"></a>
+<span class="sourceLineNo">330</span>    } catch (DoNotRetryIOException | InterruptedIOException | RetriesExhaustedException e) {<a name="line.330"></a>
+<span class="sourceLineNo">331</span>      throw e;<a name="line.331"></a>
+<span class="sourceLineNo">332</span>    } catch (IOException e) {<a name="line.332"></a>
+<span class="sourceLineNo">333</span>      throw new RetriesExhaustedException("Can't get the location for replica " + replicaId, e);<a name="line.333"></a>
+<span class="sourceLineNo">334</span>    }<a name="line.334"></a>
+<span class="sourceLineNo">335</span>    if (rl == null) {<a name="line.335"></a>
+<span class="sourceLineNo">336</span>      throw new RetriesExhaustedException("Can't get the location for replica " + replicaId);<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>    return rl;<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>
 
 
 


[50/50] hbase-site git commit: Published site at 26babcf013de696b899d76a3c39434b794440d8d.

Posted by gi...@apache.org.
Published site at 26babcf013de696b899d76a3c39434b794440d8d.


Project: http://git-wip-us.apache.org/repos/asf/hbase-site/repo
Commit: http://git-wip-us.apache.org/repos/asf/hbase-site/commit/da4482ac
Tree: http://git-wip-us.apache.org/repos/asf/hbase-site/tree/da4482ac
Diff: http://git-wip-us.apache.org/repos/asf/hbase-site/diff/da4482ac

Branch: refs/heads/asf-site
Commit: da4482ac24b3874e3aaadacdbcd3ff145bc892ee
Parents: 58454ff
Author: jenkins <bu...@apache.org>
Authored: Tue May 15 14:49:24 2018 +0000
Committer: jenkins <bu...@apache.org>
Committed: Tue May 15 14:49:24 2018 +0000

----------------------------------------------------------------------
 acid-semantics.html                             |    4 +-
 apache_hbase_reference_guide.pdf                |    4 +-
 book.html                                       |    2 +-
 bulk-loads.html                                 |    4 +-
 checkstyle-aggregate.html                       |  268 +-
 coc.html                                        |    4 +-
 dependencies.html                               |    4 +-
 dependency-convergence.html                     |    4 +-
 dependency-info.html                            |    4 +-
 dependency-management.html                      |    4 +-
 devapidocs/constant-values.html                 |    6 +-
 devapidocs/index-all.html                       |   25 +-
 .../hadoop/hbase/backup/package-tree.html       |    2 +-
 .../RpcRetryingCallerWithReadReplicas.html      |    4 +-
 .../hadoop/hbase/client/package-tree.html       |   22 +-
 .../hadoop/hbase/filter/package-tree.html       |    8 +-
 ...BlockCacheUtil.CachedBlockCountsPerFile.html |   24 +-
 .../BlockCacheUtil.CachedBlocksByFile.html      |   42 +-
 .../hadoop/hbase/io/hfile/BlockCacheUtil.html   |   84 +-
 .../hbase/io/hfile/Cacheable.MemoryType.html    |    6 +-
 .../apache/hadoop/hbase/io/hfile/Cacheable.html |   15 +-
 .../io/hfile/HFileBlock.BlockIterator.html      |    6 +-
 .../io/hfile/HFileBlock.BlockWritable.html      |    6 +-
 .../hbase/io/hfile/HFileBlock.FSReader.html     |   18 +-
 .../hbase/io/hfile/HFileBlock.FSReaderImpl.html |   58 +-
 .../io/hfile/HFileBlock.PrefetchedHeader.html   |   12 +-
 .../hbase/io/hfile/HFileBlock.Writer.State.html |   12 +-
 .../hbase/io/hfile/HFileBlock.Writer.html       |   80 +-
 .../hadoop/hbase/io/hfile/HFileBlock.html       |  140 +-
 .../io/hfile/LruBlockCache.BlockBucket.html     |   28 +-
 .../io/hfile/LruBlockCache.EvictionThread.html  |   18 +-
 .../hfile/LruBlockCache.StatisticsThread.html   |    8 +-
 .../hadoop/hbase/io/hfile/LruBlockCache.html    |   80 +-
 .../hfile/bucket/BucketCache.BucketEntry.html   |   48 +-
 .../bucket/BucketCache.BucketEntryGroup.html    |   18 +-
 .../hfile/bucket/BucketCache.RAMQueueEntry.html |   20 +-
 .../BucketCache.SharedMemoryBucketEntry.html    |   20 +-
 .../bucket/BucketCache.StatisticsThread.html    |    8 +-
 .../hfile/bucket/BucketCache.WriterThread.html  |   14 +-
 .../hbase/io/hfile/bucket/BucketCache.html      |   82 +-
 .../hbase/io/hfile/class-use/BlockCacheKey.html |    9 +
 .../hbase/io/hfile/class-use/Cacheable.html     |   16 +-
 .../hadoop/hbase/io/hfile/package-tree.html     |    8 +-
 .../apache/hadoop/hbase/ipc/package-tree.html   |    2 +-
 .../hadoop/hbase/mapreduce/package-tree.html    |    2 +-
 .../hbase/master/balancer/package-tree.html     |    2 +-
 .../hadoop/hbase/master/package-tree.html       |    4 +-
 .../hbase/master/procedure/package-tree.html    |    2 +-
 .../org/apache/hadoop/hbase/package-tree.html   |   16 +-
 .../hadoop/hbase/procedure2/package-tree.html   |    4 +-
 .../hadoop/hbase/quotas/package-tree.html       |    6 +-
 .../regionserver/NoLimitScannerContext.html     |    2 +-
 .../regionserver/ScannerContext.Builder.html    |   24 +-
 .../ScannerContext.LimitFields.html             |   84 +-
 .../regionserver/ScannerContext.LimitScope.html |   12 +-
 .../regionserver/ScannerContext.NextState.html  |   28 +-
 .../ScannerContext.ProgressFields.html          |   45 +-
 .../hbase/regionserver/ScannerContext.html      |  114 +-
 .../hadoop/hbase/regionserver/StoreScanner.html |   44 +-
 .../class-use/ScannerContext.LimitScope.html    |   16 -
 .../hadoop/hbase/regionserver/package-tree.html |   16 +-
 .../regionserver/querymatcher/package-tree.html |    2 +-
 .../hbase/regionserver/wal/package-tree.html    |    2 +-
 .../replication/regionserver/package-tree.html  |    2 +-
 .../hadoop/hbase/rest/model/package-tree.html   |    2 +-
 .../hbase/security/access/package-tree.html     |    2 +-
 .../hadoop/hbase/security/package-tree.html     |    2 +-
 .../apache/hadoop/hbase/util/package-tree.html  |   10 +-
 .../org/apache/hadoop/hbase/Version.html        |    6 +-
 ...eadReplicas.ReplicaRegionServerCallable.html |  119 +-
 .../RpcRetryingCallerWithReadReplicas.html      |  119 +-
 ...BlockCacheUtil.CachedBlockCountsPerFile.html |  562 +--
 .../BlockCacheUtil.CachedBlocksByFile.html      |  562 +--
 .../hadoop/hbase/io/hfile/BlockCacheUtil.html   |  562 +--
 .../hbase/io/hfile/Cacheable.MemoryType.html    |   61 +-
 .../apache/hadoop/hbase/io/hfile/Cacheable.html |   61 +-
 .../io/hfile/HFileBlock.BlockIterator.html      | 3512 +++++++++---------
 .../io/hfile/HFileBlock.BlockWritable.html      | 3512 +++++++++---------
 .../hbase/io/hfile/HFileBlock.FSReader.html     | 3512 +++++++++---------
 .../hbase/io/hfile/HFileBlock.FSReaderImpl.html | 3512 +++++++++---------
 .../hbase/io/hfile/HFileBlock.Header.html       | 3512 +++++++++---------
 .../io/hfile/HFileBlock.PrefetchedHeader.html   | 3512 +++++++++---------
 .../hbase/io/hfile/HFileBlock.Writer.State.html | 3512 +++++++++---------
 .../hbase/io/hfile/HFileBlock.Writer.html       | 3512 +++++++++---------
 .../hadoop/hbase/io/hfile/HFileBlock.html       | 3512 +++++++++---------
 .../io/hfile/LruBlockCache.BlockBucket.html     | 1463 ++++----
 .../io/hfile/LruBlockCache.EvictionThread.html  | 1463 ++++----
 .../hfile/LruBlockCache.StatisticsThread.html   | 1463 ++++----
 .../hadoop/hbase/io/hfile/LruBlockCache.html    | 1463 ++++----
 ...emcachedBlockCache.HFileBlockTranscoder.html |    2 +-
 .../hbase/io/hfile/MemcachedBlockCache.html     |    2 +-
 .../hfile/bucket/BucketCache.BucketEntry.html   | 2463 ++++++------
 .../bucket/BucketCache.BucketEntryGroup.html    | 2463 ++++++------
 .../hfile/bucket/BucketCache.RAMQueueEntry.html | 2463 ++++++------
 .../BucketCache.SharedMemoryBucketEntry.html    | 2463 ++++++------
 .../bucket/BucketCache.StatisticsThread.html    | 2463 ++++++------
 .../hfile/bucket/BucketCache.WriterThread.html  | 2463 ++++++------
 .../hbase/io/hfile/bucket/BucketCache.html      | 2463 ++++++------
 .../regionserver/ScannerContext.Builder.html    | 1233 +++---
 .../ScannerContext.LimitFields.html             | 1233 +++---
 .../regionserver/ScannerContext.LimitScope.html | 1233 +++---
 .../regionserver/ScannerContext.NextState.html  | 1233 +++---
 .../ScannerContext.ProgressFields.html          | 1233 +++---
 .../hbase/regionserver/ScannerContext.html      | 1233 +++---
 .../hadoop/hbase/regionserver/StoreScanner.html | 1171 +++---
 downloads.html                                  |    4 +-
 export_control.html                             |    4 +-
 index.html                                      |    4 +-
 integration.html                                |    4 +-
 issue-tracking.html                             |    4 +-
 license.html                                    |    4 +-
 mail-lists.html                                 |    4 +-
 metrics.html                                    |    4 +-
 old_news.html                                   |    4 +-
 plugin-management.html                          |    4 +-
 plugins.html                                    |    4 +-
 poweredbyhbase.html                             |    4 +-
 project-info.html                               |    4 +-
 project-reports.html                            |    4 +-
 project-summary.html                            |    4 +-
 pseudo-distributed.html                         |    4 +-
 replication.html                                |    4 +-
 resources.html                                  |    4 +-
 source-repository.html                          |    4 +-
 sponsors.html                                   |    4 +-
 supportingprojects.html                         |    4 +-
 team-list.html                                  |    4 +-
 testdevapidocs/allclasses-frame.html            |    4 +
 testdevapidocs/allclasses-noframe.html          |    4 +
 testdevapidocs/index-all.html                   |   56 +-
 .../hadoop/hbase/backup/package-tree.html       |    2 +-
 .../CacheTestUtils.ByteArrayCacheable.html      |    8 +-
 .../hadoop/hbase/io/hfile/CacheTestUtils.html   |   33 +-
 .../hfile/TestCacheConfig.DataCacheEntry.html   |    8 +-
 .../hfile/TestCacheConfig.IndexCacheEntry.html  |    2 +-
 .../hfile/TestCacheConfig.MetaCacheEntry.html   |    2 +-
 .../hadoop/hbase/io/hfile/TestHFileBlock.html   |   21 +-
 .../io/hfile/TestLruBlockCache.CachedItem.html  |   30 +-
 .../hbase/io/hfile/TestLruBlockCache.html       |   71 +-
 .../TestBucketCache.MockedBucketCache.html      |    8 +-
 .../hbase/io/hfile/bucket/TestBucketCache.html  |  117 +-
 .../org/apache/hadoop/hbase/package-tree.html   |   10 +-
 .../hadoop/hbase/procedure/package-tree.html    |    8 +-
 .../hadoop/hbase/procedure2/package-tree.html   |    2 +-
 ...treamRead.MatchLastRowCellNextColFilter.html |  337 ++
 ...treamRead.MatchLastRowCellNextRowFilter.html |  337 ++
 ...oStreamRead.MatchLastRowFilterRowFilter.html |  422 +++
 ...witchToStreamRead.MatchLastRowKeyFilter.html |  337 ++
 .../regionserver/TestSwitchToStreamRead.html    |  157 +-
 .../regionserver/TestSyncTimeRangeTracker.html  |    4 +-
 ...treamRead.MatchLastRowCellNextColFilter.html |  125 +
 ...treamRead.MatchLastRowCellNextRowFilter.html |  125 +
 ...oStreamRead.MatchLastRowFilterRowFilter.html |  125 +
 ...witchToStreamRead.MatchLastRowKeyFilter.html |  125 +
 .../hbase/regionserver/package-frame.html       |    4 +
 .../hbase/regionserver/package-summary.html     |   16 +
 .../hadoop/hbase/regionserver/package-tree.html |    8 +-
 .../apache/hadoop/hbase/test/package-tree.html  |    4 +-
 .../apache/hadoop/hbase/wal/package-tree.html   |    2 +-
 testdevapidocs/overview-tree.html               |    4 +
 .../CacheTestUtils.ByteArrayCacheable.html      |   15 +-
 .../io/hfile/CacheTestUtils.HFileBlockPair.html |   15 +-
 .../hadoop/hbase/io/hfile/CacheTestUtils.html   |   15 +-
 .../hfile/TestCacheConfig.DataCacheEntry.html   |    2 +-
 .../io/hfile/TestCacheConfig.Deserializer.html  |    2 +-
 .../hfile/TestCacheConfig.IndexCacheEntry.html  |    2 +-
 .../hfile/TestCacheConfig.MetaCacheEntry.html   |    2 +-
 .../hadoop/hbase/io/hfile/TestCacheConfig.html  |    2 +-
 .../hfile/TestCachedBlockQueue.CachedBlock.html |    2 +-
 .../hbase/io/hfile/TestCachedBlockQueue.html    |    2 +-
 .../hfile/TestHFileBlock.BlockReaderThread.html |   27 +-
 .../hadoop/hbase/io/hfile/TestHFileBlock.html   |   27 +-
 .../io/hfile/TestLruBlockCache.CachedItem.html  | 1778 ++++-----
 .../hbase/io/hfile/TestLruBlockCache.html       | 1778 ++++-----
 .../TestBucketCache.MockedBucketCache.html      |  813 ++--
 .../hbase/io/hfile/bucket/TestBucketCache.html  |  813 ++--
 ...treamRead.MatchLastRowCellNextColFilter.html |  334 ++
 ...treamRead.MatchLastRowCellNextRowFilter.html |  334 ++
 ...oStreamRead.MatchLastRowFilterRowFilter.html |  334 ++
 ...witchToStreamRead.MatchLastRowKeyFilter.html |  334 ++
 .../regionserver/TestSwitchToStreamRead.html    |  313 +-
 .../hadoop/hbase/rsgroup/TestEnableRSGroup.html |    2 +-
 182 files changed, 40381 insertions(+), 36191 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/acid-semantics.html
----------------------------------------------------------------------
diff --git a/acid-semantics.html b/acid-semantics.html
index e2adaf4..6cc0010 100644
--- a/acid-semantics.html
+++ b/acid-semantics.html
@@ -7,7 +7,7 @@
   <head>
     <meta charset="UTF-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-    <meta name="Date-Revision-yyyymmdd" content="20180514" />
+    <meta name="Date-Revision-yyyymmdd" content="20180515" />
     <meta http-equiv="Content-Language" content="en" />
     <title>Apache HBase &#x2013;  
       Apache HBase (TM) ACID Properties
@@ -601,7 +601,7 @@ under the License. -->
                         <a href="https://www.apache.org/">The Apache Software Foundation</a>.
             All rights reserved.      
                     
-                  <li id="publishDate" class="pull-right">Last Published: 2018-05-14</li>
+                  <li id="publishDate" class="pull-right">Last Published: 2018-05-15</li>
             </p>
                 </div>
 

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/apache_hbase_reference_guide.pdf
----------------------------------------------------------------------
diff --git a/apache_hbase_reference_guide.pdf b/apache_hbase_reference_guide.pdf
index 9b11342..da25bdb 100644
--- a/apache_hbase_reference_guide.pdf
+++ b/apache_hbase_reference_guide.pdf
@@ -5,8 +5,8 @@
 /Author (Apache HBase Team)
 /Creator (Asciidoctor PDF 1.5.0.alpha.15, based on Prawn 2.2.2)
 /Producer (Apache HBase Team)
-/ModDate (D:20180514142953+00'00')
-/CreationDate (D:20180514144433+00'00')
+/ModDate (D:20180515142954+00'00')
+/CreationDate (D:20180515144632+00'00')
 >>
 endobj
 2 0 obj

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/book.html
----------------------------------------------------------------------
diff --git a/book.html b/book.html
index b6aefe4..377d88e 100644
--- a/book.html
+++ b/book.html
@@ -37873,7 +37873,7 @@ The server will return cellblocks compressed using this same compressor as long
 <div id="footer">
 <div id="footer-text">
 Version 3.0.0-SNAPSHOT<br>
-Last updated 2018-05-14 14:29:53 UTC
+Last updated 2018-05-15 14:29:54 UTC
 </div>
 </div>
 </body>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/bulk-loads.html
----------------------------------------------------------------------
diff --git a/bulk-loads.html b/bulk-loads.html
index a22b742..639c1ac 100644
--- a/bulk-loads.html
+++ b/bulk-loads.html
@@ -7,7 +7,7 @@
   <head>
     <meta charset="UTF-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-    <meta name="Date-Revision-yyyymmdd" content="20180514" />
+    <meta name="Date-Revision-yyyymmdd" content="20180515" />
     <meta http-equiv="Content-Language" content="en" />
     <title>Apache HBase &#x2013;  
       Bulk Loads in Apache HBase (TM)
@@ -306,7 +306,7 @@ under the License. -->
                         <a href="https://www.apache.org/">The Apache Software Foundation</a>.
             All rights reserved.      
                     
-                  <li id="publishDate" class="pull-right">Last Published: 2018-05-14</li>
+                  <li id="publishDate" class="pull-right">Last Published: 2018-05-15</li>
             </p>
                 </div>
 

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/checkstyle-aggregate.html
----------------------------------------------------------------------
diff --git a/checkstyle-aggregate.html b/checkstyle-aggregate.html
index 6d9c5bc..e85f02a 100644
--- a/checkstyle-aggregate.html
+++ b/checkstyle-aggregate.html
@@ -7,7 +7,7 @@
   <head>
     <meta charset="UTF-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-    <meta name="Date-Revision-yyyymmdd" content="20180514" />
+    <meta name="Date-Revision-yyyymmdd" content="20180515" />
     <meta http-equiv="Content-Language" content="en" />
     <title>Apache HBase &#x2013; Checkstyle Results</title>
     <link rel="stylesheet" href="./css/apache-maven-fluido-1.5-HBASE.min.css" />
@@ -10327,12 +10327,12 @@
 <td><a class="externalLink" href="http://checkstyle.sourceforge.net/config_javadoc.html#JavadocTagContinuationIndentation">JavadocTagContinuationIndentation</a>
 <ul>
 <li>offset: <tt>&quot;2&quot;</tt></li></ul></td>
-<td>797</td>
+<td>783</td>
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td></tr>
 <tr class="a">
 <td></td>
 <td><a class="externalLink" href="http://checkstyle.sourceforge.net/config_javadoc.html#NonEmptyAtclauseDescription">NonEmptyAtclauseDescription</a></td>
-<td>3817</td>
+<td>3831</td>
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td></tr>
 <tr class="b">
 <td>misc</td>
@@ -14505,7 +14505,7 @@
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
-<td>JavadocTagContinuationIndentation</td>
+<td>NonEmptyAtclauseDescription</td>
 <td>Javadoc comment at column 26 has parse error. Missed HTML close tag 'arg'. Sometimes it means that close tag missed for one of previous tags.</td>
 <td>44</td></tr></table></div>
 <div class="section">
@@ -15141,7 +15141,7 @@
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
-<td>JavadocTagContinuationIndentation</td>
+<td>NonEmptyAtclauseDescription</td>
 <td>Javadoc comment at column 4 has parse error. Missed HTML close tag 'pre'. Sometimes it means that close tag missed for one of previous tags.</td>
 <td>59</td></tr></table></div>
 <div class="section">
@@ -16896,7 +16896,7 @@
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
-<td>JavadocTagContinuationIndentation</td>
+<td>NonEmptyAtclauseDescription</td>
 <td>Javadoc comment at column 19 has parse error. Details: no viable alternative at input '&lt;code&gt;\n   *   List&lt;Future&lt;' while parsing HTML_TAG</td>
 <td>167</td></tr></table></div>
 <div class="section">
@@ -19902,7 +19902,7 @@
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
-<td>JavadocTagContinuationIndentation</td>
+<td>NonEmptyAtclauseDescription</td>
 <td>Javadoc comment at column 2 has parse error. Unrecognized error from ANTLR parser: null</td>
 <td>83</td></tr>
 <tr class="b">
@@ -33849,7 +33849,7 @@
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
-<td>JavadocTagContinuationIndentation</td>
+<td>NonEmptyAtclauseDescription</td>
 <td>Javadoc comment at column 37 has parse error. Details: no viable alternative at input '&lt;ColumnFamily,' while parsing HTML_ELEMENT</td>
 <td>29</td></tr></table></div>
 <div class="section">
@@ -48077,139 +48077,139 @@
 <td>design</td>
 <td>HideUtilityClassConstructor</td>
 <td>Utility classes should not have a public or default constructor.</td>
-<td>41</td></tr>
+<td>43</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>NonEmptyAtclauseDescription</td>
 <td>At-clause should have a non-empty description.</td>
-<td>58</td></tr>
+<td>61</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>NonEmptyAtclauseDescription</td>
 <td>At-clause should have a non-empty description.</td>
-<td>102</td></tr>
+<td>105</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>NonEmptyAtclauseDescription</td>
 <td>At-clause should have a non-empty description.</td>
-<td>103</td></tr>
+<td>106</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>NonEmptyAtclauseDescription</td>
 <td>At-clause should have a non-empty description.</td>
-<td>105</td></tr>
+<td>108</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>NonEmptyAtclauseDescription</td>
 <td>At-clause should have a non-empty description.</td>
-<td>106</td></tr>
+<td>109</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>NonEmptyAtclauseDescription</td>
 <td>At-clause should have a non-empty description.</td>
-<td>107</td></tr>
+<td>110</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>NonEmptyAtclauseDescription</td>
 <td>At-clause should have a non-empty description.</td>
-<td>125</td></tr>
+<td>128</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>NonEmptyAtclauseDescription</td>
 <td>At-clause should have a non-empty description.</td>
-<td>127</td></tr>
+<td>130</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>NonEmptyAtclauseDescription</td>
 <td>At-clause should have a non-empty description.</td>
-<td>128</td></tr>
+<td>131</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>NonEmptyAtclauseDescription</td>
 <td>At-clause should have a non-empty description.</td>
-<td>129</td></tr>
+<td>132</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>NonEmptyAtclauseDescription</td>
 <td>At-clause should have a non-empty description.</td>
-<td>137</td></tr>
+<td>140</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>NonEmptyAtclauseDescription</td>
 <td>At-clause should have a non-empty description.</td>
-<td>139</td></tr>
+<td>142</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>NonEmptyAtclauseDescription</td>
 <td>At-clause should have a non-empty description.</td>
-<td>140</td></tr>
+<td>143</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>NonEmptyAtclauseDescription</td>
 <td>At-clause should have a non-empty description.</td>
-<td>141</td></tr>
+<td>144</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>NonEmptyAtclauseDescription</td>
 <td>At-clause should have a non-empty description.</td>
-<td>149</td></tr>
+<td>152</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>blocks</td>
 <td>NeedBraces</td>
 <td>'if' construct must use '{}'s.</td>
-<td>171</td></tr>
+<td>174</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>whitespace</td>
 <td>FileTabCharacter</td>
 <td>File contains tab characters (this is the first instance).</td>
-<td>182</td></tr>
+<td>186</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>sizes</td>
 <td>LineLength</td>
 <td>Line is longer than 100 characters (found 110).</td>
-<td>218</td></tr>
+<td>250</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>NonEmptyAtclauseDescription</td>
 <td>At-clause should have a non-empty description.</td>
-<td>222</td></tr>
+<td>254</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>blocks</td>
 <td>NeedBraces</td>
 <td>'if' construct must use '{}'s.</td>
-<td>226</td></tr>
+<td>258</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>JavadocTagContinuationIndentation</td>
 <td>Line continuation have incorrect indentation level, expected level should be 2.</td>
-<td>247</td></tr>
+<td>279</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>JavadocTagContinuationIndentation</td>
 <td>Line continuation have incorrect indentation level, expected level should be 2.</td>
-<td>248</td></tr></table></div>
+<td>280</td></tr></table></div>
 <div class="section">
 <h3 id="org.apache.hadoop.hbase.io.hfile.BlockCachesIterator.java">org/apache/hadoop/hbase/io/hfile/BlockCachesIterator.java</h3>
 <table border="0" class="table table-striped">
@@ -48914,121 +48914,121 @@
 <td>javadoc</td>
 <td>JavadocTagContinuationIndentation</td>
 <td>Line continuation have incorrect indentation level, expected level should be 2.</td>
-<td>431</td></tr>
+<td>432</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>JavadocTagContinuationIndentation</td>
 <td>Line continuation have incorrect indentation level, expected level should be 2.</td>
-<td>432</td></tr>
+<td>433</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>indentation</td>
 <td>Indentation</td>
 <td>'method def modifier' have incorrect indentation level 3, expected level should be 2.</td>
-<td>469</td></tr>
+<td>470</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>sizes</td>
 <td>LineLength</td>
 <td>Line is longer than 100 characters (found 104).</td>
-<td>701</td></tr>
+<td>703</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>NonEmptyAtclauseDescription</td>
 <td>At-clause should have a non-empty description.</td>
-<td>943</td></tr>
+<td>945</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>NonEmptyAtclauseDescription</td>
 <td>At-clause should have a non-empty description.</td>
-<td>973</td></tr>
+<td>975</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>NonEmptyAtclauseDescription</td>
 <td>At-clause should have a non-empty description.</td>
-<td>974</td></tr>
+<td>976</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>NonEmptyAtclauseDescription</td>
 <td>At-clause should have a non-empty description.</td>
-<td>1093</td></tr>
+<td>1095</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>NonEmptyAtclauseDescription</td>
 <td>At-clause should have a non-empty description.</td>
-<td>1094</td></tr>
+<td>1096</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>NonEmptyAtclauseDescription</td>
 <td>At-clause should have a non-empty description.</td>
-<td>1115</td></tr>
+<td>1117</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>blocks</td>
 <td>NeedBraces</td>
 <td>'if' construct must use '{}'s.</td>
-<td>1219</td></tr>
+<td>1221</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>blocks</td>
 <td>NeedBraces</td>
 <td>'if' construct must use '{}'s.</td>
-<td>1232</td></tr>
+<td>1234</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>NonEmptyAtclauseDescription</td>
 <td>At-clause should have a non-empty description.</td>
-<td>1285</td></tr>
+<td>1287</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>indentation</td>
 <td>Indentation</td>
 <td>'method def' child have incorrect indentation level 7, expected level should be 6.</td>
-<td>1318</td></tr>
+<td>1320</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>NonEmptyAtclauseDescription</td>
 <td>At-clause should have a non-empty description.</td>
-<td>1362</td></tr>
+<td>1364</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>sizes</td>
 <td>LineLength</td>
 <td>Line is longer than 100 characters (found 111).</td>
-<td>1440</td></tr>
+<td>1442</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>NonEmptyAtclauseDescription</td>
 <td>At-clause should have a non-empty description.</td>
-<td>1530</td></tr>
+<td>1532</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>NonEmptyAtclauseDescription</td>
 <td>At-clause should have a non-empty description.</td>
-<td>1651</td></tr>
+<td>1653</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>NonEmptyAtclauseDescription</td>
 <td>At-clause should have a non-empty description.</td>
-<td>1667</td></tr>
+<td>1669</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>JavadocTagContinuationIndentation</td>
 <td>Line continuation have incorrect indentation level, expected level should be 2.</td>
-<td>2059</td></tr></table></div>
+<td>2061</td></tr></table></div>
 <div class="section">
 <h3 id="org.apache.hadoop.hbase.io.hfile.HFileBlockIndex.java">org/apache/hadoop/hbase/io/hfile/HFileBlockIndex.java</h3>
 <table border="0" class="table table-striped">
@@ -50160,7 +50160,7 @@
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
-<td>JavadocTagContinuationIndentation</td>
+<td>NonEmptyAtclauseDescription</td>
 <td>Javadoc comment at column 24 has parse error. Details: no viable alternative at input '&lt;key,' while parsing HTML_ELEMENT</td>
 <td>25</td></tr>
 <tr class="a">
@@ -50207,73 +50207,73 @@
 <td>indentation</td>
 <td>Indentation</td>
 <td>'if' child have incorrect indentation level 7, expected level should be 6.</td>
-<td>414</td></tr>
+<td>419</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>indentation</td>
 <td>Indentation</td>
 <td>'if' child have incorrect indentation level 7, expected level should be 6.</td>
-<td>468</td></tr>
+<td>473</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>blocks</td>
 <td>NeedBraces</td>
 <td>'if' construct must use '{}'s.</td>
-<td>510</td></tr>
+<td>515</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>blocks</td>
 <td>NeedBraces</td>
 <td>'if' construct must use '{}'s.</td>
-<td>545</td></tr>
+<td>550</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>indentation</td>
 <td>Indentation</td>
 <td>'if' child have incorrect indentation level 7, expected level should be 6.</td>
-<td>575</td></tr>
+<td>580</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>blocks</td>
 <td>NeedBraces</td>
 <td>'if' construct must use '{}'s.</td>
-<td>615</td></tr>
+<td>620</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>blocks</td>
 <td>NeedBraces</td>
 <td>'if' construct must use '{}'s.</td>
-<td>628</td></tr>
+<td>633</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>coding</td>
 <td>MissingSwitchDefault</td>
 <td>switch without &quot;default&quot; clause.</td>
-<td>637</td></tr>
+<td>642</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>blocks</td>
 <td>NeedBraces</td>
 <td>'if' construct must use '{}'s.</td>
-<td>903</td></tr>
+<td>908</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>blocks</td>
 <td>NeedBraces</td>
 <td>'if' construct must use '{}'s.</td>
-<td>1051</td></tr>
+<td>1056</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>blocks</td>
 <td>NeedBraces</td>
 <td>'if' construct must use '{}'s.</td>
-<td>1053</td></tr>
+<td>1058</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>blocks</td>
 <td>NeedBraces</td>
 <td>'if' construct must use '{}'s.</td>
-<td>1183</td></tr></table></div>
+<td>1188</td></tr></table></div>
 <div class="section">
 <h3 id="org.apache.hadoop.hbase.io.hfile.LruCachedBlock.java">org/apache/hadoop/hbase/io/hfile/LruCachedBlock.java</h3>
 <table border="0" class="table table-striped">
@@ -51383,19 +51383,19 @@
 <td>sizes</td>
 <td>LineLength</td>
 <td>Line is longer than 100 characters (found 117).</td>
-<td>84</td></tr>
+<td>85</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>sizes</td>
 <td>LineLength</td>
 <td>Line is longer than 100 characters (found 106).</td>
-<td>85</td></tr>
+<td>86</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>indentation</td>
 <td>Indentation</td>
 <td>'method def' child have incorrect indentation level 3, expected level should be 4.</td>
-<td>719</td></tr></table></div>
+<td>720</td></tr></table></div>
 <div class="section">
 <h3 id="org.apache.hadoop.hbase.io.hfile.TestPrefetch.java">org/apache/hadoop/hbase/io/hfile/TestPrefetch.java</h3>
 <table border="0" class="table table-striped">
@@ -51824,127 +51824,127 @@
 <td>coding</td>
 <td>MissingSwitchDefault</td>
 <td>switch without &quot;default&quot; clause.</td>
-<td>808</td></tr>
+<td>815</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>blocks</td>
 <td>NeedBraces</td>
 <td>'if' construct must use '{}'s.</td>
-<td>919</td></tr>
+<td>926</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>NonEmptyAtclauseDescription</td>
 <td>At-clause should have a non-empty description.</td>
-<td>938</td></tr>
+<td>945</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>blocks</td>
 <td>NeedBraces</td>
 <td>'if' construct must use '{}'s.</td>
-<td>1077</td></tr>
+<td>1084</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>blocks</td>
 <td>NeedBraces</td>
 <td>'if' construct must use '{}'s.</td>
-<td>1078</td></tr>
+<td>1085</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>blocks</td>
 <td>NeedBraces</td>
 <td>'if' construct must use '{}'s.</td>
-<td>1093</td></tr>
+<td>1100</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>blocks</td>
 <td>NeedBraces</td>
 <td>'if' construct must use '{}'s.</td>
-<td>1099</td></tr>
+<td>1106</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>blocks</td>
 <td>NeedBraces</td>
 <td>'if' construct must use '{}'s.</td>
-<td>1105</td></tr>
+<td>1112</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>blocks</td>
 <td>NeedBraces</td>
 <td>'if' construct must use '{}'s.</td>
-<td>1108</td></tr>
+<td>1115</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>blocks</td>
 <td>NeedBraces</td>
 <td>'if' construct must use '{}'s.</td>
-<td>1121</td></tr>
+<td>1128</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>blocks</td>
 <td>NeedBraces</td>
 <td>'if' construct must use '{}'s.</td>
-<td>1122</td></tr>
+<td>1129</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>blocks</td>
 <td>NeedBraces</td>
 <td>'if' construct must use '{}'s.</td>
-<td>1152</td></tr>
+<td>1159</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>blocks</td>
 <td>NeedBraces</td>
 <td>'for' construct must use '{}'s.</td>
-<td>1156</td></tr>
+<td>1163</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>blocks</td>
 <td>NeedBraces</td>
 <td>'for' construct must use '{}'s.</td>
-<td>1165</td></tr>
+<td>1172</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>indentation</td>
 <td>Indentation</td>
 <td>'if' child have incorrect indentation level 10, expected level should be 8.</td>
-<td>1246</td></tr>
+<td>1253</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>sizes</td>
 <td>LineLength</td>
 <td>Line is longer than 100 characters (found 130).</td>
-<td>1297</td></tr>
+<td>1304</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>sizes</td>
 <td>LineLength</td>
 <td>Line is longer than 100 characters (found 127).</td>
-<td>1298</td></tr>
+<td>1305</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>blocks</td>
 <td>NeedBraces</td>
 <td>'if' construct must use '{}'s.</td>
-<td>1487</td></tr>
+<td>1494</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>NonEmptyAtclauseDescription</td>
 <td>At-clause should have a non-empty description.</td>
-<td>1524</td></tr>
+<td>1531</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>blocks</td>
 <td>NeedBraces</td>
 <td>'if' construct must use '{}'s.</td>
-<td>1590</td></tr>
+<td>1597</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>blocks</td>
 <td>NeedBraces</td>
 <td>'if' construct must use '{}'s.</td>
-<td>1593</td></tr></table></div>
+<td>1600</td></tr></table></div>
 <div class="section">
 <h3 id="org.apache.hadoop.hbase.io.hfile.bucket.BucketCacheStats.java">org/apache/hadoop/hbase/io/hfile/bucket/BucketCacheStats.java</h3>
 <table border="0" class="table table-striped">
@@ -52133,91 +52133,91 @@
 <td>indentation</td>
 <td>Indentation</td>
 <td>'array initialization' child have incorrect indentation level 12, expected level should be 8.</td>
-<td>76</td></tr>
+<td>83</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>indentation</td>
 <td>Indentation</td>
 <td>'array initialization' child have incorrect indentation level 12, expected level should be 8.</td>
-<td>77</td></tr>
+<td>84</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>indentation</td>
 <td>Indentation</td>
 <td>'array initialization' child have incorrect indentation level 16, expected level should be one of the following: 14, 24.</td>
-<td>78</td></tr>
+<td>85</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>indentation</td>
 <td>Indentation</td>
 <td>'array initialization' child have incorrect indentation level 16, expected level should be one of the following: 14, 24.</td>
-<td>79</td></tr>
+<td>86</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>blocks</td>
 <td>NeedBraces</td>
 <td>'if' construct must use '{}'s.</td>
-<td>167</td></tr>
+<td>168</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>sizes</td>
 <td>LineLength</td>
 <td>Line is longer than 100 characters (found 103).</td>
-<td>293</td></tr>
+<td>294</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>sizes</td>
 <td>LineLength</td>
 <td>Line is longer than 100 characters (found 111).</td>
-<td>340</td></tr>
+<td>341</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>sizes</td>
 <td>LineLength</td>
 <td>Line is longer than 100 characters (found 115).</td>
-<td>361</td></tr>
+<td>362</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>sizes</td>
 <td>LineLength</td>
 <td>Line is longer than 100 characters (found 137).</td>
-<td>371</td></tr>
+<td>372</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>sizes</td>
 <td>LineLength</td>
 <td>Line is longer than 100 characters (found 130).</td>
-<td>380</td></tr>
+<td>381</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>sizes</td>
 <td>LineLength</td>
 <td>Line is longer than 100 characters (found 156).</td>
-<td>389</td></tr>
+<td>390</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>sizes</td>
 <td>LineLength</td>
 <td>Line is longer than 100 characters (found 157).</td>
-<td>391</td></tr>
+<td>392</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>sizes</td>
 <td>LineLength</td>
 <td>Line is longer than 100 characters (found 106).</td>
-<td>396</td></tr>
+<td>397</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>sizes</td>
 <td>LineLength</td>
 <td>Line is longer than 100 characters (found 117).</td>
-<td>397</td></tr>
+<td>398</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>sizes</td>
 <td>LineLength</td>
 <td>Line is longer than 100 characters (found 107).</td>
-<td>403</td></tr></table></div>
+<td>404</td></tr></table></div>
 <div class="section">
 <h3 id="org.apache.hadoop.hbase.io.hfile.bucket.TestBucketWriterThread.java">org/apache/hadoop/hbase/io/hfile/bucket/TestBucketWriterThread.java</h3>
 <table border="0" class="table table-striped">
@@ -53748,7 +53748,7 @@
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
-<td>JavadocTagContinuationIndentation</td>
+<td>NonEmptyAtclauseDescription</td>
 <td>Javadoc comment at column 2 has parse error. Unrecognized error from ANTLR parser: null</td>
 <td>587</td></tr>
 <tr class="b">
@@ -73353,7 +73353,7 @@
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
-<td>JavadocTagContinuationIndentation</td>
+<td>NonEmptyAtclauseDescription</td>
 <td>Javadoc comment at column 60 has parse error. Missed HTML close tag 'Comparable'. Sometimes it means that close tag missed for one of previous tags.</td>
 <td>29</td></tr>
 <tr class="b">
@@ -77535,7 +77535,7 @@
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
-<td>JavadocTagContinuationIndentation</td>
+<td>NonEmptyAtclauseDescription</td>
 <td>Javadoc comment at column 0 has parse error. Unrecognized error from ANTLR parser: null</td>
 <td>74</td></tr>
 <tr class="b">
@@ -85340,49 +85340,49 @@
 <td>javadoc</td>
 <td>NonEmptyAtclauseDescription</td>
 <td>At-clause should have a non-empty description.</td>
-<td>206</td></tr>
+<td>212</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>NonEmptyAtclauseDescription</td>
 <td>At-clause should have a non-empty description.</td>
-<td>229</td></tr>
+<td>235</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>NonEmptyAtclauseDescription</td>
 <td>At-clause should have a non-empty description.</td>
-<td>237</td></tr>
+<td>243</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>NonEmptyAtclauseDescription</td>
 <td>At-clause should have a non-empty description.</td>
-<td>246</td></tr>
+<td>252</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>NonEmptyAtclauseDescription</td>
 <td>At-clause should have a non-empty description.</td>
-<td>254</td></tr>
+<td>261</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>NonEmptyAtclauseDescription</td>
 <td>At-clause should have a non-empty description.</td>
-<td>576</td></tr>
+<td>583</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>NonEmptyAtclauseDescription</td>
 <td>At-clause should have a non-empty description.</td>
-<td>614</td></tr>
+<td>621</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>NonEmptyAtclauseDescription</td>
 <td>At-clause should have a non-empty description.</td>
-<td>644</td></tr></table></div>
+<td>651</td></tr></table></div>
 <div class="section">
 <h3 id="org.apache.hadoop.hbase.regionserver.ScannerIdGenerator.java">org/apache/hadoop/hbase/regionserver/ScannerIdGenerator.java</h3>
 <table border="0" class="table table-striped">
@@ -86344,86 +86344,86 @@
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>sizes</td>
 <td>MethodLength</td>
-<td>Method length is 189 lines (max allowed is 150).</td>
+<td>Method length is 204 lines (max allowed is 150).</td>
 <td>512</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>coding</td>
 <td>InnerAssignment</td>
 <td>Inner assignments should be avoided.</td>
-<td>692</td></tr>
+<td>707</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>coding</td>
 <td>InnerAssignment</td>
 <td>Inner assignments should be avoided.</td>
-<td>799</td></tr>
+<td>814</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>coding</td>
 <td>InnerAssignment</td>
 <td>Inner assignments should be avoided.</td>
-<td>820</td></tr>
+<td>835</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>NonEmptyAtclauseDescription</td>
 <td>At-clause should have a non-empty description.</td>
-<td>940</td></tr>
+<td>955</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>NonEmptyAtclauseDescription</td>
 <td>At-clause should have a non-empty description.</td>
-<td>941</td></tr>
+<td>956</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>NonEmptyAtclauseDescription</td>
 <td>At-clause should have a non-empty description.</td>
-<td>942</td></tr>
+<td>957</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>NonEmptyAtclauseDescription</td>
 <td>At-clause should have a non-empty description.</td>
-<td>943</td></tr>
+<td>958</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>NonEmptyAtclauseDescription</td>
 <td>At-clause should have a non-empty description.</td>
-<td>959</td></tr>
+<td>974</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>NonEmptyAtclauseDescription</td>
 <td>At-clause should have a non-empty description.</td>
-<td>961</td></tr>
+<td>976</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>NonEmptyAtclauseDescription</td>
 <td>At-clause should have a non-empty description.</td>
-<td>1054</td></tr>
+<td>1069</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>blocks</td>
 <td>NeedBraces</td>
 <td>'if' construct must use '{}'s.</td>
-<td>1058</td></tr>
+<td>1073</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>blocks</td>
 <td>NeedBraces</td>
 <td>'if' construct must use '{}'s.</td>
-<td>1095</td></tr>
+<td>1110</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>blocks</td>
 <td>NeedBraces</td>
 <td>'for' construct must use '{}'s.</td>
-<td>1097</td></tr></table></div>
+<td>1112</td></tr></table></div>
 <div class="section">
 <h3 id="org.apache.hadoop.hbase.regionserver.StoreUtils.java">org/apache/hadoop/hbase/regionserver/StoreUtils.java</h3>
 <table border="0" class="table table-striped">
@@ -87435,7 +87435,7 @@
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
-<td>JavadocTagContinuationIndentation</td>
+<td>NonEmptyAtclauseDescription</td>
 <td>Javadoc comment at column 33 has parse error. Missed HTML close tag 'number'. Sometimes it means that close tag missed for one of previous tags.</td>
 <td>127</td></tr>
 <tr class="b">
@@ -115983,7 +115983,7 @@
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
-<td>JavadocTagContinuationIndentation</td>
+<td>NonEmptyAtclauseDescription</td>
 <td>Javadoc comment at column 23 has parse error. Details: no viable alternative at input '&lt;expected,' while parsing HTML_ELEMENT</td>
 <td>143</td></tr>
 <tr class="a">
@@ -116187,7 +116187,7 @@
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
-<td>JavadocTagContinuationIndentation</td>
+<td>NonEmptyAtclauseDescription</td>
 <td>Javadoc comment at column 78 has parse error. Details: no viable alternative at input '&lt;Object&gt;, Map&lt;String,' while parsing HTML_TAG</td>
 <td>33</td></tr>
 <tr class="a">
@@ -116787,7 +116787,7 @@
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
-<td>JavadocTagContinuationIndentation</td>
+<td>NonEmptyAtclauseDescription</td>
 <td>Javadoc comment at column 35 has parse error. Missed HTML close tag 'index'. Sometimes it means that close tag missed for one of previous tags.</td>
 <td>823</td></tr>
 <tr class="b">
@@ -120600,7 +120600,7 @@
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
-<td>JavadocTagContinuationIndentation</td>
+<td>NonEmptyAtclauseDescription</td>
 <td>Javadoc comment at column 58 has parse error. Details: no viable alternative at input '&lt;byte[' while parsing HTML_ELEMENT</td>
 <td>426</td></tr>
 <tr class="b">
@@ -123435,7 +123435,7 @@
                         <a href="https://www.apache.org/">The Apache Software Foundation</a>.
             All rights reserved.      
                     
-                  <li id="publishDate" class="pull-right">Last Published: 2018-05-14</li>
+                  <li id="publishDate" class="pull-right">Last Published: 2018-05-15</li>
             </p>
                 </div>
 

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/coc.html
----------------------------------------------------------------------
diff --git a/coc.html b/coc.html
index 84282d4..af3dc34 100644
--- a/coc.html
+++ b/coc.html
@@ -7,7 +7,7 @@
   <head>
     <meta charset="UTF-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-    <meta name="Date-Revision-yyyymmdd" content="20180514" />
+    <meta name="Date-Revision-yyyymmdd" content="20180515" />
     <meta http-equiv="Content-Language" content="en" />
     <title>Apache HBase &#x2013; 
       Code of Conduct Policy
@@ -375,7 +375,7 @@ email to <a class="externalLink" href="mailto:private@hbase.apache.org">the priv
                         <a href="https://www.apache.org/">The Apache Software Foundation</a>.
             All rights reserved.      
                     
-                  <li id="publishDate" class="pull-right">Last Published: 2018-05-14</li>
+                  <li id="publishDate" class="pull-right">Last Published: 2018-05-15</li>
             </p>
                 </div>
 

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/dependencies.html
----------------------------------------------------------------------
diff --git a/dependencies.html b/dependencies.html
index a402556..f48f703 100644
--- a/dependencies.html
+++ b/dependencies.html
@@ -7,7 +7,7 @@
   <head>
     <meta charset="UTF-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-    <meta name="Date-Revision-yyyymmdd" content="20180514" />
+    <meta name="Date-Revision-yyyymmdd" content="20180515" />
     <meta http-equiv="Content-Language" content="en" />
     <title>Apache HBase &#x2013; Project Dependencies</title>
     <link rel="stylesheet" href="./css/apache-maven-fluido-1.5-HBASE.min.css" />
@@ -440,7 +440,7 @@
                         <a href="https://www.apache.org/">The Apache Software Foundation</a>.
             All rights reserved.      
                     
-                  <li id="publishDate" class="pull-right">Last Published: 2018-05-14</li>
+                  <li id="publishDate" class="pull-right">Last Published: 2018-05-15</li>
             </p>
                 </div>
 

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/dependency-convergence.html
----------------------------------------------------------------------
diff --git a/dependency-convergence.html b/dependency-convergence.html
index 8af1bc9..97132c9 100644
--- a/dependency-convergence.html
+++ b/dependency-convergence.html
@@ -7,7 +7,7 @@
   <head>
     <meta charset="UTF-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-    <meta name="Date-Revision-yyyymmdd" content="20180514" />
+    <meta name="Date-Revision-yyyymmdd" content="20180515" />
     <meta http-equiv="Content-Language" content="en" />
     <title>Apache HBase &#x2013; Reactor Dependency Convergence</title>
     <link rel="stylesheet" href="./css/apache-maven-fluido-1.5-HBASE.min.css" />
@@ -1105,7 +1105,7 @@
                         <a href="https://www.apache.org/">The Apache Software Foundation</a>.
             All rights reserved.      
                     
-                  <li id="publishDate" class="pull-right">Last Published: 2018-05-14</li>
+                  <li id="publishDate" class="pull-right">Last Published: 2018-05-15</li>
             </p>
                 </div>
 

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/dependency-info.html
----------------------------------------------------------------------
diff --git a/dependency-info.html b/dependency-info.html
index b6b46aa..3314a6c 100644
--- a/dependency-info.html
+++ b/dependency-info.html
@@ -7,7 +7,7 @@
   <head>
     <meta charset="UTF-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-    <meta name="Date-Revision-yyyymmdd" content="20180514" />
+    <meta name="Date-Revision-yyyymmdd" content="20180515" />
     <meta http-equiv="Content-Language" content="en" />
     <title>Apache HBase &#x2013; Dependency Information</title>
     <link rel="stylesheet" href="./css/apache-maven-fluido-1.5-HBASE.min.css" />
@@ -313,7 +313,7 @@
                         <a href="https://www.apache.org/">The Apache Software Foundation</a>.
             All rights reserved.      
                     
-                  <li id="publishDate" class="pull-right">Last Published: 2018-05-14</li>
+                  <li id="publishDate" class="pull-right">Last Published: 2018-05-15</li>
             </p>
                 </div>
 

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/dependency-management.html
----------------------------------------------------------------------
diff --git a/dependency-management.html b/dependency-management.html
index 6849fea..cd8795f 100644
--- a/dependency-management.html
+++ b/dependency-management.html
@@ -7,7 +7,7 @@
   <head>
     <meta charset="UTF-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-    <meta name="Date-Revision-yyyymmdd" content="20180514" />
+    <meta name="Date-Revision-yyyymmdd" content="20180515" />
     <meta http-equiv="Content-Language" content="en" />
     <title>Apache HBase &#x2013; Project Dependency Management</title>
     <link rel="stylesheet" href="./css/apache-maven-fluido-1.5-HBASE.min.css" />
@@ -969,7 +969,7 @@
                         <a href="https://www.apache.org/">The Apache Software Foundation</a>.
             All rights reserved.      
                     
-                  <li id="publishDate" class="pull-right">Last Published: 2018-05-14</li>
+                  <li id="publishDate" class="pull-right">Last Published: 2018-05-15</li>
             </p>
                 </div>
 

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/constant-values.html
----------------------------------------------------------------------
diff --git a/devapidocs/constant-values.html b/devapidocs/constant-values.html
index 0a97748..74733ae 100644
--- a/devapidocs/constant-values.html
+++ b/devapidocs/constant-values.html
@@ -3768,21 +3768,21 @@
 <!--   -->
 </a><code>public&nbsp;static&nbsp;final&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a></code></td>
 <td><code><a href="org/apache/hadoop/hbase/Version.html#date">date</a></code></td>
-<td class="colLast"><code>"Mon May 14 14:39:07 UTC 2018"</code></td>
+<td class="colLast"><code>"Tue May 15 14:40:24 UTC 2018"</code></td>
 </tr>
 <tr class="rowColor">
 <td class="colFirst"><a name="org.apache.hadoop.hbase.Version.revision">
 <!--   -->
 </a><code>public&nbsp;static&nbsp;final&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a></code></td>
 <td><code><a href="org/apache/hadoop/hbase/Version.html#revision">revision</a></code></td>
-<td class="colLast"><code>"db04a9f9d910caf3976f8a86cdd8bacbafcd78e4"</code></td>
+<td class="colLast"><code>"26babcf013de696b899d76a3c39434b794440d8d"</code></td>
 </tr>
 <tr class="altColor">
 <td class="colFirst"><a name="org.apache.hadoop.hbase.Version.srcChecksum">
 <!--   -->
 </a><code>public&nbsp;static&nbsp;final&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a></code></td>
 <td><code><a href="org/apache/hadoop/hbase/Version.html#srcChecksum">srcChecksum</a></code></td>
-<td class="colLast"><code>"8e687f8e84d8f8e7032c526137add45a"</code></td>
+<td class="colLast"><code>"ae490ceba5391b59f223517b4f11795d"</code></td>
 </tr>
 <tr class="rowColor">
 <td class="colFirst"><a name="org.apache.hadoop.hbase.Version.url">

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/index-all.html
----------------------------------------------------------------------
diff --git a/devapidocs/index-all.html b/devapidocs/index-all.html
index ba113d3..9c2bf73 100644
--- a/devapidocs/index-all.html
+++ b/devapidocs/index-all.html
@@ -1923,7 +1923,7 @@
 <dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/regionserver/RegionServicesForStores.html#addMemStoreSize-long-long-long-">addMemStoreSize(long, long, long)</a></span> - Method in class org.apache.hadoop.hbase.regionserver.<a href="org/apache/hadoop/hbase/regionserver/RegionServicesForStores.html" title="class in org.apache.hadoop.hbase.regionserver">RegionServicesForStores</a></dt>
 <dd>&nbsp;</dd>
-<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/io/hfile/HFileBlock.html#addMetaData-java.nio.ByteBuffer-">addMetaData(ByteBuffer)</a></span> - Method in class org.apache.hadoop.hbase.io.hfile.<a href="org/apache/hadoop/hbase/io/hfile/HFileBlock.html" title="class in org.apache.hadoop.hbase.io.hfile">HFileBlock</a></dt>
+<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/io/hfile/HFileBlock.html#addMetaData-java.nio.ByteBuffer-boolean-">addMetaData(ByteBuffer, boolean)</a></span> - Method in class org.apache.hadoop.hbase.io.hfile.<a href="org/apache/hadoop/hbase/io/hfile/HFileBlock.html" title="class in org.apache.hadoop.hbase.io.hfile">HFileBlock</a></dt>
 <dd>
 <div class="block">Adds metadata at current position (position is moved forward).</div>
 </dd>
@@ -14788,7 +14788,7 @@
 <dd>
 <div class="block">Specialized comparator for the ByteBufferKeyValue type exclusivesly.</div>
 </dd>
-<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html#compareCacheBlock-org.apache.hadoop.hbase.io.hfile.Cacheable-org.apache.hadoop.hbase.io.hfile.Cacheable-">compareCacheBlock(Cacheable, Cacheable)</a></span> - Static method in class org.apache.hadoop.hbase.io.hfile.<a href="org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheUtil</a></dt>
+<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html#compareCacheBlock-org.apache.hadoop.hbase.io.hfile.Cacheable-org.apache.hadoop.hbase.io.hfile.Cacheable-boolean-">compareCacheBlock(Cacheable, Cacheable, boolean)</a></span> - Static method in class org.apache.hadoop.hbase.io.hfile.<a href="org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheUtil</a></dt>
 <dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/filter/FilterListBase.html#compareCell-org.apache.hadoop.hbase.Cell-org.apache.hadoop.hbase.Cell-">compareCell(Cell, Cell)</a></span> - Method in class org.apache.hadoop.hbase.filter.<a href="org/apache/hadoop/hbase/filter/FilterListBase.html" title="class in org.apache.hadoop.hbase.filter">FilterListBase</a></dt>
 <dd>&nbsp;</dd>
@@ -65565,8 +65565,6 @@
 <dd>
 <div class="block">Fields keep their default values.</div>
 </dd>
-<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#LimitFields-int-org.apache.hadoop.hbase.regionserver.ScannerContext.LimitScope-long-long-org.apache.hadoop.hbase.regionserver.ScannerContext.LimitScope-long-">LimitFields(int, ScannerContext.LimitScope, long, long, ScannerContext.LimitScope, long)</a></span> - Constructor for class org.apache.hadoop.hbase.regionserver.<a href="org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html" title="class in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitFields</a></dt>
-<dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/quotas/QuotaSettingsFactory.html#limitNamespaceSpace-java.lang.String-long-org.apache.hadoop.hbase.quotas.SpaceViolationPolicy-">limitNamespaceSpace(String, long, SpaceViolationPolicy)</a></span> - Static method in class org.apache.hadoop.hbase.quotas.<a href="org/apache/hadoop/hbase/quotas/QuotaSettingsFactory.html" title="class in org.apache.hadoop.hbase.quotas">QuotaSettingsFactory</a></dt>
 <dd>
 <div class="block">Creates a <a href="org/apache/hadoop/hbase/quotas/QuotaSettings.html" title="class in org.apache.hadoop.hbase.quotas"><code>QuotaSettings</code></a> object to limit the FileSystem space usage for the given
@@ -67250,6 +67248,8 @@
 <dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/io/HalfStoreFileReader.html#LOG">LOG</a></span> - Static variable in class org.apache.hadoop.hbase.io.<a href="org/apache/hadoop/hbase/io/HalfStoreFileReader.html" title="class in org.apache.hadoop.hbase.io">HalfStoreFileReader</a></dt>
 <dd>&nbsp;</dd>
+<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html#LOG">LOG</a></span> - Static variable in class org.apache.hadoop.hbase.io.hfile.<a href="org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheUtil</a></dt>
+<dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#LOG">LOG</a></span> - Static variable in class org.apache.hadoop.hbase.io.hfile.bucket.<a href="org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketAllocator</a></dt>
 <dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#LOG">LOG</a></span> - Static variable in class org.apache.hadoop.hbase.io.hfile.bucket.<a href="org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketCache</a></dt>
@@ -84532,10 +84532,6 @@ service.</div>
 <dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/backup/mapreduce/MapReduceBackupCopyJob.html#progressDone">progressDone</a></span> - Variable in class org.apache.hadoop.hbase.backup.mapreduce.<a href="org/apache/hadoop/hbase/backup/mapreduce/MapReduceBackupCopyJob.html" title="class in org.apache.hadoop.hbase.backup.mapreduce">MapReduceBackupCopyJob</a></dt>
 <dd>&nbsp;</dd>
-<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/regionserver/ScannerContext.ProgressFields.html#ProgressFields--">ProgressFields()</a></span> - Constructor for class org.apache.hadoop.hbase.regionserver.<a href="org/apache/hadoop/hbase/regionserver/ScannerContext.ProgressFields.html" title="class in org.apache.hadoop.hbase.regionserver">ScannerContext.ProgressFields</a></dt>
-<dd>
-<div class="block">Fields keep their default values.</div>
-</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/regionserver/ScannerContext.ProgressFields.html#ProgressFields-int-long-long-">ProgressFields(int, long, long)</a></span> - Constructor for class org.apache.hadoop.hbase.regionserver.<a href="org/apache/hadoop/hbase/regionserver/ScannerContext.ProgressFields.html" title="class in org.apache.hadoop.hbase.regionserver">ScannerContext.ProgressFields</a></dt>
 <dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/util/HBaseFsck.PrintingErrorReporter.html#progressThreshold">progressThreshold</a></span> - Static variable in class org.apache.hadoop.hbase.util.<a href="org/apache/hadoop/hbase/util/HBaseFsck.PrintingErrorReporter.html" title="class in org.apache.hadoop.hbase.util">HBaseFsck.PrintingErrorReporter</a></dt>
@@ -93472,6 +93468,10 @@ service.</div>
 <dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/metrics2/lib/DynamicMetricsRegistry.html#returnExistingWithCast-org.apache.hadoop.metrics2.lib.MutableMetric-java.lang.Class-java.lang.String-">returnExistingWithCast(MutableMetric, Class&lt;T&gt;, String)</a></span> - Method in class org.apache.hadoop.metrics2.lib.<a href="org/apache/hadoop/metrics2/lib/DynamicMetricsRegistry.html" title="class in org.apache.hadoop.metrics2.lib">DynamicMetricsRegistry</a></dt>
 <dd>&nbsp;</dd>
+<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/regionserver/ScannerContext.html#returnImmediately">returnImmediately</a></span> - Variable in class org.apache.hadoop.hbase.regionserver.<a href="org/apache/hadoop/hbase/regionserver/ScannerContext.html" title="class in org.apache.hadoop.hbase.regionserver">ScannerContext</a></dt>
+<dd>&nbsp;</dd>
+<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/regionserver/ScannerContext.html#returnImmediately--">returnImmediately()</a></span> - Method in class org.apache.hadoop.hbase.regionserver.<a href="org/apache/hadoop/hbase/regionserver/ScannerContext.html" title="class in org.apache.hadoop.hbase.regionserver">ScannerContext</a></dt>
+<dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/rest/RowResource.html#returnResult">returnResult</a></span> - Variable in class org.apache.hadoop.hbase.rest.<a href="org/apache/hadoop/hbase/rest/RowResource.html" title="class in org.apache.hadoop.hbase.rest">RowResource</a></dt>
 <dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/io/compress/ReusableStreamGzipCodec.ReusableGzipOutputStream.html#ReusableGzipOutputStream-java.io.OutputStream-">ReusableGzipOutputStream(OutputStream)</a></span> - Constructor for class org.apache.hadoop.hbase.io.compress.<a href="org/apache/hadoop/hbase/io/compress/ReusableStreamGzipCodec.ReusableGzipOutputStream.html" title="class in org.apache.hadoop.hbase.io.compress">ReusableStreamGzipCodec.ReusableGzipOutputStream</a></dt>
@@ -97434,7 +97434,7 @@ service.</div>
 <dd>
 <div class="block">Converts a ForeignException to an array of bytes.</div>
 </dd>
-<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/io/hfile/Cacheable.html#serialize-java.nio.ByteBuffer-">serialize(ByteBuffer)</a></span> - Method in interface org.apache.hadoop.hbase.io.hfile.<a href="org/apache/hadoop/hbase/io/hfile/Cacheable.html" title="interface in org.apache.hadoop.hbase.io.hfile">Cacheable</a></dt>
+<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/io/hfile/Cacheable.html#serialize-java.nio.ByteBuffer-boolean-">serialize(ByteBuffer, boolean)</a></span> - Method in interface org.apache.hadoop.hbase.io.hfile.<a href="org/apache/hadoop/hbase/io/hfile/Cacheable.html" title="interface in org.apache.hadoop.hbase.io.hfile">Cacheable</a></dt>
 <dd>
 <div class="block">Serializes its data into destination.</div>
 </dd>
@@ -97442,7 +97442,7 @@ service.</div>
 <dd>
 <div class="block">Write the trailer to a data stream.</div>
 </dd>
-<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/io/hfile/HFileBlock.html#serialize-java.nio.ByteBuffer-">serialize(ByteBuffer)</a></span> - Method in class org.apache.hadoop.hbase.io.hfile.<a href="org/apache/hadoop/hbase/io/hfile/HFileBlock.html" title="class in org.apache.hadoop.hbase.io.hfile">HFileBlock</a></dt>
+<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/io/hfile/HFileBlock.html#serialize-java.nio.ByteBuffer-boolean-">serialize(ByteBuffer, boolean)</a></span> - Method in class org.apache.hadoop.hbase.io.hfile.<a href="org/apache/hadoop/hbase/io/hfile/HFileBlock.html" title="class in org.apache.hadoop.hbase.io.hfile">HFileBlock</a></dt>
 <dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/mapreduce/CellSerialization.CellSerializer.html#serialize-org.apache.hadoop.hbase.Cell-">serialize(Cell)</a></span> - Method in class org.apache.hadoop.hbase.mapreduce.<a href="org/apache/hadoop/hbase/mapreduce/CellSerialization.CellSerializer.html" title="class in org.apache.hadoop.hbase.mapreduce">CellSerialization.CellSerializer</a></dt>
 <dd>&nbsp;</dd>
@@ -116914,6 +116914,11 @@ service.</div>
 </dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/client/coprocessor/AggregationHelper.html#validateArgAndGetPB-org.apache.hadoop.hbase.client.Scan-org.apache.hadoop.hbase.coprocessor.ColumnInterpreter-boolean-">validateArgAndGetPB(Scan, ColumnInterpreter&lt;R, S, P, Q, T&gt;, boolean)</a></span> - Static method in class org.apache.hadoop.hbase.client.coprocessor.<a href="org/apache/hadoop/hbase/client/coprocessor/AggregationHelper.html" title="class in org.apache.hadoop.hbase.client.coprocessor">AggregationHelper</a></dt>
 <dd>&nbsp;</dd>
+<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html#validateBlockAddition-org.apache.hadoop.hbase.io.hfile.Cacheable-org.apache.hadoop.hbase.io.hfile.Cacheable-org.apache.hadoop.hbase.io.hfile.BlockCacheKey-">validateBlockAddition(Cacheable, Cacheable, BlockCacheKey)</a></span> - Static method in class org.apache.hadoop.hbase.io.hfile.<a href="org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheUtil</a></dt>
+<dd>
+<div class="block">Validate that the existing and newBlock are the same without including the nextBlockMetadata,
+ if not, throw an exception.</div>
+</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/io/hfile/HFileReaderImpl.html#validateBlockType-org.apache.hadoop.hbase.io.hfile.HFileBlock-org.apache.hadoop.hbase.io.hfile.BlockType-">validateBlockType(HFileBlock, BlockType)</a></span> - Method in class org.apache.hadoop.hbase.io.hfile.<a href="org/apache/hadoop/hbase/io/hfile/HFileReaderImpl.html" title="class in org.apache.hadoop.hbase.io.hfile">HFileReaderImpl</a></dt>
 <dd>
 <div class="block">Compares the actual type of a block retrieved from cache or disk with its

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/backup/package-tree.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/backup/package-tree.html b/devapidocs/org/apache/hadoop/hbase/backup/package-tree.html
index 249def3..35b548a 100644
--- a/devapidocs/org/apache/hadoop/hbase/backup/package-tree.html
+++ b/devapidocs/org/apache/hadoop/hbase/backup/package-tree.html
@@ -167,10 +167,10 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true" title="class or interface in java.io">Serializable</a>)
 <ul>
+<li type="circle">org.apache.hadoop.hbase.backup.<a href="../../../../../org/apache/hadoop/hbase/backup/BackupType.html" title="enum in org.apache.hadoop.hbase.backup"><span class="typeNameLink">BackupType</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.backup.<a href="../../../../../org/apache/hadoop/hbase/backup/BackupInfo.BackupState.html" title="enum in org.apache.hadoop.hbase.backup"><span class="typeNameLink">BackupInfo.BackupState</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.backup.<a href="../../../../../org/apache/hadoop/hbase/backup/BackupRestoreConstants.BackupCommand.html" title="enum in org.apache.hadoop.hbase.backup"><span class="typeNameLink">BackupRestoreConstants.BackupCommand</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.backup.<a href="../../../../../org/apache/hadoop/hbase/backup/BackupInfo.BackupPhase.html" title="enum in org.apache.hadoop.hbase.backup"><span class="typeNameLink">BackupInfo.BackupPhase</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.backup.<a href="../../../../../org/apache/hadoop/hbase/backup/BackupType.html" title="enum in org.apache.hadoop.hbase.backup"><span class="typeNameLink">BackupType</span></a></li>
 </ul>
 </li>
 </ul>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/client/RpcRetryingCallerWithReadReplicas.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/client/RpcRetryingCallerWithReadReplicas.html b/devapidocs/org/apache/hadoop/hbase/client/RpcRetryingCallerWithReadReplicas.html
index 9eec050..8c1381b 100644
--- a/devapidocs/org/apache/hadoop/hbase/client/RpcRetryingCallerWithReadReplicas.html
+++ b/devapidocs/org/apache/hadoop/hbase/client/RpcRetryingCallerWithReadReplicas.html
@@ -498,7 +498,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>addCallsForReplica</h4>
-<pre>private&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/client/RpcRetryingCallerWithReadReplicas.html#line.309">addCallsForReplica</a>(<a href="../../../../../org/apache/hadoop/hbase/client/ResultBoundedCompletionService.html" title="class in org.apache.hadoop.hbase.client">ResultBoundedCompletionService</a>&lt;<a href="../../../../../org/apache/hadoop/hbase/client/Result.html" title="class in org.apache.hadoop.hbase.client">Result</a>&gt;&nbsp;cs,
+<pre>private&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/client/RpcRetryingCallerWithReadReplicas.html#line.310">addCallsForReplica</a>(<a href="../../../../../org/apache/hadoop/hbase/client/ResultBoundedCompletionService.html" title="class in org.apache.hadoop.hbase.client">ResultBoundedCompletionService</a>&lt;<a href="../../../../../org/apache/hadoop/hbase/client/Result.html" title="class in org.apache.hadoop.hbase.client">Result</a>&gt;&nbsp;cs,
                                 <a href="../../../../../org/apache/hadoop/hbase/RegionLocations.html" title="class in org.apache.hadoop.hbase">RegionLocations</a>&nbsp;rl,
                                 int&nbsp;min,
                                 int&nbsp;max)</pre>
@@ -518,7 +518,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>getRegionLocations</h4>
-<pre>static&nbsp;<a href="../../../../../org/apache/hadoop/hbase/RegionLocations.html" title="class in org.apache.hadoop.hbase">RegionLocations</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/client/RpcRetryingCallerWithReadReplicas.html#line.318">getRegionLocations</a>(boolean&nbsp;useCache,
+<pre>static&nbsp;<a href="../../../../../org/apache/hadoop/hbase/RegionLocations.html" title="class in org.apache.hadoop.hbase">RegionLocations</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/client/RpcRetryingCallerWithReadReplicas.html#line.319">getRegionLocations</a>(boolean&nbsp;useCache,
                                           int&nbsp;replicaId,
                                           <a href="../../../../../org/apache/hadoop/hbase/client/ClusterConnection.html" title="interface in org.apache.hadoop.hbase.client">ClusterConnection</a>&nbsp;cConnection,
                                           <a href="../../../../../org/apache/hadoop/hbase/TableName.html" title="class in org.apache.hadoop.hbase">TableName</a>&nbsp;tableName,

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/client/package-tree.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/client/package-tree.html b/devapidocs/org/apache/hadoop/hbase/client/package-tree.html
index 88bde01..8a35374 100644
--- a/devapidocs/org/apache/hadoop/hbase/client/package-tree.html
+++ b/devapidocs/org/apache/hadoop/hbase/client/package-tree.html
@@ -550,24 +550,24 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true" title="class or interface in java.io">Serializable</a>)
 <ul>
-<li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/MobCompactPartitionPolicy.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">MobCompactPartitionPolicy</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/IsolationLevel.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">IsolationLevel</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/AsyncScanSingleRegionRpcRetryingCaller.ScanResumerState.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">AsyncScanSingleRegionRpcRetryingCaller.ScanResumerState</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/AsyncProcessTask.SubmittedRows.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">AsyncProcessTask.SubmittedRows</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/SnapshotType.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">SnapshotType</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/RequestController.ReturnCode.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">RequestController.ReturnCode</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/CompactionState.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">CompactionState</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/TableState.State.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">TableState.State</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/Scan.ReadType.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">Scan.ReadType</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/Consistency.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">Consistency</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/IsolationLevel.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">IsolationLevel</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/Durability.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">Durability</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/AsyncScanSingleRegionRpcRetryingCaller.ScanControllerState.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">AsyncScanSingleRegionRpcRetryingCaller.ScanControllerState</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/CompactionState.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">CompactionState</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/MasterSwitchType.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">MasterSwitchType</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/AsyncRequestFutureImpl.Retry.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">AsyncRequestFutureImpl.Retry</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/ScannerCallable.MoreResults.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">ScannerCallable.MoreResults</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/Consistency.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">Consistency</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/AsyncScanSingleRegionRpcRetryingCaller.ScanControllerState.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">AsyncScanSingleRegionRpcRetryingCaller.ScanControllerState</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/AbstractResponse.ResponseType.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">AbstractResponse.ResponseType</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/AsyncRequestFutureImpl.Retry.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">AsyncRequestFutureImpl.Retry</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/RegionLocateType.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">RegionLocateType</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/SnapshotType.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">SnapshotType</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/AsyncProcessTask.SubmittedRows.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">AsyncProcessTask.SubmittedRows</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/MasterSwitchType.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">MasterSwitchType</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/AsyncScanSingleRegionRpcRetryingCaller.ScanResumerState.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">AsyncScanSingleRegionRpcRetryingCaller.ScanResumerState</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/CompactType.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">CompactType</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/TableState.State.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">TableState.State</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/MobCompactPartitionPolicy.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">MobCompactPartitionPolicy</span></a></li>
 </ul>
 </li>
 </ul>


[29/50] hbase-site git commit: Published site at 26babcf013de696b899d76a3c39434b794440d8d.

Posted by gi...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.EvictionThread.html
----------------------------------------------------------------------
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.EvictionThread.html b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.EvictionThread.html
index f5747c6..b94ef5e 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.EvictionThread.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.EvictionThread.html
@@ -388,811 +388,816 @@
 <span class="sourceLineNo">380</span><a name="line.380"></a>
 <span class="sourceLineNo">381</span>    LruCachedBlock cb = map.get(cacheKey);<a name="line.381"></a>
 <span class="sourceLineNo">382</span>    if (cb != null) {<a name="line.382"></a>
-<span class="sourceLineNo">383</span>      // compare the contents, if they are not equal, we are in big trouble<a name="line.383"></a>
-<span class="sourceLineNo">384</span>      if (BlockCacheUtil.compareCacheBlock(buf, cb.getBuffer()) != 0) {<a name="line.384"></a>
-<span class="sourceLineNo">385</span>        throw new RuntimeException("Cached block contents differ, which should not have happened."<a name="line.385"></a>
-<span class="sourceLineNo">386</span>          + "cacheKey:" + cacheKey);<a name="line.386"></a>
-<span class="sourceLineNo">387</span>      }<a name="line.387"></a>
-<span class="sourceLineNo">388</span>      String msg = "Cached an already cached block: " + cacheKey + " cb:" + cb.getCacheKey();<a name="line.388"></a>
-<span class="sourceLineNo">389</span>      msg += ". This is harmless and can happen in rare cases (see HBASE-8547)";<a name="line.389"></a>
-<span class="sourceLineNo">390</span>      LOG.warn(msg);<a name="line.390"></a>
-<span class="sourceLineNo">391</span>      return;<a name="line.391"></a>
-<span class="sourceLineNo">392</span>    }<a name="line.392"></a>
-<span class="sourceLineNo">393</span>    long currentSize = size.get();<a name="line.393"></a>
-<span class="sourceLineNo">394</span>    long currentAcceptableSize = acceptableSize();<a name="line.394"></a>
-<span class="sourceLineNo">395</span>    long hardLimitSize = (long) (hardCapacityLimitFactor * currentAcceptableSize);<a name="line.395"></a>
-<span class="sourceLineNo">396</span>    if (currentSize &gt;= hardLimitSize) {<a name="line.396"></a>
-<span class="sourceLineNo">397</span>      stats.failInsert();<a name="line.397"></a>
-<span class="sourceLineNo">398</span>      if (LOG.isTraceEnabled()) {<a name="line.398"></a>
-<span class="sourceLineNo">399</span>        LOG.trace("LruBlockCache current size " + StringUtils.byteDesc(currentSize)<a name="line.399"></a>
-<span class="sourceLineNo">400</span>          + " has exceeded acceptable size " + StringUtils.byteDesc(currentAcceptableSize) + "."<a name="line.400"></a>
-<span class="sourceLineNo">401</span>          + " The hard limit size is " + StringUtils.byteDesc(hardLimitSize)<a name="line.401"></a>
-<span class="sourceLineNo">402</span>          + ", failed to put cacheKey:" + cacheKey + " into LruBlockCache.");<a name="line.402"></a>
-<span class="sourceLineNo">403</span>      }<a name="line.403"></a>
-<span class="sourceLineNo">404</span>      if (!evictionInProgress) {<a name="line.404"></a>
-<span class="sourceLineNo">405</span>        runEviction();<a name="line.405"></a>
-<span class="sourceLineNo">406</span>      }<a name="line.406"></a>
-<span class="sourceLineNo">407</span>      return;<a name="line.407"></a>
-<span class="sourceLineNo">408</span>    }<a name="line.408"></a>
-<span class="sourceLineNo">409</span>    cb = new LruCachedBlock(cacheKey, buf, count.incrementAndGet(), inMemory);<a name="line.409"></a>
-<span class="sourceLineNo">410</span>    long newSize = updateSizeMetrics(cb, false);<a name="line.410"></a>
-<span class="sourceLineNo">411</span>    map.put(cacheKey, cb);<a name="line.411"></a>
-<span class="sourceLineNo">412</span>    long val = elements.incrementAndGet();<a name="line.412"></a>
-<span class="sourceLineNo">413</span>    if (buf.getBlockType().isData()) {<a name="line.413"></a>
-<span class="sourceLineNo">414</span>       dataBlockElements.increment();<a name="line.414"></a>
-<span class="sourceLineNo">415</span>    }<a name="line.415"></a>
-<span class="sourceLineNo">416</span>    if (LOG.isTraceEnabled()) {<a name="line.416"></a>
-<span class="sourceLineNo">417</span>      long size = map.size();<a name="line.417"></a>
-<span class="sourceLineNo">418</span>      assertCounterSanity(size, val);<a name="line.418"></a>
-<span class="sourceLineNo">419</span>    }<a name="line.419"></a>
-<span class="sourceLineNo">420</span>    if (newSize &gt; currentAcceptableSize &amp;&amp; !evictionInProgress) {<a name="line.420"></a>
-<span class="sourceLineNo">421</span>      runEviction();<a name="line.421"></a>
-<span class="sourceLineNo">422</span>    }<a name="line.422"></a>
-<span class="sourceLineNo">423</span>  }<a name="line.423"></a>
-<span class="sourceLineNo">424</span><a name="line.424"></a>
-<span class="sourceLineNo">425</span>  /**<a name="line.425"></a>
-<span class="sourceLineNo">426</span>   * Sanity-checking for parity between actual block cache content and metrics.<a name="line.426"></a>
-<span class="sourceLineNo">427</span>   * Intended only for use with TRACE level logging and -ea JVM.<a name="line.427"></a>
-<span class="sourceLineNo">428</span>   */<a name="line.428"></a>
-<span class="sourceLineNo">429</span>  private static void assertCounterSanity(long mapSize, long counterVal) {<a name="line.429"></a>
-<span class="sourceLineNo">430</span>    if (counterVal &lt; 0) {<a name="line.430"></a>
-<span class="sourceLineNo">431</span>      LOG.trace("counterVal overflow. Assertions unreliable. counterVal=" + counterVal +<a name="line.431"></a>
-<span class="sourceLineNo">432</span>        ", mapSize=" + mapSize);<a name="line.432"></a>
-<span class="sourceLineNo">433</span>      return;<a name="line.433"></a>
-<span class="sourceLineNo">434</span>    }<a name="line.434"></a>
-<span class="sourceLineNo">435</span>    if (mapSize &lt; Integer.MAX_VALUE) {<a name="line.435"></a>
-<span class="sourceLineNo">436</span>      double pct_diff = Math.abs((((double) counterVal) / ((double) mapSize)) - 1.);<a name="line.436"></a>
-<span class="sourceLineNo">437</span>      if (pct_diff &gt; 0.05) {<a name="line.437"></a>
-<span class="sourceLineNo">438</span>        LOG.trace("delta between reported and actual size &gt; 5%. counterVal=" + counterVal +<a name="line.438"></a>
-<span class="sourceLineNo">439</span>          ", mapSize=" + mapSize);<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><a name="line.443"></a>
-<span class="sourceLineNo">444</span>  /**<a name="line.444"></a>
-<span class="sourceLineNo">445</span>   * Cache the block with the specified name and buffer.<a name="line.445"></a>
-<span class="sourceLineNo">446</span>   * &lt;p&gt;<a name="line.446"></a>
-<span class="sourceLineNo">447</span>   *<a name="line.447"></a>
-<span class="sourceLineNo">448</span>   * @param cacheKey block's cache key<a name="line.448"></a>
-<span class="sourceLineNo">449</span>   * @param buf      block buffer<a name="line.449"></a>
-<span class="sourceLineNo">450</span>   */<a name="line.450"></a>
-<span class="sourceLineNo">451</span>  @Override<a name="line.451"></a>
-<span class="sourceLineNo">452</span>  public void cacheBlock(BlockCacheKey cacheKey, Cacheable buf) {<a name="line.452"></a>
-<span class="sourceLineNo">453</span>    cacheBlock(cacheKey, buf, false);<a name="line.453"></a>
-<span class="sourceLineNo">454</span>  }<a name="line.454"></a>
-<span class="sourceLineNo">455</span><a name="line.455"></a>
-<span class="sourceLineNo">456</span>  /**<a name="line.456"></a>
-<span class="sourceLineNo">457</span>   * Helper function that updates the local size counter and also updates any<a name="line.457"></a>
-<span class="sourceLineNo">458</span>   * per-cf or per-blocktype metrics it can discern from given<a name="line.458"></a>
-<span class="sourceLineNo">459</span>   * {@link LruCachedBlock}<a name="line.459"></a>
-<span class="sourceLineNo">460</span>   */<a name="line.460"></a>
-<span class="sourceLineNo">461</span>  private long updateSizeMetrics(LruCachedBlock cb, boolean evict) {<a name="line.461"></a>
-<span class="sourceLineNo">462</span>    long heapsize = cb.heapSize();<a name="line.462"></a>
-<span class="sourceLineNo">463</span>    BlockType bt = cb.getBuffer().getBlockType();<a name="line.463"></a>
-<span class="sourceLineNo">464</span>    if (evict) {<a name="line.464"></a>
-<span class="sourceLineNo">465</span>      heapsize *= -1;<a name="line.465"></a>
-<span class="sourceLineNo">466</span>    }<a name="line.466"></a>
-<span class="sourceLineNo">467</span>    if (bt != null &amp;&amp; bt.isData()) {<a name="line.467"></a>
-<span class="sourceLineNo">468</span>       dataBlockSize.add(heapsize);<a name="line.468"></a>
-<span class="sourceLineNo">469</span>    }<a name="line.469"></a>
-<span class="sourceLineNo">470</span>    return size.addAndGet(heapsize);<a name="line.470"></a>
-<span class="sourceLineNo">471</span>  }<a name="line.471"></a>
-<span class="sourceLineNo">472</span><a name="line.472"></a>
-<span class="sourceLineNo">473</span>  /**<a name="line.473"></a>
-<span class="sourceLineNo">474</span>   * Get the buffer of the block with the specified name.<a name="line.474"></a>
-<span class="sourceLineNo">475</span>   *<a name="line.475"></a>
-<span class="sourceLineNo">476</span>   * @param cacheKey           block's cache key<a name="line.476"></a>
-<span class="sourceLineNo">477</span>   * @param caching            true if the caller caches blocks on cache misses<a name="line.477"></a>
-<span class="sourceLineNo">478</span>   * @param repeat             Whether this is a repeat lookup for the same block<a name="line.478"></a>
-<span class="sourceLineNo">479</span>   *                           (used to avoid double counting cache misses when doing double-check<a name="line.479"></a>
-<span class="sourceLineNo">480</span>   *                           locking)<a name="line.480"></a>
-<span class="sourceLineNo">481</span>   * @param updateCacheMetrics Whether to update cache metrics or not<a name="line.481"></a>
-<span class="sourceLineNo">482</span>   *<a name="line.482"></a>
-<span class="sourceLineNo">483</span>   * @return buffer of specified cache key, or null if not in cache<a name="line.483"></a>
-<span class="sourceLineNo">484</span>   */<a name="line.484"></a>
-<span class="sourceLineNo">485</span>  @Override<a name="line.485"></a>
-<span class="sourceLineNo">486</span>  public Cacheable getBlock(BlockCacheKey cacheKey, boolean caching, boolean repeat,<a name="line.486"></a>
-<span class="sourceLineNo">487</span>      boolean updateCacheMetrics) {<a name="line.487"></a>
-<span class="sourceLineNo">488</span>    LruCachedBlock cb = map.get(cacheKey);<a name="line.488"></a>
-<span class="sourceLineNo">489</span>    if (cb == null) {<a name="line.489"></a>
-<span class="sourceLineNo">490</span>      if (!repeat &amp;&amp; updateCacheMetrics) {<a name="line.490"></a>
-<span class="sourceLineNo">491</span>        stats.miss(caching, cacheKey.isPrimary(), cacheKey.getBlockType());<a name="line.491"></a>
-<span class="sourceLineNo">492</span>      }<a name="line.492"></a>
-<span class="sourceLineNo">493</span>      // If there is another block cache then try and read there.<a name="line.493"></a>
-<span class="sourceLineNo">494</span>      // However if this is a retry ( second time in double checked locking )<a name="line.494"></a>
-<span class="sourceLineNo">495</span>      // And it's already a miss then the l2 will also be a miss.<a name="line.495"></a>
-<span class="sourceLineNo">496</span>      if (victimHandler != null &amp;&amp; !repeat) {<a name="line.496"></a>
-<span class="sourceLineNo">497</span>        Cacheable result = victimHandler.getBlock(cacheKey, caching, repeat, updateCacheMetrics);<a name="line.497"></a>
-<span class="sourceLineNo">498</span><a name="line.498"></a>
-<span class="sourceLineNo">499</span>        // Promote this to L1.<a name="line.499"></a>
-<span class="sourceLineNo">500</span>        if (result != null &amp;&amp; caching) {<a name="line.500"></a>
-<span class="sourceLineNo">501</span>          if (result instanceof HFileBlock &amp;&amp; ((HFileBlock) result).usesSharedMemory()) {<a name="line.501"></a>
-<span class="sourceLineNo">502</span>            result = ((HFileBlock) result).deepClone();<a name="line.502"></a>
-<span class="sourceLineNo">503</span>          }<a name="line.503"></a>
-<span class="sourceLineNo">504</span>          cacheBlock(cacheKey, result, /* inMemory = */ false);<a name="line.504"></a>
-<span class="sourceLineNo">505</span>        }<a name="line.505"></a>
-<span class="sourceLineNo">506</span>        return result;<a name="line.506"></a>
-<span class="sourceLineNo">507</span>      }<a name="line.507"></a>
-<span class="sourceLineNo">508</span>      return null;<a name="line.508"></a>
-<span class="sourceLineNo">509</span>    }<a name="line.509"></a>
-<span class="sourceLineNo">510</span>    if (updateCacheMetrics) stats.hit(caching, cacheKey.isPrimary(), cacheKey.getBlockType());<a name="line.510"></a>
-<span class="sourceLineNo">511</span>    cb.access(count.incrementAndGet());<a name="line.511"></a>
-<span class="sourceLineNo">512</span>    return cb.getBuffer();<a name="line.512"></a>
-<span class="sourceLineNo">513</span>  }<a name="line.513"></a>
-<span class="sourceLineNo">514</span><a name="line.514"></a>
-<span class="sourceLineNo">515</span>  /**<a name="line.515"></a>
-<span class="sourceLineNo">516</span>   * Whether the cache contains block with specified cacheKey<a name="line.516"></a>
-<span class="sourceLineNo">517</span>   *<a name="line.517"></a>
-<span class="sourceLineNo">518</span>   * @return true if contains the block<a name="line.518"></a>
-<span class="sourceLineNo">519</span>   */<a name="line.519"></a>
-<span class="sourceLineNo">520</span>  public boolean containsBlock(BlockCacheKey cacheKey) {<a name="line.520"></a>
-<span class="sourceLineNo">521</span>    return map.containsKey(cacheKey);<a name="line.521"></a>
-<span class="sourceLineNo">522</span>  }<a name="line.522"></a>
-<span class="sourceLineNo">523</span><a name="line.523"></a>
-<span class="sourceLineNo">524</span>  @Override<a name="line.524"></a>
-<span class="sourceLineNo">525</span>  public boolean evictBlock(BlockCacheKey cacheKey) {<a name="line.525"></a>
-<span class="sourceLineNo">526</span>    LruCachedBlock cb = map.get(cacheKey);<a name="line.526"></a>
-<span class="sourceLineNo">527</span>    return cb != null &amp;&amp; evictBlock(cb, false) &gt; 0;<a name="line.527"></a>
-<span class="sourceLineNo">528</span>  }<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>   * Evicts all blocks for a specific HFile. This is an<a name="line.531"></a>
-<span class="sourceLineNo">532</span>   * expensive operation implemented as a linear-time search through all blocks<a name="line.532"></a>
-<span class="sourceLineNo">533</span>   * in the cache. Ideally this should be a search in a log-access-time map.<a name="line.533"></a>
-<span class="sourceLineNo">534</span>   *<a name="line.534"></a>
-<span class="sourceLineNo">535</span>   * &lt;p&gt;<a name="line.535"></a>
-<span class="sourceLineNo">536</span>   * This is used for evict-on-close to remove all blocks of a specific HFile.<a name="line.536"></a>
-<span class="sourceLineNo">537</span>   *<a name="line.537"></a>
-<span class="sourceLineNo">538</span>   * @return the number of blocks evicted<a name="line.538"></a>
-<span class="sourceLineNo">539</span>   */<a name="line.539"></a>
-<span class="sourceLineNo">540</span>  @Override<a name="line.540"></a>
-<span class="sourceLineNo">541</span>  public int evictBlocksByHfileName(String hfileName) {<a name="line.541"></a>
-<span class="sourceLineNo">542</span>    int numEvicted = 0;<a name="line.542"></a>
-<span class="sourceLineNo">543</span>    for (BlockCacheKey key : map.keySet()) {<a name="line.543"></a>
-<span class="sourceLineNo">544</span>      if (key.getHfileName().equals(hfileName)) {<a name="line.544"></a>
-<span class="sourceLineNo">545</span>        if (evictBlock(key))<a name="line.545"></a>
-<span class="sourceLineNo">546</span>          ++numEvicted;<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>    if (victimHandler != null) {<a name="line.549"></a>
-<span class="sourceLineNo">550</span>      numEvicted += victimHandler.evictBlocksByHfileName(hfileName);<a name="line.550"></a>
-<span class="sourceLineNo">551</span>    }<a name="line.551"></a>
-<span class="sourceLineNo">552</span>    return numEvicted;<a name="line.552"></a>
-<span class="sourceLineNo">553</span>  }<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>   * Evict the block, and it will be cached by the victim handler if exists &amp;amp;&amp;amp;<a name="line.556"></a>
-<span class="sourceLineNo">557</span>   * block may be read again later<a name="line.557"></a>
-<span class="sourceLineNo">558</span>   *<a name="line.558"></a>
-<span class="sourceLineNo">559</span>   * @param evictedByEvictionProcess true if the given block is evicted by<a name="line.559"></a>
-<span class="sourceLineNo">560</span>   *          EvictionThread<a name="line.560"></a>
-<span class="sourceLineNo">561</span>   * @return the heap size of evicted block<a name="line.561"></a>
-<span class="sourceLineNo">562</span>   */<a name="line.562"></a>
-<span class="sourceLineNo">563</span>  protected long evictBlock(LruCachedBlock block, boolean evictedByEvictionProcess) {<a name="line.563"></a>
-<span class="sourceLineNo">564</span>    boolean found = map.remove(block.getCacheKey()) != null;<a name="line.564"></a>
-<span class="sourceLineNo">565</span>    if (!found) {<a name="line.565"></a>
-<span class="sourceLineNo">566</span>      return 0;<a name="line.566"></a>
-<span class="sourceLineNo">567</span>    }<a name="line.567"></a>
-<span class="sourceLineNo">568</span>    updateSizeMetrics(block, true);<a name="line.568"></a>
-<span class="sourceLineNo">569</span>    long val = elements.decrementAndGet();<a name="line.569"></a>
-<span class="sourceLineNo">570</span>    if (LOG.isTraceEnabled()) {<a name="line.570"></a>
-<span class="sourceLineNo">571</span>      long size = map.size();<a name="line.571"></a>
-<span class="sourceLineNo">572</span>      assertCounterSanity(size, val);<a name="line.572"></a>
-<span class="sourceLineNo">573</span>    }<a name="line.573"></a>
-<span class="sourceLineNo">574</span>    if (block.getBuffer().getBlockType().isData()) {<a name="line.574"></a>
-<span class="sourceLineNo">575</span>       dataBlockElements.decrement();<a name="line.575"></a>
-<span class="sourceLineNo">576</span>    }<a name="line.576"></a>
-<span class="sourceLineNo">577</span>    if (evictedByEvictionProcess) {<a name="line.577"></a>
-<span class="sourceLineNo">578</span>      // When the eviction of the block happened because of invalidation of HFiles, no need to<a name="line.578"></a>
-<span class="sourceLineNo">579</span>      // update the stats counter.<a name="line.579"></a>
-<span class="sourceLineNo">580</span>      stats.evicted(block.getCachedTime(), block.getCacheKey().isPrimary());<a name="line.580"></a>
-<span class="sourceLineNo">581</span>      if (victimHandler != null) {<a name="line.581"></a>
-<span class="sourceLineNo">582</span>        victimHandler.cacheBlock(block.getCacheKey(), block.getBuffer());<a name="line.582"></a>
-<span class="sourceLineNo">583</span>      }<a name="line.583"></a>
-<span class="sourceLineNo">584</span>    }<a name="line.584"></a>
-<span class="sourceLineNo">585</span>    return block.heapSize();<a name="line.585"></a>
-<span class="sourceLineNo">586</span>  }<a name="line.586"></a>
-<span class="sourceLineNo">587</span><a name="line.587"></a>
-<span class="sourceLineNo">588</span>  /**<a name="line.588"></a>
-<span class="sourceLineNo">589</span>   * Multi-threaded call to run the eviction process.<a name="line.589"></a>
-<span class="sourceLineNo">590</span>   */<a name="line.590"></a>
-<span class="sourceLineNo">591</span>  private void runEviction() {<a name="line.591"></a>
-<span class="sourceLineNo">592</span>    if (evictionThread == null) {<a name="line.592"></a>
-<span class="sourceLineNo">593</span>      evict();<a name="line.593"></a>
-<span class="sourceLineNo">594</span>    } else {<a name="line.594"></a>
-<span class="sourceLineNo">595</span>      evictionThread.evict();<a name="line.595"></a>
-<span class="sourceLineNo">596</span>    }<a name="line.596"></a>
-<span class="sourceLineNo">597</span>  }<a name="line.597"></a>
-<span class="sourceLineNo">598</span><a name="line.598"></a>
-<span class="sourceLineNo">599</span>  @VisibleForTesting<a name="line.599"></a>
-<span class="sourceLineNo">600</span>  boolean isEvictionInProgress() {<a name="line.600"></a>
-<span class="sourceLineNo">601</span>    return evictionInProgress;<a name="line.601"></a>
+<span class="sourceLineNo">383</span>      int comparison = BlockCacheUtil.validateBlockAddition(cb.getBuffer(), buf, cacheKey);<a name="line.383"></a>
+<span class="sourceLineNo">384</span>      if (comparison != 0) {<a name="line.384"></a>
+<span class="sourceLineNo">385</span>        if (comparison &lt; 0) {<a name="line.385"></a>
+<span class="sourceLineNo">386</span>          LOG.warn("Cached block contents differ by nextBlockOnDiskSize. Keeping cached block.");<a name="line.386"></a>
+<span class="sourceLineNo">387</span>          return;<a name="line.387"></a>
+<span class="sourceLineNo">388</span>        } else {<a name="line.388"></a>
+<span class="sourceLineNo">389</span>          LOG.warn("Cached block contents differ by nextBlockOnDiskSize. Caching new block.");<a name="line.389"></a>
+<span class="sourceLineNo">390</span>        }<a name="line.390"></a>
+<span class="sourceLineNo">391</span>      } else {<a name="line.391"></a>
+<span class="sourceLineNo">392</span>        String msg = "Cached an already cached block: " + cacheKey + " cb:" + cb.getCacheKey();<a name="line.392"></a>
+<span class="sourceLineNo">393</span>        msg += ". This is harmless and can happen in rare cases (see HBASE-8547)";<a name="line.393"></a>
+<span class="sourceLineNo">394</span>        LOG.warn(msg);<a name="line.394"></a>
+<span class="sourceLineNo">395</span>        return;<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>    long currentSize = size.get();<a name="line.398"></a>
+<span class="sourceLineNo">399</span>    long currentAcceptableSize = acceptableSize();<a name="line.399"></a>
+<span class="sourceLineNo">400</span>    long hardLimitSize = (long) (hardCapacityLimitFactor * currentAcceptableSize);<a name="line.400"></a>
+<span class="sourceLineNo">401</span>    if (currentSize &gt;= hardLimitSize) {<a name="line.401"></a>
+<span class="sourceLineNo">402</span>      stats.failInsert();<a name="line.402"></a>
+<span class="sourceLineNo">403</span>      if (LOG.isTraceEnabled()) {<a name="line.403"></a>
+<span class="sourceLineNo">404</span>        LOG.trace("LruBlockCache current size " + StringUtils.byteDesc(currentSize)<a name="line.404"></a>
+<span class="sourceLineNo">405</span>          + " has exceeded acceptable size " + StringUtils.byteDesc(currentAcceptableSize) + "."<a name="line.405"></a>
+<span class="sourceLineNo">406</span>          + " The hard limit size is " + StringUtils.byteDesc(hardLimitSize)<a name="line.406"></a>
+<span class="sourceLineNo">407</span>          + ", failed to put cacheKey:" + cacheKey + " into LruBlockCache.");<a name="line.407"></a>
+<span class="sourceLineNo">408</span>      }<a name="line.408"></a>
+<span class="sourceLineNo">409</span>      if (!evictionInProgress) {<a name="line.409"></a>
+<span class="sourceLineNo">410</span>        runEviction();<a name="line.410"></a>
+<span class="sourceLineNo">411</span>      }<a name="line.411"></a>
+<span class="sourceLineNo">412</span>      return;<a name="line.412"></a>
+<span class="sourceLineNo">413</span>    }<a name="line.413"></a>
+<span class="sourceLineNo">414</span>    cb = new LruCachedBlock(cacheKey, buf, count.incrementAndGet(), inMemory);<a name="line.414"></a>
+<span class="sourceLineNo">415</span>    long newSize = updateSizeMetrics(cb, false);<a name="line.415"></a>
+<span class="sourceLineNo">416</span>    map.put(cacheKey, cb);<a name="line.416"></a>
+<span class="sourceLineNo">417</span>    long val = elements.incrementAndGet();<a name="line.417"></a>
+<span class="sourceLineNo">418</span>    if (buf.getBlockType().isData()) {<a name="line.418"></a>
+<span class="sourceLineNo">419</span>       dataBlockElements.increment();<a name="line.419"></a>
+<span class="sourceLineNo">420</span>    }<a name="line.420"></a>
+<span class="sourceLineNo">421</span>    if (LOG.isTraceEnabled()) {<a name="line.421"></a>
+<span class="sourceLineNo">422</span>      long size = map.size();<a name="line.422"></a>
+<span class="sourceLineNo">423</span>      assertCounterSanity(size, val);<a name="line.423"></a>
+<span class="sourceLineNo">424</span>    }<a name="line.424"></a>
+<span class="sourceLineNo">425</span>    if (newSize &gt; currentAcceptableSize &amp;&amp; !evictionInProgress) {<a name="line.425"></a>
+<span class="sourceLineNo">426</span>      runEviction();<a name="line.426"></a>
+<span class="sourceLineNo">427</span>    }<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>   * Sanity-checking for parity between actual block cache content and metrics.<a name="line.431"></a>
+<span class="sourceLineNo">432</span>   * Intended only for use with TRACE level logging and -ea JVM.<a name="line.432"></a>
+<span class="sourceLineNo">433</span>   */<a name="line.433"></a>
+<span class="sourceLineNo">434</span>  private static void assertCounterSanity(long mapSize, long counterVal) {<a name="line.434"></a>
+<span class="sourceLineNo">435</span>    if (counterVal &lt; 0) {<a name="line.435"></a>
+<span class="sourceLineNo">436</span>      LOG.trace("counterVal overflow. Assertions unreliable. counterVal=" + counterVal +<a name="line.436"></a>
+<span class="sourceLineNo">437</span>        ", mapSize=" + mapSize);<a name="line.437"></a>
+<span class="sourceLineNo">438</span>      return;<a name="line.438"></a>
+<span class="sourceLineNo">439</span>    }<a name="line.439"></a>
+<span class="sourceLineNo">440</span>    if (mapSize &lt; Integer.MAX_VALUE) {<a name="line.440"></a>
+<span class="sourceLineNo">441</span>      double pct_diff = Math.abs((((double) counterVal) / ((double) mapSize)) - 1.);<a name="line.441"></a>
+<span class="sourceLineNo">442</span>      if (pct_diff &gt; 0.05) {<a name="line.442"></a>
+<span class="sourceLineNo">443</span>        LOG.trace("delta between reported and actual size &gt; 5%. counterVal=" + counterVal +<a name="line.443"></a>
+<span class="sourceLineNo">444</span>          ", mapSize=" + mapSize);<a name="line.444"></a>
+<span class="sourceLineNo">445</span>      }<a name="line.445"></a>
+<span class="sourceLineNo">446</span>    }<a name="line.446"></a>
+<span class="sourceLineNo">447</span>  }<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>   * Cache the block with the specified name and buffer.<a name="line.450"></a>
+<span class="sourceLineNo">451</span>   * &lt;p&gt;<a name="line.451"></a>
+<span class="sourceLineNo">452</span>   *<a name="line.452"></a>
+<span class="sourceLineNo">453</span>   * @param cacheKey block's cache key<a name="line.453"></a>
+<span class="sourceLineNo">454</span>   * @param buf      block buffer<a name="line.454"></a>
+<span class="sourceLineNo">455</span>   */<a name="line.455"></a>
+<span class="sourceLineNo">456</span>  @Override<a name="line.456"></a>
+<span class="sourceLineNo">457</span>  public void cacheBlock(BlockCacheKey cacheKey, Cacheable buf) {<a name="line.457"></a>
+<span class="sourceLineNo">458</span>    cacheBlock(cacheKey, buf, false);<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>  /**<a name="line.461"></a>
+<span class="sourceLineNo">462</span>   * Helper function that updates the local size counter and also updates any<a name="line.462"></a>
+<span class="sourceLineNo">463</span>   * per-cf or per-blocktype metrics it can discern from given<a name="line.463"></a>
+<span class="sourceLineNo">464</span>   * {@link LruCachedBlock}<a name="line.464"></a>
+<span class="sourceLineNo">465</span>   */<a name="line.465"></a>
+<span class="sourceLineNo">466</span>  private long updateSizeMetrics(LruCachedBlock cb, boolean evict) {<a name="line.466"></a>
+<span class="sourceLineNo">467</span>    long heapsize = cb.heapSize();<a name="line.467"></a>
+<span class="sourceLineNo">468</span>    BlockType bt = cb.getBuffer().getBlockType();<a name="line.468"></a>
+<span class="sourceLineNo">469</span>    if (evict) {<a name="line.469"></a>
+<span class="sourceLineNo">470</span>      heapsize *= -1;<a name="line.470"></a>
+<span class="sourceLineNo">471</span>    }<a name="line.471"></a>
+<span class="sourceLineNo">472</span>    if (bt != null &amp;&amp; bt.isData()) {<a name="line.472"></a>
+<span class="sourceLineNo">473</span>       dataBlockSize.add(heapsize);<a name="line.473"></a>
+<span class="sourceLineNo">474</span>    }<a name="line.474"></a>
+<span class="sourceLineNo">475</span>    return size.addAndGet(heapsize);<a name="line.475"></a>
+<span class="sourceLineNo">476</span>  }<a name="line.476"></a>
+<span class="sourceLineNo">477</span><a name="line.477"></a>
+<span class="sourceLineNo">478</span>  /**<a name="line.478"></a>
+<span class="sourceLineNo">479</span>   * Get the buffer of the block with the specified name.<a name="line.479"></a>
+<span class="sourceLineNo">480</span>   *<a name="line.480"></a>
+<span class="sourceLineNo">481</span>   * @param cacheKey           block's cache key<a name="line.481"></a>
+<span class="sourceLineNo">482</span>   * @param caching            true if the caller caches blocks on cache misses<a name="line.482"></a>
+<span class="sourceLineNo">483</span>   * @param repeat             Whether this is a repeat lookup for the same block<a name="line.483"></a>
+<span class="sourceLineNo">484</span>   *                           (used to avoid double counting cache misses when doing double-check<a name="line.484"></a>
+<span class="sourceLineNo">485</span>   *                           locking)<a name="line.485"></a>
+<span class="sourceLineNo">486</span>   * @param updateCacheMetrics Whether to update cache metrics or not<a name="line.486"></a>
+<span class="sourceLineNo">487</span>   *<a name="line.487"></a>
+<span class="sourceLineNo">488</span>   * @return buffer of specified cache key, or null if not in cache<a name="line.488"></a>
+<span class="sourceLineNo">489</span>   */<a name="line.489"></a>
+<span class="sourceLineNo">490</span>  @Override<a name="line.490"></a>
+<span class="sourceLineNo">491</span>  public Cacheable getBlock(BlockCacheKey cacheKey, boolean caching, boolean repeat,<a name="line.491"></a>
+<span class="sourceLineNo">492</span>      boolean updateCacheMetrics) {<a name="line.492"></a>
+<span class="sourceLineNo">493</span>    LruCachedBlock cb = map.get(cacheKey);<a name="line.493"></a>
+<span class="sourceLineNo">494</span>    if (cb == null) {<a name="line.494"></a>
+<span class="sourceLineNo">495</span>      if (!repeat &amp;&amp; updateCacheMetrics) {<a name="line.495"></a>
+<span class="sourceLineNo">496</span>        stats.miss(caching, cacheKey.isPrimary(), cacheKey.getBlockType());<a name="line.496"></a>
+<span class="sourceLineNo">497</span>      }<a name="line.497"></a>
+<span class="sourceLineNo">498</span>      // If there is another block cache then try and read there.<a name="line.498"></a>
+<span class="sourceLineNo">499</span>      // However if this is a retry ( second time in double checked locking )<a name="line.499"></a>
+<span class="sourceLineNo">500</span>      // And it's already a miss then the l2 will also be a miss.<a name="line.500"></a>
+<span class="sourceLineNo">501</span>      if (victimHandler != null &amp;&amp; !repeat) {<a name="line.501"></a>
+<span class="sourceLineNo">502</span>        Cacheable result = victimHandler.getBlock(cacheKey, caching, repeat, updateCacheMetrics);<a name="line.502"></a>
+<span class="sourceLineNo">503</span><a name="line.503"></a>
+<span class="sourceLineNo">504</span>        // Promote this to L1.<a name="line.504"></a>
+<span class="sourceLineNo">505</span>        if (result != null &amp;&amp; caching) {<a name="line.505"></a>
+<span class="sourceLineNo">506</span>          if (result instanceof HFileBlock &amp;&amp; ((HFileBlock) result).usesSharedMemory()) {<a name="line.506"></a>
+<span class="sourceLineNo">507</span>            result = ((HFileBlock) result).deepClone();<a name="line.507"></a>
+<span class="sourceLineNo">508</span>          }<a name="line.508"></a>
+<span class="sourceLineNo">509</span>          cacheBlock(cacheKey, result, /* inMemory = */ false);<a name="line.509"></a>
+<span class="sourceLineNo">510</span>        }<a name="line.510"></a>
+<span class="sourceLineNo">511</span>        return result;<a name="line.511"></a>
+<span class="sourceLineNo">512</span>      }<a name="line.512"></a>
+<span class="sourceLineNo">513</span>      return null;<a name="line.513"></a>
+<span class="sourceLineNo">514</span>    }<a name="line.514"></a>
+<span class="sourceLineNo">515</span>    if (updateCacheMetrics) stats.hit(caching, cacheKey.isPrimary(), cacheKey.getBlockType());<a name="line.515"></a>
+<span class="sourceLineNo">516</span>    cb.access(count.incrementAndGet());<a name="line.516"></a>
+<span class="sourceLineNo">517</span>    return cb.getBuffer();<a name="line.517"></a>
+<span class="sourceLineNo">518</span>  }<a name="line.518"></a>
+<span class="sourceLineNo">519</span><a name="line.519"></a>
+<span class="sourceLineNo">520</span>  /**<a name="line.520"></a>
+<span class="sourceLineNo">521</span>   * Whether the cache contains block with specified cacheKey<a name="line.521"></a>
+<span class="sourceLineNo">522</span>   *<a name="line.522"></a>
+<span class="sourceLineNo">523</span>   * @return true if contains the block<a name="line.523"></a>
+<span class="sourceLineNo">524</span>   */<a name="line.524"></a>
+<span class="sourceLineNo">525</span>  public boolean containsBlock(BlockCacheKey cacheKey) {<a name="line.525"></a>
+<span class="sourceLineNo">526</span>    return map.containsKey(cacheKey);<a name="line.526"></a>
+<span class="sourceLineNo">527</span>  }<a name="line.527"></a>
+<span class="sourceLineNo">528</span><a name="line.528"></a>
+<span class="sourceLineNo">529</span>  @Override<a name="line.529"></a>
+<span class="sourceLineNo">530</span>  public boolean evictBlock(BlockCacheKey cacheKey) {<a name="line.530"></a>
+<span class="sourceLineNo">531</span>    LruCachedBlock cb = map.get(cacheKey);<a name="line.531"></a>
+<span class="sourceLineNo">532</span>    return cb != null &amp;&amp; evictBlock(cb, false) &gt; 0;<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>   * Evicts all blocks for a specific HFile. This is an<a name="line.536"></a>
+<span class="sourceLineNo">537</span>   * expensive operation implemented as a linear-time search through all blocks<a name="line.537"></a>
+<span class="sourceLineNo">538</span>   * in the cache. Ideally this should be a search in a log-access-time map.<a name="line.538"></a>
+<span class="sourceLineNo">539</span>   *<a name="line.539"></a>
+<span class="sourceLineNo">540</span>   * &lt;p&gt;<a name="line.540"></a>
+<span class="sourceLineNo">541</span>   * This is used for evict-on-close to remove all blocks of a specific HFile.<a name="line.541"></a>
+<span class="sourceLineNo">542</span>   *<a name="line.542"></a>
+<span class="sourceLineNo">543</span>   * @return the number of blocks evicted<a name="line.543"></a>
+<span class="sourceLineNo">544</span>   */<a name="line.544"></a>
+<span class="sourceLineNo">545</span>  @Override<a name="line.545"></a>
+<span class="sourceLineNo">546</span>  public int evictBlocksByHfileName(String hfileName) {<a name="line.546"></a>
+<span class="sourceLineNo">547</span>    int numEvicted = 0;<a name="line.547"></a>
+<span class="sourceLineNo">548</span>    for (BlockCacheKey key : map.keySet()) {<a name="line.548"></a>
+<span class="sourceLineNo">549</span>      if (key.getHfileName().equals(hfileName)) {<a name="line.549"></a>
+<span class="sourceLineNo">550</span>        if (evictBlock(key))<a name="line.550"></a>
+<span class="sourceLineNo">551</span>          ++numEvicted;<a name="line.551"></a>
+<span class="sourceLineNo">552</span>      }<a name="line.552"></a>
+<span class="sourceLineNo">553</span>    }<a name="line.553"></a>
+<span class="sourceLineNo">554</span>    if (victimHandler != null) {<a name="line.554"></a>
+<span class="sourceLineNo">555</span>      numEvicted += victimHandler.evictBlocksByHfileName(hfileName);<a name="line.555"></a>
+<span class="sourceLineNo">556</span>    }<a name="line.556"></a>
+<span class="sourceLineNo">557</span>    return numEvicted;<a name="line.557"></a>
+<span class="sourceLineNo">558</span>  }<a name="line.558"></a>
+<span class="sourceLineNo">559</span><a name="line.559"></a>
+<span class="sourceLineNo">560</span>  /**<a name="line.560"></a>
+<span class="sourceLineNo">561</span>   * Evict the block, and it will be cached by the victim handler if exists &amp;amp;&amp;amp;<a name="line.561"></a>
+<span class="sourceLineNo">562</span>   * block may be read again later<a name="line.562"></a>
+<span class="sourceLineNo">563</span>   *<a name="line.563"></a>
+<span class="sourceLineNo">564</span>   * @param evictedByEvictionProcess true if the given block is evicted by<a name="line.564"></a>
+<span class="sourceLineNo">565</span>   *          EvictionThread<a name="line.565"></a>
+<span class="sourceLineNo">566</span>   * @return the heap size of evicted block<a name="line.566"></a>
+<span class="sourceLineNo">567</span>   */<a name="line.567"></a>
+<span class="sourceLineNo">568</span>  protected long evictBlock(LruCachedBlock block, boolean evictedByEvictionProcess) {<a name="line.568"></a>
+<span class="sourceLineNo">569</span>    boolean found = map.remove(block.getCacheKey()) != null;<a name="line.569"></a>
+<span class="sourceLineNo">570</span>    if (!found) {<a name="line.570"></a>
+<span class="sourceLineNo">571</span>      return 0;<a name="line.571"></a>
+<span class="sourceLineNo">572</span>    }<a name="line.572"></a>
+<span class="sourceLineNo">573</span>    updateSizeMetrics(block, true);<a name="line.573"></a>
+<span class="sourceLineNo">574</span>    long val = elements.decrementAndGet();<a name="line.574"></a>
+<span class="sourceLineNo">575</span>    if (LOG.isTraceEnabled()) {<a name="line.575"></a>
+<span class="sourceLineNo">576</span>      long size = map.size();<a name="line.576"></a>
+<span class="sourceLineNo">577</span>      assertCounterSanity(size, val);<a name="line.577"></a>
+<span class="sourceLineNo">578</span>    }<a name="line.578"></a>
+<span class="sourceLineNo">579</span>    if (block.getBuffer().getBlockType().isData()) {<a name="line.579"></a>
+<span class="sourceLineNo">580</span>       dataBlockElements.decrement();<a name="line.580"></a>
+<span class="sourceLineNo">581</span>    }<a name="line.581"></a>
+<span class="sourceLineNo">582</span>    if (evictedByEvictionProcess) {<a name="line.582"></a>
+<span class="sourceLineNo">583</span>      // When the eviction of the block happened because of invalidation of HFiles, no need to<a name="line.583"></a>
+<span class="sourceLineNo">584</span>      // update the stats counter.<a name="line.584"></a>
+<span class="sourceLineNo">585</span>      stats.evicted(block.getCachedTime(), block.getCacheKey().isPrimary());<a name="line.585"></a>
+<span class="sourceLineNo">586</span>      if (victimHandler != null) {<a name="line.586"></a>
+<span class="sourceLineNo">587</span>        victimHandler.cacheBlock(block.getCacheKey(), block.getBuffer());<a name="line.587"></a>
+<span class="sourceLineNo">588</span>      }<a name="line.588"></a>
+<span class="sourceLineNo">589</span>    }<a name="line.589"></a>
+<span class="sourceLineNo">590</span>    return block.heapSize();<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>   * Multi-threaded call to run the eviction process.<a name="line.594"></a>
+<span class="sourceLineNo">595</span>   */<a name="line.595"></a>
+<span class="sourceLineNo">596</span>  private void runEviction() {<a name="line.596"></a>
+<span class="sourceLineNo">597</span>    if (evictionThread == null) {<a name="line.597"></a>
+<span class="sourceLineNo">598</span>      evict();<a name="line.598"></a>
+<span class="sourceLineNo">599</span>    } else {<a name="line.599"></a>
+<span class="sourceLineNo">600</span>      evictionThread.evict();<a name="line.600"></a>
+<span class="sourceLineNo">601</span>    }<a name="line.601"></a>
 <span class="sourceLineNo">602</span>  }<a name="line.602"></a>
 <span class="sourceLineNo">603</span><a name="line.603"></a>
 <span class="sourceLineNo">604</span>  @VisibleForTesting<a name="line.604"></a>
-<span class="sourceLineNo">605</span>  long getOverhead() {<a name="line.605"></a>
-<span class="sourceLineNo">606</span>    return overhead;<a name="line.606"></a>
+<span class="sourceLineNo">605</span>  boolean isEvictionInProgress() {<a name="line.605"></a>
+<span class="sourceLineNo">606</span>    return evictionInProgress;<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>   * Eviction method.<a name="line.610"></a>
-<span class="sourceLineNo">611</span>   */<a name="line.611"></a>
-<span class="sourceLineNo">612</span>  void evict() {<a name="line.612"></a>
+<span class="sourceLineNo">609</span>  @VisibleForTesting<a name="line.609"></a>
+<span class="sourceLineNo">610</span>  long getOverhead() {<a name="line.610"></a>
+<span class="sourceLineNo">611</span>    return overhead;<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>    // Ensure only one eviction at a time<a name="line.614"></a>
-<span class="sourceLineNo">615</span>    if(!evictionLock.tryLock()) return;<a name="line.615"></a>
-<span class="sourceLineNo">616</span><a name="line.616"></a>
-<span class="sourceLineNo">617</span>    try {<a name="line.617"></a>
-<span class="sourceLineNo">618</span>      evictionInProgress = true;<a name="line.618"></a>
-<span class="sourceLineNo">619</span>      long currentSize = this.size.get();<a name="line.619"></a>
-<span class="sourceLineNo">620</span>      long bytesToFree = currentSize - minSize();<a name="line.620"></a>
+<span class="sourceLineNo">614</span>  /**<a name="line.614"></a>
+<span class="sourceLineNo">615</span>   * Eviction method.<a name="line.615"></a>
+<span class="sourceLineNo">616</span>   */<a name="line.616"></a>
+<span class="sourceLineNo">617</span>  void evict() {<a name="line.617"></a>
+<span class="sourceLineNo">618</span><a name="line.618"></a>
+<span class="sourceLineNo">619</span>    // Ensure only one eviction at a time<a name="line.619"></a>
+<span class="sourceLineNo">620</span>    if(!evictionLock.tryLock()) return;<a name="line.620"></a>
 <span class="sourceLineNo">621</span><a name="line.621"></a>
-<span class="sourceLineNo">622</span>      if (LOG.isTraceEnabled()) {<a name="line.622"></a>
-<span class="sourceLineNo">623</span>        LOG.trace("Block cache LRU eviction started; Attempting to free " +<a name="line.623"></a>
-<span class="sourceLineNo">624</span>          StringUtils.byteDesc(bytesToFree) + " of total=" +<a name="line.624"></a>
-<span class="sourceLineNo">625</span>          StringUtils.byteDesc(currentSize));<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>      if (bytesToFree &lt;= 0) return;<a name="line.628"></a>
-<span class="sourceLineNo">629</span><a name="line.629"></a>
-<span class="sourceLineNo">630</span>      // Instantiate priority buckets<a name="line.630"></a>
-<span class="sourceLineNo">631</span>      BlockBucket bucketSingle = new BlockBucket("single", bytesToFree, blockSize, singleSize());<a name="line.631"></a>
-<span class="sourceLineNo">632</span>      BlockBucket bucketMulti = new BlockBucket("multi", bytesToFree, blockSize, multiSize());<a name="line.632"></a>
-<span class="sourceLineNo">633</span>      BlockBucket bucketMemory = new BlockBucket("memory", bytesToFree, blockSize, memorySize());<a name="line.633"></a>
+<span class="sourceLineNo">622</span>    try {<a name="line.622"></a>
+<span class="sourceLineNo">623</span>      evictionInProgress = true;<a name="line.623"></a>
+<span class="sourceLineNo">624</span>      long currentSize = this.size.get();<a name="line.624"></a>
+<span class="sourceLineNo">625</span>      long bytesToFree = currentSize - minSize();<a name="line.625"></a>
+<span class="sourceLineNo">626</span><a name="line.626"></a>
+<span class="sourceLineNo">627</span>      if (LOG.isTraceEnabled()) {<a name="line.627"></a>
+<span class="sourceLineNo">628</span>        LOG.trace("Block cache LRU eviction started; Attempting to free " +<a name="line.628"></a>
+<span class="sourceLineNo">629</span>          StringUtils.byteDesc(bytesToFree) + " of total=" +<a name="line.629"></a>
+<span class="sourceLineNo">630</span>          StringUtils.byteDesc(currentSize));<a name="line.630"></a>
+<span class="sourceLineNo">631</span>      }<a name="line.631"></a>
+<span class="sourceLineNo">632</span><a name="line.632"></a>
+<span class="sourceLineNo">633</span>      if (bytesToFree &lt;= 0) return;<a name="line.633"></a>
 <span class="sourceLineNo">634</span><a name="line.634"></a>
-<span class="sourceLineNo">635</span>      // Scan entire map putting into appropriate buckets<a name="line.635"></a>
-<span class="sourceLineNo">636</span>      for (LruCachedBlock cachedBlock : map.values()) {<a name="line.636"></a>
-<span class="sourceLineNo">637</span>        switch (cachedBlock.getPriority()) {<a name="line.637"></a>
-<span class="sourceLineNo">638</span>          case SINGLE: {<a name="line.638"></a>
-<span class="sourceLineNo">639</span>            bucketSingle.add(cachedBlock);<a name="line.639"></a>
-<span class="sourceLineNo">640</span>            break;<a name="line.640"></a>
-<span class="sourceLineNo">641</span>          }<a name="line.641"></a>
-<span class="sourceLineNo">642</span>          case MULTI: {<a name="line.642"></a>
-<span class="sourceLineNo">643</span>            bucketMulti.add(cachedBlock);<a name="line.643"></a>
-<span class="sourceLineNo">644</span>            break;<a name="line.644"></a>
-<span class="sourceLineNo">645</span>          }<a name="line.645"></a>
-<span class="sourceLineNo">646</span>          case MEMORY: {<a name="line.646"></a>
-<span class="sourceLineNo">647</span>            bucketMemory.add(cachedBlock);<a name="line.647"></a>
-<span class="sourceLineNo">648</span>            break;<a name="line.648"></a>
-<span class="sourceLineNo">649</span>          }<a name="line.649"></a>
-<span class="sourceLineNo">650</span>        }<a name="line.650"></a>
-<span class="sourceLineNo">651</span>      }<a name="line.651"></a>
-<span class="sourceLineNo">652</span><a name="line.652"></a>
-<span class="sourceLineNo">653</span>      long bytesFreed = 0;<a name="line.653"></a>
-<span class="sourceLineNo">654</span>      if (forceInMemory || memoryFactor &gt; 0.999f) {<a name="line.654"></a>
-<span class="sourceLineNo">655</span>        long s = bucketSingle.totalSize();<a name="line.655"></a>
-<span class="sourceLineNo">656</span>        long m = bucketMulti.totalSize();<a name="line.656"></a>
-<span class="sourceLineNo">657</span>        if (bytesToFree &gt; (s + m)) {<a name="line.657"></a>
-<span class="sourceLineNo">658</span>          // this means we need to evict blocks in memory bucket to make room,<a name="line.658"></a>
-<span class="sourceLineNo">659</span>          // so the single and multi buckets will be emptied<a name="line.659"></a>
-<span class="sourceLineNo">660</span>          bytesFreed = bucketSingle.free(s);<a name="line.660"></a>
-<span class="sourceLineNo">661</span>          bytesFreed += bucketMulti.free(m);<a name="line.661"></a>
-<span class="sourceLineNo">662</span>          if (LOG.isTraceEnabled()) {<a name="line.662"></a>
-<span class="sourceLineNo">663</span>            LOG.trace("freed " + StringUtils.byteDesc(bytesFreed) +<a name="line.663"></a>
-<span class="sourceLineNo">664</span>              " from single and multi buckets");<a name="line.664"></a>
-<span class="sourceLineNo">665</span>          }<a name="line.665"></a>
-<span class="sourceLineNo">666</span>          bytesFreed += bucketMemory.free(bytesToFree - bytesFreed);<a name="line.666"></a>
+<span class="sourceLineNo">635</span>      // Instantiate priority buckets<a name="line.635"></a>
+<span class="sourceLineNo">636</span>      BlockBucket bucketSingle = new BlockBucket("single", bytesToFree, blockSize, singleSize());<a name="line.636"></a>
+<span class="sourceLineNo">637</span>      BlockBucket bucketMulti = new BlockBucket("multi", bytesToFree, blockSize, multiSize());<a name="line.637"></a>
+<span class="sourceLineNo">638</span>      BlockBucket bucketMemory = new BlockBucket("memory", bytesToFree, blockSize, memorySize());<a name="line.638"></a>
+<span class="sourceLineNo">639</span><a name="line.639"></a>
+<span class="sourceLineNo">640</span>      // Scan entire map putting into appropriate buckets<a name="line.640"></a>
+<span class="sourceLineNo">641</span>      for (LruCachedBlock cachedBlock : map.values()) {<a name="line.641"></a>
+<span class="sourceLineNo">642</span>        switch (cachedBlock.getPriority()) {<a name="line.642"></a>
+<span class="sourceLineNo">643</span>          case SINGLE: {<a name="line.643"></a>
+<span class="sourceLineNo">644</span>            bucketSingle.add(cachedBlock);<a name="line.644"></a>
+<span class="sourceLineNo">645</span>            break;<a name="line.645"></a>
+<span class="sourceLineNo">646</span>          }<a name="line.646"></a>
+<span class="sourceLineNo">647</span>          case MULTI: {<a name="line.647"></a>
+<span class="sourceLineNo">648</span>            bucketMulti.add(cachedBlock);<a name="line.648"></a>
+<span class="sourceLineNo">649</span>            break;<a name="line.649"></a>
+<span class="sourceLineNo">650</span>          }<a name="line.650"></a>
+<span class="sourceLineNo">651</span>          case MEMORY: {<a name="line.651"></a>
+<span class="sourceLineNo">652</span>            bucketMemory.add(cachedBlock);<a name="line.652"></a>
+<span class="sourceLineNo">653</span>            break;<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>      }<a name="line.656"></a>
+<span class="sourceLineNo">657</span><a name="line.657"></a>
+<span class="sourceLineNo">658</span>      long bytesFreed = 0;<a name="line.658"></a>
+<span class="sourceLineNo">659</span>      if (forceInMemory || memoryFactor &gt; 0.999f) {<a name="line.659"></a>
+<span class="sourceLineNo">660</span>        long s = bucketSingle.totalSize();<a name="line.660"></a>
+<span class="sourceLineNo">661</span>        long m = bucketMulti.totalSize();<a name="line.661"></a>
+<span class="sourceLineNo">662</span>        if (bytesToFree &gt; (s + m)) {<a name="line.662"></a>
+<span class="sourceLineNo">663</span>          // this means we need to evict blocks in memory bucket to make room,<a name="line.663"></a>
+<span class="sourceLineNo">664</span>          // so the single and multi buckets will be emptied<a name="line.664"></a>
+<span class="sourceLineNo">665</span>          bytesFreed = bucketSingle.free(s);<a name="line.665"></a>
+<span class="sourceLineNo">666</span>          bytesFreed += bucketMulti.free(m);<a name="line.666"></a>
 <span class="sourceLineNo">667</span>          if (LOG.isTraceEnabled()) {<a name="line.667"></a>
 <span class="sourceLineNo">668</span>            LOG.trace("freed " + StringUtils.byteDesc(bytesFreed) +<a name="line.668"></a>
-<span class="sourceLineNo">669</span>              " total from all three buckets ");<a name="line.669"></a>
+<span class="sourceLineNo">669</span>              " from single and multi buckets");<a name="line.669"></a>
 <span class="sourceLineNo">670</span>          }<a name="line.670"></a>
-<span class="sourceLineNo">671</span>        } else {<a name="line.671"></a>
-<span class="sourceLineNo">672</span>          // this means no need to evict block in memory bucket,<a name="line.672"></a>
-<span class="sourceLineNo">673</span>          // and we try best to make the ratio between single-bucket and<a name="line.673"></a>
-<span class="sourceLineNo">674</span>          // multi-bucket is 1:2<a name="line.674"></a>
-<span class="sourceLineNo">675</span>          long bytesRemain = s + m - bytesToFree;<a name="line.675"></a>
-<span class="sourceLineNo">676</span>          if (3 * s &lt;= bytesRemain) {<a name="line.676"></a>
-<span class="sourceLineNo">677</span>            // single-bucket is small enough that no eviction happens for it<a name="line.677"></a>
-<span class="sourceLineNo">678</span>            // hence all eviction goes from multi-bucket<a name="line.678"></a>
-<span class="sourceLineNo">679</span>            bytesFreed = bucketMulti.free(bytesToFree);<a name="line.679"></a>
-<span class="sourceLineNo">680</span>          } else if (3 * m &lt;= 2 * bytesRemain) {<a name="line.680"></a>
-<span class="sourceLineNo">681</span>            // multi-bucket is small enough that no eviction happens for it<a name="line.681"></a>
-<span class="sourceLineNo">682</span>            // hence all eviction goes from single-bucket<a name="line.682"></a>
-<span class="sourceLineNo">683</span>            bytesFreed = bucketSingle.free(bytesToFree);<a name="line.683"></a>
-<span class="sourceLineNo">684</span>          } else {<a name="line.684"></a>
-<span class="sourceLineNo">685</span>            // both buckets need to evict some blocks<a name="line.685"></a>
-<span class="sourceLineNo">686</span>            bytesFreed = bucketSingle.free(s - bytesRemain / 3);<a name="line.686"></a>
-<span class="sourceLineNo">687</span>            if (bytesFreed &lt; bytesToFree) {<a name="line.687"></a>
-<span class="sourceLineNo">688</span>              bytesFreed += bucketMulti.free(bytesToFree - bytesFreed);<a name="line.688"></a>
-<span class="sourceLineNo">689</span>            }<a name="line.689"></a>
-<span class="sourceLineNo">690</span>          }<a name="line.690"></a>
-<span class="sourceLineNo">691</span>        }<a name="line.691"></a>
-<span class="sourceLineNo">692</span>      } else {<a name="line.692"></a>
-<span class="sourceLineNo">693</span>        PriorityQueue&lt;BlockBucket&gt; bucketQueue = new PriorityQueue&lt;&gt;(3);<a name="line.693"></a>
-<span class="sourceLineNo">694</span><a name="line.694"></a>
-<span class="sourceLineNo">695</span>        bucketQueue.add(bucketSingle);<a name="line.695"></a>
-<span class="sourceLineNo">696</span>        bucketQueue.add(bucketMulti);<a name="line.696"></a>
-<span class="sourceLineNo">697</span>        bucketQueue.add(bucketMemory);<a name="line.697"></a>
-<span class="sourceLineNo">698</span><a name="line.698"></a>
-<span class="sourceLineNo">699</span>        int remainingBuckets = 3;<a name="line.699"></a>
-<span class="sourceLineNo">700</span><a name="line.700"></a>
-<span class="sourceLineNo">701</span>        BlockBucket bucket;<a name="line.701"></a>
-<span class="sourceLineNo">702</span>        while ((bucket = bucketQueue.poll()) != null) {<a name="line.702"></a>
-<span class="sourceLineNo">703</span>          long overflow = bucket.overflow();<a name="line.703"></a>
-<span class="sourceLineNo">704</span>          if (overflow &gt; 0) {<a name="line.704"></a>
-<span class="sourceLineNo">705</span>            long bucketBytesToFree =<a name="line.705"></a>
-<span class="sourceLineNo">706</span>                Math.min(overflow, (bytesToFree - bytesFreed) / remainingBuckets);<a name="line.706"></a>
-<span class="sourceLineNo">707</span>            bytesFreed += bucket.free(bucketBytesToFree);<a name="line.707"></a>
-<span class="sourceLineNo">708</span>          }<a name="line.708"></a>
-<span class="sourceLineNo">709</span>          remainingBuckets--;<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>      if (LOG.isTraceEnabled()) {<a name="line.712"></a>
-<span class="sourceLineNo">713</span>        long single = bucketSingle.totalSize();<a name="line.713"></a>
-<span class="sourceLineNo">714</span>        long multi = bucketMulti.totalSize();<a name="line.714"></a>
-<span class="sourceLineNo">715</span>        long memory = bucketMemory.totalSize();<a name="line.715"></a>
-<span class="sourceLineNo">716</span>        LOG.trace("Block cache LRU eviction completed; " +<a name="line.716"></a>
-<span class="sourceLineNo">717</span>          "freed=" + StringUtils.byteDesc(bytesFreed) + ", " +<a name="line.717"></a>
-<span class="sourceLineNo">718</span>          "total=" + StringUtils.byteDesc(this.size.get()) + ", " +<a name="line.718"></a>
-<span class="sourceLineNo">719</span>          "single=" + StringUtils.byteDesc(single) + ", " +<a name="line.719"></a>
-<span class="sourceLineNo">720</span>          "multi=" + StringUtils.byteDesc(multi) + ", " +<a name="line.720"></a>
-<span class="sourceLineNo">721</span>          "memory=" + StringUtils.byteDesc(memory));<a name="line.721"></a>
-<span class="sourceLineNo">722</span>      }<a name="line.722"></a>
-<span class="sourceLineNo">723</span>    } finally {<a name="line.723"></a>
-<span class="sourceLineNo">724</span>      stats.evict();<a name="line.724"></a>
-<span class="sourceLineNo">725</span>      evictionInProgress = false;<a name="line.725"></a>
-<span class="sourceLineNo">726</span>      evictionLock.unlock();<a name="line.726"></a>
-<span class="sourceLineNo">727</span>    }<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>  @Override<a name="line.730"></a>
-<span class="sourceLineNo">731</span>  public String toString() {<a name="line.731"></a>
-<span class="sourceLineNo">732</span>    return MoreObjects.toStringHelper(this)<a name="line.732"></a>
-<span class="sourceLineNo">733</span>      .add("blockCount", getBlockCount())<a name="line.733"></a>
-<span class="sourceLineNo">734</span>      .add("currentSize", StringUtils.byteDesc(getCurrentSize()))<a name="line.734"></a>
-<span class="sourceLineNo">735</span>      .add("freeSize", StringUtils.byteDesc(getFreeSize()))<a name="line.735"></a>
-<span class="sourceLineNo">736</span>      .add("maxSize", StringUtils.byteDesc(getMaxSize()))<a name="line.736"></a>
-<span class="sourceLineNo">737</span>      .add("heapSize", StringUtils.byteDesc(heapSize()))<a name="line.737"></a>
-<span class="sourceLineNo">738</span>      .add("minSize", StringUtils.byteDesc(minSize()))<a name="line.738"></a>
-<span class="sourceLineNo">739</span>      .add("minFactor", minFactor)<a name="line.739"></a>
-<span class="sourceLineNo">740</span>      .add("multiSize", StringUtils.byteDesc(multiSize()))<a name="line.740"></a>
-<span class="sourceLineNo">741</span>      .add("multiFactor", multiFactor)<a name="line.741"></a>
-<span class="sourceLineNo">742</span>      .add("singleSize", StringUtils.byteDesc(singleSize()))<a name="line.742"></a>
-<span class="sourceLineNo">743</span>      .add("singleFactor", singleFactor)<a name="line.743"></a>
-<span class="sourceLineNo">744</span>      .toString();<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>  /**<a name="line.747"></a>
-<span class="sourceLineNo">748</span>   * Used to group blocks into priority buckets.  There will be a BlockBucket<a name="line.748"></a>
-<span class="sourceLineNo">749</span>   * for each priority (single, multi, memory).  Once bucketed, the eviction<a name="line.749"></a>
-<span class="sourceLineNo">750</span>   * algorithm takes the appropriate number of elements out of each according<a name="line.750"></a>
-<span class="sourceLineNo">751</span>   * to configuration parameters and their relatives sizes.<a name="line.751"></a>
-<span class="sourceLineNo">752</span>   */<a name="line.752"></a>
-<span class="sourceLineNo">753</span>  private class BlockBucket implements Comparable&lt;BlockBucket&gt; {<a name="line.753"></a>
-<span class="sourceLineNo">754</span><a name="line.754"></a>
-<span class="sourceLineNo">755</span>    private final String name;<a name="line.755"></a>
-<span class="sourceLineNo">756</span>    private LruCachedBlockQueue queue;<a name="line.756"></a>
-<span class="sourceLineNo">757</span>    private long totalSize = 0;<a name="line.757"></a>
-<span class="sourceLineNo">758</span>    private long bucketSize;<a name="line.758"></a>
+<span class="sourceLineNo">671</span>          bytesFreed += bucketMemory.free(bytesToFree - bytesFreed);<a name="line.671"></a>
+<span class="sourceLineNo">672</span>          if (LOG.isTraceEnabled()) {<a name="line.672"></a>
+<span class="sourceLineNo">673</span>            LOG.trace("freed " + StringUtils.byteDesc(bytesFreed) +<a name="line.673"></a>
+<span class="sourceLineNo">674</span>              " total from all three buckets ");<a name="line.674"></a>
+<span class="sourceLineNo">675</span>          }<a name="line.675"></a>
+<span class="sourceLineNo">676</span>        } else {<a name="line.676"></a>
+<span class="sourceLineNo">677</span>          // this means no need to evict block in memory bucket,<a name="line.677"></a>
+<span class="sourceLineNo">678</span>          // and we try best to make the ratio between single-bucket and<a name="line.678"></a>
+<span class="sourceLineNo">679</span>          // multi-bucket is 1:2<a name="line.679"></a>
+<span class="sourceLineNo">680</span>          long bytesRemain = s + m - bytesToFree;<a name="line.680"></a>
+<span class="sourceLineNo">681</span>          if (3 * s &lt;= bytesRemain) {<a name="line.681"></a>
+<span class="sourceLineNo">682</span>            // single-bucket is small enough that no eviction happens for it<a name="line.682"></a>
+<span class="sourceLineNo">683</span>            // hence all eviction goes from multi-bucket<a name="line.683"></a>
+<span class="sourceLineNo">684</span>            bytesFreed = bucketMulti.free(bytesToFree);<a name="line.684"></a>
+<span class="sourceLineNo">685</span>          } else if (3 * m &lt;= 2 * bytesRemain) {<a name="line.685"></a>
+<span class="sourceLineNo">686</span>            // multi-bucket is small enough that no eviction happens for it<a name="line.686"></a>
+<span class="sourceLineNo">687</span>            // hence all eviction goes from single-bucket<a name="line.687"></a>
+<span class="sourceLineNo">688</span>            bytesFreed = bucketSingle.free(bytesToFree);<a name="line.688"></a>
+<span class="sourceLineNo">689</span>          } else {<a name="line.689"></a>
+<span class="sourceLineNo">690</span>            // both buckets need to evict some blocks<a name="line.690"></a>
+<span class="sourceLineNo">691</span>            bytesFreed = bucketSingle.free(s - bytesRemain / 3);<a name="line.691"></a>
+<span class="sourceLineNo">692</span>            if (bytesFreed &lt; bytesToFree) {<a name="line.692"></a>
+<span class="sourceLineNo">693</span>              bytesFreed += bucketMulti.free(bytesToFree - bytesFreed);<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>        }<a name="line.696"></a>
+<span class="sourceLineNo">697</span>      } else {<a name="line.697"></a>
+<span class="sourceLineNo">698</span>        PriorityQueue&lt;BlockBucket&gt; bucketQueue = new PriorityQueue&lt;&gt;(3);<a name="line.698"></a>
+<span class="sourceLineNo">699</span><a name="line.699"></a>
+<span class="sourceLineNo">700</span>        bucketQueue.add(bucketSingle);<a name="line.700"></a>
+<span class="sourceLineNo">701</span>        bucketQueue.add(bucketMulti);<a name="line.701"></a>
+<span class="sourceLineNo">702</span>        bucketQueue.add(bucketMemory);<a name="line.702"></a>
+<span class="sourceLineNo">703</span><a name="line.703"></a>
+<span class="sourceLineNo">704</span>        int remainingBuckets = 3;<a name="line.704"></a>
+<span class="sourceLineNo">705</span><a name="line.705"></a>
+<span class="sourceLineNo">706</span>        BlockBucket bucket;<a name="line.706"></a>
+<span class="sourceLineNo">707</span>        while ((bucket = bucketQueue.poll()) != null) {<a name="line.707"></a>
+<span class="sourceLineNo">708</span>          long overflow = bucket.overflow();<a name="line.708"></a>
+<span class="sourceLineNo">709</span>          if (overflow &gt; 0) {<a name="line.709"></a>
+<span class="sourceLineNo">710</span>            long bucketBytesToFree =<a name="line.710"></a>
+<span class="sourceLineNo">711</span>                Math.min(overflow, (bytesToFree - bytesFreed) / remainingBuckets);<a name="line.711"></a>
+<span class="sourceLineNo">712</span>            bytesFreed += bucket.free(bucketBytesToFree);<a name="line.712"></a>
+<span class="sourceLineNo">713</span>          }<a name="line.713"></a>
+<span class="sourceLineNo">714</span>          remainingBuckets--;<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">717</span>      if (LOG.isTraceEnabled()) {<a name="line.717"></a>
+<span class="sourceLineNo">718</span>        long single = bucketSingle.totalSize();<a name="line.718"></a>
+<span class="sourceLineNo">719</span>        long multi = bucketMulti.totalSize();<a name="line.719"></a>
+<span class="sourceLineNo">720</span>        long memory = bucketMemory.totalSize();<a name="line.720"></a>
+<span class="sourceLineNo">721</span>        LOG.trace("Block cache LRU eviction completed; " +<a name="line.721"></a>
+<span class="sourceLineNo">722</span>          "freed=" + StringUtils.byteDesc(bytesFreed) + ", " +<a name="line.722"></a>
+<span class="sourceLineNo">723</span>          "total=" + StringUtils.byteDesc(this.size.get()) + ", " +<a name="line.723"></a>
+<span class="sourceLineNo">724</span>          "single=" + StringUtils.byteDesc(single) + ", " +<a name="line.724"></a>
+<span class="sourceLineNo">725</span>          "multi=" + StringUtils.byteDesc(multi) + ", " +<a name="line.725"></a>
+<span class="sourceLineNo">726</span>          "memory=" + StringUtils.byteDesc(memory));<a name="line.726"></a>
+<span class="sourceLineNo">727</span>      }<a name="line.727"></a>
+<span class="sourceLineNo">728</span>    } finally {<a name="line.728"></a>
+<span class="sourceLineNo">729</span>      stats.evict();<a name="line.729"></a>
+<span class="sourceLineNo">730</span>      evictionInProgress = false;<a name="line.730"></a>
+<span class="sourceLineNo">731</span>      evictionLock.unlock();<a name="line.731"></a>
+<span class="sourceLineNo">732</span>    }<a name="line.732"></a>
+<span class="sourceLineNo">733</span>  }<a name="line.733"></a>
+<span class="sourceLineNo">734</span><a name="line.734"></a>
+<span class="sourceLineNo">735</span>  @Override<a name="line.735"></a>
+<span class="sourceLineNo">736</span>  public String toString() {<a name="line.736"></a>
+<span class="sourceLineNo">737</span>    return MoreObjects.toStringHelper(this)<a name="line.737"></a>
+<span class="sourceLineNo">738</span>      .add("blockCount", getBlockCount())<a name="line.738"></a>
+<span class="sourceLineNo">739</span>      .add("currentSize", StringUtils.byteDesc(getCurrentSize()))<a name="line.739"></a>
+<span class="sourceLineNo">740</span>      .add("freeSize", StringUtils.byteDesc(getFreeSize()))<a name="line.740"></a>
+<span class="sourceLineNo">741</span>      .add("maxSize", StringUtils.byteDesc(getMaxSize()))<a name="line.741"></a>
+<span class="sourceLineNo">742</span>      .add("heapSize", StringUtils.byteDesc(heapSize()))<a name="line.742"></a>
+<span class="sourceLineNo">743</span>      .add("minSize", StringUtils.byteDesc(minSize()))<a name="line.743"></a>
+<span class="sourceLineNo">744</span>      .add("minFactor", minFactor)<a name="line.744"></a>
+<span class="sourceLineNo">745</span>      .add("multiSize", StringUtils.byteDesc(multiSize()))<a name="line.745"></a>
+<span class="sourceLineNo">746</span>      .add("multiFactor", multiFactor)<a name="line.746"></a>
+<span class="sourceLineNo">747</span>      .add("singleSize", StringUtils.byteDesc(singleSize()))<a name="line.747"></a>
+<span class="sourceLineNo">748</span>      .add("singleFactor", singleFactor)<a name="line.748"></a>
+<span class="sourceLineNo">749</span>      .toString();<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>   * Used to group blocks into priority buckets.  There will be a BlockBucket<a name="line.753"></a>
+<span class="sourceLineNo">754</span>   * for each priority (single, multi, memory).  Once bucketed, the eviction<a name="line.754"></a>
+<span class="sourceLineNo">755</span>   * algorithm takes the appropriate number of elements out of each according<a name="line.755"></a>
+<span class="sourceLineNo">756</span>   * to configuration parameters and their relatives sizes.<a name="line.756"></a>
+<span class="sourceLineNo">757</span>   */<a name="line.757"></a>
+<span class="sourceLineNo">758</span>  private class BlockBucket implements Comparable&lt;BlockBucket&gt; {<a name="line.758"></a>
 <span class="sourceLineNo">759</span><a name="line.759"></a>
-<span class="sourceLineNo">760</span>    public BlockBucket(String name, long bytesToFree, long blockSize, long bucketSize) {<a name="line.760"></a>
-<span class="sourceLineNo">761</span>      this.name = name;<a name="line.761"></a>
-<span class="sourceLineNo">762</span>      this.bucketSize = bucketSize;<a name="line.762"></a>
-<span class="sourceLineNo">763</span>      queue = new LruCachedBlockQueue(bytesToFree, blockSize);<a name="line.763"></a>
-<span class="sourceLineNo">764</span>      totalSize = 0;<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>    public void add(LruCachedBlock block) {<a name="line.767"></a>
-<span class="sourceLineNo">768</span>      totalSize += block.heapSize();<a name="line.768"></a>
-<span class="sourceLineNo">769</span>      queue.add(block);<a name="line.769"></a>
+<span class="sourceLineNo">760</span>    private final String name;<a name="line.760"></a>
+<span class="sourceLineNo">761</span>    private LruCachedBlockQueue queue;<a name="line.761"></a>
+<span class="sourceLineNo">762</span>    private long totalSize = 0;<a name="line.762"></a>
+<span class="sourceLineNo">763</span>    private long bucketSize;<a name="line.763"></a>
+<span class="sourceLineNo">764</span><a name="line.764"></a>
+<span class="sourceLineNo">765</span>    public BlockBucket(String name, long bytesToFree, long blockSize, long bucketSize) {<a name="line.765"></a>
+<span class="sourceLineNo">766</span>      this.name = name;<a name="line.766"></a>
+<span class="sourceLineNo">767</span>      this.bucketSize = bucketSize;<a name="line.767"></a>
+<span class="sourceLineNo">768</span>      queue = new LruCachedBlockQueue(bytesToFree, blockSize);<a name="line.768"></a>
+<span class="sourceLineNo">769</span>      totalSize = 0;<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>    public long free(long toFree) {<a name="line.772"></a>
-<span class="sourceLineNo">773</span>      if (LOG.isTraceEnabled()) {<a name="line.773"></a>
-<span class="sourceLineNo">774</span>        LOG.trace("freeing " + StringUtils.byteDesc(toFree) + " from " + this);<a name="line.774"></a>
-<span class="sourceLineNo">775</span>      }<a name="line.775"></a>
-<span class="sourceLineNo">776</span>      LruCachedBlock cb;<a name="line.776"></a>
-<span class="sourceLineNo">777</span>      long freedBytes = 0;<a name="line.777"></a>
-<span class="sourceLineNo">778</span>      while ((cb = queue.pollLast()) != null) {<a name="line.778"></a>
-<span class="sourceLineNo">779</span>        freedBytes += evictBlock(cb, true);<a name="line.779"></a>
-<span class="sourceLineNo">780</span>        if (freedBytes &gt;= toFree) {<a name="line.780"></a>
-<span class="sourceLineNo">781</span>          return freedBytes;<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>      if (LOG.isTraceEnabled()) {<a name="line.784"></a>
-<span class="sourceLineNo">785</span>        LOG.trace("freed " + StringUtils.byteDesc(freedBytes) + " from " + this);<a name="line.785"></a>
-<span class="sourceLineNo">786</span>      }<a name="line.786"></a>
-<span class="sourceLineNo">787</span>      return freedBytes;<a name="line.787"></a>
-<span class="sourceLineNo">788</span>    }<a name="line.788"></a>
-<span class="sourceLineNo">789</span><a name="line.789"></a>
-<span class="sourceLineNo">790</span>    public long overflow() {<a name="line.790"></a>
-<span class="sourceLineNo">791</span>      return totalSize - bucketSize;<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>
-<span class="sourceLineNo">794</span>    public long totalSize() {<a name="line.794"></a>
-<span class="sourceLineNo">795</span>      return totalSize;<a name="line.795"></a>
-<span class="sourceLineNo">796</span>    }<a name="line.796"></a>
-<span class="sourceLineNo">797</span><a name="line.797"></a>
-<span class="sourceLineNo">798</span>    @Override<a name="line.798"></a>
-<span class="sourceLineNo">799</span>    public int compareTo(BlockBucket that) {<a name="line.799"></a>
-<span class="sourceLineNo">800</span>      return Long.compare(this.overflow(), that.overflow());<a name="line.800"></a>
+<span class="sourceLineNo">772</span>    public void add(LruCachedBlock block) {<a name="line.772"></a>
+<span class="sourceLineNo">773</span>      totalSize += block.heapSize();<a name="line.773"></a>
+<span class="sourceLineNo">774</span>      queue.add(block);<a name="line.774"></a>
+<span class="sourceLineNo">775</span>    }<a name="line.775"></a>
+<span class="sourceLineNo">776</span><a name="line.776"></a>
+<span class="sourceLineNo">777</span>    public long free(long toFree) {<a name="line.777"></a>
+<span class="sourceLineNo">778</span>      if (LOG.isTraceEnabled()) {<a name="line.778"></a>
+<span class="sourceLineNo">779</span>        LOG.trace("freeing " + StringUtils.byteDesc(toFree) + " from " + this);<a name="line.779"></a>
+<span class="sourceLineNo">780</span>      }<a name="line.780"></a>
+<span class="sourceLineNo">781</span>      LruCachedBlock cb;<a name="line.781"></a>
+<span class="sourceLineNo">782</span>      long freedBytes = 0;<a name="line.782"></a>
+<span class="sourceLineNo">783</span>      while ((cb = queue.pollLast()) != null) {<a name="line.783"></a>
+<span class="sourceLineNo">784</span>        freedBytes += evictBlock(cb, true);<a name="line.784"></a>
+<span class="sourceLineNo">785</span>        if (freedBytes &gt;= toFree) {<a name="line.785"></a>
+<span class="sourceLineNo">786</span>          return freedBytes;<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>      if (LOG.isTraceEnabled()) {<a name="line.789"></a>
+<span class="sourceLineNo">790</span>        LOG.trace("freed " + StringUtils.byteDesc(freedBytes) + " from " + this);<a name="line.790"></a>
+<span class="sourceLineNo">791</span>      }<a name="line.791"></a>
+<span class="sourceLineNo">792</span>      return freedBytes;<a name="line.792"></a>
+<span class="sourceLineNo">793</span>    }<a name="line.793"></a>
+<span class="sourceLineNo">794</span><a name="line.794"></a>
+<span class="sourceLineNo">795</span>    public long overflow() {<a name="line.795"></a>
+<span class="sourceLineNo">796</span>      return totalSize - bucketSize;<a name="line.796"></a>
+<span class="sourceLineNo">797</span>    }<a name="line.797"></a>
+<span class="sourceLineNo">798</span><a name="line.798"></a>
+<span class="sourceLineNo">799</span>    public long totalSize() {<a name="line.799"></a>
+<span class="sourceLineNo">800</span>      return totalSize;<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>    @Override<a name="line.803"></a>
-<span class="sourceLineNo">804</span>    public boolean equals(Object that) {<a name="line.804"></a>
-<span class="sourceLineNo">805</span>      if (that == null || !(that instanceof BlockBucket)) {<a name="line.805"></a>
-<span class="sourceLineNo">806</span>        return false;<a name="line.806"></a>
-<span class="sourceLineNo">807</span>      }<a name="line.807"></a>
-<span class="sourceLineNo">808</span>      return compareTo((BlockBucket)that) == 0;<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>    @Override<a name="line.811"></a>
-<span class="sourceLineNo">812</span>    public int hashCode() {<a name="line.812"></a>
-<span class="sourceLineNo">813</span>      return Objects.hashCode(name, bucketSize, queue, totalSize);<a name="line.813"></a>
+<span class="sourceLineNo">804</span>    public int compareTo(BlockBucket that) {<a name="line.804"></a>
+<span class="sourceLineNo">805</span>      return Long.compare(this.overflow(), that.overflow());<a name="line.805"></a>
+<span class="sourceLineNo">806</span>    }<a name="line.806"></a>
+<span class="sourceLineNo">807</span><a name="line.807"></a>
+<span class="sourceLineNo">808</span>    @Override<a name="line.808"></a>
+<span class="sourceLineNo">809</span>    public boolean equals(Object that) {<a name="line.809"></a>
+<span class="sourceLineNo">810</span>      if (that == null || !(that instanceof BlockBucket)) {<a name="line.810"></a>
+<span class="sourceLineNo">811</span>        return false;<a name="line.811"></a>
+<span class="sourceLineNo">812</span>      }<a name="line.812"></a>
+<span class="sourceLineNo">813</span>      return compareTo((BlockBucket)that) == 0;<a name="line.813"></a>
 <span class="sourceLineNo">814</span>    }<a name="line.814"></a>
 <span class="sourceLineNo">815</span><a name="line.815"></a>
 <span class="sourceLineNo">816</span>    @Override<a name="line.816"></a>
-<span class="sourceLineNo">817</span>    public String toString() {<a name="line.817"></a>
-<span class="sourceLineNo">818</span>      return MoreObjects.toStringHelper(this)<a name="line.818"></a>
-<span class="sourceLineNo">819</span>        .add("name", name)<a name="line.819"></a>
-<span class="sourceLineNo">820</span>        .add("totalSize", StringUtils.byteDesc(totalSize))<a name="line.820"></a>
-<span class="sourceLineNo">821</span>        .add("bucketSize", StringUtils.byteDesc(bucketSize))<a name="line.821"></a>
-<span class="sourceLineNo">822</span>        .toString();<a name="line.822"></a>
-<span class="sourceLineNo">823</span>    }<a name="line.823"></a>
-<span class="sourceLineNo">824</span>  }<a name="line.824"></a>
-<span class="sourceLineNo">825</span><a name="line.825"></a>
-<span class="sourceLineNo">826</span>  /**<a name="line.826"></a>
-<span class="sourceLineNo">827</span>   * Get the maximum size of this cache.<a name="line.827"></a>
-<span class="sourceLineNo">828</span>   *<a name="line.828"></a>
-<span class="sourceLineNo">829</span>   * @return max size in bytes<a name="line.829"></a>
-<span class="sourceLineNo">830</span>   */<a name="line.830"></a>
-<span class="sourceLineNo">831</span><a name="line.831"></a>
-<span class="sourceLineNo">832</span>  @Override<a name="line.832"></a>
-<span class="sourceLineNo">833</span>  public long getMaxSize() {<a name="line.833"></a>
-<span class="sourceLineNo">834</span>    return this.maxSize;<a name="line.834"></a>
-<span class="sourceLineNo">835</span>  }<a name="line.835"></a>
+<span class="sourceLineNo">817</span>    public int hashCode() {<a name="line.817"></a>
+<span class="sourceLineNo">818</span>      return Objects.hashCode(name, bucketSize, queue, totalSize);<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>    @Override<a name="line.821"></a>
+<span class="sourceLineNo">822</span>    public String toString() {<a name="line.822"></a>
+<span class="sourceLineNo">823</span>      return MoreObjects.toStringHelper(this)<a name="line.823"></a>
+<span class="sourceLineNo">824</span>        .add("name", name)<a name="line.824"></a>
+<span class="sourceLineNo">825</span>        .add("totalSize", StringUtils.byteDesc(totalSize))<a name="line.825"></a>
+<span class="sourceLineNo">826</span>        .add("bucketSize", StringUtils.byteDesc(bucketSize))<a name="line.826"></a>
+<span class="sourceLineNo">827</span>        .toString();<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">830</span><a name="line.830"></a>
+<span class="sourceLineNo">831</span>  /**<a name="line.831"></a>
+<span class="sourceLineNo">832</span>   * Get the maximum size of this cache.<a name="line.832"></a>
+<span class="sourceLineNo">833</span>   *<a name="line.833"></a>
+<span class="sourceLineNo">834</span>   * @return max size in bytes<a name="line.834"></a>
+<span class="sourceLineNo">835</span>   */<a name="line.835"></a>
 <span class="sourceLineNo">836</span><a name="line.836"></a>
 <span class="sourceLineNo">837</span>  @Override<a name="line.837"></a>
-<span class="sourceLineNo">838</span>  public long getCurrentSize() {<a name="line.838"></a>
-<span class="sourceLineNo">839</span>    return this.size.get();<a name="line.839"></a>
+<span class="sourceLineNo">838</span>  public long getMaxSize() {<a name="line.838"></a>
+<span class="sourceLineNo">839</span>    return this.maxSize;<a name="line.839"></a>
 <span class="sourceLineNo">840</span>  }<a name="line.840"></a>
 <span class="sourceLineNo">841</span><a name="line.841"></a>
 <span class="sourceLineNo">842</span>  @Override<a name="line.842"></a>
-<span class="sourceLineNo">843</span>  public long getCurrentDataSize() {<a name="line.843"></a>
-<span class="sourceLineNo">844</span>    return this.dataBlockSize.sum();<a name="line.844"></a>
+<span class="sourceLineNo">843</span>  public long getCurrentSize() {<a name="line.843"></a>
+<span class="sourceLineNo">844</span>    return this.size.get();<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>  @Override<a name="line.847"></a>
-<span class="sourceLineNo">848</span>  public long getFreeSize() {<a name="line.848"></a>
-<span class="sourceLineNo">849</span>    return getMaxSize() - getCurrentSize();<a name="line.849"></a>
+<span class="sourceLineNo">848</span>  public long getCurrentDataSize() {<a name="line.848"></a>
+<span class="sourceLineNo">849</span>    return this.dataBlockSize.sum();<a name="line.849"></a>
 <span class="sourceLineNo">850</span>  }<a name="line.850"></a>
 <span class="sourceLineNo">851</span><a name="line.851"></a>
 <span class="sourceLineNo">852</span>  @Override<a name="line.852"></a>
-<span class="sourceLineNo">853</span>  public long size() {<a name="line.853"></a>
-<span class="sourceLineNo">854</span>    return getMaxSize();<a name="line.854"></a>
+<span class="sourceLineNo">853</span>  public long getFreeSize() {<a name="line.853"></a>
+<span class="sourceLineNo">854</span>    return getMaxSize() - getCurrentSize();<a name="line.854"></a>
 <span class="sourceLineNo">855</span>  }<a name="line.855"></a>
 <span class="sourceLineNo">856</span><a name="line.856"></a>
 <span class="sourceLineNo">857</span>  @Override<a name="line.857"></a>
-<span class="sourceLineNo">858</span>  public long getBlockCount() {<a name="line.858"></a>
-<span class="sourceLineNo">859</span>    return this.elements.get();<a name="line.859"></a>
+<span class="sourceLineNo">858</span>  public long size() {<a name="line.858"></a>
+<span class="sourceLineNo">859</span>    return getMaxSize();<a name="line.859"></a>
 <span class="sourceLineNo">860</span>  }<a name="line.860"></a>
 <span class="sourceLineNo">861</span><a name="line.861"></a>
 <span class="sourceLineNo">862</span>  @Override<a name="line.862"></a>
-<span class="sourceLineNo">863</span>  public long getDataBlockCount() {<a name="line.863"></a>
-<span class="sourceLineNo">864</span>    return this.dataBlockElements.sum();<a name="line.864"></a>
+<span class="sourceLineNo">863</span>  public long getBlockCount() {<a name="line.863"></a>
+<span class="sourceLineNo">864</span>    return this.elements.get();<a name="line.864"></a>
 <span class="sourceLineNo">865</span>  }<a name="line.865"></a>
 <span class="sourceLineNo">866</span><a name="line.866"></a>
-<span class="sourceLineNo">867</span>  EvictionThread getEvictionThread() {<a name="line.867"></a>
-<span class="sourceLineNo">868</span>    return this.evictionThread;<a name="line.868"></a>
-<span class="sourceLineNo">869</span>  }<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>   * Eviction thread.  Sits in waiting state until an eviction is triggered<a name="line.872"></a>
-<span class="sourceLineNo">873</span>   * when the cache size grows above the acceptable le

<TRUNCATED>

[41/50] hbase-site git commit: Published site at 26babcf013de696b899d76a3c39434b794440d8d.

Posted by gi...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html
----------------------------------------------------------------------
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html
index f8ce32e..f118c08 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.CachedBlocksByFile.html
@@ -41,273 +41,305 @@
 <span class="sourceLineNo">033</span>import org.apache.hadoop.conf.Configuration;<a name="line.33"></a>
 <span class="sourceLineNo">034</span>import org.apache.hadoop.hbase.metrics.impl.FastLongHistogram;<a name="line.34"></a>
 <span class="sourceLineNo">035</span>import org.apache.hadoop.hbase.util.Bytes;<a name="line.35"></a>
-<span class="sourceLineNo">036</span><a name="line.36"></a>
-<span class="sourceLineNo">037</span>/**<a name="line.37"></a>
-<span class="sourceLineNo">038</span> * Utilty for aggregating counts in CachedBlocks and toString/toJSON CachedBlocks and BlockCaches.<a name="line.38"></a>
-<span class="sourceLineNo">039</span> * No attempt has been made at making this thread safe.<a name="line.39"></a>
-<span class="sourceLineNo">040</span> */<a name="line.40"></a>
-<span class="sourceLineNo">041</span>@InterfaceAudience.Private<a name="line.41"></a>
-<span class="sourceLineNo">042</span>public class BlockCacheUtil {<a name="line.42"></a>
-<span class="sourceLineNo">043</span><a name="line.43"></a>
-<span class="sourceLineNo">044</span><a name="line.44"></a>
-<span class="sourceLineNo">045</span>  public static final long NANOS_PER_SECOND = 1000000000;<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>   * Needed generating JSON.<a name="line.48"></a>
-<span class="sourceLineNo">049</span>   */<a name="line.49"></a>
-<span class="sourceLineNo">050</span>  private static final ObjectMapper MAPPER = new ObjectMapper();<a name="line.50"></a>
-<span class="sourceLineNo">051</span>  static {<a name="line.51"></a>
-<span class="sourceLineNo">052</span>    MAPPER.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);<a name="line.52"></a>
-<span class="sourceLineNo">053</span>    MAPPER.configure(SerializationFeature.FLUSH_AFTER_WRITE_VALUE, true);<a name="line.53"></a>
-<span class="sourceLineNo">054</span>    MAPPER.configure(SerializationFeature.INDENT_OUTPUT, true);<a name="line.54"></a>
-<span class="sourceLineNo">055</span>  }<a name="line.55"></a>
-<span class="sourceLineNo">056</span><a name="line.56"></a>
-<span class="sourceLineNo">057</span>  /**<a name="line.57"></a>
-<span class="sourceLineNo">058</span>   * @param cb<a name="line.58"></a>
-<span class="sourceLineNo">059</span>   * @return The block content as String.<a name="line.59"></a>
-<span class="sourceLineNo">060</span>   */<a name="line.60"></a>
-<span class="sourceLineNo">061</span>  public static String toString(final CachedBlock cb, final long now) {<a name="line.61"></a>
-<span class="sourceLineNo">062</span>    return "filename=" + cb.getFilename() + ", " + toStringMinusFileName(cb, now);<a name="line.62"></a>
-<span class="sourceLineNo">063</span>  }<a name="line.63"></a>
-<span class="sourceLineNo">064</span><a name="line.64"></a>
-<span class="sourceLineNo">065</span>  /**<a name="line.65"></a>
-<span class="sourceLineNo">066</span>   * Little data structure to hold counts for a file.<a name="line.66"></a>
-<span class="sourceLineNo">067</span>   * Used doing a toJSON.<a name="line.67"></a>
-<span class="sourceLineNo">068</span>   */<a name="line.68"></a>
-<span class="sourceLineNo">069</span>  static class CachedBlockCountsPerFile {<a name="line.69"></a>
-<span class="sourceLineNo">070</span>    private int count = 0;<a name="line.70"></a>
-<span class="sourceLineNo">071</span>    private long size = 0;<a name="line.71"></a>
-<span class="sourceLineNo">072</span>    private int countData = 0;<a name="line.72"></a>
-<span class="sourceLineNo">073</span>    private long sizeData = 0;<a name="line.73"></a>
-<span class="sourceLineNo">074</span>    private final String filename;<a name="line.74"></a>
-<span class="sourceLineNo">075</span><a name="line.75"></a>
-<span class="sourceLineNo">076</span>    CachedBlockCountsPerFile(final String filename) {<a name="line.76"></a>
-<span class="sourceLineNo">077</span>      this.filename = filename;<a name="line.77"></a>
-<span class="sourceLineNo">078</span>    }<a name="line.78"></a>
-<span class="sourceLineNo">079</span><a name="line.79"></a>
-<span class="sourceLineNo">080</span>    public int getCount() {<a name="line.80"></a>
-<span class="sourceLineNo">081</span>      return count;<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>    public long getSize() {<a name="line.84"></a>
-<span class="sourceLineNo">085</span>      return size;<a name="line.85"></a>
-<span class="sourceLineNo">086</span>    }<a name="line.86"></a>
-<span class="sourceLineNo">087</span><a name="line.87"></a>
-<span class="sourceLineNo">088</span>    public int getCountData() {<a name="line.88"></a>
-<span class="sourceLineNo">089</span>      return countData;<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>    public long getSizeData() {<a name="line.92"></a>
-<span class="sourceLineNo">093</span>      return sizeData;<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>    public String getFilename() {<a name="line.96"></a>
-<span class="sourceLineNo">097</span>      return filename;<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>  /**<a name="line.101"></a>
-<span class="sourceLineNo">102</span>   * @param filename<a name="line.102"></a>
-<span class="sourceLineNo">103</span>   * @param blocks<a name="line.103"></a>
-<span class="sourceLineNo">104</span>   * @return A JSON String of &lt;code&gt;filename&lt;/code&gt; and counts of &lt;code&gt;blocks&lt;/code&gt;<a name="line.104"></a>
-<span class="sourceLineNo">105</span>   * @throws JsonGenerationException<a name="line.105"></a>
-<span class="sourceLineNo">106</span>   * @throws JsonMappingException<a name="line.106"></a>
-<span class="sourceLineNo">107</span>   * @throws IOException<a name="line.107"></a>
-<span class="sourceLineNo">108</span>   */<a name="line.108"></a>
-<span class="sourceLineNo">109</span>  public static String toJSON(final String filename, final NavigableSet&lt;CachedBlock&gt; blocks)<a name="line.109"></a>
-<span class="sourceLineNo">110</span>  throws JsonGenerationException, JsonMappingException, IOException {<a name="line.110"></a>
-<span class="sourceLineNo">111</span>    CachedBlockCountsPerFile counts = new CachedBlockCountsPerFile(filename);<a name="line.111"></a>
-<span class="sourceLineNo">112</span>    for (CachedBlock cb: blocks) {<a name="line.112"></a>
-<span class="sourceLineNo">113</span>      counts.count++;<a name="line.113"></a>
-<span class="sourceLineNo">114</span>      counts.size += cb.getSize();<a name="line.114"></a>
-<span class="sourceLineNo">115</span>      BlockType bt = cb.getBlockType();<a name="line.115"></a>
-<span class="sourceLineNo">116</span>      if (bt != null &amp;&amp; bt.isData()) {<a name="line.116"></a>
-<span class="sourceLineNo">117</span>        counts.countData++;<a name="line.117"></a>
-<span class="sourceLineNo">118</span>        counts.sizeData += cb.getSize();<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>    return MAPPER.writeValueAsString(counts);<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>   * @param cbsbf<a name="line.125"></a>
-<span class="sourceLineNo">126</span>   * @return JSON string of &lt;code&gt;cbsf&lt;/code&gt; aggregated<a name="line.126"></a>
-<span class="sourceLineNo">127</span>   * @throws JsonGenerationException<a name="line.127"></a>
-<span class="sourceLineNo">128</span>   * @throws JsonMappingException<a name="line.128"></a>
-<span class="sourceLineNo">129</span>   * @throws IOException<a name="line.129"></a>
-<span class="sourceLineNo">130</span>   */<a name="line.130"></a>
-<span class="sourceLineNo">131</span>  public static String toJSON(final CachedBlocksByFile cbsbf)<a name="line.131"></a>
-<span class="sourceLineNo">132</span>  throws JsonGenerationException, JsonMappingException, IOException {<a name="line.132"></a>
-<span class="sourceLineNo">133</span>    return MAPPER.writeValueAsString(cbsbf);<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>   * @param bc<a name="line.137"></a>
-<span class="sourceLineNo">138</span>   * @return JSON string of &lt;code&gt;bc&lt;/code&gt; content.<a name="line.138"></a>
-<span class="sourceLineNo">139</span>   * @throws JsonGenerationException<a name="line.139"></a>
-<span class="sourceLineNo">140</span>   * @throws JsonMappingException<a name="line.140"></a>
-<span class="sourceLineNo">141</span>   * @throws IOException<a name="line.141"></a>
-<span class="sourceLineNo">142</span>   */<a name="line.142"></a>
-<span class="sourceLineNo">143</span>  public static String toJSON(final BlockCache bc)<a name="line.143"></a>
-<span class="sourceLineNo">144</span>  throws JsonGenerationException, JsonMappingException, IOException {<a name="line.144"></a>
-<span class="sourceLineNo">145</span>    return MAPPER.writeValueAsString(bc);<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>  /**<a name="line.148"></a>
-<span class="sourceLineNo">149</span>   * @param cb<a name="line.149"></a>
-<span class="sourceLineNo">150</span>   * @return The block content of &lt;code&gt;bc&lt;/code&gt; as a String minus the filename.<a name="line.150"></a>
-<span class="sourceLineNo">151</span>   */<a name="line.151"></a>
-<span class="sourceLineNo">152</span>  public static String toStringMinusFileName(final CachedBlock cb, final long now) {<a name="line.152"></a>
-<span class="sourceLineNo">153</span>    return "offset=" + cb.getOffset() +<a name="line.153"></a>
-<span class="sourceLineNo">154</span>      ", size=" + cb.getSize() +<a name="line.154"></a>
-<span class="sourceLineNo">155</span>      ", age=" + (now - cb.getCachedTime()) +<a name="line.155"></a>
-<span class="sourceLineNo">156</span>      ", type=" + cb.getBlockType() +<a name="line.156"></a>
-<span class="sourceLineNo">157</span>      ", priority=" + cb.getBlockPriority();<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>  /**<a name="line.160"></a>
-<span class="sourceLineNo">161</span>   * Get a {@link CachedBlocksByFile} instance and load it up by iterating content in<a name="line.161"></a>
-<span class="sourceLineNo">162</span>   * {@link BlockCache}.<a name="line.162"></a>
-<span class="sourceLineNo">163</span>   * @param conf Used to read configurations<a name="line.163"></a>
-<span class="sourceLineNo">164</span>   * @param bc Block Cache to iterate.<a name="line.164"></a>
-<span class="sourceLineNo">165</span>   * @return Laoded up instance of CachedBlocksByFile<a name="line.165"></a>
-<span class="sourceLineNo">166</span>   */<a name="line.166"></a>
-<span class="sourceLineNo">167</span>  public static CachedBlocksByFile getLoadedCachedBlocksByFile(final Configuration conf,<a name="line.167"></a>
-<span class="sourceLineNo">168</span>      final BlockCache bc) {<a name="line.168"></a>
-<span class="sourceLineNo">169</span>    CachedBlocksByFile cbsbf = new CachedBlocksByFile(conf);<a name="line.169"></a>
-<span class="sourceLineNo">170</span>    for (CachedBlock cb: bc) {<a name="line.170"></a>
-<span class="sourceLineNo">171</span>      if (cbsbf.update(cb)) break;<a name="line.171"></a>
-<span class="sourceLineNo">172</span>    }<a name="line.172"></a>
-<span class="sourceLineNo">173</span>    return cbsbf;<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 static int compareCacheBlock(Cacheable left, Cacheable right) {<a name="line.176"></a>
-<span class="sourceLineNo">177</span>    ByteBuffer l = ByteBuffer.allocate(left.getSerializedLength());<a name="line.177"></a>
-<span class="sourceLineNo">178</span>    left.serialize(l);<a name="line.178"></a>
-<span class="sourceLineNo">179</span>    ByteBuffer r = ByteBuffer.allocate(right.getSerializedLength());<a name="line.179"></a>
-<span class="sourceLineNo">180</span>    right.serialize(r);<a name="line.180"></a>
-<span class="sourceLineNo">181</span>    return Bytes.compareTo(l.array(), l.arrayOffset(), l.limit(),<a name="line.181"></a>
-<span class="sourceLineNo">182</span>        r.array(), r.arrayOffset(), r.limit());<a name="line.182"></a>
-<span class="sourceLineNo">183</span>  }<a name="line.183"></a>
-<span class="sourceLineNo">184</span><a name="line.184"></a>
-<span class="sourceLineNo">185</span>  /**<a name="line.185"></a>
-<span class="sourceLineNo">186</span>   * Use one of these to keep a running account of cached blocks by file.  Throw it away when done.<a name="line.186"></a>
-<span class="sourceLineNo">187</span>   * This is different than metrics in that it is stats on current state of a cache.<a name="line.187"></a>
-<span class="sourceLineNo">188</span>   * See getLoadedCachedBlocksByFile<a name="line.188"></a>
-<span class="sourceLineNo">189</span>   */<a name="line.189"></a>
-<span class="sourceLineNo">190</span>  @JsonIgnoreProperties({"cachedBlockStatsByFile"})<a name="line.190"></a>
-<span class="sourceLineNo">191</span>  public static class CachedBlocksByFile {<a name="line.191"></a>
-<span class="sourceLineNo">192</span>    private int count;<a name="line.192"></a>
-<span class="sourceLineNo">193</span>    private int dataBlockCount;<a name="line.193"></a>
-<span class="sourceLineNo">194</span>    private long size;<a name="line.194"></a>
-<span class="sourceLineNo">195</span>    private long dataSize;<a name="line.195"></a>
-<span class="sourceLineNo">196</span>    private final long now = System.nanoTime();<a name="line.196"></a>
-<span class="sourceLineNo">197</span>    /**<a name="line.197"></a>
-<span class="sourceLineNo">198</span>     * How many blocks to look at before we give up.<a name="line.198"></a>
-<span class="sourceLineNo">199</span>     * There could be many millions of blocks. We don't want the<a name="line.199"></a>
-<span class="sourceLineNo">200</span>     * ui to freeze while we run through 1B blocks... users will<a name="line.200"></a>
-<span class="sourceLineNo">201</span>     * think hbase dead. UI displays warning in red when stats<a name="line.201"></a>
-<span class="sourceLineNo">202</span>     * are incomplete.<a name="line.202"></a>
-<span class="sourceLineNo">203</span>     */<a name="line.203"></a>
-<span class="sourceLineNo">204</span>    private final int max;<a name="line.204"></a>
-<span class="sourceLineNo">205</span>    public static final int DEFAULT_MAX = 1000000;<a name="line.205"></a>
-<span class="sourceLineNo">206</span><a name="line.206"></a>
-<span class="sourceLineNo">207</span>    CachedBlocksByFile() {<a name="line.207"></a>
-<span class="sourceLineNo">208</span>      this(null);<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>    CachedBlocksByFile(final Configuration c) {<a name="line.211"></a>
-<span class="sourceLineNo">212</span>      this.max = c == null? DEFAULT_MAX: c.getInt("hbase.ui.blockcache.by.file.max", DEFAULT_MAX);<a name="line.212"></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> * Utilty for aggregating counts in CachedBlocks and toString/toJSON CachedBlocks and BlockCaches.<a name="line.40"></a>
+<span class="sourceLineNo">041</span> * No attempt has been made at making this thread safe.<a name="line.41"></a>
+<span class="sourceLineNo">042</span> */<a name="line.42"></a>
+<span class="sourceLineNo">043</span>@InterfaceAudience.Private<a name="line.43"></a>
+<span class="sourceLineNo">044</span>public class BlockCacheUtil {<a name="line.44"></a>
+<span class="sourceLineNo">045</span><a name="line.45"></a>
+<span class="sourceLineNo">046</span>  private static final Logger LOG = LoggerFactory.getLogger(BlockCacheUtil.class);<a name="line.46"></a>
+<span class="sourceLineNo">047</span><a name="line.47"></a>
+<span class="sourceLineNo">048</span>  public static final long NANOS_PER_SECOND = 1000000000;<a name="line.48"></a>
+<span class="sourceLineNo">049</span><a name="line.49"></a>
+<span class="sourceLineNo">050</span>  /**<a name="line.50"></a>
+<span class="sourceLineNo">051</span>   * Needed generating JSON.<a name="line.51"></a>
+<span class="sourceLineNo">052</span>   */<a name="line.52"></a>
+<span class="sourceLineNo">053</span>  private static final ObjectMapper MAPPER = new ObjectMapper();<a name="line.53"></a>
+<span class="sourceLineNo">054</span>  static {<a name="line.54"></a>
+<span class="sourceLineNo">055</span>    MAPPER.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);<a name="line.55"></a>
+<span class="sourceLineNo">056</span>    MAPPER.configure(SerializationFeature.FLUSH_AFTER_WRITE_VALUE, true);<a name="line.56"></a>
+<span class="sourceLineNo">057</span>    MAPPER.configure(SerializationFeature.INDENT_OUTPUT, true);<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>  /**<a name="line.60"></a>
+<span class="sourceLineNo">061</span>   * @param cb<a name="line.61"></a>
+<span class="sourceLineNo">062</span>   * @return The block content as String.<a name="line.62"></a>
+<span class="sourceLineNo">063</span>   */<a name="line.63"></a>
+<span class="sourceLineNo">064</span>  public static String toString(final CachedBlock cb, final long now) {<a name="line.64"></a>
+<span class="sourceLineNo">065</span>    return "filename=" + cb.getFilename() + ", " + toStringMinusFileName(cb, now);<a name="line.65"></a>
+<span class="sourceLineNo">066</span>  }<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>   * Little data structure to hold counts for a file.<a name="line.69"></a>
+<span class="sourceLineNo">070</span>   * Used doing a toJSON.<a name="line.70"></a>
+<span class="sourceLineNo">071</span>   */<a name="line.71"></a>
+<span class="sourceLineNo">072</span>  static class CachedBlockCountsPerFile {<a name="line.72"></a>
+<span class="sourceLineNo">073</span>    private int count = 0;<a name="line.73"></a>
+<span class="sourceLineNo">074</span>    private long size = 0;<a name="line.74"></a>
+<span class="sourceLineNo">075</span>    private int countData = 0;<a name="line.75"></a>
+<span class="sourceLineNo">076</span>    private long sizeData = 0;<a name="line.76"></a>
+<span class="sourceLineNo">077</span>    private final String filename;<a name="line.77"></a>
+<span class="sourceLineNo">078</span><a name="line.78"></a>
+<span class="sourceLineNo">079</span>    CachedBlockCountsPerFile(final String filename) {<a name="line.79"></a>
+<span class="sourceLineNo">080</span>      this.filename = filename;<a name="line.80"></a>
+<span class="sourceLineNo">081</span>    }<a name="line.81"></a>
+<span class="sourceLineNo">082</span><a name="line.82"></a>
+<span class="sourceLineNo">083</span>    public int getCount() {<a name="line.83"></a>
+<span class="sourceLineNo">084</span>      return count;<a name="line.84"></a>
+<span class="sourceLineNo">085</span>    }<a name="line.85"></a>
+<span class="sourceLineNo">086</span><a name="line.86"></a>
+<span class="sourceLineNo">087</span>    public long getSize() {<a name="line.87"></a>
+<span class="sourceLineNo">088</span>      return size;<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>    public int getCountData() {<a name="line.91"></a>
+<span class="sourceLineNo">092</span>      return countData;<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>    public long getSizeData() {<a name="line.95"></a>
+<span class="sourceLineNo">096</span>      return sizeData;<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>    public String getFilename() {<a name="line.99"></a>
+<span class="sourceLineNo">100</span>      return filename;<a name="line.100"></a>
+<span class="sourceLineNo">101</span>    }<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>  /**<a name="line.104"></a>
+<span class="sourceLineNo">105</span>   * @param filename<a name="line.105"></a>
+<span class="sourceLineNo">106</span>   * @param blocks<a name="line.106"></a>
+<span class="sourceLineNo">107</span>   * @return A JSON String of &lt;code&gt;filename&lt;/code&gt; and counts of &lt;code&gt;blocks&lt;/code&gt;<a name="line.107"></a>
+<span class="sourceLineNo">108</span>   * @throws JsonGenerationException<a name="line.108"></a>
+<span class="sourceLineNo">109</span>   * @throws JsonMappingException<a name="line.109"></a>
+<span class="sourceLineNo">110</span>   * @throws IOException<a name="line.110"></a>
+<span class="sourceLineNo">111</span>   */<a name="line.111"></a>
+<span class="sourceLineNo">112</span>  public static String toJSON(final String filename, final NavigableSet&lt;CachedBlock&gt; blocks)<a name="line.112"></a>
+<span class="sourceLineNo">113</span>  throws JsonGenerationException, JsonMappingException, IOException {<a name="line.113"></a>
+<span class="sourceLineNo">114</span>    CachedBlockCountsPerFile counts = new CachedBlockCountsPerFile(filename);<a name="line.114"></a>
+<span class="sourceLineNo">115</span>    for (CachedBlock cb: blocks) {<a name="line.115"></a>
+<span class="sourceLineNo">116</span>      counts.count++;<a name="line.116"></a>
+<span class="sourceLineNo">117</span>      counts.size += cb.getSize();<a name="line.117"></a>
+<span class="sourceLineNo">118</span>      BlockType bt = cb.getBlockType();<a name="line.118"></a>
+<span class="sourceLineNo">119</span>      if (bt != null &amp;&amp; bt.isData()) {<a name="line.119"></a>
+<span class="sourceLineNo">120</span>        counts.countData++;<a name="line.120"></a>
+<span class="sourceLineNo">121</span>        counts.sizeData += cb.getSize();<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>    return MAPPER.writeValueAsString(counts);<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>  /**<a name="line.127"></a>
+<span class="sourceLineNo">128</span>   * @param cbsbf<a name="line.128"></a>
+<span class="sourceLineNo">129</span>   * @return JSON string of &lt;code&gt;cbsf&lt;/code&gt; aggregated<a name="line.129"></a>
+<span class="sourceLineNo">130</span>   * @throws JsonGenerationException<a name="line.130"></a>
+<span class="sourceLineNo">131</span>   * @throws JsonMappingException<a name="line.131"></a>
+<span class="sourceLineNo">132</span>   * @throws IOException<a name="line.132"></a>
+<span class="sourceLineNo">133</span>   */<a name="line.133"></a>
+<span class="sourceLineNo">134</span>  public static String toJSON(final CachedBlocksByFile cbsbf)<a name="line.134"></a>
+<span class="sourceLineNo">135</span>  throws JsonGenerationException, JsonMappingException, IOException {<a name="line.135"></a>
+<span class="sourceLineNo">136</span>    return MAPPER.writeValueAsString(cbsbf);<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>   * @param bc<a name="line.140"></a>
+<span class="sourceLineNo">141</span>   * @return JSON string of &lt;code&gt;bc&lt;/code&gt; content.<a name="line.141"></a>
+<span class="sourceLineNo">142</span>   * @throws JsonGenerationException<a name="line.142"></a>
+<span class="sourceLineNo">143</span>   * @throws JsonMappingException<a name="line.143"></a>
+<span class="sourceLineNo">144</span>   * @throws IOException<a name="line.144"></a>
+<span class="sourceLineNo">145</span>   */<a name="line.145"></a>
+<span class="sourceLineNo">146</span>  public static String toJSON(final BlockCache bc)<a name="line.146"></a>
+<span class="sourceLineNo">147</span>  throws JsonGenerationException, JsonMappingException, IOException {<a name="line.147"></a>
+<span class="sourceLineNo">148</span>    return MAPPER.writeValueAsString(bc);<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 name="line.151"></a>
+<span class="sourceLineNo">152</span>   * @param cb<a name="line.152"></a>
+<span class="sourceLineNo">153</span>   * @return The block content of &lt;code&gt;bc&lt;/code&gt; as a String minus the filename.<a name="line.153"></a>
+<span class="sourceLineNo">154</span>   */<a name="line.154"></a>
+<span class="sourceLineNo">155</span>  public static String toStringMinusFileName(final CachedBlock cb, final long now) {<a name="line.155"></a>
+<span class="sourceLineNo">156</span>    return "offset=" + cb.getOffset() +<a name="line.156"></a>
+<span class="sourceLineNo">157</span>      ", size=" + cb.getSize() +<a name="line.157"></a>
+<span class="sourceLineNo">158</span>      ", age=" + (now - cb.getCachedTime()) +<a name="line.158"></a>
+<span class="sourceLineNo">159</span>      ", type=" + cb.getBlockType() +<a name="line.159"></a>
+<span class="sourceLineNo">160</span>      ", priority=" + cb.getBlockPriority();<a name="line.160"></a>
+<span class="sourceLineNo">161</span>  }<a name="line.161"></a>
+<span class="sourceLineNo">162</span><a name="line.162"></a>
+<span class="sourceLineNo">163</span>  /**<a name="line.163"></a>
+<span class="sourceLineNo">164</span>   * Get a {@link CachedBlocksByFile} instance and load it up by iterating content in<a name="line.164"></a>
+<span class="sourceLineNo">165</span>   * {@link BlockCache}.<a name="line.165"></a>
+<span class="sourceLineNo">166</span>   * @param conf Used to read configurations<a name="line.166"></a>
+<span class="sourceLineNo">167</span>   * @param bc Block Cache to iterate.<a name="line.167"></a>
+<span class="sourceLineNo">168</span>   * @return Laoded up instance of CachedBlocksByFile<a name="line.168"></a>
+<span class="sourceLineNo">169</span>   */<a name="line.169"></a>
+<span class="sourceLineNo">170</span>  public static CachedBlocksByFile getLoadedCachedBlocksByFile(final Configuration conf,<a name="line.170"></a>
+<span class="sourceLineNo">171</span>      final BlockCache bc) {<a name="line.171"></a>
+<span class="sourceLineNo">172</span>    CachedBlocksByFile cbsbf = new CachedBlocksByFile(conf);<a name="line.172"></a>
+<span class="sourceLineNo">173</span>    for (CachedBlock cb: bc) {<a name="line.173"></a>
+<span class="sourceLineNo">174</span>      if (cbsbf.update(cb)) break;<a name="line.174"></a>
+<span class="sourceLineNo">175</span>    }<a name="line.175"></a>
+<span class="sourceLineNo">176</span>    return cbsbf;<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>  private static int compareCacheBlock(Cacheable left, Cacheable right,<a name="line.179"></a>
+<span class="sourceLineNo">180</span>                                       boolean includeNextBlockMetadata) {<a name="line.180"></a>
+<span class="sourceLineNo">181</span>    ByteBuffer l = ByteBuffer.allocate(left.getSerializedLength());<a name="line.181"></a>
+<span class="sourceLineNo">182</span>    left.serialize(l, includeNextBlockMetadata);<a name="line.182"></a>
+<span class="sourceLineNo">183</span>    ByteBuffer r = ByteBuffer.allocate(right.getSerializedLength());<a name="line.183"></a>
+<span class="sourceLineNo">184</span>    right.serialize(r, includeNextBlockMetadata);<a name="line.184"></a>
+<span class="sourceLineNo">185</span>    return Bytes.compareTo(l.array(), l.arrayOffset(), l.limit(),<a name="line.185"></a>
+<span class="sourceLineNo">186</span>        r.array(), r.arrayOffset(), r.limit());<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>   * Validate that the existing and newBlock are the same without including the nextBlockMetadata,<a name="line.190"></a>
+<span class="sourceLineNo">191</span>   * if not, throw an exception. If they are the same without the nextBlockMetadata,<a name="line.191"></a>
+<span class="sourceLineNo">192</span>   * return the comparison.<a name="line.192"></a>
+<span class="sourceLineNo">193</span>   *<a name="line.193"></a>
+<span class="sourceLineNo">194</span>   * @param existing block that is existing in the cache.<a name="line.194"></a>
+<span class="sourceLineNo">195</span>   * @param newBlock block that is trying to be cached.<a name="line.195"></a>
+<span class="sourceLineNo">196</span>   * @param cacheKey the cache key of the blocks.<a name="line.196"></a>
+<span class="sourceLineNo">197</span>   * @return comparison of the existing block to the newBlock.<a name="line.197"></a>
+<span class="sourceLineNo">198</span>   */<a name="line.198"></a>
+<span class="sourceLineNo">199</span>  public static int validateBlockAddition(Cacheable existing, Cacheable newBlock,<a name="line.199"></a>
+<span class="sourceLineNo">200</span>                                          BlockCacheKey cacheKey) {<a name="line.200"></a>
+<span class="sourceLineNo">201</span>    int comparison = compareCacheBlock(existing, newBlock, true);<a name="line.201"></a>
+<span class="sourceLineNo">202</span>    if (comparison != 0) {<a name="line.202"></a>
+<span class="sourceLineNo">203</span>      LOG.warn("Cached block contents differ, trying to just compare the block contents " +<a name="line.203"></a>
+<span class="sourceLineNo">204</span>          "without the next block. CacheKey: " + cacheKey);<a name="line.204"></a>
+<span class="sourceLineNo">205</span><a name="line.205"></a>
+<span class="sourceLineNo">206</span>      // compare the contents, if they are not equal, we are in big trouble<a name="line.206"></a>
+<span class="sourceLineNo">207</span>      int comparisonWithoutNextBlockMetadata = compareCacheBlock(existing, newBlock, false);<a name="line.207"></a>
+<span class="sourceLineNo">208</span><a name="line.208"></a>
+<span class="sourceLineNo">209</span>      if (comparisonWithoutNextBlockMetadata != 0) {<a name="line.209"></a>
+<span class="sourceLineNo">210</span>        throw new RuntimeException("Cached block contents differ, which should not have happened."<a name="line.210"></a>
+<span class="sourceLineNo">211</span>            + "cacheKey:" + cacheKey);<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>    /**<a name="line.215"></a>
-<span class="sourceLineNo">216</span>     * Map by filename. use concurent utils because we want our Map and contained blocks sorted.<a name="line.216"></a>
-<span class="sourceLineNo">217</span>     */<a name="line.217"></a>
-<span class="sourceLineNo">218</span>    private NavigableMap&lt;String, NavigableSet&lt;CachedBlock&gt;&gt; cachedBlockByFile = new ConcurrentSkipListMap&lt;&gt;();<a name="line.218"></a>
-<span class="sourceLineNo">219</span>    FastLongHistogram hist = new FastLongHistogram();<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>     * @param cb<a name="line.222"></a>
-<span class="sourceLineNo">223</span>     * @return True if full.... if we won't be adding any more.<a name="line.223"></a>
-<span class="sourceLineNo">224</span>     */<a name="line.224"></a>
-<span class="sourceLineNo">225</span>    public boolean update(final CachedBlock cb) {<a name="line.225"></a>
-<span class="sourceLineNo">226</span>      if (isFull()) return true;<a name="line.226"></a>
-<span class="sourceLineNo">227</span>      NavigableSet&lt;CachedBlock&gt; set = this.cachedBlockByFile.get(cb.getFilename());<a name="line.227"></a>
-<span class="sourceLineNo">228</span>      if (set == null) {<a name="line.228"></a>
-<span class="sourceLineNo">229</span>        set = new ConcurrentSkipListSet&lt;&gt;();<a name="line.229"></a>
-<span class="sourceLineNo">230</span>        this.cachedBlockByFile.put(cb.getFilename(), set);<a name="line.230"></a>
-<span class="sourceLineNo">231</span>      }<a name="line.231"></a>
-<span class="sourceLineNo">232</span>      set.add(cb);<a name="line.232"></a>
-<span class="sourceLineNo">233</span>      this.size += cb.getSize();<a name="line.233"></a>
-<span class="sourceLineNo">234</span>      this.count++;<a name="line.234"></a>
-<span class="sourceLineNo">235</span>      BlockType bt = cb.getBlockType();<a name="line.235"></a>
-<span class="sourceLineNo">236</span>      if (bt != null &amp;&amp; bt.isData()) {<a name="line.236"></a>
-<span class="sourceLineNo">237</span>        this.dataBlockCount++;<a name="line.237"></a>
-<span class="sourceLineNo">238</span>        this.dataSize += cb.getSize();<a name="line.238"></a>
-<span class="sourceLineNo">239</span>      }<a name="line.239"></a>
-<span class="sourceLineNo">240</span>      long age = (this.now - cb.getCachedTime())/NANOS_PER_SECOND;<a name="line.240"></a>
-<span class="sourceLineNo">241</span>      this.hist.add(age, 1);<a name="line.241"></a>
-<span class="sourceLineNo">242</span>      return false;<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>    /**<a name="line.245"></a>
-<span class="sourceLineNo">246</span>     * @return True if full; i.e. there are more items in the cache but we only loaded up<a name="line.246"></a>
-<span class="sourceLineNo">247</span>     * the maximum set in configuration &lt;code&gt;hbase.ui.blockcache.by.file.max&lt;/code&gt;<a name="line.247"></a>
-<span class="sourceLineNo">248</span>     * (Default: DEFAULT_MAX).<a name="line.248"></a>
+<span class="sourceLineNo">214</span>    return comparison;<a name="line.214"></a>
+<span class="sourceLineNo">215</span>  }<a name="line.215"></a>
+<span class="sourceLineNo">216</span><a name="line.216"></a>
+<span class="sourceLineNo">217</span>  /**<a name="line.217"></a>
+<span class="sourceLineNo">218</span>   * Use one of these to keep a running account of cached blocks by file.  Throw it away when done.<a name="line.218"></a>
+<span class="sourceLineNo">219</span>   * This is different than metrics in that it is stats on current state of a cache.<a name="line.219"></a>
+<span class="sourceLineNo">220</span>   * See getLoadedCachedBlocksByFile<a name="line.220"></a>
+<span class="sourceLineNo">221</span>   */<a name="line.221"></a>
+<span class="sourceLineNo">222</span>  @JsonIgnoreProperties({"cachedBlockStatsByFile"})<a name="line.222"></a>
+<span class="sourceLineNo">223</span>  public static class CachedBlocksByFile {<a name="line.223"></a>
+<span class="sourceLineNo">224</span>    private int count;<a name="line.224"></a>
+<span class="sourceLineNo">225</span>    private int dataBlockCount;<a name="line.225"></a>
+<span class="sourceLineNo">226</span>    private long size;<a name="line.226"></a>
+<span class="sourceLineNo">227</span>    private long dataSize;<a name="line.227"></a>
+<span class="sourceLineNo">228</span>    private final long now = System.nanoTime();<a name="line.228"></a>
+<span class="sourceLineNo">229</span>    /**<a name="line.229"></a>
+<span class="sourceLineNo">230</span>     * How many blocks to look at before we give up.<a name="line.230"></a>
+<span class="sourceLineNo">231</span>     * There could be many millions of blocks. We don't want the<a name="line.231"></a>
+<span class="sourceLineNo">232</span>     * ui to freeze while we run through 1B blocks... users will<a name="line.232"></a>
+<span class="sourceLineNo">233</span>     * think hbase dead. UI displays warning in red when stats<a name="line.233"></a>
+<span class="sourceLineNo">234</span>     * are incomplete.<a name="line.234"></a>
+<span class="sourceLineNo">235</span>     */<a name="line.235"></a>
+<span class="sourceLineNo">236</span>    private final int max;<a name="line.236"></a>
+<span class="sourceLineNo">237</span>    public static final int DEFAULT_MAX = 1000000;<a name="line.237"></a>
+<span class="sourceLineNo">238</span><a name="line.238"></a>
+<span class="sourceLineNo">239</span>    CachedBlocksByFile() {<a name="line.239"></a>
+<span class="sourceLineNo">240</span>      this(null);<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>    CachedBlocksByFile(final Configuration c) {<a name="line.243"></a>
+<span class="sourceLineNo">244</span>      this.max = c == null? DEFAULT_MAX: c.getInt("hbase.ui.blockcache.by.file.max", DEFAULT_MAX);<a name="line.244"></a>
+<span class="sourceLineNo">245</span>    }<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>     * Map by filename. use concurent utils because we want our Map and contained blocks sorted.<a name="line.248"></a>
 <span class="sourceLineNo">249</span>     */<a name="line.249"></a>
-<span class="sourceLineNo">250</span>    public boolean isFull() {<a name="line.250"></a>
-<span class="sourceLineNo">251</span>      return this.count &gt;= this.max;<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 NavigableMap&lt;String, NavigableSet&lt;CachedBlock&gt;&gt; getCachedBlockStatsByFile() {<a name="line.254"></a>
-<span class="sourceLineNo">255</span>      return this.cachedBlockByFile;<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 count of blocks in the cache<a name="line.259"></a>
-<span class="sourceLineNo">260</span>     */<a name="line.260"></a>
-<span class="sourceLineNo">261</span>    public int getCount() {<a name="line.261"></a>
-<span class="sourceLineNo">262</span>      return count;<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>    public int getDataCount() {<a name="line.265"></a>
-<span class="sourceLineNo">266</span>      return dataBlockCount;<a name="line.266"></a>
-<span class="sourceLineNo">267</span>    }<a name="line.267"></a>
-<span class="sourceLineNo">268</span><a name="line.268"></a>
-<span class="sourceLineNo">269</span>    /**<a name="line.269"></a>
-<span class="sourceLineNo">270</span>     * @return size of blocks in the cache<a name="line.270"></a>
-<span class="sourceLineNo">271</span>     */<a name="line.271"></a>
-<span class="sourceLineNo">272</span>    public long getSize() {<a name="line.272"></a>
-<span class="sourceLineNo">273</span>      return size;<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>     * @return Size of data.<a name="line.277"></a>
-<span class="sourceLineNo">278</span>     */<a name="line.278"></a>
-<span class="sourceLineNo">279</span>    public long getDataSize() {<a name="line.279"></a>
-<span class="sourceLineNo">280</span>      return dataSize;<a name="line.280"></a>
-<span class="sourceLineNo">281</span>    }<a name="line.281"></a>
-<span class="sourceLineNo">282</span><a name="line.282"></a>
-<span class="sourceLineNo">283</span>    public AgeSnapshot getAgeInCacheSnapshot() {<a name="line.283"></a>
-<span class="sourceLineNo">284</span>      return new AgeSnapshot(this.hist);<a name="line.284"></a>
-<span class="sourceLineNo">285</span>    }<a name="line.285"></a>
-<span class="sourceLineNo">286</span><a name="line.286"></a>
-<span class="sourceLineNo">287</span>    @Override<a name="line.287"></a>
-<span class="sourceLineNo">288</span>    public String toString() {<a name="line.288"></a>
-<span class="sourceLineNo">289</span>      AgeSnapshot snapshot = getAgeInCacheSnapshot();<a name="line.289"></a>
-<span class="sourceLineNo">290</span>      return "count=" + count + ", dataBlockCount=" + dataBlockCount + ", size=" + size +<a name="line.290"></a>
-<span class="sourceLineNo">291</span>          ", dataSize=" + getDataSize() +<a name="line.291"></a>
-<span class="sourceLineNo">292</span>          ", mean age=" + snapshot.getMean() +<a name="line.292"></a>
-<span class="sourceLineNo">293</span>          ", min age=" + snapshot.getMin() +<a name="line.293"></a>
-<span class="sourceLineNo">294</span>          ", max age=" + snapshot.getMax() +<a name="line.294"></a>
-<span class="sourceLineNo">295</span>          ", 75th percentile age="   + snapshot.get75thPercentile() +<a name="line.295"></a>
-<span class="sourceLineNo">296</span>          ", 95th percentile age="   + snapshot.get95thPercentile() +<a name="line.296"></a>
-<span class="sourceLineNo">297</span>          ", 98th percentile age="   + snapshot.get98thPercentile() +<a name="line.297"></a>
-<span class="sourceLineNo">298</span>          ", 99th percentile age="   + snapshot.get99thPercentile() +<a name="line.298"></a>
-<span class="sourceLineNo">299</span>          ", 99.9th percentile age=" + snapshot.get99thPercentile();<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">250</span>    private NavigableMap&lt;String, NavigableSet&lt;CachedBlock&gt;&gt; cachedBlockByFile = new ConcurrentSkipListMap&lt;&gt;();<a name="line.250"></a>
+<span class="sourceLineNo">251</span>    FastLongHistogram hist = new FastLongHistogram();<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>     * @param cb<a name="line.254"></a>
+<span class="sourceLineNo">255</span>     * @return True if full.... if we won't be adding any more.<a name="line.255"></a>
+<span class="sourceLineNo">256</span>     */<a name="line.256"></a>
+<span class="sourceLineNo">257</span>    public boolean update(final CachedBlock cb) {<a name="line.257"></a>
+<span class="sourceLineNo">258</span>      if (isFull()) return true;<a name="line.258"></a>
+<span class="sourceLineNo">259</span>      NavigableSet&lt;CachedBlock&gt; set = this.cachedBlockByFile.get(cb.getFilename());<a name="line.259"></a>
+<span class="sourceLineNo">260</span>      if (set == null) {<a name="line.260"></a>
+<span class="sourceLineNo">261</span>        set = new ConcurrentSkipListSet&lt;&gt;();<a name="line.261"></a>
+<span class="sourceLineNo">262</span>        this.cachedBlockByFile.put(cb.getFilename(), set);<a name="line.262"></a>
+<span class="sourceLineNo">263</span>      }<a name="line.263"></a>
+<span class="sourceLineNo">264</span>      set.add(cb);<a name="line.264"></a>
+<span class="sourceLineNo">265</span>      this.size += cb.getSize();<a name="line.265"></a>
+<span class="sourceLineNo">266</span>      this.count++;<a name="line.266"></a>
+<span class="sourceLineNo">267</span>      BlockType bt = cb.getBlockType();<a name="line.267"></a>
+<span class="sourceLineNo">268</span>      if (bt != null &amp;&amp; bt.isData()) {<a name="line.268"></a>
+<span class="sourceLineNo">269</span>        this.dataBlockCount++;<a name="line.269"></a>
+<span class="sourceLineNo">270</span>        this.dataSize += cb.getSize();<a name="line.270"></a>
+<span class="sourceLineNo">271</span>      }<a name="line.271"></a>
+<span class="sourceLineNo">272</span>      long age = (this.now - cb.getCachedTime())/NANOS_PER_SECOND;<a name="line.272"></a>
+<span class="sourceLineNo">273</span>      this.hist.add(age, 1);<a name="line.273"></a>
+<span class="sourceLineNo">274</span>      return false;<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>     * @return True if full; i.e. there are more items in the cache but we only loaded up<a name="line.278"></a>
+<span class="sourceLineNo">279</span>     * the maximum set in configuration &lt;code&gt;hbase.ui.blockcache.by.file.max&lt;/code&gt;<a name="line.279"></a>
+<span class="sourceLineNo">280</span>     * (Default: DEFAULT_MAX).<a name="line.280"></a>
+<span class="sourceLineNo">281</span>     */<a name="line.281"></a>
+<span class="sourceLineNo">282</span>    public boolean isFull() {<a name="line.282"></a>
+<span class="sourceLineNo">283</span>      return this.count &gt;= this.max;<a name="line.283"></a>
+<span class="sourceLineNo">284</span>    }<a name="line.284"></a>
+<span class="sourceLineNo">285</span><a name="line.285"></a>
+<span class="sourceLineNo">286</span>    public NavigableMap&lt;String, NavigableSet&lt;CachedBlock&gt;&gt; getCachedBlockStatsByFile() {<a name="line.286"></a>
+<span class="sourceLineNo">287</span>      return this.cachedBlockByFile;<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>    /**<a name="line.290"></a>
+<span class="sourceLineNo">291</span>     * @return count of blocks in the cache<a name="line.291"></a>
+<span class="sourceLineNo">292</span>     */<a name="line.292"></a>
+<span class="sourceLineNo">293</span>    public int getCount() {<a name="line.293"></a>
+<span class="sourceLineNo">294</span>      return count;<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 int getDataCount() {<a name="line.297"></a>
+<span class="sourceLineNo">298</span>      return dataBlockCount;<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>     * @return size of blocks in the cache<a name="line.302"></a>
+<span class="sourceLineNo">303</span>     */<a name="line.303"></a>
+<span class="sourceLineNo">304</span>    public long getSize() {<a name="line.304"></a>
+<span class="sourceLineNo">305</span>      return size;<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>     * @return Size of data.<a name="line.309"></a>
+<span class="sourceLineNo">310</span>     */<a name="line.310"></a>
+<span class="sourceLineNo">311</span>    public long getDataSize() {<a name="line.311"></a>
+<span class="sourceLineNo">312</span>      return dataSize;<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>    public AgeSnapshot getAgeInCacheSnapshot() {<a name="line.315"></a>
+<span class="sourceLineNo">316</span>      return new AgeSnapshot(this.hist);<a name="line.316"></a>
+<span class="sourceLineNo">317</span>    }<a name="line.317"></a>
+<span class="sourceLineNo">318</span><a name="line.318"></a>
+<span class="sourceLineNo">319</span>    @Override<a name="line.319"></a>
+<span class="sourceLineNo">320</span>    public String toString() {<a name="line.320"></a>
+<span class="sourceLineNo">321</span>      AgeSnapshot snapshot = getAgeInCacheSnapshot();<a name="line.321"></a>
+<span class="sourceLineNo">322</span>      return "count=" + count + ", dataBlockCount=" + dataBlockCount + ", size=" + size +<a name="line.322"></a>
+<span class="sourceLineNo">323</span>          ", dataSize=" + getDataSize() +<a name="line.323"></a>
+<span class="sourceLineNo">324</span>          ", mean age=" + snapshot.getMean() +<a name="line.324"></a>
+<span class="sourceLineNo">325</span>          ", min age=" + snapshot.getMin() +<a name="line.325"></a>
+<span class="sourceLineNo">326</span>          ", max age=" + snapshot.getMax() +<a name="line.326"></a>
+<span class="sourceLineNo">327</span>          ", 75th percentile age="   + snapshot.get75thPercentile() +<a name="line.327"></a>
+<span class="sourceLineNo">328</span>          ", 95th percentile age="   + snapshot.get95thPercentile() +<a name="line.328"></a>
+<span class="sourceLineNo">329</span>          ", 98th percentile age="   + snapshot.get98thPercentile() +<a name="line.329"></a>
+<span class="sourceLineNo">330</span>          ", 99th percentile age="   + snapshot.get99thPercentile() +<a name="line.330"></a>
+<span class="sourceLineNo">331</span>          ", 99.9th percentile age=" + snapshot.get99thPercentile();<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>
 
 
 


[45/50] hbase-site git commit: Published site at 26babcf013de696b899d76a3c39434b794440d8d.

Posted by gi...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html b/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html
index 9b25d3b..11df7d7 100644
--- a/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html
+++ b/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html
@@ -1523,7 +1523,7 @@ implements <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockC
 <ul class="blockList">
 <li class="blockList">
 <h4>getBlock</h4>
-<pre>public&nbsp;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html" title="interface in org.apache.hadoop.hbase.io.hfile">Cacheable</a>&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.484">getBlock</a>(<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a>&nbsp;key,
+<pre>public&nbsp;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html" title="interface in org.apache.hadoop.hbase.io.hfile">Cacheable</a>&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.491">getBlock</a>(<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a>&nbsp;key,
                           boolean&nbsp;caching,
                           boolean&nbsp;repeat,
                           boolean&nbsp;updateCacheMetrics)</pre>
@@ -1547,7 +1547,7 @@ implements <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockC
 <ul class="blockList">
 <li class="blockList">
 <h4>blockEvicted</h4>
-<pre>void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.543">blockEvicted</a>(<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a>&nbsp;cacheKey,
+<pre>void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.550">blockEvicted</a>(<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a>&nbsp;cacheKey,
                   <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketCache.BucketEntry</a>&nbsp;bucketEntry,
                   boolean&nbsp;decrementBlockNumber)</pre>
 </li>
@@ -1558,7 +1558,7 @@ implements <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockC
 <ul class="blockList">
 <li class="blockList">
 <h4>evictBlock</h4>
-<pre>public&nbsp;boolean&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.553">evictBlock</a>(<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a>&nbsp;cacheKey)</pre>
+<pre>public&nbsp;boolean&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.560">evictBlock</a>(<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a>&nbsp;cacheKey)</pre>
 <div class="block"><span class="descfrmTypeLabel">Description copied from interface:&nbsp;<code><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCache.html#evictBlock-org.apache.hadoop.hbase.io.hfile.BlockCacheKey-">BlockCache</a></code></span></div>
 <div class="block">Evict block from cache.</div>
 <dl>
@@ -1577,7 +1577,7 @@ implements <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockC
 <ul class="blockList">
 <li class="blockList">
 <h4>forceEvict</h4>
-<pre>private&nbsp;boolean&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.559">forceEvict</a>(<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a>&nbsp;cacheKey)</pre>
+<pre>private&nbsp;boolean&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.566">forceEvict</a>(<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a>&nbsp;cacheKey)</pre>
 </li>
 </ul>
 <a name="checkRamCache-org.apache.hadoop.hbase.io.hfile.BlockCacheKey-">
@@ -1586,7 +1586,7 @@ implements <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockC
 <ul class="blockList">
 <li class="blockList">
 <h4>checkRamCache</h4>
-<pre>private&nbsp;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketCache.RAMQueueEntry</a>&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.588">checkRamCache</a>(<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a>&nbsp;cacheKey)</pre>
+<pre>private&nbsp;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketCache.RAMQueueEntry</a>&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.595">checkRamCache</a>(<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a>&nbsp;cacheKey)</pre>
 </li>
 </ul>
 <a name="evictBlock-org.apache.hadoop.hbase.io.hfile.BlockCacheKey-boolean-">
@@ -1595,7 +1595,7 @@ implements <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockC
 <ul class="blockList">
 <li class="blockList">
 <h4>evictBlock</h4>
-<pre>public&nbsp;boolean&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.597">evictBlock</a>(<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a>&nbsp;cacheKey,
+<pre>public&nbsp;boolean&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.604">evictBlock</a>(<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a>&nbsp;cacheKey,
                           boolean&nbsp;deletedBlock)</pre>
 </li>
 </ul>
@@ -1605,7 +1605,7 @@ implements <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockC
 <ul class="blockList">
 <li class="blockList">
 <h4>logStats</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.662">logStats</a>()</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.669">logStats</a>()</pre>
 </li>
 </ul>
 <a name="getRealCacheSize--">
@@ -1614,7 +1614,7 @@ implements <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockC
 <ul class="blockList">
 <li class="blockList">
 <h4>getRealCacheSize</h4>
-<pre>public&nbsp;long&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.688">getRealCacheSize</a>()</pre>
+<pre>public&nbsp;long&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.695">getRealCacheSize</a>()</pre>
 </li>
 </ul>
 <a name="acceptableSize--">
@@ -1623,7 +1623,7 @@ implements <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockC
 <ul class="blockList">
 <li class="blockList">
 <h4>acceptableSize</h4>
-<pre>private&nbsp;long&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.692">acceptableSize</a>()</pre>
+<pre>private&nbsp;long&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.699">acceptableSize</a>()</pre>
 </li>
 </ul>
 <a name="getPartitionSize-float-">
@@ -1632,7 +1632,7 @@ implements <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockC
 <ul class="blockList">
 <li class="blockList">
 <h4>getPartitionSize</h4>
-<pre>long&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.697">getPartitionSize</a>(float&nbsp;partitionFactor)</pre>
+<pre>long&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.704">getPartitionSize</a>(float&nbsp;partitionFactor)</pre>
 </li>
 </ul>
 <a name="bucketSizesAboveThresholdCount-float-">
@@ -1641,7 +1641,7 @@ implements <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockC
 <ul class="blockList">
 <li class="blockList">
 <h4>bucketSizesAboveThresholdCount</h4>
-<pre>private&nbsp;int&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.704">bucketSizesAboveThresholdCount</a>(float&nbsp;minFactor)</pre>
+<pre>private&nbsp;int&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.711">bucketSizesAboveThresholdCount</a>(float&nbsp;minFactor)</pre>
 <div class="block">Return the count of bucketSizeinfos still need free space</div>
 </li>
 </ul>
@@ -1651,7 +1651,7 @@ implements <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockC
 <ul class="blockList">
 <li class="blockList">
 <h4>freeEntireBuckets</h4>
-<pre>private&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.726">freeEntireBuckets</a>(int&nbsp;completelyFreeBucketsNeeded)</pre>
+<pre>private&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.733">freeEntireBuckets</a>(int&nbsp;completelyFreeBucketsNeeded)</pre>
 <div class="block">This method will find the buckets that are minimally occupied
  and are not reference counted and will free them completely
  without any constraint on the access times of the elements,
@@ -1669,7 +1669,7 @@ implements <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockC
 <ul class="blockList">
 <li class="blockList">
 <h4>freeSpace</h4>
-<pre>private&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.754">freeSpace</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;why)</pre>
+<pre>private&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.761">freeSpace</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;why)</pre>
 <div class="block">Free the space if the used size reaches acceptableSize() or one size block
  couldn't be allocated. When freeing the space, we use the LRU algorithm and
  ensure there must be some blocks evicted</div>
@@ -1685,7 +1685,7 @@ implements <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockC
 <ul class="blockList">
 <li class="blockList">
 <h4>getRAMQueueEntries</h4>
-<pre>static&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html?is-external=true" title="class or interface in java.util">List</a>&lt;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketCache.RAMQueueEntry</a>&gt;&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1050">getRAMQueueEntries</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/BlockingQueue.html?is-external=true" title="class or interface in java.util.concurrent">BlockingQueue</a>&lt;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketCache.RAMQueueEntry</a>&gt;&nbsp;q,
+<pre>static&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html?is-external=true" title="class or interface in java.util">List</a>&lt;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketCache.RAMQueueEntry</a>&gt;&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1057">getRAMQueueEntries</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/BlockingQueue.html?is-external=true" title="class or interface in java.util.concurrent">BlockingQueue</a>&lt;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketCache.RAMQueueEntry</a>&gt;&nbsp;q,
                                                           <a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html?is-external=true" title="class or interface in java.util">List</a>&lt;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketCache.RAMQueueEntry</a>&gt;&nbsp;receptacle)
                                                    throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/InterruptedException.html?is-external=true" title="class or interface in java.lang">InterruptedException</a></pre>
 <div class="block">Blocks until elements available in <code>q</code> then tries to grab as many as possible
@@ -1708,7 +1708,7 @@ implements <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockC
 <ul class="blockList">
 <li class="blockList">
 <h4>persistToFile</h4>
-<pre>private&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1061">persistToFile</a>()
+<pre>private&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1068">persistToFile</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>
@@ -1722,7 +1722,7 @@ implements <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockC
 <ul class="blockList">
 <li class="blockList">
 <h4>retrieveFromFile</h4>
-<pre>private&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1083">retrieveFromFile</a>(int[]&nbsp;bucketSizes)
+<pre>private&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1090">retrieveFromFile</a>(int[]&nbsp;bucketSizes)
                        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="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocatorException.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketAllocatorException</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>
@@ -1740,7 +1740,7 @@ implements <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockC
 <ul class="blockList">
 <li class="blockList">
 <h4>checkIOErrorIsTolerated</h4>
-<pre>private&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1135">checkIOErrorIsTolerated</a>()</pre>
+<pre>private&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1142">checkIOErrorIsTolerated</a>()</pre>
 <div class="block">Check whether we tolerate IO error this time. If the duration of IOEngine
  throwing errors exceeds ioErrorsDurationTimeTolerated, we will disable the
  cache</div>
@@ -1752,7 +1752,7 @@ implements <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockC
 <ul class="blockList">
 <li class="blockList">
 <h4>disableCache</h4>
-<pre>private&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1151">disableCache</a>()</pre>
+<pre>private&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1158">disableCache</a>()</pre>
 <div class="block">Used to shut down the cache -or- turn it off in the case of something broken.</div>
 </li>
 </ul>
@@ -1762,7 +1762,7 @@ implements <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockC
 <ul class="blockList">
 <li class="blockList">
 <h4>join</h4>
-<pre>private&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1164">join</a>()
+<pre>private&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1171">join</a>()
            throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/InterruptedException.html?is-external=true" title="class or interface in java.lang">InterruptedException</a></pre>
 <dl>
 <dt><span class="throwsLabel">Throws:</span></dt>
@@ -1776,7 +1776,7 @@ implements <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockC
 <ul class="blockList">
 <li class="blockList">
 <h4>shutdown</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1170">shutdown</a>()</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1177">shutdown</a>()</pre>
 <div class="block"><span class="descfrmTypeLabel">Description copied from interface:&nbsp;<code><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCache.html#shutdown--">BlockCache</a></code></span></div>
 <div class="block">Shutdown the cache.</div>
 <dl>
@@ -1791,7 +1791,7 @@ implements <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockC
 <ul class="blockList">
 <li class="blockList">
 <h4>getStats</h4>
-<pre>public&nbsp;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/CacheStats.html" title="class in org.apache.hadoop.hbase.io.hfile">CacheStats</a>&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1187">getStats</a>()</pre>
+<pre>public&nbsp;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/CacheStats.html" title="class in org.apache.hadoop.hbase.io.hfile">CacheStats</a>&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1194">getStats</a>()</pre>
 <div class="block"><span class="descfrmTypeLabel">Description copied from interface:&nbsp;<code><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCache.html#getStats--">BlockCache</a></code></span></div>
 <div class="block">Get the statistics for this block cache.</div>
 <dl>
@@ -1808,7 +1808,7 @@ implements <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockC
 <ul class="blockList">
 <li class="blockList">
 <h4>getAllocator</h4>
-<pre>public&nbsp;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketAllocator</a>&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1191">getAllocator</a>()</pre>
+<pre>public&nbsp;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketAllocator</a>&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1198">getAllocator</a>()</pre>
 </li>
 </ul>
 <a name="heapSize--">
@@ -1817,7 +1817,7 @@ implements <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockC
 <ul class="blockList">
 <li class="blockList">
 <h4>heapSize</h4>
-<pre>public&nbsp;long&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1196">heapSize</a>()</pre>
+<pre>public&nbsp;long&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1203">heapSize</a>()</pre>
 <dl>
 <dt><span class="overrideSpecifyLabel">Specified by:</span></dt>
 <dd><code><a href="../../../../../../../org/apache/hadoop/hbase/io/HeapSize.html#heapSize--">heapSize</a></code>&nbsp;in interface&nbsp;<code><a href="../../../../../../../org/apache/hadoop/hbase/io/HeapSize.html" title="interface in org.apache.hadoop.hbase.io">HeapSize</a></code></dd>
@@ -1833,7 +1833,7 @@ implements <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockC
 <ul class="blockList">
 <li class="blockList">
 <h4>size</h4>
-<pre>public&nbsp;long&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1201">size</a>()</pre>
+<pre>public&nbsp;long&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1208">size</a>()</pre>
 <div class="block"><span class="descfrmTypeLabel">Description copied from interface:&nbsp;<code><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCache.html#size--">BlockCache</a></code></span></div>
 <div class="block">Returns the total size of the block cache, in bytes.</div>
 <dl>
@@ -1850,7 +1850,7 @@ implements <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockC
 <ul class="blockList">
 <li class="blockList">
 <h4>getCurrentDataSize</h4>
-<pre>public&nbsp;long&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1206">getCurrentDataSize</a>()</pre>
+<pre>public&nbsp;long&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1213">getCurrentDataSize</a>()</pre>
 <div class="block"><span class="descfrmTypeLabel">Description copied from interface:&nbsp;<code><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCache.html#getCurrentDataSize--">BlockCache</a></code></span></div>
 <div class="block">Returns the occupied size of data blocks, in bytes.</div>
 <dl>
@@ -1867,7 +1867,7 @@ implements <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockC
 <ul class="blockList">
 <li class="blockList">
 <h4>getFreeSize</h4>
-<pre>public&nbsp;long&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1211">getFreeSize</a>()</pre>
+<pre>public&nbsp;long&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1218">getFreeSize</a>()</pre>
 <div class="block"><span class="descfrmTypeLabel">Description copied from interface:&nbsp;<code><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCache.html#getFreeSize--">BlockCache</a></code></span></div>
 <div class="block">Returns the free size of the block cache, in bytes.</div>
 <dl>
@@ -1884,7 +1884,7 @@ implements <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockC
 <ul class="blockList">
 <li class="blockList">
 <h4>getBlockCount</h4>
-<pre>public&nbsp;long&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1216">getBlockCount</a>()</pre>
+<pre>public&nbsp;long&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1223">getBlockCount</a>()</pre>
 <div class="block"><span class="descfrmTypeLabel">Description copied from interface:&nbsp;<code><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCache.html#getBlockCount--">BlockCache</a></code></span></div>
 <div class="block">Returns the number of blocks currently cached in the block cache.</div>
 <dl>
@@ -1901,7 +1901,7 @@ implements <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockC
 <ul class="blockList">
 <li class="blockList">
 <h4>getDataBlockCount</h4>
-<pre>public&nbsp;long&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1221">getDataBlockCount</a>()</pre>
+<pre>public&nbsp;long&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1228">getDataBlockCount</a>()</pre>
 <div class="block"><span class="descfrmTypeLabel">Description copied from interface:&nbsp;<code><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCache.html#getDataBlockCount--">BlockCache</a></code></span></div>
 <div class="block">Returns the number of data blocks currently cached in the block cache.</div>
 <dl>
@@ -1918,7 +1918,7 @@ implements <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockC
 <ul class="blockList">
 <li class="blockList">
 <h4>getCurrentSize</h4>
-<pre>public&nbsp;long&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1226">getCurrentSize</a>()</pre>
+<pre>public&nbsp;long&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1233">getCurrentSize</a>()</pre>
 <div class="block"><span class="descfrmTypeLabel">Description copied from interface:&nbsp;<code><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCache.html#getCurrentSize--">BlockCache</a></code></span></div>
 <div class="block">Returns the occupied size of the block cache, in bytes.</div>
 <dl>
@@ -1935,7 +1935,7 @@ implements <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockC
 <ul class="blockList">
 <li class="blockList">
 <h4>evictBlocksByHfileName</h4>
-<pre>public&nbsp;int&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1238">evictBlocksByHfileName</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;hfileName)</pre>
+<pre>public&nbsp;int&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1245">evictBlocksByHfileName</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;hfileName)</pre>
 <div class="block">Evicts all blocks for a specific HFile.
  <p>
  This is used for evict-on-close to remove all blocks of a specific HFile.</div>
@@ -1953,7 +1953,7 @@ implements <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockC
 <ul class="blockList">
 <li class="blockList">
 <h4>stopWriterThreads</h4>
-<pre>void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1526">stopWriterThreads</a>()
+<pre>void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1533">stopWriterThreads</a>()
                 throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/InterruptedException.html?is-external=true" title="class or interface in java.lang">InterruptedException</a></pre>
 <div class="block">Only used in test</div>
 <dl>
@@ -1968,7 +1968,7 @@ implements <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockC
 <ul class="blockList">
 <li class="blockList">
 <h4>iterator</h4>
-<pre>public&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/Iterator.html?is-external=true" title="class or interface in java.util">Iterator</a>&lt;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/CachedBlock.html" title="interface in org.apache.hadoop.hbase.io.hfile">CachedBlock</a>&gt;&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1535">iterator</a>()</pre>
+<pre>public&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/Iterator.html?is-external=true" title="class or interface in java.util">Iterator</a>&lt;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/CachedBlock.html" title="interface in org.apache.hadoop.hbase.io.hfile">CachedBlock</a>&gt;&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1542">iterator</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/Iterable.html?is-external=true#iterator--" title="class or interface in java.lang">iterator</a></code>&nbsp;in interface&nbsp;<code><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Iterable.html?is-external=true" title="class or interface in java.lang">Iterable</a>&lt;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/CachedBlock.html" title="interface in org.apache.hadoop.hbase.io.hfile">CachedBlock</a>&gt;</code></dd>
@@ -1985,7 +1985,7 @@ implements <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockC
 <ul class="blockList">
 <li class="blockList">
 <h4>getBlockCaches</h4>
-<pre>public&nbsp;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCache.html" title="interface in org.apache.hadoop.hbase.io.hfile">BlockCache</a>[]&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1626">getBlockCaches</a>()</pre>
+<pre>public&nbsp;<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCache.html" title="interface in org.apache.hadoop.hbase.io.hfile">BlockCache</a>[]&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1633">getBlockCaches</a>()</pre>
 <dl>
 <dt><span class="overrideSpecifyLabel">Specified by:</span></dt>
 <dd><code><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCache.html#getBlockCaches--">getBlockCaches</a></code>&nbsp;in interface&nbsp;<code><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCache.html" title="interface in org.apache.hadoop.hbase.io.hfile">BlockCache</a></code></dd>
@@ -2000,7 +2000,7 @@ implements <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockC
 <ul class="blockList">
 <li class="blockList">
 <h4>returnBlock</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1631">returnBlock</a>(<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a>&nbsp;cacheKey,
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1638">returnBlock</a>(<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a>&nbsp;cacheKey,
                         <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html" title="interface in org.apache.hadoop.hbase.io.hfile">Cacheable</a>&nbsp;block)</pre>
 <div class="block"><span class="descfrmTypeLabel">Description copied from interface:&nbsp;<code><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCache.html#returnBlock-org.apache.hadoop.hbase.io.hfile.BlockCacheKey-org.apache.hadoop.hbase.io.hfile.Cacheable-">BlockCache</a></code></span></div>
 <div class="block">Called when the scanner using the block decides to return the block once its usage
@@ -2024,7 +2024,7 @@ implements <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockC
 <ul class="blockList">
 <li class="blockList">
 <h4>getRefCount</h4>
-<pre>public&nbsp;int&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1644">getRefCount</a>(<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a>&nbsp;cacheKey)</pre>
+<pre>public&nbsp;int&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1651">getRefCount</a>(<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a>&nbsp;cacheKey)</pre>
 </li>
 </ul>
 <a name="getAcceptableFactor--">
@@ -2033,7 +2033,7 @@ implements <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockC
 <ul class="blockList">
 <li class="blockList">
 <h4>getAcceptableFactor</h4>
-<pre>float&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1652">getAcceptableFactor</a>()</pre>
+<pre>float&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1659">getAcceptableFactor</a>()</pre>
 </li>
 </ul>
 <a name="getMinFactor--">
@@ -2042,7 +2042,7 @@ implements <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockC
 <ul class="blockList">
 <li class="blockList">
 <h4>getMinFactor</h4>
-<pre>float&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1656">getMinFactor</a>()</pre>
+<pre>float&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1663">getMinFactor</a>()</pre>
 </li>
 </ul>
 <a name="getExtraFreeFactor--">
@@ -2051,7 +2051,7 @@ implements <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockC
 <ul class="blockList">
 <li class="blockList">
 <h4>getExtraFreeFactor</h4>
-<pre>float&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1660">getExtraFreeFactor</a>()</pre>
+<pre>float&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1667">getExtraFreeFactor</a>()</pre>
 </li>
 </ul>
 <a name="getSingleFactor--">
@@ -2060,7 +2060,7 @@ implements <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockC
 <ul class="blockList">
 <li class="blockList">
 <h4>getSingleFactor</h4>
-<pre>float&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1664">getSingleFactor</a>()</pre>
+<pre>float&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1671">getSingleFactor</a>()</pre>
 </li>
 </ul>
 <a name="getMultiFactor--">
@@ -2069,7 +2069,7 @@ implements <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockC
 <ul class="blockList">
 <li class="blockList">
 <h4>getMultiFactor</h4>
-<pre>float&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1668">getMultiFactor</a>()</pre>
+<pre>float&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1675">getMultiFactor</a>()</pre>
 </li>
 </ul>
 <a name="getMemoryFactor--">
@@ -2078,7 +2078,7 @@ implements <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockC
 <ul class="blockListLast">
 <li class="blockList">
 <h4>getMemoryFactor</h4>
-<pre>float&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1672">getMemoryFactor</a>()</pre>
+<pre>float&nbsp;<a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line.1679">getMemoryFactor</a>()</pre>
 </li>
 </ul>
 </li>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/io/hfile/class-use/BlockCacheKey.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/io/hfile/class-use/BlockCacheKey.html b/devapidocs/org/apache/hadoop/hbase/io/hfile/class-use/BlockCacheKey.html
index 00b96e2..8a6405b 100644
--- a/devapidocs/org/apache/hadoop/hbase/io/hfile/class-use/BlockCacheKey.html
+++ b/devapidocs/org/apache/hadoop/hbase/io/hfile/class-use/BlockCacheKey.html
@@ -320,6 +320,15 @@
  is over.</div>
 </td>
 </tr>
+<tr class="altColor">
+<td class="colFirst"><code>static int</code></td>
+<td class="colLast"><span class="typeNameLabel">BlockCacheUtil.</span><code><span class="memberNameLink"><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html#validateBlockAddition-org.apache.hadoop.hbase.io.hfile.Cacheable-org.apache.hadoop.hbase.io.hfile.Cacheable-org.apache.hadoop.hbase.io.hfile.BlockCacheKey-">validateBlockAddition</a></span>(<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html" title="interface in org.apache.hadoop.hbase.io.hfile">Cacheable</a>&nbsp;existing,
+                     <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html" title="interface in org.apache.hadoop.hbase.io.hfile">Cacheable</a>&nbsp;newBlock,
+                     <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a>&nbsp;cacheKey)</code>
+<div class="block">Validate that the existing and newBlock are the same without including the nextBlockMetadata,
+ if not, throw an exception.</div>
+</td>
+</tr>
 </tbody>
 </table>
 <table class="useSummary" border="0" cellpadding="3" cellspacing="0" summary="Use table, listing constructors, and an explanation">

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/io/hfile/class-use/Cacheable.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/io/hfile/class-use/Cacheable.html b/devapidocs/org/apache/hadoop/hbase/io/hfile/class-use/Cacheable.html
index 0c0d1a2..deef407 100644
--- a/devapidocs/org/apache/hadoop/hbase/io/hfile/class-use/Cacheable.html
+++ b/devapidocs/org/apache/hadoop/hbase/io/hfile/class-use/Cacheable.html
@@ -310,9 +310,10 @@
           boolean&nbsp;inMemory)</code>&nbsp;</td>
 </tr>
 <tr class="rowColor">
-<td class="colFirst"><code>static int</code></td>
-<td class="colLast"><span class="typeNameLabel">BlockCacheUtil.</span><code><span class="memberNameLink"><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html#compareCacheBlock-org.apache.hadoop.hbase.io.hfile.Cacheable-org.apache.hadoop.hbase.io.hfile.Cacheable-">compareCacheBlock</a></span>(<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html" title="interface in org.apache.hadoop.hbase.io.hfile">Cacheable</a>&nbsp;left,
-                 <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html" title="interface in org.apache.hadoop.hbase.io.hfile">Cacheable</a>&nbsp;right)</code>&nbsp;</td>
+<td class="colFirst"><code>private static int</code></td>
+<td class="colLast"><span class="typeNameLabel">BlockCacheUtil.</span><code><span class="memberNameLink"><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html#compareCacheBlock-org.apache.hadoop.hbase.io.hfile.Cacheable-org.apache.hadoop.hbase.io.hfile.Cacheable-boolean-">compareCacheBlock</a></span>(<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html" title="interface in org.apache.hadoop.hbase.io.hfile">Cacheable</a>&nbsp;left,
+                 <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html" title="interface in org.apache.hadoop.hbase.io.hfile">Cacheable</a>&nbsp;right,
+                 boolean&nbsp;includeNextBlockMetadata)</code>&nbsp;</td>
 </tr>
 <tr class="altColor">
 <td class="colFirst"><code>void</code></td>
@@ -327,6 +328,15 @@
  is over.</div>
 </td>
 </tr>
+<tr class="altColor">
+<td class="colFirst"><code>static int</code></td>
+<td class="colLast"><span class="typeNameLabel">BlockCacheUtil.</span><code><span class="memberNameLink"><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html#validateBlockAddition-org.apache.hadoop.hbase.io.hfile.Cacheable-org.apache.hadoop.hbase.io.hfile.Cacheable-org.apache.hadoop.hbase.io.hfile.BlockCacheKey-">validateBlockAddition</a></span>(<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html" title="interface in org.apache.hadoop.hbase.io.hfile">Cacheable</a>&nbsp;existing,
+                     <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html" title="interface in org.apache.hadoop.hbase.io.hfile">Cacheable</a>&nbsp;newBlock,
+                     <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a>&nbsp;cacheKey)</code>
+<div class="block">Validate that the existing and newBlock are the same without including the nextBlockMetadata,
+ if not, throw an exception.</div>
+</td>
+</tr>
 </tbody>
 </table>
 <table class="useSummary" border="0" cellpadding="3" cellspacing="0" summary="Use table, listing methods, and an explanation">

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/io/hfile/package-tree.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/io/hfile/package-tree.html b/devapidocs/org/apache/hadoop/hbase/io/hfile/package-tree.html
index b2a359c..340ec84 100644
--- a/devapidocs/org/apache/hadoop/hbase/io/hfile/package-tree.html
+++ b/devapidocs/org/apache/hadoop/hbase/io/hfile/package-tree.html
@@ -273,12 +273,12 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true" title="class or interface in java.io">Serializable</a>)
 <ul>
-<li type="circle">org.apache.hadoop.hbase.io.hfile.<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.MemoryType.html" title="enum in org.apache.hadoop.hbase.io.hfile"><span class="typeNameLink">Cacheable.MemoryType</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.io.hfile.<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/CacheConfig.ExternalBlockCaches.html" title="enum in org.apache.hadoop.hbase.io.hfile"><span class="typeNameLink">CacheConfig.ExternalBlockCaches</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.io.hfile.<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockPriority.html" title="enum in org.apache.hadoop.hbase.io.hfile"><span class="typeNameLink">BlockPriority</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.io.hfile.<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockType.html" title="enum in org.apache.hadoop.hbase.io.hfile"><span class="typeNameLink">BlockType</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.io.hfile.<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.State.html" title="enum in org.apache.hadoop.hbase.io.hfile"><span class="typeNameLink">HFileBlock.Writer.State</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.io.hfile.<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockType.BlockCategory.html" title="enum in org.apache.hadoop.hbase.io.hfile"><span class="typeNameLink">BlockType.BlockCategory</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.io.hfile.<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockType.html" title="enum in org.apache.hadoop.hbase.io.hfile"><span class="typeNameLink">BlockType</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.io.hfile.<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockPriority.html" title="enum in org.apache.hadoop.hbase.io.hfile"><span class="typeNameLink">BlockPriority</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.io.hfile.<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.MemoryType.html" title="enum in org.apache.hadoop.hbase.io.hfile"><span class="typeNameLink">Cacheable.MemoryType</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.io.hfile.<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/CacheConfig.ExternalBlockCaches.html" title="enum in org.apache.hadoop.hbase.io.hfile"><span class="typeNameLink">CacheConfig.ExternalBlockCaches</span></a></li>
 </ul>
 </li>
 </ul>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/ipc/package-tree.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/ipc/package-tree.html b/devapidocs/org/apache/hadoop/hbase/ipc/package-tree.html
index 6a2998c..29a79fd 100644
--- a/devapidocs/org/apache/hadoop/hbase/ipc/package-tree.html
+++ b/devapidocs/org/apache/hadoop/hbase/ipc/package-tree.html
@@ -349,8 +349,8 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true" title="class or interface in java.io">Serializable</a>)
 <ul>
-<li type="circle">org.apache.hadoop.hbase.ipc.<a href="../../../../../org/apache/hadoop/hbase/ipc/CallEvent.Type.html" title="enum in org.apache.hadoop.hbase.ipc"><span class="typeNameLink">CallEvent.Type</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.ipc.<a href="../../../../../org/apache/hadoop/hbase/ipc/BufferCallBeforeInitHandler.BufferCallAction.html" title="enum in org.apache.hadoop.hbase.ipc"><span class="typeNameLink">BufferCallBeforeInitHandler.BufferCallAction</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.ipc.<a href="../../../../../org/apache/hadoop/hbase/ipc/CallEvent.Type.html" title="enum in org.apache.hadoop.hbase.ipc"><span class="typeNameLink">CallEvent.Type</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.ipc.<a href="../../../../../org/apache/hadoop/hbase/ipc/MetricsHBaseServerSourceFactoryImpl.SourceStorage.html" title="enum in org.apache.hadoop.hbase.ipc"><span class="typeNameLink">MetricsHBaseServerSourceFactoryImpl.SourceStorage</span></a></li>
 </ul>
 </li>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/mapreduce/package-tree.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/mapreduce/package-tree.html b/devapidocs/org/apache/hadoop/hbase/mapreduce/package-tree.html
index a07a1d8..f1985a3 100644
--- a/devapidocs/org/apache/hadoop/hbase/mapreduce/package-tree.html
+++ b/devapidocs/org/apache/hadoop/hbase/mapreduce/package-tree.html
@@ -293,8 +293,8 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true" title="class or interface in java.io">Serializable</a>)
 <ul>
-<li type="circle">org.apache.hadoop.hbase.mapreduce.<a href="../../../../../org/apache/hadoop/hbase/mapreduce/CellCounter.CellCounterMapper.Counters.html" title="enum in org.apache.hadoop.hbase.mapreduce"><span class="typeNameLink">CellCounter.CellCounterMapper.Counters</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.mapreduce.<a href="../../../../../org/apache/hadoop/hbase/mapreduce/TableSplit.Version.html" title="enum in org.apache.hadoop.hbase.mapreduce"><span class="typeNameLink">TableSplit.Version</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.mapreduce.<a href="../../../../../org/apache/hadoop/hbase/mapreduce/CellCounter.CellCounterMapper.Counters.html" title="enum in org.apache.hadoop.hbase.mapreduce"><span class="typeNameLink">CellCounter.CellCounterMapper.Counters</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.mapreduce.<a href="../../../../../org/apache/hadoop/hbase/mapreduce/SyncTable.SyncMapper.Counter.html" title="enum in org.apache.hadoop.hbase.mapreduce"><span class="typeNameLink">SyncTable.SyncMapper.Counter</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.mapreduce.<a href="../../../../../org/apache/hadoop/hbase/mapreduce/RowCounter.RowCounterMapper.Counters.html" title="enum in org.apache.hadoop.hbase.mapreduce"><span class="typeNameLink">RowCounter.RowCounterMapper.Counters</span></a></li>
 </ul>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/master/balancer/package-tree.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/master/balancer/package-tree.html b/devapidocs/org/apache/hadoop/hbase/master/balancer/package-tree.html
index eb945fb..ad40e69 100644
--- a/devapidocs/org/apache/hadoop/hbase/master/balancer/package-tree.html
+++ b/devapidocs/org/apache/hadoop/hbase/master/balancer/package-tree.html
@@ -197,8 +197,8 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true" title="class or interface in java.io">Serializable</a>)
 <ul>
-<li type="circle">org.apache.hadoop.hbase.master.balancer.<a href="../../../../../../org/apache/hadoop/hbase/master/balancer/BaseLoadBalancer.Cluster.Action.Type.html" title="enum in org.apache.hadoop.hbase.master.balancer"><span class="typeNameLink">BaseLoadBalancer.Cluster.Action.Type</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.master.balancer.<a href="../../../../../../org/apache/hadoop/hbase/master/balancer/BaseLoadBalancer.Cluster.LocalityType.html" title="enum in org.apache.hadoop.hbase.master.balancer"><span class="typeNameLink">BaseLoadBalancer.Cluster.LocalityType</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.master.balancer.<a href="../../../../../../org/apache/hadoop/hbase/master/balancer/BaseLoadBalancer.Cluster.Action.Type.html" title="enum in org.apache.hadoop.hbase.master.balancer"><span class="typeNameLink">BaseLoadBalancer.Cluster.Action.Type</span></a></li>
 </ul>
 </li>
 </ul>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/master/package-tree.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/master/package-tree.html b/devapidocs/org/apache/hadoop/hbase/master/package-tree.html
index 46aef14..6b8dd75 100644
--- a/devapidocs/org/apache/hadoop/hbase/master/package-tree.html
+++ b/devapidocs/org/apache/hadoop/hbase/master/package-tree.html
@@ -347,10 +347,10 @@
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true" title="class or interface in java.io">Serializable</a>)
 <ul>
 <li type="circle">org.apache.hadoop.hbase.master.<a href="../../../../../org/apache/hadoop/hbase/master/MetricsMasterSourceFactoryImpl.FactoryStorage.html" title="enum in org.apache.hadoop.hbase.master"><span class="typeNameLink">MetricsMasterSourceFactoryImpl.FactoryStorage</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.master.<a href="../../../../../org/apache/hadoop/hbase/master/SplitLogManager.ResubmitDirective.html" title="enum in org.apache.hadoop.hbase.master"><span class="typeNameLink">SplitLogManager.ResubmitDirective</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.master.<a href="../../../../../org/apache/hadoop/hbase/master/RegionState.State.html" title="enum in org.apache.hadoop.hbase.master"><span class="typeNameLink">RegionState.State</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.master.<a href="../../../../../org/apache/hadoop/hbase/master/MasterRpcServices.BalanceSwitchMode.html" title="enum in org.apache.hadoop.hbase.master"><span class="typeNameLink">MasterRpcServices.BalanceSwitchMode</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.master.<a href="../../../../../org/apache/hadoop/hbase/master/SplitLogManager.TerminationStatus.html" title="enum in org.apache.hadoop.hbase.master"><span class="typeNameLink">SplitLogManager.TerminationStatus</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.master.<a href="../../../../../org/apache/hadoop/hbase/master/RegionState.State.html" title="enum in org.apache.hadoop.hbase.master"><span class="typeNameLink">RegionState.State</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.master.<a href="../../../../../org/apache/hadoop/hbase/master/SplitLogManager.ResubmitDirective.html" title="enum in org.apache.hadoop.hbase.master"><span class="typeNameLink">SplitLogManager.ResubmitDirective</span></a></li>
 </ul>
 </li>
 </ul>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/master/procedure/package-tree.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/master/procedure/package-tree.html b/devapidocs/org/apache/hadoop/hbase/master/procedure/package-tree.html
index 0fa081d..550d779 100644
--- a/devapidocs/org/apache/hadoop/hbase/master/procedure/package-tree.html
+++ b/devapidocs/org/apache/hadoop/hbase/master/procedure/package-tree.html
@@ -209,8 +209,8 @@
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true" title="class or interface in java.io">Serializable</a>)
 <ul>
 <li type="circle">org.apache.hadoop.hbase.master.procedure.<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/ServerProcedureInterface.ServerOperationType.html" title="enum in org.apache.hadoop.hbase.master.procedure"><span class="typeNameLink">ServerProcedureInterface.ServerOperationType</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.master.procedure.<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/PeerProcedureInterface.PeerOperationType.html" title="enum in org.apache.hadoop.hbase.master.procedure"><span class="typeNameLink">PeerProcedureInterface.PeerOperationType</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.master.procedure.<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/TableProcedureInterface.TableOperationType.html" title="enum in org.apache.hadoop.hbase.master.procedure"><span class="typeNameLink">TableProcedureInterface.TableOperationType</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.master.procedure.<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/PeerProcedureInterface.PeerOperationType.html" title="enum in org.apache.hadoop.hbase.master.procedure"><span class="typeNameLink">PeerProcedureInterface.PeerOperationType</span></a></li>
 </ul>
 </li>
 </ul>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/package-tree.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/package-tree.html b/devapidocs/org/apache/hadoop/hbase/package-tree.html
index 96f03bf..17db7fb 100644
--- a/devapidocs/org/apache/hadoop/hbase/package-tree.html
+++ b/devapidocs/org/apache/hadoop/hbase/package-tree.html
@@ -441,19 +441,19 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true" title="class or interface in java.io">Serializable</a>)
 <ul>
+<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/MetaTableAccessor.QueryType.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">MetaTableAccessor.QueryType</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/Coprocessor.State.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">Coprocessor.State</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/HealthChecker.HealthCheckerExitStatus.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">HealthChecker.HealthCheckerExitStatus</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/MemoryCompactionPolicy.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">MemoryCompactionPolicy</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/Size.Unit.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">Size.Unit</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/Cell.Type.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">Cell.Type</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/CellBuilderType.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">CellBuilderType</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/ClusterMetrics.Option.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">ClusterMetrics.Option</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/CompareOperator.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">CompareOperator</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/HConstants.OperationStatusCode.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">HConstants.OperationStatusCode</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/CellBuilderType.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">CellBuilderType</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/CompatibilitySingletonFactory.SingletonStorage.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">CompatibilitySingletonFactory.SingletonStorage</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/HealthChecker.HealthCheckerExitStatus.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">HealthChecker.HealthCheckerExitStatus</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/Cell.Type.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">Cell.Type</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/KeyValue.Type.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">KeyValue.Type</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/Size.Unit.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">Size.Unit</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/KeepDeletedCells.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">KeepDeletedCells</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/CompareOperator.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">CompareOperator</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/ClusterMetrics.Option.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">ClusterMetrics.Option</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/MetaTableAccessor.QueryType.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">MetaTableAccessor.QueryType</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/CompatibilitySingletonFactory.SingletonStorage.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">CompatibilitySingletonFactory.SingletonStorage</span></a></li>
 </ul>
 </li>
 </ul>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/procedure2/package-tree.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/procedure2/package-tree.html b/devapidocs/org/apache/hadoop/hbase/procedure2/package-tree.html
index 29c7c21..bbbf765 100644
--- a/devapidocs/org/apache/hadoop/hbase/procedure2/package-tree.html
+++ b/devapidocs/org/apache/hadoop/hbase/procedure2/package-tree.html
@@ -212,10 +212,10 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true" title="class or interface in java.io">Serializable</a>)
 <ul>
-<li type="circle">org.apache.hadoop.hbase.procedure2.<a href="../../../../../org/apache/hadoop/hbase/procedure2/Procedure.LockState.html" title="enum in org.apache.hadoop.hbase.procedure2"><span class="typeNameLink">Procedure.LockState</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.procedure2.<a href="../../../../../org/apache/hadoop/hbase/procedure2/StateMachineProcedure.Flow.html" title="enum in org.apache.hadoop.hbase.procedure2"><span class="typeNameLink">StateMachineProcedure.Flow</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.procedure2.<a href="../../../../../org/apache/hadoop/hbase/procedure2/LockType.html" title="enum in org.apache.hadoop.hbase.procedure2"><span class="typeNameLink">LockType</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.procedure2.<a href="../../../../../org/apache/hadoop/hbase/procedure2/RootProcedureState.State.html" title="enum in org.apache.hadoop.hbase.procedure2"><span class="typeNameLink">RootProcedureState.State</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.procedure2.<a href="../../../../../org/apache/hadoop/hbase/procedure2/StateMachineProcedure.Flow.html" title="enum in org.apache.hadoop.hbase.procedure2"><span class="typeNameLink">StateMachineProcedure.Flow</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.procedure2.<a href="../../../../../org/apache/hadoop/hbase/procedure2/Procedure.LockState.html" title="enum in org.apache.hadoop.hbase.procedure2"><span class="typeNameLink">Procedure.LockState</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.procedure2.<a href="../../../../../org/apache/hadoop/hbase/procedure2/LockedResourceType.html" title="enum in org.apache.hadoop.hbase.procedure2"><span class="typeNameLink">LockedResourceType</span></a></li>
 </ul>
 </li>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/quotas/package-tree.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/quotas/package-tree.html b/devapidocs/org/apache/hadoop/hbase/quotas/package-tree.html
index f1ae806..81ff477 100644
--- a/devapidocs/org/apache/hadoop/hbase/quotas/package-tree.html
+++ b/devapidocs/org/apache/hadoop/hbase/quotas/package-tree.html
@@ -229,12 +229,12 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true" title="class or interface in java.io">Serializable</a>)
 <ul>
-<li type="circle">org.apache.hadoop.hbase.quotas.<a href="../../../../../org/apache/hadoop/hbase/quotas/SpaceViolationPolicy.html" title="enum in org.apache.hadoop.hbase.quotas"><span class="typeNameLink">SpaceViolationPolicy</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.quotas.<a href="../../../../../org/apache/hadoop/hbase/quotas/QuotaScope.html" title="enum in org.apache.hadoop.hbase.quotas"><span class="typeNameLink">QuotaScope</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.quotas.<a href="../../../../../org/apache/hadoop/hbase/quotas/ThrottleType.html" title="enum in org.apache.hadoop.hbase.quotas"><span class="typeNameLink">ThrottleType</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.quotas.<a href="../../../../../org/apache/hadoop/hbase/quotas/OperationQuota.OperationType.html" title="enum in org.apache.hadoop.hbase.quotas"><span class="typeNameLink">OperationQuota.OperationType</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.quotas.<a href="../../../../../org/apache/hadoop/hbase/quotas/SpaceViolationPolicy.html" title="enum in org.apache.hadoop.hbase.quotas"><span class="typeNameLink">SpaceViolationPolicy</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.quotas.<a href="../../../../../org/apache/hadoop/hbase/quotas/QuotaType.html" title="enum in org.apache.hadoop.hbase.quotas"><span class="typeNameLink">QuotaType</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.quotas.<a href="../../../../../org/apache/hadoop/hbase/quotas/OperationQuota.OperationType.html" title="enum in org.apache.hadoop.hbase.quotas"><span class="typeNameLink">OperationQuota.OperationType</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.quotas.<a href="../../../../../org/apache/hadoop/hbase/quotas/RpcThrottlingException.Type.html" title="enum in org.apache.hadoop.hbase.quotas"><span class="typeNameLink">RpcThrottlingException.Type</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.quotas.<a href="../../../../../org/apache/hadoop/hbase/quotas/ThrottleType.html" title="enum in org.apache.hadoop.hbase.quotas"><span class="typeNameLink">ThrottleType</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.quotas.<a href="../../../../../org/apache/hadoop/hbase/quotas/ThrottlingException.Type.html" title="enum in org.apache.hadoop.hbase.quotas"><span class="typeNameLink">ThrottlingException.Type</span></a></li>
 </ul>
 </li>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/regionserver/NoLimitScannerContext.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/regionserver/NoLimitScannerContext.html b/devapidocs/org/apache/hadoop/hbase/regionserver/NoLimitScannerContext.html
index 5104c60..80ee34c 100644
--- a/devapidocs/org/apache/hadoop/hbase/regionserver/NoLimitScannerContext.html
+++ b/devapidocs/org/apache/hadoop/hbase/regionserver/NoLimitScannerContext.html
@@ -269,7 +269,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerCont
 <!--   -->
 </a>
 <h3>Methods inherited from class&nbsp;org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html" title="class in org.apache.hadoop.hbase.regionserver">ScannerContext</a></h3>
-<code><a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#getBatchLimit--">getBatchLimit</a>, <a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#getBatchProgress--">getBatchProgress</a>, <a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#getDataSizeLimit--">getDataSizeLimit</a>, <a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#getDataSizeProgress--">getDataSizeProgress</a>, <a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#getHeapSizeProgress--">getHeapSizeProgress</a>, <a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#getKeepProgress--">getKeepProgress</a>, <a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#getLastPeekedCell--">getLastPeekedCell</a>, <a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#getMetrics--">getMetrics</a>, <a href="../.
 ./../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#getTimeLimit--">getTimeLimit</a>, <a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#hasAnyLimit-org.apache.hadoop.hbase.regionserver.ScannerContext.LimitScope-">hasAnyLimit</a>, <a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#hasBatchLimit-org.apache.hadoop.hbase.regionserver.ScannerContext.LimitScope-">hasBatchLimit</a>, <a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#hasSizeLimit-org.apache.hadoop.hbase.regionserver.ScannerContext.LimitScope-">hasSizeLimit</a>, <a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#hasTimeLimit-org.apache.hadoop.hbase.regionserver.ScannerContext.LimitScope-">hasTimeLimit</a>, <a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#incrementBatchProgress-int-">incrementBatchProgress</a>, <a href="../../../../../org/apache/hadoop/hbase/r
 egionserver/ScannerContext.html#incrementSizeProgress-long-long-">incrementSizeProgress</a>, <a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#isTrackingMetrics--">isTrackingMetrics</a>, <a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#mayHaveMoreCellsInRow--">mayHaveMoreCellsInRow</a>, <a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#newBuilder--">newBuilder</a>, <a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#newBuilder-boolean-">newBuilder</a>, <a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#setLastPeekedCell-org.apache.hadoop.hbase.Cell-">setLastPeekedCell</a>, <a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#toString--">toString</a></code></li>
+<code><a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#getBatchLimit--">getBatchLimit</a>, <a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#getBatchProgress--">getBatchProgress</a>, <a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#getDataSizeLimit--">getDataSizeLimit</a>, <a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#getDataSizeProgress--">getDataSizeProgress</a>, <a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#getHeapSizeProgress--">getHeapSizeProgress</a>, <a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#getKeepProgress--">getKeepProgress</a>, <a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#getLastPeekedCell--">getLastPeekedCell</a>, <a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#getMetrics--">getMetrics</a>, <a href="../.
 ./../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#getTimeLimit--">getTimeLimit</a>, <a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#hasAnyLimit-org.apache.hadoop.hbase.regionserver.ScannerContext.LimitScope-">hasAnyLimit</a>, <a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#hasBatchLimit-org.apache.hadoop.hbase.regionserver.ScannerContext.LimitScope-">hasBatchLimit</a>, <a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#hasSizeLimit-org.apache.hadoop.hbase.regionserver.ScannerContext.LimitScope-">hasSizeLimit</a>, <a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#hasTimeLimit-org.apache.hadoop.hbase.regionserver.ScannerContext.LimitScope-">hasTimeLimit</a>, <a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#incrementBatchProgress-int-">incrementBatchProgress</a>, <a href="../../../../../org/apache/hadoop/hbase/r
 egionserver/ScannerContext.html#incrementSizeProgress-long-long-">incrementSizeProgress</a>, <a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#isTrackingMetrics--">isTrackingMetrics</a>, <a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#mayHaveMoreCellsInRow--">mayHaveMoreCellsInRow</a>, <a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#newBuilder--">newBuilder</a>, <a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#newBuilder-boolean-">newBuilder</a>, <a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#returnImmediately--">returnImmediately</a>, <a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#setLastPeekedCell-org.apache.hadoop.hbase.Cell-">setLastPeekedCell</a>, <a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#toString--">toString</a></code></li>
 </ul>
 <ul class="blockList">
 <li class="blockList"><a name="methods.inherited.from.class.java.lang.Object">

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/regionserver/ScannerContext.Builder.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/regionserver/ScannerContext.Builder.html b/devapidocs/org/apache/hadoop/hbase/regionserver/ScannerContext.Builder.html
index c3eef53..2cfed85 100644
--- a/devapidocs/org/apache/hadoop/hbase/regionserver/ScannerContext.Builder.html
+++ b/devapidocs/org/apache/hadoop/hbase/regionserver/ScannerContext.Builder.html
@@ -113,7 +113,7 @@ var activeTableTab = "activeTableTab";
 </dl>
 <hr>
 <br>
-<pre>public static final class <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.359">ScannerContext.Builder</a>
+<pre>public static final class <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.371">ScannerContext.Builder</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>
 </li>
 </ul>
@@ -238,7 +238,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>keepProgress</h4>
-<pre>boolean <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.Builder.html#line.360">keepProgress</a></pre>
+<pre>boolean <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.Builder.html#line.372">keepProgress</a></pre>
 </li>
 </ul>
 <a name="trackMetrics">
@@ -247,7 +247,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>trackMetrics</h4>
-<pre>boolean <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.Builder.html#line.361">trackMetrics</a></pre>
+<pre>boolean <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.Builder.html#line.373">trackMetrics</a></pre>
 </li>
 </ul>
 <a name="limits">
@@ -256,7 +256,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>limits</h4>
-<pre><a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html" title="class in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitFields</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.Builder.html#line.362">limits</a></pre>
+<pre><a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html" title="class in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitFields</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.Builder.html#line.374">limits</a></pre>
 </li>
 </ul>
 </li>
@@ -273,7 +273,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>Builder</h4>
-<pre>private&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.Builder.html#line.364">Builder</a>()</pre>
+<pre>private&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.Builder.html#line.376">Builder</a>()</pre>
 </li>
 </ul>
 <a name="Builder-boolean-">
@@ -282,7 +282,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>Builder</h4>
-<pre>private&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.Builder.html#line.367">Builder</a>(boolean&nbsp;keepProgress)</pre>
+<pre>private&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.Builder.html#line.379">Builder</a>(boolean&nbsp;keepProgress)</pre>
 </li>
 </ul>
 </li>
@@ -299,7 +299,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>setKeepProgress</h4>
-<pre>public&nbsp;<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.Builder.html" title="class in org.apache.hadoop.hbase.regionserver">ScannerContext.Builder</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.Builder.html#line.371">setKeepProgress</a>(boolean&nbsp;keepProgress)</pre>
+<pre>public&nbsp;<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.Builder.html" title="class in org.apache.hadoop.hbase.regionserver">ScannerContext.Builder</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.Builder.html#line.383">setKeepProgress</a>(boolean&nbsp;keepProgress)</pre>
 </li>
 </ul>
 <a name="setTrackMetrics-boolean-">
@@ -308,7 +308,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>setTrackMetrics</h4>
-<pre>public&nbsp;<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.Builder.html" title="class in org.apache.hadoop.hbase.regionserver">ScannerContext.Builder</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.Builder.html#line.376">setTrackMetrics</a>(boolean&nbsp;trackMetrics)</pre>
+<pre>public&nbsp;<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.Builder.html" title="class in org.apache.hadoop.hbase.regionserver">ScannerContext.Builder</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.Builder.html#line.388">setTrackMetrics</a>(boolean&nbsp;trackMetrics)</pre>
 </li>
 </ul>
 <a name="setSizeLimit-org.apache.hadoop.hbase.regionserver.ScannerContext.LimitScope-long-long-">
@@ -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>setSizeLimit</h4>
-<pre>public&nbsp;<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.Builder.html" title="class in org.apache.hadoop.hbase.regionserver">ScannerContext.Builder</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.Builder.html#line.381">setSizeLimit</a>(<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a>&nbsp;sizeScope,
+<pre>public&nbsp;<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.Builder.html" title="class in org.apache.hadoop.hbase.regionserver">ScannerContext.Builder</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.Builder.html#line.393">setSizeLimit</a>(<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a>&nbsp;sizeScope,
                                            long&nbsp;dataSizeLimit,
                                            long&nbsp;heapSizeLimit)</pre>
 </li>
@@ -328,7 +328,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>setTimeLimit</h4>
-<pre>public&nbsp;<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.Builder.html" title="class in org.apache.hadoop.hbase.regionserver">ScannerContext.Builder</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.Builder.html#line.388">setTimeLimit</a>(<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a>&nbsp;timeScope,
+<pre>public&nbsp;<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.Builder.html" title="class in org.apache.hadoop.hbase.regionserver">ScannerContext.Builder</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.Builder.html#line.400">setTimeLimit</a>(<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a>&nbsp;timeScope,
                                            long&nbsp;timeLimit)</pre>
 </li>
 </ul>
@@ -338,7 +338,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>setBatchLimit</h4>
-<pre>public&nbsp;<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.Builder.html" title="class in org.apache.hadoop.hbase.regionserver">ScannerContext.Builder</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.Builder.html#line.394">setBatchLimit</a>(int&nbsp;batchLimit)</pre>
+<pre>public&nbsp;<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.Builder.html" title="class in org.apache.hadoop.hbase.regionserver">ScannerContext.Builder</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.Builder.html#line.406">setBatchLimit</a>(int&nbsp;batchLimit)</pre>
 </li>
 </ul>
 <a name="build--">
@@ -347,7 +347,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>build</h4>
-<pre>public&nbsp;<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html" title="class in org.apache.hadoop.hbase.regionserver">ScannerContext</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.Builder.html#line.399">build</a>()</pre>
+<pre>public&nbsp;<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html" title="class in org.apache.hadoop.hbase.regionserver">ScannerContext</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.Builder.html#line.411">build</a>()</pre>
 </li>
 </ul>
 </li>


[11/50] hbase-site git commit: Published site at 26babcf013de696b899d76a3c39434b794440d8d.

Posted by gi...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/downloads.html
----------------------------------------------------------------------
diff --git a/downloads.html b/downloads.html
index 46eec4c..f65c283 100644
--- a/downloads.html
+++ b/downloads.html
@@ -7,7 +7,7 @@
   <head>
     <meta charset="UTF-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-    <meta name="Date-Revision-yyyymmdd" content="20180514" />
+    <meta name="Date-Revision-yyyymmdd" content="20180515" />
     <meta http-equiv="Content-Language" content="en" />
     <title>Apache HBase &#x2013; Apache HBase Downloads</title>
     <link rel="stylesheet" href="./css/apache-maven-fluido-1.5-HBASE.min.css" />
@@ -366,7 +366,7 @@ under the License. -->
                         <a href="https://www.apache.org/">The Apache Software Foundation</a>.
             All rights reserved.      
                     
-                  <li id="publishDate" class="pull-right">Last Published: 2018-05-14</li>
+                  <li id="publishDate" class="pull-right">Last Published: 2018-05-15</li>
             </p>
                 </div>
 

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/export_control.html
----------------------------------------------------------------------
diff --git a/export_control.html b/export_control.html
index 99d5056..c3ea1e3 100644
--- a/export_control.html
+++ b/export_control.html
@@ -7,7 +7,7 @@
   <head>
     <meta charset="UTF-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-    <meta name="Date-Revision-yyyymmdd" content="20180514" />
+    <meta name="Date-Revision-yyyymmdd" content="20180515" />
     <meta http-equiv="Content-Language" content="en" />
     <title>Apache HBase &#x2013; 
       Export Control
@@ -331,7 +331,7 @@ for more details.</p>
                         <a href="https://www.apache.org/">The Apache Software Foundation</a>.
             All rights reserved.      
                     
-                  <li id="publishDate" class="pull-right">Last Published: 2018-05-14</li>
+                  <li id="publishDate" class="pull-right">Last Published: 2018-05-15</li>
             </p>
                 </div>
 

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/index.html
----------------------------------------------------------------------
diff --git a/index.html b/index.html
index 3ddba67..c6c9050 100644
--- a/index.html
+++ b/index.html
@@ -7,7 +7,7 @@
   <head>
     <meta charset="UTF-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-    <meta name="Date-Revision-yyyymmdd" content="20180514" />
+    <meta name="Date-Revision-yyyymmdd" content="20180515" />
     <meta http-equiv="Content-Language" content="en" />
     <title>Apache HBase &#x2013; Apache HBaseâ„¢ Home</title>
     <link rel="stylesheet" href="./css/apache-maven-fluido-1.5-HBASE.min.css" />
@@ -409,7 +409,7 @@ Apache HBase is an open-source, distributed, versioned, non-relational database
                         <a href="https://www.apache.org/">The Apache Software Foundation</a>.
             All rights reserved.      
                     
-                  <li id="publishDate" class="pull-right">Last Published: 2018-05-14</li>
+                  <li id="publishDate" class="pull-right">Last Published: 2018-05-15</li>
             </p>
                 </div>
 

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/integration.html
----------------------------------------------------------------------
diff --git a/integration.html b/integration.html
index 43ec0c6..a64256a 100644
--- a/integration.html
+++ b/integration.html
@@ -7,7 +7,7 @@
   <head>
     <meta charset="UTF-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-    <meta name="Date-Revision-yyyymmdd" content="20180514" />
+    <meta name="Date-Revision-yyyymmdd" content="20180515" />
     <meta http-equiv="Content-Language" content="en" />
     <title>Apache HBase &#x2013; CI Management</title>
     <link rel="stylesheet" href="./css/apache-maven-fluido-1.5-HBASE.min.css" />
@@ -291,7 +291,7 @@
                         <a href="https://www.apache.org/">The Apache Software Foundation</a>.
             All rights reserved.      
                     
-                  <li id="publishDate" class="pull-right">Last Published: 2018-05-14</li>
+                  <li id="publishDate" class="pull-right">Last Published: 2018-05-15</li>
             </p>
                 </div>
 

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/issue-tracking.html
----------------------------------------------------------------------
diff --git a/issue-tracking.html b/issue-tracking.html
index 0b12b13..42db059 100644
--- a/issue-tracking.html
+++ b/issue-tracking.html
@@ -7,7 +7,7 @@
   <head>
     <meta charset="UTF-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-    <meta name="Date-Revision-yyyymmdd" content="20180514" />
+    <meta name="Date-Revision-yyyymmdd" content="20180515" />
     <meta http-equiv="Content-Language" content="en" />
     <title>Apache HBase &#x2013; Issue Management</title>
     <link rel="stylesheet" href="./css/apache-maven-fluido-1.5-HBASE.min.css" />
@@ -288,7 +288,7 @@
                         <a href="https://www.apache.org/">The Apache Software Foundation</a>.
             All rights reserved.      
                     
-                  <li id="publishDate" class="pull-right">Last Published: 2018-05-14</li>
+                  <li id="publishDate" class="pull-right">Last Published: 2018-05-15</li>
             </p>
                 </div>
 

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/license.html
----------------------------------------------------------------------
diff --git a/license.html b/license.html
index 350b6f0..7147b25 100644
--- a/license.html
+++ b/license.html
@@ -7,7 +7,7 @@
   <head>
     <meta charset="UTF-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-    <meta name="Date-Revision-yyyymmdd" content="20180514" />
+    <meta name="Date-Revision-yyyymmdd" content="20180515" />
     <meta http-equiv="Content-Language" content="en" />
     <title>Apache HBase &#x2013; Project Licenses</title>
     <link rel="stylesheet" href="./css/apache-maven-fluido-1.5-HBASE.min.css" />
@@ -491,7 +491,7 @@
                         <a href="https://www.apache.org/">The Apache Software Foundation</a>.
             All rights reserved.      
                     
-                  <li id="publishDate" class="pull-right">Last Published: 2018-05-14</li>
+                  <li id="publishDate" class="pull-right">Last Published: 2018-05-15</li>
             </p>
                 </div>
 

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/mail-lists.html
----------------------------------------------------------------------
diff --git a/mail-lists.html b/mail-lists.html
index bdddcde..7ab7e28 100644
--- a/mail-lists.html
+++ b/mail-lists.html
@@ -7,7 +7,7 @@
   <head>
     <meta charset="UTF-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-    <meta name="Date-Revision-yyyymmdd" content="20180514" />
+    <meta name="Date-Revision-yyyymmdd" content="20180515" />
     <meta http-equiv="Content-Language" content="en" />
     <title>Apache HBase &#x2013; Project Mailing Lists</title>
     <link rel="stylesheet" href="./css/apache-maven-fluido-1.5-HBASE.min.css" />
@@ -341,7 +341,7 @@
                         <a href="https://www.apache.org/">The Apache Software Foundation</a>.
             All rights reserved.      
                     
-                  <li id="publishDate" class="pull-right">Last Published: 2018-05-14</li>
+                  <li id="publishDate" class="pull-right">Last Published: 2018-05-15</li>
             </p>
                 </div>
 

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/metrics.html
----------------------------------------------------------------------
diff --git a/metrics.html b/metrics.html
index cb50802..724fbb6 100644
--- a/metrics.html
+++ b/metrics.html
@@ -7,7 +7,7 @@
   <head>
     <meta charset="UTF-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-    <meta name="Date-Revision-yyyymmdd" content="20180514" />
+    <meta name="Date-Revision-yyyymmdd" content="20180515" />
     <meta http-equiv="Content-Language" content="en" />
     <title>Apache HBase &#x2013;  
       Apache HBase (TM) Metrics
@@ -459,7 +459,7 @@ export HBASE_REGIONSERVER_OPTS=&quot;$HBASE_JMX_OPTS -Dcom.sun.management.jmxrem
                         <a href="https://www.apache.org/">The Apache Software Foundation</a>.
             All rights reserved.      
                     
-                  <li id="publishDate" class="pull-right">Last Published: 2018-05-14</li>
+                  <li id="publishDate" class="pull-right">Last Published: 2018-05-15</li>
             </p>
                 </div>
 

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/old_news.html
----------------------------------------------------------------------
diff --git a/old_news.html b/old_news.html
index 04bb5ef..9e59073 100644
--- a/old_news.html
+++ b/old_news.html
@@ -7,7 +7,7 @@
   <head>
     <meta charset="UTF-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-    <meta name="Date-Revision-yyyymmdd" content="20180514" />
+    <meta name="Date-Revision-yyyymmdd" content="20180515" />
     <meta http-equiv="Content-Language" content="en" />
     <title>Apache HBase &#x2013; 
       Old Apache HBase (TM) News
@@ -440,7 +440,7 @@ under the License. -->
                         <a href="https://www.apache.org/">The Apache Software Foundation</a>.
             All rights reserved.      
                     
-                  <li id="publishDate" class="pull-right">Last Published: 2018-05-14</li>
+                  <li id="publishDate" class="pull-right">Last Published: 2018-05-15</li>
             </p>
                 </div>
 

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/plugin-management.html
----------------------------------------------------------------------
diff --git a/plugin-management.html b/plugin-management.html
index f03c101..3155007 100644
--- a/plugin-management.html
+++ b/plugin-management.html
@@ -7,7 +7,7 @@
   <head>
     <meta charset="UTF-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-    <meta name="Date-Revision-yyyymmdd" content="20180514" />
+    <meta name="Date-Revision-yyyymmdd" content="20180515" />
     <meta http-equiv="Content-Language" content="en" />
     <title>Apache HBase &#x2013; Project Plugin Management</title>
     <link rel="stylesheet" href="./css/apache-maven-fluido-1.5-HBASE.min.css" />
@@ -440,7 +440,7 @@
                         <a href="https://www.apache.org/">The Apache Software Foundation</a>.
             All rights reserved.      
                     
-                  <li id="publishDate" class="pull-right">Last Published: 2018-05-14</li>
+                  <li id="publishDate" class="pull-right">Last Published: 2018-05-15</li>
             </p>
                 </div>
 

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/plugins.html
----------------------------------------------------------------------
diff --git a/plugins.html b/plugins.html
index 818a231..41323c76 100644
--- a/plugins.html
+++ b/plugins.html
@@ -7,7 +7,7 @@
   <head>
     <meta charset="UTF-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-    <meta name="Date-Revision-yyyymmdd" content="20180514" />
+    <meta name="Date-Revision-yyyymmdd" content="20180515" />
     <meta http-equiv="Content-Language" content="en" />
     <title>Apache HBase &#x2013; Project Plugins</title>
     <link rel="stylesheet" href="./css/apache-maven-fluido-1.5-HBASE.min.css" />
@@ -375,7 +375,7 @@
                         <a href="https://www.apache.org/">The Apache Software Foundation</a>.
             All rights reserved.      
                     
-                  <li id="publishDate" class="pull-right">Last Published: 2018-05-14</li>
+                  <li id="publishDate" class="pull-right">Last Published: 2018-05-15</li>
             </p>
                 </div>
 

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/poweredbyhbase.html
----------------------------------------------------------------------
diff --git a/poweredbyhbase.html b/poweredbyhbase.html
index 30bbf5a..189a6ce 100644
--- a/poweredbyhbase.html
+++ b/poweredbyhbase.html
@@ -7,7 +7,7 @@
   <head>
     <meta charset="UTF-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-    <meta name="Date-Revision-yyyymmdd" content="20180514" />
+    <meta name="Date-Revision-yyyymmdd" content="20180515" />
     <meta http-equiv="Content-Language" content="en" />
     <title>Apache HBase &#x2013; Powered By Apache HBase™</title>
     <link rel="stylesheet" href="./css/apache-maven-fluido-1.5-HBASE.min.css" />
@@ -769,7 +769,7 @@ under the License. -->
                         <a href="https://www.apache.org/">The Apache Software Foundation</a>.
             All rights reserved.      
                     
-                  <li id="publishDate" class="pull-right">Last Published: 2018-05-14</li>
+                  <li id="publishDate" class="pull-right">Last Published: 2018-05-15</li>
             </p>
                 </div>
 

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/project-info.html
----------------------------------------------------------------------
diff --git a/project-info.html b/project-info.html
index 5bcbb37..c43d264 100644
--- a/project-info.html
+++ b/project-info.html
@@ -7,7 +7,7 @@
   <head>
     <meta charset="UTF-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-    <meta name="Date-Revision-yyyymmdd" content="20180514" />
+    <meta name="Date-Revision-yyyymmdd" content="20180515" />
     <meta http-equiv="Content-Language" content="en" />
     <title>Apache HBase &#x2013; Project Information</title>
     <link rel="stylesheet" href="./css/apache-maven-fluido-1.5-HBASE.min.css" />
@@ -335,7 +335,7 @@
                         <a href="https://www.apache.org/">The Apache Software Foundation</a>.
             All rights reserved.      
                     
-                  <li id="publishDate" class="pull-right">Last Published: 2018-05-14</li>
+                  <li id="publishDate" class="pull-right">Last Published: 2018-05-15</li>
             </p>
                 </div>
 

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/project-reports.html
----------------------------------------------------------------------
diff --git a/project-reports.html b/project-reports.html
index 1620bff..c506137 100644
--- a/project-reports.html
+++ b/project-reports.html
@@ -7,7 +7,7 @@
   <head>
     <meta charset="UTF-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-    <meta name="Date-Revision-yyyymmdd" content="20180514" />
+    <meta name="Date-Revision-yyyymmdd" content="20180515" />
     <meta http-equiv="Content-Language" content="en" />
     <title>Apache HBase &#x2013; Generated Reports</title>
     <link rel="stylesheet" href="./css/apache-maven-fluido-1.5-HBASE.min.css" />
@@ -305,7 +305,7 @@
                         <a href="https://www.apache.org/">The Apache Software Foundation</a>.
             All rights reserved.      
                     
-                  <li id="publishDate" class="pull-right">Last Published: 2018-05-14</li>
+                  <li id="publishDate" class="pull-right">Last Published: 2018-05-15</li>
             </p>
                 </div>
 

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/project-summary.html
----------------------------------------------------------------------
diff --git a/project-summary.html b/project-summary.html
index 4f9148a..bddc487 100644
--- a/project-summary.html
+++ b/project-summary.html
@@ -7,7 +7,7 @@
   <head>
     <meta charset="UTF-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-    <meta name="Date-Revision-yyyymmdd" content="20180514" />
+    <meta name="Date-Revision-yyyymmdd" content="20180515" />
     <meta http-equiv="Content-Language" content="en" />
     <title>Apache HBase &#x2013; Project Summary</title>
     <link rel="stylesheet" href="./css/apache-maven-fluido-1.5-HBASE.min.css" />
@@ -331,7 +331,7 @@
                         <a href="https://www.apache.org/">The Apache Software Foundation</a>.
             All rights reserved.      
                     
-                  <li id="publishDate" class="pull-right">Last Published: 2018-05-14</li>
+                  <li id="publishDate" class="pull-right">Last Published: 2018-05-15</li>
             </p>
                 </div>
 

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/pseudo-distributed.html
----------------------------------------------------------------------
diff --git a/pseudo-distributed.html b/pseudo-distributed.html
index cabb343..fc171f5 100644
--- a/pseudo-distributed.html
+++ b/pseudo-distributed.html
@@ -7,7 +7,7 @@
   <head>
     <meta charset="UTF-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-    <meta name="Date-Revision-yyyymmdd" content="20180514" />
+    <meta name="Date-Revision-yyyymmdd" content="20180515" />
     <meta http-equiv="Content-Language" content="en" />
     <title>Apache HBase &#x2013;  
 Running Apache HBase (TM) in pseudo-distributed mode
@@ -308,7 +308,7 @@ under the License. -->
                         <a href="https://www.apache.org/">The Apache Software Foundation</a>.
             All rights reserved.      
                     
-                  <li id="publishDate" class="pull-right">Last Published: 2018-05-14</li>
+                  <li id="publishDate" class="pull-right">Last Published: 2018-05-15</li>
             </p>
                 </div>
 

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/replication.html
----------------------------------------------------------------------
diff --git a/replication.html b/replication.html
index 77be828..1b5eb69 100644
--- a/replication.html
+++ b/replication.html
@@ -7,7 +7,7 @@
   <head>
     <meta charset="UTF-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-    <meta name="Date-Revision-yyyymmdd" content="20180514" />
+    <meta name="Date-Revision-yyyymmdd" content="20180515" />
     <meta http-equiv="Content-Language" content="en" />
     <title>Apache HBase &#x2013; 
       Apache HBase (TM) Replication
@@ -303,7 +303,7 @@ under the License. -->
                         <a href="https://www.apache.org/">The Apache Software Foundation</a>.
             All rights reserved.      
                     
-                  <li id="publishDate" class="pull-right">Last Published: 2018-05-14</li>
+                  <li id="publishDate" class="pull-right">Last Published: 2018-05-15</li>
             </p>
                 </div>
 

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/resources.html
----------------------------------------------------------------------
diff --git a/resources.html b/resources.html
index 25c1d05..9df95f5 100644
--- a/resources.html
+++ b/resources.html
@@ -7,7 +7,7 @@
   <head>
     <meta charset="UTF-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-    <meta name="Date-Revision-yyyymmdd" content="20180514" />
+    <meta name="Date-Revision-yyyymmdd" content="20180515" />
     <meta http-equiv="Content-Language" content="en" />
     <title>Apache HBase &#x2013; Other Apache HBase (TM) Resources</title>
     <link rel="stylesheet" href="./css/apache-maven-fluido-1.5-HBASE.min.css" />
@@ -331,7 +331,7 @@ under the License. -->
                         <a href="https://www.apache.org/">The Apache Software Foundation</a>.
             All rights reserved.      
                     
-                  <li id="publishDate" class="pull-right">Last Published: 2018-05-14</li>
+                  <li id="publishDate" class="pull-right">Last Published: 2018-05-15</li>
             </p>
                 </div>
 

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/source-repository.html
----------------------------------------------------------------------
diff --git a/source-repository.html b/source-repository.html
index d412278..b9d3893 100644
--- a/source-repository.html
+++ b/source-repository.html
@@ -7,7 +7,7 @@
   <head>
     <meta charset="UTF-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-    <meta name="Date-Revision-yyyymmdd" content="20180514" />
+    <meta name="Date-Revision-yyyymmdd" content="20180515" />
     <meta http-equiv="Content-Language" content="en" />
     <title>Apache HBase &#x2013; Source Code Management</title>
     <link rel="stylesheet" href="./css/apache-maven-fluido-1.5-HBASE.min.css" />
@@ -299,7 +299,7 @@
                         <a href="https://www.apache.org/">The Apache Software Foundation</a>.
             All rights reserved.      
                     
-                  <li id="publishDate" class="pull-right">Last Published: 2018-05-14</li>
+                  <li id="publishDate" class="pull-right">Last Published: 2018-05-15</li>
             </p>
                 </div>
 

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/sponsors.html
----------------------------------------------------------------------
diff --git a/sponsors.html b/sponsors.html
index aaa7bcf..758f29d 100644
--- a/sponsors.html
+++ b/sponsors.html
@@ -7,7 +7,7 @@
   <head>
     <meta charset="UTF-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-    <meta name="Date-Revision-yyyymmdd" content="20180514" />
+    <meta name="Date-Revision-yyyymmdd" content="20180515" />
     <meta http-equiv="Content-Language" content="en" />
     <title>Apache HBase &#x2013; Apache HBase™ Sponsors</title>
     <link rel="stylesheet" href="./css/apache-maven-fluido-1.5-HBASE.min.css" />
@@ -333,7 +333,7 @@ under the License. -->
                         <a href="https://www.apache.org/">The Apache Software Foundation</a>.
             All rights reserved.      
                     
-                  <li id="publishDate" class="pull-right">Last Published: 2018-05-14</li>
+                  <li id="publishDate" class="pull-right">Last Published: 2018-05-15</li>
             </p>
                 </div>
 

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/supportingprojects.html
----------------------------------------------------------------------
diff --git a/supportingprojects.html b/supportingprojects.html
index 1ca2b60..5414d6f 100644
--- a/supportingprojects.html
+++ b/supportingprojects.html
@@ -7,7 +7,7 @@
   <head>
     <meta charset="UTF-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-    <meta name="Date-Revision-yyyymmdd" content="20180514" />
+    <meta name="Date-Revision-yyyymmdd" content="20180515" />
     <meta http-equiv="Content-Language" content="en" />
     <title>Apache HBase &#x2013; Supporting Projects</title>
     <link rel="stylesheet" href="./css/apache-maven-fluido-1.5-HBASE.min.css" />
@@ -520,7 +520,7 @@ under the License. -->
                         <a href="https://www.apache.org/">The Apache Software Foundation</a>.
             All rights reserved.      
                     
-                  <li id="publishDate" class="pull-right">Last Published: 2018-05-14</li>
+                  <li id="publishDate" class="pull-right">Last Published: 2018-05-15</li>
             </p>
                 </div>
 

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/team-list.html
----------------------------------------------------------------------
diff --git a/team-list.html b/team-list.html
index 0332757..a20f072 100644
--- a/team-list.html
+++ b/team-list.html
@@ -7,7 +7,7 @@
   <head>
     <meta charset="UTF-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-    <meta name="Date-Revision-yyyymmdd" content="20180514" />
+    <meta name="Date-Revision-yyyymmdd" content="20180515" />
     <meta http-equiv="Content-Language" content="en" />
     <title>Apache HBase &#x2013; Project Team</title>
     <link rel="stylesheet" href="./css/apache-maven-fluido-1.5-HBASE.min.css" />
@@ -730,7 +730,7 @@
                         <a href="https://www.apache.org/">The Apache Software Foundation</a>.
             All rights reserved.      
                     
-                  <li id="publishDate" class="pull-right">Last Published: 2018-05-14</li>
+                  <li id="publishDate" class="pull-right">Last Published: 2018-05-15</li>
             </p>
                 </div>
 

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/allclasses-frame.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/allclasses-frame.html b/testdevapidocs/allclasses-frame.html
index 92831c8..e2cf167 100644
--- a/testdevapidocs/allclasses-frame.html
+++ b/testdevapidocs/allclasses-frame.html
@@ -2107,6 +2107,10 @@
 <li><a href="org/apache/hadoop/hbase/types/TestStructNullExtension.html" title="class in org.apache.hadoop.hbase.types" target="classFrame">TestStructNullExtension</a></li>
 <li><a href="org/apache/hadoop/hbase/quotas/TestSuperUserQuotaPermissions.html" title="class in org.apache.hadoop.hbase.quotas" target="classFrame">TestSuperUserQuotaPermissions</a></li>
 <li><a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html" title="class in org.apache.hadoop.hbase.regionserver" target="classFrame">TestSwitchToStreamRead</a></li>
+<li><a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextColFilter.html" title="class in org.apache.hadoop.hbase.regionserver" target="classFrame">TestSwitchToStreamRead.MatchLastRowCellNextColFilter</a></li>
+<li><a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextRowFilter.html" title="class in org.apache.hadoop.hbase.regionserver" target="classFrame">TestSwitchToStreamRead.MatchLastRowCellNextRowFilter</a></li>
+<li><a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html" title="class in org.apache.hadoop.hbase.regionserver" target="classFrame">TestSwitchToStreamRead.MatchLastRowFilterRowFilter</a></li>
+<li><a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowKeyFilter.html" title="class in org.apache.hadoop.hbase.regionserver" target="classFrame">TestSwitchToStreamRead.MatchLastRowKeyFilter</a></li>
 <li><a href="org/apache/hadoop/hbase/regionserver/wal/TestSyncFuture.html" title="class in org.apache.hadoop.hbase.regionserver.wal" target="classFrame">TestSyncFuture</a></li>
 <li><a href="org/apache/hadoop/hbase/mapreduce/TestSyncTable.html" title="class in org.apache.hadoop.hbase.mapreduce" target="classFrame">TestSyncTable</a></li>
 <li><a href="org/apache/hadoop/hbase/regionserver/TestSyncTimeRangeTracker.html" title="class in org.apache.hadoop.hbase.regionserver" target="classFrame">TestSyncTimeRangeTracker</a></li>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/allclasses-noframe.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/allclasses-noframe.html b/testdevapidocs/allclasses-noframe.html
index aabdc84..369e39a 100644
--- a/testdevapidocs/allclasses-noframe.html
+++ b/testdevapidocs/allclasses-noframe.html
@@ -2107,6 +2107,10 @@
 <li><a href="org/apache/hadoop/hbase/types/TestStructNullExtension.html" title="class in org.apache.hadoop.hbase.types">TestStructNullExtension</a></li>
 <li><a href="org/apache/hadoop/hbase/quotas/TestSuperUserQuotaPermissions.html" title="class in org.apache.hadoop.hbase.quotas">TestSuperUserQuotaPermissions</a></li>
 <li><a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html" title="class in org.apache.hadoop.hbase.regionserver">TestSwitchToStreamRead</a></li>
+<li><a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextColFilter.html" title="class in org.apache.hadoop.hbase.regionserver">TestSwitchToStreamRead.MatchLastRowCellNextColFilter</a></li>
+<li><a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextRowFilter.html" title="class in org.apache.hadoop.hbase.regionserver">TestSwitchToStreamRead.MatchLastRowCellNextRowFilter</a></li>
+<li><a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html" title="class in org.apache.hadoop.hbase.regionserver">TestSwitchToStreamRead.MatchLastRowFilterRowFilter</a></li>
+<li><a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowKeyFilter.html" title="class in org.apache.hadoop.hbase.regionserver">TestSwitchToStreamRead.MatchLastRowKeyFilter</a></li>
 <li><a href="org/apache/hadoop/hbase/regionserver/wal/TestSyncFuture.html" title="class in org.apache.hadoop.hbase.regionserver.wal">TestSyncFuture</a></li>
 <li><a href="org/apache/hadoop/hbase/mapreduce/TestSyncTable.html" title="class in org.apache.hadoop.hbase.mapreduce">TestSyncTable</a></li>
 <li><a href="org/apache/hadoop/hbase/regionserver/TestSyncTimeRangeTracker.html" title="class in org.apache.hadoop.hbase.regionserver">TestSyncTimeRangeTracker</a></li>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/index-all.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/index-all.html b/testdevapidocs/index-all.html
index 1b39bf3..2747f8f 100644
--- a/testdevapidocs/index-all.html
+++ b/testdevapidocs/index-all.html
@@ -12854,6 +12854,8 @@
 <dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/client/TestMetaCache.FakeRSRpcServices.html#exceptions">exceptions</a></span> - Variable in class org.apache.hadoop.hbase.client.<a href="org/apache/hadoop/hbase/client/TestMetaCache.FakeRSRpcServices.html" title="class in org.apache.hadoop.hbase.client">TestMetaCache.FakeRSRpcServices</a></dt>
 <dd>&nbsp;</dd>
+<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html#exclude">exclude</a></span> - Variable in class org.apache.hadoop.hbase.regionserver.<a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html" title="class in org.apache.hadoop.hbase.regionserver">TestSwitchToStreamRead.MatchLastRowFilterRowFilter</a></dt>
+<dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/HBaseClusterManager.html#exec-java.lang.String-org.apache.hadoop.hbase.ClusterManager.ServiceType-java.lang.String...-">exec(String, ClusterManager.ServiceType, String...)</a></span> - Method in class org.apache.hadoop.hbase.<a href="org/apache/hadoop/hbase/HBaseClusterManager.html" title="class in org.apache.hadoop.hbase">HBaseClusterManager</a></dt>
 <dd>
 <div class="block">Execute the given command on the host using SSH</div>
@@ -14169,6 +14171,10 @@
 <dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/regionserver/TestScannerHeartbeatMessages.SparseCellFilter.html#filterCell-org.apache.hadoop.hbase.Cell-">filterCell(Cell)</a></span> - Method in class org.apache.hadoop.hbase.regionserver.<a href="org/apache/hadoop/hbase/regionserver/TestScannerHeartbeatMessages.SparseCellFilter.html" title="class in org.apache.hadoop.hbase.regionserver">TestScannerHeartbeatMessages.SparseCellFilter</a></dt>
 <dd>&nbsp;</dd>
+<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextColFilter.html#filterCell-org.apache.hadoop.hbase.Cell-">filterCell(Cell)</a></span> - Method in class org.apache.hadoop.hbase.regionserver.<a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextColFilter.html" title="class in org.apache.hadoop.hbase.regionserver">TestSwitchToStreamRead.MatchLastRowCellNextColFilter</a></dt>
+<dd>&nbsp;</dd>
+<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextRowFilter.html#filterCell-org.apache.hadoop.hbase.Cell-">filterCell(Cell)</a></span> - Method in class org.apache.hadoop.hbase.regionserver.<a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextRowFilter.html" title="class in org.apache.hadoop.hbase.regionserver">TestSwitchToStreamRead.MatchLastRowCellNextRowFilter</a></dt>
+<dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/http/TestGlobalFilter.RecordingFilter.html#filterConfig">filterConfig</a></span> - Variable in class org.apache.hadoop.hbase.http.<a href="org/apache/hadoop/hbase/http/TestGlobalFilter.RecordingFilter.html" title="class in org.apache.hadoop.hbase.http">TestGlobalFilter.RecordingFilter</a></dt>
 <dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/http/TestPathFilter.RecordingFilter.html#filterConfig">filterConfig</a></span> - Variable in class org.apache.hadoop.hbase.http.<a href="org/apache/hadoop/hbase/http/TestPathFilter.RecordingFilter.html" title="class in org.apache.hadoop.hbase.http">TestPathFilter.RecordingFilter</a></dt>
@@ -14195,8 +14201,12 @@
 <dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/filter/TestFilter.SlowScanFilter.html#filterRow--">filterRow()</a></span> - Method in class org.apache.hadoop.hbase.filter.<a href="org/apache/hadoop/hbase/filter/TestFilter.SlowScanFilter.html" title="class in org.apache.hadoop.hbase.filter">TestFilter.SlowScanFilter</a></dt>
 <dd>&nbsp;</dd>
+<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html#filterRow--">filterRow()</a></span> - Method in class org.apache.hadoop.hbase.regionserver.<a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html" title="class in org.apache.hadoop.hbase.regionserver">TestSwitchToStreamRead.MatchLastRowFilterRowFilter</a></dt>
+<dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/filter/TestInvocationRecordFilter.InvocationRecordFilter.html#filterRowCells-java.util.List-">filterRowCells(List&lt;Cell&gt;)</a></span> - Method in class org.apache.hadoop.hbase.filter.<a href="org/apache/hadoop/hbase/filter/TestInvocationRecordFilter.InvocationRecordFilter.html" title="class in org.apache.hadoop.hbase.filter">TestInvocationRecordFilter.InvocationRecordFilter</a></dt>
 <dd>&nbsp;</dd>
+<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html#filterRowCells-java.util.List-">filterRowCells(List&lt;Cell&gt;)</a></span> - Method in class org.apache.hadoop.hbase.regionserver.<a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html" title="class in org.apache.hadoop.hbase.regionserver">TestSwitchToStreamRead.MatchLastRowFilterRowFilter</a></dt>
+<dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/client/TestConnectionImplementation.BlockingFilter.html#filterRowKey-byte:A-int-int-">filterRowKey(byte[], int, int)</a></span> - Method in class org.apache.hadoop.hbase.client.<a href="org/apache/hadoop/hbase/client/TestConnectionImplementation.BlockingFilter.html" title="class in org.apache.hadoop.hbase.client">TestConnectionImplementation.BlockingFilter</a></dt>
 <dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/filter/FilterAllFilter.html#filterRowKey-org.apache.hadoop.hbase.Cell-">filterRowKey(Cell)</a></span> - Method in class org.apache.hadoop.hbase.filter.<a href="org/apache/hadoop/hbase/filter/FilterAllFilter.html" title="class in org.apache.hadoop.hbase.filter">FilterAllFilter</a></dt>
@@ -14205,6 +14215,8 @@
 <dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/regionserver/TestScannerHeartbeatMessages.SparseRowFilter.html#filterRowKey-org.apache.hadoop.hbase.Cell-">filterRowKey(Cell)</a></span> - Method in class org.apache.hadoop.hbase.regionserver.<a href="org/apache/hadoop/hbase/regionserver/TestScannerHeartbeatMessages.SparseRowFilter.html" title="class in org.apache.hadoop.hbase.regionserver">TestScannerHeartbeatMessages.SparseRowFilter</a></dt>
 <dd>&nbsp;</dd>
+<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowKeyFilter.html#filterRowKey-org.apache.hadoop.hbase.Cell-">filterRowKey(Cell)</a></span> - Method in class org.apache.hadoop.hbase.regionserver.<a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowKeyFilter.html" title="class in org.apache.hadoop.hbase.regionserver">TestSwitchToStreamRead.MatchLastRowKeyFilter</a></dt>
+<dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/rest/TestTableScan.CustomFilter.html#filterRowKey-byte:A-int-int-">filterRowKey(byte[], int, int)</a></span> - Method in class org.apache.hadoop.hbase.rest.<a href="org/apache/hadoop/hbase/rest/TestTableScan.CustomFilter.html" title="class in org.apache.hadoop.hbase.rest">TestTableScan.CustomFilter</a></dt>
 <dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/client/TestOperation.html#FILTERS">FILTERS</a></span> - Static variable in class org.apache.hadoop.hbase.client.<a href="org/apache/hadoop/hbase/client/TestOperation.html" title="class in org.apache.hadoop.hbase.client">TestOperation</a></dt>
@@ -15288,6 +15300,8 @@
 <dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/regionserver/TestHeapMemoryManager.BlockCacheStub.html#getBlock-org.apache.hadoop.hbase.io.hfile.BlockCacheKey-boolean-boolean-boolean-">getBlock(BlockCacheKey, boolean, boolean, boolean)</a></span> - Method in class org.apache.hadoop.hbase.regionserver.<a href="org/apache/hadoop/hbase/regionserver/TestHeapMemoryManager.BlockCacheStub.html" title="class in org.apache.hadoop.hbase.regionserver">TestHeapMemoryManager.BlockCacheStub</a></dt>
 <dd>&nbsp;</dd>
+<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/io/hfile/CacheTestUtils.html#getBlockAndAssertEquals-org.apache.hadoop.hbase.io.hfile.BlockCache-org.apache.hadoop.hbase.io.hfile.BlockCacheKey-org.apache.hadoop.hbase.io.hfile.Cacheable-java.nio.ByteBuffer-java.nio.ByteBuffer-">getBlockAndAssertEquals(BlockCache, BlockCacheKey, Cacheable, ByteBuffer, ByteBuffer)</a></span> - Static method in class org.apache.hadoop.hbase.io.hfile.<a href="org/apache/hadoop/hbase/io/hfile/CacheTestUtils.html" title="class in org.apache.hadoop.hbase.io.hfile">CacheTestUtils</a></dt>
+<dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/regionserver/MetricsRegionServerWrapperStub.html#getBlockCacheCount--">getBlockCacheCount()</a></span> - Method in class org.apache.hadoop.hbase.regionserver.<a href="org/apache/hadoop/hbase/regionserver/MetricsRegionServerWrapperStub.html" title="class in org.apache.hadoop.hbase.regionserver">MetricsRegionServerWrapperStub</a></dt>
 <dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/regionserver/MetricsRegionServerWrapperStub.html#getBlockCacheEvictedCount--">getBlockCacheEvictedCount()</a></span> - Method in class org.apache.hadoop.hbase.regionserver.<a href="org/apache/hadoop/hbase/regionserver/MetricsRegionServerWrapperStub.html" title="class in org.apache.hadoop.hbase.regionserver">MetricsRegionServerWrapperStub</a></dt>
@@ -19097,6 +19111,8 @@
 <dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/filter/TestInvocationRecordFilter.InvocationRecordFilter.html#hasFilterRow--">hasFilterRow()</a></span> - Method in class org.apache.hadoop.hbase.filter.<a href="org/apache/hadoop/hbase/filter/TestInvocationRecordFilter.InvocationRecordFilter.html" title="class in org.apache.hadoop.hbase.filter">TestInvocationRecordFilter.InvocationRecordFilter</a></dt>
 <dd>&nbsp;</dd>
+<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html#hasFilterRow--">hasFilterRow()</a></span> - Method in class org.apache.hadoop.hbase.regionserver.<a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html" title="class in org.apache.hadoop.hbase.regionserver">TestSwitchToStreamRead.MatchLastRowFilterRowFilter</a></dt>
+<dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/security/access/TestAccessController.html#hasFoundUserPermission-java.util.List-java.util.List-">hasFoundUserPermission(List&lt;UserPermission&gt;, List&lt;UserPermission&gt;)</a></span> - Method in class org.apache.hadoop.hbase.security.access.<a href="org/apache/hadoop/hbase/security/access/TestAccessController.html" title="class in org.apache.hadoop.hbase.security.access">TestAccessController</a></dt>
 <dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/security/access/TestAccessController.html#hasFoundUserPermission-org.apache.hadoop.hbase.security.access.UserPermission-java.util.List-">hasFoundUserPermission(UserPermission, List&lt;UserPermission&gt;)</a></span> - Method in class org.apache.hadoop.hbase.security.access.<a href="org/apache/hadoop/hbase/security/access/TestAccessController.html" title="class in org.apache.hadoop.hbase.security.access">TestAccessController</a></dt>
@@ -24495,6 +24511,14 @@
 <dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/regionserver/TestBulkLoad.WalMatcher.html#matchesSafely-org.apache.hadoop.hbase.wal.WALEdit-">matchesSafely(WALEdit)</a></span> - Method in class org.apache.hadoop.hbase.regionserver.<a href="org/apache/hadoop/hbase/regionserver/TestBulkLoad.WalMatcher.html" title="class in org.apache.hadoop.hbase.regionserver">TestBulkLoad.WalMatcher</a></dt>
 <dd>&nbsp;</dd>
+<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextColFilter.html#MatchLastRowCellNextColFilter--">MatchLastRowCellNextColFilter()</a></span> - Constructor for class org.apache.hadoop.hbase.regionserver.<a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextColFilter.html" title="class in org.apache.hadoop.hbase.regionserver">TestSwitchToStreamRead.MatchLastRowCellNextColFilter</a></dt>
+<dd>&nbsp;</dd>
+<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextRowFilter.html#MatchLastRowCellNextRowFilter--">MatchLastRowCellNextRowFilter()</a></span> - Constructor for class org.apache.hadoop.hbase.regionserver.<a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextRowFilter.html" title="class in org.apache.hadoop.hbase.regionserver">TestSwitchToStreamRead.MatchLastRowCellNextRowFilter</a></dt>
+<dd>&nbsp;</dd>
+<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html#MatchLastRowFilterRowFilter--">MatchLastRowFilterRowFilter()</a></span> - Constructor for class org.apache.hadoop.hbase.regionserver.<a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html" title="class in org.apache.hadoop.hbase.regionserver">TestSwitchToStreamRead.MatchLastRowFilterRowFilter</a></dt>
+<dd>&nbsp;</dd>
+<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowKeyFilter.html#MatchLastRowKeyFilter--">MatchLastRowKeyFilter()</a></span> - Constructor for class org.apache.hadoop.hbase.regionserver.<a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowKeyFilter.html" title="class in org.apache.hadoop.hbase.regionserver">TestSwitchToStreamRead.MatchLastRowKeyFilter</a></dt>
+<dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/security/visibility/ExpAsStringVisibilityLabelServiceImpl.html#matchVisibility-java.util.List-java.lang.Byte-java.util.List-java.lang.Byte-">matchVisibility(List&lt;Tag&gt;, Byte, List&lt;Tag&gt;, Byte)</a></span> - Method in class org.apache.hadoop.hbase.security.visibility.<a href="org/apache/hadoop/hbase/security/visibility/ExpAsStringVisibilityLabelServiceImpl.html" title="class in org.apache.hadoop.hbase.security.visibility">ExpAsStringVisibilityLabelServiceImpl</a></dt>
 <dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/io/hfile/KeySampler.html#max">max</a></span> - Variable in class org.apache.hadoop.hbase.io.hfile.<a href="org/apache/hadoop/hbase/io/hfile/KeySampler.html" title="class in org.apache.hadoop.hbase.io.hfile">KeySampler</a></dt>
@@ -32338,6 +32362,8 @@
 <dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/procedure2/ProcedureTestingUtility.LoadCounter.html#reset-java.util.Set-">reset(Set&lt;Long&gt;)</a></span> - Method in class org.apache.hadoop.hbase.procedure2.<a href="org/apache/hadoop/hbase/procedure2/ProcedureTestingUtility.LoadCounter.html" title="class in org.apache.hadoop.hbase.procedure2">ProcedureTestingUtility.LoadCounter</a></dt>
 <dd>&nbsp;</dd>
+<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html#reset--">reset()</a></span> - Method in class org.apache.hadoop.hbase.regionserver.<a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html" title="class in org.apache.hadoop.hbase.regionserver">TestSwitchToStreamRead.MatchLastRowFilterRowFilter</a></dt>
+<dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/replication/regionserver/TestSerialReplicationEndpoint.TestEndpoint.html#reset--">reset()</a></span> - Static method in class org.apache.hadoop.hbase.replication.regionserver.<a href="org/apache/hadoop/hbase/replication/regionserver/TestSerialReplicationEndpoint.TestEndpoint.html" title="class in org.apache.hadoop.hbase.replication.regionserver">TestSerialReplicationEndpoint.TestEndpoint</a></dt>
 <dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/replication/TestReplicationProcedureRetry.MockHMaster.html#reset-boolean-">reset(boolean)</a></span> - Method in class org.apache.hadoop.hbase.replication.<a href="org/apache/hadoop/hbase/replication/TestReplicationProcedureRetry.MockHMaster.html" title="class in org.apache.hadoop.hbase.replication">TestReplicationProcedureRetry.MockHMaster</a></dt>
@@ -34842,11 +34868,11 @@
 <dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/filter/TestSingleColumnValueFilter.html#serializationTest-org.apache.hadoop.hbase.filter.Filter-">serializationTest(Filter)</a></span> - Method in class org.apache.hadoop.hbase.filter.<a href="org/apache/hadoop/hbase/filter/TestSingleColumnValueFilter.html" title="class in org.apache.hadoop.hbase.filter">TestSingleColumnValueFilter</a></dt>
 <dd>&nbsp;</dd>
-<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/io/hfile/CacheTestUtils.ByteArrayCacheable.html#serialize-java.nio.ByteBuffer-">serialize(ByteBuffer)</a></span> - Method in class org.apache.hadoop.hbase.io.hfile.<a href="org/apache/hadoop/hbase/io/hfile/CacheTestUtils.ByteArrayCacheable.html" title="class in org.apache.hadoop.hbase.io.hfile">CacheTestUtils.ByteArrayCacheable</a></dt>
+<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/io/hfile/CacheTestUtils.ByteArrayCacheable.html#serialize-java.nio.ByteBuffer-boolean-">serialize(ByteBuffer, boolean)</a></span> - Method in class org.apache.hadoop.hbase.io.hfile.<a href="org/apache/hadoop/hbase/io/hfile/CacheTestUtils.ByteArrayCacheable.html" title="class in org.apache.hadoop.hbase.io.hfile">CacheTestUtils.ByteArrayCacheable</a></dt>
 <dd>&nbsp;</dd>
-<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/io/hfile/TestCacheConfig.DataCacheEntry.html#serialize-java.nio.ByteBuffer-">serialize(ByteBuffer)</a></span> - Method in class org.apache.hadoop.hbase.io.hfile.<a href="org/apache/hadoop/hbase/io/hfile/TestCacheConfig.DataCacheEntry.html" title="class in org.apache.hadoop.hbase.io.hfile">TestCacheConfig.DataCacheEntry</a></dt>
+<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/io/hfile/TestCacheConfig.DataCacheEntry.html#serialize-java.nio.ByteBuffer-boolean-">serialize(ByteBuffer, boolean)</a></span> - Method in class org.apache.hadoop.hbase.io.hfile.<a href="org/apache/hadoop/hbase/io/hfile/TestCacheConfig.DataCacheEntry.html" title="class in org.apache.hadoop.hbase.io.hfile">TestCacheConfig.DataCacheEntry</a></dt>
 <dd>&nbsp;</dd>
-<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.CachedItem.html#serialize-java.nio.ByteBuffer-">serialize(ByteBuffer)</a></span> - Method in class org.apache.hadoop.hbase.io.hfile.<a href="org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.CachedItem.html" title="class in org.apache.hadoop.hbase.io.hfile">TestLruBlockCache.CachedItem</a></dt>
+<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.CachedItem.html#serialize-java.nio.ByteBuffer-boolean-">serialize(ByteBuffer, boolean)</a></span> - Method in class org.apache.hadoop.hbase.io.hfile.<a href="org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.CachedItem.html" title="class in org.apache.hadoop.hbase.io.hfile">TestLruBlockCache.CachedItem</a></dt>
 <dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/io/hfile/TestFixedFileTrailer.html#serializeAsWritable-java.io.DataOutputStream-org.apache.hadoop.hbase.io.hfile.FixedFileTrailer-">serializeAsWritable(DataOutputStream, FixedFileTrailer)</a></span> - Method in class org.apache.hadoop.hbase.io.hfile.<a href="org/apache/hadoop/hbase/io/hfile/TestFixedFileTrailer.html" title="class in org.apache.hadoop.hbase.io.hfile">TestFixedFileTrailer</a></dt>
 <dd>&nbsp;</dd>
@@ -44845,6 +44871,10 @@
 <dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/util/TestBytes.html#TestBytes--">TestBytes()</a></span> - Constructor for class org.apache.hadoop.hbase.util.<a href="org/apache/hadoop/hbase/util/TestBytes.html" title="class in org.apache.hadoop.hbase.util">TestBytes</a></dt>
 <dd>&nbsp;</dd>
+<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html#testCacheBlockNextBlockMetadataMissing--">testCacheBlockNextBlockMetadataMissing()</a></span> - Method in class org.apache.hadoop.hbase.io.hfile.bucket.<a href="org/apache/hadoop/hbase/io/hfile/bucket/TestBucketCache.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">TestBucketCache</a></dt>
+<dd>&nbsp;</dd>
+<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html#testCacheBlockNextBlockMetadataMissing--">testCacheBlockNextBlockMetadataMissing()</a></span> - Method in class org.apache.hadoop.hbase.io.hfile.<a href="org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.html" title="class in org.apache.hadoop.hbase.io.hfile">TestLruBlockCache</a></dt>
+<dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/io/hfile/TestForceCacheImportantBlocks.html#testCacheBlocks--">testCacheBlocks()</a></span> - Method in class org.apache.hadoop.hbase.io.hfile.<a href="org/apache/hadoop/hbase/io/hfile/TestForceCacheImportantBlocks.html" title="class in org.apache.hadoop.hbase.io.hfile">TestForceCacheImportantBlocks</a></dt>
 <dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/client/TestMetaCache.html#testCacheClearingOnCallQueueTooBig--">testCacheClearingOnCallQueueTooBig()</a></span> - Method in class org.apache.hadoop.hbase.client.<a href="org/apache/hadoop/hbase/client/TestMetaCache.html" title="class in org.apache.hadoop.hbase.client">TestMetaCache</a></dt>
@@ -48832,6 +48862,8 @@
 <dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/http/lib/TestStaticUserWebFilter.html#testFilter--">testFilter()</a></span> - Method in class org.apache.hadoop.hbase.http.lib.<a href="org/apache/hadoop/hbase/http/lib/TestStaticUserWebFilter.html" title="class in org.apache.hadoop.hbase.http.lib">TestStaticUserWebFilter</a></dt>
 <dd>&nbsp;</dd>
+<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html#testFilter-org.apache.hadoop.hbase.filter.Filter-">testFilter(Filter)</a></span> - Method in class org.apache.hadoop.hbase.regionserver.<a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html" title="class in org.apache.hadoop.hbase.regionserver">TestSwitchToStreamRead</a></dt>
+<dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/rest/TestResourceFilter.html#testFilter--">testFilter()</a></span> - Method in class org.apache.hadoop.hbase.rest.<a href="org/apache/hadoop/hbase/rest/TestResourceFilter.html" title="class in org.apache.hadoop.hbase.rest">TestResourceFilter</a></dt>
 <dd>&nbsp;</dd>
 <dt><a href="org/apache/hadoop/hbase/filter/TestFilter.OldTestFilter.html" title="class in org.apache.hadoop.hbase.filter"><span class="typeNameLink">TestFilter.OldTestFilter</span></a> - Class in <a href="org/apache/hadoop/hbase/filter/package-summary.html">org.apache.hadoop.hbase.filter</a></dt>
@@ -48857,6 +48889,10 @@
 <dd>
 <div class="block">Test the overridden functionality of filterCell(Cell)</div>
 </dd>
+<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html#testFilterCellNextCol--">testFilterCellNextCol()</a></span> - Method in class org.apache.hadoop.hbase.regionserver.<a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html" title="class in org.apache.hadoop.hbase.regionserver">TestSwitchToStreamRead</a></dt>
+<dd>&nbsp;</dd>
+<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html#testFilterCellNextRow--">testFilterCellNextRow()</a></span> - Method in class org.apache.hadoop.hbase.regionserver.<a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html" title="class in org.apache.hadoop.hbase.regionserver">TestSwitchToStreamRead</a></dt>
+<dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/filter/TestDependentColumnFilter.html#testFilterDropping--">testFilterDropping()</a></span> - Method in class org.apache.hadoop.hbase.filter.<a href="org/apache/hadoop/hbase/filter/TestDependentColumnFilter.html" title="class in org.apache.hadoop.hbase.filter">TestDependentColumnFilter</a></dt>
 <dd>
 <div class="block">Test that the filter correctly drops rows without a corresponding timestamp</div>
@@ -48931,6 +48967,10 @@
 <dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/thrift2/TestThriftHBaseServiceHandler.html#testFilterRegistration--">testFilterRegistration()</a></span> - Method in class org.apache.hadoop.hbase.thrift2.<a href="org/apache/hadoop/hbase/thrift2/TestThriftHBaseServiceHandler.html" title="class in org.apache.hadoop.hbase.thrift2">TestThriftHBaseServiceHandler</a></dt>
 <dd>&nbsp;</dd>
+<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html#testFilterRow--">testFilterRow()</a></span> - Method in class org.apache.hadoop.hbase.regionserver.<a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html" title="class in org.apache.hadoop.hbase.regionserver">TestSwitchToStreamRead</a></dt>
+<dd>&nbsp;</dd>
+<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html#testFilterRowKey--">testFilterRowKey()</a></span> - Method in class org.apache.hadoop.hbase.regionserver.<a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html" title="class in org.apache.hadoop.hbase.regionserver">TestSwitchToStreamRead</a></dt>
+<dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/client/TestFromClientSide.html#testFilters--">testFilters()</a></span> - Method in class org.apache.hadoop.hbase.client.<a href="org/apache/hadoop/hbase/client/TestFromClientSide.html" title="class in org.apache.hadoop.hbase.client">TestFromClientSide</a></dt>
 <dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/regionserver/TestMinVersions.html#testFilters--">testFilters()</a></span> - Method in class org.apache.hadoop.hbase.regionserver.<a href="org/apache/hadoop/hbase/regionserver/TestMinVersions.html" title="class in org.apache.hadoop.hbase.regionserver">TestMinVersions</a></dt>
@@ -59462,6 +59502,8 @@
 <div class="block">Test for <code>HFileOutputFormat2#configureDataBlockEncoding(HTableDescriptor, Configuration)</code>
  and <code>HFileOutputFormat2.createFamilyDataBlockEncodingMap(Configuration)</code>.</div>
 </dd>
+<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/io/hfile/TestHFileBlock.html#testSerializeWithoutNextBlockMetadata--">testSerializeWithoutNextBlockMetadata()</a></span> - Method in class org.apache.hadoop.hbase.io.hfile.<a href="org/apache/hadoop/hbase/io/hfile/TestHFileBlock.html" title="class in org.apache.hadoop.hbase.io.hfile">TestHFileBlock</a></dt>
+<dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/replication/regionserver/TestSerialReplicationEndpoint.html#testSerialReplicate--">testSerialReplicate()</a></span> - Method in class org.apache.hadoop.hbase.replication.regionserver.<a href="org/apache/hadoop/hbase/replication/regionserver/TestSerialReplicationEndpoint.html" title="class in org.apache.hadoop.hbase.replication.regionserver">TestSerialReplicationEndpoint</a></dt>
 <dd>&nbsp;</dd>
 <dt><a href="org/apache/hadoop/hbase/replication/TestSerialReplication.html" title="class in org.apache.hadoop.hbase.replication"><span class="typeNameLink">TestSerialReplication</span></a> - Class in <a href="org/apache/hadoop/hbase/replication/package-summary.html">org.apache.hadoop.hbase.replication</a></dt>
@@ -61054,6 +61096,14 @@
 <dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html#TestSwitchToStreamRead--">TestSwitchToStreamRead()</a></span> - Constructor for class org.apache.hadoop.hbase.regionserver.<a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.html" title="class in org.apache.hadoop.hbase.regionserver">TestSwitchToStreamRead</a></dt>
 <dd>&nbsp;</dd>
+<dt><a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextColFilter.html" title="class in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">TestSwitchToStreamRead.MatchLastRowCellNextColFilter</span></a> - Class in <a href="org/apache/hadoop/hbase/regionserver/package-summary.html">org.apache.hadoop.hbase.regionserver</a></dt>
+<dd>&nbsp;</dd>
+<dt><a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowCellNextRowFilter.html" title="class in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">TestSwitchToStreamRead.MatchLastRowCellNextRowFilter</span></a> - Class in <a href="org/apache/hadoop/hbase/regionserver/package-summary.html">org.apache.hadoop.hbase.regionserver</a></dt>
+<dd>&nbsp;</dd>
+<dt><a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowFilterRowFilter.html" title="class in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">TestSwitchToStreamRead.MatchLastRowFilterRowFilter</span></a> - Class in <a href="org/apache/hadoop/hbase/regionserver/package-summary.html">org.apache.hadoop.hbase.regionserver</a></dt>
+<dd>&nbsp;</dd>
+<dt><a href="org/apache/hadoop/hbase/regionserver/TestSwitchToStreamRead.MatchLastRowKeyFilter.html" title="class in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">TestSwitchToStreamRead.MatchLastRowKeyFilter</span></a> - Class in <a href="org/apache/hadoop/hbase/regionserver/package-summary.html">org.apache.hadoop.hbase.regionserver</a></dt>
+<dd>&nbsp;</dd>
 <dt><a href="org/apache/hadoop/hbase/regionserver/wal/TestSyncFuture.html" title="class in org.apache.hadoop.hbase.regionserver.wal"><span class="typeNameLink">TestSyncFuture</span></a> - Class in <a href="org/apache/hadoop/hbase/regionserver/wal/package-summary.html">org.apache.hadoop.hbase.regionserver.wal</a></dt>
 <dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/regionserver/wal/TestSyncFuture.html#TestSyncFuture--">TestSyncFuture()</a></span> - Constructor for class org.apache.hadoop.hbase.regionserver.wal.<a href="org/apache/hadoop/hbase/regionserver/wal/TestSyncFuture.html" title="class in org.apache.hadoop.hbase.regionserver.wal">TestSyncFuture</a></dt>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/org/apache/hadoop/hbase/backup/package-tree.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/org/apache/hadoop/hbase/backup/package-tree.html b/testdevapidocs/org/apache/hadoop/hbase/backup/package-tree.html
index 3168ee3..e159b3f 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/backup/package-tree.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/backup/package-tree.html
@@ -145,8 +145,8 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true" title="class or interface in java.io">Serializable</a>)
 <ul>
-<li type="circle">org.apache.hadoop.hbase.backup.<a href="../../../../../org/apache/hadoop/hbase/backup/TestIncrementalBackupMergeWithFailures.FailurePhase.html" title="enum in org.apache.hadoop.hbase.backup"><span class="typeNameLink">TestIncrementalBackupMergeWithFailures.FailurePhase</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.backup.<a href="../../../../../org/apache/hadoop/hbase/backup/TestBackupDeleteWithFailures.Failure.html" title="enum in org.apache.hadoop.hbase.backup"><span class="typeNameLink">TestBackupDeleteWithFailures.Failure</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.backup.<a href="../../../../../org/apache/hadoop/hbase/backup/TestIncrementalBackupMergeWithFailures.FailurePhase.html" title="enum in org.apache.hadoop.hbase.backup"><span class="typeNameLink">TestIncrementalBackupMergeWithFailures.FailurePhase</span></a></li>
 </ul>
 </li>
 </ul>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/org/apache/hadoop/hbase/io/hfile/CacheTestUtils.ByteArrayCacheable.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/org/apache/hadoop/hbase/io/hfile/CacheTestUtils.ByteArrayCacheable.html b/testdevapidocs/org/apache/hadoop/hbase/io/hfile/CacheTestUtils.ByteArrayCacheable.html
index 525b490..535b603 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/io/hfile/CacheTestUtils.ByteArrayCacheable.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/io/hfile/CacheTestUtils.ByteArrayCacheable.html
@@ -219,7 +219,8 @@ implements org.apache.hadoop.hbase.io.hfile.Cacheable</pre>
 </tr>
 <tr id="i5" class="rowColor">
 <td class="colFirst"><code>void</code></td>
-<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/CacheTestUtils.ByteArrayCacheable.html#serialize-java.nio.ByteBuffer-">serialize</a></span>(<a href="https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html?is-external=true" title="class or interface in java.nio">ByteBuffer</a>&nbsp;destination)</code>&nbsp;</td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/CacheTestUtils.ByteArrayCacheable.html#serialize-java.nio.ByteBuffer-boolean-">serialize</a></span>(<a href="https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html?is-external=true" title="class or interface in java.nio">ByteBuffer</a>&nbsp;destination,
+         boolean&nbsp;includeNextBlockMetadata)</code>&nbsp;</td>
 </tr>
 </table>
 <ul class="blockList">
@@ -321,13 +322,14 @@ implements org.apache.hadoop.hbase.io.hfile.Cacheable</pre>
 </dl>
 </li>
 </ul>
-<a name="serialize-java.nio.ByteBuffer-">
+<a name="serialize-java.nio.ByteBuffer-boolean-">
 <!--   -->
 </a>
 <ul class="blockList">
 <li class="blockList">
 <h4>serialize</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/CacheTestUtils.ByteArrayCacheable.html#line.314">serialize</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html?is-external=true" title="class or interface in java.nio">ByteBuffer</a>&nbsp;destination)</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/CacheTestUtils.ByteArrayCacheable.html#line.314">serialize</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html?is-external=true" title="class or interface in java.nio">ByteBuffer</a>&nbsp;destination,
+                      boolean&nbsp;includeNextBlockMetadata)</pre>
 <dl>
 <dt><span class="overrideSpecifyLabel">Specified by:</span></dt>
 <dd><code>serialize</code>&nbsp;in interface&nbsp;<code>org.apache.hadoop.hbase.io.hfile.Cacheable</code></dd>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/org/apache/hadoop/hbase/io/hfile/CacheTestUtils.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/org/apache/hadoop/hbase/io/hfile/CacheTestUtils.html b/testdevapidocs/org/apache/hadoop/hbase/io/hfile/CacheTestUtils.html
index 0861048..1054c17 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/io/hfile/CacheTestUtils.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/io/hfile/CacheTestUtils.html
@@ -18,7 +18,7 @@
     catch(err) {
     }
 //-->
-var methods = {"i0":9,"i1":9,"i2":9,"i3":9,"i4":9,"i5":9};
+var methods = {"i0":9,"i1":9,"i2":9,"i3":9,"i4":9,"i5":9,"i6":9};
 var tabs = {65535:["t0","All Methods"],1:["t1","Static Methods"],8:["t4","Concrete Methods"]};
 var altColor = "altColor";
 var rowColor = "rowColor";
@@ -195,19 +195,27 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 </tr>
 <tr id="i1" class="rowColor">
 <td class="colFirst"><code>static void</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/CacheTestUtils.html#getBlockAndAssertEquals-org.apache.hadoop.hbase.io.hfile.BlockCache-org.apache.hadoop.hbase.io.hfile.BlockCacheKey-org.apache.hadoop.hbase.io.hfile.Cacheable-java.nio.ByteBuffer-java.nio.ByteBuffer-">getBlockAndAssertEquals</a></span>(org.apache.hadoop.hbase.io.hfile.BlockCache&nbsp;cache,
+                       org.apache.hadoop.hbase.io.hfile.BlockCacheKey&nbsp;key,
+                       org.apache.hadoop.hbase.io.hfile.Cacheable&nbsp;blockToCache,
+                       <a href="https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html?is-external=true" title="class or interface in java.nio">ByteBuffer</a>&nbsp;destBuffer,
+                       <a href="https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html?is-external=true" title="class or interface in java.nio">ByteBuffer</a>&nbsp;expectedBuffer)</code>&nbsp;</td>
+</tr>
+<tr id="i2" class="altColor">
+<td class="colFirst"><code>static void</code></td>
 <td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/CacheTestUtils.html#hammerEviction-org.apache.hadoop.hbase.io.hfile.BlockCache-int-int-int-">hammerEviction</a></span>(org.apache.hadoop.hbase.io.hfile.BlockCache&nbsp;toBeTested,
               int&nbsp;BlockSize,
               int&nbsp;numThreads,
               int&nbsp;numQueries)</code>&nbsp;</td>
 </tr>
-<tr id="i2" class="altColor">
+<tr id="i3" class="rowColor">
 <td class="colFirst"><code>static void</code></td>
 <td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/CacheTestUtils.html#hammerSingleKey-org.apache.hadoop.hbase.io.hfile.BlockCache-int-int-int-">hammerSingleKey</a></span>(org.apache.hadoop.hbase.io.hfile.BlockCache&nbsp;toBeTested,
                int&nbsp;BlockSize,
                int&nbsp;numThreads,
                int&nbsp;numQueries)</code>&nbsp;</td>
 </tr>
-<tr id="i3" class="rowColor">
+<tr id="i4" class="altColor">
 <td class="colFirst"><code>static void</code></td>
 <td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/CacheTestUtils.html#testCacheMultiThreaded-org.apache.hadoop.hbase.io.hfile.BlockCache-int-int-int-double-">testCacheMultiThreaded</a></span>(org.apache.hadoop.hbase.io.hfile.BlockCache&nbsp;toBeTested,
                       int&nbsp;blockSize,
@@ -215,13 +223,13 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
                       int&nbsp;numQueries,
                       double&nbsp;passingScore)</code>&nbsp;</td>
 </tr>
-<tr id="i4" class="altColor">
+<tr id="i5" class="rowColor">
 <td class="colFirst"><code>static void</code></td>
 <td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/CacheTestUtils.html#testCacheSimple-org.apache.hadoop.hbase.io.hfile.BlockCache-int-int-">testCacheSimple</a></span>(org.apache.hadoop.hbase.io.hfile.BlockCache&nbsp;toBeTested,
                int&nbsp;blockSize,
                int&nbsp;numBlocks)</code>&nbsp;</td>
 </tr>
-<tr id="i5" class="rowColor">
+<tr id="i6" class="altColor">
 <td class="colFirst"><code>static void</code></td>
 <td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/CacheTestUtils.html#testHeapSizeChanges-org.apache.hadoop.hbase.io.hfile.BlockCache-int-">testHeapSizeChanges</a></span>(org.apache.hadoop.hbase.io.hfile.BlockCache&nbsp;toBeTested,
                    int&nbsp;blockSize)</code>
@@ -372,13 +380,26 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <a name="generateHFileBlocks-int-int-">
 <!--   -->
 </a>
-<ul class="blockListLast">
+<ul class="blockList">
 <li class="blockList">
 <h4>generateHFileBlocks</h4>
 <pre>public static&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/CacheTestUtils.HFileBlockPair.html" title="class in org.apache.hadoop.hbase.io.hfile">CacheTestUtils.HFileBlockPair</a>[]&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/CacheTestUtils.html#line.344">generateHFileBlocks</a>(int&nbsp;blockSize,
                                                                   int&nbsp;numBlocks)</pre>
 </li>
 </ul>
+<a name="getBlockAndAssertEquals-org.apache.hadoop.hbase.io.hfile.BlockCache-org.apache.hadoop.hbase.io.hfile.BlockCacheKey-org.apache.hadoop.hbase.io.hfile.Cacheable-java.nio.ByteBuffer-java.nio.ByteBuffer-">
+<!--   -->
+</a>
+<ul class="blockListLast">
+<li class="blockList">
+<h4>getBlockAndAssertEquals</h4>
+<pre>public static&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/CacheTestUtils.html#line.402">getBlockAndAssertEquals</a>(org.apache.hadoop.hbase.io.hfile.BlockCache&nbsp;cache,
+                                           org.apache.hadoop.hbase.io.hfile.BlockCacheKey&nbsp;key,
+                                           org.apache.hadoop.hbase.io.hfile.Cacheable&nbsp;blockToCache,
+                                           <a href="https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html?is-external=true" title="class or interface in java.nio">ByteBuffer</a>&nbsp;destBuffer,
+                                           <a href="https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html?is-external=true" title="class or interface in java.nio">ByteBuffer</a>&nbsp;expectedBuffer)</pre>
+</li>
+</ul>
 </li>
 </ul>
 </li>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/org/apache/hadoop/hbase/io/hfile/TestCacheConfig.DataCacheEntry.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/org/apache/hadoop/hbase/io/hfile/TestCacheConfig.DataCacheEntry.html b/testdevapidocs/org/apache/hadoop/hbase/io/hfile/TestCacheConfig.DataCacheEntry.html
index 7b0924c..739c24c 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/io/hfile/TestCacheConfig.DataCacheEntry.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/io/hfile/TestCacheConfig.DataCacheEntry.html
@@ -226,7 +226,8 @@ implements org.apache.hadoop.hbase.io.hfile.Cacheable</pre>
 </tr>
 <tr id="i5" class="rowColor">
 <td class="colFirst"><code>void</code></td>
-<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestCacheConfig.DataCacheEntry.html#serialize-java.nio.ByteBuffer-">serialize</a></span>(<a href="https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html?is-external=true" title="class or interface in java.nio">ByteBuffer</a>&nbsp;destination)</code>&nbsp;</td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestCacheConfig.DataCacheEntry.html#serialize-java.nio.ByteBuffer-boolean-">serialize</a></span>(<a href="https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html?is-external=true" title="class or interface in java.nio">ByteBuffer</a>&nbsp;destination,
+         boolean&nbsp;includeNextBlockMetadata)</code>&nbsp;</td>
 </tr>
 <tr id="i6" class="altColor">
 <td class="colFirst"><code><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a></code></td>
@@ -358,13 +359,14 @@ implements org.apache.hadoop.hbase.io.hfile.Cacheable</pre>
 </dl>
 </li>
 </ul>
-<a name="serialize-java.nio.ByteBuffer-">
+<a name="serialize-java.nio.ByteBuffer-boolean-">
 <!--   -->
 </a>
 <ul class="blockList">
 <li class="blockList">
 <h4>serialize</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestCacheConfig.DataCacheEntry.html#line.139">serialize</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html?is-external=true" title="class or interface in java.nio">ByteBuffer</a>&nbsp;destination)</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestCacheConfig.DataCacheEntry.html#line.139">serialize</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html?is-external=true" title="class or interface in java.nio">ByteBuffer</a>&nbsp;destination,
+                      boolean&nbsp;includeNextBlockMetadata)</pre>
 <dl>
 <dt><span class="overrideSpecifyLabel">Specified by:</span></dt>
 <dd><code>serialize</code>&nbsp;in interface&nbsp;<code>org.apache.hadoop.hbase.io.hfile.Cacheable</code></dd>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/org/apache/hadoop/hbase/io/hfile/TestCacheConfig.IndexCacheEntry.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/org/apache/hadoop/hbase/io/hfile/TestCacheConfig.IndexCacheEntry.html b/testdevapidocs/org/apache/hadoop/hbase/io/hfile/TestCacheConfig.IndexCacheEntry.html
index dcf796c..a0f595c 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/io/hfile/TestCacheConfig.IndexCacheEntry.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/io/hfile/TestCacheConfig.IndexCacheEntry.html
@@ -210,7 +210,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestCacheCon
 <!--   -->
 </a>
 <h3>Methods inherited from class&nbsp;org.apache.hadoop.hbase.io.hfile.<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestCacheConfig.DataCacheEntry.html" title="class in org.apache.hadoop.hbase.io.hfile">TestCacheConfig.DataCacheEntry</a></h3>
-<code><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestCacheConfig.DataCacheEntry.html#getDeserializer--">getDeserializer</a>, <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestCacheConfig.DataCacheEntry.html#getMemoryType--">getMemoryType</a>, <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestCacheConfig.DataCacheEntry.html#getSerializedLength--">getSerializedLength</a>, <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestCacheConfig.DataCacheEntry.html#heapSize--">heapSize</a>, <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestCacheConfig.DataCacheEntry.html#serialize-java.nio.ByteBuffer-">serialize</a>, <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestCacheConfig.DataCacheEntry.html#toString--">toString</a></code></li>
+<code><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestCacheConfig.DataCacheEntry.html#getDeserializer--">getDeserializer</a>, <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestCacheConfig.DataCacheEntry.html#getMemoryType--">getMemoryType</a>, <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestCacheConfig.DataCacheEntry.html#getSerializedLength--">getSerializedLength</a>, <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestCacheConfig.DataCacheEntry.html#heapSize--">heapSize</a>, <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestCacheConfig.DataCacheEntry.html#serialize-java.nio.ByteBuffer-boolean-">serialize</a>, <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestCacheConfig.DataCacheEntry.html#toString--">toString</a></code></li>
 </ul>
 <ul class="blockList">
 <li class="blockList"><a name="methods.inherited.from.class.java.lang.Object">

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/org/apache/hadoop/hbase/io/hfile/TestCacheConfig.MetaCacheEntry.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/org/apache/hadoop/hbase/io/hfile/TestCacheConfig.MetaCacheEntry.html b/testdevapidocs/org/apache/hadoop/hbase/io/hfile/TestCacheConfig.MetaCacheEntry.html
index a5349b0..fe3e419 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/io/hfile/TestCacheConfig.MetaCacheEntry.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/io/hfile/TestCacheConfig.MetaCacheEntry.html
@@ -199,7 +199,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestCacheCon
 <!--   -->
 </a>
 <h3>Methods inherited from class&nbsp;org.apache.hadoop.hbase.io.hfile.<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestCacheConfig.DataCacheEntry.html" title="class in org.apache.hadoop.hbase.io.hfile">TestCacheConfig.DataCacheEntry</a></h3>
-<code><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestCacheConfig.DataCacheEntry.html#getDeserializer--">getDeserializer</a>, <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestCacheConfig.DataCacheEntry.html#getMemoryType--">getMemoryType</a>, <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestCacheConfig.DataCacheEntry.html#getSerializedLength--">getSerializedLength</a>, <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestCacheConfig.DataCacheEntry.html#heapSize--">heapSize</a>, <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestCacheConfig.DataCacheEntry.html#serialize-java.nio.ByteBuffer-">serialize</a>, <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestCacheConfig.DataCacheEntry.html#toString--">toString</a></code></li>
+<code><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestCacheConfig.DataCacheEntry.html#getDeserializer--">getDeserializer</a>, <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestCacheConfig.DataCacheEntry.html#getMemoryType--">getMemoryType</a>, <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestCacheConfig.DataCacheEntry.html#getSerializedLength--">getSerializedLength</a>, <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestCacheConfig.DataCacheEntry.html#heapSize--">heapSize</a>, <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestCacheConfig.DataCacheEntry.html#serialize-java.nio.ByteBuffer-boolean-">serialize</a>, <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestCacheConfig.DataCacheEntry.html#toString--">toString</a></code></li>
 </ul>
 <ul class="blockList">
 <li class="blockList"><a name="methods.inherited.from.class.java.lang.Object">

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/testdevapidocs/org/apache/hadoop/hbase/io/hfile/TestHFileBlock.html
----------------------------------------------------------------------
diff --git a/testdevapidocs/org/apache/hadoop/hbase/io/hfile/TestHFileBlock.html b/testdevapidocs/org/apache/hadoop/hbase/io/hfile/TestHFileBlock.html
index 33bde60..3d010ce 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/io/hfile/TestHFileBlock.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/io/hfile/TestHFileBlock.html
@@ -18,7 +18,7 @@
     catch(err) {
     }
 //-->
-var methods = {"i0":9,"i1":9,"i2":10,"i3":10,"i4":9,"i5":10,"i6":9,"i7":9,"i8":10,"i9":10,"i10":10,"i11":10,"i12":10,"i13":10,"i14":10,"i15":10,"i16":10,"i17":10,"i18":10,"i19":10,"i20":10,"i21":10,"i22":9,"i23":9};
+var methods = {"i0":9,"i1":9,"i2":10,"i3":10,"i4":9,"i5":10,"i6":9,"i7":9,"i8":10,"i9":10,"i10":10,"i11":10,"i12":10,"i13":10,"i14":10,"i15":10,"i16":10,"i17":10,"i18":10,"i19":10,"i20":10,"i21":10,"i22":10,"i23":9,"i24":9};
 var tabs = {65535:["t0","All Methods"],1:["t1","Static Methods"],2:["t2","Instance Methods"],8:["t4","Concrete Methods"]};
 var altColor = "altColor";
 var rowColor = "rowColor";
@@ -338,6 +338,10 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestHFileBlock.html#testReaderV2Internals--">testReaderV2Internals</a></span>()</code>&nbsp;</td>
 </tr>
 <tr id="i21" class="rowColor">
+<td class="colFirst"><code>void</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestHFileBlock.html#testSerializeWithoutNextBlockMetadata--">testSerializeWithoutNextBlockMetadata</a></span>()</code>&nbsp;</td>
+</tr>
+<tr id="i22" class="altColor">
 <td class="colFirst"><code>private long</code></td>
 <td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestHFileBlock.html#writeBlocks-java.util.Random-org.apache.hadoop.hbase.io.compress.Compression.Algorithm-org.apache.hadoop.fs.Path-java.util.List-java.util.List-java.util.List-java.util.List-">writeBlocks</a></span>(<a href="https://docs.oracle.com/javase/8/docs/api/java/util/Random.html?is-external=true" title="class or interface in java.util">Random</a>&nbsp;rand,
            org.apache.hadoop.hbase.io.compress.Compression.Algorithm&nbsp;compressAlgo,
@@ -347,11 +351,11 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
            <a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html?is-external=true" title="class or interface in java.util">List</a>&lt;org.apache.hadoop.hbase.io.hfile.BlockType&gt;&nbsp;expectedTypes,
            <a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html?is-external=true" title="class or interface in java.util">List</a>&lt;<a href="https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html?is-external=true" title="class or interface in java.nio">ByteBuffer</a>&gt;&nbsp;expectedContents)</code>&nbsp;</td>
 </tr>
-<tr id="i22" class="altColor">
+<tr id="i23" class="rowColor">
 <td class="colFirst"><code>(package private) static void</code></td>
 <td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestHFileBlock.html#writeTestBlockContents-java.io.DataOutputStream-">writeTestBlockContents</a></span>(<a href="https://docs.oracle.com/javase/8/docs/api/java/io/DataOutputStream.html?is-external=true" title="class or interface in java.io">DataOutputStream</a>&nbsp;dos)</code>&nbsp;</td>
 </tr>
-<tr id="i23" class="rowColor">
+<tr id="i24" class="altColor">
 <td class="colFirst"><code>(package private) static int</code></td>
 <td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestHFileBlock.html#writeTestKeyValues-org.apache.hadoop.hbase.io.hfile.HFileBlock.Writer-int-boolean-boolean-">writeTestKeyValues</a></span>(org.apache.hadoop.hbase.io.hfile.HFileBlock.Writer&nbsp;hbw,
                   int&nbsp;seed,
@@ -866,12 +870,21 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <a name="testBlockHeapSizeInternals--">
 <!--   -->
 </a>
-<ul class="blockListLast">
+<ul class="blockList">
 <li class="blockList">
 <h4>testBlockHeapSizeInternals</h4>
 <pre>protected&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestHFileBlock.html#line.829">testBlockHeapSizeInternals</a>()</pre>
 </li>
 </ul>
+<a name="testSerializeWithoutNextBlockMetadata--">
+<!--   -->
+</a>
+<ul class="blockListLast">
+<li class="blockList">
+<h4>testSerializeWithoutNextBlockMetadata</h4>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/TestHFileBlock.html#line.863">testSerializeWithoutNextBlockMetadata</a>()</pre>
+</li>
+</ul>
 </li>
 </ul>
 </li>


[22/50] hbase-site git commit: Published site at 26babcf013de696b899d76a3c39434b794440d8d.

Posted by gi...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.SharedMemoryBucketEntry.html
----------------------------------------------------------------------
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.SharedMemoryBucketEntry.html b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.SharedMemoryBucketEntry.html
index e8070ca..8cb24b3 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.SharedMemoryBucketEntry.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.SharedMemoryBucketEntry.html
@@ -433,1254 +433,1261 @@
 <span class="sourceLineNo">425</span>      return;<a name="line.425"></a>
 <span class="sourceLineNo">426</span>    }<a name="line.426"></a>
 <span class="sourceLineNo">427</span><a name="line.427"></a>
-<span class="sourceLineNo">428</span>    if (backingMap.containsKey(cacheKey)) {<a name="line.428"></a>
+<span class="sourceLineNo">428</span>    if (backingMap.containsKey(cacheKey) || ramCache.containsKey(cacheKey)) {<a name="line.428"></a>
 <span class="sourceLineNo">429</span>      Cacheable existingBlock = getBlock(cacheKey, false, false, false);<a name="line.429"></a>
-<span class="sourceLineNo">430</span>      try {<a name="line.430"></a>
-<span class="sourceLineNo">431</span>        if (BlockCacheUtil.compareCacheBlock(cachedItem, existingBlock) != 0) {<a name="line.431"></a>
-<span class="sourceLineNo">432</span>          throw new RuntimeException("Cached block contents differ, which should not have happened."<a name="line.432"></a>
-<span class="sourceLineNo">433</span>              + "cacheKey:" + cacheKey);<a name="line.433"></a>
-<span class="sourceLineNo">434</span>        }<a name="line.434"></a>
-<span class="sourceLineNo">435</span>        String msg = "Caching an already cached block: " + cacheKey;<a name="line.435"></a>
-<span class="sourceLineNo">436</span>        msg += ". This is harmless and can happen in rare cases (see HBASE-8547)";<a name="line.436"></a>
-<span class="sourceLineNo">437</span>        LOG.warn(msg);<a name="line.437"></a>
-<span class="sourceLineNo">438</span>      } finally {<a name="line.438"></a>
-<span class="sourceLineNo">439</span>        // return the block since we need to decrement the count<a name="line.439"></a>
-<span class="sourceLineNo">440</span>        returnBlock(cacheKey, existingBlock);<a name="line.440"></a>
-<span class="sourceLineNo">441</span>      }<a name="line.441"></a>
-<span class="sourceLineNo">442</span>      return;<a name="line.442"></a>
-<span class="sourceLineNo">443</span>    }<a name="line.443"></a>
-<span class="sourceLineNo">444</span><a name="line.444"></a>
-<span class="sourceLineNo">445</span>    /*<a name="line.445"></a>
-<span class="sourceLineNo">446</span>     * Stuff the entry into the RAM cache so it can get drained to the persistent store<a name="line.446"></a>
-<span class="sourceLineNo">447</span>     */<a name="line.447"></a>
-<span class="sourceLineNo">448</span>    RAMQueueEntry re =<a name="line.448"></a>
-<span class="sourceLineNo">449</span>        new RAMQueueEntry(cacheKey, cachedItem, accessCount.incrementAndGet(), inMemory);<a name="line.449"></a>
-<span class="sourceLineNo">450</span>    if (ramCache.putIfAbsent(cacheKey, re) != null) {<a name="line.450"></a>
-<span class="sourceLineNo">451</span>      return;<a name="line.451"></a>
-<span class="sourceLineNo">452</span>    }<a name="line.452"></a>
-<span class="sourceLineNo">453</span>    int queueNum = (cacheKey.hashCode() &amp; 0x7FFFFFFF) % writerQueues.size();<a name="line.453"></a>
-<span class="sourceLineNo">454</span>    BlockingQueue&lt;RAMQueueEntry&gt; bq = writerQueues.get(queueNum);<a name="line.454"></a>
-<span class="sourceLineNo">455</span>    boolean successfulAddition = false;<a name="line.455"></a>
-<span class="sourceLineNo">456</span>    if (wait) {<a name="line.456"></a>
-<span class="sourceLineNo">457</span>      try {<a name="line.457"></a>
-<span class="sourceLineNo">458</span>        successfulAddition = bq.offer(re, DEFAULT_CACHE_WAIT_TIME, TimeUnit.MILLISECONDS);<a name="line.458"></a>
-<span class="sourceLineNo">459</span>      } catch (InterruptedException e) {<a name="line.459"></a>
-<span class="sourceLineNo">460</span>        Thread.currentThread().interrupt();<a name="line.460"></a>
-<span class="sourceLineNo">461</span>      }<a name="line.461"></a>
-<span class="sourceLineNo">462</span>    } else {<a name="line.462"></a>
-<span class="sourceLineNo">463</span>      successfulAddition = bq.offer(re);<a name="line.463"></a>
-<span class="sourceLineNo">464</span>    }<a name="line.464"></a>
-<span class="sourceLineNo">465</span>    if (!successfulAddition) {<a name="line.465"></a>
-<span class="sourceLineNo">466</span>      ramCache.remove(cacheKey);<a name="line.466"></a>
-<span class="sourceLineNo">467</span>      cacheStats.failInsert();<a name="line.467"></a>
-<span class="sourceLineNo">468</span>    } else {<a name="line.468"></a>
-<span class="sourceLineNo">469</span>      this.blockNumber.increment();<a name="line.469"></a>
-<span class="sourceLineNo">470</span>      this.heapSize.add(cachedItem.heapSize());<a name="line.470"></a>
-<span class="sourceLineNo">471</span>      blocksByHFile.add(cacheKey);<a name="line.471"></a>
-<span class="sourceLineNo">472</span>    }<a name="line.472"></a>
-<span class="sourceLineNo">473</span>  }<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>   * Get the buffer of the block with the specified key.<a name="line.476"></a>
-<span class="sourceLineNo">477</span>   * @param key block's cache key<a name="line.477"></a>
-<span class="sourceLineNo">478</span>   * @param caching true if the caller caches blocks on cache misses<a name="line.478"></a>
-<span class="sourceLineNo">479</span>   * @param repeat Whether this is a repeat lookup for the same block<a name="line.479"></a>
-<span class="sourceLineNo">480</span>   * @param updateCacheMetrics Whether we should update cache metrics or not<a name="line.480"></a>
-<span class="sourceLineNo">481</span>   * @return buffer of specified cache key, or null if not in cache<a name="line.481"></a>
-<span class="sourceLineNo">482</span>   */<a name="line.482"></a>
-<span class="sourceLineNo">483</span>  @Override<a name="line.483"></a>
-<span class="sourceLineNo">484</span>  public Cacheable getBlock(BlockCacheKey key, boolean caching, boolean repeat,<a name="line.484"></a>
-<span class="sourceLineNo">485</span>      boolean updateCacheMetrics) {<a name="line.485"></a>
-<span class="sourceLineNo">486</span>    if (!cacheEnabled) {<a name="line.486"></a>
-<span class="sourceLineNo">487</span>      return null;<a name="line.487"></a>
-<span class="sourceLineNo">488</span>    }<a name="line.488"></a>
-<span class="sourceLineNo">489</span>    RAMQueueEntry re = ramCache.get(key);<a name="line.489"></a>
-<span class="sourceLineNo">490</span>    if (re != null) {<a name="line.490"></a>
-<span class="sourceLineNo">491</span>      if (updateCacheMetrics) {<a name="line.491"></a>
-<span class="sourceLineNo">492</span>        cacheStats.hit(caching, key.isPrimary(), key.getBlockType());<a name="line.492"></a>
-<span class="sourceLineNo">493</span>      }<a name="line.493"></a>
-<span class="sourceLineNo">494</span>      re.access(accessCount.incrementAndGet());<a name="line.494"></a>
-<span class="sourceLineNo">495</span>      return re.getData();<a name="line.495"></a>
-<span class="sourceLineNo">496</span>    }<a name="line.496"></a>
-<span class="sourceLineNo">497</span>    BucketEntry bucketEntry = backingMap.get(key);<a name="line.497"></a>
-<span class="sourceLineNo">498</span>    if (bucketEntry != null) {<a name="line.498"></a>
-<span class="sourceLineNo">499</span>      long start = System.nanoTime();<a name="line.499"></a>
-<span class="sourceLineNo">500</span>      ReentrantReadWriteLock lock = offsetLock.getLock(bucketEntry.offset());<a name="line.500"></a>
-<span class="sourceLineNo">501</span>      try {<a name="line.501"></a>
-<span class="sourceLineNo">502</span>        lock.readLock().lock();<a name="line.502"></a>
-<span class="sourceLineNo">503</span>        // We can not read here even if backingMap does contain the given key because its offset<a name="line.503"></a>
-<span class="sourceLineNo">504</span>        // maybe changed. If we lock BlockCacheKey instead of offset, then we can only check<a name="line.504"></a>
-<span class="sourceLineNo">505</span>        // existence here.<a name="line.505"></a>
-<span class="sourceLineNo">506</span>        if (bucketEntry.equals(backingMap.get(key))) {<a name="line.506"></a>
-<span class="sourceLineNo">507</span>          // TODO : change this area - should be removed after server cells and<a name="line.507"></a>
-<span class="sourceLineNo">508</span>          // 12295 are available<a name="line.508"></a>
-<span class="sourceLineNo">509</span>          int len = bucketEntry.getLength();<a name="line.509"></a>
-<span class="sourceLineNo">510</span>          if (LOG.isTraceEnabled()) {<a name="line.510"></a>
-<span class="sourceLineNo">511</span>            LOG.trace("Read offset=" + bucketEntry.offset() + ", len=" + len);<a name="line.511"></a>
-<span class="sourceLineNo">512</span>          }<a name="line.512"></a>
-<span class="sourceLineNo">513</span>          Cacheable cachedBlock = ioEngine.read(bucketEntry.offset(), len,<a name="line.513"></a>
-<span class="sourceLineNo">514</span>              bucketEntry.deserializerReference(this.deserialiserMap));<a name="line.514"></a>
-<span class="sourceLineNo">515</span>          long timeTaken = System.nanoTime() - start;<a name="line.515"></a>
-<span class="sourceLineNo">516</span>          if (updateCacheMetrics) {<a name="line.516"></a>
-<span class="sourceLineNo">517</span>            cacheStats.hit(caching, key.isPrimary(), key.getBlockType());<a name="line.517"></a>
-<span class="sourceLineNo">518</span>            cacheStats.ioHit(timeTaken);<a name="line.518"></a>
+<span class="sourceLineNo">430</span><a name="line.430"></a>
+<span class="sourceLineNo">431</span>      try {<a name="line.431"></a>
+<span class="sourceLineNo">432</span>        int comparison = BlockCacheUtil.validateBlockAddition(existingBlock, cachedItem, cacheKey);<a name="line.432"></a>
+<span class="sourceLineNo">433</span>        if (comparison != 0) {<a name="line.433"></a>
+<span class="sourceLineNo">434</span>          if (comparison &lt; 0) {<a name="line.434"></a>
+<span class="sourceLineNo">435</span>            LOG.warn("Cached block contents differ by nextBlockOnDiskSize. Keeping cached block.");<a name="line.435"></a>
+<span class="sourceLineNo">436</span>            return;<a name="line.436"></a>
+<span class="sourceLineNo">437</span>          } else {<a name="line.437"></a>
+<span class="sourceLineNo">438</span>            LOG.warn("Cached block contents differ by nextBlockOnDiskSize. Caching new block.");<a name="line.438"></a>
+<span class="sourceLineNo">439</span>          }<a name="line.439"></a>
+<span class="sourceLineNo">440</span>        } else {<a name="line.440"></a>
+<span class="sourceLineNo">441</span>          String msg = "Caching an already cached block: " + cacheKey;<a name="line.441"></a>
+<span class="sourceLineNo">442</span>          msg += ". This is harmless and can happen in rare cases (see HBASE-8547)";<a name="line.442"></a>
+<span class="sourceLineNo">443</span>          LOG.warn(msg);<a name="line.443"></a>
+<span class="sourceLineNo">444</span>          return;<a name="line.444"></a>
+<span class="sourceLineNo">445</span>        }<a name="line.445"></a>
+<span class="sourceLineNo">446</span>      } finally {<a name="line.446"></a>
+<span class="sourceLineNo">447</span>        // return the block since we need to decrement the count<a name="line.447"></a>
+<span class="sourceLineNo">448</span>        returnBlock(cacheKey, existingBlock);<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><a name="line.451"></a>
+<span class="sourceLineNo">452</span>    /*<a name="line.452"></a>
+<span class="sourceLineNo">453</span>     * Stuff the entry into the RAM cache so it can get drained to the persistent store<a name="line.453"></a>
+<span class="sourceLineNo">454</span>     */<a name="line.454"></a>
+<span class="sourceLineNo">455</span>    RAMQueueEntry re =<a name="line.455"></a>
+<span class="sourceLineNo">456</span>        new RAMQueueEntry(cacheKey, cachedItem, accessCount.incrementAndGet(), inMemory);<a name="line.456"></a>
+<span class="sourceLineNo">457</span>    if (ramCache.putIfAbsent(cacheKey, re) != null) {<a name="line.457"></a>
+<span class="sourceLineNo">458</span>      return;<a name="line.458"></a>
+<span class="sourceLineNo">459</span>    }<a name="line.459"></a>
+<span class="sourceLineNo">460</span>    int queueNum = (cacheKey.hashCode() &amp; 0x7FFFFFFF) % writerQueues.size();<a name="line.460"></a>
+<span class="sourceLineNo">461</span>    BlockingQueue&lt;RAMQueueEntry&gt; bq = writerQueues.get(queueNum);<a name="line.461"></a>
+<span class="sourceLineNo">462</span>    boolean successfulAddition = false;<a name="line.462"></a>
+<span class="sourceLineNo">463</span>    if (wait) {<a name="line.463"></a>
+<span class="sourceLineNo">464</span>      try {<a name="line.464"></a>
+<span class="sourceLineNo">465</span>        successfulAddition = bq.offer(re, DEFAULT_CACHE_WAIT_TIME, TimeUnit.MILLISECONDS);<a name="line.465"></a>
+<span class="sourceLineNo">466</span>      } catch (InterruptedException e) {<a name="line.466"></a>
+<span class="sourceLineNo">467</span>        Thread.currentThread().interrupt();<a name="line.467"></a>
+<span class="sourceLineNo">468</span>      }<a name="line.468"></a>
+<span class="sourceLineNo">469</span>    } else {<a name="line.469"></a>
+<span class="sourceLineNo">470</span>      successfulAddition = bq.offer(re);<a name="line.470"></a>
+<span class="sourceLineNo">471</span>    }<a name="line.471"></a>
+<span class="sourceLineNo">472</span>    if (!successfulAddition) {<a name="line.472"></a>
+<span class="sourceLineNo">473</span>      ramCache.remove(cacheKey);<a name="line.473"></a>
+<span class="sourceLineNo">474</span>      cacheStats.failInsert();<a name="line.474"></a>
+<span class="sourceLineNo">475</span>    } else {<a name="line.475"></a>
+<span class="sourceLineNo">476</span>      this.blockNumber.increment();<a name="line.476"></a>
+<span class="sourceLineNo">477</span>      this.heapSize.add(cachedItem.heapSize());<a name="line.477"></a>
+<span class="sourceLineNo">478</span>      blocksByHFile.add(cacheKey);<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>  /**<a name="line.482"></a>
+<span class="sourceLineNo">483</span>   * Get the buffer of the block with the specified key.<a name="line.483"></a>
+<span class="sourceLineNo">484</span>   * @param key block's cache key<a name="line.484"></a>
+<span class="sourceLineNo">485</span>   * @param caching true if the caller caches blocks on cache misses<a name="line.485"></a>
+<span class="sourceLineNo">486</span>   * @param repeat Whether this is a repeat lookup for the same block<a name="line.486"></a>
+<span class="sourceLineNo">487</span>   * @param updateCacheMetrics Whether we should update cache metrics or not<a name="line.487"></a>
+<span class="sourceLineNo">488</span>   * @return buffer of specified cache key, or null if not in cache<a name="line.488"></a>
+<span class="sourceLineNo">489</span>   */<a name="line.489"></a>
+<span class="sourceLineNo">490</span>  @Override<a name="line.490"></a>
+<span class="sourceLineNo">491</span>  public Cacheable getBlock(BlockCacheKey key, boolean caching, boolean repeat,<a name="line.491"></a>
+<span class="sourceLineNo">492</span>      boolean updateCacheMetrics) {<a name="line.492"></a>
+<span class="sourceLineNo">493</span>    if (!cacheEnabled) {<a name="line.493"></a>
+<span class="sourceLineNo">494</span>      return null;<a name="line.494"></a>
+<span class="sourceLineNo">495</span>    }<a name="line.495"></a>
+<span class="sourceLineNo">496</span>    RAMQueueEntry re = ramCache.get(key);<a name="line.496"></a>
+<span class="sourceLineNo">497</span>    if (re != null) {<a name="line.497"></a>
+<span class="sourceLineNo">498</span>      if (updateCacheMetrics) {<a name="line.498"></a>
+<span class="sourceLineNo">499</span>        cacheStats.hit(caching, key.isPrimary(), key.getBlockType());<a name="line.499"></a>
+<span class="sourceLineNo">500</span>      }<a name="line.500"></a>
+<span class="sourceLineNo">501</span>      re.access(accessCount.incrementAndGet());<a name="line.501"></a>
+<span class="sourceLineNo">502</span>      return re.getData();<a name="line.502"></a>
+<span class="sourceLineNo">503</span>    }<a name="line.503"></a>
+<span class="sourceLineNo">504</span>    BucketEntry bucketEntry = backingMap.get(key);<a name="line.504"></a>
+<span class="sourceLineNo">505</span>    if (bucketEntry != null) {<a name="line.505"></a>
+<span class="sourceLineNo">506</span>      long start = System.nanoTime();<a name="line.506"></a>
+<span class="sourceLineNo">507</span>      ReentrantReadWriteLock lock = offsetLock.getLock(bucketEntry.offset());<a name="line.507"></a>
+<span class="sourceLineNo">508</span>      try {<a name="line.508"></a>
+<span class="sourceLineNo">509</span>        lock.readLock().lock();<a name="line.509"></a>
+<span class="sourceLineNo">510</span>        // We can not read here even if backingMap does contain the given key because its offset<a name="line.510"></a>
+<span class="sourceLineNo">511</span>        // maybe changed. If we lock BlockCacheKey instead of offset, then we can only check<a name="line.511"></a>
+<span class="sourceLineNo">512</span>        // existence here.<a name="line.512"></a>
+<span class="sourceLineNo">513</span>        if (bucketEntry.equals(backingMap.get(key))) {<a name="line.513"></a>
+<span class="sourceLineNo">514</span>          // TODO : change this area - should be removed after server cells and<a name="line.514"></a>
+<span class="sourceLineNo">515</span>          // 12295 are available<a name="line.515"></a>
+<span class="sourceLineNo">516</span>          int len = bucketEntry.getLength();<a name="line.516"></a>
+<span class="sourceLineNo">517</span>          if (LOG.isTraceEnabled()) {<a name="line.517"></a>
+<span class="sourceLineNo">518</span>            LOG.trace("Read offset=" + bucketEntry.offset() + ", len=" + len);<a name="line.518"></a>
 <span class="sourceLineNo">519</span>          }<a name="line.519"></a>
-<span class="sourceLineNo">520</span>          if (cachedBlock.getMemoryType() == MemoryType.SHARED) {<a name="line.520"></a>
-<span class="sourceLineNo">521</span>            bucketEntry.incrementRefCountAndGet();<a name="line.521"></a>
-<span class="sourceLineNo">522</span>          }<a name="line.522"></a>
-<span class="sourceLineNo">523</span>          bucketEntry.access(accessCount.incrementAndGet());<a name="line.523"></a>
-<span class="sourceLineNo">524</span>          if (this.ioErrorStartTime &gt; 0) {<a name="line.524"></a>
-<span class="sourceLineNo">525</span>            ioErrorStartTime = -1;<a name="line.525"></a>
+<span class="sourceLineNo">520</span>          Cacheable cachedBlock = ioEngine.read(bucketEntry.offset(), len,<a name="line.520"></a>
+<span class="sourceLineNo">521</span>              bucketEntry.deserializerReference(this.deserialiserMap));<a name="line.521"></a>
+<span class="sourceLineNo">522</span>          long timeTaken = System.nanoTime() - start;<a name="line.522"></a>
+<span class="sourceLineNo">523</span>          if (updateCacheMetrics) {<a name="line.523"></a>
+<span class="sourceLineNo">524</span>            cacheStats.hit(caching, key.isPrimary(), key.getBlockType());<a name="line.524"></a>
+<span class="sourceLineNo">525</span>            cacheStats.ioHit(timeTaken);<a name="line.525"></a>
 <span class="sourceLineNo">526</span>          }<a name="line.526"></a>
-<span class="sourceLineNo">527</span>          return cachedBlock;<a name="line.527"></a>
-<span class="sourceLineNo">528</span>        }<a name="line.528"></a>
-<span class="sourceLineNo">529</span>      } catch (IOException ioex) {<a name="line.529"></a>
-<span class="sourceLineNo">530</span>        LOG.error("Failed reading block " + key + " from bucket cache", ioex);<a name="line.530"></a>
-<span class="sourceLineNo">531</span>        checkIOErrorIsTolerated();<a name="line.531"></a>
-<span class="sourceLineNo">532</span>      } finally {<a name="line.532"></a>
-<span class="sourceLineNo">533</span>        lock.readLock().unlock();<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>    if (!repeat &amp;&amp; updateCacheMetrics) {<a name="line.536"></a>
-<span class="sourceLineNo">537</span>      cacheStats.miss(caching, key.isPrimary(), key.getBlockType());<a name="line.537"></a>
-<span class="sourceLineNo">538</span>    }<a name="line.538"></a>
-<span class="sourceLineNo">539</span>    return null;<a name="line.539"></a>
-<span class="sourceLineNo">540</span>  }<a name="line.540"></a>
-<span class="sourceLineNo">541</span><a name="line.541"></a>
-<span class="sourceLineNo">542</span>  @VisibleForTesting<a name="line.542"></a>
-<span class="sourceLineNo">543</span>  void blockEvicted(BlockCacheKey cacheKey, BucketEntry bucketEntry, boolean decrementBlockNumber) {<a name="line.543"></a>
-<span class="sourceLineNo">544</span>    bucketAllocator.freeBlock(bucketEntry.offset());<a name="line.544"></a>
-<span class="sourceLineNo">545</span>    realCacheSize.add(-1 * bucketEntry.getLength());<a name="line.545"></a>
-<span class="sourceLineNo">546</span>    blocksByHFile.remove(cacheKey);<a name="line.546"></a>
-<span class="sourceLineNo">547</span>    if (decrementBlockNumber) {<a name="line.547"></a>
-<span class="sourceLineNo">548</span>      this.blockNumber.decrement();<a name="line.548"></a>
-<span class="sourceLineNo">549</span>    }<a name="line.549"></a>
-<span class="sourceLineNo">550</span>  }<a name="line.550"></a>
-<span class="sourceLineNo">551</span><a name="line.551"></a>
-<span class="sourceLineNo">552</span>  @Override<a name="line.552"></a>
-<span class="sourceLineNo">553</span>  public boolean evictBlock(BlockCacheKey cacheKey) {<a name="line.553"></a>
-<span class="sourceLineNo">554</span>    return evictBlock(cacheKey, true);<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>  // does not check for the ref count. Just tries to evict it if found in the<a name="line.557"></a>
-<span class="sourceLineNo">558</span>  // bucket map<a name="line.558"></a>
-<span class="sourceLineNo">559</span>  private boolean forceEvict(BlockCacheKey cacheKey) {<a name="line.559"></a>
-<span class="sourceLineNo">560</span>    if (!cacheEnabled) {<a name="line.560"></a>
-<span class="sourceLineNo">561</span>      return false;<a name="line.561"></a>
-<span class="sourceLineNo">562</span>    }<a name="line.562"></a>
-<span class="sourceLineNo">563</span>    RAMQueueEntry removedBlock = checkRamCache(cacheKey);<a name="line.563"></a>
-<span class="sourceLineNo">564</span>    BucketEntry bucketEntry = backingMap.get(cacheKey);<a name="line.564"></a>
-<span class="sourceLineNo">565</span>    if (bucketEntry == null) {<a name="line.565"></a>
-<span class="sourceLineNo">566</span>      if (removedBlock != null) {<a name="line.566"></a>
-<span class="sourceLineNo">567</span>        cacheStats.evicted(0, cacheKey.isPrimary());<a name="line.567"></a>
-<span class="sourceLineNo">568</span>        return true;<a name="line.568"></a>
-<span class="sourceLineNo">569</span>      } else {<a name="line.569"></a>
-<span class="sourceLineNo">570</span>        return false;<a name="line.570"></a>
-<span class="sourceLineNo">571</span>      }<a name="line.571"></a>
-<span class="sourceLineNo">572</span>    }<a name="line.572"></a>
-<span class="sourceLineNo">573</span>    ReentrantReadWriteLock lock = offsetLock.getLock(bucketEntry.offset());<a name="line.573"></a>
-<span class="sourceLineNo">574</span>    try {<a name="line.574"></a>
-<span class="sourceLineNo">575</span>      lock.writeLock().lock();<a name="line.575"></a>
-<span class="sourceLineNo">576</span>      if (backingMap.remove(cacheKey, bucketEntry)) {<a name="line.576"></a>
-<span class="sourceLineNo">577</span>        blockEvicted(cacheKey, bucketEntry, removedBlock == null);<a name="line.577"></a>
-<span class="sourceLineNo">578</span>      } else {<a name="line.578"></a>
-<span class="sourceLineNo">579</span>        return false;<a name="line.579"></a>
-<span class="sourceLineNo">580</span>      }<a name="line.580"></a>
-<span class="sourceLineNo">581</span>    } finally {<a name="line.581"></a>
-<span class="sourceLineNo">582</span>      lock.writeLock().unlock();<a name="line.582"></a>
-<span class="sourceLineNo">583</span>    }<a name="line.583"></a>
-<span class="sourceLineNo">584</span>    cacheStats.evicted(bucketEntry.getCachedTime(), cacheKey.isPrimary());<a name="line.584"></a>
-<span class="sourceLineNo">585</span>    return true;<a name="line.585"></a>
-<span class="sourceLineNo">586</span>  }<a name="line.586"></a>
-<span class="sourceLineNo">587</span><a name="line.587"></a>
-<span class="sourceLineNo">588</span>  private RAMQueueEntry checkRamCache(BlockCacheKey cacheKey) {<a name="line.588"></a>
-<span class="sourceLineNo">589</span>    RAMQueueEntry removedBlock = ramCache.remove(cacheKey);<a name="line.589"></a>
-<span class="sourceLineNo">590</span>    if (removedBlock != null) {<a name="line.590"></a>
-<span class="sourceLineNo">591</span>      this.blockNumber.decrement();<a name="line.591"></a>
-<span class="sourceLineNo">592</span>      this.heapSize.add(-1 * removedBlock.getData().heapSize());<a name="line.592"></a>
-<span class="sourceLineNo">593</span>    }<a name="line.593"></a>
-<span class="sourceLineNo">594</span>    return removedBlock;<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>  public boolean evictBlock(BlockCacheKey cacheKey, boolean deletedBlock) {<a name="line.597"></a>
-<span class="sourceLineNo">598</span>    if (!cacheEnabled) {<a name="line.598"></a>
-<span class="sourceLineNo">599</span>      return false;<a name="line.599"></a>
+<span class="sourceLineNo">527</span>          if (cachedBlock.getMemoryType() == MemoryType.SHARED) {<a name="line.527"></a>
+<span class="sourceLineNo">528</span>            bucketEntry.incrementRefCountAndGet();<a name="line.528"></a>
+<span class="sourceLineNo">529</span>          }<a name="line.529"></a>
+<span class="sourceLineNo">530</span>          bucketEntry.access(accessCount.incrementAndGet());<a name="line.530"></a>
+<span class="sourceLineNo">531</span>          if (this.ioErrorStartTime &gt; 0) {<a name="line.531"></a>
+<span class="sourceLineNo">532</span>            ioErrorStartTime = -1;<a name="line.532"></a>
+<span class="sourceLineNo">533</span>          }<a name="line.533"></a>
+<span class="sourceLineNo">534</span>          return cachedBlock;<a name="line.534"></a>
+<span class="sourceLineNo">535</span>        }<a name="line.535"></a>
+<span class="sourceLineNo">536</span>      } catch (IOException ioex) {<a name="line.536"></a>
+<span class="sourceLineNo">537</span>        LOG.error("Failed reading block " + key + " from bucket cache", ioex);<a name="line.537"></a>
+<span class="sourceLineNo">538</span>        checkIOErrorIsTolerated();<a name="line.538"></a>
+<span class="sourceLineNo">539</span>      } finally {<a name="line.539"></a>
+<span class="sourceLineNo">540</span>        lock.readLock().unlock();<a name="line.540"></a>
+<span class="sourceLineNo">541</span>      }<a name="line.541"></a>
+<span class="sourceLineNo">542</span>    }<a name="line.542"></a>
+<span class="sourceLineNo">543</span>    if (!repeat &amp;&amp; updateCacheMetrics) {<a name="line.543"></a>
+<span class="sourceLineNo">544</span>      cacheStats.miss(caching, key.isPrimary(), key.getBlockType());<a name="line.544"></a>
+<span class="sourceLineNo">545</span>    }<a name="line.545"></a>
+<span class="sourceLineNo">546</span>    return null;<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>  @VisibleForTesting<a name="line.549"></a>
+<span class="sourceLineNo">550</span>  void blockEvicted(BlockCacheKey cacheKey, BucketEntry bucketEntry, boolean decrementBlockNumber) {<a name="line.550"></a>
+<span class="sourceLineNo">551</span>    bucketAllocator.freeBlock(bucketEntry.offset());<a name="line.551"></a>
+<span class="sourceLineNo">552</span>    realCacheSize.add(-1 * bucketEntry.getLength());<a name="line.552"></a>
+<span class="sourceLineNo">553</span>    blocksByHFile.remove(cacheKey);<a name="line.553"></a>
+<span class="sourceLineNo">554</span>    if (decrementBlockNumber) {<a name="line.554"></a>
+<span class="sourceLineNo">555</span>      this.blockNumber.decrement();<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>  @Override<a name="line.559"></a>
+<span class="sourceLineNo">560</span>  public boolean evictBlock(BlockCacheKey cacheKey) {<a name="line.560"></a>
+<span class="sourceLineNo">561</span>    return evictBlock(cacheKey, true);<a name="line.561"></a>
+<span class="sourceLineNo">562</span>  }<a name="line.562"></a>
+<span class="sourceLineNo">563</span><a name="line.563"></a>
+<span class="sourceLineNo">564</span>  // does not check for the ref count. Just tries to evict it if found in the<a name="line.564"></a>
+<span class="sourceLineNo">565</span>  // bucket map<a name="line.565"></a>
+<span class="sourceLineNo">566</span>  private boolean forceEvict(BlockCacheKey cacheKey) {<a name="line.566"></a>
+<span class="sourceLineNo">567</span>    if (!cacheEnabled) {<a name="line.567"></a>
+<span class="sourceLineNo">568</span>      return false;<a name="line.568"></a>
+<span class="sourceLineNo">569</span>    }<a name="line.569"></a>
+<span class="sourceLineNo">570</span>    RAMQueueEntry removedBlock = checkRamCache(cacheKey);<a name="line.570"></a>
+<span class="sourceLineNo">571</span>    BucketEntry bucketEntry = backingMap.get(cacheKey);<a name="line.571"></a>
+<span class="sourceLineNo">572</span>    if (bucketEntry == null) {<a name="line.572"></a>
+<span class="sourceLineNo">573</span>      if (removedBlock != null) {<a name="line.573"></a>
+<span class="sourceLineNo">574</span>        cacheStats.evicted(0, cacheKey.isPrimary());<a name="line.574"></a>
+<span class="sourceLineNo">575</span>        return true;<a name="line.575"></a>
+<span class="sourceLineNo">576</span>      } else {<a name="line.576"></a>
+<span class="sourceLineNo">577</span>        return false;<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>    ReentrantReadWriteLock lock = offsetLock.getLock(bucketEntry.offset());<a name="line.580"></a>
+<span class="sourceLineNo">581</span>    try {<a name="line.581"></a>
+<span class="sourceLineNo">582</span>      lock.writeLock().lock();<a name="line.582"></a>
+<span class="sourceLineNo">583</span>      if (backingMap.remove(cacheKey, bucketEntry)) {<a name="line.583"></a>
+<span class="sourceLineNo">584</span>        blockEvicted(cacheKey, bucketEntry, removedBlock == null);<a name="line.584"></a>
+<span class="sourceLineNo">585</span>      } else {<a name="line.585"></a>
+<span class="sourceLineNo">586</span>        return false;<a name="line.586"></a>
+<span class="sourceLineNo">587</span>      }<a name="line.587"></a>
+<span class="sourceLineNo">588</span>    } finally {<a name="line.588"></a>
+<span class="sourceLineNo">589</span>      lock.writeLock().unlock();<a name="line.589"></a>
+<span class="sourceLineNo">590</span>    }<a name="line.590"></a>
+<span class="sourceLineNo">591</span>    cacheStats.evicted(bucketEntry.getCachedTime(), cacheKey.isPrimary());<a name="line.591"></a>
+<span class="sourceLineNo">592</span>    return true;<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>  private RAMQueueEntry checkRamCache(BlockCacheKey cacheKey) {<a name="line.595"></a>
+<span class="sourceLineNo">596</span>    RAMQueueEntry removedBlock = ramCache.remove(cacheKey);<a name="line.596"></a>
+<span class="sourceLineNo">597</span>    if (removedBlock != null) {<a name="line.597"></a>
+<span class="sourceLineNo">598</span>      this.blockNumber.decrement();<a name="line.598"></a>
+<span class="sourceLineNo">599</span>      this.heapSize.add(-1 * removedBlock.getData().heapSize());<a name="line.599"></a>
 <span class="sourceLineNo">600</span>    }<a name="line.600"></a>
-<span class="sourceLineNo">601</span>    RAMQueueEntry removedBlock = checkRamCache(cacheKey);<a name="line.601"></a>
-<span class="sourceLineNo">602</span>    BucketEntry bucketEntry = backingMap.get(cacheKey);<a name="line.602"></a>
-<span class="sourceLineNo">603</span>    if (bucketEntry == null) {<a name="line.603"></a>
-<span class="sourceLineNo">604</span>      if (removedBlock != null) {<a name="line.604"></a>
-<span class="sourceLineNo">605</span>        cacheStats.evicted(0, cacheKey.isPrimary());<a name="line.605"></a>
-<span class="sourceLineNo">606</span>        return true;<a name="line.606"></a>
-<span class="sourceLineNo">607</span>      } else {<a name="line.607"></a>
-<span class="sourceLineNo">608</span>        return false;<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>    ReentrantReadWriteLock lock = offsetLock.getLock(bucketEntry.offset());<a name="line.611"></a>
-<span class="sourceLineNo">612</span>    try {<a name="line.612"></a>
-<span class="sourceLineNo">613</span>      lock.writeLock().lock();<a name="line.613"></a>
-<span class="sourceLineNo">614</span>      int refCount = bucketEntry.getRefCount();<a name="line.614"></a>
-<span class="sourceLineNo">615</span>      if (refCount == 0) {<a name="line.615"></a>
-<span class="sourceLineNo">616</span>        if (backingMap.remove(cacheKey, bucketEntry)) {<a name="line.616"></a>
-<span class="sourceLineNo">617</span>          blockEvicted(cacheKey, bucketEntry, removedBlock == null);<a name="line.617"></a>
-<span class="sourceLineNo">618</span>        } else {<a name="line.618"></a>
-<span class="sourceLineNo">619</span>          return false;<a name="line.619"></a>
-<span class="sourceLineNo">620</span>        }<a name="line.620"></a>
-<span class="sourceLineNo">621</span>      } else {<a name="line.621"></a>
-<span class="sourceLineNo">622</span>        if(!deletedBlock) {<a name="line.622"></a>
-<span class="sourceLineNo">623</span>          if (LOG.isDebugEnabled()) {<a name="line.623"></a>
-<span class="sourceLineNo">624</span>            LOG.debug("This block " + cacheKey + " is still referred by " + refCount<a name="line.624"></a>
-<span class="sourceLineNo">625</span>                + " readers. Can not be freed now");<a name="line.625"></a>
-<span class="sourceLineNo">626</span>          }<a name="line.626"></a>
-<span class="sourceLineNo">627</span>          return false;<a name="line.627"></a>
-<span class="sourceLineNo">628</span>        } else {<a name="line.628"></a>
-<span class="sourceLineNo">629</span>          if (LOG.isDebugEnabled()) {<a name="line.629"></a>
-<span class="sourceLineNo">630</span>            LOG.debug("This block " + cacheKey + " is still referred by " + refCount<a name="line.630"></a>
-<span class="sourceLineNo">631</span>                + " readers. Can not be freed now. Hence will mark this"<a name="line.631"></a>
-<span class="sourceLineNo">632</span>                + " for evicting at a later point");<a name="line.632"></a>
+<span class="sourceLineNo">601</span>    return removedBlock;<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>  public boolean evictBlock(BlockCacheKey cacheKey, boolean deletedBlock) {<a name="line.604"></a>
+<span class="sourceLineNo">605</span>    if (!cacheEnabled) {<a name="line.605"></a>
+<span class="sourceLineNo">606</span>      return false;<a name="line.606"></a>
+<span class="sourceLineNo">607</span>    }<a name="line.607"></a>
+<span class="sourceLineNo">608</span>    RAMQueueEntry removedBlock = checkRamCache(cacheKey);<a name="line.608"></a>
+<span class="sourceLineNo">609</span>    BucketEntry bucketEntry = backingMap.get(cacheKey);<a name="line.609"></a>
+<span class="sourceLineNo">610</span>    if (bucketEntry == null) {<a name="line.610"></a>
+<span class="sourceLineNo">611</span>      if (removedBlock != null) {<a name="line.611"></a>
+<span class="sourceLineNo">612</span>        cacheStats.evicted(0, cacheKey.isPrimary());<a name="line.612"></a>
+<span class="sourceLineNo">613</span>        return true;<a name="line.613"></a>
+<span class="sourceLineNo">614</span>      } else {<a name="line.614"></a>
+<span class="sourceLineNo">615</span>        return false;<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>    ReentrantReadWriteLock lock = offsetLock.getLock(bucketEntry.offset());<a name="line.618"></a>
+<span class="sourceLineNo">619</span>    try {<a name="line.619"></a>
+<span class="sourceLineNo">620</span>      lock.writeLock().lock();<a name="line.620"></a>
+<span class="sourceLineNo">621</span>      int refCount = bucketEntry.getRefCount();<a name="line.621"></a>
+<span class="sourceLineNo">622</span>      if (refCount == 0) {<a name="line.622"></a>
+<span class="sourceLineNo">623</span>        if (backingMap.remove(cacheKey, bucketEntry)) {<a name="line.623"></a>
+<span class="sourceLineNo">624</span>          blockEvicted(cacheKey, bucketEntry, removedBlock == null);<a name="line.624"></a>
+<span class="sourceLineNo">625</span>        } else {<a name="line.625"></a>
+<span class="sourceLineNo">626</span>          return false;<a name="line.626"></a>
+<span class="sourceLineNo">627</span>        }<a name="line.627"></a>
+<span class="sourceLineNo">628</span>      } else {<a name="line.628"></a>
+<span class="sourceLineNo">629</span>        if(!deletedBlock) {<a name="line.629"></a>
+<span class="sourceLineNo">630</span>          if (LOG.isDebugEnabled()) {<a name="line.630"></a>
+<span class="sourceLineNo">631</span>            LOG.debug("This block " + cacheKey + " is still referred by " + refCount<a name="line.631"></a>
+<span class="sourceLineNo">632</span>                + " readers. Can not be freed now");<a name="line.632"></a>
 <span class="sourceLineNo">633</span>          }<a name="line.633"></a>
-<span class="sourceLineNo">634</span>          bucketEntry.markForEvict();<a name="line.634"></a>
-<span class="sourceLineNo">635</span>        }<a name="line.635"></a>
-<span class="sourceLineNo">636</span>      }<a name="line.636"></a>
-<span class="sourceLineNo">637</span>    } finally {<a name="line.637"></a>
-<span class="sourceLineNo">638</span>      lock.writeLock().unlock();<a name="line.638"></a>
-<span class="sourceLineNo">639</span>    }<a name="line.639"></a>
-<span class="sourceLineNo">640</span>    cacheStats.evicted(bucketEntry.getCachedTime(), cacheKey.isPrimary());<a name="line.640"></a>
-<span class="sourceLineNo">641</span>    return true;<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>   * Statistics thread.  Periodically output cache statistics to the log.<a name="line.645"></a>
-<span class="sourceLineNo">646</span>   */<a name="line.646"></a>
-<span class="sourceLineNo">647</span>  private static class StatisticsThread extends Thread {<a name="line.647"></a>
-<span class="sourceLineNo">648</span>    private final BucketCache bucketCache;<a name="line.648"></a>
-<span class="sourceLineNo">649</span><a name="line.649"></a>
-<span class="sourceLineNo">650</span>    public StatisticsThread(BucketCache bucketCache) {<a name="line.650"></a>
-<span class="sourceLineNo">651</span>      super("BucketCacheStatsThread");<a name="line.651"></a>
-<span class="sourceLineNo">652</span>      setDaemon(true);<a name="line.652"></a>
-<span class="sourceLineNo">653</span>      this.bucketCache = bucketCache;<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 void run() {<a name="line.657"></a>
-<span class="sourceLineNo">658</span>      bucketCache.logStats();<a name="line.658"></a>
-<span class="sourceLineNo">659</span>    }<a name="line.659"></a>
-<span class="sourceLineNo">660</span>  }<a name="line.660"></a>
-<span class="sourceLineNo">661</span><a name="line.661"></a>
-<span class="sourceLineNo">662</span>  public void logStats() {<a name="line.662"></a>
-<span class="sourceLineNo">663</span>    long totalSize = bucketAllocator.getTotalSize();<a name="line.663"></a>
-<span class="sourceLineNo">664</span>    long usedSize = bucketAllocator.getUsedSize();<a name="line.664"></a>
-<span class="sourceLineNo">665</span>    long freeSize = totalSize - usedSize;<a name="line.665"></a>
-<span class="sourceLineNo">666</span>    long cacheSize = getRealCacheSize();<a name="line.666"></a>
-<span class="sourceLineNo">667</span>    LOG.info("failedBlockAdditions=" + cacheStats.getFailedInserts() + ", " +<a name="line.667"></a>
-<span class="sourceLineNo">668</span>        "totalSize=" + StringUtils.byteDesc(totalSize) + ", " +<a name="line.668"></a>
-<span class="sourceLineNo">669</span>        "freeSize=" + StringUtils.byteDesc(freeSize) + ", " +<a name="line.669"></a>
-<span class="sourceLineNo">670</span>        "usedSize=" + StringUtils.byteDesc(usedSize) +", " +<a name="line.670"></a>
-<span class="sourceLineNo">671</span>        "cacheSize=" + StringUtils.byteDesc(cacheSize) +", " +<a name="line.671"></a>
-<span class="sourceLineNo">672</span>        "accesses=" + cacheStats.getRequestCount() + ", " +<a name="line.672"></a>
-<span class="sourceLineNo">673</span>        "hits=" + cacheStats.getHitCount() + ", " +<a name="line.673"></a>
-<span class="sourceLineNo">674</span>        "IOhitsPerSecond=" + cacheStats.getIOHitsPerSecond() + ", " +<a name="line.674"></a>
-<span class="sourceLineNo">675</span>        "IOTimePerHit=" + String.format("%.2f", cacheStats.getIOTimePerHit())+ ", " +<a name="line.675"></a>
-<span class="sourceLineNo">676</span>        "hitRatio=" + (cacheStats.getHitCount() == 0 ? "0," :<a name="line.676"></a>
-<span class="sourceLineNo">677</span>          (StringUtils.formatPercent(cacheStats.getHitRatio(), 2)+ ", ")) +<a name="line.677"></a>
-<span class="sourceLineNo">678</span>        "cachingAccesses=" + cacheStats.getRequestCachingCount() + ", " +<a name="line.678"></a>
-<span class="sourceLineNo">679</span>        "cachingHits=" + cacheStats.getHitCachingCount() + ", " +<a name="line.679"></a>
-<span class="sourceLineNo">680</span>        "cachingHitsRatio=" +(cacheStats.getHitCachingCount() == 0 ? "0," :<a name="line.680"></a>
-<span class="sourceLineNo">681</span>          (StringUtils.formatPercent(cacheStats.getHitCachingRatio(), 2)+ ", ")) +<a name="line.681"></a>
-<span class="sourceLineNo">682</span>        "evictions=" + cacheStats.getEvictionCount() + ", " +<a name="line.682"></a>
-<span class="sourceLineNo">683</span>        "evicted=" + cacheStats.getEvictedCount() + ", " +<a name="line.683"></a>
-<span class="sourceLineNo">684</span>        "evictedPerRun=" + cacheStats.evictedPerEviction());<a name="line.684"></a>
-<span class="sourceLineNo">685</span>    cacheStats.reset();<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>  public long getRealCacheSize() {<a name="line.688"></a>
-<span class="sourceLineNo">689</span>    return this.realCacheSize.sum();<a name="line.689"></a>
-<span class="sourceLineNo">690</span>  }<a name="line.690"></a>
-<span class="sourceLineNo">691</span><a name="line.691"></a>
-<span class="sourceLineNo">692</span>  private long acceptableSize() {<a name="line.692"></a>
-<span class="sourceLineNo">693</span>    return (long) Math.floor(bucketAllocator.getTotalSize() * acceptableFactor);<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>  @VisibleForTesting<a name="line.696"></a>
-<span class="sourceLineNo">697</span>  long getPartitionSize(float partitionFactor) {<a name="line.697"></a>
-<span class="sourceLineNo">698</span>    return (long) Math.floor(bucketAllocator.getTotalSize() * partitionFactor * minFactor);<a name="line.698"></a>
-<span class="sourceLineNo">699</span>  }<a name="line.699"></a>
-<span class="sourceLineNo">700</span><a name="line.700"></a>
-<span class="sourceLineNo">701</span>  /**<a name="line.701"></a>
-<span class="sourceLineNo">702</span>   * Return the count of bucketSizeinfos still need free space<a name="line.702"></a>
-<span class="sourceLineNo">703</span>   */<a name="line.703"></a>
-<span class="sourceLineNo">704</span>  private int bucketSizesAboveThresholdCount(float minFactor) {<a name="line.704"></a>
-<span class="sourceLineNo">705</span>    BucketAllocator.IndexStatistics[] stats = bucketAllocator.getIndexStatistics();<a name="line.705"></a>
-<span class="sourceLineNo">706</span>    int fullCount = 0;<a name="line.706"></a>
-<span class="sourceLineNo">707</span>    for (int i = 0; i &lt; stats.length; i++) {<a name="line.707"></a>
-<span class="sourceLineNo">708</span>      long freeGoal = (long) Math.floor(stats[i].totalCount() * (1 - minFactor));<a name="line.708"></a>
-<span class="sourceLineNo">709</span>      freeGoal = Math.max(freeGoal, 1);<a name="line.709"></a>
-<span class="sourceLineNo">710</span>      if (stats[i].freeCount() &lt; freeGoal) {<a name="line.710"></a>
-<span class="sourceLineNo">711</span>        fullCount++;<a name="line.711"></a>
-<span class="sourceLineNo">712</span>      }<a name="line.712"></a>
-<span class="sourceLineNo">713</span>    }<a name="line.713"></a>
-<span class="sourceLineNo">714</span>    return fullCount;<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">717</span>  /**<a name="line.717"></a>
-<span class="sourceLineNo">718</span>   * This method will find the buckets that are minimally occupied<a name="line.718"></a>
-<span class="sourceLineNo">719</span>   * and are not reference counted and will free them completely<a name="line.719"></a>
-<span class="sourceLineNo">720</span>   * without any constraint on the access times of the elements,<a name="line.720"></a>
-<span class="sourceLineNo">721</span>   * and as a process will completely free at most the number of buckets<a name="line.721"></a>
-<span class="sourceLineNo">722</span>   * passed, sometimes it might not due to changing refCounts<a name="line.722"></a>
-<span class="sourceLineNo">723</span>   *<a name="line.723"></a>
-<span class="sourceLineNo">724</span>   * @param completelyFreeBucketsNeeded number of buckets to free<a name="line.724"></a>
-<span class="sourceLineNo">725</span>   **/<a name="line.725"></a>
-<span class="sourceLineNo">726</span>  private void freeEntireBuckets(int completelyFreeBucketsNeeded) {<a name="line.726"></a>
-<span class="sourceLineNo">727</span>    if (completelyFreeBucketsNeeded != 0) {<a name="line.727"></a>
-<span class="sourceLineNo">728</span>      // First we will build a set where the offsets are reference counted, usually<a name="line.728"></a>
-<span class="sourceLineNo">729</span>      // this set is small around O(Handler Count) unless something else is wrong<a name="line.729"></a>
-<span class="sourceLineNo">730</span>      Set&lt;Integer&gt; inUseBuckets = new HashSet&lt;Integer&gt;();<a name="line.730"></a>
-<span class="sourceLineNo">731</span>      for (BucketEntry entry : backingMap.values()) {<a name="line.731"></a>
-<span class="sourceLineNo">732</span>        if (entry.getRefCount() != 0) {<a name="line.732"></a>
-<span class="sourceLineNo">733</span>          inUseBuckets.add(bucketAllocator.getBucketIndex(entry.offset()));<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><a name="line.736"></a>
-<span class="sourceLineNo">737</span>      Set&lt;Integer&gt; candidateBuckets = bucketAllocator.getLeastFilledBuckets(<a name="line.737"></a>
-<span class="sourceLineNo">738</span>          inUseBuckets, completelyFreeBucketsNeeded);<a name="line.738"></a>
-<span class="sourceLineNo">739</span>      for (Map.Entry&lt;BlockCacheKey, BucketEntry&gt; entry : backingMap.entrySet()) {<a name="line.739"></a>
-<span class="sourceLineNo">740</span>        if (candidateBuckets.contains(bucketAllocator<a name="line.740"></a>
-<span class="sourceLineNo">741</span>            .getBucketIndex(entry.getValue().offset()))) {<a name="line.741"></a>
-<span class="sourceLineNo">742</span>          evictBlock(entry.getKey(), false);<a name="line.742"></a>
-<span class="sourceLineNo">743</span>        }<a name="line.743"></a>
-<span class="sourceLineNo">744</span>      }<a name="line.744"></a>
-<span class="sourceLineNo">745</span>    }<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>  /**<a name="line.748"></a>
-<span class="sourceLineNo">749</span>   * Free the space if the used size reaches acceptableSize() or one size block<a name="line.749"></a>
-<span class="sourceLineNo">750</span>   * couldn't be allocated. When freeing the space, we use the LRU algorithm and<a name="line.750"></a>
-<span class="sourceLineNo">751</span>   * ensure there must be some blocks evicted<a name="line.751"></a>
-<span class="sourceLineNo">752</span>   * @param why Why we are being called<a name="line.752"></a>
-<span class="sourceLineNo">753</span>   */<a name="line.753"></a>
-<span class="sourceLineNo">754</span>  private void freeSpace(final String why) {<a name="line.754"></a>
-<span class="sourceLineNo">755</span>    // Ensure only one freeSpace progress at a time<a name="line.755"></a>
-<span class="sourceLineNo">756</span>    if (!freeSpaceLock.tryLock()) {<a name="line.756"></a>
-<span class="sourceLineNo">757</span>      return;<a name="line.757"></a>
-<span class="sourceLineNo">758</span>    }<a name="line.758"></a>
-<span class="sourceLineNo">759</span>    try {<a name="line.759"></a>
-<span class="sourceLineNo">760</span>      freeInProgress = true;<a name="line.760"></a>
-<span class="sourceLineNo">761</span>      long bytesToFreeWithoutExtra = 0;<a name="line.761"></a>
-<span class="sourceLineNo">762</span>      // Calculate free byte for each bucketSizeinfo<a name="line.762"></a>
-<span class="sourceLineNo">763</span>      StringBuilder msgBuffer = LOG.isDebugEnabled()? new StringBuilder(): null;<a name="line.763"></a>
-<span class="sourceLineNo">764</span>      BucketAllocator.IndexStatistics[] stats = bucketAllocator.getIndexStatistics();<a name="line.764"></a>
-<span class="sourceLineNo">765</span>      long[] bytesToFreeForBucket = new long[stats.length];<a name="line.765"></a>
-<span class="sourceLineNo">766</span>      for (int i = 0; i &lt; stats.length; i++) {<a name="line.766"></a>
-<span class="sourceLineNo">767</span>        bytesToFreeForBucket[i] = 0;<a name="line.767"></a>
-<span class="sourceLineNo">768</span>        long freeGoal = (long) Math.floor(stats[i].totalCount() * (1 - minFactor));<a name="line.768"></a>
-<span class="sourceLineNo">769</span>        freeGoal = Math.max(freeGoal, 1);<a name="line.769"></a>
-<span class="sourceLineNo">770</span>        if (stats[i].freeCount() &lt; freeGoal) {<a name="line.770"></a>
-<span class="sourceLineNo">771</span>          bytesToFreeForBucket[i] = stats[i].itemSize() * (freeGoal - stats[i].freeCount());<a name="line.771"></a>
-<span class="sourceLineNo">772</span>          bytesToFreeWithoutExtra += bytesToFreeForBucket[i];<a name="line.772"></a>
-<span class="sourceLineNo">773</span>          if (msgBuffer != null) {<a name="line.773"></a>
-<span class="sourceLineNo">774</span>            msgBuffer.append("Free for bucketSize(" + stats[i].itemSize() + ")="<a name="line.774"></a>
-<span class="sourceLineNo">775</span>              + StringUtils.byteDesc(bytesToFreeForBucket[i]) + ", ");<a name="line.775"></a>
-<span class="sourceLineNo">776</span>          }<a name="line.776"></a>
-<span class="sourceLineNo">777</span>        }<a name="line.777"></a>
-<span class="sourceLineNo">778</span>      }<a name="line.778"></a>
-<span class="sourceLineNo">779</span>      if (msgBuffer != null) {<a name="line.779"></a>
-<span class="sourceLineNo">780</span>        msgBuffer.append("Free for total=" + StringUtils.byteDesc(bytesToFreeWithoutExtra) + ", ");<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>      if (bytesToFreeWithoutExtra &lt;= 0) {<a name="line.783"></a>
-<span class="sourceLineNo">784</span>        return;<a name="line.784"></a>
+<span class="sourceLineNo">634</span>          return false;<a name="line.634"></a>
+<span class="sourceLineNo">635</span>        } else {<a name="line.635"></a>
+<span class="sourceLineNo">636</span>          if (LOG.isDebugEnabled()) {<a name="line.636"></a>
+<span class="sourceLineNo">637</span>            LOG.debug("This block " + cacheKey + " is still referred by " + refCount<a name="line.637"></a>
+<span class="sourceLineNo">638</span>                + " readers. Can not be freed now. Hence will mark this"<a name="line.638"></a>
+<span class="sourceLineNo">639</span>                + " for evicting at a later point");<a name="line.639"></a>
+<span class="sourceLineNo">640</span>          }<a name="line.640"></a>
+<span class="sourceLineNo">641</span>          bucketEntry.markForEvict();<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>    } finally {<a name="line.644"></a>
+<span class="sourceLineNo">645</span>      lock.writeLock().unlock();<a name="line.645"></a>
+<span class="sourceLineNo">646</span>    }<a name="line.646"></a>
+<span class="sourceLineNo">647</span>    cacheStats.evicted(bucketEntry.getCachedTime(), cacheKey.isPrimary());<a name="line.647"></a>
+<span class="sourceLineNo">648</span>    return true;<a name="line.648"></a>
+<span class="sourceLineNo">649</span>  }<a name="line.649"></a>
+<span class="sourceLineNo">650</span><a name="line.650"></a>
+<span class="sourceLineNo">651</span>  /*<a name="line.651"></a>
+<span class="sourceLineNo">652</span>   * Statistics thread.  Periodically output cache statistics to the log.<a name="line.652"></a>
+<span class="sourceLineNo">653</span>   */<a name="line.653"></a>
+<span class="sourceLineNo">654</span>  private static class StatisticsThread extends Thread {<a name="line.654"></a>
+<span class="sourceLineNo">655</span>    private final BucketCache bucketCache;<a name="line.655"></a>
+<span class="sourceLineNo">656</span><a name="line.656"></a>
+<span class="sourceLineNo">657</span>    public StatisticsThread(BucketCache bucketCache) {<a name="line.657"></a>
+<span class="sourceLineNo">658</span>      super("BucketCacheStatsThread");<a name="line.658"></a>
+<span class="sourceLineNo">659</span>      setDaemon(true);<a name="line.659"></a>
+<span class="sourceLineNo">660</span>      this.bucketCache = bucketCache;<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>    @Override<a name="line.663"></a>
+<span class="sourceLineNo">664</span>    public void run() {<a name="line.664"></a>
+<span class="sourceLineNo">665</span>      bucketCache.logStats();<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>  public void logStats() {<a name="line.669"></a>
+<span class="sourceLineNo">670</span>    long totalSize = bucketAllocator.getTotalSize();<a name="line.670"></a>
+<span class="sourceLineNo">671</span>    long usedSize = bucketAllocator.getUsedSize();<a name="line.671"></a>
+<span class="sourceLineNo">672</span>    long freeSize = totalSize - usedSize;<a name="line.672"></a>
+<span class="sourceLineNo">673</span>    long cacheSize = getRealCacheSize();<a name="line.673"></a>
+<span class="sourceLineNo">674</span>    LOG.info("failedBlockAdditions=" + cacheStats.getFailedInserts() + ", " +<a name="line.674"></a>
+<span class="sourceLineNo">675</span>        "totalSize=" + StringUtils.byteDesc(totalSize) + ", " +<a name="line.675"></a>
+<span class="sourceLineNo">676</span>        "freeSize=" + StringUtils.byteDesc(freeSize) + ", " +<a name="line.676"></a>
+<span class="sourceLineNo">677</span>        "usedSize=" + StringUtils.byteDesc(usedSize) +", " +<a name="line.677"></a>
+<span class="sourceLineNo">678</span>        "cacheSize=" + StringUtils.byteDesc(cacheSize) +", " +<a name="line.678"></a>
+<span class="sourceLineNo">679</span>        "accesses=" + cacheStats.getRequestCount() + ", " +<a name="line.679"></a>
+<span class="sourceLineNo">680</span>        "hits=" + cacheStats.getHitCount() + ", " +<a name="line.680"></a>
+<span class="sourceLineNo">681</span>        "IOhitsPerSecond=" + cacheStats.getIOHitsPerSecond() + ", " +<a name="line.681"></a>
+<span class="sourceLineNo">682</span>        "IOTimePerHit=" + String.format("%.2f", cacheStats.getIOTimePerHit())+ ", " +<a name="line.682"></a>
+<span class="sourceLineNo">683</span>        "hitRatio=" + (cacheStats.getHitCount() == 0 ? "0," :<a name="line.683"></a>
+<span class="sourceLineNo">684</span>          (StringUtils.formatPercent(cacheStats.getHitRatio(), 2)+ ", ")) +<a name="line.684"></a>
+<span class="sourceLineNo">685</span>        "cachingAccesses=" + cacheStats.getRequestCachingCount() + ", " +<a name="line.685"></a>
+<span class="sourceLineNo">686</span>        "cachingHits=" + cacheStats.getHitCachingCount() + ", " +<a name="line.686"></a>
+<span class="sourceLineNo">687</span>        "cachingHitsRatio=" +(cacheStats.getHitCachingCount() == 0 ? "0," :<a name="line.687"></a>
+<span class="sourceLineNo">688</span>          (StringUtils.formatPercent(cacheStats.getHitCachingRatio(), 2)+ ", ")) +<a name="line.688"></a>
+<span class="sourceLineNo">689</span>        "evictions=" + cacheStats.getEvictionCount() + ", " +<a name="line.689"></a>
+<span class="sourceLineNo">690</span>        "evicted=" + cacheStats.getEvictedCount() + ", " +<a name="line.690"></a>
+<span class="sourceLineNo">691</span>        "evictedPerRun=" + cacheStats.evictedPerEviction());<a name="line.691"></a>
+<span class="sourceLineNo">692</span>    cacheStats.reset();<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>  public long getRealCacheSize() {<a name="line.695"></a>
+<span class="sourceLineNo">696</span>    return this.realCacheSize.sum();<a name="line.696"></a>
+<span class="sourceLineNo">697</span>  }<a name="line.697"></a>
+<span class="sourceLineNo">698</span><a name="line.698"></a>
+<span class="sourceLineNo">699</span>  private long acceptableSize() {<a name="line.699"></a>
+<span class="sourceLineNo">700</span>    return (long) Math.floor(bucketAllocator.getTotalSize() * acceptableFactor);<a name="line.700"></a>
+<span class="sourceLineNo">701</span>  }<a name="line.701"></a>
+<span class="sourceLineNo">702</span><a name="line.702"></a>
+<span class="sourceLineNo">703</span>  @VisibleForTesting<a name="line.703"></a>
+<span class="sourceLineNo">704</span>  long getPartitionSize(float partitionFactor) {<a name="line.704"></a>
+<span class="sourceLineNo">705</span>    return (long) Math.floor(bucketAllocator.getTotalSize() * partitionFactor * minFactor);<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>   * Return the count of bucketSizeinfos still need free space<a name="line.709"></a>
+<span class="sourceLineNo">710</span>   */<a name="line.710"></a>
+<span class="sourceLineNo">711</span>  private int bucketSizesAboveThresholdCount(float minFactor) {<a name="line.711"></a>
+<span class="sourceLineNo">712</span>    BucketAllocator.IndexStatistics[] stats = bucketAllocator.getIndexStatistics();<a name="line.712"></a>
+<span class="sourceLineNo">713</span>    int fullCount = 0;<a name="line.713"></a>
+<span class="sourceLineNo">714</span>    for (int i = 0; i &lt; stats.length; i++) {<a name="line.714"></a>
+<span class="sourceLineNo">715</span>      long freeGoal = (long) Math.floor(stats[i].totalCount() * (1 - minFactor));<a name="line.715"></a>
+<span class="sourceLineNo">716</span>      freeGoal = Math.max(freeGoal, 1);<a name="line.716"></a>
+<span class="sourceLineNo">717</span>      if (stats[i].freeCount() &lt; freeGoal) {<a name="line.717"></a>
+<span class="sourceLineNo">718</span>        fullCount++;<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>
+<span class="sourceLineNo">721</span>    return fullCount;<a name="line.721"></a>
+<span class="sourceLineNo">722</span>  }<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>   * This method will find the buckets that are minimally occupied<a name="line.725"></a>
+<span class="sourceLineNo">726</span>   * and are not reference counted and will free them completely<a name="line.726"></a>
+<span class="sourceLineNo">727</span>   * without any constraint on the access times of the elements,<a name="line.727"></a>
+<span class="sourceLineNo">728</span>   * and as a process will completely free at most the number of buckets<a name="line.728"></a>
+<span class="sourceLineNo">729</span>   * passed, sometimes it might not due to changing refCounts<a name="line.729"></a>
+<span class="sourceLineNo">730</span>   *<a name="line.730"></a>
+<span class="sourceLineNo">731</span>   * @param completelyFreeBucketsNeeded number of buckets to free<a name="line.731"></a>
+<span class="sourceLineNo">732</span>   **/<a name="line.732"></a>
+<span class="sourceLineNo">733</span>  private void freeEntireBuckets(int completelyFreeBucketsNeeded) {<a name="line.733"></a>
+<span class="sourceLineNo">734</span>    if (completelyFreeBucketsNeeded != 0) {<a name="line.734"></a>
+<span class="sourceLineNo">735</span>      // First we will build a set where the offsets are reference counted, usually<a name="line.735"></a>
+<span class="sourceLineNo">736</span>      // this set is small around O(Handler Count) unless something else is wrong<a name="line.736"></a>
+<span class="sourceLineNo">737</span>      Set&lt;Integer&gt; inUseBuckets = new HashSet&lt;Integer&gt;();<a name="line.737"></a>
+<span class="sourceLineNo">738</span>      for (BucketEntry entry : backingMap.values()) {<a name="line.738"></a>
+<span class="sourceLineNo">739</span>        if (entry.getRefCount() != 0) {<a name="line.739"></a>
+<span class="sourceLineNo">740</span>          inUseBuckets.add(bucketAllocator.getBucketIndex(entry.offset()));<a name="line.740"></a>
+<span class="sourceLineNo">741</span>        }<a name="line.741"></a>
+<span class="sourceLineNo">742</span>      }<a name="line.742"></a>
+<span class="sourceLineNo">743</span><a name="line.743"></a>
+<span class="sourceLineNo">744</span>      Set&lt;Integer&gt; candidateBuckets = bucketAllocator.getLeastFilledBuckets(<a name="line.744"></a>
+<span class="sourceLineNo">745</span>          inUseBuckets, completelyFreeBucketsNeeded);<a name="line.745"></a>
+<span class="sourceLineNo">746</span>      for (Map.Entry&lt;BlockCacheKey, BucketEntry&gt; entry : backingMap.entrySet()) {<a name="line.746"></a>
+<span class="sourceLineNo">747</span>        if (candidateBuckets.contains(bucketAllocator<a name="line.747"></a>
+<span class="sourceLineNo">748</span>            .getBucketIndex(entry.getValue().offset()))) {<a name="line.748"></a>
+<span class="sourceLineNo">749</span>          evictBlock(entry.getKey(), false);<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>  }<a name="line.753"></a>
+<span class="sourceLineNo">754</span><a name="line.754"></a>
+<span class="sourceLineNo">755</span>  /**<a name="line.755"></a>
+<span class="sourceLineNo">756</span>   * Free the space if the used size reaches acceptableSize() or one size block<a name="line.756"></a>
+<span class="sourceLineNo">757</span>   * couldn't be allocated. When freeing the space, we use the LRU algorithm and<a name="line.757"></a>
+<span class="sourceLineNo">758</span>   * ensure there must be some blocks evicted<a name="line.758"></a>
+<span class="sourceLineNo">759</span>   * @param why Why we are being called<a name="line.759"></a>
+<span class="sourceLineNo">760</span>   */<a name="line.760"></a>
+<span class="sourceLineNo">761</span>  private void freeSpace(final String why) {<a name="line.761"></a>
+<span class="sourceLineNo">762</span>    // Ensure only one freeSpace progress at a time<a name="line.762"></a>
+<span class="sourceLineNo">763</span>    if (!freeSpaceLock.tryLock()) {<a name="line.763"></a>
+<span class="sourceLineNo">764</span>      return;<a name="line.764"></a>
+<span class="sourceLineNo">765</span>    }<a name="line.765"></a>
+<span class="sourceLineNo">766</span>    try {<a name="line.766"></a>
+<span class="sourceLineNo">767</span>      freeInProgress = true;<a name="line.767"></a>
+<span class="sourceLineNo">768</span>      long bytesToFreeWithoutExtra = 0;<a name="line.768"></a>
+<span class="sourceLineNo">769</span>      // Calculate free byte for each bucketSizeinfo<a name="line.769"></a>
+<span class="sourceLineNo">770</span>      StringBuilder msgBuffer = LOG.isDebugEnabled()? new StringBuilder(): null;<a name="line.770"></a>
+<span class="sourceLineNo">771</span>      BucketAllocator.IndexStatistics[] stats = bucketAllocator.getIndexStatistics();<a name="line.771"></a>
+<span class="sourceLineNo">772</span>      long[] bytesToFreeForBucket = new long[stats.length];<a name="line.772"></a>
+<span class="sourceLineNo">773</span>      for (int i = 0; i &lt; stats.length; i++) {<a name="line.773"></a>
+<span class="sourceLineNo">774</span>        bytesToFreeForBucket[i] = 0;<a name="line.774"></a>
+<span class="sourceLineNo">775</span>        long freeGoal = (long) Math.floor(stats[i].totalCount() * (1 - minFactor));<a name="line.775"></a>
+<span class="sourceLineNo">776</span>        freeGoal = Math.max(freeGoal, 1);<a name="line.776"></a>
+<span class="sourceLineNo">777</span>        if (stats[i].freeCount() &lt; freeGoal) {<a name="line.777"></a>
+<span class="sourceLineNo">778</span>          bytesToFreeForBucket[i] = stats[i].itemSize() * (freeGoal - stats[i].freeCount());<a name="line.778"></a>
+<span class="sourceLineNo">779</span>          bytesToFreeWithoutExtra += bytesToFreeForBucket[i];<a name="line.779"></a>
+<span class="sourceLineNo">780</span>          if (msgBuffer != null) {<a name="line.780"></a>
+<span class="sourceLineNo">781</span>            msgBuffer.append("Free for bucketSize(" + stats[i].itemSize() + ")="<a name="line.781"></a>
+<span class="sourceLineNo">782</span>              + StringUtils.byteDesc(bytesToFreeForBucket[i]) + ", ");<a name="line.782"></a>
+<span class="sourceLineNo">783</span>          }<a name="line.783"></a>
+<span class="sourceLineNo">784</span>        }<a name="line.784"></a>
 <span class="sourceLineNo">785</span>      }<a name="line.785"></a>
-<span class="sourceLineNo">786</span>      long currentSize = bucketAllocator.getUsedSize();<a name="line.786"></a>
-<span class="sourceLineNo">787</span>      long totalSize = bucketAllocator.getTotalSize();<a name="line.787"></a>
-<span class="sourceLineNo">788</span>      if (LOG.isDebugEnabled() &amp;&amp; msgBuffer != null) {<a name="line.788"></a>
-<span class="sourceLineNo">789</span>        LOG.debug("Free started because \"" + why + "\"; " + msgBuffer.toString() +<a name="line.789"></a>
-<span class="sourceLineNo">790</span>          " of current used=" + StringUtils.byteDesc(currentSize) + ", actual cacheSize=" +<a name="line.790"></a>
-<span class="sourceLineNo">791</span>          StringUtils.byteDesc(realCacheSize.sum()) + ", total=" + StringUtils.byteDesc(totalSize));<a name="line.791"></a>
+<span class="sourceLineNo">786</span>      if (msgBuffer != null) {<a name="line.786"></a>
+<span class="sourceLineNo">787</span>        msgBuffer.append("Free for total=" + StringUtils.byteDesc(bytesToFreeWithoutExtra) + ", ");<a name="line.787"></a>
+<span class="sourceLineNo">788</span>      }<a name="line.788"></a>
+<span class="sourceLineNo">789</span><a name="line.789"></a>
+<span class="sourceLineNo">790</span>      if (bytesToFreeWithoutExtra &lt;= 0) {<a name="line.790"></a>
+<span class="sourceLineNo">791</span>        return;<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>
-<span class="sourceLineNo">794</span>      long bytesToFreeWithExtra = (long) Math.floor(bytesToFreeWithoutExtra<a name="line.794"></a>
-<span class="sourceLineNo">795</span>          * (1 + extraFreeFactor));<a name="line.795"></a>
-<span class="sourceLineNo">796</span><a name="line.796"></a>
-<span class="sourceLineNo">797</span>      // Instantiate priority buckets<a name="line.797"></a>
-<span class="sourceLineNo">798</span>      BucketEntryGroup bucketSingle = new BucketEntryGroup(bytesToFreeWithExtra,<a name="line.798"></a>
-<span class="sourceLineNo">799</span>          blockSize, getPartitionSize(singleFactor));<a name="line.799"></a>
-<span class="sourceLineNo">800</span>      BucketEntryGroup bucketMulti = new BucketEntryGroup(bytesToFreeWithExtra,<a name="line.800"></a>
-<span class="sourceLineNo">801</span>          blockSize, getPartitionSize(multiFactor));<a name="line.801"></a>
-<span class="sourceLineNo">802</span>      BucketEntryGroup bucketMemory = new BucketEntryGroup(bytesToFreeWithExtra,<a name="line.802"></a>
-<span class="sourceLineNo">803</span>          blockSize, getPartitionSize(memoryFactor));<a name="line.803"></a>
-<span class="sourceLineNo">804</span><a name="line.804"></a>
-<span class="sourceLineNo">805</span>      // Scan entire map putting bucket entry into appropriate bucket entry<a name="line.805"></a>
-<span class="sourceLineNo">806</span>      // group<a name="line.806"></a>
-<span class="sourceLineNo">807</span>      for (Map.Entry&lt;BlockCacheKey, BucketEntry&gt; bucketEntryWithKey : backingMap.entrySet()) {<a name="line.807"></a>
-<span class="sourceLineNo">808</span>        switch (bucketEntryWithKey.getValue().getPriority()) {<a name="line.808"></a>
-<span class="sourceLineNo">809</span>          case SINGLE: {<a name="line.809"></a>
-<span class="sourceLineNo">810</span>            bucketSingle.add(bucketEntryWithKey);<a name="line.810"></a>
-<span class="sourceLineNo">811</span>            break;<a name="line.811"></a>
-<span class="sourceLineNo">812</span>          }<a name="line.812"></a>
-<span class="sourceLineNo">813</span>          case MULTI: {<a name="line.813"></a>
-<span class="sourceLineNo">814</span>            bucketMulti.add(bucketEntryWithKey);<a name="line.814"></a>
-<span class="sourceLineNo">815</span>            break;<a name="line.815"></a>
-<span class="sourceLineNo">816</span>          }<a name="line.816"></a>
-<span class="sourceLineNo">817</span>          case MEMORY: {<a name="line.817"></a>
-<span class="sourceLineNo">818</span>            bucketMemory.add(bucketEntryWithKey);<a name="line.818"></a>
-<span class="sourceLineNo">819</span>            break;<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><a name="line.823"></a>
-<span class="sourceLineNo">824</span>      PriorityQueue&lt;BucketEntryGroup&gt; bucketQueue = new PriorityQueue&lt;&gt;(3,<a name="line.824"></a>
-<span class="sourceLineNo">825</span>          Comparator.comparingLong(BucketEntryGroup::overflow));<a name="line.825"></a>
-<span class="sourceLineNo">826</span><a name="line.826"></a>
-<span class="sourceLineNo">827</span>      bucketQueue.add(bucketSingle);<a name="line.827"></a>
-<span class="sourceLineNo">828</span>      bucketQueue.add(bucketMulti);<a name="line.828"></a>
-<span class="sourceLineNo">829</span>      bucketQueue.add(bucketMemory);<a name="line.829"></a>
+<span class="sourceLineNo">793</span>      long currentSize = bucketAllocator.getUsedSize();<a name="line.793"></a>
+<span class="sourceLineNo">794</span>      long totalSize = bucketAllocator.getTotalSize();<a name="line.794"></a>
+<span class="sourceLineNo">795</span>      if (LOG.isDebugEnabled() &amp;&amp; msgBuffer != null) {<a name="line.795"></a>
+<span class="sourceLineNo">796</span>        LOG.debug("Free started because \"" + why + "\"; " + msgBuffer.toString() +<a name="line.796"></a>
+<span class="sourceLineNo">797</span>          " of current used=" + StringUtils.byteDesc(currentSize) + ", actual cacheSize=" +<a name="line.797"></a>
+<span class="sourceLineNo">798</span>          StringUtils.byteDesc(realCacheSize.sum()) + ", total=" + StringUtils.byteDesc(totalSize));<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>      long bytesToFreeWithExtra = (long) Math.floor(bytesToFreeWithoutExtra<a name="line.801"></a>
+<span class="sourceLineNo">802</span>          * (1 + extraFreeFactor));<a name="line.802"></a>
+<span class="sourceLineNo">803</span><a name="line.803"></a>
+<span class="sourceLineNo">804</span>      // Instantiate priority buckets<a name="line.804"></a>
+<span class="sourceLineNo">805</span>      BucketEntryGroup bucketSingle = new BucketEntryGroup(bytesToFreeWithExtra,<a name="line.805"></a>
+<span class="sourceLineNo">806</span>          blockSize, getPartitionSize(singleFactor));<a name="line.806"></a>
+<span class="sourceLineNo">807</span>      BucketEntryGroup bucketMulti = new BucketEntryGroup(bytesToFreeWithExtra,<a name="line.807"></a>
+<span class="sourceLineNo">808</span>          blockSize, getPartitionSize(multiFactor));<a name="line.808"></a>
+<span class="sourceLineNo">809</span>      BucketEntryGroup bucketMemory = new BucketEntryGroup(bytesToFreeWithExtra,<a name="line.809"></a>
+<span class="sourceLineNo">810</span>          blockSize, getPartitionSize(memoryFactor));<a name="line.810"></a>
+<span class="sourceLineNo">811</span><a name="line.811"></a>
+<span class="sourceLineNo">812</span>      // Scan entire map putting bucket entry into appropriate bucket entry<a name="line.812"></a>
+<span class="sourceLineNo">813</span>      // group<a name="line.813"></a>
+<span class="sourceLineNo">814</span>      for (Map.Entry&lt;BlockCacheKey, BucketEntry&gt; bucketEntryWithKey : backingMap.entrySet()) {<a name="line.814"></a>
+<span class="sourceLineNo">815</span>        switch (bucketEntryWithKey.getValue().getPriority()) {<a name="line.815"></a>
+<span class="sourceLineNo">816</span>          case SINGLE: {<a name="line.816"></a>
+<span class="sourceLineNo">817</span>            bucketSingle.add(bucketEntryWithKey);<a name="line.817"></a>
+<span class="sourceLineNo">818</span>            break;<a name="line.818"></a>
+<span class="sourceLineNo">819</span>          }<a name="line.819"></a>
+<span class="sourceLineNo">820</span>          case MULTI: {<a name="line.820"></a>
+<span class="sourceLineNo">821</span>            bucketMulti.add(bucketEntryWithKey);<a name="line.821"></a>
+<span class="sourceLineNo">822</span>            break;<a name="line.822"></a>
+<span class="sourceLineNo">823</span>          }<a name="line.823"></a>
+<span class="sourceLineNo">824</span>          case MEMORY: {<a name="line.824"></a>
+<span class="sourceLineNo">825</span>            bucketMemory.add(bucketEntryWithKey);<a name="line.825"></a>
+<span class="sourceLineNo">826</span>            break;<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">830</span><a name="line.830"></a>
-<span class="sourceLineNo">831</span>      int remainingBuckets = 3;<a name="line.831"></a>
-<span class="sourceLineNo">832</span>      long bytesFreed = 0;<a name="line.832"></a>
+<span class="sourceLineNo">831</span>      PriorityQueue&lt;BucketEntryGroup&gt; bucketQueue = new PriorityQueue&lt;&gt;(3,<a name="line.831"></a>
+<span class="sourceLineNo">832</span>          Comparator.comparingLong(BucketEntryGroup::overflow));<a name="line.832"></a>
 <span class="sourceLineNo">833</span><a name="line.833"></a>
-<span class="sourceLineNo">834</span>      BucketEntryGroup bucketGroup;<a name="line.834"></a>
-<span class="sourceLineNo">835</span>      while ((bucketGroup = bucketQueue.poll()) != null) {<a name="line.835"></a>
-<span class="sourceLineNo">836</span>        long overflow = bucketGroup.overflow();<a name="line.836"></a>
-<span class="sourceLineNo">837</span>        if (overflow &gt; 0) {<a name="line.837"></a>
-<span class="sourceLineNo">838</span>          long bucketBytesToFree = Math.min(overflow,<a name="line.838"></a>
-<span class="sourceLineNo">839</span>              (bytesToFreeWithoutExtra - bytesFreed) / remainingBuckets);<a name="line.839"></a>
-<span class="sourceLineNo">840</span>          bytesFreed += bucketGroup.free(bucketBytesToFree);<a name="line.840"></a>
-<span class="sourceLineNo">841</span>        }<a name="line.841"></a>
-<span class="sourceLineNo">842</span>        remainingBuckets--;<a name="line.842"></a>
-<span class="sourceLineNo">843</span>      }<a name="line.843"></a>
-<span class="sourceLineNo">844</span><a name="line.844"></a>
-<span class="sourceLineNo">845</span>      // Check and free if there are buckets that still need freeing of space<a name="line.845"></a>
-<span class="sourceLineNo">846</span>      if (bucketSizesAboveThresholdCount(minFactor) &gt; 0) {<a name="line.846"></a>
-<span class="sourceLineNo">847</span>        bucketQueue.clear();<a name="line.847"></a>
-<span class="sourceLineNo">848</span>        remainingBuckets = 3;<a name="line.848"></a>
-<span class="sourceLineNo">849</span><a name="line.849"></a>
-<span class="sourceLineNo">850</span>        bucketQueue.add(bucketSingle);<a name="line.850"></a>
-<span class="sourceLineNo">851</span>        bucketQueue.add(bucketMulti);<a name="line.851"></a>
-<span class="sourceLineNo">852</span>        bucketQueue.add(bucketMemory);<a name="line.852"></a>
-<span class="sourceLineNo">853</span><a name="line.853"></a>
-<span class="sourceLineNo">854</span>        while ((bucketGroup = bucketQueue.poll()) != null) {<a name="line.854"></a>
-<span class="sourceLineNo">855</span>          long bucketBytesToFree = (bytesToFreeWithExtra - bytesFreed) / remainingBuckets;<a name="line.855"></a>
-<span class="sourceLineNo">856</span>          bytesFreed += bucketGroup.free(bucketBytesToFree);<a name="line.856"></a>
-<span class="sourceLineNo">857</span>          remainingBuckets--;<a name="line.857"></a>
-<span class="sourceLineNo">858</span>        }<a name="line.858"></a>
-<span class="sourceLineNo">859</span>      }<a name="line.859"></a>
+<span class="sourceLineNo">834</span>      bucketQueue.add(bucketSingle);<a name="line.834"></a>
+<span class="sourceLineNo">835</span>      bucketQueue.add(bucketMulti);<a name="line.835"></a>
+<span class="sourceLineNo">836</span>      bucketQueue.add(bucketMemory);<a name="line.836"></a>
+<span class="sourceLineNo">837</span><a name="line.837"></a>
+<span class="sourceLineNo">838</span>      int remainingBuckets = 3;<a name="line.838"></a>
+<span class="sourceLineNo">839</span>      long bytesFreed = 0;<a name="line.839"></a>
+<span class="sourceLineNo">840</span><a name="line.840"></a>
+<span class="sourceLineNo">841</span>      BucketEntryGroup bucketGroup;<a name="line.841"></a>
+<span class="sourceLineNo">842</span>      while ((bucketGroup = bucketQueue.poll()) != null) {<a name="line.842"></a>
+<span class="sourceLineNo">843</span>        long overflow = bucketGroup.overflow();<a name="line.843"></a>
+<span class="sourceLineNo">844</span>        if (overflow &gt; 0) {<a name="line.844"></a>
+<span class="sourceLineNo">845</span>          long bucketBytesToFree = Math.min(overflow,<a name="line.845"></a>
+<span class="sourceLineNo">846</span>              (bytesToFreeWithoutExtra - bytesFreed) / remainingBuckets);<a name="line.846"></a>
+<span class="sourceLineNo">847</span>          bytesFreed += bucketGroup.free(bucketBytesToFree);<a name="line.847"></a>
+<span class="sourceLineNo">848</span>        }<a name="line.848"></a>
+<span class="sourceLineNo">849</span>        remainingBuckets--;<a name="line.849"></a>
+<span class="sourceLineNo">850</span>      }<a name="line.850"></a>
+<span class="sourceLineNo">851</span><a name="line.851"></a>
+<span class="sourceLineNo">852</span>      // Check and free if there are buckets that still need freeing of space<a name="line.852"></a>
+<span class="sourceLineNo">853</span>      if (bucketSizesAboveThresholdCount(minFactor) &gt; 0) {<a name="line.853"></a>
+<span class="sourceLineNo">854</span>        bucketQueue.clear();<a name="line.854"></a>
+<span class="sourceLineNo">855</span>        remainingBuckets = 3;<a name="line.855"></a>
+<span class="sourceLineNo">856</span><a name="line.856"></a>
+<span class="sourceLineNo">857</span>        bucketQueue.add(bucketSingle);<a name="line.857"></a>
+<span class="sourceLineNo">858</span>        bucketQueue.add(bucketMulti);<a name="line.858"></a>
+<span class="sourceLineNo">859</span>        bucketQueue.add(bucketMemory);<a name="line.859"></a>
 <span class="sourceLineNo">860</span><a name="line.860"></a>
-<span class="sourceLineNo">861</span>      // Even after the above free we might still need freeing because of the<a name="line.861"></a>
-<span class="sourceLineNo">862</span>      // De-fragmentation of the buckets (also called Slab Calcification problem), i.e<a name="line.862"></a>
-<span class="sourceLineNo">863</span>      // there might be some buckets where the occupancy is very sparse and thus are not<a name="line.863"></a>
-<span class="sourceLineNo">864</span>      // yielding the free for the other bucket sizes, the fix for this to evict some<a name="line.864"></a>
-<span class="sourceLineNo">865</span>      // of the buckets, we do this by evicting the buckets that are least fulled<a name="line.865"></a>
-<span class="sourceLineNo">866</span>      freeEntireBuckets(DEFAULT_FREE_ENTIRE_BLOCK_FACTOR *<a name="line.866"></a>
-<span class="sourceLineNo">867</span>          bucketSizesAboveThresholdCount(1.0f));<a name="line.867"></a>
-<span class="sourceLineNo">868</span><a name="line.868"></a>
-<span class="sourceLineNo">869</span>      if (LOG.isDebugEnabled()) {<a name="line.869"></a>
-<span class="sourceLineNo">870</span>        long single = bucketSingle.totalSize();<a name="line.870"></a>
-<span class="sourceLineNo">871</span>        long multi = bucketMulti.totalSize();<a name="line.871"></a>
-<span class="sourceLineNo">872</span>        long memory = bucketMemory.totalSize();<a name="line.872"></a>
-<span class="sourceLineNo">873</span>        if (LOG.isDebugEnabled()) {<a name="line.873"></a>
-<span class="sourceLineNo">874</span>          LOG.debug("Bucket cache free space completed; " + "freed="<a name="line.874"></a>
-<span class="sourceLineNo">875</span>            + StringUtils.byteDesc(bytesFreed) + ", " + "total="<a name="line.875"></a>
-<span class="sourceLineNo">876</span>            + StringUtils.byteDesc(totalSize) + ", " + "single="<a name="line.876"></a>
-<span class="sourceLineNo">877</span>            + StringUtils.byteDesc(single) + ", " + "multi="<a name="line.877"></a>
-<span class="sourceLineNo">878</span>            + StringUtils.byteDesc(multi) + ", " + "memory="<a name="line.878"></a>
-<span class="sourceLineNo">879</span>            + StringUtils.byteDesc(memory));<a name="line.879"></a>
-<span class="sourceLineNo">880</span>        }<a name="line.880"></a>
-<span class="sourceLineNo">881</span>      }<a name="line.881"></a>
-<span class="sourceLineNo">882</span><a name="line.882"></a>
-<span class="sourceLineNo">883</span>    } catch (Throwable t) {<a name="line.883"></a>
-<span class="sourceLineNo">884</span>      LOG.warn("Failed freeing space", t);<a name="line.884"></a>
-<span class="sourceLineNo">885</span>    } finally {<a name="line.885"></a>
-<span class="sourceLineNo">886</span>      cacheStats.evict();<a name="line.886"></a>
-<span class="sourceLineNo">887</span>      freeInProgress = false;<a name="line.887"></a>
-<span class="sourceLineNo">888</span>      freeSpaceLock.unlock();<a name="line.888"></a>
-<span class="sourceLineNo">889</span>    }<a name="line.889"></a>
-<span class="sourceLineNo">890</span>  }<a name="line.890"></a>
-<span class="sourceLineNo">891</span><a name="line.891"></a>
-<span class="sourceLineNo">892</span>  // This handles flushing the RAM cache to IOEngine.<a name="line.892"></a>
-<span class="sourceLineNo">893</span>  @VisibleForTesting<a name="line.893"></a>
-<span class="sourceLineNo">894</span>  class WriterThread extends HasThread {<a name="line.894"></a>
-<span class="sourceLineNo">895</span>    private final BlockingQueue&lt;RAMQueueEntry&gt; inputQueue;<a name="line.895"></a>
-<span class="sourceLineNo">896</span>    private volatile boolean writerEnabled = true;<a name="line.896"></a>
-<span class="sourceLineNo">897</span><a name="line.897"></a>
-<span class="sourceLineNo">898</span>    WriterThread(BlockingQueue&lt;RAMQueueEntry&gt; queue) {<a name="line.898"></a>
-<span class="sourceLineNo">899</span>      super("Buck

<TRUNCATED>

[28/50] hbase-site git commit: Published site at 26babcf013de696b899d76a3c39434b794440d8d.

Posted by gi...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.StatisticsThread.html
----------------------------------------------------------------------
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.StatisticsThread.html b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.StatisticsThread.html
index f5747c6..b94ef5e 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.StatisticsThread.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.StatisticsThread.html
@@ -388,811 +388,816 @@
 <span class="sourceLineNo">380</span><a name="line.380"></a>
 <span class="sourceLineNo">381</span>    LruCachedBlock cb = map.get(cacheKey);<a name="line.381"></a>
 <span class="sourceLineNo">382</span>    if (cb != null) {<a name="line.382"></a>
-<span class="sourceLineNo">383</span>      // compare the contents, if they are not equal, we are in big trouble<a name="line.383"></a>
-<span class="sourceLineNo">384</span>      if (BlockCacheUtil.compareCacheBlock(buf, cb.getBuffer()) != 0) {<a name="line.384"></a>
-<span class="sourceLineNo">385</span>        throw new RuntimeException("Cached block contents differ, which should not have happened."<a name="line.385"></a>
-<span class="sourceLineNo">386</span>          + "cacheKey:" + cacheKey);<a name="line.386"></a>
-<span class="sourceLineNo">387</span>      }<a name="line.387"></a>
-<span class="sourceLineNo">388</span>      String msg = "Cached an already cached block: " + cacheKey + " cb:" + cb.getCacheKey();<a name="line.388"></a>
-<span class="sourceLineNo">389</span>      msg += ". This is harmless and can happen in rare cases (see HBASE-8547)";<a name="line.389"></a>
-<span class="sourceLineNo">390</span>      LOG.warn(msg);<a name="line.390"></a>
-<span class="sourceLineNo">391</span>      return;<a name="line.391"></a>
-<span class="sourceLineNo">392</span>    }<a name="line.392"></a>
-<span class="sourceLineNo">393</span>    long currentSize = size.get();<a name="line.393"></a>
-<span class="sourceLineNo">394</span>    long currentAcceptableSize = acceptableSize();<a name="line.394"></a>
-<span class="sourceLineNo">395</span>    long hardLimitSize = (long) (hardCapacityLimitFactor * currentAcceptableSize);<a name="line.395"></a>
-<span class="sourceLineNo">396</span>    if (currentSize &gt;= hardLimitSize) {<a name="line.396"></a>
-<span class="sourceLineNo">397</span>      stats.failInsert();<a name="line.397"></a>
-<span class="sourceLineNo">398</span>      if (LOG.isTraceEnabled()) {<a name="line.398"></a>
-<span class="sourceLineNo">399</span>        LOG.trace("LruBlockCache current size " + StringUtils.byteDesc(currentSize)<a name="line.399"></a>
-<span class="sourceLineNo">400</span>          + " has exceeded acceptable size " + StringUtils.byteDesc(currentAcceptableSize) + "."<a name="line.400"></a>
-<span class="sourceLineNo">401</span>          + " The hard limit size is " + StringUtils.byteDesc(hardLimitSize)<a name="line.401"></a>
-<span class="sourceLineNo">402</span>          + ", failed to put cacheKey:" + cacheKey + " into LruBlockCache.");<a name="line.402"></a>
-<span class="sourceLineNo">403</span>      }<a name="line.403"></a>
-<span class="sourceLineNo">404</span>      if (!evictionInProgress) {<a name="line.404"></a>
-<span class="sourceLineNo">405</span>        runEviction();<a name="line.405"></a>
-<span class="sourceLineNo">406</span>      }<a name="line.406"></a>
-<span class="sourceLineNo">407</span>      return;<a name="line.407"></a>
-<span class="sourceLineNo">408</span>    }<a name="line.408"></a>
-<span class="sourceLineNo">409</span>    cb = new LruCachedBlock(cacheKey, buf, count.incrementAndGet(), inMemory);<a name="line.409"></a>
-<span class="sourceLineNo">410</span>    long newSize = updateSizeMetrics(cb, false);<a name="line.410"></a>
-<span class="sourceLineNo">411</span>    map.put(cacheKey, cb);<a name="line.411"></a>
-<span class="sourceLineNo">412</span>    long val = elements.incrementAndGet();<a name="line.412"></a>
-<span class="sourceLineNo">413</span>    if (buf.getBlockType().isData()) {<a name="line.413"></a>
-<span class="sourceLineNo">414</span>       dataBlockElements.increment();<a name="line.414"></a>
-<span class="sourceLineNo">415</span>    }<a name="line.415"></a>
-<span class="sourceLineNo">416</span>    if (LOG.isTraceEnabled()) {<a name="line.416"></a>
-<span class="sourceLineNo">417</span>      long size = map.size();<a name="line.417"></a>
-<span class="sourceLineNo">418</span>      assertCounterSanity(size, val);<a name="line.418"></a>
-<span class="sourceLineNo">419</span>    }<a name="line.419"></a>
-<span class="sourceLineNo">420</span>    if (newSize &gt; currentAcceptableSize &amp;&amp; !evictionInProgress) {<a name="line.420"></a>
-<span class="sourceLineNo">421</span>      runEviction();<a name="line.421"></a>
-<span class="sourceLineNo">422</span>    }<a name="line.422"></a>
-<span class="sourceLineNo">423</span>  }<a name="line.423"></a>
-<span class="sourceLineNo">424</span><a name="line.424"></a>
-<span class="sourceLineNo">425</span>  /**<a name="line.425"></a>
-<span class="sourceLineNo">426</span>   * Sanity-checking for parity between actual block cache content and metrics.<a name="line.426"></a>
-<span class="sourceLineNo">427</span>   * Intended only for use with TRACE level logging and -ea JVM.<a name="line.427"></a>
-<span class="sourceLineNo">428</span>   */<a name="line.428"></a>
-<span class="sourceLineNo">429</span>  private static void assertCounterSanity(long mapSize, long counterVal) {<a name="line.429"></a>
-<span class="sourceLineNo">430</span>    if (counterVal &lt; 0) {<a name="line.430"></a>
-<span class="sourceLineNo">431</span>      LOG.trace("counterVal overflow. Assertions unreliable. counterVal=" + counterVal +<a name="line.431"></a>
-<span class="sourceLineNo">432</span>        ", mapSize=" + mapSize);<a name="line.432"></a>
-<span class="sourceLineNo">433</span>      return;<a name="line.433"></a>
-<span class="sourceLineNo">434</span>    }<a name="line.434"></a>
-<span class="sourceLineNo">435</span>    if (mapSize &lt; Integer.MAX_VALUE) {<a name="line.435"></a>
-<span class="sourceLineNo">436</span>      double pct_diff = Math.abs((((double) counterVal) / ((double) mapSize)) - 1.);<a name="line.436"></a>
-<span class="sourceLineNo">437</span>      if (pct_diff &gt; 0.05) {<a name="line.437"></a>
-<span class="sourceLineNo">438</span>        LOG.trace("delta between reported and actual size &gt; 5%. counterVal=" + counterVal +<a name="line.438"></a>
-<span class="sourceLineNo">439</span>          ", mapSize=" + mapSize);<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><a name="line.443"></a>
-<span class="sourceLineNo">444</span>  /**<a name="line.444"></a>
-<span class="sourceLineNo">445</span>   * Cache the block with the specified name and buffer.<a name="line.445"></a>
-<span class="sourceLineNo">446</span>   * &lt;p&gt;<a name="line.446"></a>
-<span class="sourceLineNo">447</span>   *<a name="line.447"></a>
-<span class="sourceLineNo">448</span>   * @param cacheKey block's cache key<a name="line.448"></a>
-<span class="sourceLineNo">449</span>   * @param buf      block buffer<a name="line.449"></a>
-<span class="sourceLineNo">450</span>   */<a name="line.450"></a>
-<span class="sourceLineNo">451</span>  @Override<a name="line.451"></a>
-<span class="sourceLineNo">452</span>  public void cacheBlock(BlockCacheKey cacheKey, Cacheable buf) {<a name="line.452"></a>
-<span class="sourceLineNo">453</span>    cacheBlock(cacheKey, buf, false);<a name="line.453"></a>
-<span class="sourceLineNo">454</span>  }<a name="line.454"></a>
-<span class="sourceLineNo">455</span><a name="line.455"></a>
-<span class="sourceLineNo">456</span>  /**<a name="line.456"></a>
-<span class="sourceLineNo">457</span>   * Helper function that updates the local size counter and also updates any<a name="line.457"></a>
-<span class="sourceLineNo">458</span>   * per-cf or per-blocktype metrics it can discern from given<a name="line.458"></a>
-<span class="sourceLineNo">459</span>   * {@link LruCachedBlock}<a name="line.459"></a>
-<span class="sourceLineNo">460</span>   */<a name="line.460"></a>
-<span class="sourceLineNo">461</span>  private long updateSizeMetrics(LruCachedBlock cb, boolean evict) {<a name="line.461"></a>
-<span class="sourceLineNo">462</span>    long heapsize = cb.heapSize();<a name="line.462"></a>
-<span class="sourceLineNo">463</span>    BlockType bt = cb.getBuffer().getBlockType();<a name="line.463"></a>
-<span class="sourceLineNo">464</span>    if (evict) {<a name="line.464"></a>
-<span class="sourceLineNo">465</span>      heapsize *= -1;<a name="line.465"></a>
-<span class="sourceLineNo">466</span>    }<a name="line.466"></a>
-<span class="sourceLineNo">467</span>    if (bt != null &amp;&amp; bt.isData()) {<a name="line.467"></a>
-<span class="sourceLineNo">468</span>       dataBlockSize.add(heapsize);<a name="line.468"></a>
-<span class="sourceLineNo">469</span>    }<a name="line.469"></a>
-<span class="sourceLineNo">470</span>    return size.addAndGet(heapsize);<a name="line.470"></a>
-<span class="sourceLineNo">471</span>  }<a name="line.471"></a>
-<span class="sourceLineNo">472</span><a name="line.472"></a>
-<span class="sourceLineNo">473</span>  /**<a name="line.473"></a>
-<span class="sourceLineNo">474</span>   * Get the buffer of the block with the specified name.<a name="line.474"></a>
-<span class="sourceLineNo">475</span>   *<a name="line.475"></a>
-<span class="sourceLineNo">476</span>   * @param cacheKey           block's cache key<a name="line.476"></a>
-<span class="sourceLineNo">477</span>   * @param caching            true if the caller caches blocks on cache misses<a name="line.477"></a>
-<span class="sourceLineNo">478</span>   * @param repeat             Whether this is a repeat lookup for the same block<a name="line.478"></a>
-<span class="sourceLineNo">479</span>   *                           (used to avoid double counting cache misses when doing double-check<a name="line.479"></a>
-<span class="sourceLineNo">480</span>   *                           locking)<a name="line.480"></a>
-<span class="sourceLineNo">481</span>   * @param updateCacheMetrics Whether to update cache metrics or not<a name="line.481"></a>
-<span class="sourceLineNo">482</span>   *<a name="line.482"></a>
-<span class="sourceLineNo">483</span>   * @return buffer of specified cache key, or null if not in cache<a name="line.483"></a>
-<span class="sourceLineNo">484</span>   */<a name="line.484"></a>
-<span class="sourceLineNo">485</span>  @Override<a name="line.485"></a>
-<span class="sourceLineNo">486</span>  public Cacheable getBlock(BlockCacheKey cacheKey, boolean caching, boolean repeat,<a name="line.486"></a>
-<span class="sourceLineNo">487</span>      boolean updateCacheMetrics) {<a name="line.487"></a>
-<span class="sourceLineNo">488</span>    LruCachedBlock cb = map.get(cacheKey);<a name="line.488"></a>
-<span class="sourceLineNo">489</span>    if (cb == null) {<a name="line.489"></a>
-<span class="sourceLineNo">490</span>      if (!repeat &amp;&amp; updateCacheMetrics) {<a name="line.490"></a>
-<span class="sourceLineNo">491</span>        stats.miss(caching, cacheKey.isPrimary(), cacheKey.getBlockType());<a name="line.491"></a>
-<span class="sourceLineNo">492</span>      }<a name="line.492"></a>
-<span class="sourceLineNo">493</span>      // If there is another block cache then try and read there.<a name="line.493"></a>
-<span class="sourceLineNo">494</span>      // However if this is a retry ( second time in double checked locking )<a name="line.494"></a>
-<span class="sourceLineNo">495</span>      // And it's already a miss then the l2 will also be a miss.<a name="line.495"></a>
-<span class="sourceLineNo">496</span>      if (victimHandler != null &amp;&amp; !repeat) {<a name="line.496"></a>
-<span class="sourceLineNo">497</span>        Cacheable result = victimHandler.getBlock(cacheKey, caching, repeat, updateCacheMetrics);<a name="line.497"></a>
-<span class="sourceLineNo">498</span><a name="line.498"></a>
-<span class="sourceLineNo">499</span>        // Promote this to L1.<a name="line.499"></a>
-<span class="sourceLineNo">500</span>        if (result != null &amp;&amp; caching) {<a name="line.500"></a>
-<span class="sourceLineNo">501</span>          if (result instanceof HFileBlock &amp;&amp; ((HFileBlock) result).usesSharedMemory()) {<a name="line.501"></a>
-<span class="sourceLineNo">502</span>            result = ((HFileBlock) result).deepClone();<a name="line.502"></a>
-<span class="sourceLineNo">503</span>          }<a name="line.503"></a>
-<span class="sourceLineNo">504</span>          cacheBlock(cacheKey, result, /* inMemory = */ false);<a name="line.504"></a>
-<span class="sourceLineNo">505</span>        }<a name="line.505"></a>
-<span class="sourceLineNo">506</span>        return result;<a name="line.506"></a>
-<span class="sourceLineNo">507</span>      }<a name="line.507"></a>
-<span class="sourceLineNo">508</span>      return null;<a name="line.508"></a>
-<span class="sourceLineNo">509</span>    }<a name="line.509"></a>
-<span class="sourceLineNo">510</span>    if (updateCacheMetrics) stats.hit(caching, cacheKey.isPrimary(), cacheKey.getBlockType());<a name="line.510"></a>
-<span class="sourceLineNo">511</span>    cb.access(count.incrementAndGet());<a name="line.511"></a>
-<span class="sourceLineNo">512</span>    return cb.getBuffer();<a name="line.512"></a>
-<span class="sourceLineNo">513</span>  }<a name="line.513"></a>
-<span class="sourceLineNo">514</span><a name="line.514"></a>
-<span class="sourceLineNo">515</span>  /**<a name="line.515"></a>
-<span class="sourceLineNo">516</span>   * Whether the cache contains block with specified cacheKey<a name="line.516"></a>
-<span class="sourceLineNo">517</span>   *<a name="line.517"></a>
-<span class="sourceLineNo">518</span>   * @return true if contains the block<a name="line.518"></a>
-<span class="sourceLineNo">519</span>   */<a name="line.519"></a>
-<span class="sourceLineNo">520</span>  public boolean containsBlock(BlockCacheKey cacheKey) {<a name="line.520"></a>
-<span class="sourceLineNo">521</span>    return map.containsKey(cacheKey);<a name="line.521"></a>
-<span class="sourceLineNo">522</span>  }<a name="line.522"></a>
-<span class="sourceLineNo">523</span><a name="line.523"></a>
-<span class="sourceLineNo">524</span>  @Override<a name="line.524"></a>
-<span class="sourceLineNo">525</span>  public boolean evictBlock(BlockCacheKey cacheKey) {<a name="line.525"></a>
-<span class="sourceLineNo">526</span>    LruCachedBlock cb = map.get(cacheKey);<a name="line.526"></a>
-<span class="sourceLineNo">527</span>    return cb != null &amp;&amp; evictBlock(cb, false) &gt; 0;<a name="line.527"></a>
-<span class="sourceLineNo">528</span>  }<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>   * Evicts all blocks for a specific HFile. This is an<a name="line.531"></a>
-<span class="sourceLineNo">532</span>   * expensive operation implemented as a linear-time search through all blocks<a name="line.532"></a>
-<span class="sourceLineNo">533</span>   * in the cache. Ideally this should be a search in a log-access-time map.<a name="line.533"></a>
-<span class="sourceLineNo">534</span>   *<a name="line.534"></a>
-<span class="sourceLineNo">535</span>   * &lt;p&gt;<a name="line.535"></a>
-<span class="sourceLineNo">536</span>   * This is used for evict-on-close to remove all blocks of a specific HFile.<a name="line.536"></a>
-<span class="sourceLineNo">537</span>   *<a name="line.537"></a>
-<span class="sourceLineNo">538</span>   * @return the number of blocks evicted<a name="line.538"></a>
-<span class="sourceLineNo">539</span>   */<a name="line.539"></a>
-<span class="sourceLineNo">540</span>  @Override<a name="line.540"></a>
-<span class="sourceLineNo">541</span>  public int evictBlocksByHfileName(String hfileName) {<a name="line.541"></a>
-<span class="sourceLineNo">542</span>    int numEvicted = 0;<a name="line.542"></a>
-<span class="sourceLineNo">543</span>    for (BlockCacheKey key : map.keySet()) {<a name="line.543"></a>
-<span class="sourceLineNo">544</span>      if (key.getHfileName().equals(hfileName)) {<a name="line.544"></a>
-<span class="sourceLineNo">545</span>        if (evictBlock(key))<a name="line.545"></a>
-<span class="sourceLineNo">546</span>          ++numEvicted;<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>    if (victimHandler != null) {<a name="line.549"></a>
-<span class="sourceLineNo">550</span>      numEvicted += victimHandler.evictBlocksByHfileName(hfileName);<a name="line.550"></a>
-<span class="sourceLineNo">551</span>    }<a name="line.551"></a>
-<span class="sourceLineNo">552</span>    return numEvicted;<a name="line.552"></a>
-<span class="sourceLineNo">553</span>  }<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>   * Evict the block, and it will be cached by the victim handler if exists &amp;amp;&amp;amp;<a name="line.556"></a>
-<span class="sourceLineNo">557</span>   * block may be read again later<a name="line.557"></a>
-<span class="sourceLineNo">558</span>   *<a name="line.558"></a>
-<span class="sourceLineNo">559</span>   * @param evictedByEvictionProcess true if the given block is evicted by<a name="line.559"></a>
-<span class="sourceLineNo">560</span>   *          EvictionThread<a name="line.560"></a>
-<span class="sourceLineNo">561</span>   * @return the heap size of evicted block<a name="line.561"></a>
-<span class="sourceLineNo">562</span>   */<a name="line.562"></a>
-<span class="sourceLineNo">563</span>  protected long evictBlock(LruCachedBlock block, boolean evictedByEvictionProcess) {<a name="line.563"></a>
-<span class="sourceLineNo">564</span>    boolean found = map.remove(block.getCacheKey()) != null;<a name="line.564"></a>
-<span class="sourceLineNo">565</span>    if (!found) {<a name="line.565"></a>
-<span class="sourceLineNo">566</span>      return 0;<a name="line.566"></a>
-<span class="sourceLineNo">567</span>    }<a name="line.567"></a>
-<span class="sourceLineNo">568</span>    updateSizeMetrics(block, true);<a name="line.568"></a>
-<span class="sourceLineNo">569</span>    long val = elements.decrementAndGet();<a name="line.569"></a>
-<span class="sourceLineNo">570</span>    if (LOG.isTraceEnabled()) {<a name="line.570"></a>
-<span class="sourceLineNo">571</span>      long size = map.size();<a name="line.571"></a>
-<span class="sourceLineNo">572</span>      assertCounterSanity(size, val);<a name="line.572"></a>
-<span class="sourceLineNo">573</span>    }<a name="line.573"></a>
-<span class="sourceLineNo">574</span>    if (block.getBuffer().getBlockType().isData()) {<a name="line.574"></a>
-<span class="sourceLineNo">575</span>       dataBlockElements.decrement();<a name="line.575"></a>
-<span class="sourceLineNo">576</span>    }<a name="line.576"></a>
-<span class="sourceLineNo">577</span>    if (evictedByEvictionProcess) {<a name="line.577"></a>
-<span class="sourceLineNo">578</span>      // When the eviction of the block happened because of invalidation of HFiles, no need to<a name="line.578"></a>
-<span class="sourceLineNo">579</span>      // update the stats counter.<a name="line.579"></a>
-<span class="sourceLineNo">580</span>      stats.evicted(block.getCachedTime(), block.getCacheKey().isPrimary());<a name="line.580"></a>
-<span class="sourceLineNo">581</span>      if (victimHandler != null) {<a name="line.581"></a>
-<span class="sourceLineNo">582</span>        victimHandler.cacheBlock(block.getCacheKey(), block.getBuffer());<a name="line.582"></a>
-<span class="sourceLineNo">583</span>      }<a name="line.583"></a>
-<span class="sourceLineNo">584</span>    }<a name="line.584"></a>
-<span class="sourceLineNo">585</span>    return block.heapSize();<a name="line.585"></a>
-<span class="sourceLineNo">586</span>  }<a name="line.586"></a>
-<span class="sourceLineNo">587</span><a name="line.587"></a>
-<span class="sourceLineNo">588</span>  /**<a name="line.588"></a>
-<span class="sourceLineNo">589</span>   * Multi-threaded call to run the eviction process.<a name="line.589"></a>
-<span class="sourceLineNo">590</span>   */<a name="line.590"></a>
-<span class="sourceLineNo">591</span>  private void runEviction() {<a name="line.591"></a>
-<span class="sourceLineNo">592</span>    if (evictionThread == null) {<a name="line.592"></a>
-<span class="sourceLineNo">593</span>      evict();<a name="line.593"></a>
-<span class="sourceLineNo">594</span>    } else {<a name="line.594"></a>
-<span class="sourceLineNo">595</span>      evictionThread.evict();<a name="line.595"></a>
-<span class="sourceLineNo">596</span>    }<a name="line.596"></a>
-<span class="sourceLineNo">597</span>  }<a name="line.597"></a>
-<span class="sourceLineNo">598</span><a name="line.598"></a>
-<span class="sourceLineNo">599</span>  @VisibleForTesting<a name="line.599"></a>
-<span class="sourceLineNo">600</span>  boolean isEvictionInProgress() {<a name="line.600"></a>
-<span class="sourceLineNo">601</span>    return evictionInProgress;<a name="line.601"></a>
+<span class="sourceLineNo">383</span>      int comparison = BlockCacheUtil.validateBlockAddition(cb.getBuffer(), buf, cacheKey);<a name="line.383"></a>
+<span class="sourceLineNo">384</span>      if (comparison != 0) {<a name="line.384"></a>
+<span class="sourceLineNo">385</span>        if (comparison &lt; 0) {<a name="line.385"></a>
+<span class="sourceLineNo">386</span>          LOG.warn("Cached block contents differ by nextBlockOnDiskSize. Keeping cached block.");<a name="line.386"></a>
+<span class="sourceLineNo">387</span>          return;<a name="line.387"></a>
+<span class="sourceLineNo">388</span>        } else {<a name="line.388"></a>
+<span class="sourceLineNo">389</span>          LOG.warn("Cached block contents differ by nextBlockOnDiskSize. Caching new block.");<a name="line.389"></a>
+<span class="sourceLineNo">390</span>        }<a name="line.390"></a>
+<span class="sourceLineNo">391</span>      } else {<a name="line.391"></a>
+<span class="sourceLineNo">392</span>        String msg = "Cached an already cached block: " + cacheKey + " cb:" + cb.getCacheKey();<a name="line.392"></a>
+<span class="sourceLineNo">393</span>        msg += ". This is harmless and can happen in rare cases (see HBASE-8547)";<a name="line.393"></a>
+<span class="sourceLineNo">394</span>        LOG.warn(msg);<a name="line.394"></a>
+<span class="sourceLineNo">395</span>        return;<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>    long currentSize = size.get();<a name="line.398"></a>
+<span class="sourceLineNo">399</span>    long currentAcceptableSize = acceptableSize();<a name="line.399"></a>
+<span class="sourceLineNo">400</span>    long hardLimitSize = (long) (hardCapacityLimitFactor * currentAcceptableSize);<a name="line.400"></a>
+<span class="sourceLineNo">401</span>    if (currentSize &gt;= hardLimitSize) {<a name="line.401"></a>
+<span class="sourceLineNo">402</span>      stats.failInsert();<a name="line.402"></a>
+<span class="sourceLineNo">403</span>      if (LOG.isTraceEnabled()) {<a name="line.403"></a>
+<span class="sourceLineNo">404</span>        LOG.trace("LruBlockCache current size " + StringUtils.byteDesc(currentSize)<a name="line.404"></a>
+<span class="sourceLineNo">405</span>          + " has exceeded acceptable size " + StringUtils.byteDesc(currentAcceptableSize) + "."<a name="line.405"></a>
+<span class="sourceLineNo">406</span>          + " The hard limit size is " + StringUtils.byteDesc(hardLimitSize)<a name="line.406"></a>
+<span class="sourceLineNo">407</span>          + ", failed to put cacheKey:" + cacheKey + " into LruBlockCache.");<a name="line.407"></a>
+<span class="sourceLineNo">408</span>      }<a name="line.408"></a>
+<span class="sourceLineNo">409</span>      if (!evictionInProgress) {<a name="line.409"></a>
+<span class="sourceLineNo">410</span>        runEviction();<a name="line.410"></a>
+<span class="sourceLineNo">411</span>      }<a name="line.411"></a>
+<span class="sourceLineNo">412</span>      return;<a name="line.412"></a>
+<span class="sourceLineNo">413</span>    }<a name="line.413"></a>
+<span class="sourceLineNo">414</span>    cb = new LruCachedBlock(cacheKey, buf, count.incrementAndGet(), inMemory);<a name="line.414"></a>
+<span class="sourceLineNo">415</span>    long newSize = updateSizeMetrics(cb, false);<a name="line.415"></a>
+<span class="sourceLineNo">416</span>    map.put(cacheKey, cb);<a name="line.416"></a>
+<span class="sourceLineNo">417</span>    long val = elements.incrementAndGet();<a name="line.417"></a>
+<span class="sourceLineNo">418</span>    if (buf.getBlockType().isData()) {<a name="line.418"></a>
+<span class="sourceLineNo">419</span>       dataBlockElements.increment();<a name="line.419"></a>
+<span class="sourceLineNo">420</span>    }<a name="line.420"></a>
+<span class="sourceLineNo">421</span>    if (LOG.isTraceEnabled()) {<a name="line.421"></a>
+<span class="sourceLineNo">422</span>      long size = map.size();<a name="line.422"></a>
+<span class="sourceLineNo">423</span>      assertCounterSanity(size, val);<a name="line.423"></a>
+<span class="sourceLineNo">424</span>    }<a name="line.424"></a>
+<span class="sourceLineNo">425</span>    if (newSize &gt; currentAcceptableSize &amp;&amp; !evictionInProgress) {<a name="line.425"></a>
+<span class="sourceLineNo">426</span>      runEviction();<a name="line.426"></a>
+<span class="sourceLineNo">427</span>    }<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>   * Sanity-checking for parity between actual block cache content and metrics.<a name="line.431"></a>
+<span class="sourceLineNo">432</span>   * Intended only for use with TRACE level logging and -ea JVM.<a name="line.432"></a>
+<span class="sourceLineNo">433</span>   */<a name="line.433"></a>
+<span class="sourceLineNo">434</span>  private static void assertCounterSanity(long mapSize, long counterVal) {<a name="line.434"></a>
+<span class="sourceLineNo">435</span>    if (counterVal &lt; 0) {<a name="line.435"></a>
+<span class="sourceLineNo">436</span>      LOG.trace("counterVal overflow. Assertions unreliable. counterVal=" + counterVal +<a name="line.436"></a>
+<span class="sourceLineNo">437</span>        ", mapSize=" + mapSize);<a name="line.437"></a>
+<span class="sourceLineNo">438</span>      return;<a name="line.438"></a>
+<span class="sourceLineNo">439</span>    }<a name="line.439"></a>
+<span class="sourceLineNo">440</span>    if (mapSize &lt; Integer.MAX_VALUE) {<a name="line.440"></a>
+<span class="sourceLineNo">441</span>      double pct_diff = Math.abs((((double) counterVal) / ((double) mapSize)) - 1.);<a name="line.441"></a>
+<span class="sourceLineNo">442</span>      if (pct_diff &gt; 0.05) {<a name="line.442"></a>
+<span class="sourceLineNo">443</span>        LOG.trace("delta between reported and actual size &gt; 5%. counterVal=" + counterVal +<a name="line.443"></a>
+<span class="sourceLineNo">444</span>          ", mapSize=" + mapSize);<a name="line.444"></a>
+<span class="sourceLineNo">445</span>      }<a name="line.445"></a>
+<span class="sourceLineNo">446</span>    }<a name="line.446"></a>
+<span class="sourceLineNo">447</span>  }<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>   * Cache the block with the specified name and buffer.<a name="line.450"></a>
+<span class="sourceLineNo">451</span>   * &lt;p&gt;<a name="line.451"></a>
+<span class="sourceLineNo">452</span>   *<a name="line.452"></a>
+<span class="sourceLineNo">453</span>   * @param cacheKey block's cache key<a name="line.453"></a>
+<span class="sourceLineNo">454</span>   * @param buf      block buffer<a name="line.454"></a>
+<span class="sourceLineNo">455</span>   */<a name="line.455"></a>
+<span class="sourceLineNo">456</span>  @Override<a name="line.456"></a>
+<span class="sourceLineNo">457</span>  public void cacheBlock(BlockCacheKey cacheKey, Cacheable buf) {<a name="line.457"></a>
+<span class="sourceLineNo">458</span>    cacheBlock(cacheKey, buf, false);<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>  /**<a name="line.461"></a>
+<span class="sourceLineNo">462</span>   * Helper function that updates the local size counter and also updates any<a name="line.462"></a>
+<span class="sourceLineNo">463</span>   * per-cf or per-blocktype metrics it can discern from given<a name="line.463"></a>
+<span class="sourceLineNo">464</span>   * {@link LruCachedBlock}<a name="line.464"></a>
+<span class="sourceLineNo">465</span>   */<a name="line.465"></a>
+<span class="sourceLineNo">466</span>  private long updateSizeMetrics(LruCachedBlock cb, boolean evict) {<a name="line.466"></a>
+<span class="sourceLineNo">467</span>    long heapsize = cb.heapSize();<a name="line.467"></a>
+<span class="sourceLineNo">468</span>    BlockType bt = cb.getBuffer().getBlockType();<a name="line.468"></a>
+<span class="sourceLineNo">469</span>    if (evict) {<a name="line.469"></a>
+<span class="sourceLineNo">470</span>      heapsize *= -1;<a name="line.470"></a>
+<span class="sourceLineNo">471</span>    }<a name="line.471"></a>
+<span class="sourceLineNo">472</span>    if (bt != null &amp;&amp; bt.isData()) {<a name="line.472"></a>
+<span class="sourceLineNo">473</span>       dataBlockSize.add(heapsize);<a name="line.473"></a>
+<span class="sourceLineNo">474</span>    }<a name="line.474"></a>
+<span class="sourceLineNo">475</span>    return size.addAndGet(heapsize);<a name="line.475"></a>
+<span class="sourceLineNo">476</span>  }<a name="line.476"></a>
+<span class="sourceLineNo">477</span><a name="line.477"></a>
+<span class="sourceLineNo">478</span>  /**<a name="line.478"></a>
+<span class="sourceLineNo">479</span>   * Get the buffer of the block with the specified name.<a name="line.479"></a>
+<span class="sourceLineNo">480</span>   *<a name="line.480"></a>
+<span class="sourceLineNo">481</span>   * @param cacheKey           block's cache key<a name="line.481"></a>
+<span class="sourceLineNo">482</span>   * @param caching            true if the caller caches blocks on cache misses<a name="line.482"></a>
+<span class="sourceLineNo">483</span>   * @param repeat             Whether this is a repeat lookup for the same block<a name="line.483"></a>
+<span class="sourceLineNo">484</span>   *                           (used to avoid double counting cache misses when doing double-check<a name="line.484"></a>
+<span class="sourceLineNo">485</span>   *                           locking)<a name="line.485"></a>
+<span class="sourceLineNo">486</span>   * @param updateCacheMetrics Whether to update cache metrics or not<a name="line.486"></a>
+<span class="sourceLineNo">487</span>   *<a name="line.487"></a>
+<span class="sourceLineNo">488</span>   * @return buffer of specified cache key, or null if not in cache<a name="line.488"></a>
+<span class="sourceLineNo">489</span>   */<a name="line.489"></a>
+<span class="sourceLineNo">490</span>  @Override<a name="line.490"></a>
+<span class="sourceLineNo">491</span>  public Cacheable getBlock(BlockCacheKey cacheKey, boolean caching, boolean repeat,<a name="line.491"></a>
+<span class="sourceLineNo">492</span>      boolean updateCacheMetrics) {<a name="line.492"></a>
+<span class="sourceLineNo">493</span>    LruCachedBlock cb = map.get(cacheKey);<a name="line.493"></a>
+<span class="sourceLineNo">494</span>    if (cb == null) {<a name="line.494"></a>
+<span class="sourceLineNo">495</span>      if (!repeat &amp;&amp; updateCacheMetrics) {<a name="line.495"></a>
+<span class="sourceLineNo">496</span>        stats.miss(caching, cacheKey.isPrimary(), cacheKey.getBlockType());<a name="line.496"></a>
+<span class="sourceLineNo">497</span>      }<a name="line.497"></a>
+<span class="sourceLineNo">498</span>      // If there is another block cache then try and read there.<a name="line.498"></a>
+<span class="sourceLineNo">499</span>      // However if this is a retry ( second time in double checked locking )<a name="line.499"></a>
+<span class="sourceLineNo">500</span>      // And it's already a miss then the l2 will also be a miss.<a name="line.500"></a>
+<span class="sourceLineNo">501</span>      if (victimHandler != null &amp;&amp; !repeat) {<a name="line.501"></a>
+<span class="sourceLineNo">502</span>        Cacheable result = victimHandler.getBlock(cacheKey, caching, repeat, updateCacheMetrics);<a name="line.502"></a>
+<span class="sourceLineNo">503</span><a name="line.503"></a>
+<span class="sourceLineNo">504</span>        // Promote this to L1.<a name="line.504"></a>
+<span class="sourceLineNo">505</span>        if (result != null &amp;&amp; caching) {<a name="line.505"></a>
+<span class="sourceLineNo">506</span>          if (result instanceof HFileBlock &amp;&amp; ((HFileBlock) result).usesSharedMemory()) {<a name="line.506"></a>
+<span class="sourceLineNo">507</span>            result = ((HFileBlock) result).deepClone();<a name="line.507"></a>
+<span class="sourceLineNo">508</span>          }<a name="line.508"></a>
+<span class="sourceLineNo">509</span>          cacheBlock(cacheKey, result, /* inMemory = */ false);<a name="line.509"></a>
+<span class="sourceLineNo">510</span>        }<a name="line.510"></a>
+<span class="sourceLineNo">511</span>        return result;<a name="line.511"></a>
+<span class="sourceLineNo">512</span>      }<a name="line.512"></a>
+<span class="sourceLineNo">513</span>      return null;<a name="line.513"></a>
+<span class="sourceLineNo">514</span>    }<a name="line.514"></a>
+<span class="sourceLineNo">515</span>    if (updateCacheMetrics) stats.hit(caching, cacheKey.isPrimary(), cacheKey.getBlockType());<a name="line.515"></a>
+<span class="sourceLineNo">516</span>    cb.access(count.incrementAndGet());<a name="line.516"></a>
+<span class="sourceLineNo">517</span>    return cb.getBuffer();<a name="line.517"></a>
+<span class="sourceLineNo">518</span>  }<a name="line.518"></a>
+<span class="sourceLineNo">519</span><a name="line.519"></a>
+<span class="sourceLineNo">520</span>  /**<a name="line.520"></a>
+<span class="sourceLineNo">521</span>   * Whether the cache contains block with specified cacheKey<a name="line.521"></a>
+<span class="sourceLineNo">522</span>   *<a name="line.522"></a>
+<span class="sourceLineNo">523</span>   * @return true if contains the block<a name="line.523"></a>
+<span class="sourceLineNo">524</span>   */<a name="line.524"></a>
+<span class="sourceLineNo">525</span>  public boolean containsBlock(BlockCacheKey cacheKey) {<a name="line.525"></a>
+<span class="sourceLineNo">526</span>    return map.containsKey(cacheKey);<a name="line.526"></a>
+<span class="sourceLineNo">527</span>  }<a name="line.527"></a>
+<span class="sourceLineNo">528</span><a name="line.528"></a>
+<span class="sourceLineNo">529</span>  @Override<a name="line.529"></a>
+<span class="sourceLineNo">530</span>  public boolean evictBlock(BlockCacheKey cacheKey) {<a name="line.530"></a>
+<span class="sourceLineNo">531</span>    LruCachedBlock cb = map.get(cacheKey);<a name="line.531"></a>
+<span class="sourceLineNo">532</span>    return cb != null &amp;&amp; evictBlock(cb, false) &gt; 0;<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>   * Evicts all blocks for a specific HFile. This is an<a name="line.536"></a>
+<span class="sourceLineNo">537</span>   * expensive operation implemented as a linear-time search through all blocks<a name="line.537"></a>
+<span class="sourceLineNo">538</span>   * in the cache. Ideally this should be a search in a log-access-time map.<a name="line.538"></a>
+<span class="sourceLineNo">539</span>   *<a name="line.539"></a>
+<span class="sourceLineNo">540</span>   * &lt;p&gt;<a name="line.540"></a>
+<span class="sourceLineNo">541</span>   * This is used for evict-on-close to remove all blocks of a specific HFile.<a name="line.541"></a>
+<span class="sourceLineNo">542</span>   *<a name="line.542"></a>
+<span class="sourceLineNo">543</span>   * @return the number of blocks evicted<a name="line.543"></a>
+<span class="sourceLineNo">544</span>   */<a name="line.544"></a>
+<span class="sourceLineNo">545</span>  @Override<a name="line.545"></a>
+<span class="sourceLineNo">546</span>  public int evictBlocksByHfileName(String hfileName) {<a name="line.546"></a>
+<span class="sourceLineNo">547</span>    int numEvicted = 0;<a name="line.547"></a>
+<span class="sourceLineNo">548</span>    for (BlockCacheKey key : map.keySet()) {<a name="line.548"></a>
+<span class="sourceLineNo">549</span>      if (key.getHfileName().equals(hfileName)) {<a name="line.549"></a>
+<span class="sourceLineNo">550</span>        if (evictBlock(key))<a name="line.550"></a>
+<span class="sourceLineNo">551</span>          ++numEvicted;<a name="line.551"></a>
+<span class="sourceLineNo">552</span>      }<a name="line.552"></a>
+<span class="sourceLineNo">553</span>    }<a name="line.553"></a>
+<span class="sourceLineNo">554</span>    if (victimHandler != null) {<a name="line.554"></a>
+<span class="sourceLineNo">555</span>      numEvicted += victimHandler.evictBlocksByHfileName(hfileName);<a name="line.555"></a>
+<span class="sourceLineNo">556</span>    }<a name="line.556"></a>
+<span class="sourceLineNo">557</span>    return numEvicted;<a name="line.557"></a>
+<span class="sourceLineNo">558</span>  }<a name="line.558"></a>
+<span class="sourceLineNo">559</span><a name="line.559"></a>
+<span class="sourceLineNo">560</span>  /**<a name="line.560"></a>
+<span class="sourceLineNo">561</span>   * Evict the block, and it will be cached by the victim handler if exists &amp;amp;&amp;amp;<a name="line.561"></a>
+<span class="sourceLineNo">562</span>   * block may be read again later<a name="line.562"></a>
+<span class="sourceLineNo">563</span>   *<a name="line.563"></a>
+<span class="sourceLineNo">564</span>   * @param evictedByEvictionProcess true if the given block is evicted by<a name="line.564"></a>
+<span class="sourceLineNo">565</span>   *          EvictionThread<a name="line.565"></a>
+<span class="sourceLineNo">566</span>   * @return the heap size of evicted block<a name="line.566"></a>
+<span class="sourceLineNo">567</span>   */<a name="line.567"></a>
+<span class="sourceLineNo">568</span>  protected long evictBlock(LruCachedBlock block, boolean evictedByEvictionProcess) {<a name="line.568"></a>
+<span class="sourceLineNo">569</span>    boolean found = map.remove(block.getCacheKey()) != null;<a name="line.569"></a>
+<span class="sourceLineNo">570</span>    if (!found) {<a name="line.570"></a>
+<span class="sourceLineNo">571</span>      return 0;<a name="line.571"></a>
+<span class="sourceLineNo">572</span>    }<a name="line.572"></a>
+<span class="sourceLineNo">573</span>    updateSizeMetrics(block, true);<a name="line.573"></a>
+<span class="sourceLineNo">574</span>    long val = elements.decrementAndGet();<a name="line.574"></a>
+<span class="sourceLineNo">575</span>    if (LOG.isTraceEnabled()) {<a name="line.575"></a>
+<span class="sourceLineNo">576</span>      long size = map.size();<a name="line.576"></a>
+<span class="sourceLineNo">577</span>      assertCounterSanity(size, val);<a name="line.577"></a>
+<span class="sourceLineNo">578</span>    }<a name="line.578"></a>
+<span class="sourceLineNo">579</span>    if (block.getBuffer().getBlockType().isData()) {<a name="line.579"></a>
+<span class="sourceLineNo">580</span>       dataBlockElements.decrement();<a name="line.580"></a>
+<span class="sourceLineNo">581</span>    }<a name="line.581"></a>
+<span class="sourceLineNo">582</span>    if (evictedByEvictionProcess) {<a name="line.582"></a>
+<span class="sourceLineNo">583</span>      // When the eviction of the block happened because of invalidation of HFiles, no need to<a name="line.583"></a>
+<span class="sourceLineNo">584</span>      // update the stats counter.<a name="line.584"></a>
+<span class="sourceLineNo">585</span>      stats.evicted(block.getCachedTime(), block.getCacheKey().isPrimary());<a name="line.585"></a>
+<span class="sourceLineNo">586</span>      if (victimHandler != null) {<a name="line.586"></a>
+<span class="sourceLineNo">587</span>        victimHandler.cacheBlock(block.getCacheKey(), block.getBuffer());<a name="line.587"></a>
+<span class="sourceLineNo">588</span>      }<a name="line.588"></a>
+<span class="sourceLineNo">589</span>    }<a name="line.589"></a>
+<span class="sourceLineNo">590</span>    return block.heapSize();<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>   * Multi-threaded call to run the eviction process.<a name="line.594"></a>
+<span class="sourceLineNo">595</span>   */<a name="line.595"></a>
+<span class="sourceLineNo">596</span>  private void runEviction() {<a name="line.596"></a>
+<span class="sourceLineNo">597</span>    if (evictionThread == null) {<a name="line.597"></a>
+<span class="sourceLineNo">598</span>      evict();<a name="line.598"></a>
+<span class="sourceLineNo">599</span>    } else {<a name="line.599"></a>
+<span class="sourceLineNo">600</span>      evictionThread.evict();<a name="line.600"></a>
+<span class="sourceLineNo">601</span>    }<a name="line.601"></a>
 <span class="sourceLineNo">602</span>  }<a name="line.602"></a>
 <span class="sourceLineNo">603</span><a name="line.603"></a>
 <span class="sourceLineNo">604</span>  @VisibleForTesting<a name="line.604"></a>
-<span class="sourceLineNo">605</span>  long getOverhead() {<a name="line.605"></a>
-<span class="sourceLineNo">606</span>    return overhead;<a name="line.606"></a>
+<span class="sourceLineNo">605</span>  boolean isEvictionInProgress() {<a name="line.605"></a>
+<span class="sourceLineNo">606</span>    return evictionInProgress;<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>   * Eviction method.<a name="line.610"></a>
-<span class="sourceLineNo">611</span>   */<a name="line.611"></a>
-<span class="sourceLineNo">612</span>  void evict() {<a name="line.612"></a>
+<span class="sourceLineNo">609</span>  @VisibleForTesting<a name="line.609"></a>
+<span class="sourceLineNo">610</span>  long getOverhead() {<a name="line.610"></a>
+<span class="sourceLineNo">611</span>    return overhead;<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>    // Ensure only one eviction at a time<a name="line.614"></a>
-<span class="sourceLineNo">615</span>    if(!evictionLock.tryLock()) return;<a name="line.615"></a>
-<span class="sourceLineNo">616</span><a name="line.616"></a>
-<span class="sourceLineNo">617</span>    try {<a name="line.617"></a>
-<span class="sourceLineNo">618</span>      evictionInProgress = true;<a name="line.618"></a>
-<span class="sourceLineNo">619</span>      long currentSize = this.size.get();<a name="line.619"></a>
-<span class="sourceLineNo">620</span>      long bytesToFree = currentSize - minSize();<a name="line.620"></a>
+<span class="sourceLineNo">614</span>  /**<a name="line.614"></a>
+<span class="sourceLineNo">615</span>   * Eviction method.<a name="line.615"></a>
+<span class="sourceLineNo">616</span>   */<a name="line.616"></a>
+<span class="sourceLineNo">617</span>  void evict() {<a name="line.617"></a>
+<span class="sourceLineNo">618</span><a name="line.618"></a>
+<span class="sourceLineNo">619</span>    // Ensure only one eviction at a time<a name="line.619"></a>
+<span class="sourceLineNo">620</span>    if(!evictionLock.tryLock()) return;<a name="line.620"></a>
 <span class="sourceLineNo">621</span><a name="line.621"></a>
-<span class="sourceLineNo">622</span>      if (LOG.isTraceEnabled()) {<a name="line.622"></a>
-<span class="sourceLineNo">623</span>        LOG.trace("Block cache LRU eviction started; Attempting to free " +<a name="line.623"></a>
-<span class="sourceLineNo">624</span>          StringUtils.byteDesc(bytesToFree) + " of total=" +<a name="line.624"></a>
-<span class="sourceLineNo">625</span>          StringUtils.byteDesc(currentSize));<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>      if (bytesToFree &lt;= 0) return;<a name="line.628"></a>
-<span class="sourceLineNo">629</span><a name="line.629"></a>
-<span class="sourceLineNo">630</span>      // Instantiate priority buckets<a name="line.630"></a>
-<span class="sourceLineNo">631</span>      BlockBucket bucketSingle = new BlockBucket("single", bytesToFree, blockSize, singleSize());<a name="line.631"></a>
-<span class="sourceLineNo">632</span>      BlockBucket bucketMulti = new BlockBucket("multi", bytesToFree, blockSize, multiSize());<a name="line.632"></a>
-<span class="sourceLineNo">633</span>      BlockBucket bucketMemory = new BlockBucket("memory", bytesToFree, blockSize, memorySize());<a name="line.633"></a>
+<span class="sourceLineNo">622</span>    try {<a name="line.622"></a>
+<span class="sourceLineNo">623</span>      evictionInProgress = true;<a name="line.623"></a>
+<span class="sourceLineNo">624</span>      long currentSize = this.size.get();<a name="line.624"></a>
+<span class="sourceLineNo">625</span>      long bytesToFree = currentSize - minSize();<a name="line.625"></a>
+<span class="sourceLineNo">626</span><a name="line.626"></a>
+<span class="sourceLineNo">627</span>      if (LOG.isTraceEnabled()) {<a name="line.627"></a>
+<span class="sourceLineNo">628</span>        LOG.trace("Block cache LRU eviction started; Attempting to free " +<a name="line.628"></a>
+<span class="sourceLineNo">629</span>          StringUtils.byteDesc(bytesToFree) + " of total=" +<a name="line.629"></a>
+<span class="sourceLineNo">630</span>          StringUtils.byteDesc(currentSize));<a name="line.630"></a>
+<span class="sourceLineNo">631</span>      }<a name="line.631"></a>
+<span class="sourceLineNo">632</span><a name="line.632"></a>
+<span class="sourceLineNo">633</span>      if (bytesToFree &lt;= 0) return;<a name="line.633"></a>
 <span class="sourceLineNo">634</span><a name="line.634"></a>
-<span class="sourceLineNo">635</span>      // Scan entire map putting into appropriate buckets<a name="line.635"></a>
-<span class="sourceLineNo">636</span>      for (LruCachedBlock cachedBlock : map.values()) {<a name="line.636"></a>
-<span class="sourceLineNo">637</span>        switch (cachedBlock.getPriority()) {<a name="line.637"></a>
-<span class="sourceLineNo">638</span>          case SINGLE: {<a name="line.638"></a>
-<span class="sourceLineNo">639</span>            bucketSingle.add(cachedBlock);<a name="line.639"></a>
-<span class="sourceLineNo">640</span>            break;<a name="line.640"></a>
-<span class="sourceLineNo">641</span>          }<a name="line.641"></a>
-<span class="sourceLineNo">642</span>          case MULTI: {<a name="line.642"></a>
-<span class="sourceLineNo">643</span>            bucketMulti.add(cachedBlock);<a name="line.643"></a>
-<span class="sourceLineNo">644</span>            break;<a name="line.644"></a>
-<span class="sourceLineNo">645</span>          }<a name="line.645"></a>
-<span class="sourceLineNo">646</span>          case MEMORY: {<a name="line.646"></a>
-<span class="sourceLineNo">647</span>            bucketMemory.add(cachedBlock);<a name="line.647"></a>
-<span class="sourceLineNo">648</span>            break;<a name="line.648"></a>
-<span class="sourceLineNo">649</span>          }<a name="line.649"></a>
-<span class="sourceLineNo">650</span>        }<a name="line.650"></a>
-<span class="sourceLineNo">651</span>      }<a name="line.651"></a>
-<span class="sourceLineNo">652</span><a name="line.652"></a>
-<span class="sourceLineNo">653</span>      long bytesFreed = 0;<a name="line.653"></a>
-<span class="sourceLineNo">654</span>      if (forceInMemory || memoryFactor &gt; 0.999f) {<a name="line.654"></a>
-<span class="sourceLineNo">655</span>        long s = bucketSingle.totalSize();<a name="line.655"></a>
-<span class="sourceLineNo">656</span>        long m = bucketMulti.totalSize();<a name="line.656"></a>
-<span class="sourceLineNo">657</span>        if (bytesToFree &gt; (s + m)) {<a name="line.657"></a>
-<span class="sourceLineNo">658</span>          // this means we need to evict blocks in memory bucket to make room,<a name="line.658"></a>
-<span class="sourceLineNo">659</span>          // so the single and multi buckets will be emptied<a name="line.659"></a>
-<span class="sourceLineNo">660</span>          bytesFreed = bucketSingle.free(s);<a name="line.660"></a>
-<span class="sourceLineNo">661</span>          bytesFreed += bucketMulti.free(m);<a name="line.661"></a>
-<span class="sourceLineNo">662</span>          if (LOG.isTraceEnabled()) {<a name="line.662"></a>
-<span class="sourceLineNo">663</span>            LOG.trace("freed " + StringUtils.byteDesc(bytesFreed) +<a name="line.663"></a>
-<span class="sourceLineNo">664</span>              " from single and multi buckets");<a name="line.664"></a>
-<span class="sourceLineNo">665</span>          }<a name="line.665"></a>
-<span class="sourceLineNo">666</span>          bytesFreed += bucketMemory.free(bytesToFree - bytesFreed);<a name="line.666"></a>
+<span class="sourceLineNo">635</span>      // Instantiate priority buckets<a name="line.635"></a>
+<span class="sourceLineNo">636</span>      BlockBucket bucketSingle = new BlockBucket("single", bytesToFree, blockSize, singleSize());<a name="line.636"></a>
+<span class="sourceLineNo">637</span>      BlockBucket bucketMulti = new BlockBucket("multi", bytesToFree, blockSize, multiSize());<a name="line.637"></a>
+<span class="sourceLineNo">638</span>      BlockBucket bucketMemory = new BlockBucket("memory", bytesToFree, blockSize, memorySize());<a name="line.638"></a>
+<span class="sourceLineNo">639</span><a name="line.639"></a>
+<span class="sourceLineNo">640</span>      // Scan entire map putting into appropriate buckets<a name="line.640"></a>
+<span class="sourceLineNo">641</span>      for (LruCachedBlock cachedBlock : map.values()) {<a name="line.641"></a>
+<span class="sourceLineNo">642</span>        switch (cachedBlock.getPriority()) {<a name="line.642"></a>
+<span class="sourceLineNo">643</span>          case SINGLE: {<a name="line.643"></a>
+<span class="sourceLineNo">644</span>            bucketSingle.add(cachedBlock);<a name="line.644"></a>
+<span class="sourceLineNo">645</span>            break;<a name="line.645"></a>
+<span class="sourceLineNo">646</span>          }<a name="line.646"></a>
+<span class="sourceLineNo">647</span>          case MULTI: {<a name="line.647"></a>
+<span class="sourceLineNo">648</span>            bucketMulti.add(cachedBlock);<a name="line.648"></a>
+<span class="sourceLineNo">649</span>            break;<a name="line.649"></a>
+<span class="sourceLineNo">650</span>          }<a name="line.650"></a>
+<span class="sourceLineNo">651</span>          case MEMORY: {<a name="line.651"></a>
+<span class="sourceLineNo">652</span>            bucketMemory.add(cachedBlock);<a name="line.652"></a>
+<span class="sourceLineNo">653</span>            break;<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>      }<a name="line.656"></a>
+<span class="sourceLineNo">657</span><a name="line.657"></a>
+<span class="sourceLineNo">658</span>      long bytesFreed = 0;<a name="line.658"></a>
+<span class="sourceLineNo">659</span>      if (forceInMemory || memoryFactor &gt; 0.999f) {<a name="line.659"></a>
+<span class="sourceLineNo">660</span>        long s = bucketSingle.totalSize();<a name="line.660"></a>
+<span class="sourceLineNo">661</span>        long m = bucketMulti.totalSize();<a name="line.661"></a>
+<span class="sourceLineNo">662</span>        if (bytesToFree &gt; (s + m)) {<a name="line.662"></a>
+<span class="sourceLineNo">663</span>          // this means we need to evict blocks in memory bucket to make room,<a name="line.663"></a>
+<span class="sourceLineNo">664</span>          // so the single and multi buckets will be emptied<a name="line.664"></a>
+<span class="sourceLineNo">665</span>          bytesFreed = bucketSingle.free(s);<a name="line.665"></a>
+<span class="sourceLineNo">666</span>          bytesFreed += bucketMulti.free(m);<a name="line.666"></a>
 <span class="sourceLineNo">667</span>          if (LOG.isTraceEnabled()) {<a name="line.667"></a>
 <span class="sourceLineNo">668</span>            LOG.trace("freed " + StringUtils.byteDesc(bytesFreed) +<a name="line.668"></a>
-<span class="sourceLineNo">669</span>              " total from all three buckets ");<a name="line.669"></a>
+<span class="sourceLineNo">669</span>              " from single and multi buckets");<a name="line.669"></a>
 <span class="sourceLineNo">670</span>          }<a name="line.670"></a>
-<span class="sourceLineNo">671</span>        } else {<a name="line.671"></a>
-<span class="sourceLineNo">672</span>          // this means no need to evict block in memory bucket,<a name="line.672"></a>
-<span class="sourceLineNo">673</span>          // and we try best to make the ratio between single-bucket and<a name="line.673"></a>
-<span class="sourceLineNo">674</span>          // multi-bucket is 1:2<a name="line.674"></a>
-<span class="sourceLineNo">675</span>          long bytesRemain = s + m - bytesToFree;<a name="line.675"></a>
-<span class="sourceLineNo">676</span>          if (3 * s &lt;= bytesRemain) {<a name="line.676"></a>
-<span class="sourceLineNo">677</span>            // single-bucket is small enough that no eviction happens for it<a name="line.677"></a>
-<span class="sourceLineNo">678</span>            // hence all eviction goes from multi-bucket<a name="line.678"></a>
-<span class="sourceLineNo">679</span>            bytesFreed = bucketMulti.free(bytesToFree);<a name="line.679"></a>
-<span class="sourceLineNo">680</span>          } else if (3 * m &lt;= 2 * bytesRemain) {<a name="line.680"></a>
-<span class="sourceLineNo">681</span>            // multi-bucket is small enough that no eviction happens for it<a name="line.681"></a>
-<span class="sourceLineNo">682</span>            // hence all eviction goes from single-bucket<a name="line.682"></a>
-<span class="sourceLineNo">683</span>            bytesFreed = bucketSingle.free(bytesToFree);<a name="line.683"></a>
-<span class="sourceLineNo">684</span>          } else {<a name="line.684"></a>
-<span class="sourceLineNo">685</span>            // both buckets need to evict some blocks<a name="line.685"></a>
-<span class="sourceLineNo">686</span>            bytesFreed = bucketSingle.free(s - bytesRemain / 3);<a name="line.686"></a>
-<span class="sourceLineNo">687</span>            if (bytesFreed &lt; bytesToFree) {<a name="line.687"></a>
-<span class="sourceLineNo">688</span>              bytesFreed += bucketMulti.free(bytesToFree - bytesFreed);<a name="line.688"></a>
-<span class="sourceLineNo">689</span>            }<a name="line.689"></a>
-<span class="sourceLineNo">690</span>          }<a name="line.690"></a>
-<span class="sourceLineNo">691</span>        }<a name="line.691"></a>
-<span class="sourceLineNo">692</span>      } else {<a name="line.692"></a>
-<span class="sourceLineNo">693</span>        PriorityQueue&lt;BlockBucket&gt; bucketQueue = new PriorityQueue&lt;&gt;(3);<a name="line.693"></a>
-<span class="sourceLineNo">694</span><a name="line.694"></a>
-<span class="sourceLineNo">695</span>        bucketQueue.add(bucketSingle);<a name="line.695"></a>
-<span class="sourceLineNo">696</span>        bucketQueue.add(bucketMulti);<a name="line.696"></a>
-<span class="sourceLineNo">697</span>        bucketQueue.add(bucketMemory);<a name="line.697"></a>
-<span class="sourceLineNo">698</span><a name="line.698"></a>
-<span class="sourceLineNo">699</span>        int remainingBuckets = 3;<a name="line.699"></a>
-<span class="sourceLineNo">700</span><a name="line.700"></a>
-<span class="sourceLineNo">701</span>        BlockBucket bucket;<a name="line.701"></a>
-<span class="sourceLineNo">702</span>        while ((bucket = bucketQueue.poll()) != null) {<a name="line.702"></a>
-<span class="sourceLineNo">703</span>          long overflow = bucket.overflow();<a name="line.703"></a>
-<span class="sourceLineNo">704</span>          if (overflow &gt; 0) {<a name="line.704"></a>
-<span class="sourceLineNo">705</span>            long bucketBytesToFree =<a name="line.705"></a>
-<span class="sourceLineNo">706</span>                Math.min(overflow, (bytesToFree - bytesFreed) / remainingBuckets);<a name="line.706"></a>
-<span class="sourceLineNo">707</span>            bytesFreed += bucket.free(bucketBytesToFree);<a name="line.707"></a>
-<span class="sourceLineNo">708</span>          }<a name="line.708"></a>
-<span class="sourceLineNo">709</span>          remainingBuckets--;<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>      if (LOG.isTraceEnabled()) {<a name="line.712"></a>
-<span class="sourceLineNo">713</span>        long single = bucketSingle.totalSize();<a name="line.713"></a>
-<span class="sourceLineNo">714</span>        long multi = bucketMulti.totalSize();<a name="line.714"></a>
-<span class="sourceLineNo">715</span>        long memory = bucketMemory.totalSize();<a name="line.715"></a>
-<span class="sourceLineNo">716</span>        LOG.trace("Block cache LRU eviction completed; " +<a name="line.716"></a>
-<span class="sourceLineNo">717</span>          "freed=" + StringUtils.byteDesc(bytesFreed) + ", " +<a name="line.717"></a>
-<span class="sourceLineNo">718</span>          "total=" + StringUtils.byteDesc(this.size.get()) + ", " +<a name="line.718"></a>
-<span class="sourceLineNo">719</span>          "single=" + StringUtils.byteDesc(single) + ", " +<a name="line.719"></a>
-<span class="sourceLineNo">720</span>          "multi=" + StringUtils.byteDesc(multi) + ", " +<a name="line.720"></a>
-<span class="sourceLineNo">721</span>          "memory=" + StringUtils.byteDesc(memory));<a name="line.721"></a>
-<span class="sourceLineNo">722</span>      }<a name="line.722"></a>
-<span class="sourceLineNo">723</span>    } finally {<a name="line.723"></a>
-<span class="sourceLineNo">724</span>      stats.evict();<a name="line.724"></a>
-<span class="sourceLineNo">725</span>      evictionInProgress = false;<a name="line.725"></a>
-<span class="sourceLineNo">726</span>      evictionLock.unlock();<a name="line.726"></a>
-<span class="sourceLineNo">727</span>    }<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>  @Override<a name="line.730"></a>
-<span class="sourceLineNo">731</span>  public String toString() {<a name="line.731"></a>
-<span class="sourceLineNo">732</span>    return MoreObjects.toStringHelper(this)<a name="line.732"></a>
-<span class="sourceLineNo">733</span>      .add("blockCount", getBlockCount())<a name="line.733"></a>
-<span class="sourceLineNo">734</span>      .add("currentSize", StringUtils.byteDesc(getCurrentSize()))<a name="line.734"></a>
-<span class="sourceLineNo">735</span>      .add("freeSize", StringUtils.byteDesc(getFreeSize()))<a name="line.735"></a>
-<span class="sourceLineNo">736</span>      .add("maxSize", StringUtils.byteDesc(getMaxSize()))<a name="line.736"></a>
-<span class="sourceLineNo">737</span>      .add("heapSize", StringUtils.byteDesc(heapSize()))<a name="line.737"></a>
-<span class="sourceLineNo">738</span>      .add("minSize", StringUtils.byteDesc(minSize()))<a name="line.738"></a>
-<span class="sourceLineNo">739</span>      .add("minFactor", minFactor)<a name="line.739"></a>
-<span class="sourceLineNo">740</span>      .add("multiSize", StringUtils.byteDesc(multiSize()))<a name="line.740"></a>
-<span class="sourceLineNo">741</span>      .add("multiFactor", multiFactor)<a name="line.741"></a>
-<span class="sourceLineNo">742</span>      .add("singleSize", StringUtils.byteDesc(singleSize()))<a name="line.742"></a>
-<span class="sourceLineNo">743</span>      .add("singleFactor", singleFactor)<a name="line.743"></a>
-<span class="sourceLineNo">744</span>      .toString();<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>  /**<a name="line.747"></a>
-<span class="sourceLineNo">748</span>   * Used to group blocks into priority buckets.  There will be a BlockBucket<a name="line.748"></a>
-<span class="sourceLineNo">749</span>   * for each priority (single, multi, memory).  Once bucketed, the eviction<a name="line.749"></a>
-<span class="sourceLineNo">750</span>   * algorithm takes the appropriate number of elements out of each according<a name="line.750"></a>
-<span class="sourceLineNo">751</span>   * to configuration parameters and their relatives sizes.<a name="line.751"></a>
-<span class="sourceLineNo">752</span>   */<a name="line.752"></a>
-<span class="sourceLineNo">753</span>  private class BlockBucket implements Comparable&lt;BlockBucket&gt; {<a name="line.753"></a>
-<span class="sourceLineNo">754</span><a name="line.754"></a>
-<span class="sourceLineNo">755</span>    private final String name;<a name="line.755"></a>
-<span class="sourceLineNo">756</span>    private LruCachedBlockQueue queue;<a name="line.756"></a>
-<span class="sourceLineNo">757</span>    private long totalSize = 0;<a name="line.757"></a>
-<span class="sourceLineNo">758</span>    private long bucketSize;<a name="line.758"></a>
+<span class="sourceLineNo">671</span>          bytesFreed += bucketMemory.free(bytesToFree - bytesFreed);<a name="line.671"></a>
+<span class="sourceLineNo">672</span>          if (LOG.isTraceEnabled()) {<a name="line.672"></a>
+<span class="sourceLineNo">673</span>            LOG.trace("freed " + StringUtils.byteDesc(bytesFreed) +<a name="line.673"></a>
+<span class="sourceLineNo">674</span>              " total from all three buckets ");<a name="line.674"></a>
+<span class="sourceLineNo">675</span>          }<a name="line.675"></a>
+<span class="sourceLineNo">676</span>        } else {<a name="line.676"></a>
+<span class="sourceLineNo">677</span>          // this means no need to evict block in memory bucket,<a name="line.677"></a>
+<span class="sourceLineNo">678</span>          // and we try best to make the ratio between single-bucket and<a name="line.678"></a>
+<span class="sourceLineNo">679</span>          // multi-bucket is 1:2<a name="line.679"></a>
+<span class="sourceLineNo">680</span>          long bytesRemain = s + m - bytesToFree;<a name="line.680"></a>
+<span class="sourceLineNo">681</span>          if (3 * s &lt;= bytesRemain) {<a name="line.681"></a>
+<span class="sourceLineNo">682</span>            // single-bucket is small enough that no eviction happens for it<a name="line.682"></a>
+<span class="sourceLineNo">683</span>            // hence all eviction goes from multi-bucket<a name="line.683"></a>
+<span class="sourceLineNo">684</span>            bytesFreed = bucketMulti.free(bytesToFree);<a name="line.684"></a>
+<span class="sourceLineNo">685</span>          } else if (3 * m &lt;= 2 * bytesRemain) {<a name="line.685"></a>
+<span class="sourceLineNo">686</span>            // multi-bucket is small enough that no eviction happens for it<a name="line.686"></a>
+<span class="sourceLineNo">687</span>            // hence all eviction goes from single-bucket<a name="line.687"></a>
+<span class="sourceLineNo">688</span>            bytesFreed = bucketSingle.free(bytesToFree);<a name="line.688"></a>
+<span class="sourceLineNo">689</span>          } else {<a name="line.689"></a>
+<span class="sourceLineNo">690</span>            // both buckets need to evict some blocks<a name="line.690"></a>
+<span class="sourceLineNo">691</span>            bytesFreed = bucketSingle.free(s - bytesRemain / 3);<a name="line.691"></a>
+<span class="sourceLineNo">692</span>            if (bytesFreed &lt; bytesToFree) {<a name="line.692"></a>
+<span class="sourceLineNo">693</span>              bytesFreed += bucketMulti.free(bytesToFree - bytesFreed);<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>        }<a name="line.696"></a>
+<span class="sourceLineNo">697</span>      } else {<a name="line.697"></a>
+<span class="sourceLineNo">698</span>        PriorityQueue&lt;BlockBucket&gt; bucketQueue = new PriorityQueue&lt;&gt;(3);<a name="line.698"></a>
+<span class="sourceLineNo">699</span><a name="line.699"></a>
+<span class="sourceLineNo">700</span>        bucketQueue.add(bucketSingle);<a name="line.700"></a>
+<span class="sourceLineNo">701</span>        bucketQueue.add(bucketMulti);<a name="line.701"></a>
+<span class="sourceLineNo">702</span>        bucketQueue.add(bucketMemory);<a name="line.702"></a>
+<span class="sourceLineNo">703</span><a name="line.703"></a>
+<span class="sourceLineNo">704</span>        int remainingBuckets = 3;<a name="line.704"></a>
+<span class="sourceLineNo">705</span><a name="line.705"></a>
+<span class="sourceLineNo">706</span>        BlockBucket bucket;<a name="line.706"></a>
+<span class="sourceLineNo">707</span>        while ((bucket = bucketQueue.poll()) != null) {<a name="line.707"></a>
+<span class="sourceLineNo">708</span>          long overflow = bucket.overflow();<a name="line.708"></a>
+<span class="sourceLineNo">709</span>          if (overflow &gt; 0) {<a name="line.709"></a>
+<span class="sourceLineNo">710</span>            long bucketBytesToFree =<a name="line.710"></a>
+<span class="sourceLineNo">711</span>                Math.min(overflow, (bytesToFree - bytesFreed) / remainingBuckets);<a name="line.711"></a>
+<span class="sourceLineNo">712</span>            bytesFreed += bucket.free(bucketBytesToFree);<a name="line.712"></a>
+<span class="sourceLineNo">713</span>          }<a name="line.713"></a>
+<span class="sourceLineNo">714</span>          remainingBuckets--;<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">717</span>      if (LOG.isTraceEnabled()) {<a name="line.717"></a>
+<span class="sourceLineNo">718</span>        long single = bucketSingle.totalSize();<a name="line.718"></a>
+<span class="sourceLineNo">719</span>        long multi = bucketMulti.totalSize();<a name="line.719"></a>
+<span class="sourceLineNo">720</span>        long memory = bucketMemory.totalSize();<a name="line.720"></a>
+<span class="sourceLineNo">721</span>        LOG.trace("Block cache LRU eviction completed; " +<a name="line.721"></a>
+<span class="sourceLineNo">722</span>          "freed=" + StringUtils.byteDesc(bytesFreed) + ", " +<a name="line.722"></a>
+<span class="sourceLineNo">723</span>          "total=" + StringUtils.byteDesc(this.size.get()) + ", " +<a name="line.723"></a>
+<span class="sourceLineNo">724</span>          "single=" + StringUtils.byteDesc(single) + ", " +<a name="line.724"></a>
+<span class="sourceLineNo">725</span>          "multi=" + StringUtils.byteDesc(multi) + ", " +<a name="line.725"></a>
+<span class="sourceLineNo">726</span>          "memory=" + StringUtils.byteDesc(memory));<a name="line.726"></a>
+<span class="sourceLineNo">727</span>      }<a name="line.727"></a>
+<span class="sourceLineNo">728</span>    } finally {<a name="line.728"></a>
+<span class="sourceLineNo">729</span>      stats.evict();<a name="line.729"></a>
+<span class="sourceLineNo">730</span>      evictionInProgress = false;<a name="line.730"></a>
+<span class="sourceLineNo">731</span>      evictionLock.unlock();<a name="line.731"></a>
+<span class="sourceLineNo">732</span>    }<a name="line.732"></a>
+<span class="sourceLineNo">733</span>  }<a name="line.733"></a>
+<span class="sourceLineNo">734</span><a name="line.734"></a>
+<span class="sourceLineNo">735</span>  @Override<a name="line.735"></a>
+<span class="sourceLineNo">736</span>  public String toString() {<a name="line.736"></a>
+<span class="sourceLineNo">737</span>    return MoreObjects.toStringHelper(this)<a name="line.737"></a>
+<span class="sourceLineNo">738</span>      .add("blockCount", getBlockCount())<a name="line.738"></a>
+<span class="sourceLineNo">739</span>      .add("currentSize", StringUtils.byteDesc(getCurrentSize()))<a name="line.739"></a>
+<span class="sourceLineNo">740</span>      .add("freeSize", StringUtils.byteDesc(getFreeSize()))<a name="line.740"></a>
+<span class="sourceLineNo">741</span>      .add("maxSize", StringUtils.byteDesc(getMaxSize()))<a name="line.741"></a>
+<span class="sourceLineNo">742</span>      .add("heapSize", StringUtils.byteDesc(heapSize()))<a name="line.742"></a>
+<span class="sourceLineNo">743</span>      .add("minSize", StringUtils.byteDesc(minSize()))<a name="line.743"></a>
+<span class="sourceLineNo">744</span>      .add("minFactor", minFactor)<a name="line.744"></a>
+<span class="sourceLineNo">745</span>      .add("multiSize", StringUtils.byteDesc(multiSize()))<a name="line.745"></a>
+<span class="sourceLineNo">746</span>      .add("multiFactor", multiFactor)<a name="line.746"></a>
+<span class="sourceLineNo">747</span>      .add("singleSize", StringUtils.byteDesc(singleSize()))<a name="line.747"></a>
+<span class="sourceLineNo">748</span>      .add("singleFactor", singleFactor)<a name="line.748"></a>
+<span class="sourceLineNo">749</span>      .toString();<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>   * Used to group blocks into priority buckets.  There will be a BlockBucket<a name="line.753"></a>
+<span class="sourceLineNo">754</span>   * for each priority (single, multi, memory).  Once bucketed, the eviction<a name="line.754"></a>
+<span class="sourceLineNo">755</span>   * algorithm takes the appropriate number of elements out of each according<a name="line.755"></a>
+<span class="sourceLineNo">756</span>   * to configuration parameters and their relatives sizes.<a name="line.756"></a>
+<span class="sourceLineNo">757</span>   */<a name="line.757"></a>
+<span class="sourceLineNo">758</span>  private class BlockBucket implements Comparable&lt;BlockBucket&gt; {<a name="line.758"></a>
 <span class="sourceLineNo">759</span><a name="line.759"></a>
-<span class="sourceLineNo">760</span>    public BlockBucket(String name, long bytesToFree, long blockSize, long bucketSize) {<a name="line.760"></a>
-<span class="sourceLineNo">761</span>      this.name = name;<a name="line.761"></a>
-<span class="sourceLineNo">762</span>      this.bucketSize = bucketSize;<a name="line.762"></a>
-<span class="sourceLineNo">763</span>      queue = new LruCachedBlockQueue(bytesToFree, blockSize);<a name="line.763"></a>
-<span class="sourceLineNo">764</span>      totalSize = 0;<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>    public void add(LruCachedBlock block) {<a name="line.767"></a>
-<span class="sourceLineNo">768</span>      totalSize += block.heapSize();<a name="line.768"></a>
-<span class="sourceLineNo">769</span>      queue.add(block);<a name="line.769"></a>
+<span class="sourceLineNo">760</span>    private final String name;<a name="line.760"></a>
+<span class="sourceLineNo">761</span>    private LruCachedBlockQueue queue;<a name="line.761"></a>
+<span class="sourceLineNo">762</span>    private long totalSize = 0;<a name="line.762"></a>
+<span class="sourceLineNo">763</span>    private long bucketSize;<a name="line.763"></a>
+<span class="sourceLineNo">764</span><a name="line.764"></a>
+<span class="sourceLineNo">765</span>    public BlockBucket(String name, long bytesToFree, long blockSize, long bucketSize) {<a name="line.765"></a>
+<span class="sourceLineNo">766</span>      this.name = name;<a name="line.766"></a>
+<span class="sourceLineNo">767</span>      this.bucketSize = bucketSize;<a name="line.767"></a>
+<span class="sourceLineNo">768</span>      queue = new LruCachedBlockQueue(bytesToFree, blockSize);<a name="line.768"></a>
+<span class="sourceLineNo">769</span>      totalSize = 0;<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>    public long free(long toFree) {<a name="line.772"></a>
-<span class="sourceLineNo">773</span>      if (LOG.isTraceEnabled()) {<a name="line.773"></a>
-<span class="sourceLineNo">774</span>        LOG.trace("freeing " + StringUtils.byteDesc(toFree) + " from " + this);<a name="line.774"></a>
-<span class="sourceLineNo">775</span>      }<a name="line.775"></a>
-<span class="sourceLineNo">776</span>      LruCachedBlock cb;<a name="line.776"></a>
-<span class="sourceLineNo">777</span>      long freedBytes = 0;<a name="line.777"></a>
-<span class="sourceLineNo">778</span>      while ((cb = queue.pollLast()) != null) {<a name="line.778"></a>
-<span class="sourceLineNo">779</span>        freedBytes += evictBlock(cb, true);<a name="line.779"></a>
-<span class="sourceLineNo">780</span>        if (freedBytes &gt;= toFree) {<a name="line.780"></a>
-<span class="sourceLineNo">781</span>          return freedBytes;<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>      if (LOG.isTraceEnabled()) {<a name="line.784"></a>
-<span class="sourceLineNo">785</span>        LOG.trace("freed " + StringUtils.byteDesc(freedBytes) + " from " + this);<a name="line.785"></a>
-<span class="sourceLineNo">786</span>      }<a name="line.786"></a>
-<span class="sourceLineNo">787</span>      return freedBytes;<a name="line.787"></a>
-<span class="sourceLineNo">788</span>    }<a name="line.788"></a>
-<span class="sourceLineNo">789</span><a name="line.789"></a>
-<span class="sourceLineNo">790</span>    public long overflow() {<a name="line.790"></a>
-<span class="sourceLineNo">791</span>      return totalSize - bucketSize;<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>
-<span class="sourceLineNo">794</span>    public long totalSize() {<a name="line.794"></a>
-<span class="sourceLineNo">795</span>      return totalSize;<a name="line.795"></a>
-<span class="sourceLineNo">796</span>    }<a name="line.796"></a>
-<span class="sourceLineNo">797</span><a name="line.797"></a>
-<span class="sourceLineNo">798</span>    @Override<a name="line.798"></a>
-<span class="sourceLineNo">799</span>    public int compareTo(BlockBucket that) {<a name="line.799"></a>
-<span class="sourceLineNo">800</span>      return Long.compare(this.overflow(), that.overflow());<a name="line.800"></a>
+<span class="sourceLineNo">772</span>    public void add(LruCachedBlock block) {<a name="line.772"></a>
+<span class="sourceLineNo">773</span>      totalSize += block.heapSize();<a name="line.773"></a>
+<span class="sourceLineNo">774</span>      queue.add(block);<a name="line.774"></a>
+<span class="sourceLineNo">775</span>    }<a name="line.775"></a>
+<span class="sourceLineNo">776</span><a name="line.776"></a>
+<span class="sourceLineNo">777</span>    public long free(long toFree) {<a name="line.777"></a>
+<span class="sourceLineNo">778</span>      if (LOG.isTraceEnabled()) {<a name="line.778"></a>
+<span class="sourceLineNo">779</span>        LOG.trace("freeing " + StringUtils.byteDesc(toFree) + " from " + this);<a name="line.779"></a>
+<span class="sourceLineNo">780</span>      }<a name="line.780"></a>
+<span class="sourceLineNo">781</span>      LruCachedBlock cb;<a name="line.781"></a>
+<span class="sourceLineNo">782</span>      long freedBytes = 0;<a name="line.782"></a>
+<span class="sourceLineNo">783</span>      while ((cb = queue.pollLast()) != null) {<a name="line.783"></a>
+<span class="sourceLineNo">784</span>        freedBytes += evictBlock(cb, true);<a name="line.784"></a>
+<span class="sourceLineNo">785</span>        if (freedBytes &gt;= toFree) {<a name="line.785"></a>
+<span class="sourceLineNo">786</span>          return freedBytes;<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>      if (LOG.isTraceEnabled()) {<a name="line.789"></a>
+<span class="sourceLineNo">790</span>        LOG.trace("freed " + StringUtils.byteDesc(freedBytes) + " from " + this);<a name="line.790"></a>
+<span class="sourceLineNo">791</span>      }<a name="line.791"></a>
+<span class="sourceLineNo">792</span>      return freedBytes;<a name="line.792"></a>
+<span class="sourceLineNo">793</span>    }<a name="line.793"></a>
+<span class="sourceLineNo">794</span><a name="line.794"></a>
+<span class="sourceLineNo">795</span>    public long overflow() {<a name="line.795"></a>
+<span class="sourceLineNo">796</span>      return totalSize - bucketSize;<a name="line.796"></a>
+<span class="sourceLineNo">797</span>    }<a name="line.797"></a>
+<span class="sourceLineNo">798</span><a name="line.798"></a>
+<span class="sourceLineNo">799</span>    public long totalSize() {<a name="line.799"></a>
+<span class="sourceLineNo">800</span>      return totalSize;<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>    @Override<a name="line.803"></a>
-<span class="sourceLineNo">804</span>    public boolean equals(Object that) {<a name="line.804"></a>
-<span class="sourceLineNo">805</span>      if (that == null || !(that instanceof BlockBucket)) {<a name="line.805"></a>
-<span class="sourceLineNo">806</span>        return false;<a name="line.806"></a>
-<span class="sourceLineNo">807</span>      }<a name="line.807"></a>
-<span class="sourceLineNo">808</span>      return compareTo((BlockBucket)that) == 0;<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>    @Override<a name="line.811"></a>
-<span class="sourceLineNo">812</span>    public int hashCode() {<a name="line.812"></a>
-<span class="sourceLineNo">813</span>      return Objects.hashCode(name, bucketSize, queue, totalSize);<a name="line.813"></a>
+<span class="sourceLineNo">804</span>    public int compareTo(BlockBucket that) {<a name="line.804"></a>
+<span class="sourceLineNo">805</span>      return Long.compare(this.overflow(), that.overflow());<a name="line.805"></a>
+<span class="sourceLineNo">806</span>    }<a name="line.806"></a>
+<span class="sourceLineNo">807</span><a name="line.807"></a>
+<span class="sourceLineNo">808</span>    @Override<a name="line.808"></a>
+<span class="sourceLineNo">809</span>    public boolean equals(Object that) {<a name="line.809"></a>
+<span class="sourceLineNo">810</span>      if (that == null || !(that instanceof BlockBucket)) {<a name="line.810"></a>
+<span class="sourceLineNo">811</span>        return false;<a name="line.811"></a>
+<span class="sourceLineNo">812</span>      }<a name="line.812"></a>
+<span class="sourceLineNo">813</span>      return compareTo((BlockBucket)that) == 0;<a name="line.813"></a>
 <span class="sourceLineNo">814</span>    }<a name="line.814"></a>
 <span class="sourceLineNo">815</span><a name="line.815"></a>
 <span class="sourceLineNo">816</span>    @Override<a name="line.816"></a>
-<span class="sourceLineNo">817</span>    public String toString() {<a name="line.817"></a>
-<span class="sourceLineNo">818</span>      return MoreObjects.toStringHelper(this)<a name="line.818"></a>
-<span class="sourceLineNo">819</span>        .add("name", name)<a name="line.819"></a>
-<span class="sourceLineNo">820</span>        .add("totalSize", StringUtils.byteDesc(totalSize))<a name="line.820"></a>
-<span class="sourceLineNo">821</span>        .add("bucketSize", StringUtils.byteDesc(bucketSize))<a name="line.821"></a>
-<span class="sourceLineNo">822</span>        .toString();<a name="line.822"></a>
-<span class="sourceLineNo">823</span>    }<a name="line.823"></a>
-<span class="sourceLineNo">824</span>  }<a name="line.824"></a>
-<span class="sourceLineNo">825</span><a name="line.825"></a>
-<span class="sourceLineNo">826</span>  /**<a name="line.826"></a>
-<span class="sourceLineNo">827</span>   * Get the maximum size of this cache.<a name="line.827"></a>
-<span class="sourceLineNo">828</span>   *<a name="line.828"></a>
-<span class="sourceLineNo">829</span>   * @return max size in bytes<a name="line.829"></a>
-<span class="sourceLineNo">830</span>   */<a name="line.830"></a>
-<span class="sourceLineNo">831</span><a name="line.831"></a>
-<span class="sourceLineNo">832</span>  @Override<a name="line.832"></a>
-<span class="sourceLineNo">833</span>  public long getMaxSize() {<a name="line.833"></a>
-<span class="sourceLineNo">834</span>    return this.maxSize;<a name="line.834"></a>
-<span class="sourceLineNo">835</span>  }<a name="line.835"></a>
+<span class="sourceLineNo">817</span>    public int hashCode() {<a name="line.817"></a>
+<span class="sourceLineNo">818</span>      return Objects.hashCode(name, bucketSize, queue, totalSize);<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>    @Override<a name="line.821"></a>
+<span class="sourceLineNo">822</span>    public String toString() {<a name="line.822"></a>
+<span class="sourceLineNo">823</span>      return MoreObjects.toStringHelper(this)<a name="line.823"></a>
+<span class="sourceLineNo">824</span>        .add("name", name)<a name="line.824"></a>
+<span class="sourceLineNo">825</span>        .add("totalSize", StringUtils.byteDesc(totalSize))<a name="line.825"></a>
+<span class="sourceLineNo">826</span>        .add("bucketSize", StringUtils.byteDesc(bucketSize))<a name="line.826"></a>
+<span class="sourceLineNo">827</span>        .toString();<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">830</span><a name="line.830"></a>
+<span class="sourceLineNo">831</span>  /**<a name="line.831"></a>
+<span class="sourceLineNo">832</span>   * Get the maximum size of this cache.<a name="line.832"></a>
+<span class="sourceLineNo">833</span>   *<a name="line.833"></a>
+<span class="sourceLineNo">834</span>   * @return max size in bytes<a name="line.834"></a>
+<span class="sourceLineNo">835</span>   */<a name="line.835"></a>
 <span class="sourceLineNo">836</span><a name="line.836"></a>
 <span class="sourceLineNo">837</span>  @Override<a name="line.837"></a>
-<span class="sourceLineNo">838</span>  public long getCurrentSize() {<a name="line.838"></a>
-<span class="sourceLineNo">839</span>    return this.size.get();<a name="line.839"></a>
+<span class="sourceLineNo">838</span>  public long getMaxSize() {<a name="line.838"></a>
+<span class="sourceLineNo">839</span>    return this.maxSize;<a name="line.839"></a>
 <span class="sourceLineNo">840</span>  }<a name="line.840"></a>
 <span class="sourceLineNo">841</span><a name="line.841"></a>
 <span class="sourceLineNo">842</span>  @Override<a name="line.842"></a>
-<span class="sourceLineNo">843</span>  public long getCurrentDataSize() {<a name="line.843"></a>
-<span class="sourceLineNo">844</span>    return this.dataBlockSize.sum();<a name="line.844"></a>
+<span class="sourceLineNo">843</span>  public long getCurrentSize() {<a name="line.843"></a>
+<span class="sourceLineNo">844</span>    return this.size.get();<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>  @Override<a name="line.847"></a>
-<span class="sourceLineNo">848</span>  public long getFreeSize() {<a name="line.848"></a>
-<span class="sourceLineNo">849</span>    return getMaxSize() - getCurrentSize();<a name="line.849"></a>
+<span class="sourceLineNo">848</span>  public long getCurrentDataSize() {<a name="line.848"></a>
+<span class="sourceLineNo">849</span>    return this.dataBlockSize.sum();<a name="line.849"></a>
 <span class="sourceLineNo">850</span>  }<a name="line.850"></a>
 <span class="sourceLineNo">851</span><a name="line.851"></a>
 <span class="sourceLineNo">852</span>  @Override<a name="line.852"></a>
-<span class="sourceLineNo">853</span>  public long size() {<a name="line.853"></a>
-<span class="sourceLineNo">854</span>    return getMaxSize();<a name="line.854"></a>
+<span class="sourceLineNo">853</span>  public long getFreeSize() {<a name="line.853"></a>
+<span class="sourceLineNo">854</span>    return getMaxSize() - getCurrentSize();<a name="line.854"></a>
 <span class="sourceLineNo">855</span>  }<a name="line.855"></a>
 <span class="sourceLineNo">856</span><a name="line.856"></a>
 <span class="sourceLineNo">857</span>  @Override<a name="line.857"></a>
-<span class="sourceLineNo">858</span>  public long getBlockCount() {<a name="line.858"></a>
-<span class="sourceLineNo">859</span>    return this.elements.get();<a name="line.859"></a>
+<span class="sourceLineNo">858</span>  public long size() {<a name="line.858"></a>
+<span class="sourceLineNo">859</span>    return getMaxSize();<a name="line.859"></a>
 <span class="sourceLineNo">860</span>  }<a name="line.860"></a>
 <span class="sourceLineNo">861</span><a name="line.861"></a>
 <span class="sourceLineNo">862</span>  @Override<a name="line.862"></a>
-<span class="sourceLineNo">863</span>  public long getDataBlockCount() {<a name="line.863"></a>
-<span class="sourceLineNo">864</span>    return this.dataBlockElements.sum();<a name="line.864"></a>
+<span class="sourceLineNo">863</span>  public long getBlockCount() {<a name="line.863"></a>
+<span class="sourceLineNo">864</span>    return this.elements.get();<a name="line.864"></a>
 <span class="sourceLineNo">865</span>  }<a name="line.865"></a>
 <span class="sourceLineNo">866</span><a name="line.866"></a>
-<span class="sourceLineNo">867</span>  EvictionThread getEvictionThread() {<a name="line.867"></a>
-<span class="sourceLineNo">868</span>    return this.evictionThread;<a name="line.868"></a>
-<span class="sourceLineNo">869</span>  }<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>   * Eviction thread.  Sits in waiting state until an eviction is triggered<a name="line.872"></a>
-<span class="sourceLineNo">873</span>   * when the cache size grows above the acc

<TRUNCATED>

[44/50] hbase-site git commit: Published site at 26babcf013de696b899d76a3c39434b794440d8d.

Posted by gi...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html b/devapidocs/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html
index 4cec32f..21e34e3 100644
--- a/devapidocs/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html
+++ b/devapidocs/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html
@@ -113,7 +113,7 @@ var activeTableTab = "activeTableTab";
 </dl>
 <hr>
 <br>
-<pre>private static class <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.508">ScannerContext.LimitFields</a>
+<pre>private static class <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.520">ScannerContext.LimitFields</a>
 extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true" title="class or interface in java.lang">Object</a></pre>
 <div class="block">The different fields that can be used as limits in calls to
  <a href="../../../../../org/apache/hadoop/hbase/regionserver/InternalScanner.html#next-java.util.List-"><code>InternalScanner.next(java.util.List)</code></a> and <a href="../../../../../org/apache/hadoop/hbase/regionserver/InternalScanner.html#next-java.util.List-"><code>InternalScanner.next(java.util.List)</code></a></div>
@@ -198,14 +198,6 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <div class="block">Fields keep their default values.</div>
 </td>
 </tr>
-<tr class="rowColor">
-<td class="colOne"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#LimitFields-int-org.apache.hadoop.hbase.regionserver.ScannerContext.LimitScope-long-long-org.apache.hadoop.hbase.regionserver.ScannerContext.LimitScope-long-">LimitFields</a></span>(int&nbsp;batch,
-           <a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a>&nbsp;sizeScope,
-           long&nbsp;size,
-           long&nbsp;heapSize,
-           <a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a>&nbsp;timeScope,
-           long&nbsp;time)</code>&nbsp;</td>
-</tr>
 </table>
 </li>
 </ul>
@@ -332,7 +324,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>DEFAULT_BATCH</h4>
-<pre>private static&nbsp;int <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.513">DEFAULT_BATCH</a></pre>
+<pre>private static&nbsp;int <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.525">DEFAULT_BATCH</a></pre>
 <div class="block">Default values of the limit fields. Defined such that if a field does NOT change from its
  default, it will not be enforced</div>
 </li>
@@ -343,7 +335,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>DEFAULT_SIZE</h4>
-<pre>private static&nbsp;long <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.514">DEFAULT_SIZE</a></pre>
+<pre>private static&nbsp;long <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.526">DEFAULT_SIZE</a></pre>
 </li>
 </ul>
 <a name="DEFAULT_TIME">
@@ -352,7 +344,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>DEFAULT_TIME</h4>
-<pre>private static&nbsp;long <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.515">DEFAULT_TIME</a></pre>
+<pre>private static&nbsp;long <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.527">DEFAULT_TIME</a></pre>
 </li>
 </ul>
 <a name="DEFAULT_SCOPE">
@@ -361,7 +353,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>DEFAULT_SCOPE</h4>
-<pre>private static final&nbsp;<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.520">DEFAULT_SCOPE</a></pre>
+<pre>private static final&nbsp;<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.532">DEFAULT_SCOPE</a></pre>
 <div class="block">Default scope that is assigned to a limit if a scope is not specified.</div>
 </li>
 </ul>
@@ -371,7 +363,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>batch</h4>
-<pre>int <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.524">batch</a></pre>
+<pre>int <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.536">batch</a></pre>
 </li>
 </ul>
 <a name="sizeScope">
@@ -380,7 +372,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>sizeScope</h4>
-<pre><a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.526">sizeScope</a></pre>
+<pre><a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.538">sizeScope</a></pre>
 </li>
 </ul>
 <a name="dataSize">
@@ -389,7 +381,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>dataSize</h4>
-<pre>long <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.528">dataSize</a></pre>
+<pre>long <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.540">dataSize</a></pre>
 </li>
 </ul>
 <a name="heapSize">
@@ -398,7 +390,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>heapSize</h4>
-<pre>long <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.531">heapSize</a></pre>
+<pre>long <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.543">heapSize</a></pre>
 </li>
 </ul>
 <a name="timeScope">
@@ -407,7 +399,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>timeScope</h4>
-<pre><a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.533">timeScope</a></pre>
+<pre><a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.545">timeScope</a></pre>
 </li>
 </ul>
 <a name="time">
@@ -416,7 +408,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>time</h4>
-<pre>long <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.534">time</a></pre>
+<pre>long <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.546">time</a></pre>
 </li>
 </ul>
 </li>
@@ -430,25 +422,11 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <a name="LimitFields--">
 <!--   -->
 </a>
-<ul class="blockList">
-<li class="blockList">
-<h4>LimitFields</h4>
-<pre><a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.539">LimitFields</a>()</pre>
-<div class="block">Fields keep their default values.</div>
-</li>
-</ul>
-<a name="LimitFields-int-org.apache.hadoop.hbase.regionserver.ScannerContext.LimitScope-long-long-org.apache.hadoop.hbase.regionserver.ScannerContext.LimitScope-long-">
-<!--   -->
-</a>
 <ul class="blockListLast">
 <li class="blockList">
 <h4>LimitFields</h4>
-<pre><a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.542">LimitFields</a>(int&nbsp;batch,
-            <a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a>&nbsp;sizeScope,
-            long&nbsp;size,
-            long&nbsp;heapSize,
-            <a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a>&nbsp;timeScope,
-            long&nbsp;time)</pre>
+<pre><a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.551">LimitFields</a>()</pre>
+<div class="block">Fields keep their default values.</div>
 </li>
 </ul>
 </li>
@@ -465,7 +443,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>copy</h4>
-<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.547">copy</a>(<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html" title="class in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitFields</a>&nbsp;limitsToCopy)</pre>
+<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.554">copy</a>(<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html" title="class in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitFields</a>&nbsp;limitsToCopy)</pre>
 </li>
 </ul>
 <a name="setFields-int-org.apache.hadoop.hbase.regionserver.ScannerContext.LimitScope-long-long-org.apache.hadoop.hbase.regionserver.ScannerContext.LimitScope-long-">
@@ -474,7 +452,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>setFields</h4>
-<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.557">setFields</a>(int&nbsp;batch,
+<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.564">setFields</a>(int&nbsp;batch,
                <a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a>&nbsp;sizeScope,
                long&nbsp;dataSize,
                long&nbsp;heapSize,
@@ -489,7 +467,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getBatch</h4>
-<pre>int&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.567">getBatch</a>()</pre>
+<pre>int&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.574">getBatch</a>()</pre>
 </li>
 </ul>
 <a name="setBatch-int-">
@@ -498,7 +476,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>setBatch</h4>
-<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.571">setBatch</a>(int&nbsp;batch)</pre>
+<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.578">setBatch</a>(int&nbsp;batch)</pre>
 </li>
 </ul>
 <a name="canEnforceBatchLimitFromScope-org.apache.hadoop.hbase.regionserver.ScannerContext.LimitScope-">
@@ -507,7 +485,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>canEnforceBatchLimitFromScope</h4>
-<pre>boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.579">canEnforceBatchLimitFromScope</a>(<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a>&nbsp;checkerScope)</pre>
+<pre>boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.586">canEnforceBatchLimitFromScope</a>(<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a>&nbsp;checkerScope)</pre>
 <dl>
 <dt><span class="paramLabel">Parameters:</span></dt>
 <dd><code>checkerScope</code> - </dd>
@@ -522,7 +500,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getDataSize</h4>
-<pre>long&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.583">getDataSize</a>()</pre>
+<pre>long&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.590">getDataSize</a>()</pre>
 </li>
 </ul>
 <a name="getHeapSize--">
@@ -531,7 +509,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getHeapSize</h4>
-<pre>long&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.587">getHeapSize</a>()</pre>
+<pre>long&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.594">getHeapSize</a>()</pre>
 </li>
 </ul>
 <a name="setDataSize-long-">
@@ -540,7 +518,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>setDataSize</h4>
-<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.591">setDataSize</a>(long&nbsp;dataSize)</pre>
+<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.598">setDataSize</a>(long&nbsp;dataSize)</pre>
 </li>
 </ul>
 <a name="setHeapSize-long-">
@@ -549,7 +527,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>setHeapSize</h4>
-<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.595">setHeapSize</a>(long&nbsp;heapSize)</pre>
+<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.602">setHeapSize</a>(long&nbsp;heapSize)</pre>
 </li>
 </ul>
 <a name="getSizeScope--">
@@ -558,7 +536,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getSizeScope</h4>
-<pre><a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.602">getSizeScope</a>()</pre>
+<pre><a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.609">getSizeScope</a>()</pre>
 <dl>
 <dt><span class="returnLabel">Returns:</span></dt>
 <dd><a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver"><code>ScannerContext.LimitScope</code></a> indicating scope in which the size limit is enforced</dd>
@@ -571,7 +549,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>setSizeScope</h4>
-<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.609">setSizeScope</a>(<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a>&nbsp;scope)</pre>
+<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.616">setSizeScope</a>(<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a>&nbsp;scope)</pre>
 <div class="block">Change the scope in which the size limit is enforced</div>
 </li>
 </ul>
@@ -581,7 +559,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>canEnforceSizeLimitFromScope</h4>
-<pre>boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.617">canEnforceSizeLimitFromScope</a>(<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a>&nbsp;checkerScope)</pre>
+<pre>boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.624">canEnforceSizeLimitFromScope</a>(<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a>&nbsp;checkerScope)</pre>
 <dl>
 <dt><span class="paramLabel">Parameters:</span></dt>
 <dd><code>checkerScope</code> - </dd>
@@ -596,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>getTime</h4>
-<pre>long&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.621">getTime</a>()</pre>
+<pre>long&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.628">getTime</a>()</pre>
 </li>
 </ul>
 <a name="setTime-long-">
@@ -605,7 +583,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>setTime</h4>
-<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.625">setTime</a>(long&nbsp;time)</pre>
+<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.632">setTime</a>(long&nbsp;time)</pre>
 </li>
 </ul>
 <a name="getTimeScope--">
@@ -614,7 +592,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getTimeScope</h4>
-<pre><a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.632">getTimeScope</a>()</pre>
+<pre><a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.639">getTimeScope</a>()</pre>
 <dl>
 <dt><span class="returnLabel">Returns:</span></dt>
 <dd><a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver"><code>ScannerContext.LimitScope</code></a> indicating scope in which the time limit is enforced</dd>
@@ -627,7 +605,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>setTimeScope</h4>
-<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.639">setTimeScope</a>(<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a>&nbsp;scope)</pre>
+<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.646">setTimeScope</a>(<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a>&nbsp;scope)</pre>
 <div class="block">Change the scope in which the time limit is enforced</div>
 </li>
 </ul>
@@ -637,7 +615,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>canEnforceTimeLimitFromScope</h4>
-<pre>boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.647">canEnforceTimeLimitFromScope</a>(<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a>&nbsp;checkerScope)</pre>
+<pre>boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html#line.654">canEnforceTimeLimitFromScope</a>(<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a>&nbsp;checkerScope)</pre>
 <dl>
 <dt><span class="paramLabel">Parameters:</span></dt>
 <dd><code>checkerScope</code> - </dd>
@@ -652,7 +630,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>toString</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/regionserver/ScannerContext.LimitFields.html#line.652">toString</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/regionserver/ScannerContext.LimitFields.html#line.659">toString</a>()</pre>
 <dl>
 <dt><span class="overrideSpecifyLabel">Overrides:</span></dt>
 <dd><code><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true#toString--" title="class or interface in java.lang">toString</a></code>&nbsp;in class&nbsp;<code><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></code></dd>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html b/devapidocs/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html
index f1534ee..4ed5e16 100644
--- a/devapidocs/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html
+++ b/devapidocs/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html
@@ -122,7 +122,7 @@ var activeTableTab = "activeTableTab";
 </dl>
 <hr>
 <br>
-<pre>public static enum <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.462">ScannerContext.LimitScope</a>
+<pre>public static enum <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.474">ScannerContext.LimitScope</a>
 extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang">Enum</a>&lt;<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a>&gt;</pre>
 <div class="block">The various scopes where a limit can be enforced. Used to differentiate when a limit should be
  enforced or not.</div>
@@ -247,7 +247,7 @@ the order they are declared.</div>
 <ul class="blockList">
 <li class="blockList">
 <h4>BETWEEN_ROWS</h4>
-<pre>public static final&nbsp;<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html#line.467">BETWEEN_ROWS</a></pre>
+<pre>public static final&nbsp;<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html#line.479">BETWEEN_ROWS</a></pre>
 <div class="block">Enforcing a limit between rows means that the limit will not be considered until all the
  cells for a particular row have been retrieved</div>
 </li>
@@ -258,7 +258,7 @@ the order they are declared.</div>
 <ul class="blockListLast">
 <li class="blockList">
 <h4>BETWEEN_CELLS</h4>
-<pre>public static final&nbsp;<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html#line.473">BETWEEN_CELLS</a></pre>
+<pre>public static final&nbsp;<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html#line.485">BETWEEN_CELLS</a></pre>
 <div class="block">Enforcing a limit between cells means that the limit will be considered after each full cell
  has been retrieved</div>
 </li>
@@ -277,7 +277,7 @@ the order they are declared.</div>
 <ul class="blockListLast">
 <li class="blockList">
 <h4>depth</h4>
-<pre>final&nbsp;int <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html#line.483">depth</a></pre>
+<pre>final&nbsp;int <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html#line.495">depth</a></pre>
 <div class="block">When enforcing a limit, we must check that the scope is appropriate for enforcement.
  <p>
  To communicate this concept, each scope has a depth. A limit will be enforced if the depth of
@@ -342,7 +342,7 @@ not permitted.)</div>
 <ul class="blockList">
 <li class="blockList">
 <h4>depth</h4>
-<pre>final&nbsp;int&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html#line.489">depth</a>()</pre>
+<pre>final&nbsp;int&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html#line.501">depth</a>()</pre>
 </li>
 </ul>
 <a name="canEnforceLimitFromScope-org.apache.hadoop.hbase.regionserver.ScannerContext.LimitScope-">
@@ -351,7 +351,7 @@ not permitted.)</div>
 <ul class="blockListLast">
 <li class="blockList">
 <h4>canEnforceLimitFromScope</h4>
-<pre>boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html#line.499">canEnforceLimitFromScope</a>(<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a>&nbsp;checkerScope)</pre>
+<pre>boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html#line.511">canEnforceLimitFromScope</a>(<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a>&nbsp;checkerScope)</pre>
 <dl>
 <dt><span class="paramLabel">Parameters:</span></dt>
 <dd><code>checkerScope</code> - The scope in which the limit is being checked</dd>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html b/devapidocs/org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html
index edfbab9..476b5ae 100644
--- a/devapidocs/org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html
+++ b/devapidocs/org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html
@@ -122,7 +122,7 @@ var activeTableTab = "activeTableTab";
 </dl>
 <hr>
 <br>
-<pre>public static enum <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.407">ScannerContext.NextState</a>
+<pre>public static enum <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.419">ScannerContext.NextState</a>
 extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang">Enum</a>&lt;<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.NextState</a>&gt;</pre>
 <div class="block">The possible states a scanner may be in following a call to <a href="../../../../../org/apache/hadoop/hbase/regionserver/InternalScanner.html#next-java.util.List-"><code>InternalScanner.next(List)</code></a></div>
 </li>
@@ -271,7 +271,7 @@ the order they are declared.</div>
 <ul class="blockList">
 <li class="blockList">
 <h4>MORE_VALUES</h4>
-<pre>public static final&nbsp;<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.NextState</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html#line.408">MORE_VALUES</a></pre>
+<pre>public static final&nbsp;<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.NextState</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html#line.420">MORE_VALUES</a></pre>
 </li>
 </ul>
 <a name="NO_MORE_VALUES">
@@ -280,7 +280,7 @@ the order they are declared.</div>
 <ul class="blockList">
 <li class="blockList">
 <h4>NO_MORE_VALUES</h4>
-<pre>public static final&nbsp;<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.NextState</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html#line.409">NO_MORE_VALUES</a></pre>
+<pre>public static final&nbsp;<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.NextState</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html#line.421">NO_MORE_VALUES</a></pre>
 </li>
 </ul>
 <a name="SIZE_LIMIT_REACHED">
@@ -289,7 +289,7 @@ the order they are declared.</div>
 <ul class="blockList">
 <li class="blockList">
 <h4>SIZE_LIMIT_REACHED</h4>
-<pre>public static final&nbsp;<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.NextState</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html#line.410">SIZE_LIMIT_REACHED</a></pre>
+<pre>public static final&nbsp;<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.NextState</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html#line.422">SIZE_LIMIT_REACHED</a></pre>
 </li>
 </ul>
 <a name="SIZE_LIMIT_REACHED_MID_ROW">
@@ -298,7 +298,7 @@ the order they are declared.</div>
 <ul class="blockList">
 <li class="blockList">
 <h4>SIZE_LIMIT_REACHED_MID_ROW</h4>
-<pre>public static final&nbsp;<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.NextState</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html#line.416">SIZE_LIMIT_REACHED_MID_ROW</a></pre>
+<pre>public static final&nbsp;<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.NextState</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html#line.428">SIZE_LIMIT_REACHED_MID_ROW</a></pre>
 <div class="block">Special case of size limit reached to indicate that the size limit was reached in the middle
  of a row and thus a partial results was formed</div>
 </li>
@@ -309,7 +309,7 @@ the order they are declared.</div>
 <ul class="blockList">
 <li class="blockList">
 <h4>TIME_LIMIT_REACHED</h4>
-<pre>public static final&nbsp;<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.NextState</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html#line.417">TIME_LIMIT_REACHED</a></pre>
+<pre>public static final&nbsp;<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.NextState</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html#line.429">TIME_LIMIT_REACHED</a></pre>
 </li>
 </ul>
 <a name="TIME_LIMIT_REACHED_MID_ROW">
@@ -318,7 +318,7 @@ the order they are declared.</div>
 <ul class="blockList">
 <li class="blockList">
 <h4>TIME_LIMIT_REACHED_MID_ROW</h4>
-<pre>public static final&nbsp;<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.NextState</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html#line.423">TIME_LIMIT_REACHED_MID_ROW</a></pre>
+<pre>public static final&nbsp;<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.NextState</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html#line.435">TIME_LIMIT_REACHED_MID_ROW</a></pre>
 <div class="block">Special case of time limit reached to indicate that the time limit was reached in the middle
  of a row and thus a partial results was formed</div>
 </li>
@@ -329,7 +329,7 @@ the order they are declared.</div>
 <ul class="blockListLast">
 <li class="blockList">
 <h4>BATCH_LIMIT_REACHED</h4>
-<pre>public static final&nbsp;<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.NextState</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html#line.424">BATCH_LIMIT_REACHED</a></pre>
+<pre>public static final&nbsp;<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.NextState</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html#line.436">BATCH_LIMIT_REACHED</a></pre>
 </li>
 </ul>
 </li>
@@ -346,7 +346,7 @@ the order they are declared.</div>
 <ul class="blockList">
 <li class="blockList">
 <h4>moreValues</h4>
-<pre>private final&nbsp;boolean <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html#line.426">moreValues</a></pre>
+<pre>private final&nbsp;boolean <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html#line.438">moreValues</a></pre>
 </li>
 </ul>
 <a name="limitReached">
@@ -355,7 +355,7 @@ the order they are declared.</div>
 <ul class="blockListLast">
 <li class="blockList">
 <h4>limitReached</h4>
-<pre>private final&nbsp;boolean <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html#line.427">limitReached</a></pre>
+<pre>private final&nbsp;boolean <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html#line.439">limitReached</a></pre>
 </li>
 </ul>
 </li>
@@ -414,7 +414,7 @@ not permitted.)</div>
 <ul class="blockList">
 <li class="blockList">
 <h4>hasMoreValues</h4>
-<pre>public&nbsp;boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html#line.438">hasMoreValues</a>()</pre>
+<pre>public&nbsp;boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html#line.450">hasMoreValues</a>()</pre>
 <dl>
 <dt><span class="returnLabel">Returns:</span></dt>
 <dd>true when the state indicates that more values may follow those that have been
@@ -428,7 +428,7 @@ not permitted.)</div>
 <ul class="blockList">
 <li class="blockList">
 <h4>limitReached</h4>
-<pre>public&nbsp;boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html#line.445">limitReached</a>()</pre>
+<pre>public&nbsp;boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html#line.457">limitReached</a>()</pre>
 <dl>
 <dt><span class="returnLabel">Returns:</span></dt>
 <dd>true when the state indicates that a limit has been reached and scan should stop</dd>
@@ -441,7 +441,7 @@ not permitted.)</div>
 <ul class="blockList">
 <li class="blockList">
 <h4>isValidState</h4>
-<pre>public static&nbsp;boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html#line.449">isValidState</a>(<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.NextState</a>&nbsp;state)</pre>
+<pre>public static&nbsp;boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html#line.461">isValidState</a>(<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.NextState</a>&nbsp;state)</pre>
 </li>
 </ul>
 <a name="hasMoreValues-org.apache.hadoop.hbase.regionserver.ScannerContext.NextState-">
@@ -450,7 +450,7 @@ not permitted.)</div>
 <ul class="blockListLast">
 <li class="blockList">
 <h4>hasMoreValues</h4>
-<pre>public static&nbsp;boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html#line.453">hasMoreValues</a>(<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.NextState</a>&nbsp;state)</pre>
+<pre>public static&nbsp;boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html#line.465">hasMoreValues</a>(<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.NextState</a>&nbsp;state)</pre>
 </li>
 </ul>
 </li>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/regionserver/ScannerContext.ProgressFields.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/regionserver/ScannerContext.ProgressFields.html b/devapidocs/org/apache/hadoop/hbase/regionserver/ScannerContext.ProgressFields.html
index 4147bce..515d3f9 100644
--- a/devapidocs/org/apache/hadoop/hbase/regionserver/ScannerContext.ProgressFields.html
+++ b/devapidocs/org/apache/hadoop/hbase/regionserver/ScannerContext.ProgressFields.html
@@ -113,7 +113,7 @@ var activeTableTab = "activeTableTab";
 </dl>
 <hr>
 <br>
-<pre>private static class <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.679">ScannerContext.ProgressFields</a>
+<pre>private static class <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.686">ScannerContext.ProgressFields</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>
 </li>
 </ul>
@@ -168,11 +168,6 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <th class="colOne" scope="col">Constructor and Description</th>
 </tr>
 <tr class="altColor">
-<td class="colOne"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.ProgressFields.html#ProgressFields--">ProgressFields</a></span>()</code>
-<div class="block">Fields keep their default values.</div>
-</td>
-</tr>
-<tr class="rowColor">
 <td class="colOne"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.ProgressFields.html#ProgressFields-int-long-long-">ProgressFields</a></span>(int&nbsp;batch,
               long&nbsp;size,
               long&nbsp;heapSize)</code>&nbsp;</td>
@@ -256,7 +251,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>DEFAULT_BATCH</h4>
-<pre>private static&nbsp;int <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.ProgressFields.html#line.681">DEFAULT_BATCH</a></pre>
+<pre>private static&nbsp;int <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.ProgressFields.html#line.688">DEFAULT_BATCH</a></pre>
 </li>
 </ul>
 <a name="DEFAULT_SIZE">
@@ -265,7 +260,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>DEFAULT_SIZE</h4>
-<pre>private static&nbsp;long <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.ProgressFields.html#line.682">DEFAULT_SIZE</a></pre>
+<pre>private static&nbsp;long <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.ProgressFields.html#line.689">DEFAULT_SIZE</a></pre>
 </li>
 </ul>
 <a name="batch">
@@ -274,7 +269,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>batch</h4>
-<pre>int <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.ProgressFields.html#line.686">batch</a></pre>
+<pre>int <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.ProgressFields.html#line.693">batch</a></pre>
 </li>
 </ul>
 <a name="dataSize">
@@ -283,7 +278,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>dataSize</h4>
-<pre>long <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.ProgressFields.html#line.689">dataSize</a></pre>
+<pre>long <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.ProgressFields.html#line.696">dataSize</a></pre>
 </li>
 </ul>
 <a name="heapSize">
@@ -292,7 +287,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>heapSize</h4>
-<pre>long <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.ProgressFields.html#line.692">heapSize</a></pre>
+<pre>long <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.ProgressFields.html#line.699">heapSize</a></pre>
 </li>
 </ul>
 </li>
@@ -303,23 +298,13 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <!--   -->
 </a>
 <h3>Constructor Detail</h3>
-<a name="ProgressFields--">
-<!--   -->
-</a>
-<ul class="blockList">
-<li class="blockList">
-<h4>ProgressFields</h4>
-<pre><a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.ProgressFields.html#line.697">ProgressFields</a>()</pre>
-<div class="block">Fields keep their default values.</div>
-</li>
-</ul>
 <a name="ProgressFields-int-long-long-">
 <!--   -->
 </a>
 <ul class="blockListLast">
 <li class="blockList">
 <h4>ProgressFields</h4>
-<pre><a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.ProgressFields.html#line.700">ProgressFields</a>(int&nbsp;batch,
+<pre><a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.ProgressFields.html#line.701">ProgressFields</a>(int&nbsp;batch,
                long&nbsp;size,
                long&nbsp;heapSize)</pre>
 </li>
@@ -338,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>setFields</h4>
-<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.ProgressFields.html#line.707">setFields</a>(int&nbsp;batch,
+<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.ProgressFields.html#line.708">setFields</a>(int&nbsp;batch,
                long&nbsp;dataSize,
                long&nbsp;heapSize)</pre>
 <div class="block">Set all fields together.</div>
@@ -350,7 +335,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getBatch</h4>
-<pre>int&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.ProgressFields.html#line.713">getBatch</a>()</pre>
+<pre>int&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.ProgressFields.html#line.714">getBatch</a>()</pre>
 </li>
 </ul>
 <a name="setBatch-int-">
@@ -359,7 +344,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>setBatch</h4>
-<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.ProgressFields.html#line.717">setBatch</a>(int&nbsp;batch)</pre>
+<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.ProgressFields.html#line.718">setBatch</a>(int&nbsp;batch)</pre>
 </li>
 </ul>
 <a name="getDataSize--">
@@ -368,7 +353,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getDataSize</h4>
-<pre>long&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.ProgressFields.html#line.721">getDataSize</a>()</pre>
+<pre>long&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.ProgressFields.html#line.722">getDataSize</a>()</pre>
 </li>
 </ul>
 <a name="getHeapSize--">
@@ -377,7 +362,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getHeapSize</h4>
-<pre>long&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.ProgressFields.html#line.725">getHeapSize</a>()</pre>
+<pre>long&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.ProgressFields.html#line.726">getHeapSize</a>()</pre>
 </li>
 </ul>
 <a name="setDataSize-long-">
@@ -386,7 +371,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>setDataSize</h4>
-<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.ProgressFields.html#line.729">setDataSize</a>(long&nbsp;dataSize)</pre>
+<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.ProgressFields.html#line.730">setDataSize</a>(long&nbsp;dataSize)</pre>
 </li>
 </ul>
 <a name="setHeapSize-long-">
@@ -395,7 +380,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>setHeapSize</h4>
-<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.ProgressFields.html#line.733">setHeapSize</a>(long&nbsp;heapSize)</pre>
+<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.ProgressFields.html#line.734">setHeapSize</a>(long&nbsp;heapSize)</pre>
 </li>
 </ul>
 <a name="toString--">
@@ -404,7 +389,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>toString</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/regionserver/ScannerContext.ProgressFields.html#line.738">toString</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/regionserver/ScannerContext.ProgressFields.html#line.739">toString</a>()</pre>
 <dl>
 <dt><span class="overrideSpecifyLabel">Overrides:</span></dt>
 <dd><code><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true#toString--" title="class or interface in java.lang">toString</a></code>&nbsp;in class&nbsp;<code><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></code></dd>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/regionserver/ScannerContext.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/regionserver/ScannerContext.html b/devapidocs/org/apache/hadoop/hbase/regionserver/ScannerContext.html
index ea280ae..24bd178 100644
--- a/devapidocs/org/apache/hadoop/hbase/regionserver/ScannerContext.html
+++ b/devapidocs/org/apache/hadoop/hbase/regionserver/ScannerContext.html
@@ -18,7 +18,7 @@
     catch(err) {
     }
 //-->
-var methods = {"i0":10,"i1":10,"i2":10,"i3":10,"i4":10,"i5":10,"i6":10,"i7":10,"i8":10,"i9":10,"i10":10,"i11":10,"i12":10,"i13":10,"i14":10,"i15":10,"i16":10,"i17":10,"i18":10,"i19":10,"i20":10,"i21":10,"i22":9,"i23":9,"i24":10,"i25":10,"i26":10,"i27":10,"i28":10,"i29":10,"i30":10,"i31":10,"i32":10};
+var methods = {"i0":10,"i1":10,"i2":10,"i3":10,"i4":10,"i5":10,"i6":10,"i7":10,"i8":10,"i9":10,"i10":10,"i11":10,"i12":10,"i13":10,"i14":10,"i15":10,"i16":10,"i17":10,"i18":10,"i19":10,"i20":10,"i21":10,"i22":9,"i23":9,"i24":10,"i25":10,"i26":10,"i27":10,"i28":10,"i29":10,"i30":10,"i31":10,"i32":10,"i33":10};
 var tabs = {65535:["t0","All Methods"],1:["t1","Static Methods"],2:["t2","Instance Methods"],8:["t4","Concrete Methods"]};
 var altColor = "altColor";
 var rowColor = "rowColor";
@@ -234,6 +234,10 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 </td>
 </tr>
 <tr class="rowColor">
+<td class="colFirst"><code>private boolean</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#returnImmediately">returnImmediately</a></span></code>&nbsp;</td>
+</tr>
+<tr class="altColor">
 <td class="colFirst"><code>(package private) <a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.NextState</a></code></td>
 <td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#scannerState">scannerState</a></span></code>
 <div class="block">The state of the scanner after the invocation of <a href="../../../../../org/apache/hadoop/hbase/regionserver/InternalScanner.html#next-java.util.List-"><code>InternalScanner.next(java.util.List)</code></a>
@@ -381,42 +385,46 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 </tr>
 <tr id="i24" class="altColor">
 <td class="colFirst"><code>(package private) void</code></td>
-<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#setBatchProgress-int-">setBatchProgress</a></span>(int&nbsp;batchProgress)</code>&nbsp;</td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#returnImmediately--">returnImmediately</a></span>()</code>&nbsp;</td>
 </tr>
 <tr id="i25" class="rowColor">
 <td class="colFirst"><code>(package private) void</code></td>
-<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#setKeepProgress-boolean-">setKeepProgress</a></span>(boolean&nbsp;keepProgress)</code>&nbsp;</td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#setBatchProgress-int-">setBatchProgress</a></span>(int&nbsp;batchProgress)</code>&nbsp;</td>
 </tr>
 <tr id="i26" class="altColor">
 <td class="colFirst"><code>(package private) void</code></td>
-<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#setLastPeekedCell-org.apache.hadoop.hbase.Cell-">setLastPeekedCell</a></span>(<a href="../../../../../org/apache/hadoop/hbase/Cell.html" title="interface in org.apache.hadoop.hbase">Cell</a>&nbsp;lastPeekedCell)</code>&nbsp;</td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#setKeepProgress-boolean-">setKeepProgress</a></span>(boolean&nbsp;keepProgress)</code>&nbsp;</td>
 </tr>
 <tr id="i27" class="rowColor">
 <td class="colFirst"><code>(package private) void</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#setLastPeekedCell-org.apache.hadoop.hbase.Cell-">setLastPeekedCell</a></span>(<a href="../../../../../org/apache/hadoop/hbase/Cell.html" title="interface in org.apache.hadoop.hbase">Cell</a>&nbsp;lastPeekedCell)</code>&nbsp;</td>
+</tr>
+<tr id="i28" class="altColor">
+<td class="colFirst"><code>(package private) void</code></td>
 <td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#setProgress-int-long-long-">setProgress</a></span>(int&nbsp;batchProgress,
            long&nbsp;sizeProgress,
            long&nbsp;heapSizeProgress)</code>&nbsp;</td>
 </tr>
-<tr id="i28" class="altColor">
+<tr id="i29" class="rowColor">
 <td class="colFirst"><code>(package private) <a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.NextState</a></code></td>
 <td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#setScannerState-org.apache.hadoop.hbase.regionserver.ScannerContext.NextState-">setScannerState</a></span>(<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.NextState</a>&nbsp;state)</code>
 <div class="block">Note that this is not a typical setter.</div>
 </td>
 </tr>
-<tr id="i29" class="rowColor">
+<tr id="i30" class="altColor">
 <td class="colFirst"><code>(package private) void</code></td>
 <td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#setSizeLimitScope-org.apache.hadoop.hbase.regionserver.ScannerContext.LimitScope-">setSizeLimitScope</a></span>(<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a>&nbsp;scope)</code>&nbsp;</td>
 </tr>
-<tr id="i30" class="altColor">
+<tr id="i31" class="rowColor">
 <td class="colFirst"><code>(package private) void</code></td>
 <td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#setSizeProgress-long-long-">setSizeProgress</a></span>(long&nbsp;dataSizeProgress,
                long&nbsp;heapSizeProgress)</code>&nbsp;</td>
 </tr>
-<tr id="i31" class="rowColor">
+<tr id="i32" class="altColor">
 <td class="colFirst"><code>(package private) void</code></td>
 <td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#setTimeLimitScope-org.apache.hadoop.hbase.regionserver.ScannerContext.LimitScope-">setTimeLimitScope</a></span>(<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a>&nbsp;scope)</code>&nbsp;</td>
 </tr>
-<tr id="i32" class="altColor">
+<tr id="i33" class="rowColor">
 <td class="colFirst"><code><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a></code></td>
 <td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#toString--">toString</a></span>()</code>&nbsp;</td>
 </tr>
@@ -536,13 +544,22 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <pre>private&nbsp;<a href="../../../../../org/apache/hadoop/hbase/Cell.html" title="interface in org.apache.hadoop.hbase">Cell</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.100">lastPeekedCell</a></pre>
 </li>
 </ul>
+<a name="returnImmediately">
+<!--   -->
+</a>
+<ul class="blockList">
+<li class="blockList">
+<h4>returnImmediately</h4>
+<pre>private&nbsp;boolean <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.106">returnImmediately</a></pre>
+</li>
+</ul>
 <a name="metrics">
 <!--   -->
 </a>
 <ul class="blockListLast">
 <li class="blockList">
 <h4>metrics</h4>
-<pre>final&nbsp;<a href="../../../../../org/apache/hadoop/hbase/client/metrics/ServerSideScanMetrics.html" title="class in org.apache.hadoop.hbase.client.metrics">ServerSideScanMetrics</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.105">metrics</a></pre>
+<pre>final&nbsp;<a href="../../../../../org/apache/hadoop/hbase/client/metrics/ServerSideScanMetrics.html" title="class in org.apache.hadoop.hbase.client.metrics">ServerSideScanMetrics</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.111">metrics</a></pre>
 <div class="block">Tracks the relevant server side metrics during scans. null when metrics should not be tracked</div>
 </li>
 </ul>
@@ -560,7 +577,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>ScannerContext</h4>
-<pre><a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.107">ScannerContext</a>(boolean&nbsp;keepProgress,
+<pre><a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.113">ScannerContext</a>(boolean&nbsp;keepProgress,
                <a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html" title="class in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitFields</a>&nbsp;limitsToCopy,
                boolean&nbsp;trackMetrics)</pre>
 </li>
@@ -579,7 +596,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>isTrackingMetrics</h4>
-<pre>boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.121">isTrackingMetrics</a>()</pre>
+<pre>boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.127">isTrackingMetrics</a>()</pre>
 </li>
 </ul>
 <a name="getMetrics--">
@@ -588,7 +605,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getMetrics</h4>
-<pre><a href="../../../../../org/apache/hadoop/hbase/client/metrics/ServerSideScanMetrics.html" title="class in org.apache.hadoop.hbase.client.metrics">ServerSideScanMetrics</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.130">getMetrics</a>()</pre>
+<pre><a href="../../../../../org/apache/hadoop/hbase/client/metrics/ServerSideScanMetrics.html" title="class in org.apache.hadoop.hbase.client.metrics">ServerSideScanMetrics</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.136">getMetrics</a>()</pre>
 <div class="block">Get the metrics instance. Should only be called after a call to <a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.html#isTrackingMetrics--"><code>isTrackingMetrics()</code></a>
  has been made to confirm that metrics are indeed being tracked.</div>
 <dl>
@@ -603,7 +620,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getKeepProgress</h4>
-<pre>boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.141">getKeepProgress</a>()</pre>
+<pre>boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.147">getKeepProgress</a>()</pre>
 <dl>
 <dt><span class="returnLabel">Returns:</span></dt>
 <dd>true if the progress tracked so far in this instance will be considered during an
@@ -619,7 +636,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>setKeepProgress</h4>
-<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.145">setKeepProgress</a>(boolean&nbsp;keepProgress)</pre>
+<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.151">setKeepProgress</a>(boolean&nbsp;keepProgress)</pre>
 </li>
 </ul>
 <a name="incrementBatchProgress-int-">
@@ -628,7 +645,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>incrementBatchProgress</h4>
-<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.152">incrementBatchProgress</a>(int&nbsp;batch)</pre>
+<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.158">incrementBatchProgress</a>(int&nbsp;batch)</pre>
 <div class="block">Progress towards the batch limit has been made. Increment internal tracking of batch progress</div>
 </li>
 </ul>
@@ -638,7 +655,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>incrementSizeProgress</h4>
-<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.160">incrementSizeProgress</a>(long&nbsp;dataSize,
+<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.166">incrementSizeProgress</a>(long&nbsp;dataSize,
                            long&nbsp;heapSize)</pre>
 <div class="block">Progress towards the size limit has been made. Increment internal tracking of size progress</div>
 </li>
@@ -649,7 +666,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getBatchProgress</h4>
-<pre>int&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.167">getBatchProgress</a>()</pre>
+<pre>int&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.173">getBatchProgress</a>()</pre>
 </li>
 </ul>
 <a name="getDataSizeProgress--">
@@ -658,7 +675,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getDataSizeProgress</h4>
-<pre>long&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.171">getDataSizeProgress</a>()</pre>
+<pre>long&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.177">getDataSizeProgress</a>()</pre>
 </li>
 </ul>
 <a name="getHeapSizeProgress--">
@@ -667,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>getHeapSizeProgress</h4>
-<pre>long&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.175">getHeapSizeProgress</a>()</pre>
+<pre>long&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.181">getHeapSizeProgress</a>()</pre>
 </li>
 </ul>
 <a name="setProgress-int-long-long-">
@@ -676,7 +693,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>setProgress</h4>
-<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.179">setProgress</a>(int&nbsp;batchProgress,
+<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.185">setProgress</a>(int&nbsp;batchProgress,
                  long&nbsp;sizeProgress,
                  long&nbsp;heapSizeProgress)</pre>
 </li>
@@ -687,7 +704,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>setSizeProgress</h4>
-<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.184">setSizeProgress</a>(long&nbsp;dataSizeProgress,
+<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.190">setSizeProgress</a>(long&nbsp;dataSizeProgress,
                      long&nbsp;heapSizeProgress)</pre>
 </li>
 </ul>
@@ -697,7 +714,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>setBatchProgress</h4>
-<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.189">setBatchProgress</a>(int&nbsp;batchProgress)</pre>
+<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.195">setBatchProgress</a>(int&nbsp;batchProgress)</pre>
 </li>
 </ul>
 <a name="clearProgress--">
@@ -706,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>clearProgress</h4>
-<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.197">clearProgress</a>()</pre>
+<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.203">clearProgress</a>()</pre>
 <div class="block">Clear away any progress that has been made so far. All progress fields are reset to initial
  values</div>
 </li>
@@ -717,7 +734,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>setScannerState</h4>
-<pre><a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.NextState</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.209">setScannerState</a>(<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.NextState</a>&nbsp;state)</pre>
+<pre><a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.NextState</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.215">setScannerState</a>(<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.NextState</a>&nbsp;state)</pre>
 <div class="block">Note that this is not a typical setter. This setter returns the <a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html" title="enum in org.apache.hadoop.hbase.regionserver"><code>ScannerContext.NextState</code></a> that was
  passed in so that methods can be invoked against the new state. Furthermore, this pattern
  allows the <a href="../../../../../org/apache/hadoop/hbase/regionserver/NoLimitScannerContext.html" title="class in org.apache.hadoop.hbase.regionserver"><code>NoLimitScannerContext</code></a> to cleanly override this setter and simply return the
@@ -736,7 +753,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>mayHaveMoreCellsInRow</h4>
-<pre>boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.222">mayHaveMoreCellsInRow</a>()</pre>
+<pre>boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.228">mayHaveMoreCellsInRow</a>()</pre>
 <dl>
 <dt><span class="returnLabel">Returns:</span></dt>
 <dd>true when we have more cells for the current row. This usually because we have reached
@@ -750,7 +767,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>hasBatchLimit</h4>
-<pre>boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.232">hasBatchLimit</a>(<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a>&nbsp;checkerScope)</pre>
+<pre>boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.238">hasBatchLimit</a>(<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a>&nbsp;checkerScope)</pre>
 <dl>
 <dt><span class="paramLabel">Parameters:</span></dt>
 <dd><code>checkerScope</code> - </dd>
@@ -765,7 +782,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>hasSizeLimit</h4>
-<pre>boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.240">hasSizeLimit</a>(<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a>&nbsp;checkerScope)</pre>
+<pre>boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.246">hasSizeLimit</a>(<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a>&nbsp;checkerScope)</pre>
 <dl>
 <dt><span class="paramLabel">Parameters:</span></dt>
 <dd><code>checkerScope</code> - </dd>
@@ -780,7 +797,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>hasTimeLimit</h4>
-<pre>boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.249">hasTimeLimit</a>(<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a>&nbsp;checkerScope)</pre>
+<pre>boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.255">hasTimeLimit</a>(<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a>&nbsp;checkerScope)</pre>
 <dl>
 <dt><span class="paramLabel">Parameters:</span></dt>
 <dd><code>checkerScope</code> - </dd>
@@ -795,7 +812,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>hasAnyLimit</h4>
-<pre>boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.257">hasAnyLimit</a>(<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a>&nbsp;checkerScope)</pre>
+<pre>boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.264">hasAnyLimit</a>(<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a>&nbsp;checkerScope)</pre>
 <dl>
 <dt><span class="paramLabel">Parameters:</span></dt>
 <dd><code>checkerScope</code> - </dd>
@@ -810,7 +827,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>setSizeLimitScope</h4>
-<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.264">setSizeLimitScope</a>(<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a>&nbsp;scope)</pre>
+<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.271">setSizeLimitScope</a>(<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a>&nbsp;scope)</pre>
 <dl>
 <dt><span class="paramLabel">Parameters:</span></dt>
 <dd><code>scope</code> - The scope in which the size limit will be enforced</dd>
@@ -823,7 +840,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>setTimeLimitScope</h4>
-<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.271">setTimeLimitScope</a>(<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a>&nbsp;scope)</pre>
+<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.278">setTimeLimitScope</a>(<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a>&nbsp;scope)</pre>
 <dl>
 <dt><span class="paramLabel">Parameters:</span></dt>
 <dd><code>scope</code> - The scope in which the time limit will be enforced</dd>
@@ -836,7 +853,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getBatchLimit</h4>
-<pre>int&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.275">getBatchLimit</a>()</pre>
+<pre>int&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.282">getBatchLimit</a>()</pre>
 </li>
 </ul>
 <a name="getDataSizeLimit--">
@@ -845,7 +862,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getDataSizeLimit</h4>
-<pre>long&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.279">getDataSizeLimit</a>()</pre>
+<pre>long&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.286">getDataSizeLimit</a>()</pre>
 </li>
 </ul>
 <a name="getTimeLimit--">
@@ -854,7 +871,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getTimeLimit</h4>
-<pre>long&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.283">getTimeLimit</a>()</pre>
+<pre>long&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.290">getTimeLimit</a>()</pre>
 </li>
 </ul>
 <a name="checkBatchLimit-org.apache.hadoop.hbase.regionserver.ScannerContext.LimitScope-">
@@ -863,7 +880,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>checkBatchLimit</h4>
-<pre>boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.291">checkBatchLimit</a>(<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a>&nbsp;checkerScope)</pre>
+<pre>boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.298">checkBatchLimit</a>(<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a>&nbsp;checkerScope)</pre>
 <dl>
 <dt><span class="paramLabel">Parameters:</span></dt>
 <dd><code>checkerScope</code> - The scope that the limit is being checked from</dd>
@@ -878,7 +895,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>checkSizeLimit</h4>
-<pre>boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.299">checkSizeLimit</a>(<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a>&nbsp;checkerScope)</pre>
+<pre>boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.306">checkSizeLimit</a>(<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a>&nbsp;checkerScope)</pre>
 <dl>
 <dt><span class="paramLabel">Parameters:</span></dt>
 <dd><code>checkerScope</code> - The scope that the limit is being checked from</dd>
@@ -893,7 +910,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>checkTimeLimit</h4>
-<pre>boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.309">checkTimeLimit</a>(<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a>&nbsp;checkerScope)</pre>
+<pre>boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.316">checkTimeLimit</a>(<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a>&nbsp;checkerScope)</pre>
 <dl>
 <dt><span class="paramLabel">Parameters:</span></dt>
 <dd><code>checkerScope</code> - The scope that the limit is being checked from. The time limit is always
@@ -909,7 +926,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>checkAnyLimitReached</h4>
-<pre>boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.317">checkAnyLimitReached</a>(<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a>&nbsp;checkerScope)</pre>
+<pre>boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.325">checkAnyLimitReached</a>(<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver">ScannerContext.LimitScope</a>&nbsp;checkerScope)</pre>
 <dl>
 <dt><span class="paramLabel">Parameters:</span></dt>
 <dd><code>checkerScope</code> - The scope that the limits are being checked from</dd>
@@ -924,7 +941,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getLastPeekedCell</h4>
-<pre><a href="../../../../../org/apache/hadoop/hbase/Cell.html" title="interface in org.apache.hadoop.hbase">Cell</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.322">getLastPeekedCell</a>()</pre>
+<pre><a href="../../../../../org/apache/hadoop/hbase/Cell.html" title="interface in org.apache.hadoop.hbase">Cell</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.330">getLastPeekedCell</a>()</pre>
 </li>
 </ul>
 <a name="setLastPeekedCell-org.apache.hadoop.hbase.Cell-">
@@ -933,7 +950,16 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>setLastPeekedCell</h4>
-<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.326">setLastPeekedCell</a>(<a href="../../../../../org/apache/hadoop/hbase/Cell.html" title="interface in org.apache.hadoop.hbase">Cell</a>&nbsp;lastPeekedCell)</pre>
+<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.334">setLastPeekedCell</a>(<a href="../../../../../org/apache/hadoop/hbase/Cell.html" title="interface in org.apache.hadoop.hbase">Cell</a>&nbsp;lastPeekedCell)</pre>
+</li>
+</ul>
+<a name="returnImmediately--">
+<!--   -->
+</a>
+<ul class="blockList">
+<li class="blockList">
+<h4>returnImmediately</h4>
+<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.338">returnImmediately</a>()</pre>
 </li>
 </ul>
 <a name="toString--">
@@ -942,7 +968,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>toString</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/regionserver/ScannerContext.html#line.331">toString</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/regionserver/ScannerContext.html#line.343">toString</a>()</pre>
 <dl>
 <dt><span class="overrideSpecifyLabel">Overrides:</span></dt>
 <dd><code><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true#toString--" title="class or interface in java.lang">toString</a></code>&nbsp;in class&nbsp;<code><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></code></dd>
@@ -955,7 +981,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>newBuilder</h4>
-<pre>public static&nbsp;<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.Builder.html" title="class in org.apache.hadoop.hbase.regionserver">ScannerContext.Builder</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.351">newBuilder</a>()</pre>
+<pre>public static&nbsp;<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.Builder.html" title="class in org.apache.hadoop.hbase.regionserver">ScannerContext.Builder</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.363">newBuilder</a>()</pre>
 </li>
 </ul>
 <a name="newBuilder-boolean-">
@@ -964,7 +990,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>newBuilder</h4>
-<pre>public static&nbsp;<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.Builder.html" title="class in org.apache.hadoop.hbase.regionserver">ScannerContext.Builder</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.355">newBuilder</a>(boolean&nbsp;keepProgress)</pre>
+<pre>public static&nbsp;<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.Builder.html" title="class in org.apache.hadoop.hbase.regionserver">ScannerContext.Builder</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.html#line.367">newBuilder</a>(boolean&nbsp;keepProgress)</pre>
 </li>
 </ul>
 </li>


[38/50] hbase-site git commit: Published site at 26babcf013de696b899d76a3c39434b794440d8d.

Posted by gi...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.BlockWritable.html
----------------------------------------------------------------------
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.BlockWritable.html b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.BlockWritable.html
index 97ceefd..b7b4236 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.BlockWritable.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.BlockWritable.html
@@ -103,8 +103,8 @@
 <span class="sourceLineNo">095</span> * Caches cache whole blocks with trailing checksums if any. We then tag on some metadata, the<a name="line.95"></a>
 <span class="sourceLineNo">096</span> * content of BLOCK_METADATA_SPACE which will be flag on if we are doing 'hbase'<a name="line.96"></a>
 <span class="sourceLineNo">097</span> * checksums and then the offset into the file which is needed when we re-make a cache key<a name="line.97"></a>
-<span class="sourceLineNo">098</span> * when we return the block to the cache as 'done'. See {@link Cacheable#serialize(ByteBuffer)} and<a name="line.98"></a>
-<span class="sourceLineNo">099</span> * {@link Cacheable#getDeserializer()}.<a name="line.99"></a>
+<span class="sourceLineNo">098</span> * when we return the block to the cache as 'done'.<a name="line.98"></a>
+<span class="sourceLineNo">099</span> * See {@link Cacheable#serialize(ByteBuffer, boolean)} and {@link Cacheable#getDeserializer()}.<a name="line.99"></a>
 <span class="sourceLineNo">100</span> *<a name="line.100"></a>
 <span class="sourceLineNo">101</span> * &lt;p&gt;TODO: Should we cache the checksums? Down in Writer#getBlockForCaching(CacheConfig) where<a name="line.101"></a>
 <span class="sourceLineNo">102</span> * we make a block to cache-on-write, there is an attempt at turning off checksums. This is not the<a name="line.102"></a>
@@ -333,1579 +333,1579 @@
 <span class="sourceLineNo">325</span>   * Creates a new {@link HFile} block from the given fields. This constructor<a name="line.325"></a>
 <span class="sourceLineNo">326</span>   * is used only while writing blocks and caching,<a name="line.326"></a>
 <span class="sourceLineNo">327</span>   * and is sitting in a byte buffer and we want to stuff the block into cache.<a name="line.327"></a>
-<span class="sourceLineNo">328</span>   * See {@link Writer#getBlockForCaching(CacheConfig)}.<a name="line.328"></a>
-<span class="sourceLineNo">329</span>   *<a name="line.329"></a>
-<span class="sourceLineNo">330</span>   * &lt;p&gt;TODO: The caller presumes no checksumming<a name="line.330"></a>
-<span class="sourceLineNo">331</span>   * required of this block instance since going into cache; checksum already verified on<a name="line.331"></a>
-<span class="sourceLineNo">332</span>   * underlying block data pulled in from filesystem. Is that correct? What if cache is SSD?<a name="line.332"></a>
-<span class="sourceLineNo">333</span>   *<a name="line.333"></a>
-<span class="sourceLineNo">334</span>   * @param blockType the type of this block, see {@link BlockType}<a name="line.334"></a>
-<span class="sourceLineNo">335</span>   * @param onDiskSizeWithoutHeader see {@link #onDiskSizeWithoutHeader}<a name="line.335"></a>
-<span class="sourceLineNo">336</span>   * @param uncompressedSizeWithoutHeader see {@link #uncompressedSizeWithoutHeader}<a name="line.336"></a>
-<span class="sourceLineNo">337</span>   * @param prevBlockOffset see {@link #prevBlockOffset}<a name="line.337"></a>
-<span class="sourceLineNo">338</span>   * @param b block header ({@link HConstants#HFILEBLOCK_HEADER_SIZE} bytes)<a name="line.338"></a>
-<span class="sourceLineNo">339</span>   * @param fillHeader when true, write the first 4 header fields into passed buffer.<a name="line.339"></a>
-<span class="sourceLineNo">340</span>   * @param offset the file offset the block was read from<a name="line.340"></a>
-<span class="sourceLineNo">341</span>   * @param onDiskDataSizeWithHeader see {@link #onDiskDataSizeWithHeader}<a name="line.341"></a>
-<span class="sourceLineNo">342</span>   * @param fileContext HFile meta data<a name="line.342"></a>
-<span class="sourceLineNo">343</span>   */<a name="line.343"></a>
-<span class="sourceLineNo">344</span>  HFileBlock(BlockType blockType, int onDiskSizeWithoutHeader, int uncompressedSizeWithoutHeader,<a name="line.344"></a>
-<span class="sourceLineNo">345</span>      long prevBlockOffset, ByteBuffer b, boolean fillHeader, long offset,<a name="line.345"></a>
-<span class="sourceLineNo">346</span>      final int nextBlockOnDiskSize, int onDiskDataSizeWithHeader, HFileContext fileContext) {<a name="line.346"></a>
-<span class="sourceLineNo">347</span>    init(blockType, onDiskSizeWithoutHeader, uncompressedSizeWithoutHeader,<a name="line.347"></a>
-<span class="sourceLineNo">348</span>        prevBlockOffset, offset, onDiskDataSizeWithHeader, nextBlockOnDiskSize, fileContext);<a name="line.348"></a>
-<span class="sourceLineNo">349</span>    this.buf = new SingleByteBuff(b);<a name="line.349"></a>
-<span class="sourceLineNo">350</span>    if (fillHeader) {<a name="line.350"></a>
-<span class="sourceLineNo">351</span>      overwriteHeader();<a name="line.351"></a>
-<span class="sourceLineNo">352</span>    }<a name="line.352"></a>
-<span class="sourceLineNo">353</span>    this.buf.rewind();<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>  /**<a name="line.356"></a>
-<span class="sourceLineNo">357</span>   * Creates a block from an existing buffer starting with a header. Rewinds<a name="line.357"></a>
-<span class="sourceLineNo">358</span>   * and takes ownership of the buffer. By definition of rewind, ignores the<a name="line.358"></a>
-<span class="sourceLineNo">359</span>   * buffer position, but if you slice the buffer beforehand, it will rewind<a name="line.359"></a>
-<span class="sourceLineNo">360</span>   * to that point.<a name="line.360"></a>
-<span class="sourceLineNo">361</span>   * @param buf Has header, content, and trailing checksums if present.<a name="line.361"></a>
-<span class="sourceLineNo">362</span>   */<a name="line.362"></a>
-<span class="sourceLineNo">363</span>  HFileBlock(ByteBuff buf, boolean usesHBaseChecksum, MemoryType memType, final long offset,<a name="line.363"></a>
-<span class="sourceLineNo">364</span>      final int nextBlockOnDiskSize, HFileContext fileContext) throws IOException {<a name="line.364"></a>
-<span class="sourceLineNo">365</span>    buf.rewind();<a name="line.365"></a>
-<span class="sourceLineNo">366</span>    final BlockType blockType = BlockType.read(buf);<a name="line.366"></a>
-<span class="sourceLineNo">367</span>    final int onDiskSizeWithoutHeader = buf.getInt(Header.ON_DISK_SIZE_WITHOUT_HEADER_INDEX);<a name="line.367"></a>
-<span class="sourceLineNo">368</span>    final int uncompressedSizeWithoutHeader =<a name="line.368"></a>
-<span class="sourceLineNo">369</span>        buf.getInt(Header.UNCOMPRESSED_SIZE_WITHOUT_HEADER_INDEX);<a name="line.369"></a>
-<span class="sourceLineNo">370</span>    final long prevBlockOffset = buf.getLong(Header.PREV_BLOCK_OFFSET_INDEX);<a name="line.370"></a>
-<span class="sourceLineNo">371</span>    // This constructor is called when we deserialize a block from cache and when we read a block in<a name="line.371"></a>
-<span class="sourceLineNo">372</span>    // from the fs. fileCache is null when deserialized from cache so need to make up one.<a name="line.372"></a>
-<span class="sourceLineNo">373</span>    HFileContextBuilder fileContextBuilder = fileContext != null?<a name="line.373"></a>
-<span class="sourceLineNo">374</span>        new HFileContextBuilder(fileContext): new HFileContextBuilder();<a name="line.374"></a>
-<span class="sourceLineNo">375</span>    fileContextBuilder.withHBaseCheckSum(usesHBaseChecksum);<a name="line.375"></a>
-<span class="sourceLineNo">376</span>    int onDiskDataSizeWithHeader;<a name="line.376"></a>
-<span class="sourceLineNo">377</span>    if (usesHBaseChecksum) {<a name="line.377"></a>
-<span class="sourceLineNo">378</span>      byte checksumType = buf.get(Header.CHECKSUM_TYPE_INDEX);<a name="line.378"></a>
-<span class="sourceLineNo">379</span>      int bytesPerChecksum = buf.getInt(Header.BYTES_PER_CHECKSUM_INDEX);<a name="line.379"></a>
-<span class="sourceLineNo">380</span>      onDiskDataSizeWithHeader = buf.getInt(Header.ON_DISK_DATA_SIZE_WITH_HEADER_INDEX);<a name="line.380"></a>
-<span class="sourceLineNo">381</span>      // Use the checksum type and bytes per checksum from header, not from filecontext.<a name="line.381"></a>
-<span class="sourceLineNo">382</span>      fileContextBuilder.withChecksumType(ChecksumType.codeToType(checksumType));<a name="line.382"></a>
-<span class="sourceLineNo">383</span>      fileContextBuilder.withBytesPerCheckSum(bytesPerChecksum);<a name="line.383"></a>
-<span class="sourceLineNo">384</span>    } else {<a name="line.384"></a>
-<span class="sourceLineNo">385</span>      fileContextBuilder.withChecksumType(ChecksumType.NULL);<a name="line.385"></a>
-<span class="sourceLineNo">386</span>      fileContextBuilder.withBytesPerCheckSum(0);<a name="line.386"></a>
-<span class="sourceLineNo">387</span>      // Need to fix onDiskDataSizeWithHeader; there are not checksums after-block-data<a name="line.387"></a>
-<span class="sourceLineNo">388</span>      onDiskDataSizeWithHeader = onDiskSizeWithoutHeader + headerSize(usesHBaseChecksum);<a name="line.388"></a>
-<span class="sourceLineNo">389</span>    }<a name="line.389"></a>
-<span class="sourceLineNo">390</span>    fileContext = fileContextBuilder.build();<a name="line.390"></a>
-<span class="sourceLineNo">391</span>    assert usesHBaseChecksum == fileContext.isUseHBaseChecksum();<a name="line.391"></a>
-<span class="sourceLineNo">392</span>    init(blockType, onDiskSizeWithoutHeader, uncompressedSizeWithoutHeader,<a name="line.392"></a>
-<span class="sourceLineNo">393</span>        prevBlockOffset, offset, onDiskDataSizeWithHeader, nextBlockOnDiskSize, fileContext);<a name="line.393"></a>
-<span class="sourceLineNo">394</span>    this.memType = memType;<a name="line.394"></a>
-<span class="sourceLineNo">395</span>    this.offset = offset;<a name="line.395"></a>
-<span class="sourceLineNo">396</span>    this.buf = buf;<a name="line.396"></a>
-<span class="sourceLineNo">397</span>    this.buf.rewind();<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>  /**<a name="line.400"></a>
-<span class="sourceLineNo">401</span>   * Called from constructors.<a name="line.401"></a>
-<span class="sourceLineNo">402</span>   */<a name="line.402"></a>
-<span class="sourceLineNo">403</span>  private void init(BlockType blockType, int onDiskSizeWithoutHeader,<a name="line.403"></a>
-<span class="sourceLineNo">404</span>      int uncompressedSizeWithoutHeader, long prevBlockOffset,<a name="line.404"></a>
-<span class="sourceLineNo">405</span>      long offset, int onDiskDataSizeWithHeader, final int nextBlockOnDiskSize,<a name="line.405"></a>
-<span class="sourceLineNo">406</span>      HFileContext fileContext) {<a name="line.406"></a>
-<span class="sourceLineNo">407</span>    this.blockType = blockType;<a name="line.407"></a>
-<span class="sourceLineNo">408</span>    this.onDiskSizeWithoutHeader = onDiskSizeWithoutHeader;<a name="line.408"></a>
-<span class="sourceLineNo">409</span>    this.uncompressedSizeWithoutHeader = uncompressedSizeWithoutHeader;<a name="line.409"></a>
-<span class="sourceLineNo">410</span>    this.prevBlockOffset = prevBlockOffset;<a name="line.410"></a>
-<span class="sourceLineNo">411</span>    this.offset = offset;<a name="line.411"></a>
-<span class="sourceLineNo">412</span>    this.onDiskDataSizeWithHeader = onDiskDataSizeWithHeader;<a name="line.412"></a>
-<span class="sourceLineNo">413</span>    this.nextBlockOnDiskSize = nextBlockOnDiskSize;<a name="line.413"></a>
-<span class="sourceLineNo">414</span>    this.fileContext = fileContext;<a name="line.414"></a>
-<span class="sourceLineNo">415</span>  }<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">418</span>   * Parse total on disk size including header and checksum.<a name="line.418"></a>
-<span class="sourceLineNo">419</span>   * @param headerBuf Header ByteBuffer. Presumed exact size of header.<a name="line.419"></a>
-<span class="sourceLineNo">420</span>   * @param verifyChecksum true if checksum verification is in use.<a name="line.420"></a>
-<span class="sourceLineNo">421</span>   * @return Size of the block with header included.<a name="line.421"></a>
-<span class="sourceLineNo">422</span>   */<a name="line.422"></a>
-<span class="sourceLineNo">423</span>  private static int getOnDiskSizeWithHeader(final ByteBuffer headerBuf,<a name="line.423"></a>
-<span class="sourceLineNo">424</span>      boolean verifyChecksum) {<a name="line.424"></a>
-<span class="sourceLineNo">425</span>    return headerBuf.getInt(Header.ON_DISK_SIZE_WITHOUT_HEADER_INDEX) +<a name="line.425"></a>
-<span class="sourceLineNo">426</span>      headerSize(verifyChecksum);<a name="line.426"></a>
-<span class="sourceLineNo">427</span>  }<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>   * @return the on-disk size of the next block (including the header size and any checksums if<a name="line.430"></a>
-<span class="sourceLineNo">431</span>   * present) read by peeking into the next block's header; use as a hint when doing<a name="line.431"></a>
-<span class="sourceLineNo">432</span>   * a read of the next block when scanning or running over a file.<a name="line.432"></a>
-<span class="sourceLineNo">433</span>   */<a name="line.433"></a>
-<span class="sourceLineNo">434</span>  int getNextBlockOnDiskSize() {<a name="line.434"></a>
-<span class="sourceLineNo">435</span>    return nextBlockOnDiskSize;<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>  @Override<a name="line.438"></a>
-<span class="sourceLineNo">439</span>  public BlockType getBlockType() {<a name="line.439"></a>
-<span class="sourceLineNo">440</span>    return blockType;<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>  /** @return get data block encoding id that was used to encode this block */<a name="line.443"></a>
-<span class="sourceLineNo">444</span>  short getDataBlockEncodingId() {<a name="line.444"></a>
-<span class="sourceLineNo">445</span>    if (blockType != BlockType.ENCODED_DATA) {<a name="line.445"></a>
-<span class="sourceLineNo">446</span>      throw new IllegalArgumentException("Querying encoder ID of a block " +<a name="line.446"></a>
-<span class="sourceLineNo">447</span>          "of type other than " + BlockType.ENCODED_DATA + ": " + blockType);<a name="line.447"></a>
-<span class="sourceLineNo">448</span>    }<a name="line.448"></a>
-<span class="sourceLineNo">449</span>    return buf.getShort(headerSize());<a name="line.449"></a>
-<span class="sourceLineNo">450</span>  }<a name="line.450"></a>
-<span class="sourceLineNo">451</span><a name="line.451"></a>
-<span class="sourceLineNo">452</span>  /**<a name="line.452"></a>
-<span class="sourceLineNo">453</span>   * @return the on-disk size of header + data part + checksum.<a name="line.453"></a>
-<span class="sourceLineNo">454</span>   */<a name="line.454"></a>
-<span class="sourceLineNo">455</span>  public int getOnDiskSizeWithHeader() {<a name="line.455"></a>
-<span class="sourceLineNo">456</span>    return onDiskSizeWithoutHeader + headerSize();<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>   * @return the on-disk size of the data part + checksum (header excluded).<a name="line.460"></a>
-<span class="sourceLineNo">461</span>   */<a name="line.461"></a>
-<span class="sourceLineNo">462</span>  int getOnDiskSizeWithoutHeader() {<a name="line.462"></a>
-<span class="sourceLineNo">463</span>    return onDiskSizeWithoutHeader;<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>  /**<a name="line.466"></a>
-<span class="sourceLineNo">467</span>   * @return the uncompressed size of data part (header and checksum excluded).<a name="line.467"></a>
-<span class="sourceLineNo">468</span>   */<a name="line.468"></a>
-<span class="sourceLineNo">469</span>   int getUncompressedSizeWithoutHeader() {<a name="line.469"></a>
-<span class="sourceLineNo">470</span>    return uncompressedSizeWithoutHeader;<a name="line.470"></a>
-<span class="sourceLineNo">471</span>  }<a name="line.471"></a>
-<span class="sourceLineNo">472</span><a name="line.472"></a>
-<span class="sourceLineNo">473</span>  /**<a name="line.473"></a>
-<span class="sourceLineNo">474</span>   * @return the offset of the previous block of the same type in the file, or<a name="line.474"></a>
-<span class="sourceLineNo">475</span>   *         -1 if unknown<a name="line.475"></a>
-<span class="sourceLineNo">476</span>   */<a name="line.476"></a>
-<span class="sourceLineNo">477</span>  long getPrevBlockOffset() {<a name="line.477"></a>
-<span class="sourceLineNo">478</span>    return prevBlockOffset;<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>   * Rewinds {@code buf} and writes first 4 header fields. {@code buf} position<a name="line.482"></a>
-<span class="sourceLineNo">483</span>   * is modified as side-effect.<a name="line.483"></a>
-<span class="sourceLineNo">484</span>   */<a name="line.484"></a>
-<span class="sourceLineNo">485</span>  private void overwriteHeader() {<a name="line.485"></a>
-<span class="sourceLineNo">486</span>    buf.rewind();<a name="line.486"></a>
-<span class="sourceLineNo">487</span>    blockType.write(buf);<a name="line.487"></a>
-<span class="sourceLineNo">488</span>    buf.putInt(onDiskSizeWithoutHeader);<a name="line.488"></a>
-<span class="sourceLineNo">489</span>    buf.putInt(uncompressedSizeWithoutHeader);<a name="line.489"></a>
-<span class="sourceLineNo">490</span>    buf.putLong(prevBlockOffset);<a name="line.490"></a>
-<span class="sourceLineNo">491</span>    if (this.fileContext.isUseHBaseChecksum()) {<a name="line.491"></a>
-<span class="sourceLineNo">492</span>      buf.put(fileContext.getChecksumType().getCode());<a name="line.492"></a>
-<span class="sourceLineNo">493</span>      buf.putInt(fileContext.getBytesPerChecksum());<a name="line.493"></a>
-<span class="sourceLineNo">494</span>      buf.putInt(onDiskDataSizeWithHeader);<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>  /**<a name="line.498"></a>
-<span class="sourceLineNo">499</span>   * Returns a buffer that does not include the header or checksum.<a name="line.499"></a>
-<span class="sourceLineNo">500</span>   *<a name="line.500"></a>
-<span class="sourceLineNo">501</span>   * @return the buffer with header skipped and checksum omitted.<a name="line.501"></a>
-<span class="sourceLineNo">502</span>   */<a name="line.502"></a>
-<span class="sourceLineNo">503</span>  public ByteBuff getBufferWithoutHeader() {<a name="line.503"></a>
-<span class="sourceLineNo">504</span>    ByteBuff dup = getBufferReadOnly();<a name="line.504"></a>
-<span class="sourceLineNo">505</span>    // Now set it up so Buffer spans content only -- no header or no checksums.<a name="line.505"></a>
-<span class="sourceLineNo">506</span>    return dup.position(headerSize()).limit(buf.limit() - totalChecksumBytes()).slice();<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 a read-only duplicate of the buffer this block stores internally ready to be read.<a name="line.510"></a>
-<span class="sourceLineNo">511</span>   * Clients must not modify the buffer object though they may set position and limit on the<a name="line.511"></a>
-<span class="sourceLineNo">512</span>   * returned buffer since we pass back a duplicate. This method has to be public because it is used<a name="line.512"></a>
-<span class="sourceLineNo">513</span>   * in {@link CompoundBloomFilter} to avoid object creation on every Bloom<a name="line.513"></a>
-<span class="sourceLineNo">514</span>   * filter lookup, but has to be used with caution. Buffer holds header, block content,<a name="line.514"></a>
-<span class="sourceLineNo">515</span>   * and any follow-on checksums if present.<a name="line.515"></a>
-<span class="sourceLineNo">516</span>   *<a name="line.516"></a>
-<span class="sourceLineNo">517</span>   * @return the buffer of this block for read-only operations<a name="line.517"></a>
-<span class="sourceLineNo">518</span>   */<a name="line.518"></a>
-<span class="sourceLineNo">519</span>  public ByteBuff getBufferReadOnly() {<a name="line.519"></a>
-<span class="sourceLineNo">520</span>    // TODO: ByteBuf does not support asReadOnlyBuffer(). Fix.<a name="line.520"></a>
-<span class="sourceLineNo">521</span>    ByteBuff dup = this.buf.duplicate();<a name="line.521"></a>
-<span class="sourceLineNo">522</span>    assert dup.position() == 0;<a name="line.522"></a>
-<span class="sourceLineNo">523</span>    return dup;<a name="line.523"></a>
-<span class="sourceLineNo">524</span>  }<a name="line.524"></a>
-<span class="sourceLineNo">525</span><a name="line.525"></a>
-<span class="sourceLineNo">526</span>  @VisibleForTesting<a name="line.526"></a>
-<span class="sourceLineNo">527</span>  private void sanityCheckAssertion(long valueFromBuf, long valueFromField,<a name="line.527"></a>
-<span class="sourceLineNo">528</span>      String fieldName) throws IOException {<a name="line.528"></a>
-<span class="sourceLineNo">529</span>    if (valueFromBuf != valueFromField) {<a name="line.529"></a>
-<span class="sourceLineNo">530</span>      throw new AssertionError(fieldName + " in the buffer (" + valueFromBuf<a name="line.530"></a>
-<span class="sourceLineNo">531</span>          + ") is different from that in the field (" + valueFromField + ")");<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>  @VisibleForTesting<a name="line.535"></a>
-<span class="sourceLineNo">536</span>  private void sanityCheckAssertion(BlockType valueFromBuf, BlockType valueFromField)<a name="line.536"></a>
-<span class="sourceLineNo">537</span>      throws IOException {<a name="line.537"></a>
-<span class="sourceLineNo">538</span>    if (valueFromBuf != valueFromField) {<a name="line.538"></a>
-<span class="sourceLineNo">539</span>      throw new IOException("Block type stored in the buffer: " +<a name="line.539"></a>
-<span class="sourceLineNo">540</span>        valueFromBuf + ", block type field: " + valueFromField);<a name="line.540"></a>
-<span class="sourceLineNo">541</span>    }<a name="line.541"></a>
-<span class="sourceLineNo">542</span>  }<a name="line.542"></a>
-<span class="sourceLineNo">543</span><a name="line.543"></a>
-<span class="sourceLineNo">544</span>  /**<a name="line.544"></a>
-<span class="sourceLineNo">545</span>   * Checks if the block is internally consistent, i.e. the first<a name="line.545"></a>
-<span class="sourceLineNo">546</span>   * {@link HConstants#HFILEBLOCK_HEADER_SIZE} bytes of the buffer contain a<a name="line.546"></a>
-<span class="sourceLineNo">547</span>   * valid header consistent with the fields. Assumes a packed block structure.<a name="line.547"></a>
-<span class="sourceLineNo">548</span>   * This function is primary for testing and debugging, and is not<a name="line.548"></a>
-<span class="sourceLineNo">549</span>   * thread-safe, because it alters the internal buffer pointer.<a name="line.549"></a>
-<span class="sourceLineNo">550</span>   * Used by tests only.<a name="line.550"></a>
-<span class="sourceLineNo">551</span>   */<a name="line.551"></a>
-<span class="sourceLineNo">552</span>  @VisibleForTesting<a name="line.552"></a>
-<span class="sourceLineNo">553</span>  void sanityCheck() throws IOException {<a name="line.553"></a>
-<span class="sourceLineNo">554</span>    // Duplicate so no side-effects<a name="line.554"></a>
-<span class="sourceLineNo">555</span>    ByteBuff dup = this.buf.duplicate().rewind();<a name="line.555"></a>
-<span class="sourceLineNo">556</span>    sanityCheckAssertion(BlockType.read(dup), blockType);<a name="line.556"></a>
-<span class="sourceLineNo">557</span><a name="line.557"></a>
-<span class="sourceLineNo">558</span>    sanityCheckAssertion(dup.getInt(), onDiskSizeWithoutHeader, "onDiskSizeWithoutHeader");<a name="line.558"></a>
-<span class="sourceLineNo">559</span><a name="line.559"></a>
-<span class="sourceLineNo">560</span>    sanityCheckAssertion(dup.getInt(), uncompressedSizeWithoutHeader,<a name="line.560"></a>
-<span class="sourceLineNo">561</span>        "uncompressedSizeWithoutHeader");<a name="line.561"></a>
-<span class="sourceLineNo">562</span><a name="line.562"></a>
-<span class="sourceLineNo">563</span>    sanityCheckAssertion(dup.getLong(), prevBlockOffset, "prevBlockOffset");<a name="line.563"></a>
-<span class="sourceLineNo">564</span>    if (this.fileContext.isUseHBaseChecksum()) {<a name="line.564"></a>
-<span class="sourceLineNo">565</span>      sanityCheckAssertion(dup.get(), this.fileContext.getChecksumType().getCode(), "checksumType");<a name="line.565"></a>
-<span class="sourceLineNo">566</span>      sanityCheckAssertion(dup.getInt(), this.fileContext.getBytesPerChecksum(),<a name="line.566"></a>
-<span class="sourceLineNo">567</span>          "bytesPerChecksum");<a name="line.567"></a>
-<span class="sourceLineNo">568</span>      sanityCheckAssertion(dup.getInt(), onDiskDataSizeWithHeader, "onDiskDataSizeWithHeader");<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>    int cksumBytes = totalChecksumBytes();<a name="line.571"></a>
-<span class="sourceLineNo">572</span>    int expectedBufLimit = onDiskDataSizeWithHeader + cksumBytes;<a name="line.572"></a>
-<span class="sourceLineNo">573</span>    if (dup.limit() != expectedBufLimit) {<a name="line.573"></a>
-<span class="sourceLineNo">574</span>      throw new AssertionError("Expected limit " + expectedBufLimit + ", got " + dup.limit());<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>    // We might optionally allocate HFILEBLOCK_HEADER_SIZE more bytes to read the next<a name="line.577"></a>
-<span class="sourceLineNo">578</span>    // block's header, so there are two sensible values for buffer capacity.<a name="line.578"></a>
-<span class="sourceLineNo">579</span>    int hdrSize = headerSize();<a name="line.579"></a>
-<span class="sourceLineNo">580</span>    if (dup.capacity() != expectedBufLimit &amp;&amp; dup.capacity() != expectedBufLimit + hdrSize) {<a name="line.580"></a>
-<span class="sourceLineNo">581</span>      throw new AssertionError("Invalid buffer capacity: " + dup.capacity() +<a name="line.581"></a>
-<span class="sourceLineNo">582</span>          ", expected " + expectedBufLimit + " or " + (expectedBufLimit + hdrSize));<a name="line.582"></a>
-<span class="sourceLineNo">583</span>    }<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>  @Override<a name="line.586"></a>
-<span class="sourceLineNo">587</span>  public String toString() {<a name="line.587"></a>
-<span class="sourceLineNo">588</span>    StringBuilder sb = new StringBuilder()<a name="line.588"></a>
-<span class="sourceLineNo">589</span>      .append("[")<a name="line.589"></a>
-<span class="sourceLineNo">590</span>      .append("blockType=").append(blockType)<a name="line.590"></a>
-<span class="sourceLineNo">591</span>      .append(", fileOffset=").append(offset)<a name="line.591"></a>
-<span class="sourceLineNo">592</span>      .append(", headerSize=").append(headerSize())<a name="line.592"></a>
-<span class="sourceLineNo">593</span>      .append(", onDiskSizeWithoutHeader=").append(onDiskSizeWithoutHeader)<a name="line.593"></a>
-<span class="sourceLineNo">594</span>      .append(", uncompressedSizeWithoutHeader=").append(uncompressedSizeWithoutHeader)<a name="line.594"></a>
-<span class="sourceLineNo">595</span>      .append(", prevBlockOffset=").append(prevBlockOffset)<a name="line.595"></a>
-<span class="sourceLineNo">596</span>      .append(", isUseHBaseChecksum=").append(fileContext.isUseHBaseChecksum());<a name="line.596"></a>
-<span class="sourceLineNo">597</span>    if (fileContext.isUseHBaseChecksum()) {<a name="line.597"></a>
-<span class="sourceLineNo">598</span>      sb.append(", checksumType=").append(ChecksumType.codeToType(this.buf.get(24)))<a name="line.598"></a>
-<span class="sourceLineNo">599</span>        .append(", bytesPerChecksum=").append(this.buf.getInt(24 + 1))<a name="line.599"></a>
-<span class="sourceLineNo">600</span>        .append(", onDiskDataSizeWithHeader=").append(onDiskDataSizeWithHeader);<a name="line.600"></a>
-<span class="sourceLineNo">601</span>    } else {<a name="line.601"></a>
-<span class="sourceLineNo">602</span>      sb.append(", onDiskDataSizeWithHeader=").append(onDiskDataSizeWithHeader)<a name="line.602"></a>
-<span class="sourceLineNo">603</span>        .append("(").append(onDiskSizeWithoutHeader)<a name="line.603"></a>
-<span class="sourceLineNo">604</span>        .append("+").append(HConstants.HFILEBLOCK_HEADER_SIZE_NO_CHECKSUM).append(")");<a name="line.604"></a>
-<span class="sourceLineNo">605</span>    }<a name="line.605"></a>
-<span class="sourceLineNo">606</span>    String dataBegin = null;<a name="line.606"></a>
-<span class="sourceLineNo">607</span>    if (buf.hasArray()) {<a name="line.607"></a>
-<span class="sourceLineNo">608</span>      dataBegin = Bytes.toStringBinary(buf.array(), buf.arrayOffset() + headerSize(),<a name="line.608"></a>
-<span class="sourceLineNo">609</span>          Math.min(32, buf.limit() - buf.arrayOffset() - headerSize()));<a name="line.609"></a>
-<span class="sourceLineNo">610</span>    } else {<a name="line.610"></a>
-<span class="sourceLineNo">611</span>      ByteBuff bufWithoutHeader = getBufferWithoutHeader();<a name="line.611"></a>
-<span class="sourceLineNo">612</span>      byte[] dataBeginBytes = new byte[Math.min(32,<a name="line.612"></a>
-<span class="sourceLineNo">613</span>          bufWithoutHeader.limit() - bufWithoutHeader.position())];<a name="line.613"></a>
-<span class="sourceLineNo">614</span>      bufWithoutHeader.get(dataBeginBytes);<a name="line.614"></a>
-<span class="sourceLineNo">615</span>      dataBegin = Bytes.toStringBinary(dataBeginBytes);<a name="line.615"></a>
-<span class="sourceLineNo">616</span>    }<a name="line.616"></a>
-<span class="sourceLineNo">617</span>    sb.append(", getOnDiskSizeWithHeader=").append(getOnDiskSizeWithHeader())<a name="line.617"></a>
-<span class="sourceLineNo">618</span>      .append(", totalChecksumBytes=").append(totalChecksumBytes())<a name="line.618"></a>
-<span class="sourceLineNo">619</span>      .append(", isUnpacked=").append(isUnpacked())<a name="line.619"></a>
-<span class="sourceLineNo">620</span>      .append(", buf=[").append(buf).append("]")<a name="line.620"></a>
-<span class="sourceLineNo">621</span>      .append(", dataBeginsWith=").append(dataBegin)<a name="line.621"></a>
-<span class="sourceLineNo">622</span>      .append(", fileContext=").append(fileContext)<a name="line.622"></a>
-<span class="sourceLineNo">623</span>      .append("]");<a name="line.623"></a>
-<span class="sourceLineNo">624</span>    return sb.toString();<a name="line.624"></a>
-<span class="sourceLineNo">625</span>  }<a name="line.625"></a>
-<span class="sourceLineNo">626</span><a name="line.626"></a>
-<span class="sourceLineNo">627</span>  /**<a name="line.627"></a>
-<span class="sourceLineNo">628</span>   * Retrieves the decompressed/decrypted view of this block. An encoded block remains in its<a name="line.628"></a>
-<span class="sourceLineNo">629</span>   * encoded structure. Internal structures are shared between instances where applicable.<a name="line.629"></a>
-<span class="sourceLineNo">630</span>   */<a name="line.630"></a>
-<span class="sourceLineNo">631</span>  HFileBlock unpack(HFileContext fileContext, FSReader reader) throws IOException {<a name="line.631"></a>
-<span class="sourceLineNo">632</span>    if (!fileContext.isCompressedOrEncrypted()) {<a name="line.632"></a>
-<span class="sourceLineNo">633</span>      // TODO: cannot use our own fileContext here because HFileBlock(ByteBuffer, boolean),<a name="line.633"></a>
-<span class="sourceLineNo">634</span>      // which is used for block serialization to L2 cache, does not preserve encoding and<a name="line.634"></a>
-<span class="sourceLineNo">635</span>      // encryption details.<a name="line.635"></a>
-<span class="sourceLineNo">636</span>      return this;<a name="line.636"></a>
-<span class="sourceLineNo">637</span>    }<a name="line.637"></a>
-<span class="sourceLineNo">638</span><a name="line.638"></a>
-<span class="sourceLineNo">639</span>    HFileBlock unpacked = new HFileBlock(this);<a name="line.639"></a>
-<span class="sourceLineNo">640</span>    unpacked.allocateBuffer(); // allocates space for the decompressed block<a name="line.640"></a>
-<span class="sourceLineNo">641</span><a name="line.641"></a>
-<span class="sourceLineNo">642</span>    HFileBlockDecodingContext ctx = blockType == BlockType.ENCODED_DATA ?<a name="line.642"></a>
-<span class="sourceLineNo">643</span>      reader.getBlockDecodingContext() : reader.getDefaultBlockDecodingContext();<a name="line.643"></a>
-<span class="sourceLineNo">644</span><a name="line.644"></a>
-<span class="sourceLineNo">645</span>    ByteBuff dup = this.buf.duplicate();<a name="line.645"></a>
-<span class="sourceLineNo">646</span>    dup.position(this.headerSize());<a name="line.646"></a>
-<span class="sourceLineNo">647</span>    dup = dup.slice();<a name="line.647"></a>
-<span class="sourceLineNo">648</span>    ctx.prepareDecoding(unpacked.getOnDiskSizeWithoutHeader(),<a name="line.648"></a>
-<span class="sourceLineNo">649</span>      unpacked.getUncompressedSizeWithoutHeader(), unpacked.getBufferWithoutHeader(),<a name="line.649"></a>
-<span class="sourceLineNo">650</span>      dup);<a name="line.650"></a>
-<span class="sourceLineNo">651</span>    return unpacked;<a name="line.651"></a>
-<span class="sourceLineNo">652</span>  }<a name="line.652"></a>
-<span class="sourceLineNo">653</span><a name="line.653"></a>
-<span class="sourceLineNo">654</span>  /**<a name="line.654"></a>
-<span class="sourceLineNo">655</span>   * Always allocates a new buffer of the correct size. Copies header bytes<a name="line.655"></a>
-<span class="sourceLineNo">656</span>   * from the existing buffer. Does not change header fields.<a name="line.656"></a>
-<span class="sourceLineNo">657</span>   * Reserve room to keep checksum bytes too.<a name="line.657"></a>
-<span class="sourceLineNo">658</span>   */<a name="line.658"></a>
-<span class="sourceLineNo">659</span>  private void allocateBuffer() {<a name="line.659"></a>
-<span class="sourceLineNo">660</span>    int cksumBytes = totalChecksumBytes();<a name="line.660"></a>
-<span class="sourceLineNo">661</span>    int headerSize = headerSize();<a name="line.661"></a>
-<span class="sourceLineNo">662</span>    int capacityNeeded = headerSize + uncompressedSizeWithoutHeader + cksumBytes;<a name="line.662"></a>
-<span class="sourceLineNo">663</span><a name="line.663"></a>
-<span class="sourceLineNo">664</span>    // TODO we need consider allocating offheap here?<a name="line.664"></a>
-<span class="sourceLineNo">665</span>    ByteBuffer newBuf = ByteBuffer.allocate(capacityNeeded);<a name="line.665"></a>
-<span class="sourceLineNo">666</span><a name="line.666"></a>
-<span class="sourceLineNo">667</span>    // Copy header bytes into newBuf.<a name="line.667"></a>
-<span class="sourceLineNo">668</span>    // newBuf is HBB so no issue in calling array()<a name="line.668"></a>
-<span class="sourceLineNo">669</span>    buf.position(0);<a name="line.669"></a>
-<span class="sourceLineNo">670</span>    buf.get(newBuf.array(), newBuf.arrayOffset(), headerSize);<a name="line.670"></a>
-<span class="sourceLineNo">671</span><a name="line.671"></a>
-<span class="sourceLineNo">672</span>    buf = new SingleByteBuff(newBuf);<a name="line.672"></a>
-<span class="sourceLineNo">673</span>    // set limit to exclude next block's header<a name="line.673"></a>
-<span class="sourceLineNo">674</span>    buf.limit(headerSize + uncompressedSizeWithoutHeader + cksumBytes);<a name="line.674"></a>
-<span class="sourceLineNo">675</span>  }<a name="line.675"></a>
-<span class="sourceLineNo">676</span><a name="line.676"></a>
-<span class="sourceLineNo">677</span>  /**<a name="line.677"></a>
-<span class="sourceLineNo">678</span>   * Return true when this block's buffer has been unpacked, false otherwise. Note this is a<a name="line.678"></a>
-<span class="sourceLineNo">679</span>   * calculated heuristic, not tracked attribute of the block.<a name="line.679"></a>
-<span class="sourceLineNo">680</span>   */<a name="line.680"></a>
-<span class="sourceLineNo">681</span>  public boolean isUnpacked() {<a name="line.681"></a>
-<span class="sourceLineNo">682</span>    final int cksumBytes = totalChecksumBytes();<a name="line.682"></a>
-<span class="sourceLineNo">683</span>    final int headerSize = headerSize();<a name="line.683"></a>
-<span class="sourceLineNo">684</span>    final int expectedCapacity = headerSize + uncompressedSizeWithoutHeader + cksumBytes;<a name="line.684"></a>
-<span class="sourceLineNo">685</span>    final int bufCapacity = buf.capacity();<a name="line.685"></a>
-<span class="sourceLineNo">686</span>    return bufCapacity == expectedCapacity || bufCapacity == expectedCapacity + headerSize;<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>  /** An additional sanity-check in case no compression or encryption is being used. */<a name="line.689"></a>
-<span class="sourceLineNo">690</span>  @VisibleForTesting<a name="line.690"></a>
-<span class="sourceLineNo">691</span>  void sanityCheckUncompressedSize() throws IOException {<a name="line.691"></a>
-<span class="sourceLineNo">692</span>    if (onDiskSizeWithoutHeader != uncompressedSizeWithoutHeader + totalChecksumBytes()) {<a name="line.692"></a>
-<span class="sourceLineNo">693</span>      throw new IOException("Using no compression but "<a name="line.693"></a>
-<span class="sourceLineNo">694</span>          + "onDiskSizeWithoutHeader=" + onDiskSizeWithoutHeader + ", "<a name="line.694"></a>
-<span class="sourceLineNo">695</span>          + "uncompressedSizeWithoutHeader=" + uncompressedSizeWithoutHeader<a name="line.695"></a>
-<span class="sourceLineNo">696</span>          + ", numChecksumbytes=" + totalChecksumBytes());<a name="line.696"></a>
-<span class="sourceLineNo">697</span>    }<a name="line.697"></a>
-<span class="sourceLineNo">698</span>  }<a name="line.698"></a>
-<span class="sourceLineNo">699</span><a name="line.699"></a>
-<span class="sourceLineNo">700</span>  /**<a name="line.700"></a>
-<span class="sourceLineNo">701</span>   * Cannot be {@link #UNSET}. Must be a legitimate value. Used re-making the {@link BlockCacheKey} when<a name="line.701"></a>
-<span class="sourceLineNo">702</span>   * block is returned to the cache.<a name="line.702"></a>
-<span class="sourceLineNo">703</span>   * @return the offset of this block in the file it was read from<a name="line.703"></a>
-<span class="sourceLineNo">704</span>   */<a name="line.704"></a>
-<span class="sourceLineNo">705</span>  long getOffset() {<a name="line.705"></a>
-<span class="sourceLineNo">706</span>    if (offset &lt; 0) {<a name="line.706"></a>
-<span class="sourceLineNo">707</span>      throw new IllegalStateException("HFile block offset not initialized properly");<a name="line.707"></a>
-<span class="sourceLineNo">708</span>    }<a name="line.708"></a>
-<span class="sourceLineNo">709</span>    return offset;<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>   * @return a byte stream reading the data + checksum of this block<a name="line.713"></a>
-<span class="sourceLineNo">714</span>   */<a name="line.714"></a>
-<span class="sourceLineNo">715</span>  DataInputStream getByteStream() {<a name="line.715"></a>
-<span class="sourceLineNo">716</span>    ByteBuff dup = this.buf.duplicate();<a name="line.716"></a>
-<span class="sourceLineNo">717</span>    dup.position(this.headerSize());<a name="line.717"></a>
-<span class="sourceLineNo">718</span>    return new DataInputStream(new ByteBuffInputStream(dup));<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>
-<span class="sourceLineNo">721</span>  @Override<a name="line.721"></a>
-<span class="sourceLineNo">722</span>  public long heapSize() {<a name="line.722"></a>
-<span class="sourceLineNo">723</span>    long size = ClassSize.align(<a name="line.723"></a>
-<span class="sourceLineNo">724</span>        ClassSize.OBJECT +<a name="line.724"></a>
-<span class="sourceLineNo">725</span>        // Block type, multi byte buffer, MemoryType and meta references<a name="line.725"></a>
-<span class="sourceLineNo">726</span>        4 * ClassSize.REFERENCE +<a name="line.726"></a>
-<span class="sourceLineNo">727</span>        // On-disk size, uncompressed size, and next block's on-disk size<a name="line.727"></a>
-<span class="sourceLineNo">728</span>        // bytePerChecksum and onDiskDataSize<a name="line.728"></a>
-<span class="sourceLineNo">729</span>        4 * Bytes.SIZEOF_INT +<a name="line.729"></a>
-<span class="sourceLineNo">730</span>        // This and previous block offset<a name="line.730"></a>
-<span class="sourceLineNo">731</span>        2 * Bytes.SIZEOF_LONG +<a name="line.731"></a>
-<span class="sourceLineNo">732</span>        // Heap size of the meta object. meta will be always not null.<a name="line.732"></a>
-<span class="sourceLineNo">733</span>        fileContext.heapSize()<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>    if (buf != null) {<a name="line.736"></a>
-<span class="sourceLineNo">737</span>      // Deep overhead of the byte buffer. Needs to be aligned separately.<a name="line.737"></a>
-<span class="sourceLineNo">738</span>      size += ClassSize.align(buf.capacity() + MULTI_BYTE_BUFFER_HEAP_SIZE);<a name="line.738"></a>
-<span class="sourceLineNo">739</span>    }<a name="line.739"></a>
-<span class="sourceLineNo">740</span><a name="line.740"></a>
-<span class="sourceLineNo">741</span>    return ClassSize.align(size);<a name="line.741"></a>
-<span class="sourceLineNo">742</span>  }<a name="line.742"></a>
-<span class="sourceLineNo">743</span><a name="line.743"></a>
-<span class="sourceLineNo">744</span>  /**<a name="line.744"></a>
-<span class="sourceLineNo">745</span>   * Read from an input stream at least &lt;code&gt;necessaryLen&lt;/code&gt; and if possible,<a name="line.745"></a>
-<span class="sourceLineNo">746</span>   * &lt;code&gt;extraLen&lt;/code&gt; also if available. Analogous to<a name="line.746"></a>
-<span class="sourceLineNo">747</span>   * {@link IOUtils#readFully(InputStream, byte[], int, int)}, but specifies a<a name="line.747"></a>
-<span class="sourceLineNo">748</span>   * number of "extra" bytes to also optionally read.<a name="line.748"></a>
-<span class="sourceLineNo">749</span>   *<a name="line.749"></a>
-<span class="sourceLineNo">750</span>   * @param in the input stream to read from<a name="line.750"></a>
-<span class="sourceLineNo">751</span>   * @param buf the buffer to read into<a name="line.751"></a>
-<span class="sourceLineNo">752</span>   * @param bufOffset the destination offset in the buffer<a name="line.752"></a>
-<span class="sourceLineNo">753</span>   * @param necessaryLen the number of bytes that are absolutely necessary to read<a name="line.753"></a>
-<span class="sourceLineNo">754</span>   * @param extraLen the number of extra bytes that would be nice to read<a name="line.754"></a>
-<span class="sourceLineNo">755</span>   * @return true if succeeded reading the extra bytes<a name="line.755"></a>
-<span class="sourceLineNo">756</span>   * @throws IOException if failed to read the necessary bytes<a name="line.756"></a>
-<span class="sourceLineNo">757</span>   */<a name="line.757"></a>
-<span class="sourceLineNo">758</span>  static boolean readWithExtra(InputStream in, byte[] buf,<a name="line.758"></a>
-<span class="sourceLineNo">759</span>      int bufOffset, int necessaryLen, int extraLen) throws IOException {<a name="line.759"></a>
-<span class="sourceLineNo">760</span>    int bytesRemaining = necessaryLen + extraLen;<a name="line.760"></a>
-<span class="sourceLineNo">761</span>    while (bytesRemaining &gt; 0) {<a name="line.761"></a>
-<span class="sourceLineNo">762</span>      int ret = in.read(buf, bufOffset, bytesRemaining);<a name="line.762"></a>
-<span class="sourceLineNo">763</span>      if (ret == -1 &amp;&amp; bytesRemaining &lt;= extraLen) {<a name="line.763"></a>
-<span class="sourceLineNo">764</span>        // We could not read the "extra data", but that is OK.<a name="line.764"></a>
-<span class="sourceLineNo">765</span>        break;<a name="line.765"></a>
-<span class="sourceLineNo">766</span>      }<a name="line.766"></a>
-<span class="sourceLineNo">767</span>      if (ret &lt; 0) {<a name="line.767"></a>
-<span class="sourceLineNo">768</span>        throw new IOException("Premature EOF from inputStream (read "<a name="line.768"></a>
-<span class="sourceLineNo">769</span>            + "returned " + ret + ", was trying to read " + necessaryLen<a name="line.769"></a>
-<span class="sourceLineNo">770</span>            + " necessary bytes and " + extraLen + " extra bytes, "<a name="line.770"></a>
-<span class="sourceLineNo">771</span>            + "successfully read "<a name="line.771"></a>
-<span class="sourceLineNo">772</span>            + (necessaryLen + extraLen - bytesRemaining));<a name="line.772"></a>
-<span class="sourceLineNo">773</span>      }<a name="line.773"></a>
-<span class="sourceLineNo">774</span>      bufOffset += ret;<a name="line.774"></a>
-<span class="sourceLineNo">775</span>      bytesRemaining -= ret;<a name="line.775"></a>
-<span class="sourceLineNo">776</span>    }<a name="line.776"></a>
-<span class="sourceLineNo">777</span>    return bytesRemaining &lt;= 0;<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>   * Read from an input stream at least &lt;code&gt;necessaryLen&lt;/code&gt; and if possible,<a name="line.781"></a>
-<span class="sourceLineNo">782</span>   * &lt;code&gt;extraLen&lt;/code&gt; also if available. Analogous to<a name="line.782"></a>
-<span class="sourceLineNo">783</span>   * {@link IOUtils#readFully(InputStream, byte[], int, int)}, but uses<a name="line.783"></a>
-<span class="sourceLineNo">784</span>   * positional read and specifies a number of "extra" bytes that would be<a name="line.784"></a>
-<span class="sourceLineNo">785</span>   * desirable but not absolutely necessary to read.<a name="line.785"></a>
-<span class="sourceLineNo">786</span>   *<a name="line.786"></a>
-<span class="sourceLineNo">787</span>   * @param in the input stream to read from<a name="line.787"></a>
-<span class="sourceLineNo">788</span>   * @param position the position within the stream from which to start reading<a name="line.788"></a>
-<span class="sourceLineNo">789</span>   * @param buf the buffer to read into<a name="line.789"></a>
-<span class="sourceLineNo">790</span>   * @param bufOffset the destination offset in the buffer<a name="line.790"></a>
-<span class="sourceLineNo">791</span>   * @param necessaryLen the number of bytes that are absolutely necessary to<a name="line.791"></a>
-<span class="sourceLineNo">792</span>   *     read<a name="line.792"></a>
-<span class="sourceLineNo">793</span>   * @param extraLen the number of extra bytes that would be nice to read<a name="line.793"></a>
-<span class="sourceLineNo">794</span>   * @return true if and only if extraLen is &gt; 0 and reading those extra bytes<a name="line.794"></a>
-<span class="sourceLineNo">795</span>   *     was successful<a name="line.795"></a>
-<span class="sourceLineNo">796</span>   * @throws IOException if failed to read the necessary bytes<a name="line.796"></a>
-<span class="sourceLineNo">797</span>   */<a name="line.797"></a>
-<span class="sourceLineNo">798</span>  @VisibleForTesting<a name="line.798"></a>
-<span class="sourceLineNo">799</span>  static boolean positionalReadWithExtra(FSDataInputStream in,<a name="line.799"></a>
-<span class="sourceLineNo">800</span>      long position, byte[] buf, int bufOffset, int necessaryLen, int extraLen)<a name="line.800"></a>
-<span class="sourceLineNo">801</span>      throws IOException {<a name="line.801"></a>
-<span class="sourceLineNo">802</span>    int bytesRemaining = necessaryLen + extraLen;<a name="line.802"></a>
-<span class="sourceLineNo">803</span>    int bytesRead = 0;<a name="line.803"></a>
-<span class="sourceLineNo">804</span>    while (bytesRead &lt; necessaryLen) {<a name="line.804"></a>
-<span class="sourceLineNo">805</span>      int ret = in.read(position, buf, bufOffset, bytesRemaining);<a name="line.805"></a>
-<span class="sourceLineNo">806</span>      if (ret &lt; 0) {<a name="line.806"></a>
-<span class="sourceLineNo">807</span>        throw new IOException("Premature EOF from inputStream (positional read "<a name="line.807"></a>
-<span class="sourceLineNo">808</span>            + "returned " + ret + ", was trying to read " + necessaryLen<a name="line.808"></a>
-<span class="sourceLineNo">809</span>            + " necessary bytes and " + extraLen + " extra bytes, "<a name="line.809"></a>
-<span class="sourceLineNo">810</span>            + "successfully read " + bytesRead);<a name="line.810"></a>
-<span class="sourceLineNo">811</span>      }<a name="line.811"></a>
-<span class="sourceLineNo">812</span>      position += ret;<a name="line.812"></a>
-<span class="sourceLineNo">813</span>      bufOffset += ret;<a name="line.813"></a>
-<span class="sourceLineNo">814</span>      bytesRemaining -= ret;<a name="line.814"></a>
-<span class="sourceLineNo">815</span>      bytesRead += ret;<a name="line.815"></a>
-<span class="sourceLineNo">816</span>    }<a name="line.816"></a>
-<span class="sourceLineNo">817</span>    return bytesRead != necessaryLen &amp;&amp; bytesRemaining &lt;= 0;<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>   * Unified version 2 {@link HFile} block writer. The intended usage pattern<a name="line.821"></a>
-<span class="sourceLineNo">822</span>   * is as follows:<a name="line.822"></a>
-<span class="sourceLineNo">823</span>   * &lt;ol&gt;<a name="line.823"></a>
-<span class="sourceLineNo">824</span>   * &lt;li&gt;Construct an {@link HFileBlock.Writer}, providing a compression algorithm.<a name="line.824"></a>
-<span class="sourceLineNo">825</span>   * &lt;li&gt;Call {@link Writer#startWriting} and get a data stream to write to.<a name="line.825"></a>
-<span class="sourceLineNo">826</span>   * &lt;li&gt;Write your data into the stream.<a name="line.826"></a>
-<span class="sourceLineNo">827</span>   * &lt;li&gt;Call Writer#writeHeaderAndData(FSDataOutputStream) as many times as you need to.<a name="line.827"></a>
-<span class="sourceLineNo">828</span>   * store the serialized block into an external stream.<a name="line.828"></a>
-<span class="sourceLineNo">829</span>   * &lt;li&gt;Repeat to write more blocks.<a name="line.829"></a>
-<span class="sourceLineNo">830</span>   * &lt;/ol&gt;<a name="line.830"></a>
-<span class="sourceLineNo">831</span>   * &lt;p&gt;<a name="line.831"></a>
-<span class="sourceLineNo">832</span>   */<a name="line.832"></a>
-<span class="sourceLineNo">833</span>  static class Writer {<a name="line.833"></a>
-<span class="sourceLineNo">834</span>    private enum State {<a name="line.834"></a>
-<span class="sourceLineNo">835</span>      INIT,<a name="line.835"></a>
-<span class="sourceLineNo">836</span>      WRITING,<a name="line.836"></a>
-<span class="sourceLineNo">837</span>      BLOCK_READY<a name="line.837"></a>
-<span class="sourceLineNo">838</span>    }<a name="line.838"></a>
-<span class="sourceLineNo">839</span><a name="line.839"></a>
-<span class="sourceLineNo">840</span>    /** Writer state. Used to ensure the correct usage protocol. */<a name="line.840"></a>
-<span class="sourceLineNo">841</span>    private State state = State.INIT;<a name="line.841"></a>
-<span class="sourceLineNo">842</span><a name="line.842"></a>
-<span class="sourceLineNo">843</span>    /** Data block encoder used for data blocks */<a name="line.843"></a>
-<span class="sourceLineNo">844</span>    private final HFileDataBlockEncoder dataBlockEncoder;<a name="line.844"></a>
-<span class="sourceLineNo">845</span><a name="line.845"></a>
-<span class="sourceLineNo">846</span>    private HFileBlockEncodingContext dataBlockEncodingCtx;<a name="line.846"></a>
+<span class="sourceLineNo">328</span>   *<a name="line.328"></a>
+<span class="sourceLineNo">329</span>   * &lt;p&gt;TODO: The caller presumes no checksumming<a name="line.329"></a>
+<span class="sourceLineNo">330</span>   * required of this block instance since going into cache; checksum already verified on<a name="line.330"></a>
+<span class="sourceLineNo">331</span>   * underlying block data pulled in from filesystem. Is that correct? What if cache is SSD?<a name="line.331"></a>
+<span class="sourceLineNo">332</span>   *<a name="line.332"></a>
+<span class="sourceLineNo">333</span>   * @param blockType the type of this block, see {@link BlockType}<a name="line.333"></a>
+<span class="sourceLineNo">334</span>   * @param onDiskSizeWithoutHeader see {@link #onDiskSizeWithoutHeader}<a name="line.334"></a>
+<span class="sourceLineNo">335</span>   * @param uncompressedSizeWithoutHeader see {@link #uncompressedSizeWithoutHeader}<a name="line.335"></a>
+<span class="sourceLineNo">336</span>   * @param prevBlockOffset see {@link #prevBlockOffset}<a name="line.336"></a>
+<span class="sourceLineNo">337</span>   * @param b block header ({@link HConstants#HFILEBLOCK_HEADER_SIZE} bytes)<a name="line.337"></a>
+<span class="sourceLineNo">338</span>   * @param fillHeader when true, write the first 4 header fields into passed buffer.<a name="line.338"></a>
+<span class="sourceLineNo">339</span>   * @param offset the file offset the block was read from<a name="line.339"></a>
+<span class="sourceLineNo">340</span>   * @param onDiskDataSizeWithHeader see {@link #onDiskDataSizeWithHeader}<a name="line.340"></a>
+<span class="sourceLineNo">341</span>   * @param fileContext HFile meta data<a name="line.341"></a>
+<span class="sourceLineNo">342</span>   */<a name="line.342"></a>
+<span class="sourceLineNo">343</span>  @VisibleForTesting<a name="line.343"></a>
+<span class="sourceLineNo">344</span>  public HFileBlock(BlockType blockType, int onDiskSizeWithoutHeader,<a name="line.344"></a>
+<span class="sourceLineNo">345</span>      int uncompressedSizeWithoutHeader, long prevBlockOffset, ByteBuffer b, boolean fillHeader,<a name="line.345"></a>
+<span class="sourceLineNo">346</span>      long offset, final int nextBlockOnDiskSize, int onDiskDataSizeWithHeader,<a name="line.346"></a>
+<span class="sourceLineNo">347</span>      HFileContext fileContext) {<a name="line.347"></a>
+<span class="sourceLineNo">348</span>    init(blockType, onDiskSizeWithoutHeader, uncompressedSizeWithoutHeader,<a name="line.348"></a>
+<span class="sourceLineNo">349</span>        prevBlockOffset, offset, onDiskDataSizeWithHeader, nextBlockOnDiskSize, fileContext);<a name="line.349"></a>
+<span class="sourceLineNo">350</span>    this.buf = new SingleByteBuff(b);<a name="line.350"></a>
+<span class="sourceLineNo">351</span>    if (fillHeader) {<a name="line.351"></a>
+<span class="sourceLineNo">352</span>      overwriteHeader();<a name="line.352"></a>
+<span class="sourceLineNo">353</span>    }<a name="line.353"></a>
+<span class="sourceLineNo">354</span>    this.buf.rewind();<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">357</span>  /**<a name="line.357"></a>
+<span class="sourceLineNo">358</span>   * Creates a block from an existing buffer starting with a header. Rewinds<a name="line.358"></a>
+<span class="sourceLineNo">359</span>   * and takes ownership of the buffer. By definition of rewind, ignores the<a name="line.359"></a>
+<span class="sourceLineNo">360</span>   * buffer position, but if you slice the buffer beforehand, it will rewind<a name="line.360"></a>
+<span class="sourceLineNo">361</span>   * to that point.<a name="line.361"></a>
+<span class="sourceLineNo">362</span>   * @param buf Has header, content, and trailing checksums if present.<a name="line.362"></a>
+<span class="sourceLineNo">363</span>   */<a name="line.363"></a>
+<span class="sourceLineNo">364</span>  HFileBlock(ByteBuff buf, boolean usesHBaseChecksum, MemoryType memType, final long offset,<a name="line.364"></a>
+<span class="sourceLineNo">365</span>      final int nextBlockOnDiskSize, HFileContext fileContext) throws IOException {<a name="line.365"></a>
+<span class="sourceLineNo">366</span>    buf.rewind();<a name="line.366"></a>
+<span class="sourceLineNo">367</span>    final BlockType blockType = BlockType.read(buf);<a name="line.367"></a>
+<span class="sourceLineNo">368</span>    final int onDiskSizeWithoutHeader = buf.getInt(Header.ON_DISK_SIZE_WITHOUT_HEADER_INDEX);<a name="line.368"></a>
+<span class="sourceLineNo">369</span>    final int uncompressedSizeWithoutHeader =<a name="line.369"></a>
+<span class="sourceLineNo">370</span>        buf.getInt(Header.UNCOMPRESSED_SIZE_WITHOUT_HEADER_INDEX);<a name="line.370"></a>
+<span class="sourceLineNo">371</span>    final long prevBlockOffset = buf.getLong(Header.PREV_BLOCK_OFFSET_INDEX);<a name="line.371"></a>
+<span class="sourceLineNo">372</span>    // This constructor is called when we deserialize a block from cache and when we read a block in<a name="line.372"></a>
+<span class="sourceLineNo">373</span>    // from the fs. fileCache is null when deserialized from cache so need to make up one.<a name="line.373"></a>
+<span class="sourceLineNo">374</span>    HFileContextBuilder fileContextBuilder = fileContext != null?<a name="line.374"></a>
+<span class="sourceLineNo">375</span>        new HFileContextBuilder(fileContext): new HFileContextBuilder();<a name="line.375"></a>
+<span class="sourceLineNo">376</span>    fileContextBuilder.withHBaseCheckSum(usesHBaseChecksum);<a name="line.376"></a>
+<span class="sourceLineNo">377</span>    int onDiskDataSizeWithHeader;<a name="line.377"></a>
+<span class="sourceLineNo">378</span>    if (usesHBaseChecksum) {<a name="line.378"></a>
+<span class="sourceLineNo">379</span>      byte checksumType = buf.get(Header.CHECKSUM_TYPE_INDEX);<a name="line.379"></a>
+<span class="sourceLineNo">380</span>      int bytesPerChecksum = buf.getInt(Header.BYTES_PER_CHECKSUM_INDEX);<a name="line.380"></a>
+<span class="sourceLineNo">381</span>      onDiskDataSizeWithHeader = buf.getInt(Header.ON_DISK_DATA_SIZE_WITH_HEADER_INDEX);<a name="line.381"></a>
+<span class="sourceLineNo">382</span>      // Use the checksum type and bytes per checksum from header, not from filecontext.<a name="line.382"></a>
+<span class="sourceLineNo">383</span>      fileContextBuilder.withChecksumType(ChecksumType.codeToType(checksumType));<a name="line.383"></a>
+<span class="sourceLineNo">384</span>      fileContextBuilder.withBytesPerCheckSum(bytesPerChecksum);<a name="line.384"></a>
+<span class="sourceLineNo">385</span>    } else {<a name="line.385"></a>
+<span class="sourceLineNo">386</span>      fileContextBuilder.withChecksumType(ChecksumType.NULL);<a name="line.386"></a>
+<span class="sourceLineNo">387</span>      fileContextBuilder.withBytesPerCheckSum(0);<a name="line.387"></a>
+<span class="sourceLineNo">388</span>      // Need to fix onDiskDataSizeWithHeader; there are not checksums after-block-data<a name="line.388"></a>
+<span class="sourceLineNo">389</span>      onDiskDataSizeWithHeader = onDiskSizeWithoutHeader + headerSize(usesHBaseChecksum);<a name="line.389"></a>
+<span class="sourceLineNo">390</span>    }<a name="line.390"></a>
+<span class="sourceLineNo">391</span>    fileContext = fileContextBuilder.build();<a name="line.391"></a>
+<span class="sourceLineNo">392</span>    assert usesHBaseChecksum == fileContext.isUseHBaseChecksum();<a name="line.392"></a>
+<span class="sourceLineNo">393</span>    init(blockType, onDiskSizeWithoutHeader, uncompressedSizeWithoutHeader,<a name="line.393"></a>
+<span class="sourceLineNo">394</span>        prevBlockOffset, offset, onDiskDataSizeWithHeader, nextBlockOnDiskSize, fileContext);<a name="line.394"></a>
+<span class="sourceLineNo">395</span>    this.memType = memType;<a name="line.395"></a>
+<span class="sourceLineNo">396</span>    this.offset = offset;<a name="line.396"></a>
+<span class="sourceLineNo">397</span>    this.buf = buf;<a name="line.397"></a>
+<span class="sourceLineNo">398</span>    this.buf.rewind();<a name="line.398"></a>
+<span class="sourceLineNo">399</span>  }<a name="line.399"></a>
+<span class="sourceLineNo">400</span><a name="line.400"></a>
+<span class="sourceLineNo">401</span>  /**<a name="line.401"></a>
+<span class="sourceLineNo">402</span>   * Called from constructors.<a name="line.402"></a>
+<span class="sourceLineNo">403</span>   */<a name="line.403"></a>
+<span class="sourceLineNo">404</span>  private void init(BlockType blockType, int onDiskSizeWithoutHeader,<a name="line.404"></a>
+<span class="sourceLineNo">405</span>      int uncompressedSizeWithoutHeader, long prevBlockOffset,<a name="line.405"></a>
+<span class="sourceLineNo">406</span>      long offset, int onDiskDataSizeWithHeader, final int nextBlockOnDiskSize,<a name="line.406"></a>
+<span class="sourceLineNo">407</span>      HFileContext fileContext) {<a name="line.407"></a>
+<span class="sourceLineNo">408</span>    this.blockType = blockType;<a name="line.408"></a>
+<span class="sourceLineNo">409</span>    this.onDiskSizeWithoutHeader = onDiskSizeWithoutHeader;<a name="line.409"></a>
+<span class="sourceLineNo">410</span>    this.uncompressedSizeWithoutHeader = uncompressedSizeWithoutHeader;<a name="line.410"></a>
+<span class="sourceLineNo">411</span>    this.prevBlockOffset = prevBlockOffset;<a name="line.411"></a>
+<span class="sourceLineNo">412</span>    this.offset = offset;<a name="line.412"></a>
+<span class="sourceLineNo">413</span>    this.onDiskDataSizeWithHeader = onDiskDataSizeWithHeader;<a name="line.413"></a>
+<span class="sourceLineNo">414</span>    this.nextBlockOnDiskSize = nextBlockOnDiskSize;<a name="line.414"></a>
+<span class="sourceLineNo">415</span>    this.fileContext = fileContext;<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">418</span>  /**<a name="line.418"></a>
+<span class="sourceLineNo">419</span>   * Parse total on disk size including header and checksum.<a name="line.419"></a>
+<span class="sourceLineNo">420</span>   * @param headerBuf Header ByteBuffer. Presumed exact size of header.<a name="line.420"></a>
+<span class="sourceLineNo">421</span>   * @param verifyChecksum true if checksum verification is in use.<a name="line.421"></a>
+<span class="sourceLineNo">422</span>   * @return Size of the block with header included.<a name="line.422"></a>
+<span class="sourceLineNo">423</span>   */<a name="line.423"></a>
+<span class="sourceLineNo">424</span>  private static int getOnDiskSizeWithHeader(final ByteBuffer headerBuf,<a name="line.424"></a>
+<span class="sourceLineNo">425</span>      boolean verifyChecksum) {<a name="line.425"></a>
+<span class="sourceLineNo">426</span>    return headerBuf.getInt(Header.ON_DISK_SIZE_WITHOUT_HEADER_INDEX) +<a name="line.426"></a>
+<span class="sourceLineNo">427</span>      headerSize(verifyChecksum);<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>   * @return the on-disk size of the next block (including the header size and any checksums if<a name="line.431"></a>
+<span class="sourceLineNo">432</span>   * present) read by peeking into the next block's header; use as a hint when doing<a name="line.432"></a>
+<span class="sourceLineNo">433</span>   * a read of the next block when scanning or running over a file.<a name="line.433"></a>
+<span class="sourceLineNo">434</span>   */<a name="line.434"></a>
+<span class="sourceLineNo">435</span>  int getNextBlockOnDiskSize() {<a name="line.435"></a>
+<span class="sourceLineNo">436</span>    return nextBlockOnDiskSize;<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>  @Override<a name="line.439"></a>
+<span class="sourceLineNo">440</span>  public BlockType getBlockType() {<a name="line.440"></a>
+<span class="sourceLineNo">441</span>    return blockType;<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>  /** @return get data block encoding id that was used to encode this block */<a name="line.444"></a>
+<span class="sourceLineNo">445</span>  short getDataBlockEncodingId() {<a name="line.445"></a>
+<span class="sourceLineNo">446</span>    if (blockType != BlockType.ENCODED_DATA) {<a name="line.446"></a>
+<span class="sourceLineNo">447</span>      throw new IllegalArgumentException("Querying encoder ID of a block " +<a name="line.447"></a>
+<span class="sourceLineNo">448</span>          "of type other than " + BlockType.ENCODED_DATA + ": " + blockType);<a name="line.448"></a>
+<span class="sourceLineNo">449</span>    }<a name="line.449"></a>
+<span class="sourceLineNo">450</span>    return buf.getShort(headerSize());<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>   * @return the on-disk size of header + data part + checksum.<a name="line.454"></a>
+<span class="sourceLineNo">455</span>   */<a name="line.455"></a>
+<span class="sourceLineNo">456</span>  public int getOnDiskSizeWithHeader() {<a name="line.456"></a>
+<span class="sourceLineNo">457</span>    return onDiskSizeWithoutHeader + headerSize();<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>   * @return the on-disk size of the data part + checksum (header excluded).<a name="line.461"></a>
+<span class="sourceLineNo">462</span>   */<a name="line.462"></a>
+<span class="sourceLineNo">463</span>  int getOnDiskSizeWithoutHeader() {<a name="line.463"></a>
+<span class="sourceLineNo">464</span>    return onDiskSizeWithoutHeader;<a name="line.464"></a>
+<span class="sourceLineNo">465</span>  }<a name="line.465"></a>
+<span class="sourceLineNo">466</span><a name="line.466"></a>
+<span class="sourceLineNo">467</span>  /**<a name="line.467"></a>
+<span class="sourceLineNo">468</span>   * @return the uncompressed size of data part (header and checksum excluded).<a name="line.468"></a>
+<span class="sourceLineNo">469</span>   */<a name="line.469"></a>
+<span class="sourceLineNo">470</span>   int getUncompressedSizeWithoutHeader() {<a name="line.470"></a>
+<span class="sourceLineNo">471</span>    return uncompressedSizeWithoutHeader;<a name="line.471"></a>
+<span class="sourceLineNo">472</span>  }<a name="line.472"></a>
+<span class="sourceLineNo">473</span><a name="line.473"></a>
+<span class="sourceLineNo">474</span>  /**<a name="line.474"></a>
+<span class="sourceLineNo">475</span>   * @return the offset of the previous block of the same type in the file, or<a name="line.475"></a>
+<span class="sourceLineNo">476</span>   *         -1 if unknown<a name="line.476"></a>
+<span class="sourceLineNo">477</span>   */<a name="line.477"></a>
+<span class="sourceLineNo">478</span>  long getPrevBlockOffset() {<a name="line.478"></a>
+<span class="sourceLineNo">479</span>    return prevBlockOffset;<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>   * Rewinds {@code buf} and writes first 4 header fields. {@code buf} position<a name="line.483"></a>
+<span class="sourceLineNo">484</span>   * is modified as side-effect.<a name="line.484"></a>
+<span class="sourceLineNo">485</span>   */<a name="line.485"></a>
+<span class="sourceLineNo">486</span>  private void overwriteHeader() {<a name="line.486"></a>
+<span class="sourceLineNo">487</span>    buf.rewind();<a name="line.487"></a>
+<span class="sourceLineNo">488</span>    blockType.write(buf);<a name="line.488"></a>
+<span class="sourceLineNo">489</span>    buf.putInt(onDiskSizeWithoutHeader);<a name="line.489"></a>
+<span class="sourceLineNo">490</span>    buf.putInt(uncompressedSizeWithoutHeader);<a name="line.490"></a>
+<span class="sourceLineNo">491</span>    buf.putLong(prevBlockOffset);<a name="line.491"></a>
+<span class="sourceLineNo">492</span>    if (this.fileContext.isUseHBaseChecksum()) {<a name="line.492"></a>
+<span class="sourceLineNo">493</span>      buf.put(fileContext.getChecksumType().getCode());<a name="line.493"></a>
+<span class="sourceLineNo">494</span>      buf.putInt(fileContext.getBytesPerChecksum());<a name="line.494"></a>
+<span class="sourceLineNo">495</span>      buf.putInt(onDiskDataSizeWithHeader);<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><a name="line.498"></a>
+<span class="sourceLineNo">499</span>  /**<a name="line.499"></a>
+<span class="sourceLineNo">500</span>   * Returns a buffer that does not include the header or checksum.<a name="line.500"></a>
+<span class="sourceLineNo">501</span>   *<a name="line.501"></a>
+<span class="sourceLineNo">502</span>   * @return the buffer with header skipped and checksum omitted.<a name="line.502"></a>
+<span class="sourceLineNo">503</span>   */<a name="line.503"></a>
+<span class="sourceLineNo">504</span>  public ByteBuff getBufferWithoutHeader() {<a name="line.504"></a>
+<span class="sourceLineNo">505</span>    ByteBuff dup = getBufferReadOnly();<a name="line.505"></a>
+<span class="sourceLineNo">506</span>    // Now set it up so Buffer spans content only -- no header or no checksums.<a name="line.506"></a>
+<span class="sourceLineNo">507</span>    return dup.position(headerSize()).limit(buf.limit() - totalChecksumBytes()).slice();<a name="line.507"></a>
+<span class="sourceLineNo">508</span>  }<a name="line.508"></a>
+<span class="sourceLineNo">509</span><a name="line.509"></a>
+<span class="sourceLineNo">510</span>  /**<a name="line.510"></a>
+<span class="sourceLineNo">511</span>   * Returns a read-only duplicate of the buffer this block stores internally ready to be read.<a name="line.511"></a>
+<span class="sourceLineNo">512</span>   * Clients must not modify the buffer object though they may set position and limit on the<a name="line.512"></a>
+<span class="sourceLineNo">513</span>   * returned buffer since we pass back a duplicate. This method has to be public because it is used<a name="line.513"></a>
+<span class="sourceLineNo">514</span>   * in {@link CompoundBloomFilter} to avoid object creation on every Bloom<a name="line.514"></a>
+<span class="sourceLineNo">515</span>   * filter lookup, but has to be used with caution. Buffer holds header, block content,<a name="line.515"></a>
+<span class="sourceLineNo">516</span>   * and any follow-on checksums if present.<a name="line.516"></a>
+<span class="sourceLineNo">517</span>   *<a name="line.517"></a>
+<span class="sourceLineNo">518</span>   * @return the buffer of this block for read-only operations<a name="line.518"></a>
+<span class="sourceLineNo">519</span>   */<a name="line.519"></a>
+<span class="sourceLineNo">520</span>  public ByteBuff getBufferReadOnly() {<a name="line.520"></a>
+<span class="sourceLineNo">521</span>    // TODO: ByteBuf does not support asReadOnlyBuffer(). Fix.<a name="line.521"></a>
+<span class="sourceLineNo">522</span>    ByteBuff dup = this.buf.duplicate();<a name="line.522"></a>
+<span class="sourceLineNo">523</span>    assert dup.position() == 0;<a name="line.523"></a>
+<span class="sourceLineNo">524</span>    return dup;<a name="line.524"></a>
+<span class="sourceLineNo">525</span>  }<a name="line.525"></a>
+<span class="sourceLineNo">526</span><a name="line.526"></a>
+<span class="sourceLineNo">527</span>  @VisibleForTesting<a name="line.527"></a>
+<span class="sourceLineNo">528</span>  private void sanityCheckAssertion(long valueFromBuf, long valueFromField,<a name="line.528"></a>
+<span class="sourceLineNo">529</span>      String fieldName) throws IOException {<a name="line.529"></a>
+<span class="sourceLineNo">530</span>    if (valueFromBuf != valueFromField) {<a name="line.530"></a>
+<span class="sourceLineNo">531</span>      throw new AssertionError(fieldName + " in the buffer (" + valueFromBuf<a name="line.531"></a>
+<span class="sourceLineNo">532</span>          + ") is different from that in the field (" + valueFromField + ")");<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>  @VisibleForTesting<a name="line.536"></a>
+<span class="sourceLineNo">537</span>  private void sanityCheckAssertion(BlockType valueFromBuf, BlockType valueFromField)<a name="line.537"></a>
+<span class="sourceLineNo">538</span>      throws IOException {<a name="line.538"></a>
+<span class="sourceLineNo">539</span>    if (valueFromBuf != valueFromField) {<a name="line.539"></a>
+<span class="sourceLineNo">540</span>      throw new IOException("Block type stored in the buffer: " +<a name="line.540"></a>
+<span class="sourceLineNo">541</span>        valueFromBuf + ", block type field: " + valueFromField);<a name="line.541"></a>
+<span class="sourceLineNo">542</span>    }<a name="line.542"></a>
+<span class="sourceLineNo">543</span>  }<a name="line.543"></a>
+<span class="sourceLineNo">544</span><a name="line.544"></a>
+<span class="sourceLineNo">545</span>  /**<a name="line.545"></a>
+<span class="sourceLineNo">546</span>   * Checks if the block is internally consistent, i.e. the first<a name="line.546"></a>
+<span class="sourceLineNo">547</span>   * {@link HConstants#HFILEBLOCK_HEADER_SIZE} bytes of the buffer contain a<a name="line.547"></a>
+<span class="sourceLineNo">548</span>   * valid header consistent with the fields. Assumes a packed block structure.<a name="line.548"></a>
+<span class="sourceLineNo">549</span>   * This function is primary for testing and debugging, and is not<a name="line.549"></a>
+<span class="sourceLineNo">550</span>   * thread-safe, because it alters the internal buffer pointer.<a name="line.550"></a>
+<span class="sourceLineNo">551</span>   * Used by tests only.<a name="line.551"></a>
+<span class="sourceLineNo">552</span>   */<a name="line.552"></a>
+<span class="sourceLineNo">553</span>  @VisibleForTesting<a name="line.553"></a>
+<span class="sourceLineNo">554</span>  void sanityCheck() throws IOException {<a name="line.554"></a>
+<span class="sourceLineNo">555</span>    // Duplicate so no side-effects<a name="line.555"></a>
+<span class="sourceLineNo">556</span>    ByteBuff dup = this.buf.duplicate().rewind();<a name="line.556"></a>
+<span class="sourceLineNo">557</span>    sanityCheckAssertion(BlockType.read(dup), blockType);<a name="line.557"></a>
+<span class="sourceLineNo">558</span><a name="line.558"></a>
+<span class="sourceLineNo">559</span>    sanityCheckAssertion(dup.getInt(), onDiskSizeWithoutHeader, "onDiskSizeWithoutHeader");<a name="line.559"></a>
+<span class="sourceLineNo">560</span><a name="line.560"></a>
+<span class="sourceLineNo">561</span>    sanityCheckAssertion(dup.getInt(), uncompressedSizeWithoutHeader,<a name="line.561"></a>
+<span class="sourceLineNo">562</span>        "uncompressedSizeWithoutHeader");<a name="line.562"></a>
+<span class="sourceLineNo">563</span><a name="line.563"></a>
+<span class="sourceLineNo">564</span>    sanityCheckAssertion(dup.getLong(), prevBlockOffset, "prevBlockOffset");<a name="line.564"></a>
+<span class="sourceLineNo">565</span>    if (this.fileContext.isUseHBaseChecksum()) {<a name="line.565"></a>
+<span class="sourceLineNo">566</span>      sanityCheckAssertion(dup.get(), this.fileContext.getChecksumType().getCode(), "checksumType");<a name="line.566"></a>
+<span class="sourceLineNo">567</span>      sanityCheckAssertion(dup.getInt(), this.fileContext.getBytesPerChecksum(),<a name="line.567"></a>
+<span class="sourceLineNo">568</span>          "bytesPerChecksum");<a name="line.568"></a>
+<span class="sourceLineNo">569</span>      sanityCheckAssertion(dup.getInt(), onDiskDataSizeWithHeader, "onDiskDataSizeWithHeader");<a name="line.569"></a>
+<span class="sourceLineNo">570</span>    }<a name="line.570"></a>
+<span class="sourceLineNo">571</span><a name="line.571"></a>
+<span class="sourceLineNo">572</span>    int cksumBytes = totalChecksumBytes();<a name="line.572"></a>
+<span class="sourceLineNo">573</span>    int expectedBufLimit = onDiskDataSizeWithHeader + cksumBytes;<a name="line.573"></a>
+<span class="sourceLineNo">574</span>    if (dup.limit() != expectedBufLimit) {<a name="line.574"></a>
+<span class="sourceLineNo">575</span>      throw new AssertionError("Expected limit " + expectedBufLimit + ", got " + dup.limit());<a name="line.575"></a>
+<span class="sourceLineNo">576</span>    }<a name="line.576"></a>
+<span class="sourceLineNo">577</span><a name="line.577"></a>
+<span class="sourceLineNo">578</span>    // We might optionally allocate HFILEBLOCK_HEADER_SIZE more bytes to read the next<a name="line.578"></a>
+<span class="sourceLineNo">579</span>    // block's header, so there are two sensible values for buffer capacity.<a name="line.579"></a>
+<span class="sourceLineNo">580</span>    int hdrSize = headerSize();<a name="line.580"></a>
+<span class="sourceLineNo">581</span>    if (dup.capacity() != expectedBufLimit &amp;&amp; dup.capacity() != expectedBufLimit + hdrSize) {<a name="line.581"></a>
+<span class="sourceLineNo">582</span>      throw new AssertionError("Invalid buffer capacity: " + dup.capacity() +<a name="line.582"></a>
+<span class="sourceLineNo">583</span>          ", expected " + expectedBufLimit + " or " + (expectedBufLimit + hdrSize));<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>  @Override<a name="line.587"></a>
+<span class="sourceLineNo">588</span>  public String toString() {<a name="line.588"></a>
+<span class="sourceLineNo">589</span>    StringBuilder sb = new StringBuilder()<a name="line.589"></a>
+<span class="sourceLineNo">590</span>      .append("[")<a name="line.590"></a>
+<span class="sourceLineNo">591</span>      .append("blockType=").append(blockType)<a name="line.591"></a>
+<span class="sourceLineNo">592</span>      .append(", fileOffset=").append(offset)<a name="line.592"></a>
+<span class="sourceLineNo">593</span>      .append(", headerSize=").append(headerSize())<a name="line.593"></a>
+<span class="sourceLineNo">594</span>      .append(", onDiskSizeWithoutHeader=").append(onDiskSizeWithoutHeader)<a name="line.594"></a>
+<span class="sourceLineNo">595</span>      .append(", uncompressedSizeWithoutHeader=").append(uncompressedSizeWithoutHeader)<a name="line.595"></a>
+<span class="sourceLineNo">596</span>      .append(", prevBlockOffset=").append(prevBlockOffset)<a name="line.596"></a>
+<span class="sourceLineNo">597</span>      .append(", isUseHBaseChecksum=").append(fileContext.isUseHBaseChecksum());<a name="line.597"></a>
+<span class="sourceLineNo">598</span>    if (fileContext.isUseHBaseChecksum()) {<a name="line.598"></a>
+<span class="sourceLineNo">599</span>      sb.append(", checksumType=").append(ChecksumType.codeToType(this.buf.get(24)))<a name="line.599"></a>
+<span class="sourceLineNo">600</span>        .append(", bytesPerChecksum=").append(this.buf.getInt(24 + 1))<a name="line.600"></a>
+<span class="sourceLineNo">601</span>        .append(", onDiskDataSizeWithHeader=").append(onDiskDataSizeWithHeader);<a name="line.601"></a>
+<span class="sourceLineNo">602</span>    } else {<a name="line.602"></a>
+<span class="sourceLineNo">603</span>      sb.append(", onDiskDataSizeWithHeader=").append(onDiskDataSizeWithHeader)<a name="line.603"></a>
+<span class="sourceLineNo">604</span>        .append("(").append(onDiskSizeWithoutHeader)<a name="line.604"></a>
+<span class="sourceLineNo">605</span>        .append("+").append(HConstants.HFILEBLOCK_HEADER_SIZE_NO_CHECKSUM).append(")");<a name="line.605"></a>
+<span class="sourceLineNo">606</span>    }<a name="line.606"></a>
+<span class="sourceLineNo">607</span>    String dataBegin = null;<a name="line.607"></a>
+<span class="sourceLineNo">608</span>    if (buf.hasArray()) {<a name="line.608"></a>
+<span class="sourceLineNo">609</span>      dataBegin = Bytes.toStringBinary(buf.array(), buf.arrayOffset() + headerSize(),<a name="line.609"></a>
+<span class="sourceLineNo">610</span>          Math.min(32, buf.limit() - buf.arrayOffset() - headerSize()));<a name="line.610"></a>
+<span class="sourceLineNo">611</span>    } else {<a name="line.611"></a>
+<span class="sourceLineNo">612</span>      ByteBuff bufWithoutHeader = getBufferWithoutHeader();<a name="line.612"></a>
+<span class="sourceLineNo">613</span>      byte[] dataBeginBytes = new byte[Math.min(32,<a name="line.613"></a>
+<span class="sourceLineNo">614</span>          bufWithoutHeader.limit() - bufWithoutHeader.position())];<a name="line.614"></a>
+<span class="sourceLineNo">615</span>      bufWithoutHeader.get(dataBeginBytes);<a name="line.615"></a>
+<span class="sourceLineNo">616</span>      dataBegin = Bytes.toStringBinary(dataBeginBytes);<a name="line.616"></a>
+<span class="sourceLineNo">617</span>    }<a name="line.617"></a>
+<span class="sourceLineNo">618</span>    sb.append(", getOnDiskSizeWithHeader=").append(getOnDiskSizeWithHeader())<a name="line.618"></a>
+<span class="sourceLineNo">619</span>      .append(", totalChecksumBytes=").append(totalChecksumBytes())<a name="line.619"></a>
+<span class="sourceLineNo">620</span>      .append(", isUnpacked=").append(isUnpacked())<a name="line.620"></a>
+<span class="sourceLineNo">621</span>      .append(", buf=[").append(buf).append("]")<a name="line.621"></a>
+<span class="sourceLineNo">622</span>      .append(", dataBeginsWith=").append(dataBegin)<a name="line.622"></a>
+<span class="sourceLineNo">623</span>      .append(", fileContext=").append(fileContext)<a name="line.623"></a>
+<span class="sourceLineNo">624</span>      .append(", nextBlockOnDiskSize=").append(nextBlockOnDiskSize)<a name="line.624"></a>
+<span class="sourceLineNo">625</span>      .append("]");<a name="line.625"></a>
+<span class="sourceLineNo">626</span>    return sb.toString();<a name="line.626"></a>
+<span class="sourceLineNo">627</span>  }<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>   * Retrieves the decompressed/decrypted view of this block. An encoded block remains in its<a name="line.630"></a>
+<span class="sourceLineNo">631</span>   * encoded structure. Internal structures are shared between instances where applicable.<a name="line.631"></a>
+<span class="sourceLineNo">632</span>   */<a name="line.632"></a>
+<span class="sourceLineNo">633</span>  HFileBlock unpack(HFileContext fileContext, FSReader reader) throws IOException {<a name="line.633"></a>
+<span class="sourceLineNo">634</span>    if (!fileContext.isCompressedOrEncrypted()) {<a name="line.634"></a>
+<span class="sourceLineNo">635</span>      // TODO: cannot use our own fileContext here because HFileBlock(ByteBuffer, boolean),<a name="line.635"></a>
+<span class="sourceLineNo">636</span>      // which is used for block serialization to L2 cache, does not preserve encoding and<a name="line.636"></a>
+<span class="sourceLineNo">637</span>      // encryption details.<a name="line.637"></a>
+<span class="sourceLineNo">638</span>      return this;<a name="line.638"></a>
+<span class="sourceLineNo">639</span>    }<a name="line.639"></a>
+<span class="sourceLineNo">640</span><a name="line.640"></a>
+<span class="sourceLineNo">641</span>    HFileBlock unpacked = new HFileBlock(this);<a name="line.641"></a>
+<span class="sourceLineNo">642</span>    unpacked.allocateBuffer(); // allocates space for the decompressed block<a name="line.642"></a>
+<span class="sourceLineNo">643</span><a name="line.643"></a>
+<span class="sourceLineNo">644</span>    HFileBlockDecodingContext ctx = blockType == BlockType.ENCODED_DATA ?<a name="line.644"></a>
+<span class="sourceLineNo">645</span>      reader.getBlockDecodingContext() : reader.getDefaultBlockDecodingContext();<a name="line.645"></a>
+<span class="sourceLineNo">646</span><a name="line.646"></a>
+<span class="sourceLineNo">647</span>    ByteBuff dup = this.buf.duplicate();<a name="line.647"></a>
+<span class="sourceLineNo">648</span>    dup.position(this.headerSize());<a name="line.648"></a>
+<span class="sourceLineNo">649</span>    dup = dup.slice();<a name="line.649"></a>
+<span class="sourceLineNo">650</span>    ctx.prepareD

<TRUNCATED>

[14/50] hbase-site git commit: Published site at 26babcf013de696b899d76a3c39434b794440d8d.

Posted by gi...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.ProgressFields.html
----------------------------------------------------------------------
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.ProgressFields.html b/devapidocs/src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.ProgressFields.html
index cabb570..90f3b1e 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.ProgressFields.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.ProgressFields.html
@@ -107,660 +107,661 @@
 <span class="sourceLineNo">099</span><a name="line.99"></a>
 <span class="sourceLineNo">100</span>  private Cell lastPeekedCell = null;<a name="line.100"></a>
 <span class="sourceLineNo">101</span><a name="line.101"></a>
-<span class="sourceLineNo">102</span>  /**<a name="line.102"></a>
-<span class="sourceLineNo">103</span>   * Tracks the relevant server side metrics during scans. null when metrics should not be tracked<a name="line.103"></a>
-<span class="sourceLineNo">104</span>   */<a name="line.104"></a>
-<span class="sourceLineNo">105</span>  final ServerSideScanMetrics metrics;<a name="line.105"></a>
-<span class="sourceLineNo">106</span><a name="line.106"></a>
-<span class="sourceLineNo">107</span>  ScannerContext(boolean keepProgress, LimitFields limitsToCopy, boolean trackMetrics) {<a name="line.107"></a>
-<span class="sourceLineNo">108</span>    this.limits = new LimitFields();<a name="line.108"></a>
-<span class="sourceLineNo">109</span>    if (limitsToCopy != null) {<a name="line.109"></a>
-<span class="sourceLineNo">110</span>      this.limits.copy(limitsToCopy);<a name="line.110"></a>
-<span class="sourceLineNo">111</span>    }<a name="line.111"></a>
+<span class="sourceLineNo">102</span>  // Set this to true will have the same behavior with reaching the time limit.<a name="line.102"></a>
+<span class="sourceLineNo">103</span>  // This is used when you want to make the current RSRpcService.scan returns immediately. For<a name="line.103"></a>
+<span class="sourceLineNo">104</span>  // example, when we want to switch from pread to stream, we can only do it after the rpc call is<a name="line.104"></a>
+<span class="sourceLineNo">105</span>  // returned.<a name="line.105"></a>
+<span class="sourceLineNo">106</span>  private boolean returnImmediately;<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>   * Tracks the relevant server side metrics during scans. null when metrics should not be tracked<a name="line.109"></a>
+<span class="sourceLineNo">110</span>   */<a name="line.110"></a>
+<span class="sourceLineNo">111</span>  final ServerSideScanMetrics metrics;<a name="line.111"></a>
 <span class="sourceLineNo">112</span><a name="line.112"></a>
-<span class="sourceLineNo">113</span>    // Progress fields are initialized to 0<a name="line.113"></a>
-<span class="sourceLineNo">114</span>    progress = new ProgressFields(0, 0, 0);<a name="line.114"></a>
-<span class="sourceLineNo">115</span><a name="line.115"></a>
-<span class="sourceLineNo">116</span>    this.keepProgress = keepProgress;<a name="line.116"></a>
-<span class="sourceLineNo">117</span>    this.scannerState = DEFAULT_STATE;<a name="line.117"></a>
-<span class="sourceLineNo">118</span>    this.metrics = trackMetrics ? new ServerSideScanMetrics() : null;<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>  boolean isTrackingMetrics() {<a name="line.121"></a>
-<span class="sourceLineNo">122</span>    return this.metrics != null;<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>   * Get the metrics instance. Should only be called after a call to {@link #isTrackingMetrics()}<a name="line.126"></a>
-<span class="sourceLineNo">127</span>   * has been made to confirm that metrics are indeed being tracked.<a name="line.127"></a>
-<span class="sourceLineNo">128</span>   * @return {@link ServerSideScanMetrics} instance that is tracking metrics for this scan<a name="line.128"></a>
-<span class="sourceLineNo">129</span>   */<a name="line.129"></a>
-<span class="sourceLineNo">130</span>  ServerSideScanMetrics getMetrics() {<a name="line.130"></a>
-<span class="sourceLineNo">131</span>    assert isTrackingMetrics();<a name="line.131"></a>
-<span class="sourceLineNo">132</span>    return this.metrics;<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>   * @return true if the progress tracked so far in this instance will be considered during an<a name="line.136"></a>
-<span class="sourceLineNo">137</span>   *         invocation of {@link InternalScanner#next(java.util.List)} or<a name="line.137"></a>
-<span class="sourceLineNo">138</span>   *         {@link RegionScanner#next(java.util.List)}. false when the progress tracked so far<a name="line.138"></a>
-<span class="sourceLineNo">139</span>   *         should not be considered and should instead be wiped away via {@link #clearProgress()}<a name="line.139"></a>
-<span class="sourceLineNo">140</span>   */<a name="line.140"></a>
-<span class="sourceLineNo">141</span>  boolean getKeepProgress() {<a name="line.141"></a>
-<span class="sourceLineNo">142</span>    return keepProgress;<a name="line.142"></a>
-<span class="sourceLineNo">143</span>  }<a name="line.143"></a>
-<span class="sourceLineNo">144</span><a name="line.144"></a>
-<span class="sourceLineNo">145</span>  void setKeepProgress(boolean keepProgress) {<a name="line.145"></a>
-<span class="sourceLineNo">146</span>    this.keepProgress = keepProgress;<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>   * Progress towards the batch limit has been made. Increment internal tracking of batch progress<a name="line.150"></a>
-<span class="sourceLineNo">151</span>   */<a name="line.151"></a>
-<span class="sourceLineNo">152</span>  void incrementBatchProgress(int batch) {<a name="line.152"></a>
-<span class="sourceLineNo">153</span>    int currentBatch = progress.getBatch();<a name="line.153"></a>
-<span class="sourceLineNo">154</span>    progress.setBatch(currentBatch + batch);<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>   * Progress towards the size limit has been made. Increment internal tracking of size progress<a name="line.158"></a>
-<span class="sourceLineNo">159</span>   */<a name="line.159"></a>
-<span class="sourceLineNo">160</span>  void incrementSizeProgress(long dataSize, long heapSize) {<a name="line.160"></a>
-<span class="sourceLineNo">161</span>    long curDataSize = progress.getDataSize();<a name="line.161"></a>
-<span class="sourceLineNo">162</span>    progress.setDataSize(curDataSize + dataSize);<a name="line.162"></a>
-<span class="sourceLineNo">163</span>    long curHeapSize = progress.getHeapSize();<a name="line.163"></a>
-<span class="sourceLineNo">164</span>    progress.setHeapSize(curHeapSize + heapSize);<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>  int getBatchProgress() {<a name="line.167"></a>
-<span class="sourceLineNo">168</span>    return progress.getBatch();<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>  long getDataSizeProgress() {<a name="line.171"></a>
-<span class="sourceLineNo">172</span>    return progress.getDataSize();<a name="line.172"></a>
-<span class="sourceLineNo">173</span>  }<a name="line.173"></a>
-<span class="sourceLineNo">174</span><a name="line.174"></a>
-<span class="sourceLineNo">175</span>  long getHeapSizeProgress() {<a name="line.175"></a>
-<span class="sourceLineNo">176</span>    return progress.getHeapSize();<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>  void setProgress(int batchProgress, long sizeProgress, long heapSizeProgress) {<a name="line.179"></a>
-<span class="sourceLineNo">180</span>    setBatchProgress(batchProgress);<a name="line.180"></a>
-<span class="sourceLineNo">181</span>    setSizeProgress(sizeProgress, heapSizeProgress);<a name="line.181"></a>
-<span class="sourceLineNo">182</span>  }<a name="line.182"></a>
-<span class="sourceLineNo">183</span><a name="line.183"></a>
-<span class="sourceLineNo">184</span>  void setSizeProgress(long dataSizeProgress, long heapSizeProgress) {<a name="line.184"></a>
-<span class="sourceLineNo">185</span>    progress.setDataSize(dataSizeProgress);<a name="line.185"></a>
-<span class="sourceLineNo">186</span>    progress.setHeapSize(heapSizeProgress);<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>  void setBatchProgress(int batchProgress) {<a name="line.189"></a>
-<span class="sourceLineNo">190</span>    progress.setBatch(batchProgress);<a name="line.190"></a>
-<span class="sourceLineNo">191</span>  }<a name="line.191"></a>
-<span class="sourceLineNo">192</span><a name="line.192"></a>
-<span class="sourceLineNo">193</span>  /**<a name="line.193"></a>
-<span class="sourceLineNo">194</span>   * Clear away any progress that has been made so far. All progress fields are reset to initial<a name="line.194"></a>
-<span class="sourceLineNo">195</span>   * values<a name="line.195"></a>
-<span class="sourceLineNo">196</span>   */<a name="line.196"></a>
-<span class="sourceLineNo">197</span>  void clearProgress() {<a name="line.197"></a>
-<span class="sourceLineNo">198</span>    progress.setFields(0, 0, 0);<a name="line.198"></a>
-<span class="sourceLineNo">199</span>  }<a name="line.199"></a>
-<span class="sourceLineNo">200</span><a name="line.200"></a>
-<span class="sourceLineNo">201</span>  /**<a name="line.201"></a>
-<span class="sourceLineNo">202</span>   * Note that this is not a typical setter. This setter returns the {@link NextState} that was<a name="line.202"></a>
-<span class="sourceLineNo">203</span>   * passed in so that methods can be invoked against the new state. Furthermore, this pattern<a name="line.203"></a>
-<span class="sourceLineNo">204</span>   * allows the {@link NoLimitScannerContext} to cleanly override this setter and simply return the<a name="line.204"></a>
-<span class="sourceLineNo">205</span>   * new state, thus preserving the immutability of {@link NoLimitScannerContext}<a name="line.205"></a>
-<span class="sourceLineNo">206</span>   * @param state<a name="line.206"></a>
-<span class="sourceLineNo">207</span>   * @return The state that was passed in.<a name="line.207"></a>
-<span class="sourceLineNo">208</span>   */<a name="line.208"></a>
-<span class="sourceLineNo">209</span>  NextState setScannerState(NextState state) {<a name="line.209"></a>
-<span class="sourceLineNo">210</span>    if (!NextState.isValidState(state)) {<a name="line.210"></a>
-<span class="sourceLineNo">211</span>      throw new IllegalArgumentException("Cannot set to invalid state: " + state);<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>    this.scannerState = state;<a name="line.214"></a>
-<span class="sourceLineNo">215</span>    return state;<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>  /**<a name="line.218"></a>
-<span class="sourceLineNo">219</span>   * @return true when we have more cells for the current row. This usually because we have reached<a name="line.219"></a>
-<span class="sourceLineNo">220</span>   *         a limit in the middle of a row<a name="line.220"></a>
-<span class="sourceLineNo">221</span>   */<a name="line.221"></a>
-<span class="sourceLineNo">222</span>  boolean mayHaveMoreCellsInRow() {<a name="line.222"></a>
-<span class="sourceLineNo">223</span>    return scannerState == NextState.SIZE_LIMIT_REACHED_MID_ROW ||<a name="line.223"></a>
-<span class="sourceLineNo">224</span>        scannerState == NextState.TIME_LIMIT_REACHED_MID_ROW ||<a name="line.224"></a>
-<span class="sourceLineNo">225</span>        scannerState == NextState.BATCH_LIMIT_REACHED;<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>  /**<a name="line.228"></a>
-<span class="sourceLineNo">229</span>   * @param checkerScope<a name="line.229"></a>
-<span class="sourceLineNo">230</span>   * @return true if the batch limit can be enforced in the checker's scope<a name="line.230"></a>
-<span class="sourceLineNo">231</span>   */<a name="line.231"></a>
-<span class="sourceLineNo">232</span>  boolean hasBatchLimit(LimitScope checkerScope) {<a name="line.232"></a>
-<span class="sourceLineNo">233</span>    return limits.canEnforceBatchLimitFromScope(checkerScope) &amp;&amp; limits.getBatch() &gt; 0;<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>   * @param checkerScope<a name="line.237"></a>
-<span class="sourceLineNo">238</span>   * @return true if the size limit can be enforced in the checker's scope<a name="line.238"></a>
-<span class="sourceLineNo">239</span>   */<a name="line.239"></a>
-<span class="sourceLineNo">240</span>  boolean hasSizeLimit(LimitScope checkerScope) {<a name="line.240"></a>
-<span class="sourceLineNo">241</span>    return limits.canEnforceSizeLimitFromScope(checkerScope)<a name="line.241"></a>
-<span class="sourceLineNo">242</span>        &amp;&amp; (limits.getDataSize() &gt; 0 || limits.getHeapSize() &gt; 0);<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>  /**<a name="line.245"></a>
-<span class="sourceLineNo">246</span>   * @param checkerScope<a name="line.246"></a>
-<span class="sourceLineNo">247</span>   * @return true if the time limit can be enforced in the checker's scope<a name="line.247"></a>
-<span class="sourceLineNo">248</span>   */<a name="line.248"></a>
-<span class="sourceLineNo">249</span>  boolean hasTimeLimit(LimitScope checkerScope) {<a name="line.249"></a>
-<span class="sourceLineNo">250</span>    return limits.canEnforceTimeLimitFromScope(checkerScope) &amp;&amp; limits.getTime() &gt; 0;<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>   * @param checkerScope<a name="line.254"></a>
-<span class="sourceLineNo">255</span>   * @return true if any limit can be enforced within the checker's scope<a name="line.255"></a>
-<span class="sourceLineNo">256</span>   */<a name="line.256"></a>
-<span class="sourceLineNo">257</span>  boolean hasAnyLimit(LimitScope checkerScope) {<a name="line.257"></a>
-<span class="sourceLineNo">258</span>    return hasBatchLimit(checkerScope) || hasSizeLimit(checkerScope) || hasTimeLimit(checkerScope);<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>  /**<a name="line.261"></a>
-<span class="sourceLineNo">262</span>   * @param scope The scope in which the size limit will be enforced<a name="line.262"></a>
+<span class="sourceLineNo">113</span>  ScannerContext(boolean keepProgress, LimitFields limitsToCopy, boolean trackMetrics) {<a name="line.113"></a>
+<span class="sourceLineNo">114</span>    this.limits = new LimitFields();<a name="line.114"></a>
+<span class="sourceLineNo">115</span>    if (limitsToCopy != null) {<a name="line.115"></a>
+<span class="sourceLineNo">116</span>      this.limits.copy(limitsToCopy);<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>    // Progress fields are initialized to 0<a name="line.119"></a>
+<span class="sourceLineNo">120</span>    progress = new ProgressFields(0, 0, 0);<a name="line.120"></a>
+<span class="sourceLineNo">121</span><a name="line.121"></a>
+<span class="sourceLineNo">122</span>    this.keepProgress = keepProgress;<a name="line.122"></a>
+<span class="sourceLineNo">123</span>    this.scannerState = DEFAULT_STATE;<a name="line.123"></a>
+<span class="sourceLineNo">124</span>    this.metrics = trackMetrics ? new ServerSideScanMetrics() : null;<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>  boolean isTrackingMetrics() {<a name="line.127"></a>
+<span class="sourceLineNo">128</span>    return this.metrics != null;<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>   * Get the metrics instance. Should only be called after a call to {@link #isTrackingMetrics()}<a name="line.132"></a>
+<span class="sourceLineNo">133</span>   * has been made to confirm that metrics are indeed being tracked.<a name="line.133"></a>
+<span class="sourceLineNo">134</span>   * @return {@link ServerSideScanMetrics} instance that is tracking metrics for this scan<a name="line.134"></a>
+<span class="sourceLineNo">135</span>   */<a name="line.135"></a>
+<span class="sourceLineNo">136</span>  ServerSideScanMetrics getMetrics() {<a name="line.136"></a>
+<span class="sourceLineNo">137</span>    assert isTrackingMetrics();<a name="line.137"></a>
+<span class="sourceLineNo">138</span>    return this.metrics;<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>   * @return true if the progress tracked so far in this instance will be considered during an<a name="line.142"></a>
+<span class="sourceLineNo">143</span>   *         invocation of {@link InternalScanner#next(java.util.List)} or<a name="line.143"></a>
+<span class="sourceLineNo">144</span>   *         {@link RegionScanner#next(java.util.List)}. false when the progress tracked so far<a name="line.144"></a>
+<span class="sourceLineNo">145</span>   *         should not be considered and should instead be wiped away via {@link #clearProgress()}<a name="line.145"></a>
+<span class="sourceLineNo">146</span>   */<a name="line.146"></a>
+<span class="sourceLineNo">147</span>  boolean getKeepProgress() {<a name="line.147"></a>
+<span class="sourceLineNo">148</span>    return keepProgress;<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>  void setKeepProgress(boolean keepProgress) {<a name="line.151"></a>
+<span class="sourceLineNo">152</span>    this.keepProgress = keepProgress;<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>   * Progress towards the batch limit has been made. Increment internal tracking of batch progress<a name="line.156"></a>
+<span class="sourceLineNo">157</span>   */<a name="line.157"></a>
+<span class="sourceLineNo">158</span>  void incrementBatchProgress(int batch) {<a name="line.158"></a>
+<span class="sourceLineNo">159</span>    int currentBatch = progress.getBatch();<a name="line.159"></a>
+<span class="sourceLineNo">160</span>    progress.setBatch(currentBatch + batch);<a name="line.160"></a>
+<span class="sourceLineNo">161</span>  }<a name="line.161"></a>
+<span class="sourceLineNo">162</span><a name="line.162"></a>
+<span class="sourceLineNo">163</span>  /**<a name="line.163"></a>
+<span class="sourceLineNo">164</span>   * Progress towards the size limit has been made. Increment internal tracking of size progress<a name="line.164"></a>
+<span class="sourceLineNo">165</span>   */<a name="line.165"></a>
+<span class="sourceLineNo">166</span>  void incrementSizeProgress(long dataSize, long heapSize) {<a name="line.166"></a>
+<span class="sourceLineNo">167</span>    long curDataSize = progress.getDataSize();<a name="line.167"></a>
+<span class="sourceLineNo">168</span>    progress.setDataSize(curDataSize + dataSize);<a name="line.168"></a>
+<span class="sourceLineNo">169</span>    long curHeapSize = progress.getHeapSize();<a name="line.169"></a>
+<span class="sourceLineNo">170</span>    progress.setHeapSize(curHeapSize + heapSize);<a name="line.170"></a>
+<span class="sourceLineNo">171</span>  }<a name="line.171"></a>
+<span class="sourceLineNo">172</span><a name="line.172"></a>
+<span class="sourceLineNo">173</span>  int getBatchProgress() {<a name="line.173"></a>
+<span class="sourceLineNo">174</span>    return progress.getBatch();<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>  long getDataSizeProgress() {<a name="line.177"></a>
+<span class="sourceLineNo">178</span>    return progress.getDataSize();<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>  long getHeapSizeProgress() {<a name="line.181"></a>
+<span class="sourceLineNo">182</span>    return progress.getHeapSize();<a name="line.182"></a>
+<span class="sourceLineNo">183</span>  }<a name="line.183"></a>
+<span class="sourceLineNo">184</span><a name="line.184"></a>
+<span class="sourceLineNo">185</span>  void setProgress(int batchProgress, long sizeProgress, long heapSizeProgress) {<a name="line.185"></a>
+<span class="sourceLineNo">186</span>    setBatchProgress(batchProgress);<a name="line.186"></a>
+<span class="sourceLineNo">187</span>    setSizeProgress(sizeProgress, heapSizeProgress);<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>  void setSizeProgress(long dataSizeProgress, long heapSizeProgress) {<a name="line.190"></a>
+<span class="sourceLineNo">191</span>    progress.setDataSize(dataSizeProgress);<a name="line.191"></a>
+<span class="sourceLineNo">192</span>    progress.setHeapSize(heapSizeProgress);<a name="line.192"></a>
+<span class="sourceLineNo">193</span>  }<a name="line.193"></a>
+<span class="sourceLineNo">194</span><a name="line.194"></a>
+<span class="sourceLineNo">195</span>  void setBatchProgress(int batchProgress) {<a name="line.195"></a>
+<span class="sourceLineNo">196</span>    progress.setBatch(batchProgress);<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>   * Clear away any progress that has been made so far. All progress fields are reset to initial<a name="line.200"></a>
+<span class="sourceLineNo">201</span>   * values<a name="line.201"></a>
+<span class="sourceLineNo">202</span>   */<a name="line.202"></a>
+<span class="sourceLineNo">203</span>  void clearProgress() {<a name="line.203"></a>
+<span class="sourceLineNo">204</span>    progress.setFields(0, 0, 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>  /**<a name="line.207"></a>
+<span class="sourceLineNo">208</span>   * Note that this is not a typical setter. This setter returns the {@link NextState} that was<a name="line.208"></a>
+<span class="sourceLineNo">209</span>   * passed in so that methods can be invoked against the new state. Furthermore, this pattern<a name="line.209"></a>
+<span class="sourceLineNo">210</span>   * allows the {@link NoLimitScannerContext} to cleanly override this setter and simply return the<a name="line.210"></a>
+<span class="sourceLineNo">211</span>   * new state, thus preserving the immutability of {@link NoLimitScannerContext}<a name="line.211"></a>
+<span class="sourceLineNo">212</span>   * @param state<a name="line.212"></a>
+<span class="sourceLineNo">213</span>   * @return The state that was passed in.<a name="line.213"></a>
+<span class="sourceLineNo">214</span>   */<a name="line.214"></a>
+<span class="sourceLineNo">215</span>  NextState setScannerState(NextState state) {<a name="line.215"></a>
+<span class="sourceLineNo">216</span>    if (!NextState.isValidState(state)) {<a name="line.216"></a>
+<span class="sourceLineNo">217</span>      throw new IllegalArgumentException("Cannot set to invalid state: " + state);<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>    this.scannerState = state;<a name="line.220"></a>
+<span class="sourceLineNo">221</span>    return state;<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>  /**<a name="line.224"></a>
+<span class="sourceLineNo">225</span>   * @return true when we have more cells for the current row. This usually because we have reached<a name="line.225"></a>
+<span class="sourceLineNo">226</span>   *         a limit in the middle of a row<a name="line.226"></a>
+<span class="sourceLineNo">227</span>   */<a name="line.227"></a>
+<span class="sourceLineNo">228</span>  boolean mayHaveMoreCellsInRow() {<a name="line.228"></a>
+<span class="sourceLineNo">229</span>    return scannerState == NextState.SIZE_LIMIT_REACHED_MID_ROW ||<a name="line.229"></a>
+<span class="sourceLineNo">230</span>        scannerState == NextState.TIME_LIMIT_REACHED_MID_ROW ||<a name="line.230"></a>
+<span class="sourceLineNo">231</span>        scannerState == NextState.BATCH_LIMIT_REACHED;<a name="line.231"></a>
+<span class="sourceLineNo">232</span>  }<a name="line.232"></a>
+<span class="sourceLineNo">233</span><a name="line.233"></a>
+<span class="sourceLineNo">234</span>  /**<a name="line.234"></a>
+<span class="sourceLineNo">235</span>   * @param checkerScope<a name="line.235"></a>
+<span class="sourceLineNo">236</span>   * @return true if the batch limit can be enforced in the checker's scope<a name="line.236"></a>
+<span class="sourceLineNo">237</span>   */<a name="line.237"></a>
+<span class="sourceLineNo">238</span>  boolean hasBatchLimit(LimitScope checkerScope) {<a name="line.238"></a>
+<span class="sourceLineNo">239</span>    return limits.canEnforceBatchLimitFromScope(checkerScope) &amp;&amp; limits.getBatch() &gt; 0;<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>   * @param checkerScope<a name="line.243"></a>
+<span class="sourceLineNo">244</span>   * @return true if the size limit can be enforced in the checker's scope<a name="line.244"></a>
+<span class="sourceLineNo">245</span>   */<a name="line.245"></a>
+<span class="sourceLineNo">246</span>  boolean hasSizeLimit(LimitScope checkerScope) {<a name="line.246"></a>
+<span class="sourceLineNo">247</span>    return limits.canEnforceSizeLimitFromScope(checkerScope)<a name="line.247"></a>
+<span class="sourceLineNo">248</span>        &amp;&amp; (limits.getDataSize() &gt; 0 || limits.getHeapSize() &gt; 0);<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>
+<span class="sourceLineNo">252</span>   * @param checkerScope<a name="line.252"></a>
+<span class="sourceLineNo">253</span>   * @return true if the time limit can be enforced in the checker's scope<a name="line.253"></a>
+<span class="sourceLineNo">254</span>   */<a name="line.254"></a>
+<span class="sourceLineNo">255</span>  boolean hasTimeLimit(LimitScope checkerScope) {<a name="line.255"></a>
+<span class="sourceLineNo">256</span>    return limits.canEnforceTimeLimitFromScope(checkerScope) &amp;&amp;<a name="line.256"></a>
+<span class="sourceLineNo">257</span>      (limits.getTime() &gt; 0 || returnImmediately);<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>   * @param checkerScope<a name="line.261"></a>
+<span class="sourceLineNo">262</span>   * @return true if any limit can be enforced within the checker's scope<a name="line.262"></a>
 <span class="sourceLineNo">263</span>   */<a name="line.263"></a>
-<span class="sourceLineNo">264</span>  void setSizeLimitScope(LimitScope scope) {<a name="line.264"></a>
-<span class="sourceLineNo">265</span>    limits.setSizeScope(scope);<a name="line.265"></a>
+<span class="sourceLineNo">264</span>  boolean hasAnyLimit(LimitScope checkerScope) {<a name="line.264"></a>
+<span class="sourceLineNo">265</span>    return hasBatchLimit(checkerScope) || hasSizeLimit(checkerScope) || hasTimeLimit(checkerScope);<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>  /**<a name="line.268"></a>
-<span class="sourceLineNo">269</span>   * @param scope The scope in which the time limit will be enforced<a name="line.269"></a>
+<span class="sourceLineNo">269</span>   * @param scope The scope in which the size limit will be enforced<a name="line.269"></a>
 <span class="sourceLineNo">270</span>   */<a name="line.270"></a>
-<span class="sourceLineNo">271</span>  void setTimeLimitScope(LimitScope scope) {<a name="line.271"></a>
-<span class="sourceLineNo">272</span>    limits.setTimeScope(scope);<a name="line.272"></a>
+<span class="sourceLineNo">271</span>  void setSizeLimitScope(LimitScope scope) {<a name="line.271"></a>
+<span class="sourceLineNo">272</span>    limits.setSizeScope(scope);<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>  int getBatchLimit() {<a name="line.275"></a>
-<span class="sourceLineNo">276</span>    return limits.getBatch();<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>  long getDataSizeLimit() {<a name="line.279"></a>
-<span class="sourceLineNo">280</span>    return limits.getDataSize();<a name="line.280"></a>
-<span class="sourceLineNo">281</span>  }<a name="line.281"></a>
-<span class="sourceLineNo">282</span><a name="line.282"></a>
-<span class="sourceLineNo">283</span>  long getTimeLimit() {<a name="line.283"></a>
-<span class="sourceLineNo">284</span>    return limits.getTime();<a name="line.284"></a>
-<span class="sourceLineNo">285</span>  }<a name="line.285"></a>
-<span class="sourceLineNo">286</span><a name="line.286"></a>
-<span class="sourceLineNo">287</span>  /**<a name="line.287"></a>
-<span class="sourceLineNo">288</span>   * @param checkerScope The scope that the limit is being checked from<a name="line.288"></a>
-<span class="sourceLineNo">289</span>   * @return true when the limit is enforceable from the checker's scope and it has been reached<a name="line.289"></a>
-<span class="sourceLineNo">290</span>   */<a name="line.290"></a>
-<span class="sourceLineNo">291</span>  boolean checkBatchLimit(LimitScope checkerScope) {<a name="line.291"></a>
-<span class="sourceLineNo">292</span>    return hasBatchLimit(checkerScope) &amp;&amp; progress.getBatch() &gt;= limits.getBatch();<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>  /**<a name="line.295"></a>
-<span class="sourceLineNo">296</span>   * @param checkerScope The scope that the limit is being checked from<a name="line.296"></a>
-<span class="sourceLineNo">297</span>   * @return true when the limit is enforceable from the checker's scope and it has been reached<a name="line.297"></a>
-<span class="sourceLineNo">298</span>   */<a name="line.298"></a>
-<span class="sourceLineNo">299</span>  boolean checkSizeLimit(LimitScope checkerScope) {<a name="line.299"></a>
-<span class="sourceLineNo">300</span>    return hasSizeLimit(checkerScope) &amp;&amp; (progress.getDataSize() &gt;= limits.getDataSize()<a name="line.300"></a>
-<span class="sourceLineNo">301</span>        || progress.getHeapSize() &gt;= limits.getHeapSize());<a name="line.301"></a>
-<span class="sourceLineNo">302</span>  }<a name="line.302"></a>
-<span class="sourceLineNo">303</span><a name="line.303"></a>
-<span class="sourceLineNo">304</span>  /**<a name="line.304"></a>
-<span class="sourceLineNo">305</span>   * @param checkerScope The scope that the limit is being checked from. The time limit is always<a name="line.305"></a>
-<span class="sourceLineNo">306</span>   *          checked against {@link System#currentTimeMillis()}<a name="line.306"></a>
-<span class="sourceLineNo">307</span>   * @return true when the limit is enforceable from the checker's scope and it has been reached<a name="line.307"></a>
-<span class="sourceLineNo">308</span>   */<a name="line.308"></a>
-<span class="sourceLineNo">309</span>  boolean checkTimeLimit(LimitScope checkerScope) {<a name="line.309"></a>
-<span class="sourceLineNo">310</span>    return hasTimeLimit(checkerScope) &amp;&amp; (System.currentTimeMillis() &gt;= limits.getTime());<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>   * @param checkerScope The scope that the limits are being checked from<a name="line.314"></a>
-<span class="sourceLineNo">315</span>   * @return true when some limit is enforceable from the checker's scope and it has been reached<a name="line.315"></a>
-<span class="sourceLineNo">316</span>   */<a name="line.316"></a>
-<span class="sourceLineNo">317</span>  boolean checkAnyLimitReached(LimitScope checkerScope) {<a name="line.317"></a>
-<span class="sourceLineNo">318</span>    return checkSizeLimit(checkerScope) || checkBatchLimit(checkerScope)<a name="line.318"></a>
-<span class="sourceLineNo">319</span>        || checkTimeLimit(checkerScope);<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>  Cell getLastPeekedCell() {<a name="line.322"></a>
-<span class="sourceLineNo">323</span>    return lastPeekedCell;<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>  void setLastPeekedCell(Cell lastPeekedCell) {<a name="line.326"></a>
-<span class="sourceLineNo">327</span>    this.lastPeekedCell = lastPeekedCell;<a name="line.327"></a>
+<span class="sourceLineNo">275</span>  /**<a name="line.275"></a>
+<span class="sourceLineNo">276</span>   * @param scope The scope in which the time limit will be enforced<a name="line.276"></a>
+<span class="sourceLineNo">277</span>   */<a name="line.277"></a>
+<span class="sourceLineNo">278</span>  void setTimeLimitScope(LimitScope scope) {<a name="line.278"></a>
+<span class="sourceLineNo">279</span>    limits.setTimeScope(scope);<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>  int getBatchLimit() {<a name="line.282"></a>
+<span class="sourceLineNo">283</span>    return limits.getBatch();<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>  long getDataSizeLimit() {<a name="line.286"></a>
+<span class="sourceLineNo">287</span>    return limits.getDataSize();<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>  long getTimeLimit() {<a name="line.290"></a>
+<span class="sourceLineNo">291</span>    return limits.getTime();<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>   * @param checkerScope The scope that the limit is being checked from<a name="line.295"></a>
+<span class="sourceLineNo">296</span>   * @return true when the limit is enforceable from the checker's scope and it has been reached<a name="line.296"></a>
+<span class="sourceLineNo">297</span>   */<a name="line.297"></a>
+<span class="sourceLineNo">298</span>  boolean checkBatchLimit(LimitScope checkerScope) {<a name="line.298"></a>
+<span class="sourceLineNo">299</span>    return hasBatchLimit(checkerScope) &amp;&amp; progress.getBatch() &gt;= limits.getBatch();<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 checkerScope The scope that the limit is being checked from<a name="line.303"></a>
+<span class="sourceLineNo">304</span>   * @return true when the limit is enforceable from the checker's scope and it has been reached<a name="line.304"></a>
+<span class="sourceLineNo">305</span>   */<a name="line.305"></a>
+<span class="sourceLineNo">306</span>  boolean checkSizeLimit(LimitScope checkerScope) {<a name="line.306"></a>
+<span class="sourceLineNo">307</span>    return hasSizeLimit(checkerScope) &amp;&amp; (progress.getDataSize() &gt;= limits.getDataSize()<a name="line.307"></a>
+<span class="sourceLineNo">308</span>        || progress.getHeapSize() &gt;= limits.getHeapSize());<a name="line.308"></a>
+<span class="sourceLineNo">309</span>  }<a name="line.309"></a>
+<span class="sourceLineNo">310</span><a name="line.310"></a>
+<span class="sourceLineNo">311</span>  /**<a name="line.311"></a>
+<span class="sourceLineNo">312</span>   * @param checkerScope The scope that the limit is being checked from. The time limit is always<a name="line.312"></a>
+<span class="sourceLineNo">313</span>   *          checked against {@link System#currentTimeMillis()}<a name="line.313"></a>
+<span class="sourceLineNo">314</span>   * @return true when the limit is enforceable from the checker's scope and it has been reached<a name="line.314"></a>
+<span class="sourceLineNo">315</span>   */<a name="line.315"></a>
+<span class="sourceLineNo">316</span>  boolean checkTimeLimit(LimitScope checkerScope) {<a name="line.316"></a>
+<span class="sourceLineNo">317</span>    return hasTimeLimit(checkerScope) &amp;&amp;<a name="line.317"></a>
+<span class="sourceLineNo">318</span>      (returnImmediately || System.currentTimeMillis() &gt;= limits.getTime());<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>   * @param checkerScope The scope that the limits are being checked from<a name="line.322"></a>
+<span class="sourceLineNo">323</span>   * @return true when some limit is enforceable from the checker's scope and it has been reached<a name="line.323"></a>
+<span class="sourceLineNo">324</span>   */<a name="line.324"></a>
+<span class="sourceLineNo">325</span>  boolean checkAnyLimitReached(LimitScope checkerScope) {<a name="line.325"></a>
+<span class="sourceLineNo">326</span>    return checkSizeLimit(checkerScope) || checkBatchLimit(checkerScope)<a name="line.326"></a>
+<span class="sourceLineNo">327</span>        || checkTimeLimit(checkerScope);<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>  @Override<a name="line.330"></a>
-<span class="sourceLineNo">331</span>  public String toString() {<a name="line.331"></a>
-<span class="sourceLineNo">332</span>    StringBuilder sb = new StringBuilder();<a name="line.332"></a>
-<span class="sourceLineNo">333</span>    sb.append("{");<a name="line.333"></a>
-<span class="sourceLineNo">334</span><a name="line.334"></a>
-<span class="sourceLineNo">335</span>    sb.append("limits:");<a name="line.335"></a>
-<span class="sourceLineNo">336</span>    sb.append(limits);<a name="line.336"></a>
+<span class="sourceLineNo">330</span>  Cell getLastPeekedCell() {<a name="line.330"></a>
+<span class="sourceLineNo">331</span>    return lastPeekedCell;<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>  void setLastPeekedCell(Cell lastPeekedCell) {<a name="line.334"></a>
+<span class="sourceLineNo">335</span>    this.lastPeekedCell = lastPeekedCell;<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>    sb.append(", progress:");<a name="line.338"></a>
-<span class="sourceLineNo">339</span>    sb.append(progress);<a name="line.339"></a>
-<span class="sourceLineNo">340</span><a name="line.340"></a>
-<span class="sourceLineNo">341</span>    sb.append(", keepProgress:");<a name="line.341"></a>
-<span class="sourceLineNo">342</span>    sb.append(keepProgress);<a name="line.342"></a>
-<span class="sourceLineNo">343</span><a name="line.343"></a>
-<span class="sourceLineNo">344</span>    sb.append(", state:");<a name="line.344"></a>
-<span class="sourceLineNo">345</span>    sb.append(scannerState);<a name="line.345"></a>
+<span class="sourceLineNo">338</span>  void returnImmediately() {<a name="line.338"></a>
+<span class="sourceLineNo">339</span>    this.returnImmediately = true;<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>  @Override<a name="line.342"></a>
+<span class="sourceLineNo">343</span>  public String toString() {<a name="line.343"></a>
+<span class="sourceLineNo">344</span>    StringBuilder sb = new StringBuilder();<a name="line.344"></a>
+<span class="sourceLineNo">345</span>    sb.append("{");<a name="line.345"></a>
 <span class="sourceLineNo">346</span><a name="line.346"></a>
-<span class="sourceLineNo">347</span>    sb.append("}");<a name="line.347"></a>
-<span class="sourceLineNo">348</span>    return sb.toString();<a name="line.348"></a>
-<span class="sourceLineNo">349</span>  }<a name="line.349"></a>
-<span class="sourceLineNo">350</span><a name="line.350"></a>
-<span class="sourceLineNo">351</span>  public static Builder newBuilder() {<a name="line.351"></a>
-<span class="sourceLineNo">352</span>    return new Builder();<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 static Builder newBuilder(boolean keepProgress) {<a name="line.355"></a>
-<span class="sourceLineNo">356</span>    return new Builder(keepProgress);<a name="line.356"></a>
-<span class="sourceLineNo">357</span>  }<a name="line.357"></a>
+<span class="sourceLineNo">347</span>    sb.append("limits:");<a name="line.347"></a>
+<span class="sourceLineNo">348</span>    sb.append(limits);<a name="line.348"></a>
+<span class="sourceLineNo">349</span><a name="line.349"></a>
+<span class="sourceLineNo">350</span>    sb.append(", progress:");<a name="line.350"></a>
+<span class="sourceLineNo">351</span>    sb.append(progress);<a name="line.351"></a>
+<span class="sourceLineNo">352</span><a name="line.352"></a>
+<span class="sourceLineNo">353</span>    sb.append(", keepProgress:");<a name="line.353"></a>
+<span class="sourceLineNo">354</span>    sb.append(keepProgress);<a name="line.354"></a>
+<span class="sourceLineNo">355</span><a name="line.355"></a>
+<span class="sourceLineNo">356</span>    sb.append(", state:");<a name="line.356"></a>
+<span class="sourceLineNo">357</span>    sb.append(scannerState);<a name="line.357"></a>
 <span class="sourceLineNo">358</span><a name="line.358"></a>
-<span class="sourceLineNo">359</span>  public static final class Builder {<a name="line.359"></a>
-<span class="sourceLineNo">360</span>    boolean keepProgress = DEFAULT_KEEP_PROGRESS;<a name="line.360"></a>
-<span class="sourceLineNo">361</span>    boolean trackMetrics = false;<a name="line.361"></a>
-<span class="sourceLineNo">362</span>    LimitFields limits = new LimitFields();<a name="line.362"></a>
-<span class="sourceLineNo">363</span><a name="line.363"></a>
-<span class="sourceLineNo">364</span>    private Builder() {<a name="line.364"></a>
-<span class="sourceLineNo">365</span>    }<a name="line.365"></a>
+<span class="sourceLineNo">359</span>    sb.append("}");<a name="line.359"></a>
+<span class="sourceLineNo">360</span>    return sb.toString();<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 static Builder newBuilder() {<a name="line.363"></a>
+<span class="sourceLineNo">364</span>    return new Builder();<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>    private Builder(boolean keepProgress) {<a name="line.367"></a>
-<span class="sourceLineNo">368</span>      this.keepProgress = keepProgress;<a name="line.368"></a>
-<span class="sourceLineNo">369</span>    }<a name="line.369"></a>
+<span class="sourceLineNo">367</span>  public static Builder newBuilder(boolean keepProgress) {<a name="line.367"></a>
+<span class="sourceLineNo">368</span>    return new Builder(keepProgress);<a name="line.368"></a>
+<span class="sourceLineNo">369</span>  }<a name="line.369"></a>
 <span class="sourceLineNo">370</span><a name="line.370"></a>
-<span class="sourceLineNo">371</span>    public Builder setKeepProgress(boolean keepProgress) {<a name="line.371"></a>
-<span class="sourceLineNo">372</span>      this.keepProgress = keepProgress;<a name="line.372"></a>
-<span class="sourceLineNo">373</span>      return this;<a name="line.373"></a>
-<span class="sourceLineNo">374</span>    }<a name="line.374"></a>
+<span class="sourceLineNo">371</span>  public static final class Builder {<a name="line.371"></a>
+<span class="sourceLineNo">372</span>    boolean keepProgress = DEFAULT_KEEP_PROGRESS;<a name="line.372"></a>
+<span class="sourceLineNo">373</span>    boolean trackMetrics = false;<a name="line.373"></a>
+<span class="sourceLineNo">374</span>    LimitFields limits = new LimitFields();<a name="line.374"></a>
 <span class="sourceLineNo">375</span><a name="line.375"></a>
-<span class="sourceLineNo">376</span>    public Builder setTrackMetrics(boolean trackMetrics) {<a name="line.376"></a>
-<span class="sourceLineNo">377</span>      this.trackMetrics = trackMetrics;<a name="line.377"></a>
-<span class="sourceLineNo">378</span>      return this;<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 Builder setSizeLimit(LimitScope sizeScope, long dataSizeLimit, long heapSizeLimit) {<a name="line.381"></a>
-<span class="sourceLineNo">382</span>      limits.setDataSize(dataSizeLimit);<a name="line.382"></a>
-<span class="sourceLineNo">383</span>      limits.setHeapSize(heapSizeLimit);<a name="line.383"></a>
-<span class="sourceLineNo">384</span>      limits.setSizeScope(sizeScope);<a name="line.384"></a>
+<span class="sourceLineNo">376</span>    private Builder() {<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>    private Builder(boolean keepProgress) {<a name="line.379"></a>
+<span class="sourceLineNo">380</span>      this.keepProgress = keepProgress;<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>    public Builder setKeepProgress(boolean keepProgress) {<a name="line.383"></a>
+<span class="sourceLineNo">384</span>      this.keepProgress = keepProgress;<a name="line.384"></a>
 <span class="sourceLineNo">385</span>      return this;<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 Builder setTimeLimit(LimitScope timeScope, long timeLimit) {<a name="line.388"></a>
-<span class="sourceLineNo">389</span>      limits.setTime(timeLimit);<a name="line.389"></a>
-<span class="sourceLineNo">390</span>      limits.setTimeScope(timeScope);<a name="line.390"></a>
-<span class="sourceLineNo">391</span>      return this;<a name="line.391"></a>
-<span class="sourceLineNo">392</span>    }<a name="line.392"></a>
-<span class="sourceLineNo">393</span><a name="line.393"></a>
-<span class="sourceLineNo">394</span>    public Builder setBatchLimit(int batchLimit) {<a name="line.394"></a>
-<span class="sourceLineNo">395</span>      limits.setBatch(batchLimit);<a name="line.395"></a>
-<span class="sourceLineNo">396</span>      return this;<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>    public ScannerContext build() {<a name="line.399"></a>
-<span class="sourceLineNo">400</span>      return new ScannerContext(keepProgress, limits, trackMetrics);<a name="line.400"></a>
-<span class="sourceLineNo">401</span>    }<a name="line.401"></a>
-<span class="sourceLineNo">402</span>  }<a name="line.402"></a>
-<span class="sourceLineNo">403</span><a name="line.403"></a>
-<span class="sourceLineNo">404</span>  /**<a name="line.404"></a>
-<span class="sourceLineNo">405</span>   * The possible states a scanner may be in following a call to {@link InternalScanner#next(List)}<a name="line.405"></a>
-<span class="sourceLineNo">406</span>   */<a name="line.406"></a>
-<span class="sourceLineNo">407</span>  public enum NextState {<a name="line.407"></a>
-<span class="sourceLineNo">408</span>    MORE_VALUES(true, false),<a name="line.408"></a>
-<span class="sourceLineNo">409</span>    NO_MORE_VALUES(false, false),<a name="line.409"></a>
-<span class="sourceLineNo">410</span>    SIZE_LIMIT_REACHED(true, true),<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>     * Special case of size limit reached to indicate that the size limit was reached in the middle<a name="line.413"></a>
-<span class="sourceLineNo">414</span>     * of a row and thus a partial results was formed<a name="line.414"></a>
-<span class="sourceLineNo">415</span>     */<a name="line.415"></a>
-<span class="sourceLineNo">416</span>    SIZE_LIMIT_REACHED_MID_ROW(true, true),<a name="line.416"></a>
-<span class="sourceLineNo">417</span>    TIME_LIMIT_REACHED(true, true),<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>     * Special case of time limit reached to indicate that the time limit was reached in the middle<a name="line.420"></a>
-<span class="sourceLineNo">421</span>     * of a row and thus a partial results was formed<a name="line.421"></a>
-<span class="sourceLineNo">422</span>     */<a name="line.422"></a>
-<span class="sourceLineNo">423</span>    TIME_LIMIT_REACHED_MID_ROW(true, true),<a name="line.423"></a>
-<span class="sourceLineNo">424</span>    BATCH_LIMIT_REACHED(true, true);<a name="line.424"></a>
-<span class="sourceLineNo">425</span><a name="line.425"></a>
-<span class="sourceLineNo">426</span>    private final boolean moreValues;<a name="line.426"></a>
-<span class="sourceLineNo">427</span>    private final boolean limitReached;<a name="line.427"></a>
-<span class="sourceLineNo">428</span><a name="line.428"></a>
-<span class="sourceLineNo">429</span>    private NextState(boolean moreValues, boolean limitReached) {<a name="line.429"></a>
-<span class="sourceLineNo">430</span>      this.moreValues = moreValues;<a name="line.430"></a>
-<span class="sourceLineNo">431</span>      this.limitReached = limitReached;<a name="line.431"></a>
-<span class="sourceLineNo">432</span>    }<a name="line.432"></a>
-<span class="sourceLineNo">433</span><a name="line.433"></a>
-<span class="sourceLineNo">434</span>    /**<a name="line.434"></a>
-<span class="sourceLineNo">435</span>     * @return true when the state indicates that more values may follow those that have been<a name="line.435"></a>
-<span class="sourceLineNo">436</span>     *         returned<a name="line.436"></a>
-<span class="sourceLineNo">437</span>     */<a name="line.437"></a>
-<span class="sourceLineNo">438</span>    public boolean hasMoreValues() {<a name="line.438"></a>
-<span class="sourceLineNo">439</span>      return this.moreValues;<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>     * @return true when the state indicates that a limit has been reached and scan should stop<a name="line.443"></a>
-<span class="sourceLineNo">444</span>     */<a name="line.444"></a>
-<span class="sourceLineNo">445</span>    public boolean limitReached() {<a name="line.445"></a>
-<span class="sourceLineNo">446</span>      return this.limitReached;<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>    public static boolean isValidState(NextState state) {<a name="line.449"></a>
-<span class="sourceLineNo">450</span>      return state != null;<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>    public static boolean hasMoreValues(NextState state) {<a name="line.453"></a>
-<span class="sourceLineNo">454</span>      return isValidState(state) &amp;&amp; state.hasMoreValues();<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>  /**<a name="line.458"></a>
-<span class="sourceLineNo">459</span>   * The various scopes where a limit can be enforced. Used to differentiate when a limit should be<a name="line.459"></a>
-<span class="sourceLineNo">460</span>   * enforced or not.<a name="line.460"></a>
-<span class="sourceLineNo">461</span>   */<a name="line.461"></a>
-<span class="sourceLineNo">462</span>  public enum LimitScope {<a name="line.462"></a>
-<span class="sourceLineNo">463</span>    /**<a name="line.463"></a>
-<span class="sourceLineNo">464</span>     * Enforcing a limit between rows means that the limit will not be considered until all the<a name="line.464"></a>
-<span class="sourceLineNo">465</span>     * cells for a particular row have been retrieved<a name="line.465"></a>
-<span class="sourceLineNo">466</span>     */<a name="line.466"></a>
-<span class="sourceLineNo">467</span>    BETWEEN_ROWS(0),<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>     * Enforcing a limit between cells means that the limit will be considered after each full cell<a name="line.470"></a>
-<span class="sourceLineNo">471</span>     * has been retrieved<a name="line.471"></a>
-<span class="sourceLineNo">472</span>     */<a name="line.472"></a>
-<span class="sourceLineNo">473</span>    BETWEEN_CELLS(1);<a name="line.473"></a>
-<span class="sourceLineNo">474</span><a name="line.474"></a>
+<span class="sourceLineNo">388</span>    public Builder setTrackMetrics(boolean trackMetrics) {<a name="line.388"></a>
+<span class="sourceLineNo">389</span>      this.trackMetrics = trackMetrics;<a name="line.389"></a>
+<span class="sourceLineNo">390</span>      return this;<a name="line.390"></a>
+<span class="sourceLineNo">391</span>    }<a name="line.391"></a>
+<span class="sourceLineNo">392</span><a name="line.392"></a>
+<span class="sourceLineNo">393</span>    public Builder setSizeLimit(LimitScope sizeScope, long dataSizeLimit, long heapSizeLimit) {<a name="line.393"></a>
+<span class="sourceLineNo">394</span>      limits.setDataSize(dataSizeLimit);<a name="line.394"></a>
+<span class="sourceLineNo">395</span>      limits.setHeapSize(heapSizeLimit);<a name="line.395"></a>
+<span class="sourceLineNo">396</span>      limits.setSizeScope(sizeScope);<a name="line.396"></a>
+<span class="sourceLineNo">397</span>      return this;<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>    public Builder setTimeLimit(LimitScope timeScope, long timeLimit) {<a name="line.400"></a>
+<span class="sourceLineNo">401</span>      limits.setTime(timeLimit);<a name="line.401"></a>
+<span class="sourceLineNo">402</span>      limits.setTimeScope(timeScope);<a name="line.402"></a>
+<span class="sourceLineNo">403</span>      return this;<a name="line.403"></a>
+<span class="sourceLineNo">404</span>    }<a name="line.404"></a>
+<span class="sourceLineNo">405</span><a name="line.405"></a>
+<span class="sourceLineNo">406</span>    public Builder setBatchLimit(int batchLimit) {<a name="line.406"></a>
+<span class="sourceLineNo">407</span>      limits.setBatch(batchLimit);<a name="line.407"></a>
+<span class="sourceLineNo">408</span>      return this;<a name="line.408"></a>
+<span class="sourceLineNo">409</span>    }<a name="line.409"></a>
+<span class="sourceLineNo">410</span><a name="line.410"></a>
+<span class="sourceLineNo">411</span>    public ScannerContext build() {<a name="line.411"></a>
+<span class="sourceLineNo">412</span>      return new ScannerContext(keepProgress, limits, trackMetrics);<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><a name="line.415"></a>
+<span class="sourceLineNo">416</span>  /**<a name="line.416"></a>
+<span class="sourceLineNo">417</span>   * The possible states a scanner may be in following a call to {@link InternalScanner#next(List)}<a name="line.417"></a>
+<span class="sourceLineNo">418</span>   */<a name="line.418"></a>
+<span class="sourceLineNo">419</span>  public enum NextState {<a name="line.419"></a>
+<span class="sourceLineNo">420</span>    MORE_VALUES(true, false),<a name="line.420"></a>
+<span class="sourceLineNo">421</span>    NO_MORE_VALUES(false, false),<a name="line.421"></a>
+<span class="sourceLineNo">422</span>    SIZE_LIMIT_REACHED(true, true),<a name="line.422"></a>
+<span class="sourceLineNo">423</span><a name="line.423"></a>
+<span class="sourceLineNo">424</span>    /**<a name="line.424"></a>
+<span class="sourceLineNo">425</span>     * Special case of size limit reached to indicate that the size limit was reached in the middle<a name="line.425"></a>
+<span class="sourceLineNo">426</span>     * of a row and thus a partial results was formed<a name="line.426"></a>
+<span class="sourceLineNo">427</span>     */<a name="line.427"></a>
+<span class="sourceLineNo">428</span>    SIZE_LIMIT_REACHED_MID_ROW(true, true),<a name="line.428"></a>
+<span class="sourceLineNo">429</span>    TIME_LIMIT_REACHED(true, true),<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>     * Special case of time limit reached to indicate that the time limit was reached in the middle<a name="line.432"></a>
+<span class="sourceLineNo">433</span>     * of a row and thus a partial results was formed<a name="line.433"></a>
+<span class="sourceLineNo">434</span>     */<a name="line.434"></a>
+<span class="sourceLineNo">435</span>    TIME_LIMIT_REACHED_MID_ROW(true, true),<a name="line.435"></a>
+<span class="sourceLineNo">436</span>    BATCH_LIMIT_REACHED(true, true);<a name="line.436"></a>
+<span class="sourceLineNo">437</span><a name="line.437"></a>
+<span class="sourceLineNo">438</span>    private final boolean moreValues;<a name="line.438"></a>
+<span class="sourceLineNo">439</span>    private final boolean limitReached;<a name="line.439"></a>
+<span class="sourceLineNo">440</span><a name="line.440"></a>
+<span class="sourceLineNo">441</span>    private NextState(boolean moreValues, boolean limitReached) {<a name="line.441"></a>
+<span class="sourceLineNo">442</span>      this.moreValues = moreValues;<a name="line.442"></a>
+<span class="sourceLineNo">443</span>      this.limitReached = limitReached;<a name="line.443"></a>
+<span class="sourceLineNo">444</span>    }<a name="line.444"></a>
+<span class="sourceLineNo">445</span><a name="line.445"></a>
+<span class="sourceLineNo">446</span>    /**<a name="line.446"></a>
+<span class="sourceLineNo">447</span>     * @return true when the state indicates that more values may follow those that have been<a name="line.447"></a>
+<span class="sourceLineNo">448</span>     *         returned<a name="line.448"></a>
+<span class="sourceLineNo">449</span>     */<a name="line.449"></a>
+<span class="sourceLineNo">450</span>    public boolean hasMoreValues() {<a name="line.450"></a>
+<span class="sourceLineNo">451</span>      return this.moreValues;<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>     * @return true when the state indicates that a limit has been reached and scan should stop<a name="line.455"></a>
+<span class="sourceLineNo">456</span>     */<a name="line.456"></a>
+<span class="sourceLineNo">457</span>    public boolean limitReached() {<a name="line.457"></a>
+<span class="sourceLineNo">458</span>      return this.limitReached;<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>    public static boolean isValidState(NextState state) {<a name="line.461"></a>
+<span class="sourceLineNo">462</span>      return state != 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>    public static boolean hasMoreValues(NextState state) {<a name="line.465"></a>
+<span class="sourceLineNo">466</span>      return isValidState(state) &amp;&amp; state.hasMoreValues();<a name="line.466"></a>
+<span class="sourceLineNo">467</span>    }<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>   * The various scopes where a limit can be enforced. Used to differentiate when a limit should be<a name="line.471"></a>
+<span class="sourceLineNo">472</span>   * enforced or not.<a name="line.472"></a>
+<span class="sourceLineNo">473</span>   */<a name="line.473"></a>
+<span class="sourceLineNo">474</span>  public enum LimitScope {<a name="line.474"></a>
 <span class="sourceLineNo">475</span>    /**<a name="line.475"></a>
-<span class="sourceLineNo">476</span>     * When enforcing a limit, we must check that the scope is appropriate for enforcement.<a name="line.476"></a>
-<span class="sourceLineNo">477</span>     * &lt;p&gt;<a name="line.477"></a>
-<span class="sourceLineNo">478</span>     * To communicate this concept, each scope has a depth. A limit will be enforced if the depth of<a name="line.478"></a>
-<span class="sourceLineNo">479</span>     * the checker's scope is less than or equal to the limit's scope. This means that when checking<a name="line.479"></a>
-<span class="sourceLineNo">480</span>     * limits, the checker must know their own scope (i.e. are they checking the limits between<a name="line.480"></a>
-<span class="sourceLineNo">481</span>     * rows, between cells, etc...)<a name="line.481"></a>
-<span class="sourceLineNo">482</span>     */<a name="line.482"></a>
-<span class="sourceLineNo">483</span>    final int depth;<a name="line.483"></a>
-<span class="sourceLineNo">484</span><a name="line.484"></a>
-<span class="sourceLineNo">485</span>    LimitScope(int depth) {<a name="line.485"></a>
-<span class="sourceLineNo">486</span>      this.depth = depth;<a name="line.486"></a>
-<span class="sourceLineNo">487</span>    }<a name="line.487"></a>
-<span class="sourceLineNo">488</span><a name="line.488"></a>
-<span class="sourceLineNo">489</span>    final int depth() {<a name="line.489"></a>
-<span class="sourceLineNo">490</span>      return depth;<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>     * @param checkerScope The scope in which the limit is being checked<a name="line.494"></a>
-<span class="sourceLineNo">495</span>     * @return true when the checker is in a scope that indicates the limit can be enforced. Limits<a name="line.495"></a>
-<span class="sourceLineNo">496</span>     *         can be enforced from "higher or equal" scopes (i.e. the checker's scope is at a<a name="line.496"></a>
-<span class="sourceLineNo">497</span>     *         lesser depth than the limit)<a name="line.497"></a>
-<span class="sourceLineNo">498</span>     */<a name="line.498"></a>
-<span class="sourceLineNo">499</span>    boolean canEnforceLimitFromScope(LimitScope checkerScope) {<a name="line.499"></a>
-<span class="sourceLineNo">500</span>      return checkerScope != null &amp;&amp; checkerScope.depth() &lt;= depth;<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><a name="line.503"></a>
-<span class="sourceLineNo">504</span>  /**<a name="line.504"></a>
-<span class="sourceLineNo">505</span>   * The different fields that can be used as limits in calls to<a name="line.505"></a>
-<span class="sourceLineNo">506</span>   * {@link InternalScanner#next(java.util.List)} and {@link RegionScanner#next(java.util.List)}<a name="line.506"></a>
-<span class="sourceLineNo">507</span>   */<a name="line.507"></a>
-<span class="sourceLineNo">508</span>  private static class LimitFields {<a name="line.508"></a>
-<span class="sourceLineNo">509</span>    /**<a name="line.509"></a>
-<span class="sourceLineNo">510</span>     * Default values of the limit fields. Defined such that if a field does NOT change from its<a name="line.510"></a>
-<span class="sourceLineNo">511</span>     * default, it will not be enforced<a name="line.511"></a>
-<span class="sourceLineNo">512</span>     */<a name="line.512"></a>
-<span class="sourceLineNo">513</span>    private static int DEFAULT_BATCH = -1;<a name="line.513"></a>
-<span class="sourceLineNo">514</span>    private static long DEFAULT_SIZE = -1L;<a name="line.514"></a>
-<span class="sourceLineNo">515</span>    private static long DEFAULT_TIME = -1L;<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>     * Default scope that is assigned to a limit if a scope is not specified.<a name="line.518"></a>
-<span class="sourceLineNo">519</span>     */<a name="line.519"></a>
-<span class="sourceLineNo">520</span>    private static final LimitScope DEFAULT_SCOPE = LimitScope.BETWEEN_ROWS;<a name="line.520"></a>
-<span class="sourceLineNo">521</span><a name="line.521"></a>
-<span class="sourceLineNo">522</span>    // The batch limit will always be enforced between cells, thus, there isn't a field to hold the<a name="line.522"></a>
-<span class="sourceLineNo">523</span>    // batch scope<a name="line.523"></a>
-<span class="sourceLineNo">524</span>    int batch = DEFAULT_BATCH;<a name="line.524"></a>
-<span class="sourceLineNo">525</span><a name="line.525"></a>
-<span class="sourceLineNo">526</span>    LimitScope sizeScope = DEFAULT_SCOPE;<a name="line.526"></a>
-<span class="sourceLineNo">527</span>    // The sum of cell data sizes(key + value). The Cell data might be in on heap or off heap area.<a name="line.527"></a>
-<span class="sourceLineNo">528</span>    long dataSize = DEFAULT_SIZE;<a name="line.528"></a>
-<span class="sourceLineNo">529</span>    // The sum of heap space occupied by all tracked cells. This includes Cell POJO's overhead as<a name="line.529"></a>
-<span class="sourceLineNo">530</span>    // such AND data cells of Cells which are in on heap area.<a name="line.530"></a>
-<span class="sourceLineNo">531</span>    long heapSize = DEFAULT_SIZE;<a name="line.531"></a>
-<span class="sourceLineNo">532</span><a name="line.532"></a>
-<span class="sourceLineNo">533</span>    LimitScope timeScope = DEFAULT_SCOPE;<a name="line.533"></a>
-<span class="sourceLineNo">534</span>    long time = DEFAULT_TIME;<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>     * Fields keep their default values.<a name="line.537"></a>
-<span class="sourceLineNo">538</span>     */<a name="line.538"></a>
-<span class="sourceLineNo">539</span>    LimitFields() {<a name="line.539"></a>
-<span class="sourceLineNo">540</span>    }<a name="line.540"></a>
-<span class="sourceLineNo">541</span><a name="line.541"></a>
-<span class="sourceLineNo">542</span>    LimitFields(int batch, LimitScope sizeScope, long size, long heapSize, LimitScope timeScope,<a name="line.542"></a>
-<span class="sourceLineNo">543</span>        long time) {<a name="line.543"></a>
-<span class="sourceLineNo">544</span>      setFields(batch, sizeScope, size, heapSize, timeScope, time);<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>    void copy(LimitFields limitsToCopy) {<a name="line.547"></a>
-<span class="sourceLineNo">548</span>      if (limitsToCopy != null) {<a name="line.548"></a>
-<span class="sourceLineNo">549</span>        setFields(limitsToCopy.getBatch(), limitsToCopy.getSizeScope(), limitsToCopy.getDataSize(),<a name="line.549"></a>
-<span class="sourceLineNo">550</span>            limitsToCopy.getHeapSize(), limitsToCopy.getTimeScope(), limitsToCopy.getTime());<a name="line.550"></a>
-<span class="sourceLineNo">551</span>      }<a name="line.551"></a>
+<span class="sourceLineNo">476</span>     * Enforcing a limit between rows means that the limit will not be considered until all the<a name="line.476"></a>
+<span class="sourceLineNo">477</span>     * cells for a particular row have been retrieved<a name="line.477"></a>
+<span class="sourceLineNo">478</span>     */<a name="line.478"></a>
+<span class="sourceLineNo">479</span>    BETWEEN_ROWS(0),<a name="line.479"></a>
+<span class="sourceLineNo">480</span><a name="line.480"></a>
+<span class="sourceLineNo">481</span>    /**<a name="line.481"></a>
+<span class="sourceLineNo">482</span>     * Enforcing a limit between cells means that the limit will be considered after each full cell<a name="line.482"></a>
+<span class="sourceLineNo">483</span>     * has been retrieved<a name="line.483"></a>
+<span class="sourceLineNo">484</span>     */<a name="line.484"></a>
+<span class="sourceLineNo">485</span>    BETWEEN_CELLS(1);<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>     * When enforcing a limit, we must check that the scope is appropriate for enforcement.<a name="line.488"></a>
+<span class="sourceLineNo">489</span>     * &lt;p&gt;<a name="line.489"></a>
+<span class="sourceLineNo">490</span>     * To communicate this concept, each scope has a depth. A limit will be enforced if the depth of<a name="line.490"></a>
+<span class="sourceLineNo">491</span>     * the checker's scope is less than or equal to the limit's scope. This means that when checking<a name="line.491"></a>
+<span class="sourceLineNo">492</span>     * limits, the checker must know their own scope (i.e. are they checking the limits between<a name="line.492"></a>
+<span class="sourceLineNo">493</span>     * rows, between cells, etc...)<a name="line.493"></a>
+<span class="sourceLineNo">494</span>     */<a name="line.494"></a>
+<span class="sourceLineNo">495</span>    final int depth;<a name="line.495"></a>
+<span class="sourceLineNo">496</span><a name="line.496"></a>
+<span class="sourceLineNo">497</span>    LimitScope(int depth) {<a name="line.497"></a>
+<span class="sourceLineNo">498</span>      this.depth = depth;<a name="line.498"></a>
+<span class="sourceLineNo">499</span>    }<a name="line.499"></a>
+<span class="sourceLineNo">500</span><a name="line.500"></a>
+<span class="sourceLineNo">501</span>    final int depth() {<a name="line.501"></a>
+<span class="sourceLineNo">502</span>      return depth;<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>    /**<a name="line.505"></a>
+<span class="sourceLineNo">506</span>     * @param checkerScope The scope in which the limit is being checked<a name="line.506"></a>
+<span class="sourceLineNo">507</span>     * @return true when the checker is in a scope that indicates the limit can be enforced. Limits<a name="line.507"></a>
+<span class="sourceLineNo">508</span>     *         can be enforced from "higher or equal" scopes (i.e. the checker's scope is at a<a name="line.508"></a>
+<span class="sourceLineNo">509</span>     *         lesser depth than the limit)<a name="line.509"></a>
+<span class="sourceLineNo">510</span>     */<a name="line.510"></a>
+<span class="sourceLineNo">511</span>    boolean canEnforceLimitFromScope(LimitScope checkerScope) {<a name="line.511"></a>
+<span class="sourceLineNo">512</span>      return checkerScope != null &amp;&amp; checkerScope.depth() &lt;= depth;<a name="line.512"></a>
+<span class="sourceLineNo">513</span>    }<a name="line.513"></a>
+<span class="sourceLineNo">514</span>  }<a name="line.514"></a>
+<span class="sourceLineNo">515</span><a name="line.515"></a>
+<span class="sourceLineNo">516</span>  /**<a name="line.516"></a>
+<span class="sourceLineNo">517</span>   * The different fields that can be used as limits in calls to<a name="line.517"></a>
+<span class="sourceLineNo">518</span>   * {@link InternalScanner#next(java.util.List)} and {@link RegionScanner#next(java.util.List)}<a name="line.518"></a>
+<span class="sourceLineNo">519</span>   */<a name="line.519"></a>
+<span class="sourceLineNo">520</span>  private static class LimitFields {<a name="line.520"></a>
+<span class="sourceLineNo">521</span>    /**<a name="line.521"></a>
+<span class="sourceLineNo">522</span>     * Default values of the limit fields. Defined such that if a field does NOT change from its<a name="line.522"></a>
+<span class="sourceLineNo">523</span>     * default, it will not be enforced<a name="line.523"></a>
+<span class="sourceLineNo">524</span>     */<a name="line.524"></a>
+<span class="sourceLineNo">525</span>    private static int DEFAULT_BATCH = -1;<a name="line.525"></a>
+<span class="sourceLineNo">526</span>    private static long DEFAULT_SIZE = -1L;<a name="line.526"></a>
+<span class="sourceLineNo">527</span>    private static long DEFAULT_TIME = -1L;<a name="line.527"></a>
+<span class="sourceLineNo">528</span><a name="line.528"></a>
+<span class="sourceLineNo">529</span>    /**<a name="line.529"></a>
+<span class="sourceLineNo">530</span>     * Default scope that is assigned to a limit if a scope is not specified.<a name="line.530"></a>
+<span class="sourceLineNo">531</span>     */<a name="line.531"></a>
+<span class="sourceLineNo">532</span>    private static final LimitScope DEFAULT_SCOPE = LimitScope.BETWEEN_ROWS;<a name="line.532"></a>
+<span class="sourceLineNo">533</span><a name="line.533"></a>
+<span class="sourceLineNo">534</span>    // The batch limit will always be enforced between cells, thus, there isn't a field to hold the<a name="line.534"></a>
+<span class="sourceLineNo">535</span>    // batch scope<a name="line.535"></a>
+<span class="sourceLineNo">536</span>    int batch = DEFAULT_BATCH;<a name="line.536"></a>
+<span class="sourceLineNo">537</span><a name="line.537"></a>
+<span class="sourceLineNo">538</span>    LimitScope sizeScope = DEFAULT_SCOPE;<a name="line.538"></a>
+<span class="sourceLineNo">539</span>    // The sum of cell data sizes(key + value). The Cell data might be in on heap or off heap area.<a name="line.539"></a>
+<span class="sourceLineNo">540</span>    long dataSize = DEFAULT_SIZE;<a name="line.540"></a>
+<span class="sourceLineNo">541</span>    // The sum of heap space occupied by all tracked cells. This includes Cell POJO's overhead as<a name="line.541"></a>
+<span class="sourceLineNo">542</span>    // such AND data cells of Cells which are in on heap area.<a name="line.542"></a>
+<span class="sourceLineNo">543</span>    long heapSize = DEFAULT_SIZE;<a name="line.543"></a>
+<span class="sourceLineNo">544</span><a name="line.544"></a>
+<span class="sourceLineNo">545</span>    LimitScope timeScope = DEFAULT_SCOPE;<a name="line.545"></a>
+<span class="sourceLineNo">546</span>    long time = DEFAULT_TIME;<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>     * Fields keep their default values.<a name="line.549"></a>
+<span class="sourceLineNo">550</span>     */<a name="line.550"></a>
+<span class="sourceLineNo">551</span>    LimitFields() {<a name="line.551"></a>
 <span class="sourceLineNo">552</span>    }<a name="line.552"></a>
 <span class="sourceLineNo">553</span><a name="line.553"></a>
-<span class="sourceLineNo">554</span>    /**<a name="line.554"></a>
-<span class="sourceLineNo">555</span>     * Set all fields together.<a name="line.555"></a>
-<span class="sourceLineNo">556</span>     */<a name="line.556"></a>
-<span class="sourceLineNo">557</span>    void setFields(int batch, LimitScope sizeScope, long dataSize, long heapSize,<a name="line.557"></a>
-<span class="sourceLineNo">558</span>        LimitScope timeScope, long time) {<a name="line.558"></a>
-<span class="sourceLineNo">559</span>      setBatch(batch);<a name="line.559"></a>
-<span class="sourceLineNo">560</span>      setSizeScope(sizeScope);<a name="line.560"></a>
-<span class="sourceLineNo">561</span>      setDataSize(dataSize);<a name="line.561"></a>
-<span class="sourceLineNo">562</span>      setHeapSize(heapSize);<a name="line.562"></a>
-<span class="sourceLineNo">563</span>      setTimeScope(timeScope);<a name="line.563"></a>
-<span class="sourceLineNo">564</span>      setTime(time);<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>    int getBatch() {<a name="line.567"></a>
-<span class="sourceLineNo">568</span>      return this.batch;<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>    void setBatch(int batch) {<a name="line.571"></a>
-<span class="sourceLineNo">572</span>      this.batch = batch;<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>    /**<a name="line.575"></a>
-<span class="sourceLineNo">576</span>     * @param checkerScope<a name="line.576"></a>
-<span class="sourceLineNo">577</span>     * @return true when the limit can be enforced from the scope of the checker<a name="line.577"></a>
-<span class="sourceLineNo">578</span>     */<a name="line.578"></a>
-<span class="sourceLineNo">579</span>    boolean canEnforceBatchLimitFromScope(LimitScope checkerScope) {<a name="line.579"></a>
-<span class="sourceLineNo">580</span>      return LimitScope.BETWEEN_CELLS.canEnforceLimitFromScope(checkerScope);<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>    long getDataSize() {<a name="line.583"></a>
-<span class="sourceLineNo">584</span>      return this.dataSize;<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>    long getHeapSize() {<a name="line.587"></a>
-<span class="sourceLineNo">588</span>      return this.heapSize;<a name="line.588"></a>
-<span class="sourceLineNo">589</span>    }<a name="line.589"></a>
-<span class="sourceLineNo">590</span><a name="line.590"></a>
-<span class="sourceLineNo">591</span>    void setDataSize(long dataSize) {<a name="line.591"></a>
-<span class="sourceLineNo">592</span>      this.dataSize = dataSize;<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>    void setHeapSize(long heapSize) {<a name="line.595"></a>
-<span class="sourceLineNo">596</span>      this.heapSize = heapSize;<a name="line.596"></a>
-<span class="sourceLineNo">597</span>    }<a name="line.597"></a>
-<span class="sourceLineNo">598</span><a name="line.598"></a>
-<span class="sourceLineNo">599</span>    /**<a name="line.599"></a>
-<span class="sourceLineNo">600</span>     * @return {@link LimitScope} indicating scope in which the size limit is enforced<a name="line.600"></a>
-<span class="sourceLineNo">601</span>     */<a name="line.601"></a>
-<span class="sourceLineNo">602</span>    LimitScope getSizeScope() {<a name="line.602"></a>
-<span class="sourceLineNo">603</span>      return this.sizeScope;<a name="line.603"></a>
+<span class="sourceLineNo">554</span>    void copy(LimitFields limitsToCopy) {<a name="line.554"></a>
+<span class="sourceLineNo">555</span>      if (limitsToCopy != null) {<a name="line.555"></a>
+<span class="sourceLineNo">556</span>        setFields(limitsToCopy.getBatch(), limitsToCopy.getSizeScope(), limitsToCopy.getDataSize(),<a name="line.556"></a>
+<span class="sourceLineNo">557</span>            limitsToCopy.getHeapSize(), limitsToCopy.getTimeScope(), limitsToCopy.getTime());<a name="line.557"></a>
+<span class="sourceLineNo">558</span>      }<a name="line.558"></a>
+<span class="sourceLineNo">559</span>    }<a name="line.559"></a>
+<span class="sourceLineNo">560</span><a name="line.560"></a>
+<span class="sourceLineNo">561</span>    /**<a name="line.561"></a>
+<span class="sourceLineNo">562</span>     * Set all fields together.<a name="line.562"></a>
+<span class="sourceLineNo">563</span>     */<a name="line.563"></a>
+<span class="sourceLineNo">564</span>    void setFields(int batch, LimitScope sizeScope, long dataSize, long heapSize,<a name="line.564"></a>
+<span class="sourceLineNo">565</span>        LimitScope timeScope, long time) {<a name="line.565"></a>
+<span class="sourceLineNo">566</span>      setBatch(batch);<a name="line.566"></a>
+<span class="sourceLineNo">567</span>      setSizeScope(sizeScope);<a name="line.567"></a>
+<span class="sourceLineNo">568</span>      setDataSize(dataSize);<a name="line.568"></a>
+<span class="sourceLineNo">569</span>      setHeapSize(heapSize);<a name="line.569"></a>
+<span class="sourceLineNo">570</span>      setTimeScope(timeScope);<a name="line.570"></a>
+<span class="sourceLineNo">571</span>      setTime(time);<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>    int getBatch() {<a name="line.574"></a>
+<span class="sourceLineNo">575</span>      return this.batch;<a name="line.575"></a>
+<span class="sourceLineNo">576</span>    }<a name="line.576"></a>
+<span class="sourceLineNo">577</span><a name="line.577"></a>
+<span class="sourceLineNo">578</span>    void setBatch(int batch) {<a name="line.578"></a>
+<span class="sourceLineNo">579</span>      this.batch = batch;<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

<TRUNCATED>

[26/50] hbase-site git commit: Published site at 26babcf013de696b899d76a3c39434b794440d8d.

Posted by gi...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/MemcachedBlockCache.HFileBlockTranscoder.html
----------------------------------------------------------------------
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/MemcachedBlockCache.HFileBlockTranscoder.html b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/MemcachedBlockCache.HFileBlockTranscoder.html
index 80df615..e32fc70 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/MemcachedBlockCache.HFileBlockTranscoder.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/MemcachedBlockCache.HFileBlockTranscoder.html
@@ -271,7 +271,7 @@
 <span class="sourceLineNo">263</span>    @Override<a name="line.263"></a>
 <span class="sourceLineNo">264</span>    public CachedData encode(HFileBlock block) {<a name="line.264"></a>
 <span class="sourceLineNo">265</span>      ByteBuffer bb = ByteBuffer.allocate(block.getSerializedLength());<a name="line.265"></a>
-<span class="sourceLineNo">266</span>      block.serialize(bb);<a name="line.266"></a>
+<span class="sourceLineNo">266</span>      block.serialize(bb, true);<a name="line.266"></a>
 <span class="sourceLineNo">267</span>      return new CachedData(0, bb.array(), CachedData.MAX_SIZE);<a name="line.267"></a>
 <span class="sourceLineNo">268</span>    }<a name="line.268"></a>
 <span class="sourceLineNo">269</span><a name="line.269"></a>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/MemcachedBlockCache.html
----------------------------------------------------------------------
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/MemcachedBlockCache.html b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/MemcachedBlockCache.html
index 80df615..e32fc70 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/MemcachedBlockCache.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/MemcachedBlockCache.html
@@ -271,7 +271,7 @@
 <span class="sourceLineNo">263</span>    @Override<a name="line.263"></a>
 <span class="sourceLineNo">264</span>    public CachedData encode(HFileBlock block) {<a name="line.264"></a>
 <span class="sourceLineNo">265</span>      ByteBuffer bb = ByteBuffer.allocate(block.getSerializedLength());<a name="line.265"></a>
-<span class="sourceLineNo">266</span>      block.serialize(bb);<a name="line.266"></a>
+<span class="sourceLineNo">266</span>      block.serialize(bb, true);<a name="line.266"></a>
 <span class="sourceLineNo">267</span>      return new CachedData(0, bb.array(), CachedData.MAX_SIZE);<a name="line.267"></a>
 <span class="sourceLineNo">268</span>    }<a name="line.268"></a>
 <span class="sourceLineNo">269</span><a name="line.269"></a>


[24/50] hbase-site git commit: Published site at 26babcf013de696b899d76a3c39434b794440d8d.

Posted by gi...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntryGroup.html
----------------------------------------------------------------------
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntryGroup.html b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntryGroup.html
index e8070ca..8cb24b3 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntryGroup.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntryGroup.html
@@ -433,1254 +433,1261 @@
 <span class="sourceLineNo">425</span>      return;<a name="line.425"></a>
 <span class="sourceLineNo">426</span>    }<a name="line.426"></a>
 <span class="sourceLineNo">427</span><a name="line.427"></a>
-<span class="sourceLineNo">428</span>    if (backingMap.containsKey(cacheKey)) {<a name="line.428"></a>
+<span class="sourceLineNo">428</span>    if (backingMap.containsKey(cacheKey) || ramCache.containsKey(cacheKey)) {<a name="line.428"></a>
 <span class="sourceLineNo">429</span>      Cacheable existingBlock = getBlock(cacheKey, false, false, false);<a name="line.429"></a>
-<span class="sourceLineNo">430</span>      try {<a name="line.430"></a>
-<span class="sourceLineNo">431</span>        if (BlockCacheUtil.compareCacheBlock(cachedItem, existingBlock) != 0) {<a name="line.431"></a>
-<span class="sourceLineNo">432</span>          throw new RuntimeException("Cached block contents differ, which should not have happened."<a name="line.432"></a>
-<span class="sourceLineNo">433</span>              + "cacheKey:" + cacheKey);<a name="line.433"></a>
-<span class="sourceLineNo">434</span>        }<a name="line.434"></a>
-<span class="sourceLineNo">435</span>        String msg = "Caching an already cached block: " + cacheKey;<a name="line.435"></a>
-<span class="sourceLineNo">436</span>        msg += ". This is harmless and can happen in rare cases (see HBASE-8547)";<a name="line.436"></a>
-<span class="sourceLineNo">437</span>        LOG.warn(msg);<a name="line.437"></a>
-<span class="sourceLineNo">438</span>      } finally {<a name="line.438"></a>
-<span class="sourceLineNo">439</span>        // return the block since we need to decrement the count<a name="line.439"></a>
-<span class="sourceLineNo">440</span>        returnBlock(cacheKey, existingBlock);<a name="line.440"></a>
-<span class="sourceLineNo">441</span>      }<a name="line.441"></a>
-<span class="sourceLineNo">442</span>      return;<a name="line.442"></a>
-<span class="sourceLineNo">443</span>    }<a name="line.443"></a>
-<span class="sourceLineNo">444</span><a name="line.444"></a>
-<span class="sourceLineNo">445</span>    /*<a name="line.445"></a>
-<span class="sourceLineNo">446</span>     * Stuff the entry into the RAM cache so it can get drained to the persistent store<a name="line.446"></a>
-<span class="sourceLineNo">447</span>     */<a name="line.447"></a>
-<span class="sourceLineNo">448</span>    RAMQueueEntry re =<a name="line.448"></a>
-<span class="sourceLineNo">449</span>        new RAMQueueEntry(cacheKey, cachedItem, accessCount.incrementAndGet(), inMemory);<a name="line.449"></a>
-<span class="sourceLineNo">450</span>    if (ramCache.putIfAbsent(cacheKey, re) != null) {<a name="line.450"></a>
-<span class="sourceLineNo">451</span>      return;<a name="line.451"></a>
-<span class="sourceLineNo">452</span>    }<a name="line.452"></a>
-<span class="sourceLineNo">453</span>    int queueNum = (cacheKey.hashCode() &amp; 0x7FFFFFFF) % writerQueues.size();<a name="line.453"></a>
-<span class="sourceLineNo">454</span>    BlockingQueue&lt;RAMQueueEntry&gt; bq = writerQueues.get(queueNum);<a name="line.454"></a>
-<span class="sourceLineNo">455</span>    boolean successfulAddition = false;<a name="line.455"></a>
-<span class="sourceLineNo">456</span>    if (wait) {<a name="line.456"></a>
-<span class="sourceLineNo">457</span>      try {<a name="line.457"></a>
-<span class="sourceLineNo">458</span>        successfulAddition = bq.offer(re, DEFAULT_CACHE_WAIT_TIME, TimeUnit.MILLISECONDS);<a name="line.458"></a>
-<span class="sourceLineNo">459</span>      } catch (InterruptedException e) {<a name="line.459"></a>
-<span class="sourceLineNo">460</span>        Thread.currentThread().interrupt();<a name="line.460"></a>
-<span class="sourceLineNo">461</span>      }<a name="line.461"></a>
-<span class="sourceLineNo">462</span>    } else {<a name="line.462"></a>
-<span class="sourceLineNo">463</span>      successfulAddition = bq.offer(re);<a name="line.463"></a>
-<span class="sourceLineNo">464</span>    }<a name="line.464"></a>
-<span class="sourceLineNo">465</span>    if (!successfulAddition) {<a name="line.465"></a>
-<span class="sourceLineNo">466</span>      ramCache.remove(cacheKey);<a name="line.466"></a>
-<span class="sourceLineNo">467</span>      cacheStats.failInsert();<a name="line.467"></a>
-<span class="sourceLineNo">468</span>    } else {<a name="line.468"></a>
-<span class="sourceLineNo">469</span>      this.blockNumber.increment();<a name="line.469"></a>
-<span class="sourceLineNo">470</span>      this.heapSize.add(cachedItem.heapSize());<a name="line.470"></a>
-<span class="sourceLineNo">471</span>      blocksByHFile.add(cacheKey);<a name="line.471"></a>
-<span class="sourceLineNo">472</span>    }<a name="line.472"></a>
-<span class="sourceLineNo">473</span>  }<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>   * Get the buffer of the block with the specified key.<a name="line.476"></a>
-<span class="sourceLineNo">477</span>   * @param key block's cache key<a name="line.477"></a>
-<span class="sourceLineNo">478</span>   * @param caching true if the caller caches blocks on cache misses<a name="line.478"></a>
-<span class="sourceLineNo">479</span>   * @param repeat Whether this is a repeat lookup for the same block<a name="line.479"></a>
-<span class="sourceLineNo">480</span>   * @param updateCacheMetrics Whether we should update cache metrics or not<a name="line.480"></a>
-<span class="sourceLineNo">481</span>   * @return buffer of specified cache key, or null if not in cache<a name="line.481"></a>
-<span class="sourceLineNo">482</span>   */<a name="line.482"></a>
-<span class="sourceLineNo">483</span>  @Override<a name="line.483"></a>
-<span class="sourceLineNo">484</span>  public Cacheable getBlock(BlockCacheKey key, boolean caching, boolean repeat,<a name="line.484"></a>
-<span class="sourceLineNo">485</span>      boolean updateCacheMetrics) {<a name="line.485"></a>
-<span class="sourceLineNo">486</span>    if (!cacheEnabled) {<a name="line.486"></a>
-<span class="sourceLineNo">487</span>      return null;<a name="line.487"></a>
-<span class="sourceLineNo">488</span>    }<a name="line.488"></a>
-<span class="sourceLineNo">489</span>    RAMQueueEntry re = ramCache.get(key);<a name="line.489"></a>
-<span class="sourceLineNo">490</span>    if (re != null) {<a name="line.490"></a>
-<span class="sourceLineNo">491</span>      if (updateCacheMetrics) {<a name="line.491"></a>
-<span class="sourceLineNo">492</span>        cacheStats.hit(caching, key.isPrimary(), key.getBlockType());<a name="line.492"></a>
-<span class="sourceLineNo">493</span>      }<a name="line.493"></a>
-<span class="sourceLineNo">494</span>      re.access(accessCount.incrementAndGet());<a name="line.494"></a>
-<span class="sourceLineNo">495</span>      return re.getData();<a name="line.495"></a>
-<span class="sourceLineNo">496</span>    }<a name="line.496"></a>
-<span class="sourceLineNo">497</span>    BucketEntry bucketEntry = backingMap.get(key);<a name="line.497"></a>
-<span class="sourceLineNo">498</span>    if (bucketEntry != null) {<a name="line.498"></a>
-<span class="sourceLineNo">499</span>      long start = System.nanoTime();<a name="line.499"></a>
-<span class="sourceLineNo">500</span>      ReentrantReadWriteLock lock = offsetLock.getLock(bucketEntry.offset());<a name="line.500"></a>
-<span class="sourceLineNo">501</span>      try {<a name="line.501"></a>
-<span class="sourceLineNo">502</span>        lock.readLock().lock();<a name="line.502"></a>
-<span class="sourceLineNo">503</span>        // We can not read here even if backingMap does contain the given key because its offset<a name="line.503"></a>
-<span class="sourceLineNo">504</span>        // maybe changed. If we lock BlockCacheKey instead of offset, then we can only check<a name="line.504"></a>
-<span class="sourceLineNo">505</span>        // existence here.<a name="line.505"></a>
-<span class="sourceLineNo">506</span>        if (bucketEntry.equals(backingMap.get(key))) {<a name="line.506"></a>
-<span class="sourceLineNo">507</span>          // TODO : change this area - should be removed after server cells and<a name="line.507"></a>
-<span class="sourceLineNo">508</span>          // 12295 are available<a name="line.508"></a>
-<span class="sourceLineNo">509</span>          int len = bucketEntry.getLength();<a name="line.509"></a>
-<span class="sourceLineNo">510</span>          if (LOG.isTraceEnabled()) {<a name="line.510"></a>
-<span class="sourceLineNo">511</span>            LOG.trace("Read offset=" + bucketEntry.offset() + ", len=" + len);<a name="line.511"></a>
-<span class="sourceLineNo">512</span>          }<a name="line.512"></a>
-<span class="sourceLineNo">513</span>          Cacheable cachedBlock = ioEngine.read(bucketEntry.offset(), len,<a name="line.513"></a>
-<span class="sourceLineNo">514</span>              bucketEntry.deserializerReference(this.deserialiserMap));<a name="line.514"></a>
-<span class="sourceLineNo">515</span>          long timeTaken = System.nanoTime() - start;<a name="line.515"></a>
-<span class="sourceLineNo">516</span>          if (updateCacheMetrics) {<a name="line.516"></a>
-<span class="sourceLineNo">517</span>            cacheStats.hit(caching, key.isPrimary(), key.getBlockType());<a name="line.517"></a>
-<span class="sourceLineNo">518</span>            cacheStats.ioHit(timeTaken);<a name="line.518"></a>
+<span class="sourceLineNo">430</span><a name="line.430"></a>
+<span class="sourceLineNo">431</span>      try {<a name="line.431"></a>
+<span class="sourceLineNo">432</span>        int comparison = BlockCacheUtil.validateBlockAddition(existingBlock, cachedItem, cacheKey);<a name="line.432"></a>
+<span class="sourceLineNo">433</span>        if (comparison != 0) {<a name="line.433"></a>
+<span class="sourceLineNo">434</span>          if (comparison &lt; 0) {<a name="line.434"></a>
+<span class="sourceLineNo">435</span>            LOG.warn("Cached block contents differ by nextBlockOnDiskSize. Keeping cached block.");<a name="line.435"></a>
+<span class="sourceLineNo">436</span>            return;<a name="line.436"></a>
+<span class="sourceLineNo">437</span>          } else {<a name="line.437"></a>
+<span class="sourceLineNo">438</span>            LOG.warn("Cached block contents differ by nextBlockOnDiskSize. Caching new block.");<a name="line.438"></a>
+<span class="sourceLineNo">439</span>          }<a name="line.439"></a>
+<span class="sourceLineNo">440</span>        } else {<a name="line.440"></a>
+<span class="sourceLineNo">441</span>          String msg = "Caching an already cached block: " + cacheKey;<a name="line.441"></a>
+<span class="sourceLineNo">442</span>          msg += ". This is harmless and can happen in rare cases (see HBASE-8547)";<a name="line.442"></a>
+<span class="sourceLineNo">443</span>          LOG.warn(msg);<a name="line.443"></a>
+<span class="sourceLineNo">444</span>          return;<a name="line.444"></a>
+<span class="sourceLineNo">445</span>        }<a name="line.445"></a>
+<span class="sourceLineNo">446</span>      } finally {<a name="line.446"></a>
+<span class="sourceLineNo">447</span>        // return the block since we need to decrement the count<a name="line.447"></a>
+<span class="sourceLineNo">448</span>        returnBlock(cacheKey, existingBlock);<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><a name="line.451"></a>
+<span class="sourceLineNo">452</span>    /*<a name="line.452"></a>
+<span class="sourceLineNo">453</span>     * Stuff the entry into the RAM cache so it can get drained to the persistent store<a name="line.453"></a>
+<span class="sourceLineNo">454</span>     */<a name="line.454"></a>
+<span class="sourceLineNo">455</span>    RAMQueueEntry re =<a name="line.455"></a>
+<span class="sourceLineNo">456</span>        new RAMQueueEntry(cacheKey, cachedItem, accessCount.incrementAndGet(), inMemory);<a name="line.456"></a>
+<span class="sourceLineNo">457</span>    if (ramCache.putIfAbsent(cacheKey, re) != null) {<a name="line.457"></a>
+<span class="sourceLineNo">458</span>      return;<a name="line.458"></a>
+<span class="sourceLineNo">459</span>    }<a name="line.459"></a>
+<span class="sourceLineNo">460</span>    int queueNum = (cacheKey.hashCode() &amp; 0x7FFFFFFF) % writerQueues.size();<a name="line.460"></a>
+<span class="sourceLineNo">461</span>    BlockingQueue&lt;RAMQueueEntry&gt; bq = writerQueues.get(queueNum);<a name="line.461"></a>
+<span class="sourceLineNo">462</span>    boolean successfulAddition = false;<a name="line.462"></a>
+<span class="sourceLineNo">463</span>    if (wait) {<a name="line.463"></a>
+<span class="sourceLineNo">464</span>      try {<a name="line.464"></a>
+<span class="sourceLineNo">465</span>        successfulAddition = bq.offer(re, DEFAULT_CACHE_WAIT_TIME, TimeUnit.MILLISECONDS);<a name="line.465"></a>
+<span class="sourceLineNo">466</span>      } catch (InterruptedException e) {<a name="line.466"></a>
+<span class="sourceLineNo">467</span>        Thread.currentThread().interrupt();<a name="line.467"></a>
+<span class="sourceLineNo">468</span>      }<a name="line.468"></a>
+<span class="sourceLineNo">469</span>    } else {<a name="line.469"></a>
+<span class="sourceLineNo">470</span>      successfulAddition = bq.offer(re);<a name="line.470"></a>
+<span class="sourceLineNo">471</span>    }<a name="line.471"></a>
+<span class="sourceLineNo">472</span>    if (!successfulAddition) {<a name="line.472"></a>
+<span class="sourceLineNo">473</span>      ramCache.remove(cacheKey);<a name="line.473"></a>
+<span class="sourceLineNo">474</span>      cacheStats.failInsert();<a name="line.474"></a>
+<span class="sourceLineNo">475</span>    } else {<a name="line.475"></a>
+<span class="sourceLineNo">476</span>      this.blockNumber.increment();<a name="line.476"></a>
+<span class="sourceLineNo">477</span>      this.heapSize.add(cachedItem.heapSize());<a name="line.477"></a>
+<span class="sourceLineNo">478</span>      blocksByHFile.add(cacheKey);<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>  /**<a name="line.482"></a>
+<span class="sourceLineNo">483</span>   * Get the buffer of the block with the specified key.<a name="line.483"></a>
+<span class="sourceLineNo">484</span>   * @param key block's cache key<a name="line.484"></a>
+<span class="sourceLineNo">485</span>   * @param caching true if the caller caches blocks on cache misses<a name="line.485"></a>
+<span class="sourceLineNo">486</span>   * @param repeat Whether this is a repeat lookup for the same block<a name="line.486"></a>
+<span class="sourceLineNo">487</span>   * @param updateCacheMetrics Whether we should update cache metrics or not<a name="line.487"></a>
+<span class="sourceLineNo">488</span>   * @return buffer of specified cache key, or null if not in cache<a name="line.488"></a>
+<span class="sourceLineNo">489</span>   */<a name="line.489"></a>
+<span class="sourceLineNo">490</span>  @Override<a name="line.490"></a>
+<span class="sourceLineNo">491</span>  public Cacheable getBlock(BlockCacheKey key, boolean caching, boolean repeat,<a name="line.491"></a>
+<span class="sourceLineNo">492</span>      boolean updateCacheMetrics) {<a name="line.492"></a>
+<span class="sourceLineNo">493</span>    if (!cacheEnabled) {<a name="line.493"></a>
+<span class="sourceLineNo">494</span>      return null;<a name="line.494"></a>
+<span class="sourceLineNo">495</span>    }<a name="line.495"></a>
+<span class="sourceLineNo">496</span>    RAMQueueEntry re = ramCache.get(key);<a name="line.496"></a>
+<span class="sourceLineNo">497</span>    if (re != null) {<a name="line.497"></a>
+<span class="sourceLineNo">498</span>      if (updateCacheMetrics) {<a name="line.498"></a>
+<span class="sourceLineNo">499</span>        cacheStats.hit(caching, key.isPrimary(), key.getBlockType());<a name="line.499"></a>
+<span class="sourceLineNo">500</span>      }<a name="line.500"></a>
+<span class="sourceLineNo">501</span>      re.access(accessCount.incrementAndGet());<a name="line.501"></a>
+<span class="sourceLineNo">502</span>      return re.getData();<a name="line.502"></a>
+<span class="sourceLineNo">503</span>    }<a name="line.503"></a>
+<span class="sourceLineNo">504</span>    BucketEntry bucketEntry = backingMap.get(key);<a name="line.504"></a>
+<span class="sourceLineNo">505</span>    if (bucketEntry != null) {<a name="line.505"></a>
+<span class="sourceLineNo">506</span>      long start = System.nanoTime();<a name="line.506"></a>
+<span class="sourceLineNo">507</span>      ReentrantReadWriteLock lock = offsetLock.getLock(bucketEntry.offset());<a name="line.507"></a>
+<span class="sourceLineNo">508</span>      try {<a name="line.508"></a>
+<span class="sourceLineNo">509</span>        lock.readLock().lock();<a name="line.509"></a>
+<span class="sourceLineNo">510</span>        // We can not read here even if backingMap does contain the given key because its offset<a name="line.510"></a>
+<span class="sourceLineNo">511</span>        // maybe changed. If we lock BlockCacheKey instead of offset, then we can only check<a name="line.511"></a>
+<span class="sourceLineNo">512</span>        // existence here.<a name="line.512"></a>
+<span class="sourceLineNo">513</span>        if (bucketEntry.equals(backingMap.get(key))) {<a name="line.513"></a>
+<span class="sourceLineNo">514</span>          // TODO : change this area - should be removed after server cells and<a name="line.514"></a>
+<span class="sourceLineNo">515</span>          // 12295 are available<a name="line.515"></a>
+<span class="sourceLineNo">516</span>          int len = bucketEntry.getLength();<a name="line.516"></a>
+<span class="sourceLineNo">517</span>          if (LOG.isTraceEnabled()) {<a name="line.517"></a>
+<span class="sourceLineNo">518</span>            LOG.trace("Read offset=" + bucketEntry.offset() + ", len=" + len);<a name="line.518"></a>
 <span class="sourceLineNo">519</span>          }<a name="line.519"></a>
-<span class="sourceLineNo">520</span>          if (cachedBlock.getMemoryType() == MemoryType.SHARED) {<a name="line.520"></a>
-<span class="sourceLineNo">521</span>            bucketEntry.incrementRefCountAndGet();<a name="line.521"></a>
-<span class="sourceLineNo">522</span>          }<a name="line.522"></a>
-<span class="sourceLineNo">523</span>          bucketEntry.access(accessCount.incrementAndGet());<a name="line.523"></a>
-<span class="sourceLineNo">524</span>          if (this.ioErrorStartTime &gt; 0) {<a name="line.524"></a>
-<span class="sourceLineNo">525</span>            ioErrorStartTime = -1;<a name="line.525"></a>
+<span class="sourceLineNo">520</span>          Cacheable cachedBlock = ioEngine.read(bucketEntry.offset(), len,<a name="line.520"></a>
+<span class="sourceLineNo">521</span>              bucketEntry.deserializerReference(this.deserialiserMap));<a name="line.521"></a>
+<span class="sourceLineNo">522</span>          long timeTaken = System.nanoTime() - start;<a name="line.522"></a>
+<span class="sourceLineNo">523</span>          if (updateCacheMetrics) {<a name="line.523"></a>
+<span class="sourceLineNo">524</span>            cacheStats.hit(caching, key.isPrimary(), key.getBlockType());<a name="line.524"></a>
+<span class="sourceLineNo">525</span>            cacheStats.ioHit(timeTaken);<a name="line.525"></a>
 <span class="sourceLineNo">526</span>          }<a name="line.526"></a>
-<span class="sourceLineNo">527</span>          return cachedBlock;<a name="line.527"></a>
-<span class="sourceLineNo">528</span>        }<a name="line.528"></a>
-<span class="sourceLineNo">529</span>      } catch (IOException ioex) {<a name="line.529"></a>
-<span class="sourceLineNo">530</span>        LOG.error("Failed reading block " + key + " from bucket cache", ioex);<a name="line.530"></a>
-<span class="sourceLineNo">531</span>        checkIOErrorIsTolerated();<a name="line.531"></a>
-<span class="sourceLineNo">532</span>      } finally {<a name="line.532"></a>
-<span class="sourceLineNo">533</span>        lock.readLock().unlock();<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>    if (!repeat &amp;&amp; updateCacheMetrics) {<a name="line.536"></a>
-<span class="sourceLineNo">537</span>      cacheStats.miss(caching, key.isPrimary(), key.getBlockType());<a name="line.537"></a>
-<span class="sourceLineNo">538</span>    }<a name="line.538"></a>
-<span class="sourceLineNo">539</span>    return null;<a name="line.539"></a>
-<span class="sourceLineNo">540</span>  }<a name="line.540"></a>
-<span class="sourceLineNo">541</span><a name="line.541"></a>
-<span class="sourceLineNo">542</span>  @VisibleForTesting<a name="line.542"></a>
-<span class="sourceLineNo">543</span>  void blockEvicted(BlockCacheKey cacheKey, BucketEntry bucketEntry, boolean decrementBlockNumber) {<a name="line.543"></a>
-<span class="sourceLineNo">544</span>    bucketAllocator.freeBlock(bucketEntry.offset());<a name="line.544"></a>
-<span class="sourceLineNo">545</span>    realCacheSize.add(-1 * bucketEntry.getLength());<a name="line.545"></a>
-<span class="sourceLineNo">546</span>    blocksByHFile.remove(cacheKey);<a name="line.546"></a>
-<span class="sourceLineNo">547</span>    if (decrementBlockNumber) {<a name="line.547"></a>
-<span class="sourceLineNo">548</span>      this.blockNumber.decrement();<a name="line.548"></a>
-<span class="sourceLineNo">549</span>    }<a name="line.549"></a>
-<span class="sourceLineNo">550</span>  }<a name="line.550"></a>
-<span class="sourceLineNo">551</span><a name="line.551"></a>
-<span class="sourceLineNo">552</span>  @Override<a name="line.552"></a>
-<span class="sourceLineNo">553</span>  public boolean evictBlock(BlockCacheKey cacheKey) {<a name="line.553"></a>
-<span class="sourceLineNo">554</span>    return evictBlock(cacheKey, true);<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>  // does not check for the ref count. Just tries to evict it if found in the<a name="line.557"></a>
-<span class="sourceLineNo">558</span>  // bucket map<a name="line.558"></a>
-<span class="sourceLineNo">559</span>  private boolean forceEvict(BlockCacheKey cacheKey) {<a name="line.559"></a>
-<span class="sourceLineNo">560</span>    if (!cacheEnabled) {<a name="line.560"></a>
-<span class="sourceLineNo">561</span>      return false;<a name="line.561"></a>
-<span class="sourceLineNo">562</span>    }<a name="line.562"></a>
-<span class="sourceLineNo">563</span>    RAMQueueEntry removedBlock = checkRamCache(cacheKey);<a name="line.563"></a>
-<span class="sourceLineNo">564</span>    BucketEntry bucketEntry = backingMap.get(cacheKey);<a name="line.564"></a>
-<span class="sourceLineNo">565</span>    if (bucketEntry == null) {<a name="line.565"></a>
-<span class="sourceLineNo">566</span>      if (removedBlock != null) {<a name="line.566"></a>
-<span class="sourceLineNo">567</span>        cacheStats.evicted(0, cacheKey.isPrimary());<a name="line.567"></a>
-<span class="sourceLineNo">568</span>        return true;<a name="line.568"></a>
-<span class="sourceLineNo">569</span>      } else {<a name="line.569"></a>
-<span class="sourceLineNo">570</span>        return false;<a name="line.570"></a>
-<span class="sourceLineNo">571</span>      }<a name="line.571"></a>
-<span class="sourceLineNo">572</span>    }<a name="line.572"></a>
-<span class="sourceLineNo">573</span>    ReentrantReadWriteLock lock = offsetLock.getLock(bucketEntry.offset());<a name="line.573"></a>
-<span class="sourceLineNo">574</span>    try {<a name="line.574"></a>
-<span class="sourceLineNo">575</span>      lock.writeLock().lock();<a name="line.575"></a>
-<span class="sourceLineNo">576</span>      if (backingMap.remove(cacheKey, bucketEntry)) {<a name="line.576"></a>
-<span class="sourceLineNo">577</span>        blockEvicted(cacheKey, bucketEntry, removedBlock == null);<a name="line.577"></a>
-<span class="sourceLineNo">578</span>      } else {<a name="line.578"></a>
-<span class="sourceLineNo">579</span>        return false;<a name="line.579"></a>
-<span class="sourceLineNo">580</span>      }<a name="line.580"></a>
-<span class="sourceLineNo">581</span>    } finally {<a name="line.581"></a>
-<span class="sourceLineNo">582</span>      lock.writeLock().unlock();<a name="line.582"></a>
-<span class="sourceLineNo">583</span>    }<a name="line.583"></a>
-<span class="sourceLineNo">584</span>    cacheStats.evicted(bucketEntry.getCachedTime(), cacheKey.isPrimary());<a name="line.584"></a>
-<span class="sourceLineNo">585</span>    return true;<a name="line.585"></a>
-<span class="sourceLineNo">586</span>  }<a name="line.586"></a>
-<span class="sourceLineNo">587</span><a name="line.587"></a>
-<span class="sourceLineNo">588</span>  private RAMQueueEntry checkRamCache(BlockCacheKey cacheKey) {<a name="line.588"></a>
-<span class="sourceLineNo">589</span>    RAMQueueEntry removedBlock = ramCache.remove(cacheKey);<a name="line.589"></a>
-<span class="sourceLineNo">590</span>    if (removedBlock != null) {<a name="line.590"></a>
-<span class="sourceLineNo">591</span>      this.blockNumber.decrement();<a name="line.591"></a>
-<span class="sourceLineNo">592</span>      this.heapSize.add(-1 * removedBlock.getData().heapSize());<a name="line.592"></a>
-<span class="sourceLineNo">593</span>    }<a name="line.593"></a>
-<span class="sourceLineNo">594</span>    return removedBlock;<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>  public boolean evictBlock(BlockCacheKey cacheKey, boolean deletedBlock) {<a name="line.597"></a>
-<span class="sourceLineNo">598</span>    if (!cacheEnabled) {<a name="line.598"></a>
-<span class="sourceLineNo">599</span>      return false;<a name="line.599"></a>
+<span class="sourceLineNo">527</span>          if (cachedBlock.getMemoryType() == MemoryType.SHARED) {<a name="line.527"></a>
+<span class="sourceLineNo">528</span>            bucketEntry.incrementRefCountAndGet();<a name="line.528"></a>
+<span class="sourceLineNo">529</span>          }<a name="line.529"></a>
+<span class="sourceLineNo">530</span>          bucketEntry.access(accessCount.incrementAndGet());<a name="line.530"></a>
+<span class="sourceLineNo">531</span>          if (this.ioErrorStartTime &gt; 0) {<a name="line.531"></a>
+<span class="sourceLineNo">532</span>            ioErrorStartTime = -1;<a name="line.532"></a>
+<span class="sourceLineNo">533</span>          }<a name="line.533"></a>
+<span class="sourceLineNo">534</span>          return cachedBlock;<a name="line.534"></a>
+<span class="sourceLineNo">535</span>        }<a name="line.535"></a>
+<span class="sourceLineNo">536</span>      } catch (IOException ioex) {<a name="line.536"></a>
+<span class="sourceLineNo">537</span>        LOG.error("Failed reading block " + key + " from bucket cache", ioex);<a name="line.537"></a>
+<span class="sourceLineNo">538</span>        checkIOErrorIsTolerated();<a name="line.538"></a>
+<span class="sourceLineNo">539</span>      } finally {<a name="line.539"></a>
+<span class="sourceLineNo">540</span>        lock.readLock().unlock();<a name="line.540"></a>
+<span class="sourceLineNo">541</span>      }<a name="line.541"></a>
+<span class="sourceLineNo">542</span>    }<a name="line.542"></a>
+<span class="sourceLineNo">543</span>    if (!repeat &amp;&amp; updateCacheMetrics) {<a name="line.543"></a>
+<span class="sourceLineNo">544</span>      cacheStats.miss(caching, key.isPrimary(), key.getBlockType());<a name="line.544"></a>
+<span class="sourceLineNo">545</span>    }<a name="line.545"></a>
+<span class="sourceLineNo">546</span>    return null;<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>  @VisibleForTesting<a name="line.549"></a>
+<span class="sourceLineNo">550</span>  void blockEvicted(BlockCacheKey cacheKey, BucketEntry bucketEntry, boolean decrementBlockNumber) {<a name="line.550"></a>
+<span class="sourceLineNo">551</span>    bucketAllocator.freeBlock(bucketEntry.offset());<a name="line.551"></a>
+<span class="sourceLineNo">552</span>    realCacheSize.add(-1 * bucketEntry.getLength());<a name="line.552"></a>
+<span class="sourceLineNo">553</span>    blocksByHFile.remove(cacheKey);<a name="line.553"></a>
+<span class="sourceLineNo">554</span>    if (decrementBlockNumber) {<a name="line.554"></a>
+<span class="sourceLineNo">555</span>      this.blockNumber.decrement();<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>  @Override<a name="line.559"></a>
+<span class="sourceLineNo">560</span>  public boolean evictBlock(BlockCacheKey cacheKey) {<a name="line.560"></a>
+<span class="sourceLineNo">561</span>    return evictBlock(cacheKey, true);<a name="line.561"></a>
+<span class="sourceLineNo">562</span>  }<a name="line.562"></a>
+<span class="sourceLineNo">563</span><a name="line.563"></a>
+<span class="sourceLineNo">564</span>  // does not check for the ref count. Just tries to evict it if found in the<a name="line.564"></a>
+<span class="sourceLineNo">565</span>  // bucket map<a name="line.565"></a>
+<span class="sourceLineNo">566</span>  private boolean forceEvict(BlockCacheKey cacheKey) {<a name="line.566"></a>
+<span class="sourceLineNo">567</span>    if (!cacheEnabled) {<a name="line.567"></a>
+<span class="sourceLineNo">568</span>      return false;<a name="line.568"></a>
+<span class="sourceLineNo">569</span>    }<a name="line.569"></a>
+<span class="sourceLineNo">570</span>    RAMQueueEntry removedBlock = checkRamCache(cacheKey);<a name="line.570"></a>
+<span class="sourceLineNo">571</span>    BucketEntry bucketEntry = backingMap.get(cacheKey);<a name="line.571"></a>
+<span class="sourceLineNo">572</span>    if (bucketEntry == null) {<a name="line.572"></a>
+<span class="sourceLineNo">573</span>      if (removedBlock != null) {<a name="line.573"></a>
+<span class="sourceLineNo">574</span>        cacheStats.evicted(0, cacheKey.isPrimary());<a name="line.574"></a>
+<span class="sourceLineNo">575</span>        return true;<a name="line.575"></a>
+<span class="sourceLineNo">576</span>      } else {<a name="line.576"></a>
+<span class="sourceLineNo">577</span>        return false;<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>    ReentrantReadWriteLock lock = offsetLock.getLock(bucketEntry.offset());<a name="line.580"></a>
+<span class="sourceLineNo">581</span>    try {<a name="line.581"></a>
+<span class="sourceLineNo">582</span>      lock.writeLock().lock();<a name="line.582"></a>
+<span class="sourceLineNo">583</span>      if (backingMap.remove(cacheKey, bucketEntry)) {<a name="line.583"></a>
+<span class="sourceLineNo">584</span>        blockEvicted(cacheKey, bucketEntry, removedBlock == null);<a name="line.584"></a>
+<span class="sourceLineNo">585</span>      } else {<a name="line.585"></a>
+<span class="sourceLineNo">586</span>        return false;<a name="line.586"></a>
+<span class="sourceLineNo">587</span>      }<a name="line.587"></a>
+<span class="sourceLineNo">588</span>    } finally {<a name="line.588"></a>
+<span class="sourceLineNo">589</span>      lock.writeLock().unlock();<a name="line.589"></a>
+<span class="sourceLineNo">590</span>    }<a name="line.590"></a>
+<span class="sourceLineNo">591</span>    cacheStats.evicted(bucketEntry.getCachedTime(), cacheKey.isPrimary());<a name="line.591"></a>
+<span class="sourceLineNo">592</span>    return true;<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>  private RAMQueueEntry checkRamCache(BlockCacheKey cacheKey) {<a name="line.595"></a>
+<span class="sourceLineNo">596</span>    RAMQueueEntry removedBlock = ramCache.remove(cacheKey);<a name="line.596"></a>
+<span class="sourceLineNo">597</span>    if (removedBlock != null) {<a name="line.597"></a>
+<span class="sourceLineNo">598</span>      this.blockNumber.decrement();<a name="line.598"></a>
+<span class="sourceLineNo">599</span>      this.heapSize.add(-1 * removedBlock.getData().heapSize());<a name="line.599"></a>
 <span class="sourceLineNo">600</span>    }<a name="line.600"></a>
-<span class="sourceLineNo">601</span>    RAMQueueEntry removedBlock = checkRamCache(cacheKey);<a name="line.601"></a>
-<span class="sourceLineNo">602</span>    BucketEntry bucketEntry = backingMap.get(cacheKey);<a name="line.602"></a>
-<span class="sourceLineNo">603</span>    if (bucketEntry == null) {<a name="line.603"></a>
-<span class="sourceLineNo">604</span>      if (removedBlock != null) {<a name="line.604"></a>
-<span class="sourceLineNo">605</span>        cacheStats.evicted(0, cacheKey.isPrimary());<a name="line.605"></a>
-<span class="sourceLineNo">606</span>        return true;<a name="line.606"></a>
-<span class="sourceLineNo">607</span>      } else {<a name="line.607"></a>
-<span class="sourceLineNo">608</span>        return false;<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>    ReentrantReadWriteLock lock = offsetLock.getLock(bucketEntry.offset());<a name="line.611"></a>
-<span class="sourceLineNo">612</span>    try {<a name="line.612"></a>
-<span class="sourceLineNo">613</span>      lock.writeLock().lock();<a name="line.613"></a>
-<span class="sourceLineNo">614</span>      int refCount = bucketEntry.getRefCount();<a name="line.614"></a>
-<span class="sourceLineNo">615</span>      if (refCount == 0) {<a name="line.615"></a>
-<span class="sourceLineNo">616</span>        if (backingMap.remove(cacheKey, bucketEntry)) {<a name="line.616"></a>
-<span class="sourceLineNo">617</span>          blockEvicted(cacheKey, bucketEntry, removedBlock == null);<a name="line.617"></a>
-<span class="sourceLineNo">618</span>        } else {<a name="line.618"></a>
-<span class="sourceLineNo">619</span>          return false;<a name="line.619"></a>
-<span class="sourceLineNo">620</span>        }<a name="line.620"></a>
-<span class="sourceLineNo">621</span>      } else {<a name="line.621"></a>
-<span class="sourceLineNo">622</span>        if(!deletedBlock) {<a name="line.622"></a>
-<span class="sourceLineNo">623</span>          if (LOG.isDebugEnabled()) {<a name="line.623"></a>
-<span class="sourceLineNo">624</span>            LOG.debug("This block " + cacheKey + " is still referred by " + refCount<a name="line.624"></a>
-<span class="sourceLineNo">625</span>                + " readers. Can not be freed now");<a name="line.625"></a>
-<span class="sourceLineNo">626</span>          }<a name="line.626"></a>
-<span class="sourceLineNo">627</span>          return false;<a name="line.627"></a>
-<span class="sourceLineNo">628</span>        } else {<a name="line.628"></a>
-<span class="sourceLineNo">629</span>          if (LOG.isDebugEnabled()) {<a name="line.629"></a>
-<span class="sourceLineNo">630</span>            LOG.debug("This block " + cacheKey + " is still referred by " + refCount<a name="line.630"></a>
-<span class="sourceLineNo">631</span>                + " readers. Can not be freed now. Hence will mark this"<a name="line.631"></a>
-<span class="sourceLineNo">632</span>                + " for evicting at a later point");<a name="line.632"></a>
+<span class="sourceLineNo">601</span>    return removedBlock;<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>  public boolean evictBlock(BlockCacheKey cacheKey, boolean deletedBlock) {<a name="line.604"></a>
+<span class="sourceLineNo">605</span>    if (!cacheEnabled) {<a name="line.605"></a>
+<span class="sourceLineNo">606</span>      return false;<a name="line.606"></a>
+<span class="sourceLineNo">607</span>    }<a name="line.607"></a>
+<span class="sourceLineNo">608</span>    RAMQueueEntry removedBlock = checkRamCache(cacheKey);<a name="line.608"></a>
+<span class="sourceLineNo">609</span>    BucketEntry bucketEntry = backingMap.get(cacheKey);<a name="line.609"></a>
+<span class="sourceLineNo">610</span>    if (bucketEntry == null) {<a name="line.610"></a>
+<span class="sourceLineNo">611</span>      if (removedBlock != null) {<a name="line.611"></a>
+<span class="sourceLineNo">612</span>        cacheStats.evicted(0, cacheKey.isPrimary());<a name="line.612"></a>
+<span class="sourceLineNo">613</span>        return true;<a name="line.613"></a>
+<span class="sourceLineNo">614</span>      } else {<a name="line.614"></a>
+<span class="sourceLineNo">615</span>        return false;<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>    ReentrantReadWriteLock lock = offsetLock.getLock(bucketEntry.offset());<a name="line.618"></a>
+<span class="sourceLineNo">619</span>    try {<a name="line.619"></a>
+<span class="sourceLineNo">620</span>      lock.writeLock().lock();<a name="line.620"></a>
+<span class="sourceLineNo">621</span>      int refCount = bucketEntry.getRefCount();<a name="line.621"></a>
+<span class="sourceLineNo">622</span>      if (refCount == 0) {<a name="line.622"></a>
+<span class="sourceLineNo">623</span>        if (backingMap.remove(cacheKey, bucketEntry)) {<a name="line.623"></a>
+<span class="sourceLineNo">624</span>          blockEvicted(cacheKey, bucketEntry, removedBlock == null);<a name="line.624"></a>
+<span class="sourceLineNo">625</span>        } else {<a name="line.625"></a>
+<span class="sourceLineNo">626</span>          return false;<a name="line.626"></a>
+<span class="sourceLineNo">627</span>        }<a name="line.627"></a>
+<span class="sourceLineNo">628</span>      } else {<a name="line.628"></a>
+<span class="sourceLineNo">629</span>        if(!deletedBlock) {<a name="line.629"></a>
+<span class="sourceLineNo">630</span>          if (LOG.isDebugEnabled()) {<a name="line.630"></a>
+<span class="sourceLineNo">631</span>            LOG.debug("This block " + cacheKey + " is still referred by " + refCount<a name="line.631"></a>
+<span class="sourceLineNo">632</span>                + " readers. Can not be freed now");<a name="line.632"></a>
 <span class="sourceLineNo">633</span>          }<a name="line.633"></a>
-<span class="sourceLineNo">634</span>          bucketEntry.markForEvict();<a name="line.634"></a>
-<span class="sourceLineNo">635</span>        }<a name="line.635"></a>
-<span class="sourceLineNo">636</span>      }<a name="line.636"></a>
-<span class="sourceLineNo">637</span>    } finally {<a name="line.637"></a>
-<span class="sourceLineNo">638</span>      lock.writeLock().unlock();<a name="line.638"></a>
-<span class="sourceLineNo">639</span>    }<a name="line.639"></a>
-<span class="sourceLineNo">640</span>    cacheStats.evicted(bucketEntry.getCachedTime(), cacheKey.isPrimary());<a name="line.640"></a>
-<span class="sourceLineNo">641</span>    return true;<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>   * Statistics thread.  Periodically output cache statistics to the log.<a name="line.645"></a>
-<span class="sourceLineNo">646</span>   */<a name="line.646"></a>
-<span class="sourceLineNo">647</span>  private static class StatisticsThread extends Thread {<a name="line.647"></a>
-<span class="sourceLineNo">648</span>    private final BucketCache bucketCache;<a name="line.648"></a>
-<span class="sourceLineNo">649</span><a name="line.649"></a>
-<span class="sourceLineNo">650</span>    public StatisticsThread(BucketCache bucketCache) {<a name="line.650"></a>
-<span class="sourceLineNo">651</span>      super("BucketCacheStatsThread");<a name="line.651"></a>
-<span class="sourceLineNo">652</span>      setDaemon(true);<a name="line.652"></a>
-<span class="sourceLineNo">653</span>      this.bucketCache = bucketCache;<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 void run() {<a name="line.657"></a>
-<span class="sourceLineNo">658</span>      bucketCache.logStats();<a name="line.658"></a>
-<span class="sourceLineNo">659</span>    }<a name="line.659"></a>
-<span class="sourceLineNo">660</span>  }<a name="line.660"></a>
-<span class="sourceLineNo">661</span><a name="line.661"></a>
-<span class="sourceLineNo">662</span>  public void logStats() {<a name="line.662"></a>
-<span class="sourceLineNo">663</span>    long totalSize = bucketAllocator.getTotalSize();<a name="line.663"></a>
-<span class="sourceLineNo">664</span>    long usedSize = bucketAllocator.getUsedSize();<a name="line.664"></a>
-<span class="sourceLineNo">665</span>    long freeSize = totalSize - usedSize;<a name="line.665"></a>
-<span class="sourceLineNo">666</span>    long cacheSize = getRealCacheSize();<a name="line.666"></a>
-<span class="sourceLineNo">667</span>    LOG.info("failedBlockAdditions=" + cacheStats.getFailedInserts() + ", " +<a name="line.667"></a>
-<span class="sourceLineNo">668</span>        "totalSize=" + StringUtils.byteDesc(totalSize) + ", " +<a name="line.668"></a>
-<span class="sourceLineNo">669</span>        "freeSize=" + StringUtils.byteDesc(freeSize) + ", " +<a name="line.669"></a>
-<span class="sourceLineNo">670</span>        "usedSize=" + StringUtils.byteDesc(usedSize) +", " +<a name="line.670"></a>
-<span class="sourceLineNo">671</span>        "cacheSize=" + StringUtils.byteDesc(cacheSize) +", " +<a name="line.671"></a>
-<span class="sourceLineNo">672</span>        "accesses=" + cacheStats.getRequestCount() + ", " +<a name="line.672"></a>
-<span class="sourceLineNo">673</span>        "hits=" + cacheStats.getHitCount() + ", " +<a name="line.673"></a>
-<span class="sourceLineNo">674</span>        "IOhitsPerSecond=" + cacheStats.getIOHitsPerSecond() + ", " +<a name="line.674"></a>
-<span class="sourceLineNo">675</span>        "IOTimePerHit=" + String.format("%.2f", cacheStats.getIOTimePerHit())+ ", " +<a name="line.675"></a>
-<span class="sourceLineNo">676</span>        "hitRatio=" + (cacheStats.getHitCount() == 0 ? "0," :<a name="line.676"></a>
-<span class="sourceLineNo">677</span>          (StringUtils.formatPercent(cacheStats.getHitRatio(), 2)+ ", ")) +<a name="line.677"></a>
-<span class="sourceLineNo">678</span>        "cachingAccesses=" + cacheStats.getRequestCachingCount() + ", " +<a name="line.678"></a>
-<span class="sourceLineNo">679</span>        "cachingHits=" + cacheStats.getHitCachingCount() + ", " +<a name="line.679"></a>
-<span class="sourceLineNo">680</span>        "cachingHitsRatio=" +(cacheStats.getHitCachingCount() == 0 ? "0," :<a name="line.680"></a>
-<span class="sourceLineNo">681</span>          (StringUtils.formatPercent(cacheStats.getHitCachingRatio(), 2)+ ", ")) +<a name="line.681"></a>
-<span class="sourceLineNo">682</span>        "evictions=" + cacheStats.getEvictionCount() + ", " +<a name="line.682"></a>
-<span class="sourceLineNo">683</span>        "evicted=" + cacheStats.getEvictedCount() + ", " +<a name="line.683"></a>
-<span class="sourceLineNo">684</span>        "evictedPerRun=" + cacheStats.evictedPerEviction());<a name="line.684"></a>
-<span class="sourceLineNo">685</span>    cacheStats.reset();<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>  public long getRealCacheSize() {<a name="line.688"></a>
-<span class="sourceLineNo">689</span>    return this.realCacheSize.sum();<a name="line.689"></a>
-<span class="sourceLineNo">690</span>  }<a name="line.690"></a>
-<span class="sourceLineNo">691</span><a name="line.691"></a>
-<span class="sourceLineNo">692</span>  private long acceptableSize() {<a name="line.692"></a>
-<span class="sourceLineNo">693</span>    return (long) Math.floor(bucketAllocator.getTotalSize() * acceptableFactor);<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>  @VisibleForTesting<a name="line.696"></a>
-<span class="sourceLineNo">697</span>  long getPartitionSize(float partitionFactor) {<a name="line.697"></a>
-<span class="sourceLineNo">698</span>    return (long) Math.floor(bucketAllocator.getTotalSize() * partitionFactor * minFactor);<a name="line.698"></a>
-<span class="sourceLineNo">699</span>  }<a name="line.699"></a>
-<span class="sourceLineNo">700</span><a name="line.700"></a>
-<span class="sourceLineNo">701</span>  /**<a name="line.701"></a>
-<span class="sourceLineNo">702</span>   * Return the count of bucketSizeinfos still need free space<a name="line.702"></a>
-<span class="sourceLineNo">703</span>   */<a name="line.703"></a>
-<span class="sourceLineNo">704</span>  private int bucketSizesAboveThresholdCount(float minFactor) {<a name="line.704"></a>
-<span class="sourceLineNo">705</span>    BucketAllocator.IndexStatistics[] stats = bucketAllocator.getIndexStatistics();<a name="line.705"></a>
-<span class="sourceLineNo">706</span>    int fullCount = 0;<a name="line.706"></a>
-<span class="sourceLineNo">707</span>    for (int i = 0; i &lt; stats.length; i++) {<a name="line.707"></a>
-<span class="sourceLineNo">708</span>      long freeGoal = (long) Math.floor(stats[i].totalCount() * (1 - minFactor));<a name="line.708"></a>
-<span class="sourceLineNo">709</span>      freeGoal = Math.max(freeGoal, 1);<a name="line.709"></a>
-<span class="sourceLineNo">710</span>      if (stats[i].freeCount() &lt; freeGoal) {<a name="line.710"></a>
-<span class="sourceLineNo">711</span>        fullCount++;<a name="line.711"></a>
-<span class="sourceLineNo">712</span>      }<a name="line.712"></a>
-<span class="sourceLineNo">713</span>    }<a name="line.713"></a>
-<span class="sourceLineNo">714</span>    return fullCount;<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">717</span>  /**<a name="line.717"></a>
-<span class="sourceLineNo">718</span>   * This method will find the buckets that are minimally occupied<a name="line.718"></a>
-<span class="sourceLineNo">719</span>   * and are not reference counted and will free them completely<a name="line.719"></a>
-<span class="sourceLineNo">720</span>   * without any constraint on the access times of the elements,<a name="line.720"></a>
-<span class="sourceLineNo">721</span>   * and as a process will completely free at most the number of buckets<a name="line.721"></a>
-<span class="sourceLineNo">722</span>   * passed, sometimes it might not due to changing refCounts<a name="line.722"></a>
-<span class="sourceLineNo">723</span>   *<a name="line.723"></a>
-<span class="sourceLineNo">724</span>   * @param completelyFreeBucketsNeeded number of buckets to free<a name="line.724"></a>
-<span class="sourceLineNo">725</span>   **/<a name="line.725"></a>
-<span class="sourceLineNo">726</span>  private void freeEntireBuckets(int completelyFreeBucketsNeeded) {<a name="line.726"></a>
-<span class="sourceLineNo">727</span>    if (completelyFreeBucketsNeeded != 0) {<a name="line.727"></a>
-<span class="sourceLineNo">728</span>      // First we will build a set where the offsets are reference counted, usually<a name="line.728"></a>
-<span class="sourceLineNo">729</span>      // this set is small around O(Handler Count) unless something else is wrong<a name="line.729"></a>
-<span class="sourceLineNo">730</span>      Set&lt;Integer&gt; inUseBuckets = new HashSet&lt;Integer&gt;();<a name="line.730"></a>
-<span class="sourceLineNo">731</span>      for (BucketEntry entry : backingMap.values()) {<a name="line.731"></a>
-<span class="sourceLineNo">732</span>        if (entry.getRefCount() != 0) {<a name="line.732"></a>
-<span class="sourceLineNo">733</span>          inUseBuckets.add(bucketAllocator.getBucketIndex(entry.offset()));<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><a name="line.736"></a>
-<span class="sourceLineNo">737</span>      Set&lt;Integer&gt; candidateBuckets = bucketAllocator.getLeastFilledBuckets(<a name="line.737"></a>
-<span class="sourceLineNo">738</span>          inUseBuckets, completelyFreeBucketsNeeded);<a name="line.738"></a>
-<span class="sourceLineNo">739</span>      for (Map.Entry&lt;BlockCacheKey, BucketEntry&gt; entry : backingMap.entrySet()) {<a name="line.739"></a>
-<span class="sourceLineNo">740</span>        if (candidateBuckets.contains(bucketAllocator<a name="line.740"></a>
-<span class="sourceLineNo">741</span>            .getBucketIndex(entry.getValue().offset()))) {<a name="line.741"></a>
-<span class="sourceLineNo">742</span>          evictBlock(entry.getKey(), false);<a name="line.742"></a>
-<span class="sourceLineNo">743</span>        }<a name="line.743"></a>
-<span class="sourceLineNo">744</span>      }<a name="line.744"></a>
-<span class="sourceLineNo">745</span>    }<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>  /**<a name="line.748"></a>
-<span class="sourceLineNo">749</span>   * Free the space if the used size reaches acceptableSize() or one size block<a name="line.749"></a>
-<span class="sourceLineNo">750</span>   * couldn't be allocated. When freeing the space, we use the LRU algorithm and<a name="line.750"></a>
-<span class="sourceLineNo">751</span>   * ensure there must be some blocks evicted<a name="line.751"></a>
-<span class="sourceLineNo">752</span>   * @param why Why we are being called<a name="line.752"></a>
-<span class="sourceLineNo">753</span>   */<a name="line.753"></a>
-<span class="sourceLineNo">754</span>  private void freeSpace(final String why) {<a name="line.754"></a>
-<span class="sourceLineNo">755</span>    // Ensure only one freeSpace progress at a time<a name="line.755"></a>
-<span class="sourceLineNo">756</span>    if (!freeSpaceLock.tryLock()) {<a name="line.756"></a>
-<span class="sourceLineNo">757</span>      return;<a name="line.757"></a>
-<span class="sourceLineNo">758</span>    }<a name="line.758"></a>
-<span class="sourceLineNo">759</span>    try {<a name="line.759"></a>
-<span class="sourceLineNo">760</span>      freeInProgress = true;<a name="line.760"></a>
-<span class="sourceLineNo">761</span>      long bytesToFreeWithoutExtra = 0;<a name="line.761"></a>
-<span class="sourceLineNo">762</span>      // Calculate free byte for each bucketSizeinfo<a name="line.762"></a>
-<span class="sourceLineNo">763</span>      StringBuilder msgBuffer = LOG.isDebugEnabled()? new StringBuilder(): null;<a name="line.763"></a>
-<span class="sourceLineNo">764</span>      BucketAllocator.IndexStatistics[] stats = bucketAllocator.getIndexStatistics();<a name="line.764"></a>
-<span class="sourceLineNo">765</span>      long[] bytesToFreeForBucket = new long[stats.length];<a name="line.765"></a>
-<span class="sourceLineNo">766</span>      for (int i = 0; i &lt; stats.length; i++) {<a name="line.766"></a>
-<span class="sourceLineNo">767</span>        bytesToFreeForBucket[i] = 0;<a name="line.767"></a>
-<span class="sourceLineNo">768</span>        long freeGoal = (long) Math.floor(stats[i].totalCount() * (1 - minFactor));<a name="line.768"></a>
-<span class="sourceLineNo">769</span>        freeGoal = Math.max(freeGoal, 1);<a name="line.769"></a>
-<span class="sourceLineNo">770</span>        if (stats[i].freeCount() &lt; freeGoal) {<a name="line.770"></a>
-<span class="sourceLineNo">771</span>          bytesToFreeForBucket[i] = stats[i].itemSize() * (freeGoal - stats[i].freeCount());<a name="line.771"></a>
-<span class="sourceLineNo">772</span>          bytesToFreeWithoutExtra += bytesToFreeForBucket[i];<a name="line.772"></a>
-<span class="sourceLineNo">773</span>          if (msgBuffer != null) {<a name="line.773"></a>
-<span class="sourceLineNo">774</span>            msgBuffer.append("Free for bucketSize(" + stats[i].itemSize() + ")="<a name="line.774"></a>
-<span class="sourceLineNo">775</span>              + StringUtils.byteDesc(bytesToFreeForBucket[i]) + ", ");<a name="line.775"></a>
-<span class="sourceLineNo">776</span>          }<a name="line.776"></a>
-<span class="sourceLineNo">777</span>        }<a name="line.777"></a>
-<span class="sourceLineNo">778</span>      }<a name="line.778"></a>
-<span class="sourceLineNo">779</span>      if (msgBuffer != null) {<a name="line.779"></a>
-<span class="sourceLineNo">780</span>        msgBuffer.append("Free for total=" + StringUtils.byteDesc(bytesToFreeWithoutExtra) + ", ");<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>      if (bytesToFreeWithoutExtra &lt;= 0) {<a name="line.783"></a>
-<span class="sourceLineNo">784</span>        return;<a name="line.784"></a>
+<span class="sourceLineNo">634</span>          return false;<a name="line.634"></a>
+<span class="sourceLineNo">635</span>        } else {<a name="line.635"></a>
+<span class="sourceLineNo">636</span>          if (LOG.isDebugEnabled()) {<a name="line.636"></a>
+<span class="sourceLineNo">637</span>            LOG.debug("This block " + cacheKey + " is still referred by " + refCount<a name="line.637"></a>
+<span class="sourceLineNo">638</span>                + " readers. Can not be freed now. Hence will mark this"<a name="line.638"></a>
+<span class="sourceLineNo">639</span>                + " for evicting at a later point");<a name="line.639"></a>
+<span class="sourceLineNo">640</span>          }<a name="line.640"></a>
+<span class="sourceLineNo">641</span>          bucketEntry.markForEvict();<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>    } finally {<a name="line.644"></a>
+<span class="sourceLineNo">645</span>      lock.writeLock().unlock();<a name="line.645"></a>
+<span class="sourceLineNo">646</span>    }<a name="line.646"></a>
+<span class="sourceLineNo">647</span>    cacheStats.evicted(bucketEntry.getCachedTime(), cacheKey.isPrimary());<a name="line.647"></a>
+<span class="sourceLineNo">648</span>    return true;<a name="line.648"></a>
+<span class="sourceLineNo">649</span>  }<a name="line.649"></a>
+<span class="sourceLineNo">650</span><a name="line.650"></a>
+<span class="sourceLineNo">651</span>  /*<a name="line.651"></a>
+<span class="sourceLineNo">652</span>   * Statistics thread.  Periodically output cache statistics to the log.<a name="line.652"></a>
+<span class="sourceLineNo">653</span>   */<a name="line.653"></a>
+<span class="sourceLineNo">654</span>  private static class StatisticsThread extends Thread {<a name="line.654"></a>
+<span class="sourceLineNo">655</span>    private final BucketCache bucketCache;<a name="line.655"></a>
+<span class="sourceLineNo">656</span><a name="line.656"></a>
+<span class="sourceLineNo">657</span>    public StatisticsThread(BucketCache bucketCache) {<a name="line.657"></a>
+<span class="sourceLineNo">658</span>      super("BucketCacheStatsThread");<a name="line.658"></a>
+<span class="sourceLineNo">659</span>      setDaemon(true);<a name="line.659"></a>
+<span class="sourceLineNo">660</span>      this.bucketCache = bucketCache;<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>    @Override<a name="line.663"></a>
+<span class="sourceLineNo">664</span>    public void run() {<a name="line.664"></a>
+<span class="sourceLineNo">665</span>      bucketCache.logStats();<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>  public void logStats() {<a name="line.669"></a>
+<span class="sourceLineNo">670</span>    long totalSize = bucketAllocator.getTotalSize();<a name="line.670"></a>
+<span class="sourceLineNo">671</span>    long usedSize = bucketAllocator.getUsedSize();<a name="line.671"></a>
+<span class="sourceLineNo">672</span>    long freeSize = totalSize - usedSize;<a name="line.672"></a>
+<span class="sourceLineNo">673</span>    long cacheSize = getRealCacheSize();<a name="line.673"></a>
+<span class="sourceLineNo">674</span>    LOG.info("failedBlockAdditions=" + cacheStats.getFailedInserts() + ", " +<a name="line.674"></a>
+<span class="sourceLineNo">675</span>        "totalSize=" + StringUtils.byteDesc(totalSize) + ", " +<a name="line.675"></a>
+<span class="sourceLineNo">676</span>        "freeSize=" + StringUtils.byteDesc(freeSize) + ", " +<a name="line.676"></a>
+<span class="sourceLineNo">677</span>        "usedSize=" + StringUtils.byteDesc(usedSize) +", " +<a name="line.677"></a>
+<span class="sourceLineNo">678</span>        "cacheSize=" + StringUtils.byteDesc(cacheSize) +", " +<a name="line.678"></a>
+<span class="sourceLineNo">679</span>        "accesses=" + cacheStats.getRequestCount() + ", " +<a name="line.679"></a>
+<span class="sourceLineNo">680</span>        "hits=" + cacheStats.getHitCount() + ", " +<a name="line.680"></a>
+<span class="sourceLineNo">681</span>        "IOhitsPerSecond=" + cacheStats.getIOHitsPerSecond() + ", " +<a name="line.681"></a>
+<span class="sourceLineNo">682</span>        "IOTimePerHit=" + String.format("%.2f", cacheStats.getIOTimePerHit())+ ", " +<a name="line.682"></a>
+<span class="sourceLineNo">683</span>        "hitRatio=" + (cacheStats.getHitCount() == 0 ? "0," :<a name="line.683"></a>
+<span class="sourceLineNo">684</span>          (StringUtils.formatPercent(cacheStats.getHitRatio(), 2)+ ", ")) +<a name="line.684"></a>
+<span class="sourceLineNo">685</span>        "cachingAccesses=" + cacheStats.getRequestCachingCount() + ", " +<a name="line.685"></a>
+<span class="sourceLineNo">686</span>        "cachingHits=" + cacheStats.getHitCachingCount() + ", " +<a name="line.686"></a>
+<span class="sourceLineNo">687</span>        "cachingHitsRatio=" +(cacheStats.getHitCachingCount() == 0 ? "0," :<a name="line.687"></a>
+<span class="sourceLineNo">688</span>          (StringUtils.formatPercent(cacheStats.getHitCachingRatio(), 2)+ ", ")) +<a name="line.688"></a>
+<span class="sourceLineNo">689</span>        "evictions=" + cacheStats.getEvictionCount() + ", " +<a name="line.689"></a>
+<span class="sourceLineNo">690</span>        "evicted=" + cacheStats.getEvictedCount() + ", " +<a name="line.690"></a>
+<span class="sourceLineNo">691</span>        "evictedPerRun=" + cacheStats.evictedPerEviction());<a name="line.691"></a>
+<span class="sourceLineNo">692</span>    cacheStats.reset();<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>  public long getRealCacheSize() {<a name="line.695"></a>
+<span class="sourceLineNo">696</span>    return this.realCacheSize.sum();<a name="line.696"></a>
+<span class="sourceLineNo">697</span>  }<a name="line.697"></a>
+<span class="sourceLineNo">698</span><a name="line.698"></a>
+<span class="sourceLineNo">699</span>  private long acceptableSize() {<a name="line.699"></a>
+<span class="sourceLineNo">700</span>    return (long) Math.floor(bucketAllocator.getTotalSize() * acceptableFactor);<a name="line.700"></a>
+<span class="sourceLineNo">701</span>  }<a name="line.701"></a>
+<span class="sourceLineNo">702</span><a name="line.702"></a>
+<span class="sourceLineNo">703</span>  @VisibleForTesting<a name="line.703"></a>
+<span class="sourceLineNo">704</span>  long getPartitionSize(float partitionFactor) {<a name="line.704"></a>
+<span class="sourceLineNo">705</span>    return (long) Math.floor(bucketAllocator.getTotalSize() * partitionFactor * minFactor);<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>   * Return the count of bucketSizeinfos still need free space<a name="line.709"></a>
+<span class="sourceLineNo">710</span>   */<a name="line.710"></a>
+<span class="sourceLineNo">711</span>  private int bucketSizesAboveThresholdCount(float minFactor) {<a name="line.711"></a>
+<span class="sourceLineNo">712</span>    BucketAllocator.IndexStatistics[] stats = bucketAllocator.getIndexStatistics();<a name="line.712"></a>
+<span class="sourceLineNo">713</span>    int fullCount = 0;<a name="line.713"></a>
+<span class="sourceLineNo">714</span>    for (int i = 0; i &lt; stats.length; i++) {<a name="line.714"></a>
+<span class="sourceLineNo">715</span>      long freeGoal = (long) Math.floor(stats[i].totalCount() * (1 - minFactor));<a name="line.715"></a>
+<span class="sourceLineNo">716</span>      freeGoal = Math.max(freeGoal, 1);<a name="line.716"></a>
+<span class="sourceLineNo">717</span>      if (stats[i].freeCount() &lt; freeGoal) {<a name="line.717"></a>
+<span class="sourceLineNo">718</span>        fullCount++;<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>
+<span class="sourceLineNo">721</span>    return fullCount;<a name="line.721"></a>
+<span class="sourceLineNo">722</span>  }<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>   * This method will find the buckets that are minimally occupied<a name="line.725"></a>
+<span class="sourceLineNo">726</span>   * and are not reference counted and will free them completely<a name="line.726"></a>
+<span class="sourceLineNo">727</span>   * without any constraint on the access times of the elements,<a name="line.727"></a>
+<span class="sourceLineNo">728</span>   * and as a process will completely free at most the number of buckets<a name="line.728"></a>
+<span class="sourceLineNo">729</span>   * passed, sometimes it might not due to changing refCounts<a name="line.729"></a>
+<span class="sourceLineNo">730</span>   *<a name="line.730"></a>
+<span class="sourceLineNo">731</span>   * @param completelyFreeBucketsNeeded number of buckets to free<a name="line.731"></a>
+<span class="sourceLineNo">732</span>   **/<a name="line.732"></a>
+<span class="sourceLineNo">733</span>  private void freeEntireBuckets(int completelyFreeBucketsNeeded) {<a name="line.733"></a>
+<span class="sourceLineNo">734</span>    if (completelyFreeBucketsNeeded != 0) {<a name="line.734"></a>
+<span class="sourceLineNo">735</span>      // First we will build a set where the offsets are reference counted, usually<a name="line.735"></a>
+<span class="sourceLineNo">736</span>      // this set is small around O(Handler Count) unless something else is wrong<a name="line.736"></a>
+<span class="sourceLineNo">737</span>      Set&lt;Integer&gt; inUseBuckets = new HashSet&lt;Integer&gt;();<a name="line.737"></a>
+<span class="sourceLineNo">738</span>      for (BucketEntry entry : backingMap.values()) {<a name="line.738"></a>
+<span class="sourceLineNo">739</span>        if (entry.getRefCount() != 0) {<a name="line.739"></a>
+<span class="sourceLineNo">740</span>          inUseBuckets.add(bucketAllocator.getBucketIndex(entry.offset()));<a name="line.740"></a>
+<span class="sourceLineNo">741</span>        }<a name="line.741"></a>
+<span class="sourceLineNo">742</span>      }<a name="line.742"></a>
+<span class="sourceLineNo">743</span><a name="line.743"></a>
+<span class="sourceLineNo">744</span>      Set&lt;Integer&gt; candidateBuckets = bucketAllocator.getLeastFilledBuckets(<a name="line.744"></a>
+<span class="sourceLineNo">745</span>          inUseBuckets, completelyFreeBucketsNeeded);<a name="line.745"></a>
+<span class="sourceLineNo">746</span>      for (Map.Entry&lt;BlockCacheKey, BucketEntry&gt; entry : backingMap.entrySet()) {<a name="line.746"></a>
+<span class="sourceLineNo">747</span>        if (candidateBuckets.contains(bucketAllocator<a name="line.747"></a>
+<span class="sourceLineNo">748</span>            .getBucketIndex(entry.getValue().offset()))) {<a name="line.748"></a>
+<span class="sourceLineNo">749</span>          evictBlock(entry.getKey(), false);<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>  }<a name="line.753"></a>
+<span class="sourceLineNo">754</span><a name="line.754"></a>
+<span class="sourceLineNo">755</span>  /**<a name="line.755"></a>
+<span class="sourceLineNo">756</span>   * Free the space if the used size reaches acceptableSize() or one size block<a name="line.756"></a>
+<span class="sourceLineNo">757</span>   * couldn't be allocated. When freeing the space, we use the LRU algorithm and<a name="line.757"></a>
+<span class="sourceLineNo">758</span>   * ensure there must be some blocks evicted<a name="line.758"></a>
+<span class="sourceLineNo">759</span>   * @param why Why we are being called<a name="line.759"></a>
+<span class="sourceLineNo">760</span>   */<a name="line.760"></a>
+<span class="sourceLineNo">761</span>  private void freeSpace(final String why) {<a name="line.761"></a>
+<span class="sourceLineNo">762</span>    // Ensure only one freeSpace progress at a time<a name="line.762"></a>
+<span class="sourceLineNo">763</span>    if (!freeSpaceLock.tryLock()) {<a name="line.763"></a>
+<span class="sourceLineNo">764</span>      return;<a name="line.764"></a>
+<span class="sourceLineNo">765</span>    }<a name="line.765"></a>
+<span class="sourceLineNo">766</span>    try {<a name="line.766"></a>
+<span class="sourceLineNo">767</span>      freeInProgress = true;<a name="line.767"></a>
+<span class="sourceLineNo">768</span>      long bytesToFreeWithoutExtra = 0;<a name="line.768"></a>
+<span class="sourceLineNo">769</span>      // Calculate free byte for each bucketSizeinfo<a name="line.769"></a>
+<span class="sourceLineNo">770</span>      StringBuilder msgBuffer = LOG.isDebugEnabled()? new StringBuilder(): null;<a name="line.770"></a>
+<span class="sourceLineNo">771</span>      BucketAllocator.IndexStatistics[] stats = bucketAllocator.getIndexStatistics();<a name="line.771"></a>
+<span class="sourceLineNo">772</span>      long[] bytesToFreeForBucket = new long[stats.length];<a name="line.772"></a>
+<span class="sourceLineNo">773</span>      for (int i = 0; i &lt; stats.length; i++) {<a name="line.773"></a>
+<span class="sourceLineNo">774</span>        bytesToFreeForBucket[i] = 0;<a name="line.774"></a>
+<span class="sourceLineNo">775</span>        long freeGoal = (long) Math.floor(stats[i].totalCount() * (1 - minFactor));<a name="line.775"></a>
+<span class="sourceLineNo">776</span>        freeGoal = Math.max(freeGoal, 1);<a name="line.776"></a>
+<span class="sourceLineNo">777</span>        if (stats[i].freeCount() &lt; freeGoal) {<a name="line.777"></a>
+<span class="sourceLineNo">778</span>          bytesToFreeForBucket[i] = stats[i].itemSize() * (freeGoal - stats[i].freeCount());<a name="line.778"></a>
+<span class="sourceLineNo">779</span>          bytesToFreeWithoutExtra += bytesToFreeForBucket[i];<a name="line.779"></a>
+<span class="sourceLineNo">780</span>          if (msgBuffer != null) {<a name="line.780"></a>
+<span class="sourceLineNo">781</span>            msgBuffer.append("Free for bucketSize(" + stats[i].itemSize() + ")="<a name="line.781"></a>
+<span class="sourceLineNo">782</span>              + StringUtils.byteDesc(bytesToFreeForBucket[i]) + ", ");<a name="line.782"></a>
+<span class="sourceLineNo">783</span>          }<a name="line.783"></a>
+<span class="sourceLineNo">784</span>        }<a name="line.784"></a>
 <span class="sourceLineNo">785</span>      }<a name="line.785"></a>
-<span class="sourceLineNo">786</span>      long currentSize = bucketAllocator.getUsedSize();<a name="line.786"></a>
-<span class="sourceLineNo">787</span>      long totalSize = bucketAllocator.getTotalSize();<a name="line.787"></a>
-<span class="sourceLineNo">788</span>      if (LOG.isDebugEnabled() &amp;&amp; msgBuffer != null) {<a name="line.788"></a>
-<span class="sourceLineNo">789</span>        LOG.debug("Free started because \"" + why + "\"; " + msgBuffer.toString() +<a name="line.789"></a>
-<span class="sourceLineNo">790</span>          " of current used=" + StringUtils.byteDesc(currentSize) + ", actual cacheSize=" +<a name="line.790"></a>
-<span class="sourceLineNo">791</span>          StringUtils.byteDesc(realCacheSize.sum()) + ", total=" + StringUtils.byteDesc(totalSize));<a name="line.791"></a>
+<span class="sourceLineNo">786</span>      if (msgBuffer != null) {<a name="line.786"></a>
+<span class="sourceLineNo">787</span>        msgBuffer.append("Free for total=" + StringUtils.byteDesc(bytesToFreeWithoutExtra) + ", ");<a name="line.787"></a>
+<span class="sourceLineNo">788</span>      }<a name="line.788"></a>
+<span class="sourceLineNo">789</span><a name="line.789"></a>
+<span class="sourceLineNo">790</span>      if (bytesToFreeWithoutExtra &lt;= 0) {<a name="line.790"></a>
+<span class="sourceLineNo">791</span>        return;<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>
-<span class="sourceLineNo">794</span>      long bytesToFreeWithExtra = (long) Math.floor(bytesToFreeWithoutExtra<a name="line.794"></a>
-<span class="sourceLineNo">795</span>          * (1 + extraFreeFactor));<a name="line.795"></a>
-<span class="sourceLineNo">796</span><a name="line.796"></a>
-<span class="sourceLineNo">797</span>      // Instantiate priority buckets<a name="line.797"></a>
-<span class="sourceLineNo">798</span>      BucketEntryGroup bucketSingle = new BucketEntryGroup(bytesToFreeWithExtra,<a name="line.798"></a>
-<span class="sourceLineNo">799</span>          blockSize, getPartitionSize(singleFactor));<a name="line.799"></a>
-<span class="sourceLineNo">800</span>      BucketEntryGroup bucketMulti = new BucketEntryGroup(bytesToFreeWithExtra,<a name="line.800"></a>
-<span class="sourceLineNo">801</span>          blockSize, getPartitionSize(multiFactor));<a name="line.801"></a>
-<span class="sourceLineNo">802</span>      BucketEntryGroup bucketMemory = new BucketEntryGroup(bytesToFreeWithExtra,<a name="line.802"></a>
-<span class="sourceLineNo">803</span>          blockSize, getPartitionSize(memoryFactor));<a name="line.803"></a>
-<span class="sourceLineNo">804</span><a name="line.804"></a>
-<span class="sourceLineNo">805</span>      // Scan entire map putting bucket entry into appropriate bucket entry<a name="line.805"></a>
-<span class="sourceLineNo">806</span>      // group<a name="line.806"></a>
-<span class="sourceLineNo">807</span>      for (Map.Entry&lt;BlockCacheKey, BucketEntry&gt; bucketEntryWithKey : backingMap.entrySet()) {<a name="line.807"></a>
-<span class="sourceLineNo">808</span>        switch (bucketEntryWithKey.getValue().getPriority()) {<a name="line.808"></a>
-<span class="sourceLineNo">809</span>          case SINGLE: {<a name="line.809"></a>
-<span class="sourceLineNo">810</span>            bucketSingle.add(bucketEntryWithKey);<a name="line.810"></a>
-<span class="sourceLineNo">811</span>            break;<a name="line.811"></a>
-<span class="sourceLineNo">812</span>          }<a name="line.812"></a>
-<span class="sourceLineNo">813</span>          case MULTI: {<a name="line.813"></a>
-<span class="sourceLineNo">814</span>            bucketMulti.add(bucketEntryWithKey);<a name="line.814"></a>
-<span class="sourceLineNo">815</span>            break;<a name="line.815"></a>
-<span class="sourceLineNo">816</span>          }<a name="line.816"></a>
-<span class="sourceLineNo">817</span>          case MEMORY: {<a name="line.817"></a>
-<span class="sourceLineNo">818</span>            bucketMemory.add(bucketEntryWithKey);<a name="line.818"></a>
-<span class="sourceLineNo">819</span>            break;<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><a name="line.823"></a>
-<span class="sourceLineNo">824</span>      PriorityQueue&lt;BucketEntryGroup&gt; bucketQueue = new PriorityQueue&lt;&gt;(3,<a name="line.824"></a>
-<span class="sourceLineNo">825</span>          Comparator.comparingLong(BucketEntryGroup::overflow));<a name="line.825"></a>
-<span class="sourceLineNo">826</span><a name="line.826"></a>
-<span class="sourceLineNo">827</span>      bucketQueue.add(bucketSingle);<a name="line.827"></a>
-<span class="sourceLineNo">828</span>      bucketQueue.add(bucketMulti);<a name="line.828"></a>
-<span class="sourceLineNo">829</span>      bucketQueue.add(bucketMemory);<a name="line.829"></a>
+<span class="sourceLineNo">793</span>      long currentSize = bucketAllocator.getUsedSize();<a name="line.793"></a>
+<span class="sourceLineNo">794</span>      long totalSize = bucketAllocator.getTotalSize();<a name="line.794"></a>
+<span class="sourceLineNo">795</span>      if (LOG.isDebugEnabled() &amp;&amp; msgBuffer != null) {<a name="line.795"></a>
+<span class="sourceLineNo">796</span>        LOG.debug("Free started because \"" + why + "\"; " + msgBuffer.toString() +<a name="line.796"></a>
+<span class="sourceLineNo">797</span>          " of current used=" + StringUtils.byteDesc(currentSize) + ", actual cacheSize=" +<a name="line.797"></a>
+<span class="sourceLineNo">798</span>          StringUtils.byteDesc(realCacheSize.sum()) + ", total=" + StringUtils.byteDesc(totalSize));<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>      long bytesToFreeWithExtra = (long) Math.floor(bytesToFreeWithoutExtra<a name="line.801"></a>
+<span class="sourceLineNo">802</span>          * (1 + extraFreeFactor));<a name="line.802"></a>
+<span class="sourceLineNo">803</span><a name="line.803"></a>
+<span class="sourceLineNo">804</span>      // Instantiate priority buckets<a name="line.804"></a>
+<span class="sourceLineNo">805</span>      BucketEntryGroup bucketSingle = new BucketEntryGroup(bytesToFreeWithExtra,<a name="line.805"></a>
+<span class="sourceLineNo">806</span>          blockSize, getPartitionSize(singleFactor));<a name="line.806"></a>
+<span class="sourceLineNo">807</span>      BucketEntryGroup bucketMulti = new BucketEntryGroup(bytesToFreeWithExtra,<a name="line.807"></a>
+<span class="sourceLineNo">808</span>          blockSize, getPartitionSize(multiFactor));<a name="line.808"></a>
+<span class="sourceLineNo">809</span>      BucketEntryGroup bucketMemory = new BucketEntryGroup(bytesToFreeWithExtra,<a name="line.809"></a>
+<span class="sourceLineNo">810</span>          blockSize, getPartitionSize(memoryFactor));<a name="line.810"></a>
+<span class="sourceLineNo">811</span><a name="line.811"></a>
+<span class="sourceLineNo">812</span>      // Scan entire map putting bucket entry into appropriate bucket entry<a name="line.812"></a>
+<span class="sourceLineNo">813</span>      // group<a name="line.813"></a>
+<span class="sourceLineNo">814</span>      for (Map.Entry&lt;BlockCacheKey, BucketEntry&gt; bucketEntryWithKey : backingMap.entrySet()) {<a name="line.814"></a>
+<span class="sourceLineNo">815</span>        switch (bucketEntryWithKey.getValue().getPriority()) {<a name="line.815"></a>
+<span class="sourceLineNo">816</span>          case SINGLE: {<a name="line.816"></a>
+<span class="sourceLineNo">817</span>            bucketSingle.add(bucketEntryWithKey);<a name="line.817"></a>
+<span class="sourceLineNo">818</span>            break;<a name="line.818"></a>
+<span class="sourceLineNo">819</span>          }<a name="line.819"></a>
+<span class="sourceLineNo">820</span>          case MULTI: {<a name="line.820"></a>
+<span class="sourceLineNo">821</span>            bucketMulti.add(bucketEntryWithKey);<a name="line.821"></a>
+<span class="sourceLineNo">822</span>            break;<a name="line.822"></a>
+<span class="sourceLineNo">823</span>          }<a name="line.823"></a>
+<span class="sourceLineNo">824</span>          case MEMORY: {<a name="line.824"></a>
+<span class="sourceLineNo">825</span>            bucketMemory.add(bucketEntryWithKey);<a name="line.825"></a>
+<span class="sourceLineNo">826</span>            break;<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">830</span><a name="line.830"></a>
-<span class="sourceLineNo">831</span>      int remainingBuckets = 3;<a name="line.831"></a>
-<span class="sourceLineNo">832</span>      long bytesFreed = 0;<a name="line.832"></a>
+<span class="sourceLineNo">831</span>      PriorityQueue&lt;BucketEntryGroup&gt; bucketQueue = new PriorityQueue&lt;&gt;(3,<a name="line.831"></a>
+<span class="sourceLineNo">832</span>          Comparator.comparingLong(BucketEntryGroup::overflow));<a name="line.832"></a>
 <span class="sourceLineNo">833</span><a name="line.833"></a>
-<span class="sourceLineNo">834</span>      BucketEntryGroup bucketGroup;<a name="line.834"></a>
-<span class="sourceLineNo">835</span>      while ((bucketGroup = bucketQueue.poll()) != null) {<a name="line.835"></a>
-<span class="sourceLineNo">836</span>        long overflow = bucketGroup.overflow();<a name="line.836"></a>
-<span class="sourceLineNo">837</span>        if (overflow &gt; 0) {<a name="line.837"></a>
-<span class="sourceLineNo">838</span>          long bucketBytesToFree = Math.min(overflow,<a name="line.838"></a>
-<span class="sourceLineNo">839</span>              (bytesToFreeWithoutExtra - bytesFreed) / remainingBuckets);<a name="line.839"></a>
-<span class="sourceLineNo">840</span>          bytesFreed += bucketGroup.free(bucketBytesToFree);<a name="line.840"></a>
-<span class="sourceLineNo">841</span>        }<a name="line.841"></a>
-<span class="sourceLineNo">842</span>        remainingBuckets--;<a name="line.842"></a>
-<span class="sourceLineNo">843</span>      }<a name="line.843"></a>
-<span class="sourceLineNo">844</span><a name="line.844"></a>
-<span class="sourceLineNo">845</span>      // Check and free if there are buckets that still need freeing of space<a name="line.845"></a>
-<span class="sourceLineNo">846</span>      if (bucketSizesAboveThresholdCount(minFactor) &gt; 0) {<a name="line.846"></a>
-<span class="sourceLineNo">847</span>        bucketQueue.clear();<a name="line.847"></a>
-<span class="sourceLineNo">848</span>        remainingBuckets = 3;<a name="line.848"></a>
-<span class="sourceLineNo">849</span><a name="line.849"></a>
-<span class="sourceLineNo">850</span>        bucketQueue.add(bucketSingle);<a name="line.850"></a>
-<span class="sourceLineNo">851</span>        bucketQueue.add(bucketMulti);<a name="line.851"></a>
-<span class="sourceLineNo">852</span>        bucketQueue.add(bucketMemory);<a name="line.852"></a>
-<span class="sourceLineNo">853</span><a name="line.853"></a>
-<span class="sourceLineNo">854</span>        while ((bucketGroup = bucketQueue.poll()) != null) {<a name="line.854"></a>
-<span class="sourceLineNo">855</span>          long bucketBytesToFree = (bytesToFreeWithExtra - bytesFreed) / remainingBuckets;<a name="line.855"></a>
-<span class="sourceLineNo">856</span>          bytesFreed += bucketGroup.free(bucketBytesToFree);<a name="line.856"></a>
-<span class="sourceLineNo">857</span>          remainingBuckets--;<a name="line.857"></a>
-<span class="sourceLineNo">858</span>        }<a name="line.858"></a>
-<span class="sourceLineNo">859</span>      }<a name="line.859"></a>
+<span class="sourceLineNo">834</span>      bucketQueue.add(bucketSingle);<a name="line.834"></a>
+<span class="sourceLineNo">835</span>      bucketQueue.add(bucketMulti);<a name="line.835"></a>
+<span class="sourceLineNo">836</span>      bucketQueue.add(bucketMemory);<a name="line.836"></a>
+<span class="sourceLineNo">837</span><a name="line.837"></a>
+<span class="sourceLineNo">838</span>      int remainingBuckets = 3;<a name="line.838"></a>
+<span class="sourceLineNo">839</span>      long bytesFreed = 0;<a name="line.839"></a>
+<span class="sourceLineNo">840</span><a name="line.840"></a>
+<span class="sourceLineNo">841</span>      BucketEntryGroup bucketGroup;<a name="line.841"></a>
+<span class="sourceLineNo">842</span>      while ((bucketGroup = bucketQueue.poll()) != null) {<a name="line.842"></a>
+<span class="sourceLineNo">843</span>        long overflow = bucketGroup.overflow();<a name="line.843"></a>
+<span class="sourceLineNo">844</span>        if (overflow &gt; 0) {<a name="line.844"></a>
+<span class="sourceLineNo">845</span>          long bucketBytesToFree = Math.min(overflow,<a name="line.845"></a>
+<span class="sourceLineNo">846</span>              (bytesToFreeWithoutExtra - bytesFreed) / remainingBuckets);<a name="line.846"></a>
+<span class="sourceLineNo">847</span>          bytesFreed += bucketGroup.free(bucketBytesToFree);<a name="line.847"></a>
+<span class="sourceLineNo">848</span>        }<a name="line.848"></a>
+<span class="sourceLineNo">849</span>        remainingBuckets--;<a name="line.849"></a>
+<span class="sourceLineNo">850</span>      }<a name="line.850"></a>
+<span class="sourceLineNo">851</span><a name="line.851"></a>
+<span class="sourceLineNo">852</span>      // Check and free if there are buckets that still need freeing of space<a name="line.852"></a>
+<span class="sourceLineNo">853</span>      if (bucketSizesAboveThresholdCount(minFactor) &gt; 0) {<a name="line.853"></a>
+<span class="sourceLineNo">854</span>        bucketQueue.clear();<a name="line.854"></a>
+<span class="sourceLineNo">855</span>        remainingBuckets = 3;<a name="line.855"></a>
+<span class="sourceLineNo">856</span><a name="line.856"></a>
+<span class="sourceLineNo">857</span>        bucketQueue.add(bucketSingle);<a name="line.857"></a>
+<span class="sourceLineNo">858</span>        bucketQueue.add(bucketMulti);<a name="line.858"></a>
+<span class="sourceLineNo">859</span>        bucketQueue.add(bucketMemory);<a name="line.859"></a>
 <span class="sourceLineNo">860</span><a name="line.860"></a>
-<span class="sourceLineNo">861</span>      // Even after the above free we might still need freeing because of the<a name="line.861"></a>
-<span class="sourceLineNo">862</span>      // De-fragmentation of the buckets (also called Slab Calcification problem), i.e<a name="line.862"></a>
-<span class="sourceLineNo">863</span>      // there might be some buckets where the occupancy is very sparse and thus are not<a name="line.863"></a>
-<span class="sourceLineNo">864</span>      // yielding the free for the other bucket sizes, the fix for this to evict some<a name="line.864"></a>
-<span class="sourceLineNo">865</span>      // of the buckets, we do this by evicting the buckets that are least fulled<a name="line.865"></a>
-<span class="sourceLineNo">866</span>      freeEntireBuckets(DEFAULT_FREE_ENTIRE_BLOCK_FACTOR *<a name="line.866"></a>
-<span class="sourceLineNo">867</span>          bucketSizesAboveThresholdCount(1.0f));<a name="line.867"></a>
-<span class="sourceLineNo">868</span><a name="line.868"></a>
-<span class="sourceLineNo">869</span>      if (LOG.isDebugEnabled()) {<a name="line.869"></a>
-<span class="sourceLineNo">870</span>        long single = bucketSingle.totalSize();<a name="line.870"></a>
-<span class="sourceLineNo">871</span>        long multi = bucketMulti.totalSize();<a name="line.871"></a>
-<span class="sourceLineNo">872</span>        long memory = bucketMemory.totalSize();<a name="line.872"></a>
-<span class="sourceLineNo">873</span>        if (LOG.isDebugEnabled()) {<a name="line.873"></a>
-<span class="sourceLineNo">874</span>          LOG.debug("Bucket cache free space completed; " + "freed="<a name="line.874"></a>
-<span class="sourceLineNo">875</span>            + StringUtils.byteDesc(bytesFreed) + ", " + "total="<a name="line.875"></a>
-<span class="sourceLineNo">876</span>            + StringUtils.byteDesc(totalSize) + ", " + "single="<a name="line.876"></a>
-<span class="sourceLineNo">877</span>            + StringUtils.byteDesc(single) + ", " + "multi="<a name="line.877"></a>
-<span class="sourceLineNo">878</span>            + StringUtils.byteDesc(multi) + ", " + "memory="<a name="line.878"></a>
-<span class="sourceLineNo">879</span>            + StringUtils.byteDesc(memory));<a name="line.879"></a>
-<span class="sourceLineNo">880</span>        }<a name="line.880"></a>
-<span class="sourceLineNo">881</span>      }<a name="line.881"></a>
-<span class="sourceLineNo">882</span><a name="line.882"></a>
-<span class="sourceLineNo">883</span>    } catch (Throwable t) {<a name="line.883"></a>
-<span class="sourceLineNo">884</span>      LOG.warn("Failed freeing space", t);<a name="line.884"></a>
-<span class="sourceLineNo">885</span>    } finally {<a name="line.885"></a>
-<span class="sourceLineNo">886</span>      cacheStats.evict();<a name="line.886"></a>
-<span class="sourceLineNo">887</span>      freeInProgress = false;<a name="line.887"></a>
-<span class="sourceLineNo">888</span>      freeSpaceLock.unlock();<a name="line.888"></a>
-<span class="sourceLineNo">889</span>    }<a name="line.889"></a>
-<span class="sourceLineNo">890</span>  }<a name="line.890"></a>
-<span class="sourceLineNo">891</span><a name="line.891"></a>
-<span class="sourceLineNo">892</span>  // This handles flushing the RAM cache to IOEngine.<a name="line.892"></a>
-<span class="sourceLineNo">893</span>  @VisibleForTesting<a name="line.893"></a>
-<span class="sourceLineNo">894</span>  class WriterThread extends HasThread {<a name="line.894"></a>
-<span class="sourceLineNo">895</span>    private final BlockingQueue&lt;RAMQueueEntry&gt; inputQueue;<a name="line.895"></a>
-<span class="sourceLineNo">896</span>    private volatile boolean writerEnabled = true;<a name="line.896"></a>
-<span class="sourceLineNo">897</span><a name="line.897"></a>
-<span class="sourceLineNo">898</span>    WriterThread(BlockingQueue&lt;RAMQueueEntry&gt; queue) {<a name="line.898"></a>
-<span class="sourceLineNo">899</span>      super("BucketCacheWriterThread");<a name="line

<TRUNCATED>

[19/50] hbase-site git commit: Published site at 26babcf013de696b899d76a3c39434b794440d8d.

Posted by gi...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html
----------------------------------------------------------------------
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html
index e8070ca..8cb24b3 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html
@@ -433,1254 +433,1261 @@
 <span class="sourceLineNo">425</span>      return;<a name="line.425"></a>
 <span class="sourceLineNo">426</span>    }<a name="line.426"></a>
 <span class="sourceLineNo">427</span><a name="line.427"></a>
-<span class="sourceLineNo">428</span>    if (backingMap.containsKey(cacheKey)) {<a name="line.428"></a>
+<span class="sourceLineNo">428</span>    if (backingMap.containsKey(cacheKey) || ramCache.containsKey(cacheKey)) {<a name="line.428"></a>
 <span class="sourceLineNo">429</span>      Cacheable existingBlock = getBlock(cacheKey, false, false, false);<a name="line.429"></a>
-<span class="sourceLineNo">430</span>      try {<a name="line.430"></a>
-<span class="sourceLineNo">431</span>        if (BlockCacheUtil.compareCacheBlock(cachedItem, existingBlock) != 0) {<a name="line.431"></a>
-<span class="sourceLineNo">432</span>          throw new RuntimeException("Cached block contents differ, which should not have happened."<a name="line.432"></a>
-<span class="sourceLineNo">433</span>              + "cacheKey:" + cacheKey);<a name="line.433"></a>
-<span class="sourceLineNo">434</span>        }<a name="line.434"></a>
-<span class="sourceLineNo">435</span>        String msg = "Caching an already cached block: " + cacheKey;<a name="line.435"></a>
-<span class="sourceLineNo">436</span>        msg += ". This is harmless and can happen in rare cases (see HBASE-8547)";<a name="line.436"></a>
-<span class="sourceLineNo">437</span>        LOG.warn(msg);<a name="line.437"></a>
-<span class="sourceLineNo">438</span>      } finally {<a name="line.438"></a>
-<span class="sourceLineNo">439</span>        // return the block since we need to decrement the count<a name="line.439"></a>
-<span class="sourceLineNo">440</span>        returnBlock(cacheKey, existingBlock);<a name="line.440"></a>
-<span class="sourceLineNo">441</span>      }<a name="line.441"></a>
-<span class="sourceLineNo">442</span>      return;<a name="line.442"></a>
-<span class="sourceLineNo">443</span>    }<a name="line.443"></a>
-<span class="sourceLineNo">444</span><a name="line.444"></a>
-<span class="sourceLineNo">445</span>    /*<a name="line.445"></a>
-<span class="sourceLineNo">446</span>     * Stuff the entry into the RAM cache so it can get drained to the persistent store<a name="line.446"></a>
-<span class="sourceLineNo">447</span>     */<a name="line.447"></a>
-<span class="sourceLineNo">448</span>    RAMQueueEntry re =<a name="line.448"></a>
-<span class="sourceLineNo">449</span>        new RAMQueueEntry(cacheKey, cachedItem, accessCount.incrementAndGet(), inMemory);<a name="line.449"></a>
-<span class="sourceLineNo">450</span>    if (ramCache.putIfAbsent(cacheKey, re) != null) {<a name="line.450"></a>
-<span class="sourceLineNo">451</span>      return;<a name="line.451"></a>
-<span class="sourceLineNo">452</span>    }<a name="line.452"></a>
-<span class="sourceLineNo">453</span>    int queueNum = (cacheKey.hashCode() &amp; 0x7FFFFFFF) % writerQueues.size();<a name="line.453"></a>
-<span class="sourceLineNo">454</span>    BlockingQueue&lt;RAMQueueEntry&gt; bq = writerQueues.get(queueNum);<a name="line.454"></a>
-<span class="sourceLineNo">455</span>    boolean successfulAddition = false;<a name="line.455"></a>
-<span class="sourceLineNo">456</span>    if (wait) {<a name="line.456"></a>
-<span class="sourceLineNo">457</span>      try {<a name="line.457"></a>
-<span class="sourceLineNo">458</span>        successfulAddition = bq.offer(re, DEFAULT_CACHE_WAIT_TIME, TimeUnit.MILLISECONDS);<a name="line.458"></a>
-<span class="sourceLineNo">459</span>      } catch (InterruptedException e) {<a name="line.459"></a>
-<span class="sourceLineNo">460</span>        Thread.currentThread().interrupt();<a name="line.460"></a>
-<span class="sourceLineNo">461</span>      }<a name="line.461"></a>
-<span class="sourceLineNo">462</span>    } else {<a name="line.462"></a>
-<span class="sourceLineNo">463</span>      successfulAddition = bq.offer(re);<a name="line.463"></a>
-<span class="sourceLineNo">464</span>    }<a name="line.464"></a>
-<span class="sourceLineNo">465</span>    if (!successfulAddition) {<a name="line.465"></a>
-<span class="sourceLineNo">466</span>      ramCache.remove(cacheKey);<a name="line.466"></a>
-<span class="sourceLineNo">467</span>      cacheStats.failInsert();<a name="line.467"></a>
-<span class="sourceLineNo">468</span>    } else {<a name="line.468"></a>
-<span class="sourceLineNo">469</span>      this.blockNumber.increment();<a name="line.469"></a>
-<span class="sourceLineNo">470</span>      this.heapSize.add(cachedItem.heapSize());<a name="line.470"></a>
-<span class="sourceLineNo">471</span>      blocksByHFile.add(cacheKey);<a name="line.471"></a>
-<span class="sourceLineNo">472</span>    }<a name="line.472"></a>
-<span class="sourceLineNo">473</span>  }<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>   * Get the buffer of the block with the specified key.<a name="line.476"></a>
-<span class="sourceLineNo">477</span>   * @param key block's cache key<a name="line.477"></a>
-<span class="sourceLineNo">478</span>   * @param caching true if the caller caches blocks on cache misses<a name="line.478"></a>
-<span class="sourceLineNo">479</span>   * @param repeat Whether this is a repeat lookup for the same block<a name="line.479"></a>
-<span class="sourceLineNo">480</span>   * @param updateCacheMetrics Whether we should update cache metrics or not<a name="line.480"></a>
-<span class="sourceLineNo">481</span>   * @return buffer of specified cache key, or null if not in cache<a name="line.481"></a>
-<span class="sourceLineNo">482</span>   */<a name="line.482"></a>
-<span class="sourceLineNo">483</span>  @Override<a name="line.483"></a>
-<span class="sourceLineNo">484</span>  public Cacheable getBlock(BlockCacheKey key, boolean caching, boolean repeat,<a name="line.484"></a>
-<span class="sourceLineNo">485</span>      boolean updateCacheMetrics) {<a name="line.485"></a>
-<span class="sourceLineNo">486</span>    if (!cacheEnabled) {<a name="line.486"></a>
-<span class="sourceLineNo">487</span>      return null;<a name="line.487"></a>
-<span class="sourceLineNo">488</span>    }<a name="line.488"></a>
-<span class="sourceLineNo">489</span>    RAMQueueEntry re = ramCache.get(key);<a name="line.489"></a>
-<span class="sourceLineNo">490</span>    if (re != null) {<a name="line.490"></a>
-<span class="sourceLineNo">491</span>      if (updateCacheMetrics) {<a name="line.491"></a>
-<span class="sourceLineNo">492</span>        cacheStats.hit(caching, key.isPrimary(), key.getBlockType());<a name="line.492"></a>
-<span class="sourceLineNo">493</span>      }<a name="line.493"></a>
-<span class="sourceLineNo">494</span>      re.access(accessCount.incrementAndGet());<a name="line.494"></a>
-<span class="sourceLineNo">495</span>      return re.getData();<a name="line.495"></a>
-<span class="sourceLineNo">496</span>    }<a name="line.496"></a>
-<span class="sourceLineNo">497</span>    BucketEntry bucketEntry = backingMap.get(key);<a name="line.497"></a>
-<span class="sourceLineNo">498</span>    if (bucketEntry != null) {<a name="line.498"></a>
-<span class="sourceLineNo">499</span>      long start = System.nanoTime();<a name="line.499"></a>
-<span class="sourceLineNo">500</span>      ReentrantReadWriteLock lock = offsetLock.getLock(bucketEntry.offset());<a name="line.500"></a>
-<span class="sourceLineNo">501</span>      try {<a name="line.501"></a>
-<span class="sourceLineNo">502</span>        lock.readLock().lock();<a name="line.502"></a>
-<span class="sourceLineNo">503</span>        // We can not read here even if backingMap does contain the given key because its offset<a name="line.503"></a>
-<span class="sourceLineNo">504</span>        // maybe changed. If we lock BlockCacheKey instead of offset, then we can only check<a name="line.504"></a>
-<span class="sourceLineNo">505</span>        // existence here.<a name="line.505"></a>
-<span class="sourceLineNo">506</span>        if (bucketEntry.equals(backingMap.get(key))) {<a name="line.506"></a>
-<span class="sourceLineNo">507</span>          // TODO : change this area - should be removed after server cells and<a name="line.507"></a>
-<span class="sourceLineNo">508</span>          // 12295 are available<a name="line.508"></a>
-<span class="sourceLineNo">509</span>          int len = bucketEntry.getLength();<a name="line.509"></a>
-<span class="sourceLineNo">510</span>          if (LOG.isTraceEnabled()) {<a name="line.510"></a>
-<span class="sourceLineNo">511</span>            LOG.trace("Read offset=" + bucketEntry.offset() + ", len=" + len);<a name="line.511"></a>
-<span class="sourceLineNo">512</span>          }<a name="line.512"></a>
-<span class="sourceLineNo">513</span>          Cacheable cachedBlock = ioEngine.read(bucketEntry.offset(), len,<a name="line.513"></a>
-<span class="sourceLineNo">514</span>              bucketEntry.deserializerReference(this.deserialiserMap));<a name="line.514"></a>
-<span class="sourceLineNo">515</span>          long timeTaken = System.nanoTime() - start;<a name="line.515"></a>
-<span class="sourceLineNo">516</span>          if (updateCacheMetrics) {<a name="line.516"></a>
-<span class="sourceLineNo">517</span>            cacheStats.hit(caching, key.isPrimary(), key.getBlockType());<a name="line.517"></a>
-<span class="sourceLineNo">518</span>            cacheStats.ioHit(timeTaken);<a name="line.518"></a>
+<span class="sourceLineNo">430</span><a name="line.430"></a>
+<span class="sourceLineNo">431</span>      try {<a name="line.431"></a>
+<span class="sourceLineNo">432</span>        int comparison = BlockCacheUtil.validateBlockAddition(existingBlock, cachedItem, cacheKey);<a name="line.432"></a>
+<span class="sourceLineNo">433</span>        if (comparison != 0) {<a name="line.433"></a>
+<span class="sourceLineNo">434</span>          if (comparison &lt; 0) {<a name="line.434"></a>
+<span class="sourceLineNo">435</span>            LOG.warn("Cached block contents differ by nextBlockOnDiskSize. Keeping cached block.");<a name="line.435"></a>
+<span class="sourceLineNo">436</span>            return;<a name="line.436"></a>
+<span class="sourceLineNo">437</span>          } else {<a name="line.437"></a>
+<span class="sourceLineNo">438</span>            LOG.warn("Cached block contents differ by nextBlockOnDiskSize. Caching new block.");<a name="line.438"></a>
+<span class="sourceLineNo">439</span>          }<a name="line.439"></a>
+<span class="sourceLineNo">440</span>        } else {<a name="line.440"></a>
+<span class="sourceLineNo">441</span>          String msg = "Caching an already cached block: " + cacheKey;<a name="line.441"></a>
+<span class="sourceLineNo">442</span>          msg += ". This is harmless and can happen in rare cases (see HBASE-8547)";<a name="line.442"></a>
+<span class="sourceLineNo">443</span>          LOG.warn(msg);<a name="line.443"></a>
+<span class="sourceLineNo">444</span>          return;<a name="line.444"></a>
+<span class="sourceLineNo">445</span>        }<a name="line.445"></a>
+<span class="sourceLineNo">446</span>      } finally {<a name="line.446"></a>
+<span class="sourceLineNo">447</span>        // return the block since we need to decrement the count<a name="line.447"></a>
+<span class="sourceLineNo">448</span>        returnBlock(cacheKey, existingBlock);<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><a name="line.451"></a>
+<span class="sourceLineNo">452</span>    /*<a name="line.452"></a>
+<span class="sourceLineNo">453</span>     * Stuff the entry into the RAM cache so it can get drained to the persistent store<a name="line.453"></a>
+<span class="sourceLineNo">454</span>     */<a name="line.454"></a>
+<span class="sourceLineNo">455</span>    RAMQueueEntry re =<a name="line.455"></a>
+<span class="sourceLineNo">456</span>        new RAMQueueEntry(cacheKey, cachedItem, accessCount.incrementAndGet(), inMemory);<a name="line.456"></a>
+<span class="sourceLineNo">457</span>    if (ramCache.putIfAbsent(cacheKey, re) != null) {<a name="line.457"></a>
+<span class="sourceLineNo">458</span>      return;<a name="line.458"></a>
+<span class="sourceLineNo">459</span>    }<a name="line.459"></a>
+<span class="sourceLineNo">460</span>    int queueNum = (cacheKey.hashCode() &amp; 0x7FFFFFFF) % writerQueues.size();<a name="line.460"></a>
+<span class="sourceLineNo">461</span>    BlockingQueue&lt;RAMQueueEntry&gt; bq = writerQueues.get(queueNum);<a name="line.461"></a>
+<span class="sourceLineNo">462</span>    boolean successfulAddition = false;<a name="line.462"></a>
+<span class="sourceLineNo">463</span>    if (wait) {<a name="line.463"></a>
+<span class="sourceLineNo">464</span>      try {<a name="line.464"></a>
+<span class="sourceLineNo">465</span>        successfulAddition = bq.offer(re, DEFAULT_CACHE_WAIT_TIME, TimeUnit.MILLISECONDS);<a name="line.465"></a>
+<span class="sourceLineNo">466</span>      } catch (InterruptedException e) {<a name="line.466"></a>
+<span class="sourceLineNo">467</span>        Thread.currentThread().interrupt();<a name="line.467"></a>
+<span class="sourceLineNo">468</span>      }<a name="line.468"></a>
+<span class="sourceLineNo">469</span>    } else {<a name="line.469"></a>
+<span class="sourceLineNo">470</span>      successfulAddition = bq.offer(re);<a name="line.470"></a>
+<span class="sourceLineNo">471</span>    }<a name="line.471"></a>
+<span class="sourceLineNo">472</span>    if (!successfulAddition) {<a name="line.472"></a>
+<span class="sourceLineNo">473</span>      ramCache.remove(cacheKey);<a name="line.473"></a>
+<span class="sourceLineNo">474</span>      cacheStats.failInsert();<a name="line.474"></a>
+<span class="sourceLineNo">475</span>    } else {<a name="line.475"></a>
+<span class="sourceLineNo">476</span>      this.blockNumber.increment();<a name="line.476"></a>
+<span class="sourceLineNo">477</span>      this.heapSize.add(cachedItem.heapSize());<a name="line.477"></a>
+<span class="sourceLineNo">478</span>      blocksByHFile.add(cacheKey);<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>  /**<a name="line.482"></a>
+<span class="sourceLineNo">483</span>   * Get the buffer of the block with the specified key.<a name="line.483"></a>
+<span class="sourceLineNo">484</span>   * @param key block's cache key<a name="line.484"></a>
+<span class="sourceLineNo">485</span>   * @param caching true if the caller caches blocks on cache misses<a name="line.485"></a>
+<span class="sourceLineNo">486</span>   * @param repeat Whether this is a repeat lookup for the same block<a name="line.486"></a>
+<span class="sourceLineNo">487</span>   * @param updateCacheMetrics Whether we should update cache metrics or not<a name="line.487"></a>
+<span class="sourceLineNo">488</span>   * @return buffer of specified cache key, or null if not in cache<a name="line.488"></a>
+<span class="sourceLineNo">489</span>   */<a name="line.489"></a>
+<span class="sourceLineNo">490</span>  @Override<a name="line.490"></a>
+<span class="sourceLineNo">491</span>  public Cacheable getBlock(BlockCacheKey key, boolean caching, boolean repeat,<a name="line.491"></a>
+<span class="sourceLineNo">492</span>      boolean updateCacheMetrics) {<a name="line.492"></a>
+<span class="sourceLineNo">493</span>    if (!cacheEnabled) {<a name="line.493"></a>
+<span class="sourceLineNo">494</span>      return null;<a name="line.494"></a>
+<span class="sourceLineNo">495</span>    }<a name="line.495"></a>
+<span class="sourceLineNo">496</span>    RAMQueueEntry re = ramCache.get(key);<a name="line.496"></a>
+<span class="sourceLineNo">497</span>    if (re != null) {<a name="line.497"></a>
+<span class="sourceLineNo">498</span>      if (updateCacheMetrics) {<a name="line.498"></a>
+<span class="sourceLineNo">499</span>        cacheStats.hit(caching, key.isPrimary(), key.getBlockType());<a name="line.499"></a>
+<span class="sourceLineNo">500</span>      }<a name="line.500"></a>
+<span class="sourceLineNo">501</span>      re.access(accessCount.incrementAndGet());<a name="line.501"></a>
+<span class="sourceLineNo">502</span>      return re.getData();<a name="line.502"></a>
+<span class="sourceLineNo">503</span>    }<a name="line.503"></a>
+<span class="sourceLineNo">504</span>    BucketEntry bucketEntry = backingMap.get(key);<a name="line.504"></a>
+<span class="sourceLineNo">505</span>    if (bucketEntry != null) {<a name="line.505"></a>
+<span class="sourceLineNo">506</span>      long start = System.nanoTime();<a name="line.506"></a>
+<span class="sourceLineNo">507</span>      ReentrantReadWriteLock lock = offsetLock.getLock(bucketEntry.offset());<a name="line.507"></a>
+<span class="sourceLineNo">508</span>      try {<a name="line.508"></a>
+<span class="sourceLineNo">509</span>        lock.readLock().lock();<a name="line.509"></a>
+<span class="sourceLineNo">510</span>        // We can not read here even if backingMap does contain the given key because its offset<a name="line.510"></a>
+<span class="sourceLineNo">511</span>        // maybe changed. If we lock BlockCacheKey instead of offset, then we can only check<a name="line.511"></a>
+<span class="sourceLineNo">512</span>        // existence here.<a name="line.512"></a>
+<span class="sourceLineNo">513</span>        if (bucketEntry.equals(backingMap.get(key))) {<a name="line.513"></a>
+<span class="sourceLineNo">514</span>          // TODO : change this area - should be removed after server cells and<a name="line.514"></a>
+<span class="sourceLineNo">515</span>          // 12295 are available<a name="line.515"></a>
+<span class="sourceLineNo">516</span>          int len = bucketEntry.getLength();<a name="line.516"></a>
+<span class="sourceLineNo">517</span>          if (LOG.isTraceEnabled()) {<a name="line.517"></a>
+<span class="sourceLineNo">518</span>            LOG.trace("Read offset=" + bucketEntry.offset() + ", len=" + len);<a name="line.518"></a>
 <span class="sourceLineNo">519</span>          }<a name="line.519"></a>
-<span class="sourceLineNo">520</span>          if (cachedBlock.getMemoryType() == MemoryType.SHARED) {<a name="line.520"></a>
-<span class="sourceLineNo">521</span>            bucketEntry.incrementRefCountAndGet();<a name="line.521"></a>
-<span class="sourceLineNo">522</span>          }<a name="line.522"></a>
-<span class="sourceLineNo">523</span>          bucketEntry.access(accessCount.incrementAndGet());<a name="line.523"></a>
-<span class="sourceLineNo">524</span>          if (this.ioErrorStartTime &gt; 0) {<a name="line.524"></a>
-<span class="sourceLineNo">525</span>            ioErrorStartTime = -1;<a name="line.525"></a>
+<span class="sourceLineNo">520</span>          Cacheable cachedBlock = ioEngine.read(bucketEntry.offset(), len,<a name="line.520"></a>
+<span class="sourceLineNo">521</span>              bucketEntry.deserializerReference(this.deserialiserMap));<a name="line.521"></a>
+<span class="sourceLineNo">522</span>          long timeTaken = System.nanoTime() - start;<a name="line.522"></a>
+<span class="sourceLineNo">523</span>          if (updateCacheMetrics) {<a name="line.523"></a>
+<span class="sourceLineNo">524</span>            cacheStats.hit(caching, key.isPrimary(), key.getBlockType());<a name="line.524"></a>
+<span class="sourceLineNo">525</span>            cacheStats.ioHit(timeTaken);<a name="line.525"></a>
 <span class="sourceLineNo">526</span>          }<a name="line.526"></a>
-<span class="sourceLineNo">527</span>          return cachedBlock;<a name="line.527"></a>
-<span class="sourceLineNo">528</span>        }<a name="line.528"></a>
-<span class="sourceLineNo">529</span>      } catch (IOException ioex) {<a name="line.529"></a>
-<span class="sourceLineNo">530</span>        LOG.error("Failed reading block " + key + " from bucket cache", ioex);<a name="line.530"></a>
-<span class="sourceLineNo">531</span>        checkIOErrorIsTolerated();<a name="line.531"></a>
-<span class="sourceLineNo">532</span>      } finally {<a name="line.532"></a>
-<span class="sourceLineNo">533</span>        lock.readLock().unlock();<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>    if (!repeat &amp;&amp; updateCacheMetrics) {<a name="line.536"></a>
-<span class="sourceLineNo">537</span>      cacheStats.miss(caching, key.isPrimary(), key.getBlockType());<a name="line.537"></a>
-<span class="sourceLineNo">538</span>    }<a name="line.538"></a>
-<span class="sourceLineNo">539</span>    return null;<a name="line.539"></a>
-<span class="sourceLineNo">540</span>  }<a name="line.540"></a>
-<span class="sourceLineNo">541</span><a name="line.541"></a>
-<span class="sourceLineNo">542</span>  @VisibleForTesting<a name="line.542"></a>
-<span class="sourceLineNo">543</span>  void blockEvicted(BlockCacheKey cacheKey, BucketEntry bucketEntry, boolean decrementBlockNumber) {<a name="line.543"></a>
-<span class="sourceLineNo">544</span>    bucketAllocator.freeBlock(bucketEntry.offset());<a name="line.544"></a>
-<span class="sourceLineNo">545</span>    realCacheSize.add(-1 * bucketEntry.getLength());<a name="line.545"></a>
-<span class="sourceLineNo">546</span>    blocksByHFile.remove(cacheKey);<a name="line.546"></a>
-<span class="sourceLineNo">547</span>    if (decrementBlockNumber) {<a name="line.547"></a>
-<span class="sourceLineNo">548</span>      this.blockNumber.decrement();<a name="line.548"></a>
-<span class="sourceLineNo">549</span>    }<a name="line.549"></a>
-<span class="sourceLineNo">550</span>  }<a name="line.550"></a>
-<span class="sourceLineNo">551</span><a name="line.551"></a>
-<span class="sourceLineNo">552</span>  @Override<a name="line.552"></a>
-<span class="sourceLineNo">553</span>  public boolean evictBlock(BlockCacheKey cacheKey) {<a name="line.553"></a>
-<span class="sourceLineNo">554</span>    return evictBlock(cacheKey, true);<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>  // does not check for the ref count. Just tries to evict it if found in the<a name="line.557"></a>
-<span class="sourceLineNo">558</span>  // bucket map<a name="line.558"></a>
-<span class="sourceLineNo">559</span>  private boolean forceEvict(BlockCacheKey cacheKey) {<a name="line.559"></a>
-<span class="sourceLineNo">560</span>    if (!cacheEnabled) {<a name="line.560"></a>
-<span class="sourceLineNo">561</span>      return false;<a name="line.561"></a>
-<span class="sourceLineNo">562</span>    }<a name="line.562"></a>
-<span class="sourceLineNo">563</span>    RAMQueueEntry removedBlock = checkRamCache(cacheKey);<a name="line.563"></a>
-<span class="sourceLineNo">564</span>    BucketEntry bucketEntry = backingMap.get(cacheKey);<a name="line.564"></a>
-<span class="sourceLineNo">565</span>    if (bucketEntry == null) {<a name="line.565"></a>
-<span class="sourceLineNo">566</span>      if (removedBlock != null) {<a name="line.566"></a>
-<span class="sourceLineNo">567</span>        cacheStats.evicted(0, cacheKey.isPrimary());<a name="line.567"></a>
-<span class="sourceLineNo">568</span>        return true;<a name="line.568"></a>
-<span class="sourceLineNo">569</span>      } else {<a name="line.569"></a>
-<span class="sourceLineNo">570</span>        return false;<a name="line.570"></a>
-<span class="sourceLineNo">571</span>      }<a name="line.571"></a>
-<span class="sourceLineNo">572</span>    }<a name="line.572"></a>
-<span class="sourceLineNo">573</span>    ReentrantReadWriteLock lock = offsetLock.getLock(bucketEntry.offset());<a name="line.573"></a>
-<span class="sourceLineNo">574</span>    try {<a name="line.574"></a>
-<span class="sourceLineNo">575</span>      lock.writeLock().lock();<a name="line.575"></a>
-<span class="sourceLineNo">576</span>      if (backingMap.remove(cacheKey, bucketEntry)) {<a name="line.576"></a>
-<span class="sourceLineNo">577</span>        blockEvicted(cacheKey, bucketEntry, removedBlock == null);<a name="line.577"></a>
-<span class="sourceLineNo">578</span>      } else {<a name="line.578"></a>
-<span class="sourceLineNo">579</span>        return false;<a name="line.579"></a>
-<span class="sourceLineNo">580</span>      }<a name="line.580"></a>
-<span class="sourceLineNo">581</span>    } finally {<a name="line.581"></a>
-<span class="sourceLineNo">582</span>      lock.writeLock().unlock();<a name="line.582"></a>
-<span class="sourceLineNo">583</span>    }<a name="line.583"></a>
-<span class="sourceLineNo">584</span>    cacheStats.evicted(bucketEntry.getCachedTime(), cacheKey.isPrimary());<a name="line.584"></a>
-<span class="sourceLineNo">585</span>    return true;<a name="line.585"></a>
-<span class="sourceLineNo">586</span>  }<a name="line.586"></a>
-<span class="sourceLineNo">587</span><a name="line.587"></a>
-<span class="sourceLineNo">588</span>  private RAMQueueEntry checkRamCache(BlockCacheKey cacheKey) {<a name="line.588"></a>
-<span class="sourceLineNo">589</span>    RAMQueueEntry removedBlock = ramCache.remove(cacheKey);<a name="line.589"></a>
-<span class="sourceLineNo">590</span>    if (removedBlock != null) {<a name="line.590"></a>
-<span class="sourceLineNo">591</span>      this.blockNumber.decrement();<a name="line.591"></a>
-<span class="sourceLineNo">592</span>      this.heapSize.add(-1 * removedBlock.getData().heapSize());<a name="line.592"></a>
-<span class="sourceLineNo">593</span>    }<a name="line.593"></a>
-<span class="sourceLineNo">594</span>    return removedBlock;<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>  public boolean evictBlock(BlockCacheKey cacheKey, boolean deletedBlock) {<a name="line.597"></a>
-<span class="sourceLineNo">598</span>    if (!cacheEnabled) {<a name="line.598"></a>
-<span class="sourceLineNo">599</span>      return false;<a name="line.599"></a>
+<span class="sourceLineNo">527</span>          if (cachedBlock.getMemoryType() == MemoryType.SHARED) {<a name="line.527"></a>
+<span class="sourceLineNo">528</span>            bucketEntry.incrementRefCountAndGet();<a name="line.528"></a>
+<span class="sourceLineNo">529</span>          }<a name="line.529"></a>
+<span class="sourceLineNo">530</span>          bucketEntry.access(accessCount.incrementAndGet());<a name="line.530"></a>
+<span class="sourceLineNo">531</span>          if (this.ioErrorStartTime &gt; 0) {<a name="line.531"></a>
+<span class="sourceLineNo">532</span>            ioErrorStartTime = -1;<a name="line.532"></a>
+<span class="sourceLineNo">533</span>          }<a name="line.533"></a>
+<span class="sourceLineNo">534</span>          return cachedBlock;<a name="line.534"></a>
+<span class="sourceLineNo">535</span>        }<a name="line.535"></a>
+<span class="sourceLineNo">536</span>      } catch (IOException ioex) {<a name="line.536"></a>
+<span class="sourceLineNo">537</span>        LOG.error("Failed reading block " + key + " from bucket cache", ioex);<a name="line.537"></a>
+<span class="sourceLineNo">538</span>        checkIOErrorIsTolerated();<a name="line.538"></a>
+<span class="sourceLineNo">539</span>      } finally {<a name="line.539"></a>
+<span class="sourceLineNo">540</span>        lock.readLock().unlock();<a name="line.540"></a>
+<span class="sourceLineNo">541</span>      }<a name="line.541"></a>
+<span class="sourceLineNo">542</span>    }<a name="line.542"></a>
+<span class="sourceLineNo">543</span>    if (!repeat &amp;&amp; updateCacheMetrics) {<a name="line.543"></a>
+<span class="sourceLineNo">544</span>      cacheStats.miss(caching, key.isPrimary(), key.getBlockType());<a name="line.544"></a>
+<span class="sourceLineNo">545</span>    }<a name="line.545"></a>
+<span class="sourceLineNo">546</span>    return null;<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>  @VisibleForTesting<a name="line.549"></a>
+<span class="sourceLineNo">550</span>  void blockEvicted(BlockCacheKey cacheKey, BucketEntry bucketEntry, boolean decrementBlockNumber) {<a name="line.550"></a>
+<span class="sourceLineNo">551</span>    bucketAllocator.freeBlock(bucketEntry.offset());<a name="line.551"></a>
+<span class="sourceLineNo">552</span>    realCacheSize.add(-1 * bucketEntry.getLength());<a name="line.552"></a>
+<span class="sourceLineNo">553</span>    blocksByHFile.remove(cacheKey);<a name="line.553"></a>
+<span class="sourceLineNo">554</span>    if (decrementBlockNumber) {<a name="line.554"></a>
+<span class="sourceLineNo">555</span>      this.blockNumber.decrement();<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>  @Override<a name="line.559"></a>
+<span class="sourceLineNo">560</span>  public boolean evictBlock(BlockCacheKey cacheKey) {<a name="line.560"></a>
+<span class="sourceLineNo">561</span>    return evictBlock(cacheKey, true);<a name="line.561"></a>
+<span class="sourceLineNo">562</span>  }<a name="line.562"></a>
+<span class="sourceLineNo">563</span><a name="line.563"></a>
+<span class="sourceLineNo">564</span>  // does not check for the ref count. Just tries to evict it if found in the<a name="line.564"></a>
+<span class="sourceLineNo">565</span>  // bucket map<a name="line.565"></a>
+<span class="sourceLineNo">566</span>  private boolean forceEvict(BlockCacheKey cacheKey) {<a name="line.566"></a>
+<span class="sourceLineNo">567</span>    if (!cacheEnabled) {<a name="line.567"></a>
+<span class="sourceLineNo">568</span>      return false;<a name="line.568"></a>
+<span class="sourceLineNo">569</span>    }<a name="line.569"></a>
+<span class="sourceLineNo">570</span>    RAMQueueEntry removedBlock = checkRamCache(cacheKey);<a name="line.570"></a>
+<span class="sourceLineNo">571</span>    BucketEntry bucketEntry = backingMap.get(cacheKey);<a name="line.571"></a>
+<span class="sourceLineNo">572</span>    if (bucketEntry == null) {<a name="line.572"></a>
+<span class="sourceLineNo">573</span>      if (removedBlock != null) {<a name="line.573"></a>
+<span class="sourceLineNo">574</span>        cacheStats.evicted(0, cacheKey.isPrimary());<a name="line.574"></a>
+<span class="sourceLineNo">575</span>        return true;<a name="line.575"></a>
+<span class="sourceLineNo">576</span>      } else {<a name="line.576"></a>
+<span class="sourceLineNo">577</span>        return false;<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>    ReentrantReadWriteLock lock = offsetLock.getLock(bucketEntry.offset());<a name="line.580"></a>
+<span class="sourceLineNo">581</span>    try {<a name="line.581"></a>
+<span class="sourceLineNo">582</span>      lock.writeLock().lock();<a name="line.582"></a>
+<span class="sourceLineNo">583</span>      if (backingMap.remove(cacheKey, bucketEntry)) {<a name="line.583"></a>
+<span class="sourceLineNo">584</span>        blockEvicted(cacheKey, bucketEntry, removedBlock == null);<a name="line.584"></a>
+<span class="sourceLineNo">585</span>      } else {<a name="line.585"></a>
+<span class="sourceLineNo">586</span>        return false;<a name="line.586"></a>
+<span class="sourceLineNo">587</span>      }<a name="line.587"></a>
+<span class="sourceLineNo">588</span>    } finally {<a name="line.588"></a>
+<span class="sourceLineNo">589</span>      lock.writeLock().unlock();<a name="line.589"></a>
+<span class="sourceLineNo">590</span>    }<a name="line.590"></a>
+<span class="sourceLineNo">591</span>    cacheStats.evicted(bucketEntry.getCachedTime(), cacheKey.isPrimary());<a name="line.591"></a>
+<span class="sourceLineNo">592</span>    return true;<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>  private RAMQueueEntry checkRamCache(BlockCacheKey cacheKey) {<a name="line.595"></a>
+<span class="sourceLineNo">596</span>    RAMQueueEntry removedBlock = ramCache.remove(cacheKey);<a name="line.596"></a>
+<span class="sourceLineNo">597</span>    if (removedBlock != null) {<a name="line.597"></a>
+<span class="sourceLineNo">598</span>      this.blockNumber.decrement();<a name="line.598"></a>
+<span class="sourceLineNo">599</span>      this.heapSize.add(-1 * removedBlock.getData().heapSize());<a name="line.599"></a>
 <span class="sourceLineNo">600</span>    }<a name="line.600"></a>
-<span class="sourceLineNo">601</span>    RAMQueueEntry removedBlock = checkRamCache(cacheKey);<a name="line.601"></a>
-<span class="sourceLineNo">602</span>    BucketEntry bucketEntry = backingMap.get(cacheKey);<a name="line.602"></a>
-<span class="sourceLineNo">603</span>    if (bucketEntry == null) {<a name="line.603"></a>
-<span class="sourceLineNo">604</span>      if (removedBlock != null) {<a name="line.604"></a>
-<span class="sourceLineNo">605</span>        cacheStats.evicted(0, cacheKey.isPrimary());<a name="line.605"></a>
-<span class="sourceLineNo">606</span>        return true;<a name="line.606"></a>
-<span class="sourceLineNo">607</span>      } else {<a name="line.607"></a>
-<span class="sourceLineNo">608</span>        return false;<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>    ReentrantReadWriteLock lock = offsetLock.getLock(bucketEntry.offset());<a name="line.611"></a>
-<span class="sourceLineNo">612</span>    try {<a name="line.612"></a>
-<span class="sourceLineNo">613</span>      lock.writeLock().lock();<a name="line.613"></a>
-<span class="sourceLineNo">614</span>      int refCount = bucketEntry.getRefCount();<a name="line.614"></a>
-<span class="sourceLineNo">615</span>      if (refCount == 0) {<a name="line.615"></a>
-<span class="sourceLineNo">616</span>        if (backingMap.remove(cacheKey, bucketEntry)) {<a name="line.616"></a>
-<span class="sourceLineNo">617</span>          blockEvicted(cacheKey, bucketEntry, removedBlock == null);<a name="line.617"></a>
-<span class="sourceLineNo">618</span>        } else {<a name="line.618"></a>
-<span class="sourceLineNo">619</span>          return false;<a name="line.619"></a>
-<span class="sourceLineNo">620</span>        }<a name="line.620"></a>
-<span class="sourceLineNo">621</span>      } else {<a name="line.621"></a>
-<span class="sourceLineNo">622</span>        if(!deletedBlock) {<a name="line.622"></a>
-<span class="sourceLineNo">623</span>          if (LOG.isDebugEnabled()) {<a name="line.623"></a>
-<span class="sourceLineNo">624</span>            LOG.debug("This block " + cacheKey + " is still referred by " + refCount<a name="line.624"></a>
-<span class="sourceLineNo">625</span>                + " readers. Can not be freed now");<a name="line.625"></a>
-<span class="sourceLineNo">626</span>          }<a name="line.626"></a>
-<span class="sourceLineNo">627</span>          return false;<a name="line.627"></a>
-<span class="sourceLineNo">628</span>        } else {<a name="line.628"></a>
-<span class="sourceLineNo">629</span>          if (LOG.isDebugEnabled()) {<a name="line.629"></a>
-<span class="sourceLineNo">630</span>            LOG.debug("This block " + cacheKey + " is still referred by " + refCount<a name="line.630"></a>
-<span class="sourceLineNo">631</span>                + " readers. Can not be freed now. Hence will mark this"<a name="line.631"></a>
-<span class="sourceLineNo">632</span>                + " for evicting at a later point");<a name="line.632"></a>
+<span class="sourceLineNo">601</span>    return removedBlock;<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>  public boolean evictBlock(BlockCacheKey cacheKey, boolean deletedBlock) {<a name="line.604"></a>
+<span class="sourceLineNo">605</span>    if (!cacheEnabled) {<a name="line.605"></a>
+<span class="sourceLineNo">606</span>      return false;<a name="line.606"></a>
+<span class="sourceLineNo">607</span>    }<a name="line.607"></a>
+<span class="sourceLineNo">608</span>    RAMQueueEntry removedBlock = checkRamCache(cacheKey);<a name="line.608"></a>
+<span class="sourceLineNo">609</span>    BucketEntry bucketEntry = backingMap.get(cacheKey);<a name="line.609"></a>
+<span class="sourceLineNo">610</span>    if (bucketEntry == null) {<a name="line.610"></a>
+<span class="sourceLineNo">611</span>      if (removedBlock != null) {<a name="line.611"></a>
+<span class="sourceLineNo">612</span>        cacheStats.evicted(0, cacheKey.isPrimary());<a name="line.612"></a>
+<span class="sourceLineNo">613</span>        return true;<a name="line.613"></a>
+<span class="sourceLineNo">614</span>      } else {<a name="line.614"></a>
+<span class="sourceLineNo">615</span>        return false;<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>    ReentrantReadWriteLock lock = offsetLock.getLock(bucketEntry.offset());<a name="line.618"></a>
+<span class="sourceLineNo">619</span>    try {<a name="line.619"></a>
+<span class="sourceLineNo">620</span>      lock.writeLock().lock();<a name="line.620"></a>
+<span class="sourceLineNo">621</span>      int refCount = bucketEntry.getRefCount();<a name="line.621"></a>
+<span class="sourceLineNo">622</span>      if (refCount == 0) {<a name="line.622"></a>
+<span class="sourceLineNo">623</span>        if (backingMap.remove(cacheKey, bucketEntry)) {<a name="line.623"></a>
+<span class="sourceLineNo">624</span>          blockEvicted(cacheKey, bucketEntry, removedBlock == null);<a name="line.624"></a>
+<span class="sourceLineNo">625</span>        } else {<a name="line.625"></a>
+<span class="sourceLineNo">626</span>          return false;<a name="line.626"></a>
+<span class="sourceLineNo">627</span>        }<a name="line.627"></a>
+<span class="sourceLineNo">628</span>      } else {<a name="line.628"></a>
+<span class="sourceLineNo">629</span>        if(!deletedBlock) {<a name="line.629"></a>
+<span class="sourceLineNo">630</span>          if (LOG.isDebugEnabled()) {<a name="line.630"></a>
+<span class="sourceLineNo">631</span>            LOG.debug("This block " + cacheKey + " is still referred by " + refCount<a name="line.631"></a>
+<span class="sourceLineNo">632</span>                + " readers. Can not be freed now");<a name="line.632"></a>
 <span class="sourceLineNo">633</span>          }<a name="line.633"></a>
-<span class="sourceLineNo">634</span>          bucketEntry.markForEvict();<a name="line.634"></a>
-<span class="sourceLineNo">635</span>        }<a name="line.635"></a>
-<span class="sourceLineNo">636</span>      }<a name="line.636"></a>
-<span class="sourceLineNo">637</span>    } finally {<a name="line.637"></a>
-<span class="sourceLineNo">638</span>      lock.writeLock().unlock();<a name="line.638"></a>
-<span class="sourceLineNo">639</span>    }<a name="line.639"></a>
-<span class="sourceLineNo">640</span>    cacheStats.evicted(bucketEntry.getCachedTime(), cacheKey.isPrimary());<a name="line.640"></a>
-<span class="sourceLineNo">641</span>    return true;<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>   * Statistics thread.  Periodically output cache statistics to the log.<a name="line.645"></a>
-<span class="sourceLineNo">646</span>   */<a name="line.646"></a>
-<span class="sourceLineNo">647</span>  private static class StatisticsThread extends Thread {<a name="line.647"></a>
-<span class="sourceLineNo">648</span>    private final BucketCache bucketCache;<a name="line.648"></a>
-<span class="sourceLineNo">649</span><a name="line.649"></a>
-<span class="sourceLineNo">650</span>    public StatisticsThread(BucketCache bucketCache) {<a name="line.650"></a>
-<span class="sourceLineNo">651</span>      super("BucketCacheStatsThread");<a name="line.651"></a>
-<span class="sourceLineNo">652</span>      setDaemon(true);<a name="line.652"></a>
-<span class="sourceLineNo">653</span>      this.bucketCache = bucketCache;<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 void run() {<a name="line.657"></a>
-<span class="sourceLineNo">658</span>      bucketCache.logStats();<a name="line.658"></a>
-<span class="sourceLineNo">659</span>    }<a name="line.659"></a>
-<span class="sourceLineNo">660</span>  }<a name="line.660"></a>
-<span class="sourceLineNo">661</span><a name="line.661"></a>
-<span class="sourceLineNo">662</span>  public void logStats() {<a name="line.662"></a>
-<span class="sourceLineNo">663</span>    long totalSize = bucketAllocator.getTotalSize();<a name="line.663"></a>
-<span class="sourceLineNo">664</span>    long usedSize = bucketAllocator.getUsedSize();<a name="line.664"></a>
-<span class="sourceLineNo">665</span>    long freeSize = totalSize - usedSize;<a name="line.665"></a>
-<span class="sourceLineNo">666</span>    long cacheSize = getRealCacheSize();<a name="line.666"></a>
-<span class="sourceLineNo">667</span>    LOG.info("failedBlockAdditions=" + cacheStats.getFailedInserts() + ", " +<a name="line.667"></a>
-<span class="sourceLineNo">668</span>        "totalSize=" + StringUtils.byteDesc(totalSize) + ", " +<a name="line.668"></a>
-<span class="sourceLineNo">669</span>        "freeSize=" + StringUtils.byteDesc(freeSize) + ", " +<a name="line.669"></a>
-<span class="sourceLineNo">670</span>        "usedSize=" + StringUtils.byteDesc(usedSize) +", " +<a name="line.670"></a>
-<span class="sourceLineNo">671</span>        "cacheSize=" + StringUtils.byteDesc(cacheSize) +", " +<a name="line.671"></a>
-<span class="sourceLineNo">672</span>        "accesses=" + cacheStats.getRequestCount() + ", " +<a name="line.672"></a>
-<span class="sourceLineNo">673</span>        "hits=" + cacheStats.getHitCount() + ", " +<a name="line.673"></a>
-<span class="sourceLineNo">674</span>        "IOhitsPerSecond=" + cacheStats.getIOHitsPerSecond() + ", " +<a name="line.674"></a>
-<span class="sourceLineNo">675</span>        "IOTimePerHit=" + String.format("%.2f", cacheStats.getIOTimePerHit())+ ", " +<a name="line.675"></a>
-<span class="sourceLineNo">676</span>        "hitRatio=" + (cacheStats.getHitCount() == 0 ? "0," :<a name="line.676"></a>
-<span class="sourceLineNo">677</span>          (StringUtils.formatPercent(cacheStats.getHitRatio(), 2)+ ", ")) +<a name="line.677"></a>
-<span class="sourceLineNo">678</span>        "cachingAccesses=" + cacheStats.getRequestCachingCount() + ", " +<a name="line.678"></a>
-<span class="sourceLineNo">679</span>        "cachingHits=" + cacheStats.getHitCachingCount() + ", " +<a name="line.679"></a>
-<span class="sourceLineNo">680</span>        "cachingHitsRatio=" +(cacheStats.getHitCachingCount() == 0 ? "0," :<a name="line.680"></a>
-<span class="sourceLineNo">681</span>          (StringUtils.formatPercent(cacheStats.getHitCachingRatio(), 2)+ ", ")) +<a name="line.681"></a>
-<span class="sourceLineNo">682</span>        "evictions=" + cacheStats.getEvictionCount() + ", " +<a name="line.682"></a>
-<span class="sourceLineNo">683</span>        "evicted=" + cacheStats.getEvictedCount() + ", " +<a name="line.683"></a>
-<span class="sourceLineNo">684</span>        "evictedPerRun=" + cacheStats.evictedPerEviction());<a name="line.684"></a>
-<span class="sourceLineNo">685</span>    cacheStats.reset();<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>  public long getRealCacheSize() {<a name="line.688"></a>
-<span class="sourceLineNo">689</span>    return this.realCacheSize.sum();<a name="line.689"></a>
-<span class="sourceLineNo">690</span>  }<a name="line.690"></a>
-<span class="sourceLineNo">691</span><a name="line.691"></a>
-<span class="sourceLineNo">692</span>  private long acceptableSize() {<a name="line.692"></a>
-<span class="sourceLineNo">693</span>    return (long) Math.floor(bucketAllocator.getTotalSize() * acceptableFactor);<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>  @VisibleForTesting<a name="line.696"></a>
-<span class="sourceLineNo">697</span>  long getPartitionSize(float partitionFactor) {<a name="line.697"></a>
-<span class="sourceLineNo">698</span>    return (long) Math.floor(bucketAllocator.getTotalSize() * partitionFactor * minFactor);<a name="line.698"></a>
-<span class="sourceLineNo">699</span>  }<a name="line.699"></a>
-<span class="sourceLineNo">700</span><a name="line.700"></a>
-<span class="sourceLineNo">701</span>  /**<a name="line.701"></a>
-<span class="sourceLineNo">702</span>   * Return the count of bucketSizeinfos still need free space<a name="line.702"></a>
-<span class="sourceLineNo">703</span>   */<a name="line.703"></a>
-<span class="sourceLineNo">704</span>  private int bucketSizesAboveThresholdCount(float minFactor) {<a name="line.704"></a>
-<span class="sourceLineNo">705</span>    BucketAllocator.IndexStatistics[] stats = bucketAllocator.getIndexStatistics();<a name="line.705"></a>
-<span class="sourceLineNo">706</span>    int fullCount = 0;<a name="line.706"></a>
-<span class="sourceLineNo">707</span>    for (int i = 0; i &lt; stats.length; i++) {<a name="line.707"></a>
-<span class="sourceLineNo">708</span>      long freeGoal = (long) Math.floor(stats[i].totalCount() * (1 - minFactor));<a name="line.708"></a>
-<span class="sourceLineNo">709</span>      freeGoal = Math.max(freeGoal, 1);<a name="line.709"></a>
-<span class="sourceLineNo">710</span>      if (stats[i].freeCount() &lt; freeGoal) {<a name="line.710"></a>
-<span class="sourceLineNo">711</span>        fullCount++;<a name="line.711"></a>
-<span class="sourceLineNo">712</span>      }<a name="line.712"></a>
-<span class="sourceLineNo">713</span>    }<a name="line.713"></a>
-<span class="sourceLineNo">714</span>    return fullCount;<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">717</span>  /**<a name="line.717"></a>
-<span class="sourceLineNo">718</span>   * This method will find the buckets that are minimally occupied<a name="line.718"></a>
-<span class="sourceLineNo">719</span>   * and are not reference counted and will free them completely<a name="line.719"></a>
-<span class="sourceLineNo">720</span>   * without any constraint on the access times of the elements,<a name="line.720"></a>
-<span class="sourceLineNo">721</span>   * and as a process will completely free at most the number of buckets<a name="line.721"></a>
-<span class="sourceLineNo">722</span>   * passed, sometimes it might not due to changing refCounts<a name="line.722"></a>
-<span class="sourceLineNo">723</span>   *<a name="line.723"></a>
-<span class="sourceLineNo">724</span>   * @param completelyFreeBucketsNeeded number of buckets to free<a name="line.724"></a>
-<span class="sourceLineNo">725</span>   **/<a name="line.725"></a>
-<span class="sourceLineNo">726</span>  private void freeEntireBuckets(int completelyFreeBucketsNeeded) {<a name="line.726"></a>
-<span class="sourceLineNo">727</span>    if (completelyFreeBucketsNeeded != 0) {<a name="line.727"></a>
-<span class="sourceLineNo">728</span>      // First we will build a set where the offsets are reference counted, usually<a name="line.728"></a>
-<span class="sourceLineNo">729</span>      // this set is small around O(Handler Count) unless something else is wrong<a name="line.729"></a>
-<span class="sourceLineNo">730</span>      Set&lt;Integer&gt; inUseBuckets = new HashSet&lt;Integer&gt;();<a name="line.730"></a>
-<span class="sourceLineNo">731</span>      for (BucketEntry entry : backingMap.values()) {<a name="line.731"></a>
-<span class="sourceLineNo">732</span>        if (entry.getRefCount() != 0) {<a name="line.732"></a>
-<span class="sourceLineNo">733</span>          inUseBuckets.add(bucketAllocator.getBucketIndex(entry.offset()));<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><a name="line.736"></a>
-<span class="sourceLineNo">737</span>      Set&lt;Integer&gt; candidateBuckets = bucketAllocator.getLeastFilledBuckets(<a name="line.737"></a>
-<span class="sourceLineNo">738</span>          inUseBuckets, completelyFreeBucketsNeeded);<a name="line.738"></a>
-<span class="sourceLineNo">739</span>      for (Map.Entry&lt;BlockCacheKey, BucketEntry&gt; entry : backingMap.entrySet()) {<a name="line.739"></a>
-<span class="sourceLineNo">740</span>        if (candidateBuckets.contains(bucketAllocator<a name="line.740"></a>
-<span class="sourceLineNo">741</span>            .getBucketIndex(entry.getValue().offset()))) {<a name="line.741"></a>
-<span class="sourceLineNo">742</span>          evictBlock(entry.getKey(), false);<a name="line.742"></a>
-<span class="sourceLineNo">743</span>        }<a name="line.743"></a>
-<span class="sourceLineNo">744</span>      }<a name="line.744"></a>
-<span class="sourceLineNo">745</span>    }<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>  /**<a name="line.748"></a>
-<span class="sourceLineNo">749</span>   * Free the space if the used size reaches acceptableSize() or one size block<a name="line.749"></a>
-<span class="sourceLineNo">750</span>   * couldn't be allocated. When freeing the space, we use the LRU algorithm and<a name="line.750"></a>
-<span class="sourceLineNo">751</span>   * ensure there must be some blocks evicted<a name="line.751"></a>
-<span class="sourceLineNo">752</span>   * @param why Why we are being called<a name="line.752"></a>
-<span class="sourceLineNo">753</span>   */<a name="line.753"></a>
-<span class="sourceLineNo">754</span>  private void freeSpace(final String why) {<a name="line.754"></a>
-<span class="sourceLineNo">755</span>    // Ensure only one freeSpace progress at a time<a name="line.755"></a>
-<span class="sourceLineNo">756</span>    if (!freeSpaceLock.tryLock()) {<a name="line.756"></a>
-<span class="sourceLineNo">757</span>      return;<a name="line.757"></a>
-<span class="sourceLineNo">758</span>    }<a name="line.758"></a>
-<span class="sourceLineNo">759</span>    try {<a name="line.759"></a>
-<span class="sourceLineNo">760</span>      freeInProgress = true;<a name="line.760"></a>
-<span class="sourceLineNo">761</span>      long bytesToFreeWithoutExtra = 0;<a name="line.761"></a>
-<span class="sourceLineNo">762</span>      // Calculate free byte for each bucketSizeinfo<a name="line.762"></a>
-<span class="sourceLineNo">763</span>      StringBuilder msgBuffer = LOG.isDebugEnabled()? new StringBuilder(): null;<a name="line.763"></a>
-<span class="sourceLineNo">764</span>      BucketAllocator.IndexStatistics[] stats = bucketAllocator.getIndexStatistics();<a name="line.764"></a>
-<span class="sourceLineNo">765</span>      long[] bytesToFreeForBucket = new long[stats.length];<a name="line.765"></a>
-<span class="sourceLineNo">766</span>      for (int i = 0; i &lt; stats.length; i++) {<a name="line.766"></a>
-<span class="sourceLineNo">767</span>        bytesToFreeForBucket[i] = 0;<a name="line.767"></a>
-<span class="sourceLineNo">768</span>        long freeGoal = (long) Math.floor(stats[i].totalCount() * (1 - minFactor));<a name="line.768"></a>
-<span class="sourceLineNo">769</span>        freeGoal = Math.max(freeGoal, 1);<a name="line.769"></a>
-<span class="sourceLineNo">770</span>        if (stats[i].freeCount() &lt; freeGoal) {<a name="line.770"></a>
-<span class="sourceLineNo">771</span>          bytesToFreeForBucket[i] = stats[i].itemSize() * (freeGoal - stats[i].freeCount());<a name="line.771"></a>
-<span class="sourceLineNo">772</span>          bytesToFreeWithoutExtra += bytesToFreeForBucket[i];<a name="line.772"></a>
-<span class="sourceLineNo">773</span>          if (msgBuffer != null) {<a name="line.773"></a>
-<span class="sourceLineNo">774</span>            msgBuffer.append("Free for bucketSize(" + stats[i].itemSize() + ")="<a name="line.774"></a>
-<span class="sourceLineNo">775</span>              + StringUtils.byteDesc(bytesToFreeForBucket[i]) + ", ");<a name="line.775"></a>
-<span class="sourceLineNo">776</span>          }<a name="line.776"></a>
-<span class="sourceLineNo">777</span>        }<a name="line.777"></a>
-<span class="sourceLineNo">778</span>      }<a name="line.778"></a>
-<span class="sourceLineNo">779</span>      if (msgBuffer != null) {<a name="line.779"></a>
-<span class="sourceLineNo">780</span>        msgBuffer.append("Free for total=" + StringUtils.byteDesc(bytesToFreeWithoutExtra) + ", ");<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>      if (bytesToFreeWithoutExtra &lt;= 0) {<a name="line.783"></a>
-<span class="sourceLineNo">784</span>        return;<a name="line.784"></a>
+<span class="sourceLineNo">634</span>          return false;<a name="line.634"></a>
+<span class="sourceLineNo">635</span>        } else {<a name="line.635"></a>
+<span class="sourceLineNo">636</span>          if (LOG.isDebugEnabled()) {<a name="line.636"></a>
+<span class="sourceLineNo">637</span>            LOG.debug("This block " + cacheKey + " is still referred by " + refCount<a name="line.637"></a>
+<span class="sourceLineNo">638</span>                + " readers. Can not be freed now. Hence will mark this"<a name="line.638"></a>
+<span class="sourceLineNo">639</span>                + " for evicting at a later point");<a name="line.639"></a>
+<span class="sourceLineNo">640</span>          }<a name="line.640"></a>
+<span class="sourceLineNo">641</span>          bucketEntry.markForEvict();<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>    } finally {<a name="line.644"></a>
+<span class="sourceLineNo">645</span>      lock.writeLock().unlock();<a name="line.645"></a>
+<span class="sourceLineNo">646</span>    }<a name="line.646"></a>
+<span class="sourceLineNo">647</span>    cacheStats.evicted(bucketEntry.getCachedTime(), cacheKey.isPrimary());<a name="line.647"></a>
+<span class="sourceLineNo">648</span>    return true;<a name="line.648"></a>
+<span class="sourceLineNo">649</span>  }<a name="line.649"></a>
+<span class="sourceLineNo">650</span><a name="line.650"></a>
+<span class="sourceLineNo">651</span>  /*<a name="line.651"></a>
+<span class="sourceLineNo">652</span>   * Statistics thread.  Periodically output cache statistics to the log.<a name="line.652"></a>
+<span class="sourceLineNo">653</span>   */<a name="line.653"></a>
+<span class="sourceLineNo">654</span>  private static class StatisticsThread extends Thread {<a name="line.654"></a>
+<span class="sourceLineNo">655</span>    private final BucketCache bucketCache;<a name="line.655"></a>
+<span class="sourceLineNo">656</span><a name="line.656"></a>
+<span class="sourceLineNo">657</span>    public StatisticsThread(BucketCache bucketCache) {<a name="line.657"></a>
+<span class="sourceLineNo">658</span>      super("BucketCacheStatsThread");<a name="line.658"></a>
+<span class="sourceLineNo">659</span>      setDaemon(true);<a name="line.659"></a>
+<span class="sourceLineNo">660</span>      this.bucketCache = bucketCache;<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>    @Override<a name="line.663"></a>
+<span class="sourceLineNo">664</span>    public void run() {<a name="line.664"></a>
+<span class="sourceLineNo">665</span>      bucketCache.logStats();<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>  public void logStats() {<a name="line.669"></a>
+<span class="sourceLineNo">670</span>    long totalSize = bucketAllocator.getTotalSize();<a name="line.670"></a>
+<span class="sourceLineNo">671</span>    long usedSize = bucketAllocator.getUsedSize();<a name="line.671"></a>
+<span class="sourceLineNo">672</span>    long freeSize = totalSize - usedSize;<a name="line.672"></a>
+<span class="sourceLineNo">673</span>    long cacheSize = getRealCacheSize();<a name="line.673"></a>
+<span class="sourceLineNo">674</span>    LOG.info("failedBlockAdditions=" + cacheStats.getFailedInserts() + ", " +<a name="line.674"></a>
+<span class="sourceLineNo">675</span>        "totalSize=" + StringUtils.byteDesc(totalSize) + ", " +<a name="line.675"></a>
+<span class="sourceLineNo">676</span>        "freeSize=" + StringUtils.byteDesc(freeSize) + ", " +<a name="line.676"></a>
+<span class="sourceLineNo">677</span>        "usedSize=" + StringUtils.byteDesc(usedSize) +", " +<a name="line.677"></a>
+<span class="sourceLineNo">678</span>        "cacheSize=" + StringUtils.byteDesc(cacheSize) +", " +<a name="line.678"></a>
+<span class="sourceLineNo">679</span>        "accesses=" + cacheStats.getRequestCount() + ", " +<a name="line.679"></a>
+<span class="sourceLineNo">680</span>        "hits=" + cacheStats.getHitCount() + ", " +<a name="line.680"></a>
+<span class="sourceLineNo">681</span>        "IOhitsPerSecond=" + cacheStats.getIOHitsPerSecond() + ", " +<a name="line.681"></a>
+<span class="sourceLineNo">682</span>        "IOTimePerHit=" + String.format("%.2f", cacheStats.getIOTimePerHit())+ ", " +<a name="line.682"></a>
+<span class="sourceLineNo">683</span>        "hitRatio=" + (cacheStats.getHitCount() == 0 ? "0," :<a name="line.683"></a>
+<span class="sourceLineNo">684</span>          (StringUtils.formatPercent(cacheStats.getHitRatio(), 2)+ ", ")) +<a name="line.684"></a>
+<span class="sourceLineNo">685</span>        "cachingAccesses=" + cacheStats.getRequestCachingCount() + ", " +<a name="line.685"></a>
+<span class="sourceLineNo">686</span>        "cachingHits=" + cacheStats.getHitCachingCount() + ", " +<a name="line.686"></a>
+<span class="sourceLineNo">687</span>        "cachingHitsRatio=" +(cacheStats.getHitCachingCount() == 0 ? "0," :<a name="line.687"></a>
+<span class="sourceLineNo">688</span>          (StringUtils.formatPercent(cacheStats.getHitCachingRatio(), 2)+ ", ")) +<a name="line.688"></a>
+<span class="sourceLineNo">689</span>        "evictions=" + cacheStats.getEvictionCount() + ", " +<a name="line.689"></a>
+<span class="sourceLineNo">690</span>        "evicted=" + cacheStats.getEvictedCount() + ", " +<a name="line.690"></a>
+<span class="sourceLineNo">691</span>        "evictedPerRun=" + cacheStats.evictedPerEviction());<a name="line.691"></a>
+<span class="sourceLineNo">692</span>    cacheStats.reset();<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>  public long getRealCacheSize() {<a name="line.695"></a>
+<span class="sourceLineNo">696</span>    return this.realCacheSize.sum();<a name="line.696"></a>
+<span class="sourceLineNo">697</span>  }<a name="line.697"></a>
+<span class="sourceLineNo">698</span><a name="line.698"></a>
+<span class="sourceLineNo">699</span>  private long acceptableSize() {<a name="line.699"></a>
+<span class="sourceLineNo">700</span>    return (long) Math.floor(bucketAllocator.getTotalSize() * acceptableFactor);<a name="line.700"></a>
+<span class="sourceLineNo">701</span>  }<a name="line.701"></a>
+<span class="sourceLineNo">702</span><a name="line.702"></a>
+<span class="sourceLineNo">703</span>  @VisibleForTesting<a name="line.703"></a>
+<span class="sourceLineNo">704</span>  long getPartitionSize(float partitionFactor) {<a name="line.704"></a>
+<span class="sourceLineNo">705</span>    return (long) Math.floor(bucketAllocator.getTotalSize() * partitionFactor * minFactor);<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>   * Return the count of bucketSizeinfos still need free space<a name="line.709"></a>
+<span class="sourceLineNo">710</span>   */<a name="line.710"></a>
+<span class="sourceLineNo">711</span>  private int bucketSizesAboveThresholdCount(float minFactor) {<a name="line.711"></a>
+<span class="sourceLineNo">712</span>    BucketAllocator.IndexStatistics[] stats = bucketAllocator.getIndexStatistics();<a name="line.712"></a>
+<span class="sourceLineNo">713</span>    int fullCount = 0;<a name="line.713"></a>
+<span class="sourceLineNo">714</span>    for (int i = 0; i &lt; stats.length; i++) {<a name="line.714"></a>
+<span class="sourceLineNo">715</span>      long freeGoal = (long) Math.floor(stats[i].totalCount() * (1 - minFactor));<a name="line.715"></a>
+<span class="sourceLineNo">716</span>      freeGoal = Math.max(freeGoal, 1);<a name="line.716"></a>
+<span class="sourceLineNo">717</span>      if (stats[i].freeCount() &lt; freeGoal) {<a name="line.717"></a>
+<span class="sourceLineNo">718</span>        fullCount++;<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>
+<span class="sourceLineNo">721</span>    return fullCount;<a name="line.721"></a>
+<span class="sourceLineNo">722</span>  }<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>   * This method will find the buckets that are minimally occupied<a name="line.725"></a>
+<span class="sourceLineNo">726</span>   * and are not reference counted and will free them completely<a name="line.726"></a>
+<span class="sourceLineNo">727</span>   * without any constraint on the access times of the elements,<a name="line.727"></a>
+<span class="sourceLineNo">728</span>   * and as a process will completely free at most the number of buckets<a name="line.728"></a>
+<span class="sourceLineNo">729</span>   * passed, sometimes it might not due to changing refCounts<a name="line.729"></a>
+<span class="sourceLineNo">730</span>   *<a name="line.730"></a>
+<span class="sourceLineNo">731</span>   * @param completelyFreeBucketsNeeded number of buckets to free<a name="line.731"></a>
+<span class="sourceLineNo">732</span>   **/<a name="line.732"></a>
+<span class="sourceLineNo">733</span>  private void freeEntireBuckets(int completelyFreeBucketsNeeded) {<a name="line.733"></a>
+<span class="sourceLineNo">734</span>    if (completelyFreeBucketsNeeded != 0) {<a name="line.734"></a>
+<span class="sourceLineNo">735</span>      // First we will build a set where the offsets are reference counted, usually<a name="line.735"></a>
+<span class="sourceLineNo">736</span>      // this set is small around O(Handler Count) unless something else is wrong<a name="line.736"></a>
+<span class="sourceLineNo">737</span>      Set&lt;Integer&gt; inUseBuckets = new HashSet&lt;Integer&gt;();<a name="line.737"></a>
+<span class="sourceLineNo">738</span>      for (BucketEntry entry : backingMap.values()) {<a name="line.738"></a>
+<span class="sourceLineNo">739</span>        if (entry.getRefCount() != 0) {<a name="line.739"></a>
+<span class="sourceLineNo">740</span>          inUseBuckets.add(bucketAllocator.getBucketIndex(entry.offset()));<a name="line.740"></a>
+<span class="sourceLineNo">741</span>        }<a name="line.741"></a>
+<span class="sourceLineNo">742</span>      }<a name="line.742"></a>
+<span class="sourceLineNo">743</span><a name="line.743"></a>
+<span class="sourceLineNo">744</span>      Set&lt;Integer&gt; candidateBuckets = bucketAllocator.getLeastFilledBuckets(<a name="line.744"></a>
+<span class="sourceLineNo">745</span>          inUseBuckets, completelyFreeBucketsNeeded);<a name="line.745"></a>
+<span class="sourceLineNo">746</span>      for (Map.Entry&lt;BlockCacheKey, BucketEntry&gt; entry : backingMap.entrySet()) {<a name="line.746"></a>
+<span class="sourceLineNo">747</span>        if (candidateBuckets.contains(bucketAllocator<a name="line.747"></a>
+<span class="sourceLineNo">748</span>            .getBucketIndex(entry.getValue().offset()))) {<a name="line.748"></a>
+<span class="sourceLineNo">749</span>          evictBlock(entry.getKey(), false);<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>  }<a name="line.753"></a>
+<span class="sourceLineNo">754</span><a name="line.754"></a>
+<span class="sourceLineNo">755</span>  /**<a name="line.755"></a>
+<span class="sourceLineNo">756</span>   * Free the space if the used size reaches acceptableSize() or one size block<a name="line.756"></a>
+<span class="sourceLineNo">757</span>   * couldn't be allocated. When freeing the space, we use the LRU algorithm and<a name="line.757"></a>
+<span class="sourceLineNo">758</span>   * ensure there must be some blocks evicted<a name="line.758"></a>
+<span class="sourceLineNo">759</span>   * @param why Why we are being called<a name="line.759"></a>
+<span class="sourceLineNo">760</span>   */<a name="line.760"></a>
+<span class="sourceLineNo">761</span>  private void freeSpace(final String why) {<a name="line.761"></a>
+<span class="sourceLineNo">762</span>    // Ensure only one freeSpace progress at a time<a name="line.762"></a>
+<span class="sourceLineNo">763</span>    if (!freeSpaceLock.tryLock()) {<a name="line.763"></a>
+<span class="sourceLineNo">764</span>      return;<a name="line.764"></a>
+<span class="sourceLineNo">765</span>    }<a name="line.765"></a>
+<span class="sourceLineNo">766</span>    try {<a name="line.766"></a>
+<span class="sourceLineNo">767</span>      freeInProgress = true;<a name="line.767"></a>
+<span class="sourceLineNo">768</span>      long bytesToFreeWithoutExtra = 0;<a name="line.768"></a>
+<span class="sourceLineNo">769</span>      // Calculate free byte for each bucketSizeinfo<a name="line.769"></a>
+<span class="sourceLineNo">770</span>      StringBuilder msgBuffer = LOG.isDebugEnabled()? new StringBuilder(): null;<a name="line.770"></a>
+<span class="sourceLineNo">771</span>      BucketAllocator.IndexStatistics[] stats = bucketAllocator.getIndexStatistics();<a name="line.771"></a>
+<span class="sourceLineNo">772</span>      long[] bytesToFreeForBucket = new long[stats.length];<a name="line.772"></a>
+<span class="sourceLineNo">773</span>      for (int i = 0; i &lt; stats.length; i++) {<a name="line.773"></a>
+<span class="sourceLineNo">774</span>        bytesToFreeForBucket[i] = 0;<a name="line.774"></a>
+<span class="sourceLineNo">775</span>        long freeGoal = (long) Math.floor(stats[i].totalCount() * (1 - minFactor));<a name="line.775"></a>
+<span class="sourceLineNo">776</span>        freeGoal = Math.max(freeGoal, 1);<a name="line.776"></a>
+<span class="sourceLineNo">777</span>        if (stats[i].freeCount() &lt; freeGoal) {<a name="line.777"></a>
+<span class="sourceLineNo">778</span>          bytesToFreeForBucket[i] = stats[i].itemSize() * (freeGoal - stats[i].freeCount());<a name="line.778"></a>
+<span class="sourceLineNo">779</span>          bytesToFreeWithoutExtra += bytesToFreeForBucket[i];<a name="line.779"></a>
+<span class="sourceLineNo">780</span>          if (msgBuffer != null) {<a name="line.780"></a>
+<span class="sourceLineNo">781</span>            msgBuffer.append("Free for bucketSize(" + stats[i].itemSize() + ")="<a name="line.781"></a>
+<span class="sourceLineNo">782</span>              + StringUtils.byteDesc(bytesToFreeForBucket[i]) + ", ");<a name="line.782"></a>
+<span class="sourceLineNo">783</span>          }<a name="line.783"></a>
+<span class="sourceLineNo">784</span>        }<a name="line.784"></a>
 <span class="sourceLineNo">785</span>      }<a name="line.785"></a>
-<span class="sourceLineNo">786</span>      long currentSize = bucketAllocator.getUsedSize();<a name="line.786"></a>
-<span class="sourceLineNo">787</span>      long totalSize = bucketAllocator.getTotalSize();<a name="line.787"></a>
-<span class="sourceLineNo">788</span>      if (LOG.isDebugEnabled() &amp;&amp; msgBuffer != null) {<a name="line.788"></a>
-<span class="sourceLineNo">789</span>        LOG.debug("Free started because \"" + why + "\"; " + msgBuffer.toString() +<a name="line.789"></a>
-<span class="sourceLineNo">790</span>          " of current used=" + StringUtils.byteDesc(currentSize) + ", actual cacheSize=" +<a name="line.790"></a>
-<span class="sourceLineNo">791</span>          StringUtils.byteDesc(realCacheSize.sum()) + ", total=" + StringUtils.byteDesc(totalSize));<a name="line.791"></a>
+<span class="sourceLineNo">786</span>      if (msgBuffer != null) {<a name="line.786"></a>
+<span class="sourceLineNo">787</span>        msgBuffer.append("Free for total=" + StringUtils.byteDesc(bytesToFreeWithoutExtra) + ", ");<a name="line.787"></a>
+<span class="sourceLineNo">788</span>      }<a name="line.788"></a>
+<span class="sourceLineNo">789</span><a name="line.789"></a>
+<span class="sourceLineNo">790</span>      if (bytesToFreeWithoutExtra &lt;= 0) {<a name="line.790"></a>
+<span class="sourceLineNo">791</span>        return;<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>
-<span class="sourceLineNo">794</span>      long bytesToFreeWithExtra = (long) Math.floor(bytesToFreeWithoutExtra<a name="line.794"></a>
-<span class="sourceLineNo">795</span>          * (1 + extraFreeFactor));<a name="line.795"></a>
-<span class="sourceLineNo">796</span><a name="line.796"></a>
-<span class="sourceLineNo">797</span>      // Instantiate priority buckets<a name="line.797"></a>
-<span class="sourceLineNo">798</span>      BucketEntryGroup bucketSingle = new BucketEntryGroup(bytesToFreeWithExtra,<a name="line.798"></a>
-<span class="sourceLineNo">799</span>          blockSize, getPartitionSize(singleFactor));<a name="line.799"></a>
-<span class="sourceLineNo">800</span>      BucketEntryGroup bucketMulti = new BucketEntryGroup(bytesToFreeWithExtra,<a name="line.800"></a>
-<span class="sourceLineNo">801</span>          blockSize, getPartitionSize(multiFactor));<a name="line.801"></a>
-<span class="sourceLineNo">802</span>      BucketEntryGroup bucketMemory = new BucketEntryGroup(bytesToFreeWithExtra,<a name="line.802"></a>
-<span class="sourceLineNo">803</span>          blockSize, getPartitionSize(memoryFactor));<a name="line.803"></a>
-<span class="sourceLineNo">804</span><a name="line.804"></a>
-<span class="sourceLineNo">805</span>      // Scan entire map putting bucket entry into appropriate bucket entry<a name="line.805"></a>
-<span class="sourceLineNo">806</span>      // group<a name="line.806"></a>
-<span class="sourceLineNo">807</span>      for (Map.Entry&lt;BlockCacheKey, BucketEntry&gt; bucketEntryWithKey : backingMap.entrySet()) {<a name="line.807"></a>
-<span class="sourceLineNo">808</span>        switch (bucketEntryWithKey.getValue().getPriority()) {<a name="line.808"></a>
-<span class="sourceLineNo">809</span>          case SINGLE: {<a name="line.809"></a>
-<span class="sourceLineNo">810</span>            bucketSingle.add(bucketEntryWithKey);<a name="line.810"></a>
-<span class="sourceLineNo">811</span>            break;<a name="line.811"></a>
-<span class="sourceLineNo">812</span>          }<a name="line.812"></a>
-<span class="sourceLineNo">813</span>          case MULTI: {<a name="line.813"></a>
-<span class="sourceLineNo">814</span>            bucketMulti.add(bucketEntryWithKey);<a name="line.814"></a>
-<span class="sourceLineNo">815</span>            break;<a name="line.815"></a>
-<span class="sourceLineNo">816</span>          }<a name="line.816"></a>
-<span class="sourceLineNo">817</span>          case MEMORY: {<a name="line.817"></a>
-<span class="sourceLineNo">818</span>            bucketMemory.add(bucketEntryWithKey);<a name="line.818"></a>
-<span class="sourceLineNo">819</span>            break;<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><a name="line.823"></a>
-<span class="sourceLineNo">824</span>      PriorityQueue&lt;BucketEntryGroup&gt; bucketQueue = new PriorityQueue&lt;&gt;(3,<a name="line.824"></a>
-<span class="sourceLineNo">825</span>          Comparator.comparingLong(BucketEntryGroup::overflow));<a name="line.825"></a>
-<span class="sourceLineNo">826</span><a name="line.826"></a>
-<span class="sourceLineNo">827</span>      bucketQueue.add(bucketSingle);<a name="line.827"></a>
-<span class="sourceLineNo">828</span>      bucketQueue.add(bucketMulti);<a name="line.828"></a>
-<span class="sourceLineNo">829</span>      bucketQueue.add(bucketMemory);<a name="line.829"></a>
+<span class="sourceLineNo">793</span>      long currentSize = bucketAllocator.getUsedSize();<a name="line.793"></a>
+<span class="sourceLineNo">794</span>      long totalSize = bucketAllocator.getTotalSize();<a name="line.794"></a>
+<span class="sourceLineNo">795</span>      if (LOG.isDebugEnabled() &amp;&amp; msgBuffer != null) {<a name="line.795"></a>
+<span class="sourceLineNo">796</span>        LOG.debug("Free started because \"" + why + "\"; " + msgBuffer.toString() +<a name="line.796"></a>
+<span class="sourceLineNo">797</span>          " of current used=" + StringUtils.byteDesc(currentSize) + ", actual cacheSize=" +<a name="line.797"></a>
+<span class="sourceLineNo">798</span>          StringUtils.byteDesc(realCacheSize.sum()) + ", total=" + StringUtils.byteDesc(totalSize));<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>      long bytesToFreeWithExtra = (long) Math.floor(bytesToFreeWithoutExtra<a name="line.801"></a>
+<span class="sourceLineNo">802</span>          * (1 + extraFreeFactor));<a name="line.802"></a>
+<span class="sourceLineNo">803</span><a name="line.803"></a>
+<span class="sourceLineNo">804</span>      // Instantiate priority buckets<a name="line.804"></a>
+<span class="sourceLineNo">805</span>      BucketEntryGroup bucketSingle = new BucketEntryGroup(bytesToFreeWithExtra,<a name="line.805"></a>
+<span class="sourceLineNo">806</span>          blockSize, getPartitionSize(singleFactor));<a name="line.806"></a>
+<span class="sourceLineNo">807</span>      BucketEntryGroup bucketMulti = new BucketEntryGroup(bytesToFreeWithExtra,<a name="line.807"></a>
+<span class="sourceLineNo">808</span>          blockSize, getPartitionSize(multiFactor));<a name="line.808"></a>
+<span class="sourceLineNo">809</span>      BucketEntryGroup bucketMemory = new BucketEntryGroup(bytesToFreeWithExtra,<a name="line.809"></a>
+<span class="sourceLineNo">810</span>          blockSize, getPartitionSize(memoryFactor));<a name="line.810"></a>
+<span class="sourceLineNo">811</span><a name="line.811"></a>
+<span class="sourceLineNo">812</span>      // Scan entire map putting bucket entry into appropriate bucket entry<a name="line.812"></a>
+<span class="sourceLineNo">813</span>      // group<a name="line.813"></a>
+<span class="sourceLineNo">814</span>      for (Map.Entry&lt;BlockCacheKey, BucketEntry&gt; bucketEntryWithKey : backingMap.entrySet()) {<a name="line.814"></a>
+<span class="sourceLineNo">815</span>        switch (bucketEntryWithKey.getValue().getPriority()) {<a name="line.815"></a>
+<span class="sourceLineNo">816</span>          case SINGLE: {<a name="line.816"></a>
+<span class="sourceLineNo">817</span>            bucketSingle.add(bucketEntryWithKey);<a name="line.817"></a>
+<span class="sourceLineNo">818</span>            break;<a name="line.818"></a>
+<span class="sourceLineNo">819</span>          }<a name="line.819"></a>
+<span class="sourceLineNo">820</span>          case MULTI: {<a name="line.820"></a>
+<span class="sourceLineNo">821</span>            bucketMulti.add(bucketEntryWithKey);<a name="line.821"></a>
+<span class="sourceLineNo">822</span>            break;<a name="line.822"></a>
+<span class="sourceLineNo">823</span>          }<a name="line.823"></a>
+<span class="sourceLineNo">824</span>          case MEMORY: {<a name="line.824"></a>
+<span class="sourceLineNo">825</span>            bucketMemory.add(bucketEntryWithKey);<a name="line.825"></a>
+<span class="sourceLineNo">826</span>            break;<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">830</span><a name="line.830"></a>
-<span class="sourceLineNo">831</span>      int remainingBuckets = 3;<a name="line.831"></a>
-<span class="sourceLineNo">832</span>      long bytesFreed = 0;<a name="line.832"></a>
+<span class="sourceLineNo">831</span>      PriorityQueue&lt;BucketEntryGroup&gt; bucketQueue = new PriorityQueue&lt;&gt;(3,<a name="line.831"></a>
+<span class="sourceLineNo">832</span>          Comparator.comparingLong(BucketEntryGroup::overflow));<a name="line.832"></a>
 <span class="sourceLineNo">833</span><a name="line.833"></a>
-<span class="sourceLineNo">834</span>      BucketEntryGroup bucketGroup;<a name="line.834"></a>
-<span class="sourceLineNo">835</span>      while ((bucketGroup = bucketQueue.poll()) != null) {<a name="line.835"></a>
-<span class="sourceLineNo">836</span>        long overflow = bucketGroup.overflow();<a name="line.836"></a>
-<span class="sourceLineNo">837</span>        if (overflow &gt; 0) {<a name="line.837"></a>
-<span class="sourceLineNo">838</span>          long bucketBytesToFree = Math.min(overflow,<a name="line.838"></a>
-<span class="sourceLineNo">839</span>              (bytesToFreeWithoutExtra - bytesFreed) / remainingBuckets);<a name="line.839"></a>
-<span class="sourceLineNo">840</span>          bytesFreed += bucketGroup.free(bucketBytesToFree);<a name="line.840"></a>
-<span class="sourceLineNo">841</span>        }<a name="line.841"></a>
-<span class="sourceLineNo">842</span>        remainingBuckets--;<a name="line.842"></a>
-<span class="sourceLineNo">843</span>      }<a name="line.843"></a>
-<span class="sourceLineNo">844</span><a name="line.844"></a>
-<span class="sourceLineNo">845</span>      // Check and free if there are buckets that still need freeing of space<a name="line.845"></a>
-<span class="sourceLineNo">846</span>      if (bucketSizesAboveThresholdCount(minFactor) &gt; 0) {<a name="line.846"></a>
-<span class="sourceLineNo">847</span>        bucketQueue.clear();<a name="line.847"></a>
-<span class="sourceLineNo">848</span>        remainingBuckets = 3;<a name="line.848"></a>
-<span class="sourceLineNo">849</span><a name="line.849"></a>
-<span class="sourceLineNo">850</span>        bucketQueue.add(bucketSingle);<a name="line.850"></a>
-<span class="sourceLineNo">851</span>        bucketQueue.add(bucketMulti);<a name="line.851"></a>
-<span class="sourceLineNo">852</span>        bucketQueue.add(bucketMemory);<a name="line.852"></a>
-<span class="sourceLineNo">853</span><a name="line.853"></a>
-<span class="sourceLineNo">854</span>        while ((bucketGroup = bucketQueue.poll()) != null) {<a name="line.854"></a>
-<span class="sourceLineNo">855</span>          long bucketBytesToFree = (bytesToFreeWithExtra - bytesFreed) / remainingBuckets;<a name="line.855"></a>
-<span class="sourceLineNo">856</span>          bytesFreed += bucketGroup.free(bucketBytesToFree);<a name="line.856"></a>
-<span class="sourceLineNo">857</span>          remainingBuckets--;<a name="line.857"></a>
-<span class="sourceLineNo">858</span>        }<a name="line.858"></a>
-<span class="sourceLineNo">859</span>      }<a name="line.859"></a>
+<span class="sourceLineNo">834</span>      bucketQueue.add(bucketSingle);<a name="line.834"></a>
+<span class="sourceLineNo">835</span>      bucketQueue.add(bucketMulti);<a name="line.835"></a>
+<span class="sourceLineNo">836</span>      bucketQueue.add(bucketMemory);<a name="line.836"></a>
+<span class="sourceLineNo">837</span><a name="line.837"></a>
+<span class="sourceLineNo">838</span>      int remainingBuckets = 3;<a name="line.838"></a>
+<span class="sourceLineNo">839</span>      long bytesFreed = 0;<a name="line.839"></a>
+<span class="sourceLineNo">840</span><a name="line.840"></a>
+<span class="sourceLineNo">841</span>      BucketEntryGroup bucketGroup;<a name="line.841"></a>
+<span class="sourceLineNo">842</span>      while ((bucketGroup = bucketQueue.poll()) != null) {<a name="line.842"></a>
+<span class="sourceLineNo">843</span>        long overflow = bucketGroup.overflow();<a name="line.843"></a>
+<span class="sourceLineNo">844</span>        if (overflow &gt; 0) {<a name="line.844"></a>
+<span class="sourceLineNo">845</span>          long bucketBytesToFree = Math.min(overflow,<a name="line.845"></a>
+<span class="sourceLineNo">846</span>              (bytesToFreeWithoutExtra - bytesFreed) / remainingBuckets);<a name="line.846"></a>
+<span class="sourceLineNo">847</span>          bytesFreed += bucketGroup.free(bucketBytesToFree);<a name="line.847"></a>
+<span class="sourceLineNo">848</span>        }<a name="line.848"></a>
+<span class="sourceLineNo">849</span>        remainingBuckets--;<a name="line.849"></a>
+<span class="sourceLineNo">850</span>      }<a name="line.850"></a>
+<span class="sourceLineNo">851</span><a name="line.851"></a>
+<span class="sourceLineNo">852</span>      // Check and free if there are buckets that still need freeing of space<a name="line.852"></a>
+<span class="sourceLineNo">853</span>      if (bucketSizesAboveThresholdCount(minFactor) &gt; 0) {<a name="line.853"></a>
+<span class="sourceLineNo">854</span>        bucketQueue.clear();<a name="line.854"></a>
+<span class="sourceLineNo">855</span>        remainingBuckets = 3;<a name="line.855"></a>
+<span class="sourceLineNo">856</span><a name="line.856"></a>
+<span class="sourceLineNo">857</span>        bucketQueue.add(bucketSingle);<a name="line.857"></a>
+<span class="sourceLineNo">858</span>        bucketQueue.add(bucketMulti);<a name="line.858"></a>
+<span class="sourceLineNo">859</span>        bucketQueue.add(bucketMemory);<a name="line.859"></a>
 <span class="sourceLineNo">860</span><a name="line.860"></a>
-<span class="sourceLineNo">861</span>      // Even after the above free we might still need freeing because of the<a name="line.861"></a>
-<span class="sourceLineNo">862</span>      // De-fragmentation of the buckets (also called Slab Calcification problem), i.e<a name="line.862"></a>
-<span class="sourceLineNo">863</span>      // there might be some buckets where the occupancy is very sparse and thus are not<a name="line.863"></a>
-<span class="sourceLineNo">864</span>      // yielding the free for the other bucket sizes, the fix for this to evict some<a name="line.864"></a>
-<span class="sourceLineNo">865</span>      // of the buckets, we do this by evicting the buckets that are least fulled<a name="line.865"></a>
-<span class="sourceLineNo">866</span>      freeEntireBuckets(DEFAULT_FREE_ENTIRE_BLOCK_FACTOR *<a name="line.866"></a>
-<span class="sourceLineNo">867</span>          bucketSizesAboveThresholdCount(1.0f));<a name="line.867"></a>
-<span class="sourceLineNo">868</span><a name="line.868"></a>
-<span class="sourceLineNo">869</span>      if (LOG.isDebugEnabled()) {<a name="line.869"></a>
-<span class="sourceLineNo">870</span>        long single = bucketSingle.totalSize();<a name="line.870"></a>
-<span class="sourceLineNo">871</span>        long multi = bucketMulti.totalSize();<a name="line.871"></a>
-<span class="sourceLineNo">872</span>        long memory = bucketMemory.totalSize();<a name="line.872"></a>
-<span class="sourceLineNo">873</span>        if (LOG.isDebugEnabled()) {<a name="line.873"></a>
-<span class="sourceLineNo">874</span>          LOG.debug("Bucket cache free space completed; " + "freed="<a name="line.874"></a>
-<span class="sourceLineNo">875</span>            + StringUtils.byteDesc(bytesFreed) + ", " + "total="<a name="line.875"></a>
-<span class="sourceLineNo">876</span>            + StringUtils.byteDesc(totalSize) + ", " + "single="<a name="line.876"></a>
-<span class="sourceLineNo">877</span>            + StringUtils.byteDesc(single) + ", " + "multi="<a name="line.877"></a>
-<span class="sourceLineNo">878</span>            + StringUtils.byteDesc(multi) + ", " + "memory="<a name="line.878"></a>
-<span class="sourceLineNo">879</span>            + StringUtils.byteDesc(memory));<a name="line.879"></a>
-<span class="sourceLineNo">880</span>        }<a name="line.880"></a>
-<span class="sourceLineNo">881</span>      }<a name="line.881"></a>
-<span class="sourceLineNo">882</span><a name="line.882"></a>
-<span class="sourceLineNo">883</span>    } catch (Throwable t) {<a name="line.883"></a>
-<span class="sourceLineNo">884</span>      LOG.warn("Failed freeing space", t);<a name="line.884"></a>
-<span class="sourceLineNo">885</span>    } finally {<a name="line.885"></a>
-<span class="sourceLineNo">886</span>      cacheStats.evict();<a name="line.886"></a>
-<span class="sourceLineNo">887</span>      freeInProgress = false;<a name="line.887"></a>
-<span class="sourceLineNo">888</span>      freeSpaceLock.unlock();<a name="line.888"></a>
-<span class="sourceLineNo">889</span>    }<a name="line.889"></a>
-<span class="sourceLineNo">890</span>  }<a name="line.890"></a>
-<span class="sourceLineNo">891</span><a name="line.891"></a>
-<span class="sourceLineNo">892</span>  // This handles flushing the RAM cache to IOEngine.<a name="line.892"></a>
-<span class="sourceLineNo">893</span>  @VisibleForTesting<a name="line.893"></a>
-<span class="sourceLineNo">894</span>  class WriterThread extends HasThread {<a name="line.894"></a>
-<span class="sourceLineNo">895</span>    private final BlockingQueue&lt;RAMQueueEntry&gt; inputQueue;<a name="line.895"></a>
-<span class="sourceLineNo">896</span>    private volatile boolean writerEnabled = true;<a name="line.896"></a>
-<span class="sourceLineNo">897</span><a name="line.897"></a>
-<span class="sourceLineNo">898</span>    WriterThread(BlockingQueue&lt;RAMQueueEntry&gt; queue) {<a name="line.898"></a>
-<span class="sourceLineNo">899</span>      super("BucketCacheWriterThread");<a name="line.899"></a>
-<span class="sourceLineNo">900</span>      this.inputQueue = queue;<a nam

<TRUNCATED>

[17/50] hbase-site git commit: Published site at 26babcf013de696b899d76a3c39434b794440d8d.

Posted by gi...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html
----------------------------------------------------------------------
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html b/devapidocs/src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html
index cabb570..90f3b1e 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.LimitFields.html
@@ -107,660 +107,661 @@
 <span class="sourceLineNo">099</span><a name="line.99"></a>
 <span class="sourceLineNo">100</span>  private Cell lastPeekedCell = null;<a name="line.100"></a>
 <span class="sourceLineNo">101</span><a name="line.101"></a>
-<span class="sourceLineNo">102</span>  /**<a name="line.102"></a>
-<span class="sourceLineNo">103</span>   * Tracks the relevant server side metrics during scans. null when metrics should not be tracked<a name="line.103"></a>
-<span class="sourceLineNo">104</span>   */<a name="line.104"></a>
-<span class="sourceLineNo">105</span>  final ServerSideScanMetrics metrics;<a name="line.105"></a>
-<span class="sourceLineNo">106</span><a name="line.106"></a>
-<span class="sourceLineNo">107</span>  ScannerContext(boolean keepProgress, LimitFields limitsToCopy, boolean trackMetrics) {<a name="line.107"></a>
-<span class="sourceLineNo">108</span>    this.limits = new LimitFields();<a name="line.108"></a>
-<span class="sourceLineNo">109</span>    if (limitsToCopy != null) {<a name="line.109"></a>
-<span class="sourceLineNo">110</span>      this.limits.copy(limitsToCopy);<a name="line.110"></a>
-<span class="sourceLineNo">111</span>    }<a name="line.111"></a>
+<span class="sourceLineNo">102</span>  // Set this to true will have the same behavior with reaching the time limit.<a name="line.102"></a>
+<span class="sourceLineNo">103</span>  // This is used when you want to make the current RSRpcService.scan returns immediately. For<a name="line.103"></a>
+<span class="sourceLineNo">104</span>  // example, when we want to switch from pread to stream, we can only do it after the rpc call is<a name="line.104"></a>
+<span class="sourceLineNo">105</span>  // returned.<a name="line.105"></a>
+<span class="sourceLineNo">106</span>  private boolean returnImmediately;<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>   * Tracks the relevant server side metrics during scans. null when metrics should not be tracked<a name="line.109"></a>
+<span class="sourceLineNo">110</span>   */<a name="line.110"></a>
+<span class="sourceLineNo">111</span>  final ServerSideScanMetrics metrics;<a name="line.111"></a>
 <span class="sourceLineNo">112</span><a name="line.112"></a>
-<span class="sourceLineNo">113</span>    // Progress fields are initialized to 0<a name="line.113"></a>
-<span class="sourceLineNo">114</span>    progress = new ProgressFields(0, 0, 0);<a name="line.114"></a>
-<span class="sourceLineNo">115</span><a name="line.115"></a>
-<span class="sourceLineNo">116</span>    this.keepProgress = keepProgress;<a name="line.116"></a>
-<span class="sourceLineNo">117</span>    this.scannerState = DEFAULT_STATE;<a name="line.117"></a>
-<span class="sourceLineNo">118</span>    this.metrics = trackMetrics ? new ServerSideScanMetrics() : null;<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>  boolean isTrackingMetrics() {<a name="line.121"></a>
-<span class="sourceLineNo">122</span>    return this.metrics != null;<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>   * Get the metrics instance. Should only be called after a call to {@link #isTrackingMetrics()}<a name="line.126"></a>
-<span class="sourceLineNo">127</span>   * has been made to confirm that metrics are indeed being tracked.<a name="line.127"></a>
-<span class="sourceLineNo">128</span>   * @return {@link ServerSideScanMetrics} instance that is tracking metrics for this scan<a name="line.128"></a>
-<span class="sourceLineNo">129</span>   */<a name="line.129"></a>
-<span class="sourceLineNo">130</span>  ServerSideScanMetrics getMetrics() {<a name="line.130"></a>
-<span class="sourceLineNo">131</span>    assert isTrackingMetrics();<a name="line.131"></a>
-<span class="sourceLineNo">132</span>    return this.metrics;<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>   * @return true if the progress tracked so far in this instance will be considered during an<a name="line.136"></a>
-<span class="sourceLineNo">137</span>   *         invocation of {@link InternalScanner#next(java.util.List)} or<a name="line.137"></a>
-<span class="sourceLineNo">138</span>   *         {@link RegionScanner#next(java.util.List)}. false when the progress tracked so far<a name="line.138"></a>
-<span class="sourceLineNo">139</span>   *         should not be considered and should instead be wiped away via {@link #clearProgress()}<a name="line.139"></a>
-<span class="sourceLineNo">140</span>   */<a name="line.140"></a>
-<span class="sourceLineNo">141</span>  boolean getKeepProgress() {<a name="line.141"></a>
-<span class="sourceLineNo">142</span>    return keepProgress;<a name="line.142"></a>
-<span class="sourceLineNo">143</span>  }<a name="line.143"></a>
-<span class="sourceLineNo">144</span><a name="line.144"></a>
-<span class="sourceLineNo">145</span>  void setKeepProgress(boolean keepProgress) {<a name="line.145"></a>
-<span class="sourceLineNo">146</span>    this.keepProgress = keepProgress;<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>   * Progress towards the batch limit has been made. Increment internal tracking of batch progress<a name="line.150"></a>
-<span class="sourceLineNo">151</span>   */<a name="line.151"></a>
-<span class="sourceLineNo">152</span>  void incrementBatchProgress(int batch) {<a name="line.152"></a>
-<span class="sourceLineNo">153</span>    int currentBatch = progress.getBatch();<a name="line.153"></a>
-<span class="sourceLineNo">154</span>    progress.setBatch(currentBatch + batch);<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>   * Progress towards the size limit has been made. Increment internal tracking of size progress<a name="line.158"></a>
-<span class="sourceLineNo">159</span>   */<a name="line.159"></a>
-<span class="sourceLineNo">160</span>  void incrementSizeProgress(long dataSize, long heapSize) {<a name="line.160"></a>
-<span class="sourceLineNo">161</span>    long curDataSize = progress.getDataSize();<a name="line.161"></a>
-<span class="sourceLineNo">162</span>    progress.setDataSize(curDataSize + dataSize);<a name="line.162"></a>
-<span class="sourceLineNo">163</span>    long curHeapSize = progress.getHeapSize();<a name="line.163"></a>
-<span class="sourceLineNo">164</span>    progress.setHeapSize(curHeapSize + heapSize);<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>  int getBatchProgress() {<a name="line.167"></a>
-<span class="sourceLineNo">168</span>    return progress.getBatch();<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>  long getDataSizeProgress() {<a name="line.171"></a>
-<span class="sourceLineNo">172</span>    return progress.getDataSize();<a name="line.172"></a>
-<span class="sourceLineNo">173</span>  }<a name="line.173"></a>
-<span class="sourceLineNo">174</span><a name="line.174"></a>
-<span class="sourceLineNo">175</span>  long getHeapSizeProgress() {<a name="line.175"></a>
-<span class="sourceLineNo">176</span>    return progress.getHeapSize();<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>  void setProgress(int batchProgress, long sizeProgress, long heapSizeProgress) {<a name="line.179"></a>
-<span class="sourceLineNo">180</span>    setBatchProgress(batchProgress);<a name="line.180"></a>
-<span class="sourceLineNo">181</span>    setSizeProgress(sizeProgress, heapSizeProgress);<a name="line.181"></a>
-<span class="sourceLineNo">182</span>  }<a name="line.182"></a>
-<span class="sourceLineNo">183</span><a name="line.183"></a>
-<span class="sourceLineNo">184</span>  void setSizeProgress(long dataSizeProgress, long heapSizeProgress) {<a name="line.184"></a>
-<span class="sourceLineNo">185</span>    progress.setDataSize(dataSizeProgress);<a name="line.185"></a>
-<span class="sourceLineNo">186</span>    progress.setHeapSize(heapSizeProgress);<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>  void setBatchProgress(int batchProgress) {<a name="line.189"></a>
-<span class="sourceLineNo">190</span>    progress.setBatch(batchProgress);<a name="line.190"></a>
-<span class="sourceLineNo">191</span>  }<a name="line.191"></a>
-<span class="sourceLineNo">192</span><a name="line.192"></a>
-<span class="sourceLineNo">193</span>  /**<a name="line.193"></a>
-<span class="sourceLineNo">194</span>   * Clear away any progress that has been made so far. All progress fields are reset to initial<a name="line.194"></a>
-<span class="sourceLineNo">195</span>   * values<a name="line.195"></a>
-<span class="sourceLineNo">196</span>   */<a name="line.196"></a>
-<span class="sourceLineNo">197</span>  void clearProgress() {<a name="line.197"></a>
-<span class="sourceLineNo">198</span>    progress.setFields(0, 0, 0);<a name="line.198"></a>
-<span class="sourceLineNo">199</span>  }<a name="line.199"></a>
-<span class="sourceLineNo">200</span><a name="line.200"></a>
-<span class="sourceLineNo">201</span>  /**<a name="line.201"></a>
-<span class="sourceLineNo">202</span>   * Note that this is not a typical setter. This setter returns the {@link NextState} that was<a name="line.202"></a>
-<span class="sourceLineNo">203</span>   * passed in so that methods can be invoked against the new state. Furthermore, this pattern<a name="line.203"></a>
-<span class="sourceLineNo">204</span>   * allows the {@link NoLimitScannerContext} to cleanly override this setter and simply return the<a name="line.204"></a>
-<span class="sourceLineNo">205</span>   * new state, thus preserving the immutability of {@link NoLimitScannerContext}<a name="line.205"></a>
-<span class="sourceLineNo">206</span>   * @param state<a name="line.206"></a>
-<span class="sourceLineNo">207</span>   * @return The state that was passed in.<a name="line.207"></a>
-<span class="sourceLineNo">208</span>   */<a name="line.208"></a>
-<span class="sourceLineNo">209</span>  NextState setScannerState(NextState state) {<a name="line.209"></a>
-<span class="sourceLineNo">210</span>    if (!NextState.isValidState(state)) {<a name="line.210"></a>
-<span class="sourceLineNo">211</span>      throw new IllegalArgumentException("Cannot set to invalid state: " + state);<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>    this.scannerState = state;<a name="line.214"></a>
-<span class="sourceLineNo">215</span>    return state;<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>  /**<a name="line.218"></a>
-<span class="sourceLineNo">219</span>   * @return true when we have more cells for the current row. This usually because we have reached<a name="line.219"></a>
-<span class="sourceLineNo">220</span>   *         a limit in the middle of a row<a name="line.220"></a>
-<span class="sourceLineNo">221</span>   */<a name="line.221"></a>
-<span class="sourceLineNo">222</span>  boolean mayHaveMoreCellsInRow() {<a name="line.222"></a>
-<span class="sourceLineNo">223</span>    return scannerState == NextState.SIZE_LIMIT_REACHED_MID_ROW ||<a name="line.223"></a>
-<span class="sourceLineNo">224</span>        scannerState == NextState.TIME_LIMIT_REACHED_MID_ROW ||<a name="line.224"></a>
-<span class="sourceLineNo">225</span>        scannerState == NextState.BATCH_LIMIT_REACHED;<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>  /**<a name="line.228"></a>
-<span class="sourceLineNo">229</span>   * @param checkerScope<a name="line.229"></a>
-<span class="sourceLineNo">230</span>   * @return true if the batch limit can be enforced in the checker's scope<a name="line.230"></a>
-<span class="sourceLineNo">231</span>   */<a name="line.231"></a>
-<span class="sourceLineNo">232</span>  boolean hasBatchLimit(LimitScope checkerScope) {<a name="line.232"></a>
-<span class="sourceLineNo">233</span>    return limits.canEnforceBatchLimitFromScope(checkerScope) &amp;&amp; limits.getBatch() &gt; 0;<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>   * @param checkerScope<a name="line.237"></a>
-<span class="sourceLineNo">238</span>   * @return true if the size limit can be enforced in the checker's scope<a name="line.238"></a>
-<span class="sourceLineNo">239</span>   */<a name="line.239"></a>
-<span class="sourceLineNo">240</span>  boolean hasSizeLimit(LimitScope checkerScope) {<a name="line.240"></a>
-<span class="sourceLineNo">241</span>    return limits.canEnforceSizeLimitFromScope(checkerScope)<a name="line.241"></a>
-<span class="sourceLineNo">242</span>        &amp;&amp; (limits.getDataSize() &gt; 0 || limits.getHeapSize() &gt; 0);<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>  /**<a name="line.245"></a>
-<span class="sourceLineNo">246</span>   * @param checkerScope<a name="line.246"></a>
-<span class="sourceLineNo">247</span>   * @return true if the time limit can be enforced in the checker's scope<a name="line.247"></a>
-<span class="sourceLineNo">248</span>   */<a name="line.248"></a>
-<span class="sourceLineNo">249</span>  boolean hasTimeLimit(LimitScope checkerScope) {<a name="line.249"></a>
-<span class="sourceLineNo">250</span>    return limits.canEnforceTimeLimitFromScope(checkerScope) &amp;&amp; limits.getTime() &gt; 0;<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>   * @param checkerScope<a name="line.254"></a>
-<span class="sourceLineNo">255</span>   * @return true if any limit can be enforced within the checker's scope<a name="line.255"></a>
-<span class="sourceLineNo">256</span>   */<a name="line.256"></a>
-<span class="sourceLineNo">257</span>  boolean hasAnyLimit(LimitScope checkerScope) {<a name="line.257"></a>
-<span class="sourceLineNo">258</span>    return hasBatchLimit(checkerScope) || hasSizeLimit(checkerScope) || hasTimeLimit(checkerScope);<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>  /**<a name="line.261"></a>
-<span class="sourceLineNo">262</span>   * @param scope The scope in which the size limit will be enforced<a name="line.262"></a>
+<span class="sourceLineNo">113</span>  ScannerContext(boolean keepProgress, LimitFields limitsToCopy, boolean trackMetrics) {<a name="line.113"></a>
+<span class="sourceLineNo">114</span>    this.limits = new LimitFields();<a name="line.114"></a>
+<span class="sourceLineNo">115</span>    if (limitsToCopy != null) {<a name="line.115"></a>
+<span class="sourceLineNo">116</span>      this.limits.copy(limitsToCopy);<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>    // Progress fields are initialized to 0<a name="line.119"></a>
+<span class="sourceLineNo">120</span>    progress = new ProgressFields(0, 0, 0);<a name="line.120"></a>
+<span class="sourceLineNo">121</span><a name="line.121"></a>
+<span class="sourceLineNo">122</span>    this.keepProgress = keepProgress;<a name="line.122"></a>
+<span class="sourceLineNo">123</span>    this.scannerState = DEFAULT_STATE;<a name="line.123"></a>
+<span class="sourceLineNo">124</span>    this.metrics = trackMetrics ? new ServerSideScanMetrics() : null;<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>  boolean isTrackingMetrics() {<a name="line.127"></a>
+<span class="sourceLineNo">128</span>    return this.metrics != null;<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>   * Get the metrics instance. Should only be called after a call to {@link #isTrackingMetrics()}<a name="line.132"></a>
+<span class="sourceLineNo">133</span>   * has been made to confirm that metrics are indeed being tracked.<a name="line.133"></a>
+<span class="sourceLineNo">134</span>   * @return {@link ServerSideScanMetrics} instance that is tracking metrics for this scan<a name="line.134"></a>
+<span class="sourceLineNo">135</span>   */<a name="line.135"></a>
+<span class="sourceLineNo">136</span>  ServerSideScanMetrics getMetrics() {<a name="line.136"></a>
+<span class="sourceLineNo">137</span>    assert isTrackingMetrics();<a name="line.137"></a>
+<span class="sourceLineNo">138</span>    return this.metrics;<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>   * @return true if the progress tracked so far in this instance will be considered during an<a name="line.142"></a>
+<span class="sourceLineNo">143</span>   *         invocation of {@link InternalScanner#next(java.util.List)} or<a name="line.143"></a>
+<span class="sourceLineNo">144</span>   *         {@link RegionScanner#next(java.util.List)}. false when the progress tracked so far<a name="line.144"></a>
+<span class="sourceLineNo">145</span>   *         should not be considered and should instead be wiped away via {@link #clearProgress()}<a name="line.145"></a>
+<span class="sourceLineNo">146</span>   */<a name="line.146"></a>
+<span class="sourceLineNo">147</span>  boolean getKeepProgress() {<a name="line.147"></a>
+<span class="sourceLineNo">148</span>    return keepProgress;<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>  void setKeepProgress(boolean keepProgress) {<a name="line.151"></a>
+<span class="sourceLineNo">152</span>    this.keepProgress = keepProgress;<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>   * Progress towards the batch limit has been made. Increment internal tracking of batch progress<a name="line.156"></a>
+<span class="sourceLineNo">157</span>   */<a name="line.157"></a>
+<span class="sourceLineNo">158</span>  void incrementBatchProgress(int batch) {<a name="line.158"></a>
+<span class="sourceLineNo">159</span>    int currentBatch = progress.getBatch();<a name="line.159"></a>
+<span class="sourceLineNo">160</span>    progress.setBatch(currentBatch + batch);<a name="line.160"></a>
+<span class="sourceLineNo">161</span>  }<a name="line.161"></a>
+<span class="sourceLineNo">162</span><a name="line.162"></a>
+<span class="sourceLineNo">163</span>  /**<a name="line.163"></a>
+<span class="sourceLineNo">164</span>   * Progress towards the size limit has been made. Increment internal tracking of size progress<a name="line.164"></a>
+<span class="sourceLineNo">165</span>   */<a name="line.165"></a>
+<span class="sourceLineNo">166</span>  void incrementSizeProgress(long dataSize, long heapSize) {<a name="line.166"></a>
+<span class="sourceLineNo">167</span>    long curDataSize = progress.getDataSize();<a name="line.167"></a>
+<span class="sourceLineNo">168</span>    progress.setDataSize(curDataSize + dataSize);<a name="line.168"></a>
+<span class="sourceLineNo">169</span>    long curHeapSize = progress.getHeapSize();<a name="line.169"></a>
+<span class="sourceLineNo">170</span>    progress.setHeapSize(curHeapSize + heapSize);<a name="line.170"></a>
+<span class="sourceLineNo">171</span>  }<a name="line.171"></a>
+<span class="sourceLineNo">172</span><a name="line.172"></a>
+<span class="sourceLineNo">173</span>  int getBatchProgress() {<a name="line.173"></a>
+<span class="sourceLineNo">174</span>    return progress.getBatch();<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>  long getDataSizeProgress() {<a name="line.177"></a>
+<span class="sourceLineNo">178</span>    return progress.getDataSize();<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>  long getHeapSizeProgress() {<a name="line.181"></a>
+<span class="sourceLineNo">182</span>    return progress.getHeapSize();<a name="line.182"></a>
+<span class="sourceLineNo">183</span>  }<a name="line.183"></a>
+<span class="sourceLineNo">184</span><a name="line.184"></a>
+<span class="sourceLineNo">185</span>  void setProgress(int batchProgress, long sizeProgress, long heapSizeProgress) {<a name="line.185"></a>
+<span class="sourceLineNo">186</span>    setBatchProgress(batchProgress);<a name="line.186"></a>
+<span class="sourceLineNo">187</span>    setSizeProgress(sizeProgress, heapSizeProgress);<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>  void setSizeProgress(long dataSizeProgress, long heapSizeProgress) {<a name="line.190"></a>
+<span class="sourceLineNo">191</span>    progress.setDataSize(dataSizeProgress);<a name="line.191"></a>
+<span class="sourceLineNo">192</span>    progress.setHeapSize(heapSizeProgress);<a name="line.192"></a>
+<span class="sourceLineNo">193</span>  }<a name="line.193"></a>
+<span class="sourceLineNo">194</span><a name="line.194"></a>
+<span class="sourceLineNo">195</span>  void setBatchProgress(int batchProgress) {<a name="line.195"></a>
+<span class="sourceLineNo">196</span>    progress.setBatch(batchProgress);<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>   * Clear away any progress that has been made so far. All progress fields are reset to initial<a name="line.200"></a>
+<span class="sourceLineNo">201</span>   * values<a name="line.201"></a>
+<span class="sourceLineNo">202</span>   */<a name="line.202"></a>
+<span class="sourceLineNo">203</span>  void clearProgress() {<a name="line.203"></a>
+<span class="sourceLineNo">204</span>    progress.setFields(0, 0, 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>  /**<a name="line.207"></a>
+<span class="sourceLineNo">208</span>   * Note that this is not a typical setter. This setter returns the {@link NextState} that was<a name="line.208"></a>
+<span class="sourceLineNo">209</span>   * passed in so that methods can be invoked against the new state. Furthermore, this pattern<a name="line.209"></a>
+<span class="sourceLineNo">210</span>   * allows the {@link NoLimitScannerContext} to cleanly override this setter and simply return the<a name="line.210"></a>
+<span class="sourceLineNo">211</span>   * new state, thus preserving the immutability of {@link NoLimitScannerContext}<a name="line.211"></a>
+<span class="sourceLineNo">212</span>   * @param state<a name="line.212"></a>
+<span class="sourceLineNo">213</span>   * @return The state that was passed in.<a name="line.213"></a>
+<span class="sourceLineNo">214</span>   */<a name="line.214"></a>
+<span class="sourceLineNo">215</span>  NextState setScannerState(NextState state) {<a name="line.215"></a>
+<span class="sourceLineNo">216</span>    if (!NextState.isValidState(state)) {<a name="line.216"></a>
+<span class="sourceLineNo">217</span>      throw new IllegalArgumentException("Cannot set to invalid state: " + state);<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>    this.scannerState = state;<a name="line.220"></a>
+<span class="sourceLineNo">221</span>    return state;<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>  /**<a name="line.224"></a>
+<span class="sourceLineNo">225</span>   * @return true when we have more cells for the current row. This usually because we have reached<a name="line.225"></a>
+<span class="sourceLineNo">226</span>   *         a limit in the middle of a row<a name="line.226"></a>
+<span class="sourceLineNo">227</span>   */<a name="line.227"></a>
+<span class="sourceLineNo">228</span>  boolean mayHaveMoreCellsInRow() {<a name="line.228"></a>
+<span class="sourceLineNo">229</span>    return scannerState == NextState.SIZE_LIMIT_REACHED_MID_ROW ||<a name="line.229"></a>
+<span class="sourceLineNo">230</span>        scannerState == NextState.TIME_LIMIT_REACHED_MID_ROW ||<a name="line.230"></a>
+<span class="sourceLineNo">231</span>        scannerState == NextState.BATCH_LIMIT_REACHED;<a name="line.231"></a>
+<span class="sourceLineNo">232</span>  }<a name="line.232"></a>
+<span class="sourceLineNo">233</span><a name="line.233"></a>
+<span class="sourceLineNo">234</span>  /**<a name="line.234"></a>
+<span class="sourceLineNo">235</span>   * @param checkerScope<a name="line.235"></a>
+<span class="sourceLineNo">236</span>   * @return true if the batch limit can be enforced in the checker's scope<a name="line.236"></a>
+<span class="sourceLineNo">237</span>   */<a name="line.237"></a>
+<span class="sourceLineNo">238</span>  boolean hasBatchLimit(LimitScope checkerScope) {<a name="line.238"></a>
+<span class="sourceLineNo">239</span>    return limits.canEnforceBatchLimitFromScope(checkerScope) &amp;&amp; limits.getBatch() &gt; 0;<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>   * @param checkerScope<a name="line.243"></a>
+<span class="sourceLineNo">244</span>   * @return true if the size limit can be enforced in the checker's scope<a name="line.244"></a>
+<span class="sourceLineNo">245</span>   */<a name="line.245"></a>
+<span class="sourceLineNo">246</span>  boolean hasSizeLimit(LimitScope checkerScope) {<a name="line.246"></a>
+<span class="sourceLineNo">247</span>    return limits.canEnforceSizeLimitFromScope(checkerScope)<a name="line.247"></a>
+<span class="sourceLineNo">248</span>        &amp;&amp; (limits.getDataSize() &gt; 0 || limits.getHeapSize() &gt; 0);<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>
+<span class="sourceLineNo">252</span>   * @param checkerScope<a name="line.252"></a>
+<span class="sourceLineNo">253</span>   * @return true if the time limit can be enforced in the checker's scope<a name="line.253"></a>
+<span class="sourceLineNo">254</span>   */<a name="line.254"></a>
+<span class="sourceLineNo">255</span>  boolean hasTimeLimit(LimitScope checkerScope) {<a name="line.255"></a>
+<span class="sourceLineNo">256</span>    return limits.canEnforceTimeLimitFromScope(checkerScope) &amp;&amp;<a name="line.256"></a>
+<span class="sourceLineNo">257</span>      (limits.getTime() &gt; 0 || returnImmediately);<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>   * @param checkerScope<a name="line.261"></a>
+<span class="sourceLineNo">262</span>   * @return true if any limit can be enforced within the checker's scope<a name="line.262"></a>
 <span class="sourceLineNo">263</span>   */<a name="line.263"></a>
-<span class="sourceLineNo">264</span>  void setSizeLimitScope(LimitScope scope) {<a name="line.264"></a>
-<span class="sourceLineNo">265</span>    limits.setSizeScope(scope);<a name="line.265"></a>
+<span class="sourceLineNo">264</span>  boolean hasAnyLimit(LimitScope checkerScope) {<a name="line.264"></a>
+<span class="sourceLineNo">265</span>    return hasBatchLimit(checkerScope) || hasSizeLimit(checkerScope) || hasTimeLimit(checkerScope);<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>  /**<a name="line.268"></a>
-<span class="sourceLineNo">269</span>   * @param scope The scope in which the time limit will be enforced<a name="line.269"></a>
+<span class="sourceLineNo">269</span>   * @param scope The scope in which the size limit will be enforced<a name="line.269"></a>
 <span class="sourceLineNo">270</span>   */<a name="line.270"></a>
-<span class="sourceLineNo">271</span>  void setTimeLimitScope(LimitScope scope) {<a name="line.271"></a>
-<span class="sourceLineNo">272</span>    limits.setTimeScope(scope);<a name="line.272"></a>
+<span class="sourceLineNo">271</span>  void setSizeLimitScope(LimitScope scope) {<a name="line.271"></a>
+<span class="sourceLineNo">272</span>    limits.setSizeScope(scope);<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>  int getBatchLimit() {<a name="line.275"></a>
-<span class="sourceLineNo">276</span>    return limits.getBatch();<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>  long getDataSizeLimit() {<a name="line.279"></a>
-<span class="sourceLineNo">280</span>    return limits.getDataSize();<a name="line.280"></a>
-<span class="sourceLineNo">281</span>  }<a name="line.281"></a>
-<span class="sourceLineNo">282</span><a name="line.282"></a>
-<span class="sourceLineNo">283</span>  long getTimeLimit() {<a name="line.283"></a>
-<span class="sourceLineNo">284</span>    return limits.getTime();<a name="line.284"></a>
-<span class="sourceLineNo">285</span>  }<a name="line.285"></a>
-<span class="sourceLineNo">286</span><a name="line.286"></a>
-<span class="sourceLineNo">287</span>  /**<a name="line.287"></a>
-<span class="sourceLineNo">288</span>   * @param checkerScope The scope that the limit is being checked from<a name="line.288"></a>
-<span class="sourceLineNo">289</span>   * @return true when the limit is enforceable from the checker's scope and it has been reached<a name="line.289"></a>
-<span class="sourceLineNo">290</span>   */<a name="line.290"></a>
-<span class="sourceLineNo">291</span>  boolean checkBatchLimit(LimitScope checkerScope) {<a name="line.291"></a>
-<span class="sourceLineNo">292</span>    return hasBatchLimit(checkerScope) &amp;&amp; progress.getBatch() &gt;= limits.getBatch();<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>  /**<a name="line.295"></a>
-<span class="sourceLineNo">296</span>   * @param checkerScope The scope that the limit is being checked from<a name="line.296"></a>
-<span class="sourceLineNo">297</span>   * @return true when the limit is enforceable from the checker's scope and it has been reached<a name="line.297"></a>
-<span class="sourceLineNo">298</span>   */<a name="line.298"></a>
-<span class="sourceLineNo">299</span>  boolean checkSizeLimit(LimitScope checkerScope) {<a name="line.299"></a>
-<span class="sourceLineNo">300</span>    return hasSizeLimit(checkerScope) &amp;&amp; (progress.getDataSize() &gt;= limits.getDataSize()<a name="line.300"></a>
-<span class="sourceLineNo">301</span>        || progress.getHeapSize() &gt;= limits.getHeapSize());<a name="line.301"></a>
-<span class="sourceLineNo">302</span>  }<a name="line.302"></a>
-<span class="sourceLineNo">303</span><a name="line.303"></a>
-<span class="sourceLineNo">304</span>  /**<a name="line.304"></a>
-<span class="sourceLineNo">305</span>   * @param checkerScope The scope that the limit is being checked from. The time limit is always<a name="line.305"></a>
-<span class="sourceLineNo">306</span>   *          checked against {@link System#currentTimeMillis()}<a name="line.306"></a>
-<span class="sourceLineNo">307</span>   * @return true when the limit is enforceable from the checker's scope and it has been reached<a name="line.307"></a>
-<span class="sourceLineNo">308</span>   */<a name="line.308"></a>
-<span class="sourceLineNo">309</span>  boolean checkTimeLimit(LimitScope checkerScope) {<a name="line.309"></a>
-<span class="sourceLineNo">310</span>    return hasTimeLimit(checkerScope) &amp;&amp; (System.currentTimeMillis() &gt;= limits.getTime());<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>   * @param checkerScope The scope that the limits are being checked from<a name="line.314"></a>
-<span class="sourceLineNo">315</span>   * @return true when some limit is enforceable from the checker's scope and it has been reached<a name="line.315"></a>
-<span class="sourceLineNo">316</span>   */<a name="line.316"></a>
-<span class="sourceLineNo">317</span>  boolean checkAnyLimitReached(LimitScope checkerScope) {<a name="line.317"></a>
-<span class="sourceLineNo">318</span>    return checkSizeLimit(checkerScope) || checkBatchLimit(checkerScope)<a name="line.318"></a>
-<span class="sourceLineNo">319</span>        || checkTimeLimit(checkerScope);<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>  Cell getLastPeekedCell() {<a name="line.322"></a>
-<span class="sourceLineNo">323</span>    return lastPeekedCell;<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>  void setLastPeekedCell(Cell lastPeekedCell) {<a name="line.326"></a>
-<span class="sourceLineNo">327</span>    this.lastPeekedCell = lastPeekedCell;<a name="line.327"></a>
+<span class="sourceLineNo">275</span>  /**<a name="line.275"></a>
+<span class="sourceLineNo">276</span>   * @param scope The scope in which the time limit will be enforced<a name="line.276"></a>
+<span class="sourceLineNo">277</span>   */<a name="line.277"></a>
+<span class="sourceLineNo">278</span>  void setTimeLimitScope(LimitScope scope) {<a name="line.278"></a>
+<span class="sourceLineNo">279</span>    limits.setTimeScope(scope);<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>  int getBatchLimit() {<a name="line.282"></a>
+<span class="sourceLineNo">283</span>    return limits.getBatch();<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>  long getDataSizeLimit() {<a name="line.286"></a>
+<span class="sourceLineNo">287</span>    return limits.getDataSize();<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>  long getTimeLimit() {<a name="line.290"></a>
+<span class="sourceLineNo">291</span>    return limits.getTime();<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>   * @param checkerScope The scope that the limit is being checked from<a name="line.295"></a>
+<span class="sourceLineNo">296</span>   * @return true when the limit is enforceable from the checker's scope and it has been reached<a name="line.296"></a>
+<span class="sourceLineNo">297</span>   */<a name="line.297"></a>
+<span class="sourceLineNo">298</span>  boolean checkBatchLimit(LimitScope checkerScope) {<a name="line.298"></a>
+<span class="sourceLineNo">299</span>    return hasBatchLimit(checkerScope) &amp;&amp; progress.getBatch() &gt;= limits.getBatch();<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 checkerScope The scope that the limit is being checked from<a name="line.303"></a>
+<span class="sourceLineNo">304</span>   * @return true when the limit is enforceable from the checker's scope and it has been reached<a name="line.304"></a>
+<span class="sourceLineNo">305</span>   */<a name="line.305"></a>
+<span class="sourceLineNo">306</span>  boolean checkSizeLimit(LimitScope checkerScope) {<a name="line.306"></a>
+<span class="sourceLineNo">307</span>    return hasSizeLimit(checkerScope) &amp;&amp; (progress.getDataSize() &gt;= limits.getDataSize()<a name="line.307"></a>
+<span class="sourceLineNo">308</span>        || progress.getHeapSize() &gt;= limits.getHeapSize());<a name="line.308"></a>
+<span class="sourceLineNo">309</span>  }<a name="line.309"></a>
+<span class="sourceLineNo">310</span><a name="line.310"></a>
+<span class="sourceLineNo">311</span>  /**<a name="line.311"></a>
+<span class="sourceLineNo">312</span>   * @param checkerScope The scope that the limit is being checked from. The time limit is always<a name="line.312"></a>
+<span class="sourceLineNo">313</span>   *          checked against {@link System#currentTimeMillis()}<a name="line.313"></a>
+<span class="sourceLineNo">314</span>   * @return true when the limit is enforceable from the checker's scope and it has been reached<a name="line.314"></a>
+<span class="sourceLineNo">315</span>   */<a name="line.315"></a>
+<span class="sourceLineNo">316</span>  boolean checkTimeLimit(LimitScope checkerScope) {<a name="line.316"></a>
+<span class="sourceLineNo">317</span>    return hasTimeLimit(checkerScope) &amp;&amp;<a name="line.317"></a>
+<span class="sourceLineNo">318</span>      (returnImmediately || System.currentTimeMillis() &gt;= limits.getTime());<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>   * @param checkerScope The scope that the limits are being checked from<a name="line.322"></a>
+<span class="sourceLineNo">323</span>   * @return true when some limit is enforceable from the checker's scope and it has been reached<a name="line.323"></a>
+<span class="sourceLineNo">324</span>   */<a name="line.324"></a>
+<span class="sourceLineNo">325</span>  boolean checkAnyLimitReached(LimitScope checkerScope) {<a name="line.325"></a>
+<span class="sourceLineNo">326</span>    return checkSizeLimit(checkerScope) || checkBatchLimit(checkerScope)<a name="line.326"></a>
+<span class="sourceLineNo">327</span>        || checkTimeLimit(checkerScope);<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>  @Override<a name="line.330"></a>
-<span class="sourceLineNo">331</span>  public String toString() {<a name="line.331"></a>
-<span class="sourceLineNo">332</span>    StringBuilder sb = new StringBuilder();<a name="line.332"></a>
-<span class="sourceLineNo">333</span>    sb.append("{");<a name="line.333"></a>
-<span class="sourceLineNo">334</span><a name="line.334"></a>
-<span class="sourceLineNo">335</span>    sb.append("limits:");<a name="line.335"></a>
-<span class="sourceLineNo">336</span>    sb.append(limits);<a name="line.336"></a>
+<span class="sourceLineNo">330</span>  Cell getLastPeekedCell() {<a name="line.330"></a>
+<span class="sourceLineNo">331</span>    return lastPeekedCell;<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>  void setLastPeekedCell(Cell lastPeekedCell) {<a name="line.334"></a>
+<span class="sourceLineNo">335</span>    this.lastPeekedCell = lastPeekedCell;<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>    sb.append(", progress:");<a name="line.338"></a>
-<span class="sourceLineNo">339</span>    sb.append(progress);<a name="line.339"></a>
-<span class="sourceLineNo">340</span><a name="line.340"></a>
-<span class="sourceLineNo">341</span>    sb.append(", keepProgress:");<a name="line.341"></a>
-<span class="sourceLineNo">342</span>    sb.append(keepProgress);<a name="line.342"></a>
-<span class="sourceLineNo">343</span><a name="line.343"></a>
-<span class="sourceLineNo">344</span>    sb.append(", state:");<a name="line.344"></a>
-<span class="sourceLineNo">345</span>    sb.append(scannerState);<a name="line.345"></a>
+<span class="sourceLineNo">338</span>  void returnImmediately() {<a name="line.338"></a>
+<span class="sourceLineNo">339</span>    this.returnImmediately = true;<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>  @Override<a name="line.342"></a>
+<span class="sourceLineNo">343</span>  public String toString() {<a name="line.343"></a>
+<span class="sourceLineNo">344</span>    StringBuilder sb = new StringBuilder();<a name="line.344"></a>
+<span class="sourceLineNo">345</span>    sb.append("{");<a name="line.345"></a>
 <span class="sourceLineNo">346</span><a name="line.346"></a>
-<span class="sourceLineNo">347</span>    sb.append("}");<a name="line.347"></a>
-<span class="sourceLineNo">348</span>    return sb.toString();<a name="line.348"></a>
-<span class="sourceLineNo">349</span>  }<a name="line.349"></a>
-<span class="sourceLineNo">350</span><a name="line.350"></a>
-<span class="sourceLineNo">351</span>  public static Builder newBuilder() {<a name="line.351"></a>
-<span class="sourceLineNo">352</span>    return new Builder();<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 static Builder newBuilder(boolean keepProgress) {<a name="line.355"></a>
-<span class="sourceLineNo">356</span>    return new Builder(keepProgress);<a name="line.356"></a>
-<span class="sourceLineNo">357</span>  }<a name="line.357"></a>
+<span class="sourceLineNo">347</span>    sb.append("limits:");<a name="line.347"></a>
+<span class="sourceLineNo">348</span>    sb.append(limits);<a name="line.348"></a>
+<span class="sourceLineNo">349</span><a name="line.349"></a>
+<span class="sourceLineNo">350</span>    sb.append(", progress:");<a name="line.350"></a>
+<span class="sourceLineNo">351</span>    sb.append(progress);<a name="line.351"></a>
+<span class="sourceLineNo">352</span><a name="line.352"></a>
+<span class="sourceLineNo">353</span>    sb.append(", keepProgress:");<a name="line.353"></a>
+<span class="sourceLineNo">354</span>    sb.append(keepProgress);<a name="line.354"></a>
+<span class="sourceLineNo">355</span><a name="line.355"></a>
+<span class="sourceLineNo">356</span>    sb.append(", state:");<a name="line.356"></a>
+<span class="sourceLineNo">357</span>    sb.append(scannerState);<a name="line.357"></a>
 <span class="sourceLineNo">358</span><a name="line.358"></a>
-<span class="sourceLineNo">359</span>  public static final class Builder {<a name="line.359"></a>
-<span class="sourceLineNo">360</span>    boolean keepProgress = DEFAULT_KEEP_PROGRESS;<a name="line.360"></a>
-<span class="sourceLineNo">361</span>    boolean trackMetrics = false;<a name="line.361"></a>
-<span class="sourceLineNo">362</span>    LimitFields limits = new LimitFields();<a name="line.362"></a>
-<span class="sourceLineNo">363</span><a name="line.363"></a>
-<span class="sourceLineNo">364</span>    private Builder() {<a name="line.364"></a>
-<span class="sourceLineNo">365</span>    }<a name="line.365"></a>
+<span class="sourceLineNo">359</span>    sb.append("}");<a name="line.359"></a>
+<span class="sourceLineNo">360</span>    return sb.toString();<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 static Builder newBuilder() {<a name="line.363"></a>
+<span class="sourceLineNo">364</span>    return new Builder();<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>    private Builder(boolean keepProgress) {<a name="line.367"></a>
-<span class="sourceLineNo">368</span>      this.keepProgress = keepProgress;<a name="line.368"></a>
-<span class="sourceLineNo">369</span>    }<a name="line.369"></a>
+<span class="sourceLineNo">367</span>  public static Builder newBuilder(boolean keepProgress) {<a name="line.367"></a>
+<span class="sourceLineNo">368</span>    return new Builder(keepProgress);<a name="line.368"></a>
+<span class="sourceLineNo">369</span>  }<a name="line.369"></a>
 <span class="sourceLineNo">370</span><a name="line.370"></a>
-<span class="sourceLineNo">371</span>    public Builder setKeepProgress(boolean keepProgress) {<a name="line.371"></a>
-<span class="sourceLineNo">372</span>      this.keepProgress = keepProgress;<a name="line.372"></a>
-<span class="sourceLineNo">373</span>      return this;<a name="line.373"></a>
-<span class="sourceLineNo">374</span>    }<a name="line.374"></a>
+<span class="sourceLineNo">371</span>  public static final class Builder {<a name="line.371"></a>
+<span class="sourceLineNo">372</span>    boolean keepProgress = DEFAULT_KEEP_PROGRESS;<a name="line.372"></a>
+<span class="sourceLineNo">373</span>    boolean trackMetrics = false;<a name="line.373"></a>
+<span class="sourceLineNo">374</span>    LimitFields limits = new LimitFields();<a name="line.374"></a>
 <span class="sourceLineNo">375</span><a name="line.375"></a>
-<span class="sourceLineNo">376</span>    public Builder setTrackMetrics(boolean trackMetrics) {<a name="line.376"></a>
-<span class="sourceLineNo">377</span>      this.trackMetrics = trackMetrics;<a name="line.377"></a>
-<span class="sourceLineNo">378</span>      return this;<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 Builder setSizeLimit(LimitScope sizeScope, long dataSizeLimit, long heapSizeLimit) {<a name="line.381"></a>
-<span class="sourceLineNo">382</span>      limits.setDataSize(dataSizeLimit);<a name="line.382"></a>
-<span class="sourceLineNo">383</span>      limits.setHeapSize(heapSizeLimit);<a name="line.383"></a>
-<span class="sourceLineNo">384</span>      limits.setSizeScope(sizeScope);<a name="line.384"></a>
+<span class="sourceLineNo">376</span>    private Builder() {<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>    private Builder(boolean keepProgress) {<a name="line.379"></a>
+<span class="sourceLineNo">380</span>      this.keepProgress = keepProgress;<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>    public Builder setKeepProgress(boolean keepProgress) {<a name="line.383"></a>
+<span class="sourceLineNo">384</span>      this.keepProgress = keepProgress;<a name="line.384"></a>
 <span class="sourceLineNo">385</span>      return this;<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 Builder setTimeLimit(LimitScope timeScope, long timeLimit) {<a name="line.388"></a>
-<span class="sourceLineNo">389</span>      limits.setTime(timeLimit);<a name="line.389"></a>
-<span class="sourceLineNo">390</span>      limits.setTimeScope(timeScope);<a name="line.390"></a>
-<span class="sourceLineNo">391</span>      return this;<a name="line.391"></a>
-<span class="sourceLineNo">392</span>    }<a name="line.392"></a>
-<span class="sourceLineNo">393</span><a name="line.393"></a>
-<span class="sourceLineNo">394</span>    public Builder setBatchLimit(int batchLimit) {<a name="line.394"></a>
-<span class="sourceLineNo">395</span>      limits.setBatch(batchLimit);<a name="line.395"></a>
-<span class="sourceLineNo">396</span>      return this;<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>    public ScannerContext build() {<a name="line.399"></a>
-<span class="sourceLineNo">400</span>      return new ScannerContext(keepProgress, limits, trackMetrics);<a name="line.400"></a>
-<span class="sourceLineNo">401</span>    }<a name="line.401"></a>
-<span class="sourceLineNo">402</span>  }<a name="line.402"></a>
-<span class="sourceLineNo">403</span><a name="line.403"></a>
-<span class="sourceLineNo">404</span>  /**<a name="line.404"></a>
-<span class="sourceLineNo">405</span>   * The possible states a scanner may be in following a call to {@link InternalScanner#next(List)}<a name="line.405"></a>
-<span class="sourceLineNo">406</span>   */<a name="line.406"></a>
-<span class="sourceLineNo">407</span>  public enum NextState {<a name="line.407"></a>
-<span class="sourceLineNo">408</span>    MORE_VALUES(true, false),<a name="line.408"></a>
-<span class="sourceLineNo">409</span>    NO_MORE_VALUES(false, false),<a name="line.409"></a>
-<span class="sourceLineNo">410</span>    SIZE_LIMIT_REACHED(true, true),<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>     * Special case of size limit reached to indicate that the size limit was reached in the middle<a name="line.413"></a>
-<span class="sourceLineNo">414</span>     * of a row and thus a partial results was formed<a name="line.414"></a>
-<span class="sourceLineNo">415</span>     */<a name="line.415"></a>
-<span class="sourceLineNo">416</span>    SIZE_LIMIT_REACHED_MID_ROW(true, true),<a name="line.416"></a>
-<span class="sourceLineNo">417</span>    TIME_LIMIT_REACHED(true, true),<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>     * Special case of time limit reached to indicate that the time limit was reached in the middle<a name="line.420"></a>
-<span class="sourceLineNo">421</span>     * of a row and thus a partial results was formed<a name="line.421"></a>
-<span class="sourceLineNo">422</span>     */<a name="line.422"></a>
-<span class="sourceLineNo">423</span>    TIME_LIMIT_REACHED_MID_ROW(true, true),<a name="line.423"></a>
-<span class="sourceLineNo">424</span>    BATCH_LIMIT_REACHED(true, true);<a name="line.424"></a>
-<span class="sourceLineNo">425</span><a name="line.425"></a>
-<span class="sourceLineNo">426</span>    private final boolean moreValues;<a name="line.426"></a>
-<span class="sourceLineNo">427</span>    private final boolean limitReached;<a name="line.427"></a>
-<span class="sourceLineNo">428</span><a name="line.428"></a>
-<span class="sourceLineNo">429</span>    private NextState(boolean moreValues, boolean limitReached) {<a name="line.429"></a>
-<span class="sourceLineNo">430</span>      this.moreValues = moreValues;<a name="line.430"></a>
-<span class="sourceLineNo">431</span>      this.limitReached = limitReached;<a name="line.431"></a>
-<span class="sourceLineNo">432</span>    }<a name="line.432"></a>
-<span class="sourceLineNo">433</span><a name="line.433"></a>
-<span class="sourceLineNo">434</span>    /**<a name="line.434"></a>
-<span class="sourceLineNo">435</span>     * @return true when the state indicates that more values may follow those that have been<a name="line.435"></a>
-<span class="sourceLineNo">436</span>     *         returned<a name="line.436"></a>
-<span class="sourceLineNo">437</span>     */<a name="line.437"></a>
-<span class="sourceLineNo">438</span>    public boolean hasMoreValues() {<a name="line.438"></a>
-<span class="sourceLineNo">439</span>      return this.moreValues;<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>     * @return true when the state indicates that a limit has been reached and scan should stop<a name="line.443"></a>
-<span class="sourceLineNo">444</span>     */<a name="line.444"></a>
-<span class="sourceLineNo">445</span>    public boolean limitReached() {<a name="line.445"></a>
-<span class="sourceLineNo">446</span>      return this.limitReached;<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>    public static boolean isValidState(NextState state) {<a name="line.449"></a>
-<span class="sourceLineNo">450</span>      return state != null;<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>    public static boolean hasMoreValues(NextState state) {<a name="line.453"></a>
-<span class="sourceLineNo">454</span>      return isValidState(state) &amp;&amp; state.hasMoreValues();<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>  /**<a name="line.458"></a>
-<span class="sourceLineNo">459</span>   * The various scopes where a limit can be enforced. Used to differentiate when a limit should be<a name="line.459"></a>
-<span class="sourceLineNo">460</span>   * enforced or not.<a name="line.460"></a>
-<span class="sourceLineNo">461</span>   */<a name="line.461"></a>
-<span class="sourceLineNo">462</span>  public enum LimitScope {<a name="line.462"></a>
-<span class="sourceLineNo">463</span>    /**<a name="line.463"></a>
-<span class="sourceLineNo">464</span>     * Enforcing a limit between rows means that the limit will not be considered until all the<a name="line.464"></a>
-<span class="sourceLineNo">465</span>     * cells for a particular row have been retrieved<a name="line.465"></a>
-<span class="sourceLineNo">466</span>     */<a name="line.466"></a>
-<span class="sourceLineNo">467</span>    BETWEEN_ROWS(0),<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>     * Enforcing a limit between cells means that the limit will be considered after each full cell<a name="line.470"></a>
-<span class="sourceLineNo">471</span>     * has been retrieved<a name="line.471"></a>
-<span class="sourceLineNo">472</span>     */<a name="line.472"></a>
-<span class="sourceLineNo">473</span>    BETWEEN_CELLS(1);<a name="line.473"></a>
-<span class="sourceLineNo">474</span><a name="line.474"></a>
+<span class="sourceLineNo">388</span>    public Builder setTrackMetrics(boolean trackMetrics) {<a name="line.388"></a>
+<span class="sourceLineNo">389</span>      this.trackMetrics = trackMetrics;<a name="line.389"></a>
+<span class="sourceLineNo">390</span>      return this;<a name="line.390"></a>
+<span class="sourceLineNo">391</span>    }<a name="line.391"></a>
+<span class="sourceLineNo">392</span><a name="line.392"></a>
+<span class="sourceLineNo">393</span>    public Builder setSizeLimit(LimitScope sizeScope, long dataSizeLimit, long heapSizeLimit) {<a name="line.393"></a>
+<span class="sourceLineNo">394</span>      limits.setDataSize(dataSizeLimit);<a name="line.394"></a>
+<span class="sourceLineNo">395</span>      limits.setHeapSize(heapSizeLimit);<a name="line.395"></a>
+<span class="sourceLineNo">396</span>      limits.setSizeScope(sizeScope);<a name="line.396"></a>
+<span class="sourceLineNo">397</span>      return this;<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>    public Builder setTimeLimit(LimitScope timeScope, long timeLimit) {<a name="line.400"></a>
+<span class="sourceLineNo">401</span>      limits.setTime(timeLimit);<a name="line.401"></a>
+<span class="sourceLineNo">402</span>      limits.setTimeScope(timeScope);<a name="line.402"></a>
+<span class="sourceLineNo">403</span>      return this;<a name="line.403"></a>
+<span class="sourceLineNo">404</span>    }<a name="line.404"></a>
+<span class="sourceLineNo">405</span><a name="line.405"></a>
+<span class="sourceLineNo">406</span>    public Builder setBatchLimit(int batchLimit) {<a name="line.406"></a>
+<span class="sourceLineNo">407</span>      limits.setBatch(batchLimit);<a name="line.407"></a>
+<span class="sourceLineNo">408</span>      return this;<a name="line.408"></a>
+<span class="sourceLineNo">409</span>    }<a name="line.409"></a>
+<span class="sourceLineNo">410</span><a name="line.410"></a>
+<span class="sourceLineNo">411</span>    public ScannerContext build() {<a name="line.411"></a>
+<span class="sourceLineNo">412</span>      return new ScannerContext(keepProgress, limits, trackMetrics);<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><a name="line.415"></a>
+<span class="sourceLineNo">416</span>  /**<a name="line.416"></a>
+<span class="sourceLineNo">417</span>   * The possible states a scanner may be in following a call to {@link InternalScanner#next(List)}<a name="line.417"></a>
+<span class="sourceLineNo">418</span>   */<a name="line.418"></a>
+<span class="sourceLineNo">419</span>  public enum NextState {<a name="line.419"></a>
+<span class="sourceLineNo">420</span>    MORE_VALUES(true, false),<a name="line.420"></a>
+<span class="sourceLineNo">421</span>    NO_MORE_VALUES(false, false),<a name="line.421"></a>
+<span class="sourceLineNo">422</span>    SIZE_LIMIT_REACHED(true, true),<a name="line.422"></a>
+<span class="sourceLineNo">423</span><a name="line.423"></a>
+<span class="sourceLineNo">424</span>    /**<a name="line.424"></a>
+<span class="sourceLineNo">425</span>     * Special case of size limit reached to indicate that the size limit was reached in the middle<a name="line.425"></a>
+<span class="sourceLineNo">426</span>     * of a row and thus a partial results was formed<a name="line.426"></a>
+<span class="sourceLineNo">427</span>     */<a name="line.427"></a>
+<span class="sourceLineNo">428</span>    SIZE_LIMIT_REACHED_MID_ROW(true, true),<a name="line.428"></a>
+<span class="sourceLineNo">429</span>    TIME_LIMIT_REACHED(true, true),<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>     * Special case of time limit reached to indicate that the time limit was reached in the middle<a name="line.432"></a>
+<span class="sourceLineNo">433</span>     * of a row and thus a partial results was formed<a name="line.433"></a>
+<span class="sourceLineNo">434</span>     */<a name="line.434"></a>
+<span class="sourceLineNo">435</span>    TIME_LIMIT_REACHED_MID_ROW(true, true),<a name="line.435"></a>
+<span class="sourceLineNo">436</span>    BATCH_LIMIT_REACHED(true, true);<a name="line.436"></a>
+<span class="sourceLineNo">437</span><a name="line.437"></a>
+<span class="sourceLineNo">438</span>    private final boolean moreValues;<a name="line.438"></a>
+<span class="sourceLineNo">439</span>    private final boolean limitReached;<a name="line.439"></a>
+<span class="sourceLineNo">440</span><a name="line.440"></a>
+<span class="sourceLineNo">441</span>    private NextState(boolean moreValues, boolean limitReached) {<a name="line.441"></a>
+<span class="sourceLineNo">442</span>      this.moreValues = moreValues;<a name="line.442"></a>
+<span class="sourceLineNo">443</span>      this.limitReached = limitReached;<a name="line.443"></a>
+<span class="sourceLineNo">444</span>    }<a name="line.444"></a>
+<span class="sourceLineNo">445</span><a name="line.445"></a>
+<span class="sourceLineNo">446</span>    /**<a name="line.446"></a>
+<span class="sourceLineNo">447</span>     * @return true when the state indicates that more values may follow those that have been<a name="line.447"></a>
+<span class="sourceLineNo">448</span>     *         returned<a name="line.448"></a>
+<span class="sourceLineNo">449</span>     */<a name="line.449"></a>
+<span class="sourceLineNo">450</span>    public boolean hasMoreValues() {<a name="line.450"></a>
+<span class="sourceLineNo">451</span>      return this.moreValues;<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>     * @return true when the state indicates that a limit has been reached and scan should stop<a name="line.455"></a>
+<span class="sourceLineNo">456</span>     */<a name="line.456"></a>
+<span class="sourceLineNo">457</span>    public boolean limitReached() {<a name="line.457"></a>
+<span class="sourceLineNo">458</span>      return this.limitReached;<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>    public static boolean isValidState(NextState state) {<a name="line.461"></a>
+<span class="sourceLineNo">462</span>      return state != 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>    public static boolean hasMoreValues(NextState state) {<a name="line.465"></a>
+<span class="sourceLineNo">466</span>      return isValidState(state) &amp;&amp; state.hasMoreValues();<a name="line.466"></a>
+<span class="sourceLineNo">467</span>    }<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>   * The various scopes where a limit can be enforced. Used to differentiate when a limit should be<a name="line.471"></a>
+<span class="sourceLineNo">472</span>   * enforced or not.<a name="line.472"></a>
+<span class="sourceLineNo">473</span>   */<a name="line.473"></a>
+<span class="sourceLineNo">474</span>  public enum LimitScope {<a name="line.474"></a>
 <span class="sourceLineNo">475</span>    /**<a name="line.475"></a>
-<span class="sourceLineNo">476</span>     * When enforcing a limit, we must check that the scope is appropriate for enforcement.<a name="line.476"></a>
-<span class="sourceLineNo">477</span>     * &lt;p&gt;<a name="line.477"></a>
-<span class="sourceLineNo">478</span>     * To communicate this concept, each scope has a depth. A limit will be enforced if the depth of<a name="line.478"></a>
-<span class="sourceLineNo">479</span>     * the checker's scope is less than or equal to the limit's scope. This means that when checking<a name="line.479"></a>
-<span class="sourceLineNo">480</span>     * limits, the checker must know their own scope (i.e. are they checking the limits between<a name="line.480"></a>
-<span class="sourceLineNo">481</span>     * rows, between cells, etc...)<a name="line.481"></a>
-<span class="sourceLineNo">482</span>     */<a name="line.482"></a>
-<span class="sourceLineNo">483</span>    final int depth;<a name="line.483"></a>
-<span class="sourceLineNo">484</span><a name="line.484"></a>
-<span class="sourceLineNo">485</span>    LimitScope(int depth) {<a name="line.485"></a>
-<span class="sourceLineNo">486</span>      this.depth = depth;<a name="line.486"></a>
-<span class="sourceLineNo">487</span>    }<a name="line.487"></a>
-<span class="sourceLineNo">488</span><a name="line.488"></a>
-<span class="sourceLineNo">489</span>    final int depth() {<a name="line.489"></a>
-<span class="sourceLineNo">490</span>      return depth;<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>     * @param checkerScope The scope in which the limit is being checked<a name="line.494"></a>
-<span class="sourceLineNo">495</span>     * @return true when the checker is in a scope that indicates the limit can be enforced. Limits<a name="line.495"></a>
-<span class="sourceLineNo">496</span>     *         can be enforced from "higher or equal" scopes (i.e. the checker's scope is at a<a name="line.496"></a>
-<span class="sourceLineNo">497</span>     *         lesser depth than the limit)<a name="line.497"></a>
-<span class="sourceLineNo">498</span>     */<a name="line.498"></a>
-<span class="sourceLineNo">499</span>    boolean canEnforceLimitFromScope(LimitScope checkerScope) {<a name="line.499"></a>
-<span class="sourceLineNo">500</span>      return checkerScope != null &amp;&amp; checkerScope.depth() &lt;= depth;<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><a name="line.503"></a>
-<span class="sourceLineNo">504</span>  /**<a name="line.504"></a>
-<span class="sourceLineNo">505</span>   * The different fields that can be used as limits in calls to<a name="line.505"></a>
-<span class="sourceLineNo">506</span>   * {@link InternalScanner#next(java.util.List)} and {@link RegionScanner#next(java.util.List)}<a name="line.506"></a>
-<span class="sourceLineNo">507</span>   */<a name="line.507"></a>
-<span class="sourceLineNo">508</span>  private static class LimitFields {<a name="line.508"></a>
-<span class="sourceLineNo">509</span>    /**<a name="line.509"></a>
-<span class="sourceLineNo">510</span>     * Default values of the limit fields. Defined such that if a field does NOT change from its<a name="line.510"></a>
-<span class="sourceLineNo">511</span>     * default, it will not be enforced<a name="line.511"></a>
-<span class="sourceLineNo">512</span>     */<a name="line.512"></a>
-<span class="sourceLineNo">513</span>    private static int DEFAULT_BATCH = -1;<a name="line.513"></a>
-<span class="sourceLineNo">514</span>    private static long DEFAULT_SIZE = -1L;<a name="line.514"></a>
-<span class="sourceLineNo">515</span>    private static long DEFAULT_TIME = -1L;<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>     * Default scope that is assigned to a limit if a scope is not specified.<a name="line.518"></a>
-<span class="sourceLineNo">519</span>     */<a name="line.519"></a>
-<span class="sourceLineNo">520</span>    private static final LimitScope DEFAULT_SCOPE = LimitScope.BETWEEN_ROWS;<a name="line.520"></a>
-<span class="sourceLineNo">521</span><a name="line.521"></a>
-<span class="sourceLineNo">522</span>    // The batch limit will always be enforced between cells, thus, there isn't a field to hold the<a name="line.522"></a>
-<span class="sourceLineNo">523</span>    // batch scope<a name="line.523"></a>
-<span class="sourceLineNo">524</span>    int batch = DEFAULT_BATCH;<a name="line.524"></a>
-<span class="sourceLineNo">525</span><a name="line.525"></a>
-<span class="sourceLineNo">526</span>    LimitScope sizeScope = DEFAULT_SCOPE;<a name="line.526"></a>
-<span class="sourceLineNo">527</span>    // The sum of cell data sizes(key + value). The Cell data might be in on heap or off heap area.<a name="line.527"></a>
-<span class="sourceLineNo">528</span>    long dataSize = DEFAULT_SIZE;<a name="line.528"></a>
-<span class="sourceLineNo">529</span>    // The sum of heap space occupied by all tracked cells. This includes Cell POJO's overhead as<a name="line.529"></a>
-<span class="sourceLineNo">530</span>    // such AND data cells of Cells which are in on heap area.<a name="line.530"></a>
-<span class="sourceLineNo">531</span>    long heapSize = DEFAULT_SIZE;<a name="line.531"></a>
-<span class="sourceLineNo">532</span><a name="line.532"></a>
-<span class="sourceLineNo">533</span>    LimitScope timeScope = DEFAULT_SCOPE;<a name="line.533"></a>
-<span class="sourceLineNo">534</span>    long time = DEFAULT_TIME;<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>     * Fields keep their default values.<a name="line.537"></a>
-<span class="sourceLineNo">538</span>     */<a name="line.538"></a>
-<span class="sourceLineNo">539</span>    LimitFields() {<a name="line.539"></a>
-<span class="sourceLineNo">540</span>    }<a name="line.540"></a>
-<span class="sourceLineNo">541</span><a name="line.541"></a>
-<span class="sourceLineNo">542</span>    LimitFields(int batch, LimitScope sizeScope, long size, long heapSize, LimitScope timeScope,<a name="line.542"></a>
-<span class="sourceLineNo">543</span>        long time) {<a name="line.543"></a>
-<span class="sourceLineNo">544</span>      setFields(batch, sizeScope, size, heapSize, timeScope, time);<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>    void copy(LimitFields limitsToCopy) {<a name="line.547"></a>
-<span class="sourceLineNo">548</span>      if (limitsToCopy != null) {<a name="line.548"></a>
-<span class="sourceLineNo">549</span>        setFields(limitsToCopy.getBatch(), limitsToCopy.getSizeScope(), limitsToCopy.getDataSize(),<a name="line.549"></a>
-<span class="sourceLineNo">550</span>            limitsToCopy.getHeapSize(), limitsToCopy.getTimeScope(), limitsToCopy.getTime());<a name="line.550"></a>
-<span class="sourceLineNo">551</span>      }<a name="line.551"></a>
+<span class="sourceLineNo">476</span>     * Enforcing a limit between rows means that the limit will not be considered until all the<a name="line.476"></a>
+<span class="sourceLineNo">477</span>     * cells for a particular row have been retrieved<a name="line.477"></a>
+<span class="sourceLineNo">478</span>     */<a name="line.478"></a>
+<span class="sourceLineNo">479</span>    BETWEEN_ROWS(0),<a name="line.479"></a>
+<span class="sourceLineNo">480</span><a name="line.480"></a>
+<span class="sourceLineNo">481</span>    /**<a name="line.481"></a>
+<span class="sourceLineNo">482</span>     * Enforcing a limit between cells means that the limit will be considered after each full cell<a name="line.482"></a>
+<span class="sourceLineNo">483</span>     * has been retrieved<a name="line.483"></a>
+<span class="sourceLineNo">484</span>     */<a name="line.484"></a>
+<span class="sourceLineNo">485</span>    BETWEEN_CELLS(1);<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>     * When enforcing a limit, we must check that the scope is appropriate for enforcement.<a name="line.488"></a>
+<span class="sourceLineNo">489</span>     * &lt;p&gt;<a name="line.489"></a>
+<span class="sourceLineNo">490</span>     * To communicate this concept, each scope has a depth. A limit will be enforced if the depth of<a name="line.490"></a>
+<span class="sourceLineNo">491</span>     * the checker's scope is less than or equal to the limit's scope. This means that when checking<a name="line.491"></a>
+<span class="sourceLineNo">492</span>     * limits, the checker must know their own scope (i.e. are they checking the limits between<a name="line.492"></a>
+<span class="sourceLineNo">493</span>     * rows, between cells, etc...)<a name="line.493"></a>
+<span class="sourceLineNo">494</span>     */<a name="line.494"></a>
+<span class="sourceLineNo">495</span>    final int depth;<a name="line.495"></a>
+<span class="sourceLineNo">496</span><a name="line.496"></a>
+<span class="sourceLineNo">497</span>    LimitScope(int depth) {<a name="line.497"></a>
+<span class="sourceLineNo">498</span>      this.depth = depth;<a name="line.498"></a>
+<span class="sourceLineNo">499</span>    }<a name="line.499"></a>
+<span class="sourceLineNo">500</span><a name="line.500"></a>
+<span class="sourceLineNo">501</span>    final int depth() {<a name="line.501"></a>
+<span class="sourceLineNo">502</span>      return depth;<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>    /**<a name="line.505"></a>
+<span class="sourceLineNo">506</span>     * @param checkerScope The scope in which the limit is being checked<a name="line.506"></a>
+<span class="sourceLineNo">507</span>     * @return true when the checker is in a scope that indicates the limit can be enforced. Limits<a name="line.507"></a>
+<span class="sourceLineNo">508</span>     *         can be enforced from "higher or equal" scopes (i.e. the checker's scope is at a<a name="line.508"></a>
+<span class="sourceLineNo">509</span>     *         lesser depth than the limit)<a name="line.509"></a>
+<span class="sourceLineNo">510</span>     */<a name="line.510"></a>
+<span class="sourceLineNo">511</span>    boolean canEnforceLimitFromScope(LimitScope checkerScope) {<a name="line.511"></a>
+<span class="sourceLineNo">512</span>      return checkerScope != null &amp;&amp; checkerScope.depth() &lt;= depth;<a name="line.512"></a>
+<span class="sourceLineNo">513</span>    }<a name="line.513"></a>
+<span class="sourceLineNo">514</span>  }<a name="line.514"></a>
+<span class="sourceLineNo">515</span><a name="line.515"></a>
+<span class="sourceLineNo">516</span>  /**<a name="line.516"></a>
+<span class="sourceLineNo">517</span>   * The different fields that can be used as limits in calls to<a name="line.517"></a>
+<span class="sourceLineNo">518</span>   * {@link InternalScanner#next(java.util.List)} and {@link RegionScanner#next(java.util.List)}<a name="line.518"></a>
+<span class="sourceLineNo">519</span>   */<a name="line.519"></a>
+<span class="sourceLineNo">520</span>  private static class LimitFields {<a name="line.520"></a>
+<span class="sourceLineNo">521</span>    /**<a name="line.521"></a>
+<span class="sourceLineNo">522</span>     * Default values of the limit fields. Defined such that if a field does NOT change from its<a name="line.522"></a>
+<span class="sourceLineNo">523</span>     * default, it will not be enforced<a name="line.523"></a>
+<span class="sourceLineNo">524</span>     */<a name="line.524"></a>
+<span class="sourceLineNo">525</span>    private static int DEFAULT_BATCH = -1;<a name="line.525"></a>
+<span class="sourceLineNo">526</span>    private static long DEFAULT_SIZE = -1L;<a name="line.526"></a>
+<span class="sourceLineNo">527</span>    private static long DEFAULT_TIME = -1L;<a name="line.527"></a>
+<span class="sourceLineNo">528</span><a name="line.528"></a>
+<span class="sourceLineNo">529</span>    /**<a name="line.529"></a>
+<span class="sourceLineNo">530</span>     * Default scope that is assigned to a limit if a scope is not specified.<a name="line.530"></a>
+<span class="sourceLineNo">531</span>     */<a name="line.531"></a>
+<span class="sourceLineNo">532</span>    private static final LimitScope DEFAULT_SCOPE = LimitScope.BETWEEN_ROWS;<a name="line.532"></a>
+<span class="sourceLineNo">533</span><a name="line.533"></a>
+<span class="sourceLineNo">534</span>    // The batch limit will always be enforced between cells, thus, there isn't a field to hold the<a name="line.534"></a>
+<span class="sourceLineNo">535</span>    // batch scope<a name="line.535"></a>
+<span class="sourceLineNo">536</span>    int batch = DEFAULT_BATCH;<a name="line.536"></a>
+<span class="sourceLineNo">537</span><a name="line.537"></a>
+<span class="sourceLineNo">538</span>    LimitScope sizeScope = DEFAULT_SCOPE;<a name="line.538"></a>
+<span class="sourceLineNo">539</span>    // The sum of cell data sizes(key + value). The Cell data might be in on heap or off heap area.<a name="line.539"></a>
+<span class="sourceLineNo">540</span>    long dataSize = DEFAULT_SIZE;<a name="line.540"></a>
+<span class="sourceLineNo">541</span>    // The sum of heap space occupied by all tracked cells. This includes Cell POJO's overhead as<a name="line.541"></a>
+<span class="sourceLineNo">542</span>    // such AND data cells of Cells which are in on heap area.<a name="line.542"></a>
+<span class="sourceLineNo">543</span>    long heapSize = DEFAULT_SIZE;<a name="line.543"></a>
+<span class="sourceLineNo">544</span><a name="line.544"></a>
+<span class="sourceLineNo">545</span>    LimitScope timeScope = DEFAULT_SCOPE;<a name="line.545"></a>
+<span class="sourceLineNo">546</span>    long time = DEFAULT_TIME;<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>     * Fields keep their default values.<a name="line.549"></a>
+<span class="sourceLineNo">550</span>     */<a name="line.550"></a>
+<span class="sourceLineNo">551</span>    LimitFields() {<a name="line.551"></a>
 <span class="sourceLineNo">552</span>    }<a name="line.552"></a>
 <span class="sourceLineNo">553</span><a name="line.553"></a>
-<span class="sourceLineNo">554</span>    /**<a name="line.554"></a>
-<span class="sourceLineNo">555</span>     * Set all fields together.<a name="line.555"></a>
-<span class="sourceLineNo">556</span>     */<a name="line.556"></a>
-<span class="sourceLineNo">557</span>    void setFields(int batch, LimitScope sizeScope, long dataSize, long heapSize,<a name="line.557"></a>
-<span class="sourceLineNo">558</span>        LimitScope timeScope, long time) {<a name="line.558"></a>
-<span class="sourceLineNo">559</span>      setBatch(batch);<a name="line.559"></a>
-<span class="sourceLineNo">560</span>      setSizeScope(sizeScope);<a name="line.560"></a>
-<span class="sourceLineNo">561</span>      setDataSize(dataSize);<a name="line.561"></a>
-<span class="sourceLineNo">562</span>      setHeapSize(heapSize);<a name="line.562"></a>
-<span class="sourceLineNo">563</span>      setTimeScope(timeScope);<a name="line.563"></a>
-<span class="sourceLineNo">564</span>      setTime(time);<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>    int getBatch() {<a name="line.567"></a>
-<span class="sourceLineNo">568</span>      return this.batch;<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>    void setBatch(int batch) {<a name="line.571"></a>
-<span class="sourceLineNo">572</span>      this.batch = batch;<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>    /**<a name="line.575"></a>
-<span class="sourceLineNo">576</span>     * @param checkerScope<a name="line.576"></a>
-<span class="sourceLineNo">577</span>     * @return true when the limit can be enforced from the scope of the checker<a name="line.577"></a>
-<span class="sourceLineNo">578</span>     */<a name="line.578"></a>
-<span class="sourceLineNo">579</span>    boolean canEnforceBatchLimitFromScope(LimitScope checkerScope) {<a name="line.579"></a>
-<span class="sourceLineNo">580</span>      return LimitScope.BETWEEN_CELLS.canEnforceLimitFromScope(checkerScope);<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>    long getDataSize() {<a name="line.583"></a>
-<span class="sourceLineNo">584</span>      return this.dataSize;<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>    long getHeapSize() {<a name="line.587"></a>
-<span class="sourceLineNo">588</span>      return this.heapSize;<a name="line.588"></a>
-<span class="sourceLineNo">589</span>    }<a name="line.589"></a>
-<span class="sourceLineNo">590</span><a name="line.590"></a>
-<span class="sourceLineNo">591</span>    void setDataSize(long dataSize) {<a name="line.591"></a>
-<span class="sourceLineNo">592</span>      this.dataSize = dataSize;<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>    void setHeapSize(long heapSize) {<a name="line.595"></a>
-<span class="sourceLineNo">596</span>      this.heapSize = heapSize;<a name="line.596"></a>
-<span class="sourceLineNo">597</span>    }<a name="line.597"></a>
-<span class="sourceLineNo">598</span><a name="line.598"></a>
-<span class="sourceLineNo">599</span>    /**<a name="line.599"></a>
-<span class="sourceLineNo">600</span>     * @return {@link LimitScope} indicating scope in which the size limit is enforced<a name="line.600"></a>
-<span class="sourceLineNo">601</span>     */<a name="line.601"></a>
-<span class="sourceLineNo">602</span>    LimitScope getSizeScope() {<a name="line.602"></a>
-<span class="sourceLineNo">603</span>      return this.sizeScope;<a name="line.603"></a>
+<span class="sourceLineNo">554</span>    void copy(LimitFields limitsToCopy) {<a name="line.554"></a>
+<span class="sourceLineNo">555</span>      if (limitsToCopy != null) {<a name="line.555"></a>
+<span class="sourceLineNo">556</span>        setFields(limitsToCopy.getBatch(), limitsToCopy.getSizeScope(), limitsToCopy.getDataSize(),<a name="line.556"></a>
+<span class="sourceLineNo">557</span>            limitsToCopy.getHeapSize(), limitsToCopy.getTimeScope(), limitsToCopy.getTime());<a name="line.557"></a>
+<span class="sourceLineNo">558</span>      }<a name="line.558"></a>
+<span class="sourceLineNo">559</span>    }<a name="line.559"></a>
+<span class="sourceLineNo">560</span><a name="line.560"></a>
+<span class="sourceLineNo">561</span>    /**<a name="line.561"></a>
+<span class="sourceLineNo">562</span>     * Set all fields together.<a name="line.562"></a>
+<span class="sourceLineNo">563</span>     */<a name="line.563"></a>
+<span class="sourceLineNo">564</span>    void setFields(int batch, LimitScope sizeScope, long dataSize, long heapSize,<a name="line.564"></a>
+<span class="sourceLineNo">565</span>        LimitScope timeScope, long time) {<a name="line.565"></a>
+<span class="sourceLineNo">566</span>      setBatch(batch);<a name="line.566"></a>
+<span class="sourceLineNo">567</span>      setSizeScope(sizeScope);<a name="line.567"></a>
+<span class="sourceLineNo">568</span>      setDataSize(dataSize);<a name="line.568"></a>
+<span class="sourceLineNo">569</span>      setHeapSize(heapSize);<a name="line.569"></a>
+<span class="sourceLineNo">570</span>      setTimeScope(timeScope);<a name="line.570"></a>
+<span class="sourceLineNo">571</span>      setTime(time);<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>    int getBatch() {<a name="line.574"></a>
+<span class="sourceLineNo">575</span>      return this.batch;<a name="line.575"></a>
+<span class="sourceLineNo">576</span>    }<a name="line.576"></a>
+<span class="sourceLineNo">577</span><a name="line.577"></a>
+<span class="sourceLineNo">578</span>    void setBatch(int batch) {<a name="line.578"></a>
+<span class="sourceLineNo">579</span>      this.batch = batch;<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="sourceL

<TRUNCATED>

[25/50] hbase-site git commit: Published site at 26babcf013de696b899d76a3c39434b794440d8d.

Posted by gi...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html
----------------------------------------------------------------------
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html
index e8070ca..8cb24b3 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntry.html
@@ -433,1254 +433,1261 @@
 <span class="sourceLineNo">425</span>      return;<a name="line.425"></a>
 <span class="sourceLineNo">426</span>    }<a name="line.426"></a>
 <span class="sourceLineNo">427</span><a name="line.427"></a>
-<span class="sourceLineNo">428</span>    if (backingMap.containsKey(cacheKey)) {<a name="line.428"></a>
+<span class="sourceLineNo">428</span>    if (backingMap.containsKey(cacheKey) || ramCache.containsKey(cacheKey)) {<a name="line.428"></a>
 <span class="sourceLineNo">429</span>      Cacheable existingBlock = getBlock(cacheKey, false, false, false);<a name="line.429"></a>
-<span class="sourceLineNo">430</span>      try {<a name="line.430"></a>
-<span class="sourceLineNo">431</span>        if (BlockCacheUtil.compareCacheBlock(cachedItem, existingBlock) != 0) {<a name="line.431"></a>
-<span class="sourceLineNo">432</span>          throw new RuntimeException("Cached block contents differ, which should not have happened."<a name="line.432"></a>
-<span class="sourceLineNo">433</span>              + "cacheKey:" + cacheKey);<a name="line.433"></a>
-<span class="sourceLineNo">434</span>        }<a name="line.434"></a>
-<span class="sourceLineNo">435</span>        String msg = "Caching an already cached block: " + cacheKey;<a name="line.435"></a>
-<span class="sourceLineNo">436</span>        msg += ". This is harmless and can happen in rare cases (see HBASE-8547)";<a name="line.436"></a>
-<span class="sourceLineNo">437</span>        LOG.warn(msg);<a name="line.437"></a>
-<span class="sourceLineNo">438</span>      } finally {<a name="line.438"></a>
-<span class="sourceLineNo">439</span>        // return the block since we need to decrement the count<a name="line.439"></a>
-<span class="sourceLineNo">440</span>        returnBlock(cacheKey, existingBlock);<a name="line.440"></a>
-<span class="sourceLineNo">441</span>      }<a name="line.441"></a>
-<span class="sourceLineNo">442</span>      return;<a name="line.442"></a>
-<span class="sourceLineNo">443</span>    }<a name="line.443"></a>
-<span class="sourceLineNo">444</span><a name="line.444"></a>
-<span class="sourceLineNo">445</span>    /*<a name="line.445"></a>
-<span class="sourceLineNo">446</span>     * Stuff the entry into the RAM cache so it can get drained to the persistent store<a name="line.446"></a>
-<span class="sourceLineNo">447</span>     */<a name="line.447"></a>
-<span class="sourceLineNo">448</span>    RAMQueueEntry re =<a name="line.448"></a>
-<span class="sourceLineNo">449</span>        new RAMQueueEntry(cacheKey, cachedItem, accessCount.incrementAndGet(), inMemory);<a name="line.449"></a>
-<span class="sourceLineNo">450</span>    if (ramCache.putIfAbsent(cacheKey, re) != null) {<a name="line.450"></a>
-<span class="sourceLineNo">451</span>      return;<a name="line.451"></a>
-<span class="sourceLineNo">452</span>    }<a name="line.452"></a>
-<span class="sourceLineNo">453</span>    int queueNum = (cacheKey.hashCode() &amp; 0x7FFFFFFF) % writerQueues.size();<a name="line.453"></a>
-<span class="sourceLineNo">454</span>    BlockingQueue&lt;RAMQueueEntry&gt; bq = writerQueues.get(queueNum);<a name="line.454"></a>
-<span class="sourceLineNo">455</span>    boolean successfulAddition = false;<a name="line.455"></a>
-<span class="sourceLineNo">456</span>    if (wait) {<a name="line.456"></a>
-<span class="sourceLineNo">457</span>      try {<a name="line.457"></a>
-<span class="sourceLineNo">458</span>        successfulAddition = bq.offer(re, DEFAULT_CACHE_WAIT_TIME, TimeUnit.MILLISECONDS);<a name="line.458"></a>
-<span class="sourceLineNo">459</span>      } catch (InterruptedException e) {<a name="line.459"></a>
-<span class="sourceLineNo">460</span>        Thread.currentThread().interrupt();<a name="line.460"></a>
-<span class="sourceLineNo">461</span>      }<a name="line.461"></a>
-<span class="sourceLineNo">462</span>    } else {<a name="line.462"></a>
-<span class="sourceLineNo">463</span>      successfulAddition = bq.offer(re);<a name="line.463"></a>
-<span class="sourceLineNo">464</span>    }<a name="line.464"></a>
-<span class="sourceLineNo">465</span>    if (!successfulAddition) {<a name="line.465"></a>
-<span class="sourceLineNo">466</span>      ramCache.remove(cacheKey);<a name="line.466"></a>
-<span class="sourceLineNo">467</span>      cacheStats.failInsert();<a name="line.467"></a>
-<span class="sourceLineNo">468</span>    } else {<a name="line.468"></a>
-<span class="sourceLineNo">469</span>      this.blockNumber.increment();<a name="line.469"></a>
-<span class="sourceLineNo">470</span>      this.heapSize.add(cachedItem.heapSize());<a name="line.470"></a>
-<span class="sourceLineNo">471</span>      blocksByHFile.add(cacheKey);<a name="line.471"></a>
-<span class="sourceLineNo">472</span>    }<a name="line.472"></a>
-<span class="sourceLineNo">473</span>  }<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>   * Get the buffer of the block with the specified key.<a name="line.476"></a>
-<span class="sourceLineNo">477</span>   * @param key block's cache key<a name="line.477"></a>
-<span class="sourceLineNo">478</span>   * @param caching true if the caller caches blocks on cache misses<a name="line.478"></a>
-<span class="sourceLineNo">479</span>   * @param repeat Whether this is a repeat lookup for the same block<a name="line.479"></a>
-<span class="sourceLineNo">480</span>   * @param updateCacheMetrics Whether we should update cache metrics or not<a name="line.480"></a>
-<span class="sourceLineNo">481</span>   * @return buffer of specified cache key, or null if not in cache<a name="line.481"></a>
-<span class="sourceLineNo">482</span>   */<a name="line.482"></a>
-<span class="sourceLineNo">483</span>  @Override<a name="line.483"></a>
-<span class="sourceLineNo">484</span>  public Cacheable getBlock(BlockCacheKey key, boolean caching, boolean repeat,<a name="line.484"></a>
-<span class="sourceLineNo">485</span>      boolean updateCacheMetrics) {<a name="line.485"></a>
-<span class="sourceLineNo">486</span>    if (!cacheEnabled) {<a name="line.486"></a>
-<span class="sourceLineNo">487</span>      return null;<a name="line.487"></a>
-<span class="sourceLineNo">488</span>    }<a name="line.488"></a>
-<span class="sourceLineNo">489</span>    RAMQueueEntry re = ramCache.get(key);<a name="line.489"></a>
-<span class="sourceLineNo">490</span>    if (re != null) {<a name="line.490"></a>
-<span class="sourceLineNo">491</span>      if (updateCacheMetrics) {<a name="line.491"></a>
-<span class="sourceLineNo">492</span>        cacheStats.hit(caching, key.isPrimary(), key.getBlockType());<a name="line.492"></a>
-<span class="sourceLineNo">493</span>      }<a name="line.493"></a>
-<span class="sourceLineNo">494</span>      re.access(accessCount.incrementAndGet());<a name="line.494"></a>
-<span class="sourceLineNo">495</span>      return re.getData();<a name="line.495"></a>
-<span class="sourceLineNo">496</span>    }<a name="line.496"></a>
-<span class="sourceLineNo">497</span>    BucketEntry bucketEntry = backingMap.get(key);<a name="line.497"></a>
-<span class="sourceLineNo">498</span>    if (bucketEntry != null) {<a name="line.498"></a>
-<span class="sourceLineNo">499</span>      long start = System.nanoTime();<a name="line.499"></a>
-<span class="sourceLineNo">500</span>      ReentrantReadWriteLock lock = offsetLock.getLock(bucketEntry.offset());<a name="line.500"></a>
-<span class="sourceLineNo">501</span>      try {<a name="line.501"></a>
-<span class="sourceLineNo">502</span>        lock.readLock().lock();<a name="line.502"></a>
-<span class="sourceLineNo">503</span>        // We can not read here even if backingMap does contain the given key because its offset<a name="line.503"></a>
-<span class="sourceLineNo">504</span>        // maybe changed. If we lock BlockCacheKey instead of offset, then we can only check<a name="line.504"></a>
-<span class="sourceLineNo">505</span>        // existence here.<a name="line.505"></a>
-<span class="sourceLineNo">506</span>        if (bucketEntry.equals(backingMap.get(key))) {<a name="line.506"></a>
-<span class="sourceLineNo">507</span>          // TODO : change this area - should be removed after server cells and<a name="line.507"></a>
-<span class="sourceLineNo">508</span>          // 12295 are available<a name="line.508"></a>
-<span class="sourceLineNo">509</span>          int len = bucketEntry.getLength();<a name="line.509"></a>
-<span class="sourceLineNo">510</span>          if (LOG.isTraceEnabled()) {<a name="line.510"></a>
-<span class="sourceLineNo">511</span>            LOG.trace("Read offset=" + bucketEntry.offset() + ", len=" + len);<a name="line.511"></a>
-<span class="sourceLineNo">512</span>          }<a name="line.512"></a>
-<span class="sourceLineNo">513</span>          Cacheable cachedBlock = ioEngine.read(bucketEntry.offset(), len,<a name="line.513"></a>
-<span class="sourceLineNo">514</span>              bucketEntry.deserializerReference(this.deserialiserMap));<a name="line.514"></a>
-<span class="sourceLineNo">515</span>          long timeTaken = System.nanoTime() - start;<a name="line.515"></a>
-<span class="sourceLineNo">516</span>          if (updateCacheMetrics) {<a name="line.516"></a>
-<span class="sourceLineNo">517</span>            cacheStats.hit(caching, key.isPrimary(), key.getBlockType());<a name="line.517"></a>
-<span class="sourceLineNo">518</span>            cacheStats.ioHit(timeTaken);<a name="line.518"></a>
+<span class="sourceLineNo">430</span><a name="line.430"></a>
+<span class="sourceLineNo">431</span>      try {<a name="line.431"></a>
+<span class="sourceLineNo">432</span>        int comparison = BlockCacheUtil.validateBlockAddition(existingBlock, cachedItem, cacheKey);<a name="line.432"></a>
+<span class="sourceLineNo">433</span>        if (comparison != 0) {<a name="line.433"></a>
+<span class="sourceLineNo">434</span>          if (comparison &lt; 0) {<a name="line.434"></a>
+<span class="sourceLineNo">435</span>            LOG.warn("Cached block contents differ by nextBlockOnDiskSize. Keeping cached block.");<a name="line.435"></a>
+<span class="sourceLineNo">436</span>            return;<a name="line.436"></a>
+<span class="sourceLineNo">437</span>          } else {<a name="line.437"></a>
+<span class="sourceLineNo">438</span>            LOG.warn("Cached block contents differ by nextBlockOnDiskSize. Caching new block.");<a name="line.438"></a>
+<span class="sourceLineNo">439</span>          }<a name="line.439"></a>
+<span class="sourceLineNo">440</span>        } else {<a name="line.440"></a>
+<span class="sourceLineNo">441</span>          String msg = "Caching an already cached block: " + cacheKey;<a name="line.441"></a>
+<span class="sourceLineNo">442</span>          msg += ". This is harmless and can happen in rare cases (see HBASE-8547)";<a name="line.442"></a>
+<span class="sourceLineNo">443</span>          LOG.warn(msg);<a name="line.443"></a>
+<span class="sourceLineNo">444</span>          return;<a name="line.444"></a>
+<span class="sourceLineNo">445</span>        }<a name="line.445"></a>
+<span class="sourceLineNo">446</span>      } finally {<a name="line.446"></a>
+<span class="sourceLineNo">447</span>        // return the block since we need to decrement the count<a name="line.447"></a>
+<span class="sourceLineNo">448</span>        returnBlock(cacheKey, existingBlock);<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><a name="line.451"></a>
+<span class="sourceLineNo">452</span>    /*<a name="line.452"></a>
+<span class="sourceLineNo">453</span>     * Stuff the entry into the RAM cache so it can get drained to the persistent store<a name="line.453"></a>
+<span class="sourceLineNo">454</span>     */<a name="line.454"></a>
+<span class="sourceLineNo">455</span>    RAMQueueEntry re =<a name="line.455"></a>
+<span class="sourceLineNo">456</span>        new RAMQueueEntry(cacheKey, cachedItem, accessCount.incrementAndGet(), inMemory);<a name="line.456"></a>
+<span class="sourceLineNo">457</span>    if (ramCache.putIfAbsent(cacheKey, re) != null) {<a name="line.457"></a>
+<span class="sourceLineNo">458</span>      return;<a name="line.458"></a>
+<span class="sourceLineNo">459</span>    }<a name="line.459"></a>
+<span class="sourceLineNo">460</span>    int queueNum = (cacheKey.hashCode() &amp; 0x7FFFFFFF) % writerQueues.size();<a name="line.460"></a>
+<span class="sourceLineNo">461</span>    BlockingQueue&lt;RAMQueueEntry&gt; bq = writerQueues.get(queueNum);<a name="line.461"></a>
+<span class="sourceLineNo">462</span>    boolean successfulAddition = false;<a name="line.462"></a>
+<span class="sourceLineNo">463</span>    if (wait) {<a name="line.463"></a>
+<span class="sourceLineNo">464</span>      try {<a name="line.464"></a>
+<span class="sourceLineNo">465</span>        successfulAddition = bq.offer(re, DEFAULT_CACHE_WAIT_TIME, TimeUnit.MILLISECONDS);<a name="line.465"></a>
+<span class="sourceLineNo">466</span>      } catch (InterruptedException e) {<a name="line.466"></a>
+<span class="sourceLineNo">467</span>        Thread.currentThread().interrupt();<a name="line.467"></a>
+<span class="sourceLineNo">468</span>      }<a name="line.468"></a>
+<span class="sourceLineNo">469</span>    } else {<a name="line.469"></a>
+<span class="sourceLineNo">470</span>      successfulAddition = bq.offer(re);<a name="line.470"></a>
+<span class="sourceLineNo">471</span>    }<a name="line.471"></a>
+<span class="sourceLineNo">472</span>    if (!successfulAddition) {<a name="line.472"></a>
+<span class="sourceLineNo">473</span>      ramCache.remove(cacheKey);<a name="line.473"></a>
+<span class="sourceLineNo">474</span>      cacheStats.failInsert();<a name="line.474"></a>
+<span class="sourceLineNo">475</span>    } else {<a name="line.475"></a>
+<span class="sourceLineNo">476</span>      this.blockNumber.increment();<a name="line.476"></a>
+<span class="sourceLineNo">477</span>      this.heapSize.add(cachedItem.heapSize());<a name="line.477"></a>
+<span class="sourceLineNo">478</span>      blocksByHFile.add(cacheKey);<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>  /**<a name="line.482"></a>
+<span class="sourceLineNo">483</span>   * Get the buffer of the block with the specified key.<a name="line.483"></a>
+<span class="sourceLineNo">484</span>   * @param key block's cache key<a name="line.484"></a>
+<span class="sourceLineNo">485</span>   * @param caching true if the caller caches blocks on cache misses<a name="line.485"></a>
+<span class="sourceLineNo">486</span>   * @param repeat Whether this is a repeat lookup for the same block<a name="line.486"></a>
+<span class="sourceLineNo">487</span>   * @param updateCacheMetrics Whether we should update cache metrics or not<a name="line.487"></a>
+<span class="sourceLineNo">488</span>   * @return buffer of specified cache key, or null if not in cache<a name="line.488"></a>
+<span class="sourceLineNo">489</span>   */<a name="line.489"></a>
+<span class="sourceLineNo">490</span>  @Override<a name="line.490"></a>
+<span class="sourceLineNo">491</span>  public Cacheable getBlock(BlockCacheKey key, boolean caching, boolean repeat,<a name="line.491"></a>
+<span class="sourceLineNo">492</span>      boolean updateCacheMetrics) {<a name="line.492"></a>
+<span class="sourceLineNo">493</span>    if (!cacheEnabled) {<a name="line.493"></a>
+<span class="sourceLineNo">494</span>      return null;<a name="line.494"></a>
+<span class="sourceLineNo">495</span>    }<a name="line.495"></a>
+<span class="sourceLineNo">496</span>    RAMQueueEntry re = ramCache.get(key);<a name="line.496"></a>
+<span class="sourceLineNo">497</span>    if (re != null) {<a name="line.497"></a>
+<span class="sourceLineNo">498</span>      if (updateCacheMetrics) {<a name="line.498"></a>
+<span class="sourceLineNo">499</span>        cacheStats.hit(caching, key.isPrimary(), key.getBlockType());<a name="line.499"></a>
+<span class="sourceLineNo">500</span>      }<a name="line.500"></a>
+<span class="sourceLineNo">501</span>      re.access(accessCount.incrementAndGet());<a name="line.501"></a>
+<span class="sourceLineNo">502</span>      return re.getData();<a name="line.502"></a>
+<span class="sourceLineNo">503</span>    }<a name="line.503"></a>
+<span class="sourceLineNo">504</span>    BucketEntry bucketEntry = backingMap.get(key);<a name="line.504"></a>
+<span class="sourceLineNo">505</span>    if (bucketEntry != null) {<a name="line.505"></a>
+<span class="sourceLineNo">506</span>      long start = System.nanoTime();<a name="line.506"></a>
+<span class="sourceLineNo">507</span>      ReentrantReadWriteLock lock = offsetLock.getLock(bucketEntry.offset());<a name="line.507"></a>
+<span class="sourceLineNo">508</span>      try {<a name="line.508"></a>
+<span class="sourceLineNo">509</span>        lock.readLock().lock();<a name="line.509"></a>
+<span class="sourceLineNo">510</span>        // We can not read here even if backingMap does contain the given key because its offset<a name="line.510"></a>
+<span class="sourceLineNo">511</span>        // maybe changed. If we lock BlockCacheKey instead of offset, then we can only check<a name="line.511"></a>
+<span class="sourceLineNo">512</span>        // existence here.<a name="line.512"></a>
+<span class="sourceLineNo">513</span>        if (bucketEntry.equals(backingMap.get(key))) {<a name="line.513"></a>
+<span class="sourceLineNo">514</span>          // TODO : change this area - should be removed after server cells and<a name="line.514"></a>
+<span class="sourceLineNo">515</span>          // 12295 are available<a name="line.515"></a>
+<span class="sourceLineNo">516</span>          int len = bucketEntry.getLength();<a name="line.516"></a>
+<span class="sourceLineNo">517</span>          if (LOG.isTraceEnabled()) {<a name="line.517"></a>
+<span class="sourceLineNo">518</span>            LOG.trace("Read offset=" + bucketEntry.offset() + ", len=" + len);<a name="line.518"></a>
 <span class="sourceLineNo">519</span>          }<a name="line.519"></a>
-<span class="sourceLineNo">520</span>          if (cachedBlock.getMemoryType() == MemoryType.SHARED) {<a name="line.520"></a>
-<span class="sourceLineNo">521</span>            bucketEntry.incrementRefCountAndGet();<a name="line.521"></a>
-<span class="sourceLineNo">522</span>          }<a name="line.522"></a>
-<span class="sourceLineNo">523</span>          bucketEntry.access(accessCount.incrementAndGet());<a name="line.523"></a>
-<span class="sourceLineNo">524</span>          if (this.ioErrorStartTime &gt; 0) {<a name="line.524"></a>
-<span class="sourceLineNo">525</span>            ioErrorStartTime = -1;<a name="line.525"></a>
+<span class="sourceLineNo">520</span>          Cacheable cachedBlock = ioEngine.read(bucketEntry.offset(), len,<a name="line.520"></a>
+<span class="sourceLineNo">521</span>              bucketEntry.deserializerReference(this.deserialiserMap));<a name="line.521"></a>
+<span class="sourceLineNo">522</span>          long timeTaken = System.nanoTime() - start;<a name="line.522"></a>
+<span class="sourceLineNo">523</span>          if (updateCacheMetrics) {<a name="line.523"></a>
+<span class="sourceLineNo">524</span>            cacheStats.hit(caching, key.isPrimary(), key.getBlockType());<a name="line.524"></a>
+<span class="sourceLineNo">525</span>            cacheStats.ioHit(timeTaken);<a name="line.525"></a>
 <span class="sourceLineNo">526</span>          }<a name="line.526"></a>
-<span class="sourceLineNo">527</span>          return cachedBlock;<a name="line.527"></a>
-<span class="sourceLineNo">528</span>        }<a name="line.528"></a>
-<span class="sourceLineNo">529</span>      } catch (IOException ioex) {<a name="line.529"></a>
-<span class="sourceLineNo">530</span>        LOG.error("Failed reading block " + key + " from bucket cache", ioex);<a name="line.530"></a>
-<span class="sourceLineNo">531</span>        checkIOErrorIsTolerated();<a name="line.531"></a>
-<span class="sourceLineNo">532</span>      } finally {<a name="line.532"></a>
-<span class="sourceLineNo">533</span>        lock.readLock().unlock();<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>    if (!repeat &amp;&amp; updateCacheMetrics) {<a name="line.536"></a>
-<span class="sourceLineNo">537</span>      cacheStats.miss(caching, key.isPrimary(), key.getBlockType());<a name="line.537"></a>
-<span class="sourceLineNo">538</span>    }<a name="line.538"></a>
-<span class="sourceLineNo">539</span>    return null;<a name="line.539"></a>
-<span class="sourceLineNo">540</span>  }<a name="line.540"></a>
-<span class="sourceLineNo">541</span><a name="line.541"></a>
-<span class="sourceLineNo">542</span>  @VisibleForTesting<a name="line.542"></a>
-<span class="sourceLineNo">543</span>  void blockEvicted(BlockCacheKey cacheKey, BucketEntry bucketEntry, boolean decrementBlockNumber) {<a name="line.543"></a>
-<span class="sourceLineNo">544</span>    bucketAllocator.freeBlock(bucketEntry.offset());<a name="line.544"></a>
-<span class="sourceLineNo">545</span>    realCacheSize.add(-1 * bucketEntry.getLength());<a name="line.545"></a>
-<span class="sourceLineNo">546</span>    blocksByHFile.remove(cacheKey);<a name="line.546"></a>
-<span class="sourceLineNo">547</span>    if (decrementBlockNumber) {<a name="line.547"></a>
-<span class="sourceLineNo">548</span>      this.blockNumber.decrement();<a name="line.548"></a>
-<span class="sourceLineNo">549</span>    }<a name="line.549"></a>
-<span class="sourceLineNo">550</span>  }<a name="line.550"></a>
-<span class="sourceLineNo">551</span><a name="line.551"></a>
-<span class="sourceLineNo">552</span>  @Override<a name="line.552"></a>
-<span class="sourceLineNo">553</span>  public boolean evictBlock(BlockCacheKey cacheKey) {<a name="line.553"></a>
-<span class="sourceLineNo">554</span>    return evictBlock(cacheKey, true);<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>  // does not check for the ref count. Just tries to evict it if found in the<a name="line.557"></a>
-<span class="sourceLineNo">558</span>  // bucket map<a name="line.558"></a>
-<span class="sourceLineNo">559</span>  private boolean forceEvict(BlockCacheKey cacheKey) {<a name="line.559"></a>
-<span class="sourceLineNo">560</span>    if (!cacheEnabled) {<a name="line.560"></a>
-<span class="sourceLineNo">561</span>      return false;<a name="line.561"></a>
-<span class="sourceLineNo">562</span>    }<a name="line.562"></a>
-<span class="sourceLineNo">563</span>    RAMQueueEntry removedBlock = checkRamCache(cacheKey);<a name="line.563"></a>
-<span class="sourceLineNo">564</span>    BucketEntry bucketEntry = backingMap.get(cacheKey);<a name="line.564"></a>
-<span class="sourceLineNo">565</span>    if (bucketEntry == null) {<a name="line.565"></a>
-<span class="sourceLineNo">566</span>      if (removedBlock != null) {<a name="line.566"></a>
-<span class="sourceLineNo">567</span>        cacheStats.evicted(0, cacheKey.isPrimary());<a name="line.567"></a>
-<span class="sourceLineNo">568</span>        return true;<a name="line.568"></a>
-<span class="sourceLineNo">569</span>      } else {<a name="line.569"></a>
-<span class="sourceLineNo">570</span>        return false;<a name="line.570"></a>
-<span class="sourceLineNo">571</span>      }<a name="line.571"></a>
-<span class="sourceLineNo">572</span>    }<a name="line.572"></a>
-<span class="sourceLineNo">573</span>    ReentrantReadWriteLock lock = offsetLock.getLock(bucketEntry.offset());<a name="line.573"></a>
-<span class="sourceLineNo">574</span>    try {<a name="line.574"></a>
-<span class="sourceLineNo">575</span>      lock.writeLock().lock();<a name="line.575"></a>
-<span class="sourceLineNo">576</span>      if (backingMap.remove(cacheKey, bucketEntry)) {<a name="line.576"></a>
-<span class="sourceLineNo">577</span>        blockEvicted(cacheKey, bucketEntry, removedBlock == null);<a name="line.577"></a>
-<span class="sourceLineNo">578</span>      } else {<a name="line.578"></a>
-<span class="sourceLineNo">579</span>        return false;<a name="line.579"></a>
-<span class="sourceLineNo">580</span>      }<a name="line.580"></a>
-<span class="sourceLineNo">581</span>    } finally {<a name="line.581"></a>
-<span class="sourceLineNo">582</span>      lock.writeLock().unlock();<a name="line.582"></a>
-<span class="sourceLineNo">583</span>    }<a name="line.583"></a>
-<span class="sourceLineNo">584</span>    cacheStats.evicted(bucketEntry.getCachedTime(), cacheKey.isPrimary());<a name="line.584"></a>
-<span class="sourceLineNo">585</span>    return true;<a name="line.585"></a>
-<span class="sourceLineNo">586</span>  }<a name="line.586"></a>
-<span class="sourceLineNo">587</span><a name="line.587"></a>
-<span class="sourceLineNo">588</span>  private RAMQueueEntry checkRamCache(BlockCacheKey cacheKey) {<a name="line.588"></a>
-<span class="sourceLineNo">589</span>    RAMQueueEntry removedBlock = ramCache.remove(cacheKey);<a name="line.589"></a>
-<span class="sourceLineNo">590</span>    if (removedBlock != null) {<a name="line.590"></a>
-<span class="sourceLineNo">591</span>      this.blockNumber.decrement();<a name="line.591"></a>
-<span class="sourceLineNo">592</span>      this.heapSize.add(-1 * removedBlock.getData().heapSize());<a name="line.592"></a>
-<span class="sourceLineNo">593</span>    }<a name="line.593"></a>
-<span class="sourceLineNo">594</span>    return removedBlock;<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>  public boolean evictBlock(BlockCacheKey cacheKey, boolean deletedBlock) {<a name="line.597"></a>
-<span class="sourceLineNo">598</span>    if (!cacheEnabled) {<a name="line.598"></a>
-<span class="sourceLineNo">599</span>      return false;<a name="line.599"></a>
+<span class="sourceLineNo">527</span>          if (cachedBlock.getMemoryType() == MemoryType.SHARED) {<a name="line.527"></a>
+<span class="sourceLineNo">528</span>            bucketEntry.incrementRefCountAndGet();<a name="line.528"></a>
+<span class="sourceLineNo">529</span>          }<a name="line.529"></a>
+<span class="sourceLineNo">530</span>          bucketEntry.access(accessCount.incrementAndGet());<a name="line.530"></a>
+<span class="sourceLineNo">531</span>          if (this.ioErrorStartTime &gt; 0) {<a name="line.531"></a>
+<span class="sourceLineNo">532</span>            ioErrorStartTime = -1;<a name="line.532"></a>
+<span class="sourceLineNo">533</span>          }<a name="line.533"></a>
+<span class="sourceLineNo">534</span>          return cachedBlock;<a name="line.534"></a>
+<span class="sourceLineNo">535</span>        }<a name="line.535"></a>
+<span class="sourceLineNo">536</span>      } catch (IOException ioex) {<a name="line.536"></a>
+<span class="sourceLineNo">537</span>        LOG.error("Failed reading block " + key + " from bucket cache", ioex);<a name="line.537"></a>
+<span class="sourceLineNo">538</span>        checkIOErrorIsTolerated();<a name="line.538"></a>
+<span class="sourceLineNo">539</span>      } finally {<a name="line.539"></a>
+<span class="sourceLineNo">540</span>        lock.readLock().unlock();<a name="line.540"></a>
+<span class="sourceLineNo">541</span>      }<a name="line.541"></a>
+<span class="sourceLineNo">542</span>    }<a name="line.542"></a>
+<span class="sourceLineNo">543</span>    if (!repeat &amp;&amp; updateCacheMetrics) {<a name="line.543"></a>
+<span class="sourceLineNo">544</span>      cacheStats.miss(caching, key.isPrimary(), key.getBlockType());<a name="line.544"></a>
+<span class="sourceLineNo">545</span>    }<a name="line.545"></a>
+<span class="sourceLineNo">546</span>    return null;<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>  @VisibleForTesting<a name="line.549"></a>
+<span class="sourceLineNo">550</span>  void blockEvicted(BlockCacheKey cacheKey, BucketEntry bucketEntry, boolean decrementBlockNumber) {<a name="line.550"></a>
+<span class="sourceLineNo">551</span>    bucketAllocator.freeBlock(bucketEntry.offset());<a name="line.551"></a>
+<span class="sourceLineNo">552</span>    realCacheSize.add(-1 * bucketEntry.getLength());<a name="line.552"></a>
+<span class="sourceLineNo">553</span>    blocksByHFile.remove(cacheKey);<a name="line.553"></a>
+<span class="sourceLineNo">554</span>    if (decrementBlockNumber) {<a name="line.554"></a>
+<span class="sourceLineNo">555</span>      this.blockNumber.decrement();<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>  @Override<a name="line.559"></a>
+<span class="sourceLineNo">560</span>  public boolean evictBlock(BlockCacheKey cacheKey) {<a name="line.560"></a>
+<span class="sourceLineNo">561</span>    return evictBlock(cacheKey, true);<a name="line.561"></a>
+<span class="sourceLineNo">562</span>  }<a name="line.562"></a>
+<span class="sourceLineNo">563</span><a name="line.563"></a>
+<span class="sourceLineNo">564</span>  // does not check for the ref count. Just tries to evict it if found in the<a name="line.564"></a>
+<span class="sourceLineNo">565</span>  // bucket map<a name="line.565"></a>
+<span class="sourceLineNo">566</span>  private boolean forceEvict(BlockCacheKey cacheKey) {<a name="line.566"></a>
+<span class="sourceLineNo">567</span>    if (!cacheEnabled) {<a name="line.567"></a>
+<span class="sourceLineNo">568</span>      return false;<a name="line.568"></a>
+<span class="sourceLineNo">569</span>    }<a name="line.569"></a>
+<span class="sourceLineNo">570</span>    RAMQueueEntry removedBlock = checkRamCache(cacheKey);<a name="line.570"></a>
+<span class="sourceLineNo">571</span>    BucketEntry bucketEntry = backingMap.get(cacheKey);<a name="line.571"></a>
+<span class="sourceLineNo">572</span>    if (bucketEntry == null) {<a name="line.572"></a>
+<span class="sourceLineNo">573</span>      if (removedBlock != null) {<a name="line.573"></a>
+<span class="sourceLineNo">574</span>        cacheStats.evicted(0, cacheKey.isPrimary());<a name="line.574"></a>
+<span class="sourceLineNo">575</span>        return true;<a name="line.575"></a>
+<span class="sourceLineNo">576</span>      } else {<a name="line.576"></a>
+<span class="sourceLineNo">577</span>        return false;<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>    ReentrantReadWriteLock lock = offsetLock.getLock(bucketEntry.offset());<a name="line.580"></a>
+<span class="sourceLineNo">581</span>    try {<a name="line.581"></a>
+<span class="sourceLineNo">582</span>      lock.writeLock().lock();<a name="line.582"></a>
+<span class="sourceLineNo">583</span>      if (backingMap.remove(cacheKey, bucketEntry)) {<a name="line.583"></a>
+<span class="sourceLineNo">584</span>        blockEvicted(cacheKey, bucketEntry, removedBlock == null);<a name="line.584"></a>
+<span class="sourceLineNo">585</span>      } else {<a name="line.585"></a>
+<span class="sourceLineNo">586</span>        return false;<a name="line.586"></a>
+<span class="sourceLineNo">587</span>      }<a name="line.587"></a>
+<span class="sourceLineNo">588</span>    } finally {<a name="line.588"></a>
+<span class="sourceLineNo">589</span>      lock.writeLock().unlock();<a name="line.589"></a>
+<span class="sourceLineNo">590</span>    }<a name="line.590"></a>
+<span class="sourceLineNo">591</span>    cacheStats.evicted(bucketEntry.getCachedTime(), cacheKey.isPrimary());<a name="line.591"></a>
+<span class="sourceLineNo">592</span>    return true;<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>  private RAMQueueEntry checkRamCache(BlockCacheKey cacheKey) {<a name="line.595"></a>
+<span class="sourceLineNo">596</span>    RAMQueueEntry removedBlock = ramCache.remove(cacheKey);<a name="line.596"></a>
+<span class="sourceLineNo">597</span>    if (removedBlock != null) {<a name="line.597"></a>
+<span class="sourceLineNo">598</span>      this.blockNumber.decrement();<a name="line.598"></a>
+<span class="sourceLineNo">599</span>      this.heapSize.add(-1 * removedBlock.getData().heapSize());<a name="line.599"></a>
 <span class="sourceLineNo">600</span>    }<a name="line.600"></a>
-<span class="sourceLineNo">601</span>    RAMQueueEntry removedBlock = checkRamCache(cacheKey);<a name="line.601"></a>
-<span class="sourceLineNo">602</span>    BucketEntry bucketEntry = backingMap.get(cacheKey);<a name="line.602"></a>
-<span class="sourceLineNo">603</span>    if (bucketEntry == null) {<a name="line.603"></a>
-<span class="sourceLineNo">604</span>      if (removedBlock != null) {<a name="line.604"></a>
-<span class="sourceLineNo">605</span>        cacheStats.evicted(0, cacheKey.isPrimary());<a name="line.605"></a>
-<span class="sourceLineNo">606</span>        return true;<a name="line.606"></a>
-<span class="sourceLineNo">607</span>      } else {<a name="line.607"></a>
-<span class="sourceLineNo">608</span>        return false;<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>    ReentrantReadWriteLock lock = offsetLock.getLock(bucketEntry.offset());<a name="line.611"></a>
-<span class="sourceLineNo">612</span>    try {<a name="line.612"></a>
-<span class="sourceLineNo">613</span>      lock.writeLock().lock();<a name="line.613"></a>
-<span class="sourceLineNo">614</span>      int refCount = bucketEntry.getRefCount();<a name="line.614"></a>
-<span class="sourceLineNo">615</span>      if (refCount == 0) {<a name="line.615"></a>
-<span class="sourceLineNo">616</span>        if (backingMap.remove(cacheKey, bucketEntry)) {<a name="line.616"></a>
-<span class="sourceLineNo">617</span>          blockEvicted(cacheKey, bucketEntry, removedBlock == null);<a name="line.617"></a>
-<span class="sourceLineNo">618</span>        } else {<a name="line.618"></a>
-<span class="sourceLineNo">619</span>          return false;<a name="line.619"></a>
-<span class="sourceLineNo">620</span>        }<a name="line.620"></a>
-<span class="sourceLineNo">621</span>      } else {<a name="line.621"></a>
-<span class="sourceLineNo">622</span>        if(!deletedBlock) {<a name="line.622"></a>
-<span class="sourceLineNo">623</span>          if (LOG.isDebugEnabled()) {<a name="line.623"></a>
-<span class="sourceLineNo">624</span>            LOG.debug("This block " + cacheKey + " is still referred by " + refCount<a name="line.624"></a>
-<span class="sourceLineNo">625</span>                + " readers. Can not be freed now");<a name="line.625"></a>
-<span class="sourceLineNo">626</span>          }<a name="line.626"></a>
-<span class="sourceLineNo">627</span>          return false;<a name="line.627"></a>
-<span class="sourceLineNo">628</span>        } else {<a name="line.628"></a>
-<span class="sourceLineNo">629</span>          if (LOG.isDebugEnabled()) {<a name="line.629"></a>
-<span class="sourceLineNo">630</span>            LOG.debug("This block " + cacheKey + " is still referred by " + refCount<a name="line.630"></a>
-<span class="sourceLineNo">631</span>                + " readers. Can not be freed now. Hence will mark this"<a name="line.631"></a>
-<span class="sourceLineNo">632</span>                + " for evicting at a later point");<a name="line.632"></a>
+<span class="sourceLineNo">601</span>    return removedBlock;<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>  public boolean evictBlock(BlockCacheKey cacheKey, boolean deletedBlock) {<a name="line.604"></a>
+<span class="sourceLineNo">605</span>    if (!cacheEnabled) {<a name="line.605"></a>
+<span class="sourceLineNo">606</span>      return false;<a name="line.606"></a>
+<span class="sourceLineNo">607</span>    }<a name="line.607"></a>
+<span class="sourceLineNo">608</span>    RAMQueueEntry removedBlock = checkRamCache(cacheKey);<a name="line.608"></a>
+<span class="sourceLineNo">609</span>    BucketEntry bucketEntry = backingMap.get(cacheKey);<a name="line.609"></a>
+<span class="sourceLineNo">610</span>    if (bucketEntry == null) {<a name="line.610"></a>
+<span class="sourceLineNo">611</span>      if (removedBlock != null) {<a name="line.611"></a>
+<span class="sourceLineNo">612</span>        cacheStats.evicted(0, cacheKey.isPrimary());<a name="line.612"></a>
+<span class="sourceLineNo">613</span>        return true;<a name="line.613"></a>
+<span class="sourceLineNo">614</span>      } else {<a name="line.614"></a>
+<span class="sourceLineNo">615</span>        return false;<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>    ReentrantReadWriteLock lock = offsetLock.getLock(bucketEntry.offset());<a name="line.618"></a>
+<span class="sourceLineNo">619</span>    try {<a name="line.619"></a>
+<span class="sourceLineNo">620</span>      lock.writeLock().lock();<a name="line.620"></a>
+<span class="sourceLineNo">621</span>      int refCount = bucketEntry.getRefCount();<a name="line.621"></a>
+<span class="sourceLineNo">622</span>      if (refCount == 0) {<a name="line.622"></a>
+<span class="sourceLineNo">623</span>        if (backingMap.remove(cacheKey, bucketEntry)) {<a name="line.623"></a>
+<span class="sourceLineNo">624</span>          blockEvicted(cacheKey, bucketEntry, removedBlock == null);<a name="line.624"></a>
+<span class="sourceLineNo">625</span>        } else {<a name="line.625"></a>
+<span class="sourceLineNo">626</span>          return false;<a name="line.626"></a>
+<span class="sourceLineNo">627</span>        }<a name="line.627"></a>
+<span class="sourceLineNo">628</span>      } else {<a name="line.628"></a>
+<span class="sourceLineNo">629</span>        if(!deletedBlock) {<a name="line.629"></a>
+<span class="sourceLineNo">630</span>          if (LOG.isDebugEnabled()) {<a name="line.630"></a>
+<span class="sourceLineNo">631</span>            LOG.debug("This block " + cacheKey + " is still referred by " + refCount<a name="line.631"></a>
+<span class="sourceLineNo">632</span>                + " readers. Can not be freed now");<a name="line.632"></a>
 <span class="sourceLineNo">633</span>          }<a name="line.633"></a>
-<span class="sourceLineNo">634</span>          bucketEntry.markForEvict();<a name="line.634"></a>
-<span class="sourceLineNo">635</span>        }<a name="line.635"></a>
-<span class="sourceLineNo">636</span>      }<a name="line.636"></a>
-<span class="sourceLineNo">637</span>    } finally {<a name="line.637"></a>
-<span class="sourceLineNo">638</span>      lock.writeLock().unlock();<a name="line.638"></a>
-<span class="sourceLineNo">639</span>    }<a name="line.639"></a>
-<span class="sourceLineNo">640</span>    cacheStats.evicted(bucketEntry.getCachedTime(), cacheKey.isPrimary());<a name="line.640"></a>
-<span class="sourceLineNo">641</span>    return true;<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>   * Statistics thread.  Periodically output cache statistics to the log.<a name="line.645"></a>
-<span class="sourceLineNo">646</span>   */<a name="line.646"></a>
-<span class="sourceLineNo">647</span>  private static class StatisticsThread extends Thread {<a name="line.647"></a>
-<span class="sourceLineNo">648</span>    private final BucketCache bucketCache;<a name="line.648"></a>
-<span class="sourceLineNo">649</span><a name="line.649"></a>
-<span class="sourceLineNo">650</span>    public StatisticsThread(BucketCache bucketCache) {<a name="line.650"></a>
-<span class="sourceLineNo">651</span>      super("BucketCacheStatsThread");<a name="line.651"></a>
-<span class="sourceLineNo">652</span>      setDaemon(true);<a name="line.652"></a>
-<span class="sourceLineNo">653</span>      this.bucketCache = bucketCache;<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 void run() {<a name="line.657"></a>
-<span class="sourceLineNo">658</span>      bucketCache.logStats();<a name="line.658"></a>
-<span class="sourceLineNo">659</span>    }<a name="line.659"></a>
-<span class="sourceLineNo">660</span>  }<a name="line.660"></a>
-<span class="sourceLineNo">661</span><a name="line.661"></a>
-<span class="sourceLineNo">662</span>  public void logStats() {<a name="line.662"></a>
-<span class="sourceLineNo">663</span>    long totalSize = bucketAllocator.getTotalSize();<a name="line.663"></a>
-<span class="sourceLineNo">664</span>    long usedSize = bucketAllocator.getUsedSize();<a name="line.664"></a>
-<span class="sourceLineNo">665</span>    long freeSize = totalSize - usedSize;<a name="line.665"></a>
-<span class="sourceLineNo">666</span>    long cacheSize = getRealCacheSize();<a name="line.666"></a>
-<span class="sourceLineNo">667</span>    LOG.info("failedBlockAdditions=" + cacheStats.getFailedInserts() + ", " +<a name="line.667"></a>
-<span class="sourceLineNo">668</span>        "totalSize=" + StringUtils.byteDesc(totalSize) + ", " +<a name="line.668"></a>
-<span class="sourceLineNo">669</span>        "freeSize=" + StringUtils.byteDesc(freeSize) + ", " +<a name="line.669"></a>
-<span class="sourceLineNo">670</span>        "usedSize=" + StringUtils.byteDesc(usedSize) +", " +<a name="line.670"></a>
-<span class="sourceLineNo">671</span>        "cacheSize=" + StringUtils.byteDesc(cacheSize) +", " +<a name="line.671"></a>
-<span class="sourceLineNo">672</span>        "accesses=" + cacheStats.getRequestCount() + ", " +<a name="line.672"></a>
-<span class="sourceLineNo">673</span>        "hits=" + cacheStats.getHitCount() + ", " +<a name="line.673"></a>
-<span class="sourceLineNo">674</span>        "IOhitsPerSecond=" + cacheStats.getIOHitsPerSecond() + ", " +<a name="line.674"></a>
-<span class="sourceLineNo">675</span>        "IOTimePerHit=" + String.format("%.2f", cacheStats.getIOTimePerHit())+ ", " +<a name="line.675"></a>
-<span class="sourceLineNo">676</span>        "hitRatio=" + (cacheStats.getHitCount() == 0 ? "0," :<a name="line.676"></a>
-<span class="sourceLineNo">677</span>          (StringUtils.formatPercent(cacheStats.getHitRatio(), 2)+ ", ")) +<a name="line.677"></a>
-<span class="sourceLineNo">678</span>        "cachingAccesses=" + cacheStats.getRequestCachingCount() + ", " +<a name="line.678"></a>
-<span class="sourceLineNo">679</span>        "cachingHits=" + cacheStats.getHitCachingCount() + ", " +<a name="line.679"></a>
-<span class="sourceLineNo">680</span>        "cachingHitsRatio=" +(cacheStats.getHitCachingCount() == 0 ? "0," :<a name="line.680"></a>
-<span class="sourceLineNo">681</span>          (StringUtils.formatPercent(cacheStats.getHitCachingRatio(), 2)+ ", ")) +<a name="line.681"></a>
-<span class="sourceLineNo">682</span>        "evictions=" + cacheStats.getEvictionCount() + ", " +<a name="line.682"></a>
-<span class="sourceLineNo">683</span>        "evicted=" + cacheStats.getEvictedCount() + ", " +<a name="line.683"></a>
-<span class="sourceLineNo">684</span>        "evictedPerRun=" + cacheStats.evictedPerEviction());<a name="line.684"></a>
-<span class="sourceLineNo">685</span>    cacheStats.reset();<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>  public long getRealCacheSize() {<a name="line.688"></a>
-<span class="sourceLineNo">689</span>    return this.realCacheSize.sum();<a name="line.689"></a>
-<span class="sourceLineNo">690</span>  }<a name="line.690"></a>
-<span class="sourceLineNo">691</span><a name="line.691"></a>
-<span class="sourceLineNo">692</span>  private long acceptableSize() {<a name="line.692"></a>
-<span class="sourceLineNo">693</span>    return (long) Math.floor(bucketAllocator.getTotalSize() * acceptableFactor);<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>  @VisibleForTesting<a name="line.696"></a>
-<span class="sourceLineNo">697</span>  long getPartitionSize(float partitionFactor) {<a name="line.697"></a>
-<span class="sourceLineNo">698</span>    return (long) Math.floor(bucketAllocator.getTotalSize() * partitionFactor * minFactor);<a name="line.698"></a>
-<span class="sourceLineNo">699</span>  }<a name="line.699"></a>
-<span class="sourceLineNo">700</span><a name="line.700"></a>
-<span class="sourceLineNo">701</span>  /**<a name="line.701"></a>
-<span class="sourceLineNo">702</span>   * Return the count of bucketSizeinfos still need free space<a name="line.702"></a>
-<span class="sourceLineNo">703</span>   */<a name="line.703"></a>
-<span class="sourceLineNo">704</span>  private int bucketSizesAboveThresholdCount(float minFactor) {<a name="line.704"></a>
-<span class="sourceLineNo">705</span>    BucketAllocator.IndexStatistics[] stats = bucketAllocator.getIndexStatistics();<a name="line.705"></a>
-<span class="sourceLineNo">706</span>    int fullCount = 0;<a name="line.706"></a>
-<span class="sourceLineNo">707</span>    for (int i = 0; i &lt; stats.length; i++) {<a name="line.707"></a>
-<span class="sourceLineNo">708</span>      long freeGoal = (long) Math.floor(stats[i].totalCount() * (1 - minFactor));<a name="line.708"></a>
-<span class="sourceLineNo">709</span>      freeGoal = Math.max(freeGoal, 1);<a name="line.709"></a>
-<span class="sourceLineNo">710</span>      if (stats[i].freeCount() &lt; freeGoal) {<a name="line.710"></a>
-<span class="sourceLineNo">711</span>        fullCount++;<a name="line.711"></a>
-<span class="sourceLineNo">712</span>      }<a name="line.712"></a>
-<span class="sourceLineNo">713</span>    }<a name="line.713"></a>
-<span class="sourceLineNo">714</span>    return fullCount;<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">717</span>  /**<a name="line.717"></a>
-<span class="sourceLineNo">718</span>   * This method will find the buckets that are minimally occupied<a name="line.718"></a>
-<span class="sourceLineNo">719</span>   * and are not reference counted and will free them completely<a name="line.719"></a>
-<span class="sourceLineNo">720</span>   * without any constraint on the access times of the elements,<a name="line.720"></a>
-<span class="sourceLineNo">721</span>   * and as a process will completely free at most the number of buckets<a name="line.721"></a>
-<span class="sourceLineNo">722</span>   * passed, sometimes it might not due to changing refCounts<a name="line.722"></a>
-<span class="sourceLineNo">723</span>   *<a name="line.723"></a>
-<span class="sourceLineNo">724</span>   * @param completelyFreeBucketsNeeded number of buckets to free<a name="line.724"></a>
-<span class="sourceLineNo">725</span>   **/<a name="line.725"></a>
-<span class="sourceLineNo">726</span>  private void freeEntireBuckets(int completelyFreeBucketsNeeded) {<a name="line.726"></a>
-<span class="sourceLineNo">727</span>    if (completelyFreeBucketsNeeded != 0) {<a name="line.727"></a>
-<span class="sourceLineNo">728</span>      // First we will build a set where the offsets are reference counted, usually<a name="line.728"></a>
-<span class="sourceLineNo">729</span>      // this set is small around O(Handler Count) unless something else is wrong<a name="line.729"></a>
-<span class="sourceLineNo">730</span>      Set&lt;Integer&gt; inUseBuckets = new HashSet&lt;Integer&gt;();<a name="line.730"></a>
-<span class="sourceLineNo">731</span>      for (BucketEntry entry : backingMap.values()) {<a name="line.731"></a>
-<span class="sourceLineNo">732</span>        if (entry.getRefCount() != 0) {<a name="line.732"></a>
-<span class="sourceLineNo">733</span>          inUseBuckets.add(bucketAllocator.getBucketIndex(entry.offset()));<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><a name="line.736"></a>
-<span class="sourceLineNo">737</span>      Set&lt;Integer&gt; candidateBuckets = bucketAllocator.getLeastFilledBuckets(<a name="line.737"></a>
-<span class="sourceLineNo">738</span>          inUseBuckets, completelyFreeBucketsNeeded);<a name="line.738"></a>
-<span class="sourceLineNo">739</span>      for (Map.Entry&lt;BlockCacheKey, BucketEntry&gt; entry : backingMap.entrySet()) {<a name="line.739"></a>
-<span class="sourceLineNo">740</span>        if (candidateBuckets.contains(bucketAllocator<a name="line.740"></a>
-<span class="sourceLineNo">741</span>            .getBucketIndex(entry.getValue().offset()))) {<a name="line.741"></a>
-<span class="sourceLineNo">742</span>          evictBlock(entry.getKey(), false);<a name="line.742"></a>
-<span class="sourceLineNo">743</span>        }<a name="line.743"></a>
-<span class="sourceLineNo">744</span>      }<a name="line.744"></a>
-<span class="sourceLineNo">745</span>    }<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>  /**<a name="line.748"></a>
-<span class="sourceLineNo">749</span>   * Free the space if the used size reaches acceptableSize() or one size block<a name="line.749"></a>
-<span class="sourceLineNo">750</span>   * couldn't be allocated. When freeing the space, we use the LRU algorithm and<a name="line.750"></a>
-<span class="sourceLineNo">751</span>   * ensure there must be some blocks evicted<a name="line.751"></a>
-<span class="sourceLineNo">752</span>   * @param why Why we are being called<a name="line.752"></a>
-<span class="sourceLineNo">753</span>   */<a name="line.753"></a>
-<span class="sourceLineNo">754</span>  private void freeSpace(final String why) {<a name="line.754"></a>
-<span class="sourceLineNo">755</span>    // Ensure only one freeSpace progress at a time<a name="line.755"></a>
-<span class="sourceLineNo">756</span>    if (!freeSpaceLock.tryLock()) {<a name="line.756"></a>
-<span class="sourceLineNo">757</span>      return;<a name="line.757"></a>
-<span class="sourceLineNo">758</span>    }<a name="line.758"></a>
-<span class="sourceLineNo">759</span>    try {<a name="line.759"></a>
-<span class="sourceLineNo">760</span>      freeInProgress = true;<a name="line.760"></a>
-<span class="sourceLineNo">761</span>      long bytesToFreeWithoutExtra = 0;<a name="line.761"></a>
-<span class="sourceLineNo">762</span>      // Calculate free byte for each bucketSizeinfo<a name="line.762"></a>
-<span class="sourceLineNo">763</span>      StringBuilder msgBuffer = LOG.isDebugEnabled()? new StringBuilder(): null;<a name="line.763"></a>
-<span class="sourceLineNo">764</span>      BucketAllocator.IndexStatistics[] stats = bucketAllocator.getIndexStatistics();<a name="line.764"></a>
-<span class="sourceLineNo">765</span>      long[] bytesToFreeForBucket = new long[stats.length];<a name="line.765"></a>
-<span class="sourceLineNo">766</span>      for (int i = 0; i &lt; stats.length; i++) {<a name="line.766"></a>
-<span class="sourceLineNo">767</span>        bytesToFreeForBucket[i] = 0;<a name="line.767"></a>
-<span class="sourceLineNo">768</span>        long freeGoal = (long) Math.floor(stats[i].totalCount() * (1 - minFactor));<a name="line.768"></a>
-<span class="sourceLineNo">769</span>        freeGoal = Math.max(freeGoal, 1);<a name="line.769"></a>
-<span class="sourceLineNo">770</span>        if (stats[i].freeCount() &lt; freeGoal) {<a name="line.770"></a>
-<span class="sourceLineNo">771</span>          bytesToFreeForBucket[i] = stats[i].itemSize() * (freeGoal - stats[i].freeCount());<a name="line.771"></a>
-<span class="sourceLineNo">772</span>          bytesToFreeWithoutExtra += bytesToFreeForBucket[i];<a name="line.772"></a>
-<span class="sourceLineNo">773</span>          if (msgBuffer != null) {<a name="line.773"></a>
-<span class="sourceLineNo">774</span>            msgBuffer.append("Free for bucketSize(" + stats[i].itemSize() + ")="<a name="line.774"></a>
-<span class="sourceLineNo">775</span>              + StringUtils.byteDesc(bytesToFreeForBucket[i]) + ", ");<a name="line.775"></a>
-<span class="sourceLineNo">776</span>          }<a name="line.776"></a>
-<span class="sourceLineNo">777</span>        }<a name="line.777"></a>
-<span class="sourceLineNo">778</span>      }<a name="line.778"></a>
-<span class="sourceLineNo">779</span>      if (msgBuffer != null) {<a name="line.779"></a>
-<span class="sourceLineNo">780</span>        msgBuffer.append("Free for total=" + StringUtils.byteDesc(bytesToFreeWithoutExtra) + ", ");<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>      if (bytesToFreeWithoutExtra &lt;= 0) {<a name="line.783"></a>
-<span class="sourceLineNo">784</span>        return;<a name="line.784"></a>
+<span class="sourceLineNo">634</span>          return false;<a name="line.634"></a>
+<span class="sourceLineNo">635</span>        } else {<a name="line.635"></a>
+<span class="sourceLineNo">636</span>          if (LOG.isDebugEnabled()) {<a name="line.636"></a>
+<span class="sourceLineNo">637</span>            LOG.debug("This block " + cacheKey + " is still referred by " + refCount<a name="line.637"></a>
+<span class="sourceLineNo">638</span>                + " readers. Can not be freed now. Hence will mark this"<a name="line.638"></a>
+<span class="sourceLineNo">639</span>                + " for evicting at a later point");<a name="line.639"></a>
+<span class="sourceLineNo">640</span>          }<a name="line.640"></a>
+<span class="sourceLineNo">641</span>          bucketEntry.markForEvict();<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>    } finally {<a name="line.644"></a>
+<span class="sourceLineNo">645</span>      lock.writeLock().unlock();<a name="line.645"></a>
+<span class="sourceLineNo">646</span>    }<a name="line.646"></a>
+<span class="sourceLineNo">647</span>    cacheStats.evicted(bucketEntry.getCachedTime(), cacheKey.isPrimary());<a name="line.647"></a>
+<span class="sourceLineNo">648</span>    return true;<a name="line.648"></a>
+<span class="sourceLineNo">649</span>  }<a name="line.649"></a>
+<span class="sourceLineNo">650</span><a name="line.650"></a>
+<span class="sourceLineNo">651</span>  /*<a name="line.651"></a>
+<span class="sourceLineNo">652</span>   * Statistics thread.  Periodically output cache statistics to the log.<a name="line.652"></a>
+<span class="sourceLineNo">653</span>   */<a name="line.653"></a>
+<span class="sourceLineNo">654</span>  private static class StatisticsThread extends Thread {<a name="line.654"></a>
+<span class="sourceLineNo">655</span>    private final BucketCache bucketCache;<a name="line.655"></a>
+<span class="sourceLineNo">656</span><a name="line.656"></a>
+<span class="sourceLineNo">657</span>    public StatisticsThread(BucketCache bucketCache) {<a name="line.657"></a>
+<span class="sourceLineNo">658</span>      super("BucketCacheStatsThread");<a name="line.658"></a>
+<span class="sourceLineNo">659</span>      setDaemon(true);<a name="line.659"></a>
+<span class="sourceLineNo">660</span>      this.bucketCache = bucketCache;<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>    @Override<a name="line.663"></a>
+<span class="sourceLineNo">664</span>    public void run() {<a name="line.664"></a>
+<span class="sourceLineNo">665</span>      bucketCache.logStats();<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>  public void logStats() {<a name="line.669"></a>
+<span class="sourceLineNo">670</span>    long totalSize = bucketAllocator.getTotalSize();<a name="line.670"></a>
+<span class="sourceLineNo">671</span>    long usedSize = bucketAllocator.getUsedSize();<a name="line.671"></a>
+<span class="sourceLineNo">672</span>    long freeSize = totalSize - usedSize;<a name="line.672"></a>
+<span class="sourceLineNo">673</span>    long cacheSize = getRealCacheSize();<a name="line.673"></a>
+<span class="sourceLineNo">674</span>    LOG.info("failedBlockAdditions=" + cacheStats.getFailedInserts() + ", " +<a name="line.674"></a>
+<span class="sourceLineNo">675</span>        "totalSize=" + StringUtils.byteDesc(totalSize) + ", " +<a name="line.675"></a>
+<span class="sourceLineNo">676</span>        "freeSize=" + StringUtils.byteDesc(freeSize) + ", " +<a name="line.676"></a>
+<span class="sourceLineNo">677</span>        "usedSize=" + StringUtils.byteDesc(usedSize) +", " +<a name="line.677"></a>
+<span class="sourceLineNo">678</span>        "cacheSize=" + StringUtils.byteDesc(cacheSize) +", " +<a name="line.678"></a>
+<span class="sourceLineNo">679</span>        "accesses=" + cacheStats.getRequestCount() + ", " +<a name="line.679"></a>
+<span class="sourceLineNo">680</span>        "hits=" + cacheStats.getHitCount() + ", " +<a name="line.680"></a>
+<span class="sourceLineNo">681</span>        "IOhitsPerSecond=" + cacheStats.getIOHitsPerSecond() + ", " +<a name="line.681"></a>
+<span class="sourceLineNo">682</span>        "IOTimePerHit=" + String.format("%.2f", cacheStats.getIOTimePerHit())+ ", " +<a name="line.682"></a>
+<span class="sourceLineNo">683</span>        "hitRatio=" + (cacheStats.getHitCount() == 0 ? "0," :<a name="line.683"></a>
+<span class="sourceLineNo">684</span>          (StringUtils.formatPercent(cacheStats.getHitRatio(), 2)+ ", ")) +<a name="line.684"></a>
+<span class="sourceLineNo">685</span>        "cachingAccesses=" + cacheStats.getRequestCachingCount() + ", " +<a name="line.685"></a>
+<span class="sourceLineNo">686</span>        "cachingHits=" + cacheStats.getHitCachingCount() + ", " +<a name="line.686"></a>
+<span class="sourceLineNo">687</span>        "cachingHitsRatio=" +(cacheStats.getHitCachingCount() == 0 ? "0," :<a name="line.687"></a>
+<span class="sourceLineNo">688</span>          (StringUtils.formatPercent(cacheStats.getHitCachingRatio(), 2)+ ", ")) +<a name="line.688"></a>
+<span class="sourceLineNo">689</span>        "evictions=" + cacheStats.getEvictionCount() + ", " +<a name="line.689"></a>
+<span class="sourceLineNo">690</span>        "evicted=" + cacheStats.getEvictedCount() + ", " +<a name="line.690"></a>
+<span class="sourceLineNo">691</span>        "evictedPerRun=" + cacheStats.evictedPerEviction());<a name="line.691"></a>
+<span class="sourceLineNo">692</span>    cacheStats.reset();<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>  public long getRealCacheSize() {<a name="line.695"></a>
+<span class="sourceLineNo">696</span>    return this.realCacheSize.sum();<a name="line.696"></a>
+<span class="sourceLineNo">697</span>  }<a name="line.697"></a>
+<span class="sourceLineNo">698</span><a name="line.698"></a>
+<span class="sourceLineNo">699</span>  private long acceptableSize() {<a name="line.699"></a>
+<span class="sourceLineNo">700</span>    return (long) Math.floor(bucketAllocator.getTotalSize() * acceptableFactor);<a name="line.700"></a>
+<span class="sourceLineNo">701</span>  }<a name="line.701"></a>
+<span class="sourceLineNo">702</span><a name="line.702"></a>
+<span class="sourceLineNo">703</span>  @VisibleForTesting<a name="line.703"></a>
+<span class="sourceLineNo">704</span>  long getPartitionSize(float partitionFactor) {<a name="line.704"></a>
+<span class="sourceLineNo">705</span>    return (long) Math.floor(bucketAllocator.getTotalSize() * partitionFactor * minFactor);<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>   * Return the count of bucketSizeinfos still need free space<a name="line.709"></a>
+<span class="sourceLineNo">710</span>   */<a name="line.710"></a>
+<span class="sourceLineNo">711</span>  private int bucketSizesAboveThresholdCount(float minFactor) {<a name="line.711"></a>
+<span class="sourceLineNo">712</span>    BucketAllocator.IndexStatistics[] stats = bucketAllocator.getIndexStatistics();<a name="line.712"></a>
+<span class="sourceLineNo">713</span>    int fullCount = 0;<a name="line.713"></a>
+<span class="sourceLineNo">714</span>    for (int i = 0; i &lt; stats.length; i++) {<a name="line.714"></a>
+<span class="sourceLineNo">715</span>      long freeGoal = (long) Math.floor(stats[i].totalCount() * (1 - minFactor));<a name="line.715"></a>
+<span class="sourceLineNo">716</span>      freeGoal = Math.max(freeGoal, 1);<a name="line.716"></a>
+<span class="sourceLineNo">717</span>      if (stats[i].freeCount() &lt; freeGoal) {<a name="line.717"></a>
+<span class="sourceLineNo">718</span>        fullCount++;<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>
+<span class="sourceLineNo">721</span>    return fullCount;<a name="line.721"></a>
+<span class="sourceLineNo">722</span>  }<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>   * This method will find the buckets that are minimally occupied<a name="line.725"></a>
+<span class="sourceLineNo">726</span>   * and are not reference counted and will free them completely<a name="line.726"></a>
+<span class="sourceLineNo">727</span>   * without any constraint on the access times of the elements,<a name="line.727"></a>
+<span class="sourceLineNo">728</span>   * and as a process will completely free at most the number of buckets<a name="line.728"></a>
+<span class="sourceLineNo">729</span>   * passed, sometimes it might not due to changing refCounts<a name="line.729"></a>
+<span class="sourceLineNo">730</span>   *<a name="line.730"></a>
+<span class="sourceLineNo">731</span>   * @param completelyFreeBucketsNeeded number of buckets to free<a name="line.731"></a>
+<span class="sourceLineNo">732</span>   **/<a name="line.732"></a>
+<span class="sourceLineNo">733</span>  private void freeEntireBuckets(int completelyFreeBucketsNeeded) {<a name="line.733"></a>
+<span class="sourceLineNo">734</span>    if (completelyFreeBucketsNeeded != 0) {<a name="line.734"></a>
+<span class="sourceLineNo">735</span>      // First we will build a set where the offsets are reference counted, usually<a name="line.735"></a>
+<span class="sourceLineNo">736</span>      // this set is small around O(Handler Count) unless something else is wrong<a name="line.736"></a>
+<span class="sourceLineNo">737</span>      Set&lt;Integer&gt; inUseBuckets = new HashSet&lt;Integer&gt;();<a name="line.737"></a>
+<span class="sourceLineNo">738</span>      for (BucketEntry entry : backingMap.values()) {<a name="line.738"></a>
+<span class="sourceLineNo">739</span>        if (entry.getRefCount() != 0) {<a name="line.739"></a>
+<span class="sourceLineNo">740</span>          inUseBuckets.add(bucketAllocator.getBucketIndex(entry.offset()));<a name="line.740"></a>
+<span class="sourceLineNo">741</span>        }<a name="line.741"></a>
+<span class="sourceLineNo">742</span>      }<a name="line.742"></a>
+<span class="sourceLineNo">743</span><a name="line.743"></a>
+<span class="sourceLineNo">744</span>      Set&lt;Integer&gt; candidateBuckets = bucketAllocator.getLeastFilledBuckets(<a name="line.744"></a>
+<span class="sourceLineNo">745</span>          inUseBuckets, completelyFreeBucketsNeeded);<a name="line.745"></a>
+<span class="sourceLineNo">746</span>      for (Map.Entry&lt;BlockCacheKey, BucketEntry&gt; entry : backingMap.entrySet()) {<a name="line.746"></a>
+<span class="sourceLineNo">747</span>        if (candidateBuckets.contains(bucketAllocator<a name="line.747"></a>
+<span class="sourceLineNo">748</span>            .getBucketIndex(entry.getValue().offset()))) {<a name="line.748"></a>
+<span class="sourceLineNo">749</span>          evictBlock(entry.getKey(), false);<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>  }<a name="line.753"></a>
+<span class="sourceLineNo">754</span><a name="line.754"></a>
+<span class="sourceLineNo">755</span>  /**<a name="line.755"></a>
+<span class="sourceLineNo">756</span>   * Free the space if the used size reaches acceptableSize() or one size block<a name="line.756"></a>
+<span class="sourceLineNo">757</span>   * couldn't be allocated. When freeing the space, we use the LRU algorithm and<a name="line.757"></a>
+<span class="sourceLineNo">758</span>   * ensure there must be some blocks evicted<a name="line.758"></a>
+<span class="sourceLineNo">759</span>   * @param why Why we are being called<a name="line.759"></a>
+<span class="sourceLineNo">760</span>   */<a name="line.760"></a>
+<span class="sourceLineNo">761</span>  private void freeSpace(final String why) {<a name="line.761"></a>
+<span class="sourceLineNo">762</span>    // Ensure only one freeSpace progress at a time<a name="line.762"></a>
+<span class="sourceLineNo">763</span>    if (!freeSpaceLock.tryLock()) {<a name="line.763"></a>
+<span class="sourceLineNo">764</span>      return;<a name="line.764"></a>
+<span class="sourceLineNo">765</span>    }<a name="line.765"></a>
+<span class="sourceLineNo">766</span>    try {<a name="line.766"></a>
+<span class="sourceLineNo">767</span>      freeInProgress = true;<a name="line.767"></a>
+<span class="sourceLineNo">768</span>      long bytesToFreeWithoutExtra = 0;<a name="line.768"></a>
+<span class="sourceLineNo">769</span>      // Calculate free byte for each bucketSizeinfo<a name="line.769"></a>
+<span class="sourceLineNo">770</span>      StringBuilder msgBuffer = LOG.isDebugEnabled()? new StringBuilder(): null;<a name="line.770"></a>
+<span class="sourceLineNo">771</span>      BucketAllocator.IndexStatistics[] stats = bucketAllocator.getIndexStatistics();<a name="line.771"></a>
+<span class="sourceLineNo">772</span>      long[] bytesToFreeForBucket = new long[stats.length];<a name="line.772"></a>
+<span class="sourceLineNo">773</span>      for (int i = 0; i &lt; stats.length; i++) {<a name="line.773"></a>
+<span class="sourceLineNo">774</span>        bytesToFreeForBucket[i] = 0;<a name="line.774"></a>
+<span class="sourceLineNo">775</span>        long freeGoal = (long) Math.floor(stats[i].totalCount() * (1 - minFactor));<a name="line.775"></a>
+<span class="sourceLineNo">776</span>        freeGoal = Math.max(freeGoal, 1);<a name="line.776"></a>
+<span class="sourceLineNo">777</span>        if (stats[i].freeCount() &lt; freeGoal) {<a name="line.777"></a>
+<span class="sourceLineNo">778</span>          bytesToFreeForBucket[i] = stats[i].itemSize() * (freeGoal - stats[i].freeCount());<a name="line.778"></a>
+<span class="sourceLineNo">779</span>          bytesToFreeWithoutExtra += bytesToFreeForBucket[i];<a name="line.779"></a>
+<span class="sourceLineNo">780</span>          if (msgBuffer != null) {<a name="line.780"></a>
+<span class="sourceLineNo">781</span>            msgBuffer.append("Free for bucketSize(" + stats[i].itemSize() + ")="<a name="line.781"></a>
+<span class="sourceLineNo">782</span>              + StringUtils.byteDesc(bytesToFreeForBucket[i]) + ", ");<a name="line.782"></a>
+<span class="sourceLineNo">783</span>          }<a name="line.783"></a>
+<span class="sourceLineNo">784</span>        }<a name="line.784"></a>
 <span class="sourceLineNo">785</span>      }<a name="line.785"></a>
-<span class="sourceLineNo">786</span>      long currentSize = bucketAllocator.getUsedSize();<a name="line.786"></a>
-<span class="sourceLineNo">787</span>      long totalSize = bucketAllocator.getTotalSize();<a name="line.787"></a>
-<span class="sourceLineNo">788</span>      if (LOG.isDebugEnabled() &amp;&amp; msgBuffer != null) {<a name="line.788"></a>
-<span class="sourceLineNo">789</span>        LOG.debug("Free started because \"" + why + "\"; " + msgBuffer.toString() +<a name="line.789"></a>
-<span class="sourceLineNo">790</span>          " of current used=" + StringUtils.byteDesc(currentSize) + ", actual cacheSize=" +<a name="line.790"></a>
-<span class="sourceLineNo">791</span>          StringUtils.byteDesc(realCacheSize.sum()) + ", total=" + StringUtils.byteDesc(totalSize));<a name="line.791"></a>
+<span class="sourceLineNo">786</span>      if (msgBuffer != null) {<a name="line.786"></a>
+<span class="sourceLineNo">787</span>        msgBuffer.append("Free for total=" + StringUtils.byteDesc(bytesToFreeWithoutExtra) + ", ");<a name="line.787"></a>
+<span class="sourceLineNo">788</span>      }<a name="line.788"></a>
+<span class="sourceLineNo">789</span><a name="line.789"></a>
+<span class="sourceLineNo">790</span>      if (bytesToFreeWithoutExtra &lt;= 0) {<a name="line.790"></a>
+<span class="sourceLineNo">791</span>        return;<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>
-<span class="sourceLineNo">794</span>      long bytesToFreeWithExtra = (long) Math.floor(bytesToFreeWithoutExtra<a name="line.794"></a>
-<span class="sourceLineNo">795</span>          * (1 + extraFreeFactor));<a name="line.795"></a>
-<span class="sourceLineNo">796</span><a name="line.796"></a>
-<span class="sourceLineNo">797</span>      // Instantiate priority buckets<a name="line.797"></a>
-<span class="sourceLineNo">798</span>      BucketEntryGroup bucketSingle = new BucketEntryGroup(bytesToFreeWithExtra,<a name="line.798"></a>
-<span class="sourceLineNo">799</span>          blockSize, getPartitionSize(singleFactor));<a name="line.799"></a>
-<span class="sourceLineNo">800</span>      BucketEntryGroup bucketMulti = new BucketEntryGroup(bytesToFreeWithExtra,<a name="line.800"></a>
-<span class="sourceLineNo">801</span>          blockSize, getPartitionSize(multiFactor));<a name="line.801"></a>
-<span class="sourceLineNo">802</span>      BucketEntryGroup bucketMemory = new BucketEntryGroup(bytesToFreeWithExtra,<a name="line.802"></a>
-<span class="sourceLineNo">803</span>          blockSize, getPartitionSize(memoryFactor));<a name="line.803"></a>
-<span class="sourceLineNo">804</span><a name="line.804"></a>
-<span class="sourceLineNo">805</span>      // Scan entire map putting bucket entry into appropriate bucket entry<a name="line.805"></a>
-<span class="sourceLineNo">806</span>      // group<a name="line.806"></a>
-<span class="sourceLineNo">807</span>      for (Map.Entry&lt;BlockCacheKey, BucketEntry&gt; bucketEntryWithKey : backingMap.entrySet()) {<a name="line.807"></a>
-<span class="sourceLineNo">808</span>        switch (bucketEntryWithKey.getValue().getPriority()) {<a name="line.808"></a>
-<span class="sourceLineNo">809</span>          case SINGLE: {<a name="line.809"></a>
-<span class="sourceLineNo">810</span>            bucketSingle.add(bucketEntryWithKey);<a name="line.810"></a>
-<span class="sourceLineNo">811</span>            break;<a name="line.811"></a>
-<span class="sourceLineNo">812</span>          }<a name="line.812"></a>
-<span class="sourceLineNo">813</span>          case MULTI: {<a name="line.813"></a>
-<span class="sourceLineNo">814</span>            bucketMulti.add(bucketEntryWithKey);<a name="line.814"></a>
-<span class="sourceLineNo">815</span>            break;<a name="line.815"></a>
-<span class="sourceLineNo">816</span>          }<a name="line.816"></a>
-<span class="sourceLineNo">817</span>          case MEMORY: {<a name="line.817"></a>
-<span class="sourceLineNo">818</span>            bucketMemory.add(bucketEntryWithKey);<a name="line.818"></a>
-<span class="sourceLineNo">819</span>            break;<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><a name="line.823"></a>
-<span class="sourceLineNo">824</span>      PriorityQueue&lt;BucketEntryGroup&gt; bucketQueue = new PriorityQueue&lt;&gt;(3,<a name="line.824"></a>
-<span class="sourceLineNo">825</span>          Comparator.comparingLong(BucketEntryGroup::overflow));<a name="line.825"></a>
-<span class="sourceLineNo">826</span><a name="line.826"></a>
-<span class="sourceLineNo">827</span>      bucketQueue.add(bucketSingle);<a name="line.827"></a>
-<span class="sourceLineNo">828</span>      bucketQueue.add(bucketMulti);<a name="line.828"></a>
-<span class="sourceLineNo">829</span>      bucketQueue.add(bucketMemory);<a name="line.829"></a>
+<span class="sourceLineNo">793</span>      long currentSize = bucketAllocator.getUsedSize();<a name="line.793"></a>
+<span class="sourceLineNo">794</span>      long totalSize = bucketAllocator.getTotalSize();<a name="line.794"></a>
+<span class="sourceLineNo">795</span>      if (LOG.isDebugEnabled() &amp;&amp; msgBuffer != null) {<a name="line.795"></a>
+<span class="sourceLineNo">796</span>        LOG.debug("Free started because \"" + why + "\"; " + msgBuffer.toString() +<a name="line.796"></a>
+<span class="sourceLineNo">797</span>          " of current used=" + StringUtils.byteDesc(currentSize) + ", actual cacheSize=" +<a name="line.797"></a>
+<span class="sourceLineNo">798</span>          StringUtils.byteDesc(realCacheSize.sum()) + ", total=" + StringUtils.byteDesc(totalSize));<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>      long bytesToFreeWithExtra = (long) Math.floor(bytesToFreeWithoutExtra<a name="line.801"></a>
+<span class="sourceLineNo">802</span>          * (1 + extraFreeFactor));<a name="line.802"></a>
+<span class="sourceLineNo">803</span><a name="line.803"></a>
+<span class="sourceLineNo">804</span>      // Instantiate priority buckets<a name="line.804"></a>
+<span class="sourceLineNo">805</span>      BucketEntryGroup bucketSingle = new BucketEntryGroup(bytesToFreeWithExtra,<a name="line.805"></a>
+<span class="sourceLineNo">806</span>          blockSize, getPartitionSize(singleFactor));<a name="line.806"></a>
+<span class="sourceLineNo">807</span>      BucketEntryGroup bucketMulti = new BucketEntryGroup(bytesToFreeWithExtra,<a name="line.807"></a>
+<span class="sourceLineNo">808</span>          blockSize, getPartitionSize(multiFactor));<a name="line.808"></a>
+<span class="sourceLineNo">809</span>      BucketEntryGroup bucketMemory = new BucketEntryGroup(bytesToFreeWithExtra,<a name="line.809"></a>
+<span class="sourceLineNo">810</span>          blockSize, getPartitionSize(memoryFactor));<a name="line.810"></a>
+<span class="sourceLineNo">811</span><a name="line.811"></a>
+<span class="sourceLineNo">812</span>      // Scan entire map putting bucket entry into appropriate bucket entry<a name="line.812"></a>
+<span class="sourceLineNo">813</span>      // group<a name="line.813"></a>
+<span class="sourceLineNo">814</span>      for (Map.Entry&lt;BlockCacheKey, BucketEntry&gt; bucketEntryWithKey : backingMap.entrySet()) {<a name="line.814"></a>
+<span class="sourceLineNo">815</span>        switch (bucketEntryWithKey.getValue().getPriority()) {<a name="line.815"></a>
+<span class="sourceLineNo">816</span>          case SINGLE: {<a name="line.816"></a>
+<span class="sourceLineNo">817</span>            bucketSingle.add(bucketEntryWithKey);<a name="line.817"></a>
+<span class="sourceLineNo">818</span>            break;<a name="line.818"></a>
+<span class="sourceLineNo">819</span>          }<a name="line.819"></a>
+<span class="sourceLineNo">820</span>          case MULTI: {<a name="line.820"></a>
+<span class="sourceLineNo">821</span>            bucketMulti.add(bucketEntryWithKey);<a name="line.821"></a>
+<span class="sourceLineNo">822</span>            break;<a name="line.822"></a>
+<span class="sourceLineNo">823</span>          }<a name="line.823"></a>
+<span class="sourceLineNo">824</span>          case MEMORY: {<a name="line.824"></a>
+<span class="sourceLineNo">825</span>            bucketMemory.add(bucketEntryWithKey);<a name="line.825"></a>
+<span class="sourceLineNo">826</span>            break;<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">830</span><a name="line.830"></a>
-<span class="sourceLineNo">831</span>      int remainingBuckets = 3;<a name="line.831"></a>
-<span class="sourceLineNo">832</span>      long bytesFreed = 0;<a name="line.832"></a>
+<span class="sourceLineNo">831</span>      PriorityQueue&lt;BucketEntryGroup&gt; bucketQueue = new PriorityQueue&lt;&gt;(3,<a name="line.831"></a>
+<span class="sourceLineNo">832</span>          Comparator.comparingLong(BucketEntryGroup::overflow));<a name="line.832"></a>
 <span class="sourceLineNo">833</span><a name="line.833"></a>
-<span class="sourceLineNo">834</span>      BucketEntryGroup bucketGroup;<a name="line.834"></a>
-<span class="sourceLineNo">835</span>      while ((bucketGroup = bucketQueue.poll()) != null) {<a name="line.835"></a>
-<span class="sourceLineNo">836</span>        long overflow = bucketGroup.overflow();<a name="line.836"></a>
-<span class="sourceLineNo">837</span>        if (overflow &gt; 0) {<a name="line.837"></a>
-<span class="sourceLineNo">838</span>          long bucketBytesToFree = Math.min(overflow,<a name="line.838"></a>
-<span class="sourceLineNo">839</span>              (bytesToFreeWithoutExtra - bytesFreed) / remainingBuckets);<a name="line.839"></a>
-<span class="sourceLineNo">840</span>          bytesFreed += bucketGroup.free(bucketBytesToFree);<a name="line.840"></a>
-<span class="sourceLineNo">841</span>        }<a name="line.841"></a>
-<span class="sourceLineNo">842</span>        remainingBuckets--;<a name="line.842"></a>
-<span class="sourceLineNo">843</span>      }<a name="line.843"></a>
-<span class="sourceLineNo">844</span><a name="line.844"></a>
-<span class="sourceLineNo">845</span>      // Check and free if there are buckets that still need freeing of space<a name="line.845"></a>
-<span class="sourceLineNo">846</span>      if (bucketSizesAboveThresholdCount(minFactor) &gt; 0) {<a name="line.846"></a>
-<span class="sourceLineNo">847</span>        bucketQueue.clear();<a name="line.847"></a>
-<span class="sourceLineNo">848</span>        remainingBuckets = 3;<a name="line.848"></a>
-<span class="sourceLineNo">849</span><a name="line.849"></a>
-<span class="sourceLineNo">850</span>        bucketQueue.add(bucketSingle);<a name="line.850"></a>
-<span class="sourceLineNo">851</span>        bucketQueue.add(bucketMulti);<a name="line.851"></a>
-<span class="sourceLineNo">852</span>        bucketQueue.add(bucketMemory);<a name="line.852"></a>
-<span class="sourceLineNo">853</span><a name="line.853"></a>
-<span class="sourceLineNo">854</span>        while ((bucketGroup = bucketQueue.poll()) != null) {<a name="line.854"></a>
-<span class="sourceLineNo">855</span>          long bucketBytesToFree = (bytesToFreeWithExtra - bytesFreed) / remainingBuckets;<a name="line.855"></a>
-<span class="sourceLineNo">856</span>          bytesFreed += bucketGroup.free(bucketBytesToFree);<a name="line.856"></a>
-<span class="sourceLineNo">857</span>          remainingBuckets--;<a name="line.857"></a>
-<span class="sourceLineNo">858</span>        }<a name="line.858"></a>
-<span class="sourceLineNo">859</span>      }<a name="line.859"></a>
+<span class="sourceLineNo">834</span>      bucketQueue.add(bucketSingle);<a name="line.834"></a>
+<span class="sourceLineNo">835</span>      bucketQueue.add(bucketMulti);<a name="line.835"></a>
+<span class="sourceLineNo">836</span>      bucketQueue.add(bucketMemory);<a name="line.836"></a>
+<span class="sourceLineNo">837</span><a name="line.837"></a>
+<span class="sourceLineNo">838</span>      int remainingBuckets = 3;<a name="line.838"></a>
+<span class="sourceLineNo">839</span>      long bytesFreed = 0;<a name="line.839"></a>
+<span class="sourceLineNo">840</span><a name="line.840"></a>
+<span class="sourceLineNo">841</span>      BucketEntryGroup bucketGroup;<a name="line.841"></a>
+<span class="sourceLineNo">842</span>      while ((bucketGroup = bucketQueue.poll()) != null) {<a name="line.842"></a>
+<span class="sourceLineNo">843</span>        long overflow = bucketGroup.overflow();<a name="line.843"></a>
+<span class="sourceLineNo">844</span>        if (overflow &gt; 0) {<a name="line.844"></a>
+<span class="sourceLineNo">845</span>          long bucketBytesToFree = Math.min(overflow,<a name="line.845"></a>
+<span class="sourceLineNo">846</span>              (bytesToFreeWithoutExtra - bytesFreed) / remainingBuckets);<a name="line.846"></a>
+<span class="sourceLineNo">847</span>          bytesFreed += bucketGroup.free(bucketBytesToFree);<a name="line.847"></a>
+<span class="sourceLineNo">848</span>        }<a name="line.848"></a>
+<span class="sourceLineNo">849</span>        remainingBuckets--;<a name="line.849"></a>
+<span class="sourceLineNo">850</span>      }<a name="line.850"></a>
+<span class="sourceLineNo">851</span><a name="line.851"></a>
+<span class="sourceLineNo">852</span>      // Check and free if there are buckets that still need freeing of space<a name="line.852"></a>
+<span class="sourceLineNo">853</span>      if (bucketSizesAboveThresholdCount(minFactor) &gt; 0) {<a name="line.853"></a>
+<span class="sourceLineNo">854</span>        bucketQueue.clear();<a name="line.854"></a>
+<span class="sourceLineNo">855</span>        remainingBuckets = 3;<a name="line.855"></a>
+<span class="sourceLineNo">856</span><a name="line.856"></a>
+<span class="sourceLineNo">857</span>        bucketQueue.add(bucketSingle);<a name="line.857"></a>
+<span class="sourceLineNo">858</span>        bucketQueue.add(bucketMulti);<a name="line.858"></a>
+<span class="sourceLineNo">859</span>        bucketQueue.add(bucketMemory);<a name="line.859"></a>
 <span class="sourceLineNo">860</span><a name="line.860"></a>
-<span class="sourceLineNo">861</span>      // Even after the above free we might still need freeing because of the<a name="line.861"></a>
-<span class="sourceLineNo">862</span>      // De-fragmentation of the buckets (also called Slab Calcification problem), i.e<a name="line.862"></a>
-<span class="sourceLineNo">863</span>      // there might be some buckets where the occupancy is very sparse and thus are not<a name="line.863"></a>
-<span class="sourceLineNo">864</span>      // yielding the free for the other bucket sizes, the fix for this to evict some<a name="line.864"></a>
-<span class="sourceLineNo">865</span>      // of the buckets, we do this by evicting the buckets that are least fulled<a name="line.865"></a>
-<span class="sourceLineNo">866</span>      freeEntireBuckets(DEFAULT_FREE_ENTIRE_BLOCK_FACTOR *<a name="line.866"></a>
-<span class="sourceLineNo">867</span>          bucketSizesAboveThresholdCount(1.0f));<a name="line.867"></a>
-<span class="sourceLineNo">868</span><a name="line.868"></a>
-<span class="sourceLineNo">869</span>      if (LOG.isDebugEnabled()) {<a name="line.869"></a>
-<span class="sourceLineNo">870</span>        long single = bucketSingle.totalSize();<a name="line.870"></a>
-<span class="sourceLineNo">871</span>        long multi = bucketMulti.totalSize();<a name="line.871"></a>
-<span class="sourceLineNo">872</span>        long memory = bucketMemory.totalSize();<a name="line.872"></a>
-<span class="sourceLineNo">873</span>        if (LOG.isDebugEnabled()) {<a name="line.873"></a>
-<span class="sourceLineNo">874</span>          LOG.debug("Bucket cache free space completed; " + "freed="<a name="line.874"></a>
-<span class="sourceLineNo">875</span>            + StringUtils.byteDesc(bytesFreed) + ", " + "total="<a name="line.875"></a>
-<span class="sourceLineNo">876</span>            + StringUtils.byteDesc(totalSize) + ", " + "single="<a name="line.876"></a>
-<span class="sourceLineNo">877</span>            + StringUtils.byteDesc(single) + ", " + "multi="<a name="line.877"></a>
-<span class="sourceLineNo">878</span>            + StringUtils.byteDesc(multi) + ", " + "memory="<a name="line.878"></a>
-<span class="sourceLineNo">879</span>            + StringUtils.byteDesc(memory));<a name="line.879"></a>
-<span class="sourceLineNo">880</span>        }<a name="line.880"></a>
-<span class="sourceLineNo">881</span>      }<a name="line.881"></a>
-<span class="sourceLineNo">882</span><a name="line.882"></a>
-<span class="sourceLineNo">883</span>    } catch (Throwable t) {<a name="line.883"></a>
-<span class="sourceLineNo">884</span>      LOG.warn("Failed freeing space", t);<a name="line.884"></a>
-<span class="sourceLineNo">885</span>    } finally {<a name="line.885"></a>
-<span class="sourceLineNo">886</span>      cacheStats.evict();<a name="line.886"></a>
-<span class="sourceLineNo">887</span>      freeInProgress = false;<a name="line.887"></a>
-<span class="sourceLineNo">888</span>      freeSpaceLock.unlock();<a name="line.888"></a>
-<span class="sourceLineNo">889</span>    }<a name="line.889"></a>
-<span class="sourceLineNo">890</span>  }<a name="line.890"></a>
-<span class="sourceLineNo">891</span><a name="line.891"></a>
-<span class="sourceLineNo">892</span>  // This handles flushing the RAM cache to IOEngine.<a name="line.892"></a>
-<span class="sourceLineNo">893</span>  @VisibleForTesting<a name="line.893"></a>
-<span class="sourceLineNo">894</span>  class WriterThread extends HasThread {<a name="line.894"></a>
-<span class="sourceLineNo">895</span>    private final BlockingQueue&lt;RAMQueueEntry&gt; inputQueue;<a name="line.895"></a>
-<span class="sourceLineNo">896</span>    private volatile boolean writerEnabled = true;<a name="line.896"></a>
-<span class="sourceLineNo">897</span><a name="line.897"></a>
-<span class="sourceLineNo">898</span>    WriterThread(BlockingQueue&lt;RAMQueueEntry&gt; queue) {<a name="line.898"></a>
-<span class="sourceLineNo">899</span>      super("BucketCacheWriterThread");<a name="line.899"></a>
-<span class="

<TRUNCATED>

[47/50] hbase-site git commit: Published site at 26babcf013de696b899d76a3c39434b794440d8d.

Posted by gi...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/io/hfile/HFileBlock.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/io/hfile/HFileBlock.html b/devapidocs/org/apache/hadoop/hbase/io/hfile/HFileBlock.html
index f0895d6..2f0eda0 100644
--- a/devapidocs/org/apache/hadoop/hbase/io/hfile/HFileBlock.html
+++ b/devapidocs/org/apache/hadoop/hbase/io/hfile/HFileBlock.html
@@ -155,8 +155,8 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
  Caches cache whole blocks with trailing checksums if any. We then tag on some metadata, the
  content of BLOCK_METADATA_SPACE which will be flag on if we are doing 'hbase'
  checksums and then the offset into the file which is needed when we re-make a cache key
- when we return the block to the cache as 'done'. See <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html#serialize-java.nio.ByteBuffer-"><code>Cacheable.serialize(ByteBuffer)</code></a> and
- <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html#getDeserializer--"><code>Cacheable.getDeserializer()</code></a>.
+ when we return the block to the cache as 'done'.
+ See <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html#serialize-java.nio.ByteBuffer-boolean-"><code>Cacheable.serialize(ByteBuffer, boolean)</code></a> and <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html#getDeserializer--"><code>Cacheable.getDeserializer()</code></a>.
 
  <p>TODO: Should we cache the checksums? Down in Writer#getBlockForCaching(CacheConfig) where
  we make a block to cache-on-write, there is an attempt at turning off checksums. This is not the
@@ -374,7 +374,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
 <th class="colLast" scope="col">Constructor and Description</th>
 </tr>
 <tr class="altColor">
-<td class="colFirst"><code>(package private)</code></td>
+<td class="colFirst"><code>&nbsp;</code></td>
 <td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.html#HFileBlock-org.apache.hadoop.hbase.io.hfile.BlockType-int-int-long-java.nio.ByteBuffer-boolean-long-int-int-org.apache.hadoop.hbase.io.hfile.HFileContext-">HFileBlock</a></span>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockType.html" title="enum in org.apache.hadoop.hbase.io.hfile">BlockType</a>&nbsp;blockType,
           int&nbsp;onDiskSizeWithoutHeader,
           int&nbsp;uncompressedSizeWithoutHeader,
@@ -429,7 +429,8 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
 </tr>
 <tr id="i0" class="altColor">
 <td class="colFirst"><code>private <a href="https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html?is-external=true" title="class or interface in java.nio">ByteBuffer</a></code></td>
-<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.html#addMetaData-java.nio.ByteBuffer-">addMetaData</a></span>(<a href="https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html?is-external=true" title="class or interface in java.nio">ByteBuffer</a>&nbsp;destination)</code>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.html#addMetaData-java.nio.ByteBuffer-boolean-">addMetaData</a></span>(<a href="https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html?is-external=true" title="class or interface in java.nio">ByteBuffer</a>&nbsp;destination,
+           boolean&nbsp;includeNextBlockMetadata)</code>
 <div class="block">Adds metadata at current position (position is moved forward).</div>
 </td>
 </tr>
@@ -657,7 +658,8 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
 </tr>
 <tr id="i41" class="rowColor">
 <td class="colFirst"><code>void</code></td>
-<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.html#serialize-java.nio.ByteBuffer-">serialize</a></span>(<a href="https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html?is-external=true" title="class or interface in java.nio">ByteBuffer</a>&nbsp;destination)</code>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.html#serialize-java.nio.ByteBuffer-boolean-">serialize</a></span>(<a href="https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html?is-external=true" title="class or interface in java.nio">ByteBuffer</a>&nbsp;destination,
+         boolean&nbsp;includeNextBlockMetadata)</code>
 <div class="block">Serializes its data into destination.</div>
 </td>
 </tr>
@@ -980,7 +982,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
  </code></div>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
-<dd><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.html#serialize-java.nio.ByteBuffer-"><code>serialize(ByteBuffer)</code></a></dd>
+<dd><code>#serialize(ByteBuffer)</code></dd>
 </dl>
 </li>
 </ul>
@@ -1029,20 +1031,19 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
 <ul class="blockList">
 <li class="blockList">
 <h4>HFileBlock</h4>
-<pre><a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.344">HFileBlock</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockType.html" title="enum in org.apache.hadoop.hbase.io.hfile">BlockType</a>&nbsp;blockType,
-           int&nbsp;onDiskSizeWithoutHeader,
-           int&nbsp;uncompressedSizeWithoutHeader,
-           long&nbsp;prevBlockOffset,
-           <a href="https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html?is-external=true" title="class or interface in java.nio">ByteBuffer</a>&nbsp;b,
-           boolean&nbsp;fillHeader,
-           long&nbsp;offset,
-           int&nbsp;nextBlockOnDiskSize,
-           int&nbsp;onDiskDataSizeWithHeader,
-           <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileContext.html" title="class in org.apache.hadoop.hbase.io.hfile">HFileContext</a>&nbsp;fileContext)</pre>
+<pre>public&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.344">HFileBlock</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockType.html" title="enum in org.apache.hadoop.hbase.io.hfile">BlockType</a>&nbsp;blockType,
+                  int&nbsp;onDiskSizeWithoutHeader,
+                  int&nbsp;uncompressedSizeWithoutHeader,
+                  long&nbsp;prevBlockOffset,
+                  <a href="https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html?is-external=true" title="class or interface in java.nio">ByteBuffer</a>&nbsp;b,
+                  boolean&nbsp;fillHeader,
+                  long&nbsp;offset,
+                  int&nbsp;nextBlockOnDiskSize,
+                  int&nbsp;onDiskDataSizeWithHeader,
+                  <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileContext.html" title="class in org.apache.hadoop.hbase.io.hfile">HFileContext</a>&nbsp;fileContext)</pre>
 <div class="block">Creates a new <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFile.html" title="class in org.apache.hadoop.hbase.io.hfile"><code>HFile</code></a> block from the given fields. This constructor
  is used only while writing blocks and caching,
  and is sitting in a byte buffer and we want to stuff the block into cache.
- See <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html#getBlockForCaching-org.apache.hadoop.hbase.io.hfile.CacheConfig-"><code>HFileBlock.Writer.getBlockForCaching(CacheConfig)</code></a>.
 
  <p>TODO: The caller presumes no checksumming
  required of this block instance since going into cache; checksum already verified on
@@ -1067,7 +1068,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
 <ul class="blockListLast">
 <li class="blockList">
 <h4>HFileBlock</h4>
-<pre><a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.363">HFileBlock</a>(<a href="../../../../../../org/apache/hadoop/hbase/nio/ByteBuff.html" title="class in org.apache.hadoop.hbase.nio">ByteBuff</a>&nbsp;buf,
+<pre><a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.364">HFileBlock</a>(<a href="../../../../../../org/apache/hadoop/hbase/nio/ByteBuff.html" title="class in org.apache.hadoop.hbase.nio">ByteBuff</a>&nbsp;buf,
            boolean&nbsp;usesHBaseChecksum,
            <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.MemoryType.html" title="enum in org.apache.hadoop.hbase.io.hfile">Cacheable.MemoryType</a>&nbsp;memType,
            long&nbsp;offset,
@@ -1100,7 +1101,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
 <ul class="blockList">
 <li class="blockList">
 <h4>init</h4>
-<pre>private&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.403">init</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockType.html" title="enum in org.apache.hadoop.hbase.io.hfile">BlockType</a>&nbsp;blockType,
+<pre>private&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.404">init</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockType.html" title="enum in org.apache.hadoop.hbase.io.hfile">BlockType</a>&nbsp;blockType,
                   int&nbsp;onDiskSizeWithoutHeader,
                   int&nbsp;uncompressedSizeWithoutHeader,
                   long&nbsp;prevBlockOffset,
@@ -1117,7 +1118,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
 <ul class="blockList">
 <li class="blockList">
 <h4>getOnDiskSizeWithHeader</h4>
-<pre>private static&nbsp;int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.423">getOnDiskSizeWithHeader</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html?is-external=true" title="class or interface in java.nio">ByteBuffer</a>&nbsp;headerBuf,
+<pre>private static&nbsp;int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.424">getOnDiskSizeWithHeader</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html?is-external=true" title="class or interface in java.nio">ByteBuffer</a>&nbsp;headerBuf,
                                            boolean&nbsp;verifyChecksum)</pre>
 <div class="block">Parse total on disk size including header and checksum.</div>
 <dl>
@@ -1135,7 +1136,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
 <ul class="blockList">
 <li class="blockList">
 <h4>getNextBlockOnDiskSize</h4>
-<pre>int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.434">getNextBlockOnDiskSize</a>()</pre>
+<pre>int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.435">getNextBlockOnDiskSize</a>()</pre>
 <dl>
 <dt><span class="returnLabel">Returns:</span></dt>
 <dd>the on-disk size of the next block (including the header size and any checksums if
@@ -1150,7 +1151,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
 <ul class="blockList">
 <li class="blockList">
 <h4>getBlockType</h4>
-<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockType.html" title="enum in org.apache.hadoop.hbase.io.hfile">BlockType</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.439">getBlockType</a>()</pre>
+<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockType.html" title="enum in org.apache.hadoop.hbase.io.hfile">BlockType</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.440">getBlockType</a>()</pre>
 <dl>
 <dt><span class="overrideSpecifyLabel">Specified by:</span></dt>
 <dd><code><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html#getBlockType--">getBlockType</a></code>&nbsp;in interface&nbsp;<code><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html" title="interface in org.apache.hadoop.hbase.io.hfile">Cacheable</a></code></dd>
@@ -1165,7 +1166,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
 <ul class="blockList">
 <li class="blockList">
 <h4>getDataBlockEncodingId</h4>
-<pre>short&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.444">getDataBlockEncodingId</a>()</pre>
+<pre>short&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.445">getDataBlockEncodingId</a>()</pre>
 <dl>
 <dt><span class="returnLabel">Returns:</span></dt>
 <dd>get data block encoding id that was used to encode this block</dd>
@@ -1178,7 +1179,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
 <ul class="blockList">
 <li class="blockList">
 <h4>getOnDiskSizeWithHeader</h4>
-<pre>public&nbsp;int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.455">getOnDiskSizeWithHeader</a>()</pre>
+<pre>public&nbsp;int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.456">getOnDiskSizeWithHeader</a>()</pre>
 <dl>
 <dt><span class="returnLabel">Returns:</span></dt>
 <dd>the on-disk size of header + data part + checksum.</dd>
@@ -1191,7 +1192,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
 <ul class="blockList">
 <li class="blockList">
 <h4>getOnDiskSizeWithoutHeader</h4>
-<pre>int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.462">getOnDiskSizeWithoutHeader</a>()</pre>
+<pre>int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.463">getOnDiskSizeWithoutHeader</a>()</pre>
 <dl>
 <dt><span class="returnLabel">Returns:</span></dt>
 <dd>the on-disk size of the data part + checksum (header excluded).</dd>
@@ -1204,7 +1205,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
 <ul class="blockList">
 <li class="blockList">
 <h4>getUncompressedSizeWithoutHeader</h4>
-<pre>int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.469">getUncompressedSizeWithoutHeader</a>()</pre>
+<pre>int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.470">getUncompressedSizeWithoutHeader</a>()</pre>
 <dl>
 <dt><span class="returnLabel">Returns:</span></dt>
 <dd>the uncompressed size of data part (header and checksum excluded).</dd>
@@ -1217,7 +1218,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
 <ul class="blockList">
 <li class="blockList">
 <h4>getPrevBlockOffset</h4>
-<pre>long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.477">getPrevBlockOffset</a>()</pre>
+<pre>long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.478">getPrevBlockOffset</a>()</pre>
 <dl>
 <dt><span class="returnLabel">Returns:</span></dt>
 <dd>the offset of the previous block of the same type in the file, or
@@ -1231,7 +1232,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
 <ul class="blockList">
 <li class="blockList">
 <h4>overwriteHeader</h4>
-<pre>private&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.485">overwriteHeader</a>()</pre>
+<pre>private&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.486">overwriteHeader</a>()</pre>
 <div class="block">Rewinds <code>buf</code> and writes first 4 header fields. <code>buf</code> position
  is modified as side-effect.</div>
 </li>
@@ -1242,7 +1243,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
 <ul class="blockList">
 <li class="blockList">
 <h4>getBufferWithoutHeader</h4>
-<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/nio/ByteBuff.html" title="class in org.apache.hadoop.hbase.nio">ByteBuff</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.503">getBufferWithoutHeader</a>()</pre>
+<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/nio/ByteBuff.html" title="class in org.apache.hadoop.hbase.nio">ByteBuff</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.504">getBufferWithoutHeader</a>()</pre>
 <div class="block">Returns a buffer that does not include the header or checksum.</div>
 <dl>
 <dt><span class="returnLabel">Returns:</span></dt>
@@ -1256,7 +1257,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
 <ul class="blockList">
 <li class="blockList">
 <h4>getBufferReadOnly</h4>
-<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/nio/ByteBuff.html" title="class in org.apache.hadoop.hbase.nio">ByteBuff</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.519">getBufferReadOnly</a>()</pre>
+<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/nio/ByteBuff.html" title="class in org.apache.hadoop.hbase.nio">ByteBuff</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.520">getBufferReadOnly</a>()</pre>
 <div class="block">Returns a read-only duplicate of the buffer this block stores internally ready to be read.
  Clients must not modify the buffer object though they may set position and limit on the
  returned buffer since we pass back a duplicate. This method has to be public because it is used
@@ -1275,7 +1276,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
 <ul class="blockList">
 <li class="blockList">
 <h4>sanityCheckAssertion</h4>
-<pre>private&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.527">sanityCheckAssertion</a>(long&nbsp;valueFromBuf,
+<pre>private&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.528">sanityCheckAssertion</a>(long&nbsp;valueFromBuf,
                                   long&nbsp;valueFromField,
                                   <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;fieldName)
                            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>
@@ -1291,7 +1292,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
 <ul class="blockList">
 <li class="blockList">
 <h4>sanityCheckAssertion</h4>
-<pre>private&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.536">sanityCheckAssertion</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockType.html" title="enum in org.apache.hadoop.hbase.io.hfile">BlockType</a>&nbsp;valueFromBuf,
+<pre>private&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.537">sanityCheckAssertion</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockType.html" title="enum in org.apache.hadoop.hbase.io.hfile">BlockType</a>&nbsp;valueFromBuf,
                                   <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockType.html" title="enum in org.apache.hadoop.hbase.io.hfile">BlockType</a>&nbsp;valueFromField)
                            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>
@@ -1306,7 +1307,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
 <ul class="blockList">
 <li class="blockList">
 <h4>sanityCheck</h4>
-<pre>void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.553">sanityCheck</a>()
+<pre>void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.554">sanityCheck</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">Checks if the block is internally consistent, i.e. the first
  <a href="../../../../../../org/apache/hadoop/hbase/HConstants.html#HFILEBLOCK_HEADER_SIZE"><code>HConstants.HFILEBLOCK_HEADER_SIZE</code></a> bytes of the buffer contain a
@@ -1326,7 +1327,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
 <ul class="blockList">
 <li class="blockList">
 <h4>toString</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/io/hfile/HFileBlock.html#line.587">toString</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/io/hfile/HFileBlock.html#line.588">toString</a>()</pre>
 <dl>
 <dt><span class="overrideSpecifyLabel">Overrides:</span></dt>
 <dd><code><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true#toString--" title="class or interface in java.lang">toString</a></code>&nbsp;in class&nbsp;<code><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></code></dd>
@@ -1339,7 +1340,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
 <ul class="blockList">
 <li class="blockList">
 <h4>unpack</h4>
-<pre><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.html" title="class in org.apache.hadoop.hbase.io.hfile">HFileBlock</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.631">unpack</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileContext.html" title="class in org.apache.hadoop.hbase.io.hfile">HFileContext</a>&nbsp;fileContext,
+<pre><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.html" title="class in org.apache.hadoop.hbase.io.hfile">HFileBlock</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.633">unpack</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileContext.html" title="class in org.apache.hadoop.hbase.io.hfile">HFileContext</a>&nbsp;fileContext,
                   <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReader.html" title="interface in org.apache.hadoop.hbase.io.hfile">HFileBlock.FSReader</a>&nbsp;reader)
            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">Retrieves the decompressed/decrypted view of this block. An encoded block remains in its
@@ -1356,7 +1357,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
 <ul class="blockList">
 <li class="blockList">
 <h4>allocateBuffer</h4>
-<pre>private&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.659">allocateBuffer</a>()</pre>
+<pre>private&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.661">allocateBuffer</a>()</pre>
 <div class="block">Always allocates a new buffer of the correct size. Copies header bytes
  from the existing buffer. Does not change header fields.
  Reserve room to keep checksum bytes too.</div>
@@ -1368,7 +1369,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
 <ul class="blockList">
 <li class="blockList">
 <h4>isUnpacked</h4>
-<pre>public&nbsp;boolean&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.681">isUnpacked</a>()</pre>
+<pre>public&nbsp;boolean&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.683">isUnpacked</a>()</pre>
 <div class="block">Return true when this block's buffer has been unpacked, false otherwise. Note this is a
  calculated heuristic, not tracked attribute of the block.</div>
 </li>
@@ -1379,7 +1380,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
 <ul class="blockList">
 <li class="blockList">
 <h4>sanityCheckUncompressedSize</h4>
-<pre>void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.691">sanityCheckUncompressedSize</a>()
+<pre>void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.693">sanityCheckUncompressedSize</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">An additional sanity-check in case no compression or encryption is being used.</div>
 <dl>
@@ -1394,7 +1395,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
 <ul class="blockList">
 <li class="blockList">
 <h4>getOffset</h4>
-<pre>long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.705">getOffset</a>()</pre>
+<pre>long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.707">getOffset</a>()</pre>
 <div class="block">Cannot be <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.html#UNSET"><code>UNSET</code></a>. Must be a legitimate value. Used re-making the <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile"><code>BlockCacheKey</code></a> when
  block is returned to the cache.</div>
 <dl>
@@ -1409,7 +1410,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
 <ul class="blockList">
 <li class="blockList">
 <h4>getByteStream</h4>
-<pre><a href="https://docs.oracle.com/javase/8/docs/api/java/io/DataInputStream.html?is-external=true" title="class or interface in java.io">DataInputStream</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.715">getByteStream</a>()</pre>
+<pre><a href="https://docs.oracle.com/javase/8/docs/api/java/io/DataInputStream.html?is-external=true" title="class or interface in java.io">DataInputStream</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.717">getByteStream</a>()</pre>
 <dl>
 <dt><span class="returnLabel">Returns:</span></dt>
 <dd>a byte stream reading the data + checksum of this block</dd>
@@ -1422,7 +1423,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
 <ul class="blockList">
 <li class="blockList">
 <h4>heapSize</h4>
-<pre>public&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.722">heapSize</a>()</pre>
+<pre>public&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.724">heapSize</a>()</pre>
 <dl>
 <dt><span class="overrideSpecifyLabel">Specified by:</span></dt>
 <dd><code><a href="../../../../../../org/apache/hadoop/hbase/io/HeapSize.html#heapSize--">heapSize</a></code>&nbsp;in interface&nbsp;<code><a href="../../../../../../org/apache/hadoop/hbase/io/HeapSize.html" title="interface in org.apache.hadoop.hbase.io">HeapSize</a></code></dd>
@@ -1438,7 +1439,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
 <ul class="blockList">
 <li class="blockList">
 <h4>readWithExtra</h4>
-<pre>static&nbsp;boolean&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.758">readWithExtra</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/io/InputStream.html?is-external=true" title="class or interface in java.io">InputStream</a>&nbsp;in,
+<pre>static&nbsp;boolean&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.760">readWithExtra</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/io/InputStream.html?is-external=true" title="class or interface in java.io">InputStream</a>&nbsp;in,
                              byte[]&nbsp;buf,
                              int&nbsp;bufOffset,
                              int&nbsp;necessaryLen,
@@ -1468,7 +1469,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
 <ul class="blockList">
 <li class="blockList">
 <h4>positionalReadWithExtra</h4>
-<pre>static&nbsp;boolean&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.799">positionalReadWithExtra</a>(org.apache.hadoop.fs.FSDataInputStream&nbsp;in,
+<pre>static&nbsp;boolean&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.801">positionalReadWithExtra</a>(org.apache.hadoop.fs.FSDataInputStream&nbsp;in,
                                        long&nbsp;position,
                                        byte[]&nbsp;buf,
                                        int&nbsp;bufOffset,
@@ -1503,7 +1504,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
 <ul class="blockList">
 <li class="blockList">
 <h4>sanityCheckUncompressed</h4>
-<pre>void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.1874">sanityCheckUncompressed</a>()
+<pre>void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.1876">sanityCheckUncompressed</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">An additional sanity-check in case no compression or encryption is being used.</div>
 <dl>
@@ -1518,7 +1519,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
 <ul class="blockList">
 <li class="blockList">
 <h4>getSerializedLength</h4>
-<pre>public&nbsp;int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.1886">getSerializedLength</a>()</pre>
+<pre>public&nbsp;int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.1888">getSerializedLength</a>()</pre>
 <div class="block"><span class="descfrmTypeLabel">Description copied from interface:&nbsp;<code><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html#getSerializedLength--">Cacheable</a></code></span></div>
 <div class="block">Returns the length of the ByteBuffer required to serialized the object. If the
  object cannot be serialized, it should return 0.</div>
@@ -1530,20 +1531,22 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
 </dl>
 </li>
 </ul>
-<a name="serialize-java.nio.ByteBuffer-">
+<a name="serialize-java.nio.ByteBuffer-boolean-">
 <!--   -->
 </a>
 <ul class="blockList">
 <li class="blockList">
 <h4>serialize</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.1896">serialize</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html?is-external=true" title="class or interface in java.nio">ByteBuffer</a>&nbsp;destination)</pre>
-<div class="block"><span class="descfrmTypeLabel">Description copied from interface:&nbsp;<code><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html#serialize-java.nio.ByteBuffer-">Cacheable</a></code></span></div>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.1898">serialize</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html?is-external=true" title="class or interface in java.nio">ByteBuffer</a>&nbsp;destination,
+                      boolean&nbsp;includeNextBlockMetadata)</pre>
+<div class="block"><span class="descfrmTypeLabel">Description copied from interface:&nbsp;<code><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html#serialize-java.nio.ByteBuffer-boolean-">Cacheable</a></code></span></div>
 <div class="block">Serializes its data into destination.</div>
 <dl>
 <dt><span class="overrideSpecifyLabel">Specified by:</span></dt>
-<dd><code><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html#serialize-java.nio.ByteBuffer-">serialize</a></code>&nbsp;in interface&nbsp;<code><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html" title="interface in org.apache.hadoop.hbase.io.hfile">Cacheable</a></code></dd>
+<dd><code><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html#serialize-java.nio.ByteBuffer-boolean-">serialize</a></code>&nbsp;in interface&nbsp;<code><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html" title="interface in org.apache.hadoop.hbase.io.hfile">Cacheable</a></code></dd>
 <dt><span class="paramLabel">Parameters:</span></dt>
 <dd><code>destination</code> - Where to serialize to</dd>
+<dd><code>includeNextBlockMetadata</code> - Whether to include nextBlockMetadata in the Cache block.</dd>
 </dl>
 </li>
 </ul>
@@ -1557,13 +1560,14 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
 <div class="block">For use by bucketcache. This exposes internals.</div>
 </li>
 </ul>
-<a name="addMetaData-java.nio.ByteBuffer-">
+<a name="addMetaData-java.nio.ByteBuffer-boolean-">
 <!--   -->
 </a>
 <ul class="blockList">
 <li class="blockList">
 <h4>addMetaData</h4>
-<pre>private&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html?is-external=true" title="class or interface in java.nio">ByteBuffer</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.1922">addMetaData</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html?is-external=true" title="class or interface in java.nio">ByteBuffer</a>&nbsp;destination)</pre>
+<pre>private&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html?is-external=true" title="class or interface in java.nio">ByteBuffer</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.1922">addMetaData</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html?is-external=true" title="class or interface in java.nio">ByteBuffer</a>&nbsp;destination,
+                               boolean&nbsp;includeNextBlockMetadata)</pre>
 <div class="block">Adds metadata at current position (position is moved forward). Does not flip or reset.</div>
 <dl>
 <dt><span class="returnLabel">Returns:</span></dt>
@@ -1577,7 +1581,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
 <ul class="blockList">
 <li class="blockList">
 <h4>getDeserializer</h4>
-<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/CacheableDeserializer.html" title="interface in org.apache.hadoop.hbase.io.hfile">CacheableDeserializer</a>&lt;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html" title="interface in org.apache.hadoop.hbase.io.hfile">Cacheable</a>&gt;&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.1931">getDeserializer</a>()</pre>
+<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/CacheableDeserializer.html" title="interface in org.apache.hadoop.hbase.io.hfile">CacheableDeserializer</a>&lt;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html" title="interface in org.apache.hadoop.hbase.io.hfile">Cacheable</a>&gt;&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.1933">getDeserializer</a>()</pre>
 <div class="block"><span class="descfrmTypeLabel">Description copied from interface:&nbsp;<code><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html#getDeserializer--">Cacheable</a></code></span></div>
 <div class="block">Returns CacheableDeserializer instance which reconstructs original object from ByteBuffer.</div>
 <dl>
@@ -1594,7 +1598,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
 <ul class="blockList">
 <li class="blockList">
 <h4>hashCode</h4>
-<pre>public&nbsp;int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.1936">hashCode</a>()</pre>
+<pre>public&nbsp;int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.1938">hashCode</a>()</pre>
 <dl>
 <dt><span class="overrideSpecifyLabel">Overrides:</span></dt>
 <dd><code><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true#hashCode--" title="class or interface in java.lang">hashCode</a></code>&nbsp;in class&nbsp;<code><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></code></dd>
@@ -1607,7 +1611,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
 <ul class="blockList">
 <li class="blockList">
 <h4>equals</h4>
-<pre>public&nbsp;boolean&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.1949">equals</a>(<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>&nbsp;comparison)</pre>
+<pre>public&nbsp;boolean&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.1951">equals</a>(<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>&nbsp;comparison)</pre>
 <dl>
 <dt><span class="overrideSpecifyLabel">Overrides:</span></dt>
 <dd><code><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true#equals-java.lang.Object-" title="class or interface in java.lang">equals</a></code>&nbsp;in class&nbsp;<code><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></code></dd>
@@ -1620,7 +1624,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
 <ul class="blockList">
 <li class="blockList">
 <h4>getDataBlockEncoding</h4>
-<pre><a href="../../../../../../org/apache/hadoop/hbase/io/encoding/DataBlockEncoding.html" title="enum in org.apache.hadoop.hbase.io.encoding">DataBlockEncoding</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.1988">getDataBlockEncoding</a>()</pre>
+<pre><a href="../../../../../../org/apache/hadoop/hbase/io/encoding/DataBlockEncoding.html" title="enum in org.apache.hadoop.hbase.io.encoding">DataBlockEncoding</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.1990">getDataBlockEncoding</a>()</pre>
 </li>
 </ul>
 <a name="getChecksumType--">
@@ -1629,7 +1633,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
 <ul class="blockList">
 <li class="blockList">
 <h4>getChecksumType</h4>
-<pre>byte&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.1996">getChecksumType</a>()</pre>
+<pre>byte&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.1998">getChecksumType</a>()</pre>
 </li>
 </ul>
 <a name="getBytesPerChecksum--">
@@ -1638,7 +1642,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
 <ul class="blockList">
 <li class="blockList">
 <h4>getBytesPerChecksum</h4>
-<pre>int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.2000">getBytesPerChecksum</a>()</pre>
+<pre>int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.2002">getBytesPerChecksum</a>()</pre>
 </li>
 </ul>
 <a name="getOnDiskDataSizeWithHeader--">
@@ -1647,7 +1651,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
 <ul class="blockList">
 <li class="blockList">
 <h4>getOnDiskDataSizeWithHeader</h4>
-<pre>int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.2006">getOnDiskDataSizeWithHeader</a>()</pre>
+<pre>int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.2008">getOnDiskDataSizeWithHeader</a>()</pre>
 <dl>
 <dt><span class="returnLabel">Returns:</span></dt>
 <dd>the size of data on disk + header. Excludes checksum.</dd>
@@ -1660,7 +1664,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
 <ul class="blockList">
 <li class="blockList">
 <h4>totalChecksumBytes</h4>
-<pre>int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.2014">totalChecksumBytes</a>()</pre>
+<pre>int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.2016">totalChecksumBytes</a>()</pre>
 <div class="block">Calculate the number of bytes required to store all the checksums
  for this block. Each checksum value is a 4 byte integer.</div>
 </li>
@@ -1671,7 +1675,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
 <ul class="blockList">
 <li class="blockList">
 <h4>headerSize</h4>
-<pre>public&nbsp;int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.2029">headerSize</a>()</pre>
+<pre>public&nbsp;int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.2031">headerSize</a>()</pre>
 <div class="block">Returns the size of this block header.</div>
 </li>
 </ul>
@@ -1681,7 +1685,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
 <ul class="blockList">
 <li class="blockList">
 <h4>headerSize</h4>
-<pre>public static&nbsp;int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.2036">headerSize</a>(boolean&nbsp;usesHBaseChecksum)</pre>
+<pre>public static&nbsp;int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.2038">headerSize</a>(boolean&nbsp;usesHBaseChecksum)</pre>
 <div class="block">Maps a minor version to the size of the header.</div>
 </li>
 </ul>
@@ -1691,7 +1695,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
 <ul class="blockList">
 <li class="blockList">
 <h4>getDummyHeaderForVersion</h4>
-<pre>byte[]&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.2046">getDummyHeaderForVersion</a>()</pre>
+<pre>byte[]&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.2048">getDummyHeaderForVersion</a>()</pre>
 <div class="block">Return the appropriate DUMMY_HEADER for the minor version</div>
 </li>
 </ul>
@@ -1701,7 +1705,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
 <ul class="blockList">
 <li class="blockList">
 <h4>getDummyHeaderForVersion</h4>
-<pre>private static&nbsp;byte[]&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.2053">getDummyHeaderForVersion</a>(boolean&nbsp;usesHBaseChecksum)</pre>
+<pre>private static&nbsp;byte[]&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.2055">getDummyHeaderForVersion</a>(boolean&nbsp;usesHBaseChecksum)</pre>
 <div class="block">Return the appropriate DUMMY_HEADER for the minor version</div>
 </li>
 </ul>
@@ -1711,7 +1715,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
 <ul class="blockList">
 <li class="blockList">
 <h4>getHFileContext</h4>
-<pre><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileContext.html" title="class in org.apache.hadoop.hbase.io.hfile">HFileContext</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.2061">getHFileContext</a>()</pre>
+<pre><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileContext.html" title="class in org.apache.hadoop.hbase.io.hfile">HFileContext</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.2063">getHFileContext</a>()</pre>
 <dl>
 <dt><span class="returnLabel">Returns:</span></dt>
 <dd>This HFileBlocks fileContext which will a derivative of the
@@ -1725,7 +1729,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
 <ul class="blockList">
 <li class="blockList">
 <h4>getMemoryType</h4>
-<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.MemoryType.html" title="enum in org.apache.hadoop.hbase.io.hfile">Cacheable.MemoryType</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.2066">getMemoryType</a>()</pre>
+<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.MemoryType.html" title="enum in org.apache.hadoop.hbase.io.hfile">Cacheable.MemoryType</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.2068">getMemoryType</a>()</pre>
 <dl>
 <dt><span class="overrideSpecifyLabel">Specified by:</span></dt>
 <dd><code><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html#getMemoryType--">getMemoryType</a></code>&nbsp;in interface&nbsp;<code><a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable.html" title="interface in org.apache.hadoop.hbase.io.hfile">Cacheable</a></code></dd>
@@ -1740,7 +1744,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
 <ul class="blockList">
 <li class="blockList">
 <h4>usesSharedMemory</h4>
-<pre>boolean&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.2073">usesSharedMemory</a>()</pre>
+<pre>boolean&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.2075">usesSharedMemory</a>()</pre>
 <dl>
 <dt><span class="returnLabel">Returns:</span></dt>
 <dd>true if this block is backed by a shared memory area(such as that of a BucketCache).</dd>
@@ -1753,7 +1757,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
 <ul class="blockList">
 <li class="blockList">
 <h4>toStringHeader</h4>
-<pre>static&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.2083">toStringHeader</a>(<a href="../../../../../../org/apache/hadoop/hbase/nio/ByteBuff.html" title="class in org.apache.hadoop.hbase.nio">ByteBuff</a>&nbsp;buf)
+<pre>static&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.2085">toStringHeader</a>(<a href="../../../../../../org/apache/hadoop/hbase/nio/ByteBuff.html" title="class in org.apache.hadoop.hbase.nio">ByteBuff</a>&nbsp;buf)
                       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">Convert the contents of the block header into a human readable string.
  This is mostly helpful for debugging. This assumes that the block
@@ -1770,7 +1774,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/io/hfile/Cacheable
 <ul class="blockListLast">
 <li class="blockList">
 <h4>deepClone</h4>
-<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.html" title="class in org.apache.hadoop.hbase.io.hfile">HFileBlock</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.2105">deepClone</a>()</pre>
+<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.html" title="class in org.apache.hadoop.hbase.io.hfile">HFileBlock</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html#line.2107">deepClone</a>()</pre>
 </li>
 </ul>
 </li>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/io/hfile/LruBlockCache.BlockBucket.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/io/hfile/LruBlockCache.BlockBucket.html b/devapidocs/org/apache/hadoop/hbase/io/hfile/LruBlockCache.BlockBucket.html
index 626a41c..125a6bd 100644
--- a/devapidocs/org/apache/hadoop/hbase/io/hfile/LruBlockCache.BlockBucket.html
+++ b/devapidocs/org/apache/hadoop/hbase/io/hfile/LruBlockCache.BlockBucket.html
@@ -117,7 +117,7 @@ var activeTableTab = "activeTableTab";
 </dl>
 <hr>
 <br>
-<pre>private class <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.753">LruBlockCache.BlockBucket</a>
+<pre>private class <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.758">LruBlockCache.BlockBucket</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/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/LruBlockCache.BlockBucket.html" title="class in org.apache.hadoop.hbase.io.hfile">LruBlockCache.BlockBucket</a>&gt;</pre>
 <div class="block">Used to group blocks into priority buckets.  There will be a BlockBucket
@@ -253,7 +253,7 @@ implements <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparab
 <ul class="blockList">
 <li class="blockList">
 <h4>name</h4>
-<pre>private 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/io/hfile/LruBlockCache.BlockBucket.html#line.755">name</a></pre>
+<pre>private 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/io/hfile/LruBlockCache.BlockBucket.html#line.760">name</a></pre>
 </li>
 </ul>
 <a name="queue">
@@ -262,7 +262,7 @@ implements <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparab
 <ul class="blockList">
 <li class="blockList">
 <h4>queue</h4>
-<pre>private&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/LruCachedBlockQueue.html" title="class in org.apache.hadoop.hbase.io.hfile">LruCachedBlockQueue</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.BlockBucket.html#line.756">queue</a></pre>
+<pre>private&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/LruCachedBlockQueue.html" title="class in org.apache.hadoop.hbase.io.hfile">LruCachedBlockQueue</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.BlockBucket.html#line.761">queue</a></pre>
 </li>
 </ul>
 <a name="totalSize">
@@ -271,7 +271,7 @@ implements <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparab
 <ul class="blockList">
 <li class="blockList">
 <h4>totalSize</h4>
-<pre>private&nbsp;long <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.BlockBucket.html#line.757">totalSize</a></pre>
+<pre>private&nbsp;long <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.BlockBucket.html#line.762">totalSize</a></pre>
 </li>
 </ul>
 <a name="bucketSize">
@@ -280,7 +280,7 @@ implements <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparab
 <ul class="blockListLast">
 <li class="blockList">
 <h4>bucketSize</h4>
-<pre>private&nbsp;long <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.BlockBucket.html#line.758">bucketSize</a></pre>
+<pre>private&nbsp;long <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.BlockBucket.html#line.763">bucketSize</a></pre>
 </li>
 </ul>
 </li>
@@ -297,7 +297,7 @@ implements <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparab
 <ul class="blockListLast">
 <li class="blockList">
 <h4>BlockBucket</h4>
-<pre>public&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.BlockBucket.html#line.760">BlockBucket</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/io/hfile/LruBlockCache.BlockBucket.html#line.765">BlockBucket</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,
                    long&nbsp;bytesToFree,
                    long&nbsp;blockSize,
                    long&nbsp;bucketSize)</pre>
@@ -317,7 +317,7 @@ implements <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparab
 <ul class="blockList">
 <li class="blockList">
 <h4>add</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.BlockBucket.html#line.767">add</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/LruCachedBlock.html" title="class in org.apache.hadoop.hbase.io.hfile">LruCachedBlock</a>&nbsp;block)</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.BlockBucket.html#line.772">add</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/LruCachedBlock.html" title="class in org.apache.hadoop.hbase.io.hfile">LruCachedBlock</a>&nbsp;block)</pre>
 </li>
 </ul>
 <a name="free-long-">
@@ -326,7 +326,7 @@ implements <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparab
 <ul class="blockList">
 <li class="blockList">
 <h4>free</h4>
-<pre>public&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.BlockBucket.html#line.772">free</a>(long&nbsp;toFree)</pre>
+<pre>public&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.BlockBucket.html#line.777">free</a>(long&nbsp;toFree)</pre>
 </li>
 </ul>
 <a name="overflow--">
@@ -335,7 +335,7 @@ implements <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparab
 <ul class="blockList">
 <li class="blockList">
 <h4>overflow</h4>
-<pre>public&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.BlockBucket.html#line.790">overflow</a>()</pre>
+<pre>public&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.BlockBucket.html#line.795">overflow</a>()</pre>
 </li>
 </ul>
 <a name="totalSize--">
@@ -344,7 +344,7 @@ implements <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparab
 <ul class="blockList">
 <li class="blockList">
 <h4>totalSize</h4>
-<pre>public&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.BlockBucket.html#line.794">totalSize</a>()</pre>
+<pre>public&nbsp;long&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.BlockBucket.html#line.799">totalSize</a>()</pre>
 </li>
 </ul>
 <a name="compareTo-org.apache.hadoop.hbase.io.hfile.LruBlockCache.BlockBucket-">
@@ -353,7 +353,7 @@ implements <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparab
 <ul class="blockList">
 <li class="blockList">
 <h4>compareTo</h4>
-<pre>public&nbsp;int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.BlockBucket.html#line.799">compareTo</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/LruBlockCache.BlockBucket.html" title="class in org.apache.hadoop.hbase.io.hfile">LruBlockCache.BlockBucket</a>&nbsp;that)</pre>
+<pre>public&nbsp;int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.BlockBucket.html#line.804">compareTo</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/LruBlockCache.BlockBucket.html" title="class in org.apache.hadoop.hbase.io.hfile">LruBlockCache.BlockBucket</a>&nbsp;that)</pre>
 <dl>
 <dt><span class="overrideSpecifyLabel">Specified by:</span></dt>
 <dd><code><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true#compareTo-T-" title="class or interface in java.lang">compareTo</a></code>&nbsp;in interface&nbsp;<code><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/LruBlockCache.BlockBucket.html" title="class in org.apache.hadoop.hbase.io.hfile">LruBlockCache.BlockBucket</a>&gt;</code></dd>
@@ -366,7 +366,7 @@ implements <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparab
 <ul class="blockList">
 <li class="blockList">
 <h4>equals</h4>
-<pre>public&nbsp;boolean&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.BlockBucket.html#line.804">equals</a>(<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>&nbsp;that)</pre>
+<pre>public&nbsp;boolean&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.BlockBucket.html#line.809">equals</a>(<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>&nbsp;that)</pre>
 <dl>
 <dt><span class="overrideSpecifyLabel">Overrides:</span></dt>
 <dd><code><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true#equals-java.lang.Object-" title="class or interface in java.lang">equals</a></code>&nbsp;in class&nbsp;<code><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></code></dd>
@@ -379,7 +379,7 @@ implements <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparab
 <ul class="blockList">
 <li class="blockList">
 <h4>hashCode</h4>
-<pre>public&nbsp;int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.BlockBucket.html#line.812">hashCode</a>()</pre>
+<pre>public&nbsp;int&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.BlockBucket.html#line.817">hashCode</a>()</pre>
 <dl>
 <dt><span class="overrideSpecifyLabel">Overrides:</span></dt>
 <dd><code><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true#hashCode--" title="class or interface in java.lang">hashCode</a></code>&nbsp;in class&nbsp;<code><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></code></dd>
@@ -392,7 +392,7 @@ implements <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparab
 <ul class="blockListLast">
 <li class="blockList">
 <h4>toString</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/io/hfile/LruBlockCache.BlockBucket.html#line.817">toString</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/io/hfile/LruBlockCache.BlockBucket.html#line.822">toString</a>()</pre>
 <dl>
 <dt><span class="overrideSpecifyLabel">Overrides:</span></dt>
 <dd><code><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true#toString--" title="class or interface in java.lang">toString</a></code>&nbsp;in class&nbsp;<code><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></code></dd>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/io/hfile/LruBlockCache.EvictionThread.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/io/hfile/LruBlockCache.EvictionThread.html b/devapidocs/org/apache/hadoop/hbase/io/hfile/LruBlockCache.EvictionThread.html
index 42c86a7..bc5912f 100644
--- a/devapidocs/org/apache/hadoop/hbase/io/hfile/LruBlockCache.EvictionThread.html
+++ b/devapidocs/org/apache/hadoop/hbase/io/hfile/LruBlockCache.EvictionThread.html
@@ -122,7 +122,7 @@ var activeTableTab = "activeTableTab";
 </dl>
 <hr>
 <br>
-<pre>static class <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.877">LruBlockCache.EvictionThread</a>
+<pre>static class <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.882">LruBlockCache.EvictionThread</a>
 extends <a href="../../../../../../org/apache/hadoop/hbase/util/HasThread.html" title="class in org.apache.hadoop.hbase.util">HasThread</a></pre>
 </li>
 </ul>
@@ -239,7 +239,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/util/HasThread.html"
 <ul class="blockList">
 <li class="blockList">
 <h4>cache</h4>
-<pre>private&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/ref/WeakReference.html?is-external=true" title="class or interface in java.lang.ref">WeakReference</a>&lt;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/LruBlockCache.html" title="class in org.apache.hadoop.hbase.io.hfile">LruBlockCache</a>&gt; <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.EvictionThread.html#line.879">cache</a></pre>
+<pre>private&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/ref/WeakReference.html?is-external=true" title="class or interface in java.lang.ref">WeakReference</a>&lt;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/LruBlockCache.html" title="class in org.apache.hadoop.hbase.io.hfile">LruBlockCache</a>&gt; <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.EvictionThread.html#line.884">cache</a></pre>
 </li>
 </ul>
 <a name="go">
@@ -248,7 +248,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/util/HasThread.html"
 <ul class="blockList">
 <li class="blockList">
 <h4>go</h4>
-<pre>private volatile&nbsp;boolean <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.EvictionThread.html#line.880">go</a></pre>
+<pre>private volatile&nbsp;boolean <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.EvictionThread.html#line.885">go</a></pre>
 </li>
 </ul>
 <a name="enteringRun">
@@ -257,7 +257,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/util/HasThread.html"
 <ul class="blockListLast">
 <li class="blockList">
 <h4>enteringRun</h4>
-<pre>private&nbsp;boolean <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.EvictionThread.html#line.882">enteringRun</a></pre>
+<pre>private&nbsp;boolean <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.EvictionThread.html#line.887">enteringRun</a></pre>
 </li>
 </ul>
 </li>
@@ -274,7 +274,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/util/HasThread.html"
 <ul class="blockListLast">
 <li class="blockList">
 <h4>EvictionThread</h4>
-<pre>public&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.EvictionThread.html#line.884">EvictionThread</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/LruBlockCache.html" title="class in org.apache.hadoop.hbase.io.hfile">LruBlockCache</a>&nbsp;cache)</pre>
+<pre>public&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.EvictionThread.html#line.889">EvictionThread</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/LruBlockCache.html" title="class in org.apache.hadoop.hbase.io.hfile">LruBlockCache</a>&nbsp;cache)</pre>
 </li>
 </ul>
 </li>
@@ -291,7 +291,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/util/HasThread.html"
 <ul class="blockList">
 <li class="blockList">
 <h4>run</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.EvictionThread.html#line.891">run</a>()</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.EvictionThread.html#line.896">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>
@@ -306,7 +306,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/util/HasThread.html"
 <ul class="blockList">
 <li class="blockList">
 <h4>evict</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.EvictionThread.html#line.910">evict</a>()</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.EvictionThread.html#line.915">evict</a>()</pre>
 </li>
 </ul>
 <a name="shutdown--">
@@ -315,7 +315,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/util/HasThread.html"
 <ul class="blockList">
 <li class="blockList">
 <h4>shutdown</h4>
-<pre>void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.EvictionThread.html#line.916">shutdown</a>()</pre>
+<pre>void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.EvictionThread.html#line.921">shutdown</a>()</pre>
 </li>
 </ul>
 <a name="isEnteringRun--">
@@ -324,7 +324,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/util/HasThread.html"
 <ul class="blockListLast">
 <li class="blockList">
 <h4>isEnteringRun</h4>
-<pre>boolean&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.EvictionThread.html#line.924">isEnteringRun</a>()</pre>
+<pre>boolean&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.EvictionThread.html#line.929">isEnteringRun</a>()</pre>
 <div class="block">Used for the test.</div>
 </li>
 </ul>

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/org/apache/hadoop/hbase/io/hfile/LruBlockCache.StatisticsThread.html
----------------------------------------------------------------------
diff --git a/devapidocs/org/apache/hadoop/hbase/io/hfile/LruBlockCache.StatisticsThread.html b/devapidocs/org/apache/hadoop/hbase/io/hfile/LruBlockCache.StatisticsThread.html
index 6918b4b..e896b6e 100644
--- a/devapidocs/org/apache/hadoop/hbase/io/hfile/LruBlockCache.StatisticsThread.html
+++ b/devapidocs/org/apache/hadoop/hbase/io/hfile/LruBlockCache.StatisticsThread.html
@@ -122,7 +122,7 @@ var activeTableTab = "activeTableTab";
 </dl>
 <hr>
 <br>
-<pre>static class <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.932">LruBlockCache.StatisticsThread</a>
+<pre>static class <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html#line.937">LruBlockCache.StatisticsThread</a>
 extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html?is-external=true" title="class or interface in java.lang">Thread</a></pre>
 </li>
 </ul>
@@ -239,7 +239,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>lru</h4>
-<pre>private final&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/LruBlockCache.html" title="class in org.apache.hadoop.hbase.io.hfile">LruBlockCache</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.StatisticsThread.html#line.934">lru</a></pre>
+<pre>private final&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/LruBlockCache.html" title="class in org.apache.hadoop.hbase.io.hfile">LruBlockCache</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.StatisticsThread.html#line.939">lru</a></pre>
 </li>
 </ul>
 </li>
@@ -256,7 +256,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>StatisticsThread</h4>
-<pre>public&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.StatisticsThread.html#line.936">StatisticsThread</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/LruBlockCache.html" title="class in org.apache.hadoop.hbase.io.hfile">LruBlockCache</a>&nbsp;lru)</pre>
+<pre>public&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.StatisticsThread.html#line.941">StatisticsThread</a>(<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/LruBlockCache.html" title="class in org.apache.hadoop.hbase.io.hfile">LruBlockCache</a>&nbsp;lru)</pre>
 </li>
 </ul>
 </li>
@@ -273,7 +273,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>run</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.StatisticsThread.html#line.943">run</a>()</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/LruBlockCache.StatisticsThread.html#line.948">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>


[32/50] hbase-site git commit: Published site at 26babcf013de696b899d76a3c39434b794440d8d.

Posted by gi...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html
----------------------------------------------------------------------
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html
index 97ceefd..b7b4236 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.html
@@ -103,8 +103,8 @@
 <span class="sourceLineNo">095</span> * Caches cache whole blocks with trailing checksums if any. We then tag on some metadata, the<a name="line.95"></a>
 <span class="sourceLineNo">096</span> * content of BLOCK_METADATA_SPACE which will be flag on if we are doing 'hbase'<a name="line.96"></a>
 <span class="sourceLineNo">097</span> * checksums and then the offset into the file which is needed when we re-make a cache key<a name="line.97"></a>
-<span class="sourceLineNo">098</span> * when we return the block to the cache as 'done'. See {@link Cacheable#serialize(ByteBuffer)} and<a name="line.98"></a>
-<span class="sourceLineNo">099</span> * {@link Cacheable#getDeserializer()}.<a name="line.99"></a>
+<span class="sourceLineNo">098</span> * when we return the block to the cache as 'done'.<a name="line.98"></a>
+<span class="sourceLineNo">099</span> * See {@link Cacheable#serialize(ByteBuffer, boolean)} and {@link Cacheable#getDeserializer()}.<a name="line.99"></a>
 <span class="sourceLineNo">100</span> *<a name="line.100"></a>
 <span class="sourceLineNo">101</span> * &lt;p&gt;TODO: Should we cache the checksums? Down in Writer#getBlockForCaching(CacheConfig) where<a name="line.101"></a>
 <span class="sourceLineNo">102</span> * we make a block to cache-on-write, there is an attempt at turning off checksums. This is not the<a name="line.102"></a>
@@ -333,1579 +333,1579 @@
 <span class="sourceLineNo">325</span>   * Creates a new {@link HFile} block from the given fields. This constructor<a name="line.325"></a>
 <span class="sourceLineNo">326</span>   * is used only while writing blocks and caching,<a name="line.326"></a>
 <span class="sourceLineNo">327</span>   * and is sitting in a byte buffer and we want to stuff the block into cache.<a name="line.327"></a>
-<span class="sourceLineNo">328</span>   * See {@link Writer#getBlockForCaching(CacheConfig)}.<a name="line.328"></a>
-<span class="sourceLineNo">329</span>   *<a name="line.329"></a>
-<span class="sourceLineNo">330</span>   * &lt;p&gt;TODO: The caller presumes no checksumming<a name="line.330"></a>
-<span class="sourceLineNo">331</span>   * required of this block instance since going into cache; checksum already verified on<a name="line.331"></a>
-<span class="sourceLineNo">332</span>   * underlying block data pulled in from filesystem. Is that correct? What if cache is SSD?<a name="line.332"></a>
-<span class="sourceLineNo">333</span>   *<a name="line.333"></a>
-<span class="sourceLineNo">334</span>   * @param blockType the type of this block, see {@link BlockType}<a name="line.334"></a>
-<span class="sourceLineNo">335</span>   * @param onDiskSizeWithoutHeader see {@link #onDiskSizeWithoutHeader}<a name="line.335"></a>
-<span class="sourceLineNo">336</span>   * @param uncompressedSizeWithoutHeader see {@link #uncompressedSizeWithoutHeader}<a name="line.336"></a>
-<span class="sourceLineNo">337</span>   * @param prevBlockOffset see {@link #prevBlockOffset}<a name="line.337"></a>
-<span class="sourceLineNo">338</span>   * @param b block header ({@link HConstants#HFILEBLOCK_HEADER_SIZE} bytes)<a name="line.338"></a>
-<span class="sourceLineNo">339</span>   * @param fillHeader when true, write the first 4 header fields into passed buffer.<a name="line.339"></a>
-<span class="sourceLineNo">340</span>   * @param offset the file offset the block was read from<a name="line.340"></a>
-<span class="sourceLineNo">341</span>   * @param onDiskDataSizeWithHeader see {@link #onDiskDataSizeWithHeader}<a name="line.341"></a>
-<span class="sourceLineNo">342</span>   * @param fileContext HFile meta data<a name="line.342"></a>
-<span class="sourceLineNo">343</span>   */<a name="line.343"></a>
-<span class="sourceLineNo">344</span>  HFileBlock(BlockType blockType, int onDiskSizeWithoutHeader, int uncompressedSizeWithoutHeader,<a name="line.344"></a>
-<span class="sourceLineNo">345</span>      long prevBlockOffset, ByteBuffer b, boolean fillHeader, long offset,<a name="line.345"></a>
-<span class="sourceLineNo">346</span>      final int nextBlockOnDiskSize, int onDiskDataSizeWithHeader, HFileContext fileContext) {<a name="line.346"></a>
-<span class="sourceLineNo">347</span>    init(blockType, onDiskSizeWithoutHeader, uncompressedSizeWithoutHeader,<a name="line.347"></a>
-<span class="sourceLineNo">348</span>        prevBlockOffset, offset, onDiskDataSizeWithHeader, nextBlockOnDiskSize, fileContext);<a name="line.348"></a>
-<span class="sourceLineNo">349</span>    this.buf = new SingleByteBuff(b);<a name="line.349"></a>
-<span class="sourceLineNo">350</span>    if (fillHeader) {<a name="line.350"></a>
-<span class="sourceLineNo">351</span>      overwriteHeader();<a name="line.351"></a>
-<span class="sourceLineNo">352</span>    }<a name="line.352"></a>
-<span class="sourceLineNo">353</span>    this.buf.rewind();<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>  /**<a name="line.356"></a>
-<span class="sourceLineNo">357</span>   * Creates a block from an existing buffer starting with a header. Rewinds<a name="line.357"></a>
-<span class="sourceLineNo">358</span>   * and takes ownership of the buffer. By definition of rewind, ignores the<a name="line.358"></a>
-<span class="sourceLineNo">359</span>   * buffer position, but if you slice the buffer beforehand, it will rewind<a name="line.359"></a>
-<span class="sourceLineNo">360</span>   * to that point.<a name="line.360"></a>
-<span class="sourceLineNo">361</span>   * @param buf Has header, content, and trailing checksums if present.<a name="line.361"></a>
-<span class="sourceLineNo">362</span>   */<a name="line.362"></a>
-<span class="sourceLineNo">363</span>  HFileBlock(ByteBuff buf, boolean usesHBaseChecksum, MemoryType memType, final long offset,<a name="line.363"></a>
-<span class="sourceLineNo">364</span>      final int nextBlockOnDiskSize, HFileContext fileContext) throws IOException {<a name="line.364"></a>
-<span class="sourceLineNo">365</span>    buf.rewind();<a name="line.365"></a>
-<span class="sourceLineNo">366</span>    final BlockType blockType = BlockType.read(buf);<a name="line.366"></a>
-<span class="sourceLineNo">367</span>    final int onDiskSizeWithoutHeader = buf.getInt(Header.ON_DISK_SIZE_WITHOUT_HEADER_INDEX);<a name="line.367"></a>
-<span class="sourceLineNo">368</span>    final int uncompressedSizeWithoutHeader =<a name="line.368"></a>
-<span class="sourceLineNo">369</span>        buf.getInt(Header.UNCOMPRESSED_SIZE_WITHOUT_HEADER_INDEX);<a name="line.369"></a>
-<span class="sourceLineNo">370</span>    final long prevBlockOffset = buf.getLong(Header.PREV_BLOCK_OFFSET_INDEX);<a name="line.370"></a>
-<span class="sourceLineNo">371</span>    // This constructor is called when we deserialize a block from cache and when we read a block in<a name="line.371"></a>
-<span class="sourceLineNo">372</span>    // from the fs. fileCache is null when deserialized from cache so need to make up one.<a name="line.372"></a>
-<span class="sourceLineNo">373</span>    HFileContextBuilder fileContextBuilder = fileContext != null?<a name="line.373"></a>
-<span class="sourceLineNo">374</span>        new HFileContextBuilder(fileContext): new HFileContextBuilder();<a name="line.374"></a>
-<span class="sourceLineNo">375</span>    fileContextBuilder.withHBaseCheckSum(usesHBaseChecksum);<a name="line.375"></a>
-<span class="sourceLineNo">376</span>    int onDiskDataSizeWithHeader;<a name="line.376"></a>
-<span class="sourceLineNo">377</span>    if (usesHBaseChecksum) {<a name="line.377"></a>
-<span class="sourceLineNo">378</span>      byte checksumType = buf.get(Header.CHECKSUM_TYPE_INDEX);<a name="line.378"></a>
-<span class="sourceLineNo">379</span>      int bytesPerChecksum = buf.getInt(Header.BYTES_PER_CHECKSUM_INDEX);<a name="line.379"></a>
-<span class="sourceLineNo">380</span>      onDiskDataSizeWithHeader = buf.getInt(Header.ON_DISK_DATA_SIZE_WITH_HEADER_INDEX);<a name="line.380"></a>
-<span class="sourceLineNo">381</span>      // Use the checksum type and bytes per checksum from header, not from filecontext.<a name="line.381"></a>
-<span class="sourceLineNo">382</span>      fileContextBuilder.withChecksumType(ChecksumType.codeToType(checksumType));<a name="line.382"></a>
-<span class="sourceLineNo">383</span>      fileContextBuilder.withBytesPerCheckSum(bytesPerChecksum);<a name="line.383"></a>
-<span class="sourceLineNo">384</span>    } else {<a name="line.384"></a>
-<span class="sourceLineNo">385</span>      fileContextBuilder.withChecksumType(ChecksumType.NULL);<a name="line.385"></a>
-<span class="sourceLineNo">386</span>      fileContextBuilder.withBytesPerCheckSum(0);<a name="line.386"></a>
-<span class="sourceLineNo">387</span>      // Need to fix onDiskDataSizeWithHeader; there are not checksums after-block-data<a name="line.387"></a>
-<span class="sourceLineNo">388</span>      onDiskDataSizeWithHeader = onDiskSizeWithoutHeader + headerSize(usesHBaseChecksum);<a name="line.388"></a>
-<span class="sourceLineNo">389</span>    }<a name="line.389"></a>
-<span class="sourceLineNo">390</span>    fileContext = fileContextBuilder.build();<a name="line.390"></a>
-<span class="sourceLineNo">391</span>    assert usesHBaseChecksum == fileContext.isUseHBaseChecksum();<a name="line.391"></a>
-<span class="sourceLineNo">392</span>    init(blockType, onDiskSizeWithoutHeader, uncompressedSizeWithoutHeader,<a name="line.392"></a>
-<span class="sourceLineNo">393</span>        prevBlockOffset, offset, onDiskDataSizeWithHeader, nextBlockOnDiskSize, fileContext);<a name="line.393"></a>
-<span class="sourceLineNo">394</span>    this.memType = memType;<a name="line.394"></a>
-<span class="sourceLineNo">395</span>    this.offset = offset;<a name="line.395"></a>
-<span class="sourceLineNo">396</span>    this.buf = buf;<a name="line.396"></a>
-<span class="sourceLineNo">397</span>    this.buf.rewind();<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>  /**<a name="line.400"></a>
-<span class="sourceLineNo">401</span>   * Called from constructors.<a name="line.401"></a>
-<span class="sourceLineNo">402</span>   */<a name="line.402"></a>
-<span class="sourceLineNo">403</span>  private void init(BlockType blockType, int onDiskSizeWithoutHeader,<a name="line.403"></a>
-<span class="sourceLineNo">404</span>      int uncompressedSizeWithoutHeader, long prevBlockOffset,<a name="line.404"></a>
-<span class="sourceLineNo">405</span>      long offset, int onDiskDataSizeWithHeader, final int nextBlockOnDiskSize,<a name="line.405"></a>
-<span class="sourceLineNo">406</span>      HFileContext fileContext) {<a name="line.406"></a>
-<span class="sourceLineNo">407</span>    this.blockType = blockType;<a name="line.407"></a>
-<span class="sourceLineNo">408</span>    this.onDiskSizeWithoutHeader = onDiskSizeWithoutHeader;<a name="line.408"></a>
-<span class="sourceLineNo">409</span>    this.uncompressedSizeWithoutHeader = uncompressedSizeWithoutHeader;<a name="line.409"></a>
-<span class="sourceLineNo">410</span>    this.prevBlockOffset = prevBlockOffset;<a name="line.410"></a>
-<span class="sourceLineNo">411</span>    this.offset = offset;<a name="line.411"></a>
-<span class="sourceLineNo">412</span>    this.onDiskDataSizeWithHeader = onDiskDataSizeWithHeader;<a name="line.412"></a>
-<span class="sourceLineNo">413</span>    this.nextBlockOnDiskSize = nextBlockOnDiskSize;<a name="line.413"></a>
-<span class="sourceLineNo">414</span>    this.fileContext = fileContext;<a name="line.414"></a>
-<span class="sourceLineNo">415</span>  }<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">418</span>   * Parse total on disk size including header and checksum.<a name="line.418"></a>
-<span class="sourceLineNo">419</span>   * @param headerBuf Header ByteBuffer. Presumed exact size of header.<a name="line.419"></a>
-<span class="sourceLineNo">420</span>   * @param verifyChecksum true if checksum verification is in use.<a name="line.420"></a>
-<span class="sourceLineNo">421</span>   * @return Size of the block with header included.<a name="line.421"></a>
-<span class="sourceLineNo">422</span>   */<a name="line.422"></a>
-<span class="sourceLineNo">423</span>  private static int getOnDiskSizeWithHeader(final ByteBuffer headerBuf,<a name="line.423"></a>
-<span class="sourceLineNo">424</span>      boolean verifyChecksum) {<a name="line.424"></a>
-<span class="sourceLineNo">425</span>    return headerBuf.getInt(Header.ON_DISK_SIZE_WITHOUT_HEADER_INDEX) +<a name="line.425"></a>
-<span class="sourceLineNo">426</span>      headerSize(verifyChecksum);<a name="line.426"></a>
-<span class="sourceLineNo">427</span>  }<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>   * @return the on-disk size of the next block (including the header size and any checksums if<a name="line.430"></a>
-<span class="sourceLineNo">431</span>   * present) read by peeking into the next block's header; use as a hint when doing<a name="line.431"></a>
-<span class="sourceLineNo">432</span>   * a read of the next block when scanning or running over a file.<a name="line.432"></a>
-<span class="sourceLineNo">433</span>   */<a name="line.433"></a>
-<span class="sourceLineNo">434</span>  int getNextBlockOnDiskSize() {<a name="line.434"></a>
-<span class="sourceLineNo">435</span>    return nextBlockOnDiskSize;<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>  @Override<a name="line.438"></a>
-<span class="sourceLineNo">439</span>  public BlockType getBlockType() {<a name="line.439"></a>
-<span class="sourceLineNo">440</span>    return blockType;<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>  /** @return get data block encoding id that was used to encode this block */<a name="line.443"></a>
-<span class="sourceLineNo">444</span>  short getDataBlockEncodingId() {<a name="line.444"></a>
-<span class="sourceLineNo">445</span>    if (blockType != BlockType.ENCODED_DATA) {<a name="line.445"></a>
-<span class="sourceLineNo">446</span>      throw new IllegalArgumentException("Querying encoder ID of a block " +<a name="line.446"></a>
-<span class="sourceLineNo">447</span>          "of type other than " + BlockType.ENCODED_DATA + ": " + blockType);<a name="line.447"></a>
-<span class="sourceLineNo">448</span>    }<a name="line.448"></a>
-<span class="sourceLineNo">449</span>    return buf.getShort(headerSize());<a name="line.449"></a>
-<span class="sourceLineNo">450</span>  }<a name="line.450"></a>
-<span class="sourceLineNo">451</span><a name="line.451"></a>
-<span class="sourceLineNo">452</span>  /**<a name="line.452"></a>
-<span class="sourceLineNo">453</span>   * @return the on-disk size of header + data part + checksum.<a name="line.453"></a>
-<span class="sourceLineNo">454</span>   */<a name="line.454"></a>
-<span class="sourceLineNo">455</span>  public int getOnDiskSizeWithHeader() {<a name="line.455"></a>
-<span class="sourceLineNo">456</span>    return onDiskSizeWithoutHeader + headerSize();<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>   * @return the on-disk size of the data part + checksum (header excluded).<a name="line.460"></a>
-<span class="sourceLineNo">461</span>   */<a name="line.461"></a>
-<span class="sourceLineNo">462</span>  int getOnDiskSizeWithoutHeader() {<a name="line.462"></a>
-<span class="sourceLineNo">463</span>    return onDiskSizeWithoutHeader;<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>  /**<a name="line.466"></a>
-<span class="sourceLineNo">467</span>   * @return the uncompressed size of data part (header and checksum excluded).<a name="line.467"></a>
-<span class="sourceLineNo">468</span>   */<a name="line.468"></a>
-<span class="sourceLineNo">469</span>   int getUncompressedSizeWithoutHeader() {<a name="line.469"></a>
-<span class="sourceLineNo">470</span>    return uncompressedSizeWithoutHeader;<a name="line.470"></a>
-<span class="sourceLineNo">471</span>  }<a name="line.471"></a>
-<span class="sourceLineNo">472</span><a name="line.472"></a>
-<span class="sourceLineNo">473</span>  /**<a name="line.473"></a>
-<span class="sourceLineNo">474</span>   * @return the offset of the previous block of the same type in the file, or<a name="line.474"></a>
-<span class="sourceLineNo">475</span>   *         -1 if unknown<a name="line.475"></a>
-<span class="sourceLineNo">476</span>   */<a name="line.476"></a>
-<span class="sourceLineNo">477</span>  long getPrevBlockOffset() {<a name="line.477"></a>
-<span class="sourceLineNo">478</span>    return prevBlockOffset;<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>   * Rewinds {@code buf} and writes first 4 header fields. {@code buf} position<a name="line.482"></a>
-<span class="sourceLineNo">483</span>   * is modified as side-effect.<a name="line.483"></a>
-<span class="sourceLineNo">484</span>   */<a name="line.484"></a>
-<span class="sourceLineNo">485</span>  private void overwriteHeader() {<a name="line.485"></a>
-<span class="sourceLineNo">486</span>    buf.rewind();<a name="line.486"></a>
-<span class="sourceLineNo">487</span>    blockType.write(buf);<a name="line.487"></a>
-<span class="sourceLineNo">488</span>    buf.putInt(onDiskSizeWithoutHeader);<a name="line.488"></a>
-<span class="sourceLineNo">489</span>    buf.putInt(uncompressedSizeWithoutHeader);<a name="line.489"></a>
-<span class="sourceLineNo">490</span>    buf.putLong(prevBlockOffset);<a name="line.490"></a>
-<span class="sourceLineNo">491</span>    if (this.fileContext.isUseHBaseChecksum()) {<a name="line.491"></a>
-<span class="sourceLineNo">492</span>      buf.put(fileContext.getChecksumType().getCode());<a name="line.492"></a>
-<span class="sourceLineNo">493</span>      buf.putInt(fileContext.getBytesPerChecksum());<a name="line.493"></a>
-<span class="sourceLineNo">494</span>      buf.putInt(onDiskDataSizeWithHeader);<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>  /**<a name="line.498"></a>
-<span class="sourceLineNo">499</span>   * Returns a buffer that does not include the header or checksum.<a name="line.499"></a>
-<span class="sourceLineNo">500</span>   *<a name="line.500"></a>
-<span class="sourceLineNo">501</span>   * @return the buffer with header skipped and checksum omitted.<a name="line.501"></a>
-<span class="sourceLineNo">502</span>   */<a name="line.502"></a>
-<span class="sourceLineNo">503</span>  public ByteBuff getBufferWithoutHeader() {<a name="line.503"></a>
-<span class="sourceLineNo">504</span>    ByteBuff dup = getBufferReadOnly();<a name="line.504"></a>
-<span class="sourceLineNo">505</span>    // Now set it up so Buffer spans content only -- no header or no checksums.<a name="line.505"></a>
-<span class="sourceLineNo">506</span>    return dup.position(headerSize()).limit(buf.limit() - totalChecksumBytes()).slice();<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 a read-only duplicate of the buffer this block stores internally ready to be read.<a name="line.510"></a>
-<span class="sourceLineNo">511</span>   * Clients must not modify the buffer object though they may set position and limit on the<a name="line.511"></a>
-<span class="sourceLineNo">512</span>   * returned buffer since we pass back a duplicate. This method has to be public because it is used<a name="line.512"></a>
-<span class="sourceLineNo">513</span>   * in {@link CompoundBloomFilter} to avoid object creation on every Bloom<a name="line.513"></a>
-<span class="sourceLineNo">514</span>   * filter lookup, but has to be used with caution. Buffer holds header, block content,<a name="line.514"></a>
-<span class="sourceLineNo">515</span>   * and any follow-on checksums if present.<a name="line.515"></a>
-<span class="sourceLineNo">516</span>   *<a name="line.516"></a>
-<span class="sourceLineNo">517</span>   * @return the buffer of this block for read-only operations<a name="line.517"></a>
-<span class="sourceLineNo">518</span>   */<a name="line.518"></a>
-<span class="sourceLineNo">519</span>  public ByteBuff getBufferReadOnly() {<a name="line.519"></a>
-<span class="sourceLineNo">520</span>    // TODO: ByteBuf does not support asReadOnlyBuffer(). Fix.<a name="line.520"></a>
-<span class="sourceLineNo">521</span>    ByteBuff dup = this.buf.duplicate();<a name="line.521"></a>
-<span class="sourceLineNo">522</span>    assert dup.position() == 0;<a name="line.522"></a>
-<span class="sourceLineNo">523</span>    return dup;<a name="line.523"></a>
-<span class="sourceLineNo">524</span>  }<a name="line.524"></a>
-<span class="sourceLineNo">525</span><a name="line.525"></a>
-<span class="sourceLineNo">526</span>  @VisibleForTesting<a name="line.526"></a>
-<span class="sourceLineNo">527</span>  private void sanityCheckAssertion(long valueFromBuf, long valueFromField,<a name="line.527"></a>
-<span class="sourceLineNo">528</span>      String fieldName) throws IOException {<a name="line.528"></a>
-<span class="sourceLineNo">529</span>    if (valueFromBuf != valueFromField) {<a name="line.529"></a>
-<span class="sourceLineNo">530</span>      throw new AssertionError(fieldName + " in the buffer (" + valueFromBuf<a name="line.530"></a>
-<span class="sourceLineNo">531</span>          + ") is different from that in the field (" + valueFromField + ")");<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>  @VisibleForTesting<a name="line.535"></a>
-<span class="sourceLineNo">536</span>  private void sanityCheckAssertion(BlockType valueFromBuf, BlockType valueFromField)<a name="line.536"></a>
-<span class="sourceLineNo">537</span>      throws IOException {<a name="line.537"></a>
-<span class="sourceLineNo">538</span>    if (valueFromBuf != valueFromField) {<a name="line.538"></a>
-<span class="sourceLineNo">539</span>      throw new IOException("Block type stored in the buffer: " +<a name="line.539"></a>
-<span class="sourceLineNo">540</span>        valueFromBuf + ", block type field: " + valueFromField);<a name="line.540"></a>
-<span class="sourceLineNo">541</span>    }<a name="line.541"></a>
-<span class="sourceLineNo">542</span>  }<a name="line.542"></a>
-<span class="sourceLineNo">543</span><a name="line.543"></a>
-<span class="sourceLineNo">544</span>  /**<a name="line.544"></a>
-<span class="sourceLineNo">545</span>   * Checks if the block is internally consistent, i.e. the first<a name="line.545"></a>
-<span class="sourceLineNo">546</span>   * {@link HConstants#HFILEBLOCK_HEADER_SIZE} bytes of the buffer contain a<a name="line.546"></a>
-<span class="sourceLineNo">547</span>   * valid header consistent with the fields. Assumes a packed block structure.<a name="line.547"></a>
-<span class="sourceLineNo">548</span>   * This function is primary for testing and debugging, and is not<a name="line.548"></a>
-<span class="sourceLineNo">549</span>   * thread-safe, because it alters the internal buffer pointer.<a name="line.549"></a>
-<span class="sourceLineNo">550</span>   * Used by tests only.<a name="line.550"></a>
-<span class="sourceLineNo">551</span>   */<a name="line.551"></a>
-<span class="sourceLineNo">552</span>  @VisibleForTesting<a name="line.552"></a>
-<span class="sourceLineNo">553</span>  void sanityCheck() throws IOException {<a name="line.553"></a>
-<span class="sourceLineNo">554</span>    // Duplicate so no side-effects<a name="line.554"></a>
-<span class="sourceLineNo">555</span>    ByteBuff dup = this.buf.duplicate().rewind();<a name="line.555"></a>
-<span class="sourceLineNo">556</span>    sanityCheckAssertion(BlockType.read(dup), blockType);<a name="line.556"></a>
-<span class="sourceLineNo">557</span><a name="line.557"></a>
-<span class="sourceLineNo">558</span>    sanityCheckAssertion(dup.getInt(), onDiskSizeWithoutHeader, "onDiskSizeWithoutHeader");<a name="line.558"></a>
-<span class="sourceLineNo">559</span><a name="line.559"></a>
-<span class="sourceLineNo">560</span>    sanityCheckAssertion(dup.getInt(), uncompressedSizeWithoutHeader,<a name="line.560"></a>
-<span class="sourceLineNo">561</span>        "uncompressedSizeWithoutHeader");<a name="line.561"></a>
-<span class="sourceLineNo">562</span><a name="line.562"></a>
-<span class="sourceLineNo">563</span>    sanityCheckAssertion(dup.getLong(), prevBlockOffset, "prevBlockOffset");<a name="line.563"></a>
-<span class="sourceLineNo">564</span>    if (this.fileContext.isUseHBaseChecksum()) {<a name="line.564"></a>
-<span class="sourceLineNo">565</span>      sanityCheckAssertion(dup.get(), this.fileContext.getChecksumType().getCode(), "checksumType");<a name="line.565"></a>
-<span class="sourceLineNo">566</span>      sanityCheckAssertion(dup.getInt(), this.fileContext.getBytesPerChecksum(),<a name="line.566"></a>
-<span class="sourceLineNo">567</span>          "bytesPerChecksum");<a name="line.567"></a>
-<span class="sourceLineNo">568</span>      sanityCheckAssertion(dup.getInt(), onDiskDataSizeWithHeader, "onDiskDataSizeWithHeader");<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>    int cksumBytes = totalChecksumBytes();<a name="line.571"></a>
-<span class="sourceLineNo">572</span>    int expectedBufLimit = onDiskDataSizeWithHeader + cksumBytes;<a name="line.572"></a>
-<span class="sourceLineNo">573</span>    if (dup.limit() != expectedBufLimit) {<a name="line.573"></a>
-<span class="sourceLineNo">574</span>      throw new AssertionError("Expected limit " + expectedBufLimit + ", got " + dup.limit());<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>    // We might optionally allocate HFILEBLOCK_HEADER_SIZE more bytes to read the next<a name="line.577"></a>
-<span class="sourceLineNo">578</span>    // block's header, so there are two sensible values for buffer capacity.<a name="line.578"></a>
-<span class="sourceLineNo">579</span>    int hdrSize = headerSize();<a name="line.579"></a>
-<span class="sourceLineNo">580</span>    if (dup.capacity() != expectedBufLimit &amp;&amp; dup.capacity() != expectedBufLimit + hdrSize) {<a name="line.580"></a>
-<span class="sourceLineNo">581</span>      throw new AssertionError("Invalid buffer capacity: " + dup.capacity() +<a name="line.581"></a>
-<span class="sourceLineNo">582</span>          ", expected " + expectedBufLimit + " or " + (expectedBufLimit + hdrSize));<a name="line.582"></a>
-<span class="sourceLineNo">583</span>    }<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>  @Override<a name="line.586"></a>
-<span class="sourceLineNo">587</span>  public String toString() {<a name="line.587"></a>
-<span class="sourceLineNo">588</span>    StringBuilder sb = new StringBuilder()<a name="line.588"></a>
-<span class="sourceLineNo">589</span>      .append("[")<a name="line.589"></a>
-<span class="sourceLineNo">590</span>      .append("blockType=").append(blockType)<a name="line.590"></a>
-<span class="sourceLineNo">591</span>      .append(", fileOffset=").append(offset)<a name="line.591"></a>
-<span class="sourceLineNo">592</span>      .append(", headerSize=").append(headerSize())<a name="line.592"></a>
-<span class="sourceLineNo">593</span>      .append(", onDiskSizeWithoutHeader=").append(onDiskSizeWithoutHeader)<a name="line.593"></a>
-<span class="sourceLineNo">594</span>      .append(", uncompressedSizeWithoutHeader=").append(uncompressedSizeWithoutHeader)<a name="line.594"></a>
-<span class="sourceLineNo">595</span>      .append(", prevBlockOffset=").append(prevBlockOffset)<a name="line.595"></a>
-<span class="sourceLineNo">596</span>      .append(", isUseHBaseChecksum=").append(fileContext.isUseHBaseChecksum());<a name="line.596"></a>
-<span class="sourceLineNo">597</span>    if (fileContext.isUseHBaseChecksum()) {<a name="line.597"></a>
-<span class="sourceLineNo">598</span>      sb.append(", checksumType=").append(ChecksumType.codeToType(this.buf.get(24)))<a name="line.598"></a>
-<span class="sourceLineNo">599</span>        .append(", bytesPerChecksum=").append(this.buf.getInt(24 + 1))<a name="line.599"></a>
-<span class="sourceLineNo">600</span>        .append(", onDiskDataSizeWithHeader=").append(onDiskDataSizeWithHeader);<a name="line.600"></a>
-<span class="sourceLineNo">601</span>    } else {<a name="line.601"></a>
-<span class="sourceLineNo">602</span>      sb.append(", onDiskDataSizeWithHeader=").append(onDiskDataSizeWithHeader)<a name="line.602"></a>
-<span class="sourceLineNo">603</span>        .append("(").append(onDiskSizeWithoutHeader)<a name="line.603"></a>
-<span class="sourceLineNo">604</span>        .append("+").append(HConstants.HFILEBLOCK_HEADER_SIZE_NO_CHECKSUM).append(")");<a name="line.604"></a>
-<span class="sourceLineNo">605</span>    }<a name="line.605"></a>
-<span class="sourceLineNo">606</span>    String dataBegin = null;<a name="line.606"></a>
-<span class="sourceLineNo">607</span>    if (buf.hasArray()) {<a name="line.607"></a>
-<span class="sourceLineNo">608</span>      dataBegin = Bytes.toStringBinary(buf.array(), buf.arrayOffset() + headerSize(),<a name="line.608"></a>
-<span class="sourceLineNo">609</span>          Math.min(32, buf.limit() - buf.arrayOffset() - headerSize()));<a name="line.609"></a>
-<span class="sourceLineNo">610</span>    } else {<a name="line.610"></a>
-<span class="sourceLineNo">611</span>      ByteBuff bufWithoutHeader = getBufferWithoutHeader();<a name="line.611"></a>
-<span class="sourceLineNo">612</span>      byte[] dataBeginBytes = new byte[Math.min(32,<a name="line.612"></a>
-<span class="sourceLineNo">613</span>          bufWithoutHeader.limit() - bufWithoutHeader.position())];<a name="line.613"></a>
-<span class="sourceLineNo">614</span>      bufWithoutHeader.get(dataBeginBytes);<a name="line.614"></a>
-<span class="sourceLineNo">615</span>      dataBegin = Bytes.toStringBinary(dataBeginBytes);<a name="line.615"></a>
-<span class="sourceLineNo">616</span>    }<a name="line.616"></a>
-<span class="sourceLineNo">617</span>    sb.append(", getOnDiskSizeWithHeader=").append(getOnDiskSizeWithHeader())<a name="line.617"></a>
-<span class="sourceLineNo">618</span>      .append(", totalChecksumBytes=").append(totalChecksumBytes())<a name="line.618"></a>
-<span class="sourceLineNo">619</span>      .append(", isUnpacked=").append(isUnpacked())<a name="line.619"></a>
-<span class="sourceLineNo">620</span>      .append(", buf=[").append(buf).append("]")<a name="line.620"></a>
-<span class="sourceLineNo">621</span>      .append(", dataBeginsWith=").append(dataBegin)<a name="line.621"></a>
-<span class="sourceLineNo">622</span>      .append(", fileContext=").append(fileContext)<a name="line.622"></a>
-<span class="sourceLineNo">623</span>      .append("]");<a name="line.623"></a>
-<span class="sourceLineNo">624</span>    return sb.toString();<a name="line.624"></a>
-<span class="sourceLineNo">625</span>  }<a name="line.625"></a>
-<span class="sourceLineNo">626</span><a name="line.626"></a>
-<span class="sourceLineNo">627</span>  /**<a name="line.627"></a>
-<span class="sourceLineNo">628</span>   * Retrieves the decompressed/decrypted view of this block. An encoded block remains in its<a name="line.628"></a>
-<span class="sourceLineNo">629</span>   * encoded structure. Internal structures are shared between instances where applicable.<a name="line.629"></a>
-<span class="sourceLineNo">630</span>   */<a name="line.630"></a>
-<span class="sourceLineNo">631</span>  HFileBlock unpack(HFileContext fileContext, FSReader reader) throws IOException {<a name="line.631"></a>
-<span class="sourceLineNo">632</span>    if (!fileContext.isCompressedOrEncrypted()) {<a name="line.632"></a>
-<span class="sourceLineNo">633</span>      // TODO: cannot use our own fileContext here because HFileBlock(ByteBuffer, boolean),<a name="line.633"></a>
-<span class="sourceLineNo">634</span>      // which is used for block serialization to L2 cache, does not preserve encoding and<a name="line.634"></a>
-<span class="sourceLineNo">635</span>      // encryption details.<a name="line.635"></a>
-<span class="sourceLineNo">636</span>      return this;<a name="line.636"></a>
-<span class="sourceLineNo">637</span>    }<a name="line.637"></a>
-<span class="sourceLineNo">638</span><a name="line.638"></a>
-<span class="sourceLineNo">639</span>    HFileBlock unpacked = new HFileBlock(this);<a name="line.639"></a>
-<span class="sourceLineNo">640</span>    unpacked.allocateBuffer(); // allocates space for the decompressed block<a name="line.640"></a>
-<span class="sourceLineNo">641</span><a name="line.641"></a>
-<span class="sourceLineNo">642</span>    HFileBlockDecodingContext ctx = blockType == BlockType.ENCODED_DATA ?<a name="line.642"></a>
-<span class="sourceLineNo">643</span>      reader.getBlockDecodingContext() : reader.getDefaultBlockDecodingContext();<a name="line.643"></a>
-<span class="sourceLineNo">644</span><a name="line.644"></a>
-<span class="sourceLineNo">645</span>    ByteBuff dup = this.buf.duplicate();<a name="line.645"></a>
-<span class="sourceLineNo">646</span>    dup.position(this.headerSize());<a name="line.646"></a>
-<span class="sourceLineNo">647</span>    dup = dup.slice();<a name="line.647"></a>
-<span class="sourceLineNo">648</span>    ctx.prepareDecoding(unpacked.getOnDiskSizeWithoutHeader(),<a name="line.648"></a>
-<span class="sourceLineNo">649</span>      unpacked.getUncompressedSizeWithoutHeader(), unpacked.getBufferWithoutHeader(),<a name="line.649"></a>
-<span class="sourceLineNo">650</span>      dup);<a name="line.650"></a>
-<span class="sourceLineNo">651</span>    return unpacked;<a name="line.651"></a>
-<span class="sourceLineNo">652</span>  }<a name="line.652"></a>
-<span class="sourceLineNo">653</span><a name="line.653"></a>
-<span class="sourceLineNo">654</span>  /**<a name="line.654"></a>
-<span class="sourceLineNo">655</span>   * Always allocates a new buffer of the correct size. Copies header bytes<a name="line.655"></a>
-<span class="sourceLineNo">656</span>   * from the existing buffer. Does not change header fields.<a name="line.656"></a>
-<span class="sourceLineNo">657</span>   * Reserve room to keep checksum bytes too.<a name="line.657"></a>
-<span class="sourceLineNo">658</span>   */<a name="line.658"></a>
-<span class="sourceLineNo">659</span>  private void allocateBuffer() {<a name="line.659"></a>
-<span class="sourceLineNo">660</span>    int cksumBytes = totalChecksumBytes();<a name="line.660"></a>
-<span class="sourceLineNo">661</span>    int headerSize = headerSize();<a name="line.661"></a>
-<span class="sourceLineNo">662</span>    int capacityNeeded = headerSize + uncompressedSizeWithoutHeader + cksumBytes;<a name="line.662"></a>
-<span class="sourceLineNo">663</span><a name="line.663"></a>
-<span class="sourceLineNo">664</span>    // TODO we need consider allocating offheap here?<a name="line.664"></a>
-<span class="sourceLineNo">665</span>    ByteBuffer newBuf = ByteBuffer.allocate(capacityNeeded);<a name="line.665"></a>
-<span class="sourceLineNo">666</span><a name="line.666"></a>
-<span class="sourceLineNo">667</span>    // Copy header bytes into newBuf.<a name="line.667"></a>
-<span class="sourceLineNo">668</span>    // newBuf is HBB so no issue in calling array()<a name="line.668"></a>
-<span class="sourceLineNo">669</span>    buf.position(0);<a name="line.669"></a>
-<span class="sourceLineNo">670</span>    buf.get(newBuf.array(), newBuf.arrayOffset(), headerSize);<a name="line.670"></a>
-<span class="sourceLineNo">671</span><a name="line.671"></a>
-<span class="sourceLineNo">672</span>    buf = new SingleByteBuff(newBuf);<a name="line.672"></a>
-<span class="sourceLineNo">673</span>    // set limit to exclude next block's header<a name="line.673"></a>
-<span class="sourceLineNo">674</span>    buf.limit(headerSize + uncompressedSizeWithoutHeader + cksumBytes);<a name="line.674"></a>
-<span class="sourceLineNo">675</span>  }<a name="line.675"></a>
-<span class="sourceLineNo">676</span><a name="line.676"></a>
-<span class="sourceLineNo">677</span>  /**<a name="line.677"></a>
-<span class="sourceLineNo">678</span>   * Return true when this block's buffer has been unpacked, false otherwise. Note this is a<a name="line.678"></a>
-<span class="sourceLineNo">679</span>   * calculated heuristic, not tracked attribute of the block.<a name="line.679"></a>
-<span class="sourceLineNo">680</span>   */<a name="line.680"></a>
-<span class="sourceLineNo">681</span>  public boolean isUnpacked() {<a name="line.681"></a>
-<span class="sourceLineNo">682</span>    final int cksumBytes = totalChecksumBytes();<a name="line.682"></a>
-<span class="sourceLineNo">683</span>    final int headerSize = headerSize();<a name="line.683"></a>
-<span class="sourceLineNo">684</span>    final int expectedCapacity = headerSize + uncompressedSizeWithoutHeader + cksumBytes;<a name="line.684"></a>
-<span class="sourceLineNo">685</span>    final int bufCapacity = buf.capacity();<a name="line.685"></a>
-<span class="sourceLineNo">686</span>    return bufCapacity == expectedCapacity || bufCapacity == expectedCapacity + headerSize;<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>  /** An additional sanity-check in case no compression or encryption is being used. */<a name="line.689"></a>
-<span class="sourceLineNo">690</span>  @VisibleForTesting<a name="line.690"></a>
-<span class="sourceLineNo">691</span>  void sanityCheckUncompressedSize() throws IOException {<a name="line.691"></a>
-<span class="sourceLineNo">692</span>    if (onDiskSizeWithoutHeader != uncompressedSizeWithoutHeader + totalChecksumBytes()) {<a name="line.692"></a>
-<span class="sourceLineNo">693</span>      throw new IOException("Using no compression but "<a name="line.693"></a>
-<span class="sourceLineNo">694</span>          + "onDiskSizeWithoutHeader=" + onDiskSizeWithoutHeader + ", "<a name="line.694"></a>
-<span class="sourceLineNo">695</span>          + "uncompressedSizeWithoutHeader=" + uncompressedSizeWithoutHeader<a name="line.695"></a>
-<span class="sourceLineNo">696</span>          + ", numChecksumbytes=" + totalChecksumBytes());<a name="line.696"></a>
-<span class="sourceLineNo">697</span>    }<a name="line.697"></a>
-<span class="sourceLineNo">698</span>  }<a name="line.698"></a>
-<span class="sourceLineNo">699</span><a name="line.699"></a>
-<span class="sourceLineNo">700</span>  /**<a name="line.700"></a>
-<span class="sourceLineNo">701</span>   * Cannot be {@link #UNSET}. Must be a legitimate value. Used re-making the {@link BlockCacheKey} when<a name="line.701"></a>
-<span class="sourceLineNo">702</span>   * block is returned to the cache.<a name="line.702"></a>
-<span class="sourceLineNo">703</span>   * @return the offset of this block in the file it was read from<a name="line.703"></a>
-<span class="sourceLineNo">704</span>   */<a name="line.704"></a>
-<span class="sourceLineNo">705</span>  long getOffset() {<a name="line.705"></a>
-<span class="sourceLineNo">706</span>    if (offset &lt; 0) {<a name="line.706"></a>
-<span class="sourceLineNo">707</span>      throw new IllegalStateException("HFile block offset not initialized properly");<a name="line.707"></a>
-<span class="sourceLineNo">708</span>    }<a name="line.708"></a>
-<span class="sourceLineNo">709</span>    return offset;<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>   * @return a byte stream reading the data + checksum of this block<a name="line.713"></a>
-<span class="sourceLineNo">714</span>   */<a name="line.714"></a>
-<span class="sourceLineNo">715</span>  DataInputStream getByteStream() {<a name="line.715"></a>
-<span class="sourceLineNo">716</span>    ByteBuff dup = this.buf.duplicate();<a name="line.716"></a>
-<span class="sourceLineNo">717</span>    dup.position(this.headerSize());<a name="line.717"></a>
-<span class="sourceLineNo">718</span>    return new DataInputStream(new ByteBuffInputStream(dup));<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>
-<span class="sourceLineNo">721</span>  @Override<a name="line.721"></a>
-<span class="sourceLineNo">722</span>  public long heapSize() {<a name="line.722"></a>
-<span class="sourceLineNo">723</span>    long size = ClassSize.align(<a name="line.723"></a>
-<span class="sourceLineNo">724</span>        ClassSize.OBJECT +<a name="line.724"></a>
-<span class="sourceLineNo">725</span>        // Block type, multi byte buffer, MemoryType and meta references<a name="line.725"></a>
-<span class="sourceLineNo">726</span>        4 * ClassSize.REFERENCE +<a name="line.726"></a>
-<span class="sourceLineNo">727</span>        // On-disk size, uncompressed size, and next block's on-disk size<a name="line.727"></a>
-<span class="sourceLineNo">728</span>        // bytePerChecksum and onDiskDataSize<a name="line.728"></a>
-<span class="sourceLineNo">729</span>        4 * Bytes.SIZEOF_INT +<a name="line.729"></a>
-<span class="sourceLineNo">730</span>        // This and previous block offset<a name="line.730"></a>
-<span class="sourceLineNo">731</span>        2 * Bytes.SIZEOF_LONG +<a name="line.731"></a>
-<span class="sourceLineNo">732</span>        // Heap size of the meta object. meta will be always not null.<a name="line.732"></a>
-<span class="sourceLineNo">733</span>        fileContext.heapSize()<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>    if (buf != null) {<a name="line.736"></a>
-<span class="sourceLineNo">737</span>      // Deep overhead of the byte buffer. Needs to be aligned separately.<a name="line.737"></a>
-<span class="sourceLineNo">738</span>      size += ClassSize.align(buf.capacity() + MULTI_BYTE_BUFFER_HEAP_SIZE);<a name="line.738"></a>
-<span class="sourceLineNo">739</span>    }<a name="line.739"></a>
-<span class="sourceLineNo">740</span><a name="line.740"></a>
-<span class="sourceLineNo">741</span>    return ClassSize.align(size);<a name="line.741"></a>
-<span class="sourceLineNo">742</span>  }<a name="line.742"></a>
-<span class="sourceLineNo">743</span><a name="line.743"></a>
-<span class="sourceLineNo">744</span>  /**<a name="line.744"></a>
-<span class="sourceLineNo">745</span>   * Read from an input stream at least &lt;code&gt;necessaryLen&lt;/code&gt; and if possible,<a name="line.745"></a>
-<span class="sourceLineNo">746</span>   * &lt;code&gt;extraLen&lt;/code&gt; also if available. Analogous to<a name="line.746"></a>
-<span class="sourceLineNo">747</span>   * {@link IOUtils#readFully(InputStream, byte[], int, int)}, but specifies a<a name="line.747"></a>
-<span class="sourceLineNo">748</span>   * number of "extra" bytes to also optionally read.<a name="line.748"></a>
-<span class="sourceLineNo">749</span>   *<a name="line.749"></a>
-<span class="sourceLineNo">750</span>   * @param in the input stream to read from<a name="line.750"></a>
-<span class="sourceLineNo">751</span>   * @param buf the buffer to read into<a name="line.751"></a>
-<span class="sourceLineNo">752</span>   * @param bufOffset the destination offset in the buffer<a name="line.752"></a>
-<span class="sourceLineNo">753</span>   * @param necessaryLen the number of bytes that are absolutely necessary to read<a name="line.753"></a>
-<span class="sourceLineNo">754</span>   * @param extraLen the number of extra bytes that would be nice to read<a name="line.754"></a>
-<span class="sourceLineNo">755</span>   * @return true if succeeded reading the extra bytes<a name="line.755"></a>
-<span class="sourceLineNo">756</span>   * @throws IOException if failed to read the necessary bytes<a name="line.756"></a>
-<span class="sourceLineNo">757</span>   */<a name="line.757"></a>
-<span class="sourceLineNo">758</span>  static boolean readWithExtra(InputStream in, byte[] buf,<a name="line.758"></a>
-<span class="sourceLineNo">759</span>      int bufOffset, int necessaryLen, int extraLen) throws IOException {<a name="line.759"></a>
-<span class="sourceLineNo">760</span>    int bytesRemaining = necessaryLen + extraLen;<a name="line.760"></a>
-<span class="sourceLineNo">761</span>    while (bytesRemaining &gt; 0) {<a name="line.761"></a>
-<span class="sourceLineNo">762</span>      int ret = in.read(buf, bufOffset, bytesRemaining);<a name="line.762"></a>
-<span class="sourceLineNo">763</span>      if (ret == -1 &amp;&amp; bytesRemaining &lt;= extraLen) {<a name="line.763"></a>
-<span class="sourceLineNo">764</span>        // We could not read the "extra data", but that is OK.<a name="line.764"></a>
-<span class="sourceLineNo">765</span>        break;<a name="line.765"></a>
-<span class="sourceLineNo">766</span>      }<a name="line.766"></a>
-<span class="sourceLineNo">767</span>      if (ret &lt; 0) {<a name="line.767"></a>
-<span class="sourceLineNo">768</span>        throw new IOException("Premature EOF from inputStream (read "<a name="line.768"></a>
-<span class="sourceLineNo">769</span>            + "returned " + ret + ", was trying to read " + necessaryLen<a name="line.769"></a>
-<span class="sourceLineNo">770</span>            + " necessary bytes and " + extraLen + " extra bytes, "<a name="line.770"></a>
-<span class="sourceLineNo">771</span>            + "successfully read "<a name="line.771"></a>
-<span class="sourceLineNo">772</span>            + (necessaryLen + extraLen - bytesRemaining));<a name="line.772"></a>
-<span class="sourceLineNo">773</span>      }<a name="line.773"></a>
-<span class="sourceLineNo">774</span>      bufOffset += ret;<a name="line.774"></a>
-<span class="sourceLineNo">775</span>      bytesRemaining -= ret;<a name="line.775"></a>
-<span class="sourceLineNo">776</span>    }<a name="line.776"></a>
-<span class="sourceLineNo">777</span>    return bytesRemaining &lt;= 0;<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>   * Read from an input stream at least &lt;code&gt;necessaryLen&lt;/code&gt; and if possible,<a name="line.781"></a>
-<span class="sourceLineNo">782</span>   * &lt;code&gt;extraLen&lt;/code&gt; also if available. Analogous to<a name="line.782"></a>
-<span class="sourceLineNo">783</span>   * {@link IOUtils#readFully(InputStream, byte[], int, int)}, but uses<a name="line.783"></a>
-<span class="sourceLineNo">784</span>   * positional read and specifies a number of "extra" bytes that would be<a name="line.784"></a>
-<span class="sourceLineNo">785</span>   * desirable but not absolutely necessary to read.<a name="line.785"></a>
-<span class="sourceLineNo">786</span>   *<a name="line.786"></a>
-<span class="sourceLineNo">787</span>   * @param in the input stream to read from<a name="line.787"></a>
-<span class="sourceLineNo">788</span>   * @param position the position within the stream from which to start reading<a name="line.788"></a>
-<span class="sourceLineNo">789</span>   * @param buf the buffer to read into<a name="line.789"></a>
-<span class="sourceLineNo">790</span>   * @param bufOffset the destination offset in the buffer<a name="line.790"></a>
-<span class="sourceLineNo">791</span>   * @param necessaryLen the number of bytes that are absolutely necessary to<a name="line.791"></a>
-<span class="sourceLineNo">792</span>   *     read<a name="line.792"></a>
-<span class="sourceLineNo">793</span>   * @param extraLen the number of extra bytes that would be nice to read<a name="line.793"></a>
-<span class="sourceLineNo">794</span>   * @return true if and only if extraLen is &gt; 0 and reading those extra bytes<a name="line.794"></a>
-<span class="sourceLineNo">795</span>   *     was successful<a name="line.795"></a>
-<span class="sourceLineNo">796</span>   * @throws IOException if failed to read the necessary bytes<a name="line.796"></a>
-<span class="sourceLineNo">797</span>   */<a name="line.797"></a>
-<span class="sourceLineNo">798</span>  @VisibleForTesting<a name="line.798"></a>
-<span class="sourceLineNo">799</span>  static boolean positionalReadWithExtra(FSDataInputStream in,<a name="line.799"></a>
-<span class="sourceLineNo">800</span>      long position, byte[] buf, int bufOffset, int necessaryLen, int extraLen)<a name="line.800"></a>
-<span class="sourceLineNo">801</span>      throws IOException {<a name="line.801"></a>
-<span class="sourceLineNo">802</span>    int bytesRemaining = necessaryLen + extraLen;<a name="line.802"></a>
-<span class="sourceLineNo">803</span>    int bytesRead = 0;<a name="line.803"></a>
-<span class="sourceLineNo">804</span>    while (bytesRead &lt; necessaryLen) {<a name="line.804"></a>
-<span class="sourceLineNo">805</span>      int ret = in.read(position, buf, bufOffset, bytesRemaining);<a name="line.805"></a>
-<span class="sourceLineNo">806</span>      if (ret &lt; 0) {<a name="line.806"></a>
-<span class="sourceLineNo">807</span>        throw new IOException("Premature EOF from inputStream (positional read "<a name="line.807"></a>
-<span class="sourceLineNo">808</span>            + "returned " + ret + ", was trying to read " + necessaryLen<a name="line.808"></a>
-<span class="sourceLineNo">809</span>            + " necessary bytes and " + extraLen + " extra bytes, "<a name="line.809"></a>
-<span class="sourceLineNo">810</span>            + "successfully read " + bytesRead);<a name="line.810"></a>
-<span class="sourceLineNo">811</span>      }<a name="line.811"></a>
-<span class="sourceLineNo">812</span>      position += ret;<a name="line.812"></a>
-<span class="sourceLineNo">813</span>      bufOffset += ret;<a name="line.813"></a>
-<span class="sourceLineNo">814</span>      bytesRemaining -= ret;<a name="line.814"></a>
-<span class="sourceLineNo">815</span>      bytesRead += ret;<a name="line.815"></a>
-<span class="sourceLineNo">816</span>    }<a name="line.816"></a>
-<span class="sourceLineNo">817</span>    return bytesRead != necessaryLen &amp;&amp; bytesRemaining &lt;= 0;<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>   * Unified version 2 {@link HFile} block writer. The intended usage pattern<a name="line.821"></a>
-<span class="sourceLineNo">822</span>   * is as follows:<a name="line.822"></a>
-<span class="sourceLineNo">823</span>   * &lt;ol&gt;<a name="line.823"></a>
-<span class="sourceLineNo">824</span>   * &lt;li&gt;Construct an {@link HFileBlock.Writer}, providing a compression algorithm.<a name="line.824"></a>
-<span class="sourceLineNo">825</span>   * &lt;li&gt;Call {@link Writer#startWriting} and get a data stream to write to.<a name="line.825"></a>
-<span class="sourceLineNo">826</span>   * &lt;li&gt;Write your data into the stream.<a name="line.826"></a>
-<span class="sourceLineNo">827</span>   * &lt;li&gt;Call Writer#writeHeaderAndData(FSDataOutputStream) as many times as you need to.<a name="line.827"></a>
-<span class="sourceLineNo">828</span>   * store the serialized block into an external stream.<a name="line.828"></a>
-<span class="sourceLineNo">829</span>   * &lt;li&gt;Repeat to write more blocks.<a name="line.829"></a>
-<span class="sourceLineNo">830</span>   * &lt;/ol&gt;<a name="line.830"></a>
-<span class="sourceLineNo">831</span>   * &lt;p&gt;<a name="line.831"></a>
-<span class="sourceLineNo">832</span>   */<a name="line.832"></a>
-<span class="sourceLineNo">833</span>  static class Writer {<a name="line.833"></a>
-<span class="sourceLineNo">834</span>    private enum State {<a name="line.834"></a>
-<span class="sourceLineNo">835</span>      INIT,<a name="line.835"></a>
-<span class="sourceLineNo">836</span>      WRITING,<a name="line.836"></a>
-<span class="sourceLineNo">837</span>      BLOCK_READY<a name="line.837"></a>
-<span class="sourceLineNo">838</span>    }<a name="line.838"></a>
-<span class="sourceLineNo">839</span><a name="line.839"></a>
-<span class="sourceLineNo">840</span>    /** Writer state. Used to ensure the correct usage protocol. */<a name="line.840"></a>
-<span class="sourceLineNo">841</span>    private State state = State.INIT;<a name="line.841"></a>
-<span class="sourceLineNo">842</span><a name="line.842"></a>
-<span class="sourceLineNo">843</span>    /** Data block encoder used for data blocks */<a name="line.843"></a>
-<span class="sourceLineNo">844</span>    private final HFileDataBlockEncoder dataBlockEncoder;<a name="line.844"></a>
-<span class="sourceLineNo">845</span><a name="line.845"></a>
-<span class="sourceLineNo">846</span>    private HFileBlockEncodingContext dataBlockEncodingCtx;<a name="line.846"></a>
+<span class="sourceLineNo">328</span>   *<a name="line.328"></a>
+<span class="sourceLineNo">329</span>   * &lt;p&gt;TODO: The caller presumes no checksumming<a name="line.329"></a>
+<span class="sourceLineNo">330</span>   * required of this block instance since going into cache; checksum already verified on<a name="line.330"></a>
+<span class="sourceLineNo">331</span>   * underlying block data pulled in from filesystem. Is that correct? What if cache is SSD?<a name="line.331"></a>
+<span class="sourceLineNo">332</span>   *<a name="line.332"></a>
+<span class="sourceLineNo">333</span>   * @param blockType the type of this block, see {@link BlockType}<a name="line.333"></a>
+<span class="sourceLineNo">334</span>   * @param onDiskSizeWithoutHeader see {@link #onDiskSizeWithoutHeader}<a name="line.334"></a>
+<span class="sourceLineNo">335</span>   * @param uncompressedSizeWithoutHeader see {@link #uncompressedSizeWithoutHeader}<a name="line.335"></a>
+<span class="sourceLineNo">336</span>   * @param prevBlockOffset see {@link #prevBlockOffset}<a name="line.336"></a>
+<span class="sourceLineNo">337</span>   * @param b block header ({@link HConstants#HFILEBLOCK_HEADER_SIZE} bytes)<a name="line.337"></a>
+<span class="sourceLineNo">338</span>   * @param fillHeader when true, write the first 4 header fields into passed buffer.<a name="line.338"></a>
+<span class="sourceLineNo">339</span>   * @param offset the file offset the block was read from<a name="line.339"></a>
+<span class="sourceLineNo">340</span>   * @param onDiskDataSizeWithHeader see {@link #onDiskDataSizeWithHeader}<a name="line.340"></a>
+<span class="sourceLineNo">341</span>   * @param fileContext HFile meta data<a name="line.341"></a>
+<span class="sourceLineNo">342</span>   */<a name="line.342"></a>
+<span class="sourceLineNo">343</span>  @VisibleForTesting<a name="line.343"></a>
+<span class="sourceLineNo">344</span>  public HFileBlock(BlockType blockType, int onDiskSizeWithoutHeader,<a name="line.344"></a>
+<span class="sourceLineNo">345</span>      int uncompressedSizeWithoutHeader, long prevBlockOffset, ByteBuffer b, boolean fillHeader,<a name="line.345"></a>
+<span class="sourceLineNo">346</span>      long offset, final int nextBlockOnDiskSize, int onDiskDataSizeWithHeader,<a name="line.346"></a>
+<span class="sourceLineNo">347</span>      HFileContext fileContext) {<a name="line.347"></a>
+<span class="sourceLineNo">348</span>    init(blockType, onDiskSizeWithoutHeader, uncompressedSizeWithoutHeader,<a name="line.348"></a>
+<span class="sourceLineNo">349</span>        prevBlockOffset, offset, onDiskDataSizeWithHeader, nextBlockOnDiskSize, fileContext);<a name="line.349"></a>
+<span class="sourceLineNo">350</span>    this.buf = new SingleByteBuff(b);<a name="line.350"></a>
+<span class="sourceLineNo">351</span>    if (fillHeader) {<a name="line.351"></a>
+<span class="sourceLineNo">352</span>      overwriteHeader();<a name="line.352"></a>
+<span class="sourceLineNo">353</span>    }<a name="line.353"></a>
+<span class="sourceLineNo">354</span>    this.buf.rewind();<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">357</span>  /**<a name="line.357"></a>
+<span class="sourceLineNo">358</span>   * Creates a block from an existing buffer starting with a header. Rewinds<a name="line.358"></a>
+<span class="sourceLineNo">359</span>   * and takes ownership of the buffer. By definition of rewind, ignores the<a name="line.359"></a>
+<span class="sourceLineNo">360</span>   * buffer position, but if you slice the buffer beforehand, it will rewind<a name="line.360"></a>
+<span class="sourceLineNo">361</span>   * to that point.<a name="line.361"></a>
+<span class="sourceLineNo">362</span>   * @param buf Has header, content, and trailing checksums if present.<a name="line.362"></a>
+<span class="sourceLineNo">363</span>   */<a name="line.363"></a>
+<span class="sourceLineNo">364</span>  HFileBlock(ByteBuff buf, boolean usesHBaseChecksum, MemoryType memType, final long offset,<a name="line.364"></a>
+<span class="sourceLineNo">365</span>      final int nextBlockOnDiskSize, HFileContext fileContext) throws IOException {<a name="line.365"></a>
+<span class="sourceLineNo">366</span>    buf.rewind();<a name="line.366"></a>
+<span class="sourceLineNo">367</span>    final BlockType blockType = BlockType.read(buf);<a name="line.367"></a>
+<span class="sourceLineNo">368</span>    final int onDiskSizeWithoutHeader = buf.getInt(Header.ON_DISK_SIZE_WITHOUT_HEADER_INDEX);<a name="line.368"></a>
+<span class="sourceLineNo">369</span>    final int uncompressedSizeWithoutHeader =<a name="line.369"></a>
+<span class="sourceLineNo">370</span>        buf.getInt(Header.UNCOMPRESSED_SIZE_WITHOUT_HEADER_INDEX);<a name="line.370"></a>
+<span class="sourceLineNo">371</span>    final long prevBlockOffset = buf.getLong(Header.PREV_BLOCK_OFFSET_INDEX);<a name="line.371"></a>
+<span class="sourceLineNo">372</span>    // This constructor is called when we deserialize a block from cache and when we read a block in<a name="line.372"></a>
+<span class="sourceLineNo">373</span>    // from the fs. fileCache is null when deserialized from cache so need to make up one.<a name="line.373"></a>
+<span class="sourceLineNo">374</span>    HFileContextBuilder fileContextBuilder = fileContext != null?<a name="line.374"></a>
+<span class="sourceLineNo">375</span>        new HFileContextBuilder(fileContext): new HFileContextBuilder();<a name="line.375"></a>
+<span class="sourceLineNo">376</span>    fileContextBuilder.withHBaseCheckSum(usesHBaseChecksum);<a name="line.376"></a>
+<span class="sourceLineNo">377</span>    int onDiskDataSizeWithHeader;<a name="line.377"></a>
+<span class="sourceLineNo">378</span>    if (usesHBaseChecksum) {<a name="line.378"></a>
+<span class="sourceLineNo">379</span>      byte checksumType = buf.get(Header.CHECKSUM_TYPE_INDEX);<a name="line.379"></a>
+<span class="sourceLineNo">380</span>      int bytesPerChecksum = buf.getInt(Header.BYTES_PER_CHECKSUM_INDEX);<a name="line.380"></a>
+<span class="sourceLineNo">381</span>      onDiskDataSizeWithHeader = buf.getInt(Header.ON_DISK_DATA_SIZE_WITH_HEADER_INDEX);<a name="line.381"></a>
+<span class="sourceLineNo">382</span>      // Use the checksum type and bytes per checksum from header, not from filecontext.<a name="line.382"></a>
+<span class="sourceLineNo">383</span>      fileContextBuilder.withChecksumType(ChecksumType.codeToType(checksumType));<a name="line.383"></a>
+<span class="sourceLineNo">384</span>      fileContextBuilder.withBytesPerCheckSum(bytesPerChecksum);<a name="line.384"></a>
+<span class="sourceLineNo">385</span>    } else {<a name="line.385"></a>
+<span class="sourceLineNo">386</span>      fileContextBuilder.withChecksumType(ChecksumType.NULL);<a name="line.386"></a>
+<span class="sourceLineNo">387</span>      fileContextBuilder.withBytesPerCheckSum(0);<a name="line.387"></a>
+<span class="sourceLineNo">388</span>      // Need to fix onDiskDataSizeWithHeader; there are not checksums after-block-data<a name="line.388"></a>
+<span class="sourceLineNo">389</span>      onDiskDataSizeWithHeader = onDiskSizeWithoutHeader + headerSize(usesHBaseChecksum);<a name="line.389"></a>
+<span class="sourceLineNo">390</span>    }<a name="line.390"></a>
+<span class="sourceLineNo">391</span>    fileContext = fileContextBuilder.build();<a name="line.391"></a>
+<span class="sourceLineNo">392</span>    assert usesHBaseChecksum == fileContext.isUseHBaseChecksum();<a name="line.392"></a>
+<span class="sourceLineNo">393</span>    init(blockType, onDiskSizeWithoutHeader, uncompressedSizeWithoutHeader,<a name="line.393"></a>
+<span class="sourceLineNo">394</span>        prevBlockOffset, offset, onDiskDataSizeWithHeader, nextBlockOnDiskSize, fileContext);<a name="line.394"></a>
+<span class="sourceLineNo">395</span>    this.memType = memType;<a name="line.395"></a>
+<span class="sourceLineNo">396</span>    this.offset = offset;<a name="line.396"></a>
+<span class="sourceLineNo">397</span>    this.buf = buf;<a name="line.397"></a>
+<span class="sourceLineNo">398</span>    this.buf.rewind();<a name="line.398"></a>
+<span class="sourceLineNo">399</span>  }<a name="line.399"></a>
+<span class="sourceLineNo">400</span><a name="line.400"></a>
+<span class="sourceLineNo">401</span>  /**<a name="line.401"></a>
+<span class="sourceLineNo">402</span>   * Called from constructors.<a name="line.402"></a>
+<span class="sourceLineNo">403</span>   */<a name="line.403"></a>
+<span class="sourceLineNo">404</span>  private void init(BlockType blockType, int onDiskSizeWithoutHeader,<a name="line.404"></a>
+<span class="sourceLineNo">405</span>      int uncompressedSizeWithoutHeader, long prevBlockOffset,<a name="line.405"></a>
+<span class="sourceLineNo">406</span>      long offset, int onDiskDataSizeWithHeader, final int nextBlockOnDiskSize,<a name="line.406"></a>
+<span class="sourceLineNo">407</span>      HFileContext fileContext) {<a name="line.407"></a>
+<span class="sourceLineNo">408</span>    this.blockType = blockType;<a name="line.408"></a>
+<span class="sourceLineNo">409</span>    this.onDiskSizeWithoutHeader = onDiskSizeWithoutHeader;<a name="line.409"></a>
+<span class="sourceLineNo">410</span>    this.uncompressedSizeWithoutHeader = uncompressedSizeWithoutHeader;<a name="line.410"></a>
+<span class="sourceLineNo">411</span>    this.prevBlockOffset = prevBlockOffset;<a name="line.411"></a>
+<span class="sourceLineNo">412</span>    this.offset = offset;<a name="line.412"></a>
+<span class="sourceLineNo">413</span>    this.onDiskDataSizeWithHeader = onDiskDataSizeWithHeader;<a name="line.413"></a>
+<span class="sourceLineNo">414</span>    this.nextBlockOnDiskSize = nextBlockOnDiskSize;<a name="line.414"></a>
+<span class="sourceLineNo">415</span>    this.fileContext = fileContext;<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">418</span>  /**<a name="line.418"></a>
+<span class="sourceLineNo">419</span>   * Parse total on disk size including header and checksum.<a name="line.419"></a>
+<span class="sourceLineNo">420</span>   * @param headerBuf Header ByteBuffer. Presumed exact size of header.<a name="line.420"></a>
+<span class="sourceLineNo">421</span>   * @param verifyChecksum true if checksum verification is in use.<a name="line.421"></a>
+<span class="sourceLineNo">422</span>   * @return Size of the block with header included.<a name="line.422"></a>
+<span class="sourceLineNo">423</span>   */<a name="line.423"></a>
+<span class="sourceLineNo">424</span>  private static int getOnDiskSizeWithHeader(final ByteBuffer headerBuf,<a name="line.424"></a>
+<span class="sourceLineNo">425</span>      boolean verifyChecksum) {<a name="line.425"></a>
+<span class="sourceLineNo">426</span>    return headerBuf.getInt(Header.ON_DISK_SIZE_WITHOUT_HEADER_INDEX) +<a name="line.426"></a>
+<span class="sourceLineNo">427</span>      headerSize(verifyChecksum);<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>   * @return the on-disk size of the next block (including the header size and any checksums if<a name="line.431"></a>
+<span class="sourceLineNo">432</span>   * present) read by peeking into the next block's header; use as a hint when doing<a name="line.432"></a>
+<span class="sourceLineNo">433</span>   * a read of the next block when scanning or running over a file.<a name="line.433"></a>
+<span class="sourceLineNo">434</span>   */<a name="line.434"></a>
+<span class="sourceLineNo">435</span>  int getNextBlockOnDiskSize() {<a name="line.435"></a>
+<span class="sourceLineNo">436</span>    return nextBlockOnDiskSize;<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>  @Override<a name="line.439"></a>
+<span class="sourceLineNo">440</span>  public BlockType getBlockType() {<a name="line.440"></a>
+<span class="sourceLineNo">441</span>    return blockType;<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>  /** @return get data block encoding id that was used to encode this block */<a name="line.444"></a>
+<span class="sourceLineNo">445</span>  short getDataBlockEncodingId() {<a name="line.445"></a>
+<span class="sourceLineNo">446</span>    if (blockType != BlockType.ENCODED_DATA) {<a name="line.446"></a>
+<span class="sourceLineNo">447</span>      throw new IllegalArgumentException("Querying encoder ID of a block " +<a name="line.447"></a>
+<span class="sourceLineNo">448</span>          "of type other than " + BlockType.ENCODED_DATA + ": " + blockType);<a name="line.448"></a>
+<span class="sourceLineNo">449</span>    }<a name="line.449"></a>
+<span class="sourceLineNo">450</span>    return buf.getShort(headerSize());<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>   * @return the on-disk size of header + data part + checksum.<a name="line.454"></a>
+<span class="sourceLineNo">455</span>   */<a name="line.455"></a>
+<span class="sourceLineNo">456</span>  public int getOnDiskSizeWithHeader() {<a name="line.456"></a>
+<span class="sourceLineNo">457</span>    return onDiskSizeWithoutHeader + headerSize();<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>   * @return the on-disk size of the data part + checksum (header excluded).<a name="line.461"></a>
+<span class="sourceLineNo">462</span>   */<a name="line.462"></a>
+<span class="sourceLineNo">463</span>  int getOnDiskSizeWithoutHeader() {<a name="line.463"></a>
+<span class="sourceLineNo">464</span>    return onDiskSizeWithoutHeader;<a name="line.464"></a>
+<span class="sourceLineNo">465</span>  }<a name="line.465"></a>
+<span class="sourceLineNo">466</span><a name="line.466"></a>
+<span class="sourceLineNo">467</span>  /**<a name="line.467"></a>
+<span class="sourceLineNo">468</span>   * @return the uncompressed size of data part (header and checksum excluded).<a name="line.468"></a>
+<span class="sourceLineNo">469</span>   */<a name="line.469"></a>
+<span class="sourceLineNo">470</span>   int getUncompressedSizeWithoutHeader() {<a name="line.470"></a>
+<span class="sourceLineNo">471</span>    return uncompressedSizeWithoutHeader;<a name="line.471"></a>
+<span class="sourceLineNo">472</span>  }<a name="line.472"></a>
+<span class="sourceLineNo">473</span><a name="line.473"></a>
+<span class="sourceLineNo">474</span>  /**<a name="line.474"></a>
+<span class="sourceLineNo">475</span>   * @return the offset of the previous block of the same type in the file, or<a name="line.475"></a>
+<span class="sourceLineNo">476</span>   *         -1 if unknown<a name="line.476"></a>
+<span class="sourceLineNo">477</span>   */<a name="line.477"></a>
+<span class="sourceLineNo">478</span>  long getPrevBlockOffset() {<a name="line.478"></a>
+<span class="sourceLineNo">479</span>    return prevBlockOffset;<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>   * Rewinds {@code buf} and writes first 4 header fields. {@code buf} position<a name="line.483"></a>
+<span class="sourceLineNo">484</span>   * is modified as side-effect.<a name="line.484"></a>
+<span class="sourceLineNo">485</span>   */<a name="line.485"></a>
+<span class="sourceLineNo">486</span>  private void overwriteHeader() {<a name="line.486"></a>
+<span class="sourceLineNo">487</span>    buf.rewind();<a name="line.487"></a>
+<span class="sourceLineNo">488</span>    blockType.write(buf);<a name="line.488"></a>
+<span class="sourceLineNo">489</span>    buf.putInt(onDiskSizeWithoutHeader);<a name="line.489"></a>
+<span class="sourceLineNo">490</span>    buf.putInt(uncompressedSizeWithoutHeader);<a name="line.490"></a>
+<span class="sourceLineNo">491</span>    buf.putLong(prevBlockOffset);<a name="line.491"></a>
+<span class="sourceLineNo">492</span>    if (this.fileContext.isUseHBaseChecksum()) {<a name="line.492"></a>
+<span class="sourceLineNo">493</span>      buf.put(fileContext.getChecksumType().getCode());<a name="line.493"></a>
+<span class="sourceLineNo">494</span>      buf.putInt(fileContext.getBytesPerChecksum());<a name="line.494"></a>
+<span class="sourceLineNo">495</span>      buf.putInt(onDiskDataSizeWithHeader);<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><a name="line.498"></a>
+<span class="sourceLineNo">499</span>  /**<a name="line.499"></a>
+<span class="sourceLineNo">500</span>   * Returns a buffer that does not include the header or checksum.<a name="line.500"></a>
+<span class="sourceLineNo">501</span>   *<a name="line.501"></a>
+<span class="sourceLineNo">502</span>   * @return the buffer with header skipped and checksum omitted.<a name="line.502"></a>
+<span class="sourceLineNo">503</span>   */<a name="line.503"></a>
+<span class="sourceLineNo">504</span>  public ByteBuff getBufferWithoutHeader() {<a name="line.504"></a>
+<span class="sourceLineNo">505</span>    ByteBuff dup = getBufferReadOnly();<a name="line.505"></a>
+<span class="sourceLineNo">506</span>    // Now set it up so Buffer spans content only -- no header or no checksums.<a name="line.506"></a>
+<span class="sourceLineNo">507</span>    return dup.position(headerSize()).limit(buf.limit() - totalChecksumBytes()).slice();<a name="line.507"></a>
+<span class="sourceLineNo">508</span>  }<a name="line.508"></a>
+<span class="sourceLineNo">509</span><a name="line.509"></a>
+<span class="sourceLineNo">510</span>  /**<a name="line.510"></a>
+<span class="sourceLineNo">511</span>   * Returns a read-only duplicate of the buffer this block stores internally ready to be read.<a name="line.511"></a>
+<span class="sourceLineNo">512</span>   * Clients must not modify the buffer object though they may set position and limit on the<a name="line.512"></a>
+<span class="sourceLineNo">513</span>   * returned buffer since we pass back a duplicate. This method has to be public because it is used<a name="line.513"></a>
+<span class="sourceLineNo">514</span>   * in {@link CompoundBloomFilter} to avoid object creation on every Bloom<a name="line.514"></a>
+<span class="sourceLineNo">515</span>   * filter lookup, but has to be used with caution. Buffer holds header, block content,<a name="line.515"></a>
+<span class="sourceLineNo">516</span>   * and any follow-on checksums if present.<a name="line.516"></a>
+<span class="sourceLineNo">517</span>   *<a name="line.517"></a>
+<span class="sourceLineNo">518</span>   * @return the buffer of this block for read-only operations<a name="line.518"></a>
+<span class="sourceLineNo">519</span>   */<a name="line.519"></a>
+<span class="sourceLineNo">520</span>  public ByteBuff getBufferReadOnly() {<a name="line.520"></a>
+<span class="sourceLineNo">521</span>    // TODO: ByteBuf does not support asReadOnlyBuffer(). Fix.<a name="line.521"></a>
+<span class="sourceLineNo">522</span>    ByteBuff dup = this.buf.duplicate();<a name="line.522"></a>
+<span class="sourceLineNo">523</span>    assert dup.position() == 0;<a name="line.523"></a>
+<span class="sourceLineNo">524</span>    return dup;<a name="line.524"></a>
+<span class="sourceLineNo">525</span>  }<a name="line.525"></a>
+<span class="sourceLineNo">526</span><a name="line.526"></a>
+<span class="sourceLineNo">527</span>  @VisibleForTesting<a name="line.527"></a>
+<span class="sourceLineNo">528</span>  private void sanityCheckAssertion(long valueFromBuf, long valueFromField,<a name="line.528"></a>
+<span class="sourceLineNo">529</span>      String fieldName) throws IOException {<a name="line.529"></a>
+<span class="sourceLineNo">530</span>    if (valueFromBuf != valueFromField) {<a name="line.530"></a>
+<span class="sourceLineNo">531</span>      throw new AssertionError(fieldName + " in the buffer (" + valueFromBuf<a name="line.531"></a>
+<span class="sourceLineNo">532</span>          + ") is different from that in the field (" + valueFromField + ")");<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>  @VisibleForTesting<a name="line.536"></a>
+<span class="sourceLineNo">537</span>  private void sanityCheckAssertion(BlockType valueFromBuf, BlockType valueFromField)<a name="line.537"></a>
+<span class="sourceLineNo">538</span>      throws IOException {<a name="line.538"></a>
+<span class="sourceLineNo">539</span>    if (valueFromBuf != valueFromField) {<a name="line.539"></a>
+<span class="sourceLineNo">540</span>      throw new IOException("Block type stored in the buffer: " +<a name="line.540"></a>
+<span class="sourceLineNo">541</span>        valueFromBuf + ", block type field: " + valueFromField);<a name="line.541"></a>
+<span class="sourceLineNo">542</span>    }<a name="line.542"></a>
+<span class="sourceLineNo">543</span>  }<a name="line.543"></a>
+<span class="sourceLineNo">544</span><a name="line.544"></a>
+<span class="sourceLineNo">545</span>  /**<a name="line.545"></a>
+<span class="sourceLineNo">546</span>   * Checks if the block is internally consistent, i.e. the first<a name="line.546"></a>
+<span class="sourceLineNo">547</span>   * {@link HConstants#HFILEBLOCK_HEADER_SIZE} bytes of the buffer contain a<a name="line.547"></a>
+<span class="sourceLineNo">548</span>   * valid header consistent with the fields. Assumes a packed block structure.<a name="line.548"></a>
+<span class="sourceLineNo">549</span>   * This function is primary for testing and debugging, and is not<a name="line.549"></a>
+<span class="sourceLineNo">550</span>   * thread-safe, because it alters the internal buffer pointer.<a name="line.550"></a>
+<span class="sourceLineNo">551</span>   * Used by tests only.<a name="line.551"></a>
+<span class="sourceLineNo">552</span>   */<a name="line.552"></a>
+<span class="sourceLineNo">553</span>  @VisibleForTesting<a name="line.553"></a>
+<span class="sourceLineNo">554</span>  void sanityCheck() throws IOException {<a name="line.554"></a>
+<span class="sourceLineNo">555</span>    // Duplicate so no side-effects<a name="line.555"></a>
+<span class="sourceLineNo">556</span>    ByteBuff dup = this.buf.duplicate().rewind();<a name="line.556"></a>
+<span class="sourceLineNo">557</span>    sanityCheckAssertion(BlockType.read(dup), blockType);<a name="line.557"></a>
+<span class="sourceLineNo">558</span><a name="line.558"></a>
+<span class="sourceLineNo">559</span>    sanityCheckAssertion(dup.getInt(), onDiskSizeWithoutHeader, "onDiskSizeWithoutHeader");<a name="line.559"></a>
+<span class="sourceLineNo">560</span><a name="line.560"></a>
+<span class="sourceLineNo">561</span>    sanityCheckAssertion(dup.getInt(), uncompressedSizeWithoutHeader,<a name="line.561"></a>
+<span class="sourceLineNo">562</span>        "uncompressedSizeWithoutHeader");<a name="line.562"></a>
+<span class="sourceLineNo">563</span><a name="line.563"></a>
+<span class="sourceLineNo">564</span>    sanityCheckAssertion(dup.getLong(), prevBlockOffset, "prevBlockOffset");<a name="line.564"></a>
+<span class="sourceLineNo">565</span>    if (this.fileContext.isUseHBaseChecksum()) {<a name="line.565"></a>
+<span class="sourceLineNo">566</span>      sanityCheckAssertion(dup.get(), this.fileContext.getChecksumType().getCode(), "checksumType");<a name="line.566"></a>
+<span class="sourceLineNo">567</span>      sanityCheckAssertion(dup.getInt(), this.fileContext.getBytesPerChecksum(),<a name="line.567"></a>
+<span class="sourceLineNo">568</span>          "bytesPerChecksum");<a name="line.568"></a>
+<span class="sourceLineNo">569</span>      sanityCheckAssertion(dup.getInt(), onDiskDataSizeWithHeader, "onDiskDataSizeWithHeader");<a name="line.569"></a>
+<span class="sourceLineNo">570</span>    }<a name="line.570"></a>
+<span class="sourceLineNo">571</span><a name="line.571"></a>
+<span class="sourceLineNo">572</span>    int cksumBytes = totalChecksumBytes();<a name="line.572"></a>
+<span class="sourceLineNo">573</span>    int expectedBufLimit = onDiskDataSizeWithHeader + cksumBytes;<a name="line.573"></a>
+<span class="sourceLineNo">574</span>    if (dup.limit() != expectedBufLimit) {<a name="line.574"></a>
+<span class="sourceLineNo">575</span>      throw new AssertionError("Expected limit " + expectedBufLimit + ", got " + dup.limit());<a name="line.575"></a>
+<span class="sourceLineNo">576</span>    }<a name="line.576"></a>
+<span class="sourceLineNo">577</span><a name="line.577"></a>
+<span class="sourceLineNo">578</span>    // We might optionally allocate HFILEBLOCK_HEADER_SIZE more bytes to read the next<a name="line.578"></a>
+<span class="sourceLineNo">579</span>    // block's header, so there are two sensible values for buffer capacity.<a name="line.579"></a>
+<span class="sourceLineNo">580</span>    int hdrSize = headerSize();<a name="line.580"></a>
+<span class="sourceLineNo">581</span>    if (dup.capacity() != expectedBufLimit &amp;&amp; dup.capacity() != expectedBufLimit + hdrSize) {<a name="line.581"></a>
+<span class="sourceLineNo">582</span>      throw new AssertionError("Invalid buffer capacity: " + dup.capacity() +<a name="line.582"></a>
+<span class="sourceLineNo">583</span>          ", expected " + expectedBufLimit + " or " + (expectedBufLimit + hdrSize));<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>  @Override<a name="line.587"></a>
+<span class="sourceLineNo">588</span>  public String toString() {<a name="line.588"></a>
+<span class="sourceLineNo">589</span>    StringBuilder sb = new StringBuilder()<a name="line.589"></a>
+<span class="sourceLineNo">590</span>      .append("[")<a name="line.590"></a>
+<span class="sourceLineNo">591</span>      .append("blockType=").append(blockType)<a name="line.591"></a>
+<span class="sourceLineNo">592</span>      .append(", fileOffset=").append(offset)<a name="line.592"></a>
+<span class="sourceLineNo">593</span>      .append(", headerSize=").append(headerSize())<a name="line.593"></a>
+<span class="sourceLineNo">594</span>      .append(", onDiskSizeWithoutHeader=").append(onDiskSizeWithoutHeader)<a name="line.594"></a>
+<span class="sourceLineNo">595</span>      .append(", uncompressedSizeWithoutHeader=").append(uncompressedSizeWithoutHeader)<a name="line.595"></a>
+<span class="sourceLineNo">596</span>      .append(", prevBlockOffset=").append(prevBlockOffset)<a name="line.596"></a>
+<span class="sourceLineNo">597</span>      .append(", isUseHBaseChecksum=").append(fileContext.isUseHBaseChecksum());<a name="line.597"></a>
+<span class="sourceLineNo">598</span>    if (fileContext.isUseHBaseChecksum()) {<a name="line.598"></a>
+<span class="sourceLineNo">599</span>      sb.append(", checksumType=").append(ChecksumType.codeToType(this.buf.get(24)))<a name="line.599"></a>
+<span class="sourceLineNo">600</span>        .append(", bytesPerChecksum=").append(this.buf.getInt(24 + 1))<a name="line.600"></a>
+<span class="sourceLineNo">601</span>        .append(", onDiskDataSizeWithHeader=").append(onDiskDataSizeWithHeader);<a name="line.601"></a>
+<span class="sourceLineNo">602</span>    } else {<a name="line.602"></a>
+<span class="sourceLineNo">603</span>      sb.append(", onDiskDataSizeWithHeader=").append(onDiskDataSizeWithHeader)<a name="line.603"></a>
+<span class="sourceLineNo">604</span>        .append("(").append(onDiskSizeWithoutHeader)<a name="line.604"></a>
+<span class="sourceLineNo">605</span>        .append("+").append(HConstants.HFILEBLOCK_HEADER_SIZE_NO_CHECKSUM).append(")");<a name="line.605"></a>
+<span class="sourceLineNo">606</span>    }<a name="line.606"></a>
+<span class="sourceLineNo">607</span>    String dataBegin = null;<a name="line.607"></a>
+<span class="sourceLineNo">608</span>    if (buf.hasArray()) {<a name="line.608"></a>
+<span class="sourceLineNo">609</span>      dataBegin = Bytes.toStringBinary(buf.array(), buf.arrayOffset() + headerSize(),<a name="line.609"></a>
+<span class="sourceLineNo">610</span>          Math.min(32, buf.limit() - buf.arrayOffset() - headerSize()));<a name="line.610"></a>
+<span class="sourceLineNo">611</span>    } else {<a name="line.611"></a>
+<span class="sourceLineNo">612</span>      ByteBuff bufWithoutHeader = getBufferWithoutHeader();<a name="line.612"></a>
+<span class="sourceLineNo">613</span>      byte[] dataBeginBytes = new byte[Math.min(32,<a name="line.613"></a>
+<span class="sourceLineNo">614</span>          bufWithoutHeader.limit() - bufWithoutHeader.position())];<a name="line.614"></a>
+<span class="sourceLineNo">615</span>      bufWithoutHeader.get(dataBeginBytes);<a name="line.615"></a>
+<span class="sourceLineNo">616</span>      dataBegin = Bytes.toStringBinary(dataBeginBytes);<a name="line.616"></a>
+<span class="sourceLineNo">617</span>    }<a name="line.617"></a>
+<span class="sourceLineNo">618</span>    sb.append(", getOnDiskSizeWithHeader=").append(getOnDiskSizeWithHeader())<a name="line.618"></a>
+<span class="sourceLineNo">619</span>      .append(", totalChecksumBytes=").append(totalChecksumBytes())<a name="line.619"></a>
+<span class="sourceLineNo">620</span>      .append(", isUnpacked=").append(isUnpacked())<a name="line.620"></a>
+<span class="sourceLineNo">621</span>      .append(", buf=[").append(buf).append("]")<a name="line.621"></a>
+<span class="sourceLineNo">622</span>      .append(", dataBeginsWith=").append(dataBegin)<a name="line.622"></a>
+<span class="sourceLineNo">623</span>      .append(", fileContext=").append(fileContext)<a name="line.623"></a>
+<span class="sourceLineNo">624</span>      .append(", nextBlockOnDiskSize=").append(nextBlockOnDiskSize)<a name="line.624"></a>
+<span class="sourceLineNo">625</span>      .append("]");<a name="line.625"></a>
+<span class="sourceLineNo">626</span>    return sb.toString();<a name="line.626"></a>
+<span class="sourceLineNo">627</span>  }<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>   * Retrieves the decompressed/decrypted view of this block. An encoded block remains in its<a name="line.630"></a>
+<span class="sourceLineNo">631</span>   * encoded structure. Internal structures are shared between instances where applicable.<a name="line.631"></a>
+<span class="sourceLineNo">632</span>   */<a name="line.632"></a>
+<span class="sourceLineNo">633</span>  HFileBlock unpack(HFileContext fileContext, FSReader reader) throws IOException {<a name="line.633"></a>
+<span class="sourceLineNo">634</span>    if (!fileContext.isCompressedOrEncrypted()) {<a name="line.634"></a>
+<span class="sourceLineNo">635</span>      // TODO: cannot use our own fileContext here because HFileBlock(ByteBuffer, boolean),<a name="line.635"></a>
+<span class="sourceLineNo">636</span>      // which is used for block serialization to L2 cache, does not preserve encoding and<a name="line.636"></a>
+<span class="sourceLineNo">637</span>      // encryption details.<a name="line.637"></a>
+<span class="sourceLineNo">638</span>      return this;<a name="line.638"></a>
+<span class="sourceLineNo">639</span>    }<a name="line.639"></a>
+<span class="sourceLineNo">640</span><a name="line.640"></a>
+<span class="sourceLineNo">641</span>    HFileBlock unpacked = new HFileBlock(this);<a name="line.641"></a>
+<span class="sourceLineNo">642</span>    unpacked.allocateBuffer(); // allocates space for the decompressed block<a name="line.642"></a>
+<span class="sourceLineNo">643</span><a name="line.643"></a>
+<span class="sourceLineNo">644</span>    HFileBlockDecodingContext ctx = blockType == BlockType.ENCODED_DATA ?<a name="line.644"></a>
+<span class="sourceLineNo">645</span>      reader.getBlockDecodingContext() : reader.getDefaultBlockDecodingContext();<a name="line.645"></a>
+<span class="sourceLineNo">646</span><a name="line.646"></a>
+<span class="sourceLineNo">647</span>    ByteBuff dup = this.buf.duplicate();<a name="line.647"></a>
+<span class="sourceLineNo">648</span>    dup.position(this.headerSize());<a name="line.648"></a>
+<span class="sourceLineNo">649</span>    dup = dup.slice();<a name="line.649"></a>
+<span class="sourceLineNo">650</span>    ctx.prepareDecoding(unpacked.getOnDiskSizeWitho

<TRUNCATED>

[36/50] hbase-site git commit: Published site at 26babcf013de696b899d76a3c39434b794440d8d.

Posted by gi...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html
----------------------------------------------------------------------
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html
index 97ceefd..b7b4236 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.FSReaderImpl.html
@@ -103,8 +103,8 @@
 <span class="sourceLineNo">095</span> * Caches cache whole blocks with trailing checksums if any. We then tag on some metadata, the<a name="line.95"></a>
 <span class="sourceLineNo">096</span> * content of BLOCK_METADATA_SPACE which will be flag on if we are doing 'hbase'<a name="line.96"></a>
 <span class="sourceLineNo">097</span> * checksums and then the offset into the file which is needed when we re-make a cache key<a name="line.97"></a>
-<span class="sourceLineNo">098</span> * when we return the block to the cache as 'done'. See {@link Cacheable#serialize(ByteBuffer)} and<a name="line.98"></a>
-<span class="sourceLineNo">099</span> * {@link Cacheable#getDeserializer()}.<a name="line.99"></a>
+<span class="sourceLineNo">098</span> * when we return the block to the cache as 'done'.<a name="line.98"></a>
+<span class="sourceLineNo">099</span> * See {@link Cacheable#serialize(ByteBuffer, boolean)} and {@link Cacheable#getDeserializer()}.<a name="line.99"></a>
 <span class="sourceLineNo">100</span> *<a name="line.100"></a>
 <span class="sourceLineNo">101</span> * &lt;p&gt;TODO: Should we cache the checksums? Down in Writer#getBlockForCaching(CacheConfig) where<a name="line.101"></a>
 <span class="sourceLineNo">102</span> * we make a block to cache-on-write, there is an attempt at turning off checksums. This is not the<a name="line.102"></a>
@@ -333,1579 +333,1579 @@
 <span class="sourceLineNo">325</span>   * Creates a new {@link HFile} block from the given fields. This constructor<a name="line.325"></a>
 <span class="sourceLineNo">326</span>   * is used only while writing blocks and caching,<a name="line.326"></a>
 <span class="sourceLineNo">327</span>   * and is sitting in a byte buffer and we want to stuff the block into cache.<a name="line.327"></a>
-<span class="sourceLineNo">328</span>   * See {@link Writer#getBlockForCaching(CacheConfig)}.<a name="line.328"></a>
-<span class="sourceLineNo">329</span>   *<a name="line.329"></a>
-<span class="sourceLineNo">330</span>   * &lt;p&gt;TODO: The caller presumes no checksumming<a name="line.330"></a>
-<span class="sourceLineNo">331</span>   * required of this block instance since going into cache; checksum already verified on<a name="line.331"></a>
-<span class="sourceLineNo">332</span>   * underlying block data pulled in from filesystem. Is that correct? What if cache is SSD?<a name="line.332"></a>
-<span class="sourceLineNo">333</span>   *<a name="line.333"></a>
-<span class="sourceLineNo">334</span>   * @param blockType the type of this block, see {@link BlockType}<a name="line.334"></a>
-<span class="sourceLineNo">335</span>   * @param onDiskSizeWithoutHeader see {@link #onDiskSizeWithoutHeader}<a name="line.335"></a>
-<span class="sourceLineNo">336</span>   * @param uncompressedSizeWithoutHeader see {@link #uncompressedSizeWithoutHeader}<a name="line.336"></a>
-<span class="sourceLineNo">337</span>   * @param prevBlockOffset see {@link #prevBlockOffset}<a name="line.337"></a>
-<span class="sourceLineNo">338</span>   * @param b block header ({@link HConstants#HFILEBLOCK_HEADER_SIZE} bytes)<a name="line.338"></a>
-<span class="sourceLineNo">339</span>   * @param fillHeader when true, write the first 4 header fields into passed buffer.<a name="line.339"></a>
-<span class="sourceLineNo">340</span>   * @param offset the file offset the block was read from<a name="line.340"></a>
-<span class="sourceLineNo">341</span>   * @param onDiskDataSizeWithHeader see {@link #onDiskDataSizeWithHeader}<a name="line.341"></a>
-<span class="sourceLineNo">342</span>   * @param fileContext HFile meta data<a name="line.342"></a>
-<span class="sourceLineNo">343</span>   */<a name="line.343"></a>
-<span class="sourceLineNo">344</span>  HFileBlock(BlockType blockType, int onDiskSizeWithoutHeader, int uncompressedSizeWithoutHeader,<a name="line.344"></a>
-<span class="sourceLineNo">345</span>      long prevBlockOffset, ByteBuffer b, boolean fillHeader, long offset,<a name="line.345"></a>
-<span class="sourceLineNo">346</span>      final int nextBlockOnDiskSize, int onDiskDataSizeWithHeader, HFileContext fileContext) {<a name="line.346"></a>
-<span class="sourceLineNo">347</span>    init(blockType, onDiskSizeWithoutHeader, uncompressedSizeWithoutHeader,<a name="line.347"></a>
-<span class="sourceLineNo">348</span>        prevBlockOffset, offset, onDiskDataSizeWithHeader, nextBlockOnDiskSize, fileContext);<a name="line.348"></a>
-<span class="sourceLineNo">349</span>    this.buf = new SingleByteBuff(b);<a name="line.349"></a>
-<span class="sourceLineNo">350</span>    if (fillHeader) {<a name="line.350"></a>
-<span class="sourceLineNo">351</span>      overwriteHeader();<a name="line.351"></a>
-<span class="sourceLineNo">352</span>    }<a name="line.352"></a>
-<span class="sourceLineNo">353</span>    this.buf.rewind();<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>  /**<a name="line.356"></a>
-<span class="sourceLineNo">357</span>   * Creates a block from an existing buffer starting with a header. Rewinds<a name="line.357"></a>
-<span class="sourceLineNo">358</span>   * and takes ownership of the buffer. By definition of rewind, ignores the<a name="line.358"></a>
-<span class="sourceLineNo">359</span>   * buffer position, but if you slice the buffer beforehand, it will rewind<a name="line.359"></a>
-<span class="sourceLineNo">360</span>   * to that point.<a name="line.360"></a>
-<span class="sourceLineNo">361</span>   * @param buf Has header, content, and trailing checksums if present.<a name="line.361"></a>
-<span class="sourceLineNo">362</span>   */<a name="line.362"></a>
-<span class="sourceLineNo">363</span>  HFileBlock(ByteBuff buf, boolean usesHBaseChecksum, MemoryType memType, final long offset,<a name="line.363"></a>
-<span class="sourceLineNo">364</span>      final int nextBlockOnDiskSize, HFileContext fileContext) throws IOException {<a name="line.364"></a>
-<span class="sourceLineNo">365</span>    buf.rewind();<a name="line.365"></a>
-<span class="sourceLineNo">366</span>    final BlockType blockType = BlockType.read(buf);<a name="line.366"></a>
-<span class="sourceLineNo">367</span>    final int onDiskSizeWithoutHeader = buf.getInt(Header.ON_DISK_SIZE_WITHOUT_HEADER_INDEX);<a name="line.367"></a>
-<span class="sourceLineNo">368</span>    final int uncompressedSizeWithoutHeader =<a name="line.368"></a>
-<span class="sourceLineNo">369</span>        buf.getInt(Header.UNCOMPRESSED_SIZE_WITHOUT_HEADER_INDEX);<a name="line.369"></a>
-<span class="sourceLineNo">370</span>    final long prevBlockOffset = buf.getLong(Header.PREV_BLOCK_OFFSET_INDEX);<a name="line.370"></a>
-<span class="sourceLineNo">371</span>    // This constructor is called when we deserialize a block from cache and when we read a block in<a name="line.371"></a>
-<span class="sourceLineNo">372</span>    // from the fs. fileCache is null when deserialized from cache so need to make up one.<a name="line.372"></a>
-<span class="sourceLineNo">373</span>    HFileContextBuilder fileContextBuilder = fileContext != null?<a name="line.373"></a>
-<span class="sourceLineNo">374</span>        new HFileContextBuilder(fileContext): new HFileContextBuilder();<a name="line.374"></a>
-<span class="sourceLineNo">375</span>    fileContextBuilder.withHBaseCheckSum(usesHBaseChecksum);<a name="line.375"></a>
-<span class="sourceLineNo">376</span>    int onDiskDataSizeWithHeader;<a name="line.376"></a>
-<span class="sourceLineNo">377</span>    if (usesHBaseChecksum) {<a name="line.377"></a>
-<span class="sourceLineNo">378</span>      byte checksumType = buf.get(Header.CHECKSUM_TYPE_INDEX);<a name="line.378"></a>
-<span class="sourceLineNo">379</span>      int bytesPerChecksum = buf.getInt(Header.BYTES_PER_CHECKSUM_INDEX);<a name="line.379"></a>
-<span class="sourceLineNo">380</span>      onDiskDataSizeWithHeader = buf.getInt(Header.ON_DISK_DATA_SIZE_WITH_HEADER_INDEX);<a name="line.380"></a>
-<span class="sourceLineNo">381</span>      // Use the checksum type and bytes per checksum from header, not from filecontext.<a name="line.381"></a>
-<span class="sourceLineNo">382</span>      fileContextBuilder.withChecksumType(ChecksumType.codeToType(checksumType));<a name="line.382"></a>
-<span class="sourceLineNo">383</span>      fileContextBuilder.withBytesPerCheckSum(bytesPerChecksum);<a name="line.383"></a>
-<span class="sourceLineNo">384</span>    } else {<a name="line.384"></a>
-<span class="sourceLineNo">385</span>      fileContextBuilder.withChecksumType(ChecksumType.NULL);<a name="line.385"></a>
-<span class="sourceLineNo">386</span>      fileContextBuilder.withBytesPerCheckSum(0);<a name="line.386"></a>
-<span class="sourceLineNo">387</span>      // Need to fix onDiskDataSizeWithHeader; there are not checksums after-block-data<a name="line.387"></a>
-<span class="sourceLineNo">388</span>      onDiskDataSizeWithHeader = onDiskSizeWithoutHeader + headerSize(usesHBaseChecksum);<a name="line.388"></a>
-<span class="sourceLineNo">389</span>    }<a name="line.389"></a>
-<span class="sourceLineNo">390</span>    fileContext = fileContextBuilder.build();<a name="line.390"></a>
-<span class="sourceLineNo">391</span>    assert usesHBaseChecksum == fileContext.isUseHBaseChecksum();<a name="line.391"></a>
-<span class="sourceLineNo">392</span>    init(blockType, onDiskSizeWithoutHeader, uncompressedSizeWithoutHeader,<a name="line.392"></a>
-<span class="sourceLineNo">393</span>        prevBlockOffset, offset, onDiskDataSizeWithHeader, nextBlockOnDiskSize, fileContext);<a name="line.393"></a>
-<span class="sourceLineNo">394</span>    this.memType = memType;<a name="line.394"></a>
-<span class="sourceLineNo">395</span>    this.offset = offset;<a name="line.395"></a>
-<span class="sourceLineNo">396</span>    this.buf = buf;<a name="line.396"></a>
-<span class="sourceLineNo">397</span>    this.buf.rewind();<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>  /**<a name="line.400"></a>
-<span class="sourceLineNo">401</span>   * Called from constructors.<a name="line.401"></a>
-<span class="sourceLineNo">402</span>   */<a name="line.402"></a>
-<span class="sourceLineNo">403</span>  private void init(BlockType blockType, int onDiskSizeWithoutHeader,<a name="line.403"></a>
-<span class="sourceLineNo">404</span>      int uncompressedSizeWithoutHeader, long prevBlockOffset,<a name="line.404"></a>
-<span class="sourceLineNo">405</span>      long offset, int onDiskDataSizeWithHeader, final int nextBlockOnDiskSize,<a name="line.405"></a>
-<span class="sourceLineNo">406</span>      HFileContext fileContext) {<a name="line.406"></a>
-<span class="sourceLineNo">407</span>    this.blockType = blockType;<a name="line.407"></a>
-<span class="sourceLineNo">408</span>    this.onDiskSizeWithoutHeader = onDiskSizeWithoutHeader;<a name="line.408"></a>
-<span class="sourceLineNo">409</span>    this.uncompressedSizeWithoutHeader = uncompressedSizeWithoutHeader;<a name="line.409"></a>
-<span class="sourceLineNo">410</span>    this.prevBlockOffset = prevBlockOffset;<a name="line.410"></a>
-<span class="sourceLineNo">411</span>    this.offset = offset;<a name="line.411"></a>
-<span class="sourceLineNo">412</span>    this.onDiskDataSizeWithHeader = onDiskDataSizeWithHeader;<a name="line.412"></a>
-<span class="sourceLineNo">413</span>    this.nextBlockOnDiskSize = nextBlockOnDiskSize;<a name="line.413"></a>
-<span class="sourceLineNo">414</span>    this.fileContext = fileContext;<a name="line.414"></a>
-<span class="sourceLineNo">415</span>  }<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">418</span>   * Parse total on disk size including header and checksum.<a name="line.418"></a>
-<span class="sourceLineNo">419</span>   * @param headerBuf Header ByteBuffer. Presumed exact size of header.<a name="line.419"></a>
-<span class="sourceLineNo">420</span>   * @param verifyChecksum true if checksum verification is in use.<a name="line.420"></a>
-<span class="sourceLineNo">421</span>   * @return Size of the block with header included.<a name="line.421"></a>
-<span class="sourceLineNo">422</span>   */<a name="line.422"></a>
-<span class="sourceLineNo">423</span>  private static int getOnDiskSizeWithHeader(final ByteBuffer headerBuf,<a name="line.423"></a>
-<span class="sourceLineNo">424</span>      boolean verifyChecksum) {<a name="line.424"></a>
-<span class="sourceLineNo">425</span>    return headerBuf.getInt(Header.ON_DISK_SIZE_WITHOUT_HEADER_INDEX) +<a name="line.425"></a>
-<span class="sourceLineNo">426</span>      headerSize(verifyChecksum);<a name="line.426"></a>
-<span class="sourceLineNo">427</span>  }<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>   * @return the on-disk size of the next block (including the header size and any checksums if<a name="line.430"></a>
-<span class="sourceLineNo">431</span>   * present) read by peeking into the next block's header; use as a hint when doing<a name="line.431"></a>
-<span class="sourceLineNo">432</span>   * a read of the next block when scanning or running over a file.<a name="line.432"></a>
-<span class="sourceLineNo">433</span>   */<a name="line.433"></a>
-<span class="sourceLineNo">434</span>  int getNextBlockOnDiskSize() {<a name="line.434"></a>
-<span class="sourceLineNo">435</span>    return nextBlockOnDiskSize;<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>  @Override<a name="line.438"></a>
-<span class="sourceLineNo">439</span>  public BlockType getBlockType() {<a name="line.439"></a>
-<span class="sourceLineNo">440</span>    return blockType;<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>  /** @return get data block encoding id that was used to encode this block */<a name="line.443"></a>
-<span class="sourceLineNo">444</span>  short getDataBlockEncodingId() {<a name="line.444"></a>
-<span class="sourceLineNo">445</span>    if (blockType != BlockType.ENCODED_DATA) {<a name="line.445"></a>
-<span class="sourceLineNo">446</span>      throw new IllegalArgumentException("Querying encoder ID of a block " +<a name="line.446"></a>
-<span class="sourceLineNo">447</span>          "of type other than " + BlockType.ENCODED_DATA + ": " + blockType);<a name="line.447"></a>
-<span class="sourceLineNo">448</span>    }<a name="line.448"></a>
-<span class="sourceLineNo">449</span>    return buf.getShort(headerSize());<a name="line.449"></a>
-<span class="sourceLineNo">450</span>  }<a name="line.450"></a>
-<span class="sourceLineNo">451</span><a name="line.451"></a>
-<span class="sourceLineNo">452</span>  /**<a name="line.452"></a>
-<span class="sourceLineNo">453</span>   * @return the on-disk size of header + data part + checksum.<a name="line.453"></a>
-<span class="sourceLineNo">454</span>   */<a name="line.454"></a>
-<span class="sourceLineNo">455</span>  public int getOnDiskSizeWithHeader() {<a name="line.455"></a>
-<span class="sourceLineNo">456</span>    return onDiskSizeWithoutHeader + headerSize();<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>   * @return the on-disk size of the data part + checksum (header excluded).<a name="line.460"></a>
-<span class="sourceLineNo">461</span>   */<a name="line.461"></a>
-<span class="sourceLineNo">462</span>  int getOnDiskSizeWithoutHeader() {<a name="line.462"></a>
-<span class="sourceLineNo">463</span>    return onDiskSizeWithoutHeader;<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>  /**<a name="line.466"></a>
-<span class="sourceLineNo">467</span>   * @return the uncompressed size of data part (header and checksum excluded).<a name="line.467"></a>
-<span class="sourceLineNo">468</span>   */<a name="line.468"></a>
-<span class="sourceLineNo">469</span>   int getUncompressedSizeWithoutHeader() {<a name="line.469"></a>
-<span class="sourceLineNo">470</span>    return uncompressedSizeWithoutHeader;<a name="line.470"></a>
-<span class="sourceLineNo">471</span>  }<a name="line.471"></a>
-<span class="sourceLineNo">472</span><a name="line.472"></a>
-<span class="sourceLineNo">473</span>  /**<a name="line.473"></a>
-<span class="sourceLineNo">474</span>   * @return the offset of the previous block of the same type in the file, or<a name="line.474"></a>
-<span class="sourceLineNo">475</span>   *         -1 if unknown<a name="line.475"></a>
-<span class="sourceLineNo">476</span>   */<a name="line.476"></a>
-<span class="sourceLineNo">477</span>  long getPrevBlockOffset() {<a name="line.477"></a>
-<span class="sourceLineNo">478</span>    return prevBlockOffset;<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>   * Rewinds {@code buf} and writes first 4 header fields. {@code buf} position<a name="line.482"></a>
-<span class="sourceLineNo">483</span>   * is modified as side-effect.<a name="line.483"></a>
-<span class="sourceLineNo">484</span>   */<a name="line.484"></a>
-<span class="sourceLineNo">485</span>  private void overwriteHeader() {<a name="line.485"></a>
-<span class="sourceLineNo">486</span>    buf.rewind();<a name="line.486"></a>
-<span class="sourceLineNo">487</span>    blockType.write(buf);<a name="line.487"></a>
-<span class="sourceLineNo">488</span>    buf.putInt(onDiskSizeWithoutHeader);<a name="line.488"></a>
-<span class="sourceLineNo">489</span>    buf.putInt(uncompressedSizeWithoutHeader);<a name="line.489"></a>
-<span class="sourceLineNo">490</span>    buf.putLong(prevBlockOffset);<a name="line.490"></a>
-<span class="sourceLineNo">491</span>    if (this.fileContext.isUseHBaseChecksum()) {<a name="line.491"></a>
-<span class="sourceLineNo">492</span>      buf.put(fileContext.getChecksumType().getCode());<a name="line.492"></a>
-<span class="sourceLineNo">493</span>      buf.putInt(fileContext.getBytesPerChecksum());<a name="line.493"></a>
-<span class="sourceLineNo">494</span>      buf.putInt(onDiskDataSizeWithHeader);<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>  /**<a name="line.498"></a>
-<span class="sourceLineNo">499</span>   * Returns a buffer that does not include the header or checksum.<a name="line.499"></a>
-<span class="sourceLineNo">500</span>   *<a name="line.500"></a>
-<span class="sourceLineNo">501</span>   * @return the buffer with header skipped and checksum omitted.<a name="line.501"></a>
-<span class="sourceLineNo">502</span>   */<a name="line.502"></a>
-<span class="sourceLineNo">503</span>  public ByteBuff getBufferWithoutHeader() {<a name="line.503"></a>
-<span class="sourceLineNo">504</span>    ByteBuff dup = getBufferReadOnly();<a name="line.504"></a>
-<span class="sourceLineNo">505</span>    // Now set it up so Buffer spans content only -- no header or no checksums.<a name="line.505"></a>
-<span class="sourceLineNo">506</span>    return dup.position(headerSize()).limit(buf.limit() - totalChecksumBytes()).slice();<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 a read-only duplicate of the buffer this block stores internally ready to be read.<a name="line.510"></a>
-<span class="sourceLineNo">511</span>   * Clients must not modify the buffer object though they may set position and limit on the<a name="line.511"></a>
-<span class="sourceLineNo">512</span>   * returned buffer since we pass back a duplicate. This method has to be public because it is used<a name="line.512"></a>
-<span class="sourceLineNo">513</span>   * in {@link CompoundBloomFilter} to avoid object creation on every Bloom<a name="line.513"></a>
-<span class="sourceLineNo">514</span>   * filter lookup, but has to be used with caution. Buffer holds header, block content,<a name="line.514"></a>
-<span class="sourceLineNo">515</span>   * and any follow-on checksums if present.<a name="line.515"></a>
-<span class="sourceLineNo">516</span>   *<a name="line.516"></a>
-<span class="sourceLineNo">517</span>   * @return the buffer of this block for read-only operations<a name="line.517"></a>
-<span class="sourceLineNo">518</span>   */<a name="line.518"></a>
-<span class="sourceLineNo">519</span>  public ByteBuff getBufferReadOnly() {<a name="line.519"></a>
-<span class="sourceLineNo">520</span>    // TODO: ByteBuf does not support asReadOnlyBuffer(). Fix.<a name="line.520"></a>
-<span class="sourceLineNo">521</span>    ByteBuff dup = this.buf.duplicate();<a name="line.521"></a>
-<span class="sourceLineNo">522</span>    assert dup.position() == 0;<a name="line.522"></a>
-<span class="sourceLineNo">523</span>    return dup;<a name="line.523"></a>
-<span class="sourceLineNo">524</span>  }<a name="line.524"></a>
-<span class="sourceLineNo">525</span><a name="line.525"></a>
-<span class="sourceLineNo">526</span>  @VisibleForTesting<a name="line.526"></a>
-<span class="sourceLineNo">527</span>  private void sanityCheckAssertion(long valueFromBuf, long valueFromField,<a name="line.527"></a>
-<span class="sourceLineNo">528</span>      String fieldName) throws IOException {<a name="line.528"></a>
-<span class="sourceLineNo">529</span>    if (valueFromBuf != valueFromField) {<a name="line.529"></a>
-<span class="sourceLineNo">530</span>      throw new AssertionError(fieldName + " in the buffer (" + valueFromBuf<a name="line.530"></a>
-<span class="sourceLineNo">531</span>          + ") is different from that in the field (" + valueFromField + ")");<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>  @VisibleForTesting<a name="line.535"></a>
-<span class="sourceLineNo">536</span>  private void sanityCheckAssertion(BlockType valueFromBuf, BlockType valueFromField)<a name="line.536"></a>
-<span class="sourceLineNo">537</span>      throws IOException {<a name="line.537"></a>
-<span class="sourceLineNo">538</span>    if (valueFromBuf != valueFromField) {<a name="line.538"></a>
-<span class="sourceLineNo">539</span>      throw new IOException("Block type stored in the buffer: " +<a name="line.539"></a>
-<span class="sourceLineNo">540</span>        valueFromBuf + ", block type field: " + valueFromField);<a name="line.540"></a>
-<span class="sourceLineNo">541</span>    }<a name="line.541"></a>
-<span class="sourceLineNo">542</span>  }<a name="line.542"></a>
-<span class="sourceLineNo">543</span><a name="line.543"></a>
-<span class="sourceLineNo">544</span>  /**<a name="line.544"></a>
-<span class="sourceLineNo">545</span>   * Checks if the block is internally consistent, i.e. the first<a name="line.545"></a>
-<span class="sourceLineNo">546</span>   * {@link HConstants#HFILEBLOCK_HEADER_SIZE} bytes of the buffer contain a<a name="line.546"></a>
-<span class="sourceLineNo">547</span>   * valid header consistent with the fields. Assumes a packed block structure.<a name="line.547"></a>
-<span class="sourceLineNo">548</span>   * This function is primary for testing and debugging, and is not<a name="line.548"></a>
-<span class="sourceLineNo">549</span>   * thread-safe, because it alters the internal buffer pointer.<a name="line.549"></a>
-<span class="sourceLineNo">550</span>   * Used by tests only.<a name="line.550"></a>
-<span class="sourceLineNo">551</span>   */<a name="line.551"></a>
-<span class="sourceLineNo">552</span>  @VisibleForTesting<a name="line.552"></a>
-<span class="sourceLineNo">553</span>  void sanityCheck() throws IOException {<a name="line.553"></a>
-<span class="sourceLineNo">554</span>    // Duplicate so no side-effects<a name="line.554"></a>
-<span class="sourceLineNo">555</span>    ByteBuff dup = this.buf.duplicate().rewind();<a name="line.555"></a>
-<span class="sourceLineNo">556</span>    sanityCheckAssertion(BlockType.read(dup), blockType);<a name="line.556"></a>
-<span class="sourceLineNo">557</span><a name="line.557"></a>
-<span class="sourceLineNo">558</span>    sanityCheckAssertion(dup.getInt(), onDiskSizeWithoutHeader, "onDiskSizeWithoutHeader");<a name="line.558"></a>
-<span class="sourceLineNo">559</span><a name="line.559"></a>
-<span class="sourceLineNo">560</span>    sanityCheckAssertion(dup.getInt(), uncompressedSizeWithoutHeader,<a name="line.560"></a>
-<span class="sourceLineNo">561</span>        "uncompressedSizeWithoutHeader");<a name="line.561"></a>
-<span class="sourceLineNo">562</span><a name="line.562"></a>
-<span class="sourceLineNo">563</span>    sanityCheckAssertion(dup.getLong(), prevBlockOffset, "prevBlockOffset");<a name="line.563"></a>
-<span class="sourceLineNo">564</span>    if (this.fileContext.isUseHBaseChecksum()) {<a name="line.564"></a>
-<span class="sourceLineNo">565</span>      sanityCheckAssertion(dup.get(), this.fileContext.getChecksumType().getCode(), "checksumType");<a name="line.565"></a>
-<span class="sourceLineNo">566</span>      sanityCheckAssertion(dup.getInt(), this.fileContext.getBytesPerChecksum(),<a name="line.566"></a>
-<span class="sourceLineNo">567</span>          "bytesPerChecksum");<a name="line.567"></a>
-<span class="sourceLineNo">568</span>      sanityCheckAssertion(dup.getInt(), onDiskDataSizeWithHeader, "onDiskDataSizeWithHeader");<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>    int cksumBytes = totalChecksumBytes();<a name="line.571"></a>
-<span class="sourceLineNo">572</span>    int expectedBufLimit = onDiskDataSizeWithHeader + cksumBytes;<a name="line.572"></a>
-<span class="sourceLineNo">573</span>    if (dup.limit() != expectedBufLimit) {<a name="line.573"></a>
-<span class="sourceLineNo">574</span>      throw new AssertionError("Expected limit " + expectedBufLimit + ", got " + dup.limit());<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>    // We might optionally allocate HFILEBLOCK_HEADER_SIZE more bytes to read the next<a name="line.577"></a>
-<span class="sourceLineNo">578</span>    // block's header, so there are two sensible values for buffer capacity.<a name="line.578"></a>
-<span class="sourceLineNo">579</span>    int hdrSize = headerSize();<a name="line.579"></a>
-<span class="sourceLineNo">580</span>    if (dup.capacity() != expectedBufLimit &amp;&amp; dup.capacity() != expectedBufLimit + hdrSize) {<a name="line.580"></a>
-<span class="sourceLineNo">581</span>      throw new AssertionError("Invalid buffer capacity: " + dup.capacity() +<a name="line.581"></a>
-<span class="sourceLineNo">582</span>          ", expected " + expectedBufLimit + " or " + (expectedBufLimit + hdrSize));<a name="line.582"></a>
-<span class="sourceLineNo">583</span>    }<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>  @Override<a name="line.586"></a>
-<span class="sourceLineNo">587</span>  public String toString() {<a name="line.587"></a>
-<span class="sourceLineNo">588</span>    StringBuilder sb = new StringBuilder()<a name="line.588"></a>
-<span class="sourceLineNo">589</span>      .append("[")<a name="line.589"></a>
-<span class="sourceLineNo">590</span>      .append("blockType=").append(blockType)<a name="line.590"></a>
-<span class="sourceLineNo">591</span>      .append(", fileOffset=").append(offset)<a name="line.591"></a>
-<span class="sourceLineNo">592</span>      .append(", headerSize=").append(headerSize())<a name="line.592"></a>
-<span class="sourceLineNo">593</span>      .append(", onDiskSizeWithoutHeader=").append(onDiskSizeWithoutHeader)<a name="line.593"></a>
-<span class="sourceLineNo">594</span>      .append(", uncompressedSizeWithoutHeader=").append(uncompressedSizeWithoutHeader)<a name="line.594"></a>
-<span class="sourceLineNo">595</span>      .append(", prevBlockOffset=").append(prevBlockOffset)<a name="line.595"></a>
-<span class="sourceLineNo">596</span>      .append(", isUseHBaseChecksum=").append(fileContext.isUseHBaseChecksum());<a name="line.596"></a>
-<span class="sourceLineNo">597</span>    if (fileContext.isUseHBaseChecksum()) {<a name="line.597"></a>
-<span class="sourceLineNo">598</span>      sb.append(", checksumType=").append(ChecksumType.codeToType(this.buf.get(24)))<a name="line.598"></a>
-<span class="sourceLineNo">599</span>        .append(", bytesPerChecksum=").append(this.buf.getInt(24 + 1))<a name="line.599"></a>
-<span class="sourceLineNo">600</span>        .append(", onDiskDataSizeWithHeader=").append(onDiskDataSizeWithHeader);<a name="line.600"></a>
-<span class="sourceLineNo">601</span>    } else {<a name="line.601"></a>
-<span class="sourceLineNo">602</span>      sb.append(", onDiskDataSizeWithHeader=").append(onDiskDataSizeWithHeader)<a name="line.602"></a>
-<span class="sourceLineNo">603</span>        .append("(").append(onDiskSizeWithoutHeader)<a name="line.603"></a>
-<span class="sourceLineNo">604</span>        .append("+").append(HConstants.HFILEBLOCK_HEADER_SIZE_NO_CHECKSUM).append(")");<a name="line.604"></a>
-<span class="sourceLineNo">605</span>    }<a name="line.605"></a>
-<span class="sourceLineNo">606</span>    String dataBegin = null;<a name="line.606"></a>
-<span class="sourceLineNo">607</span>    if (buf.hasArray()) {<a name="line.607"></a>
-<span class="sourceLineNo">608</span>      dataBegin = Bytes.toStringBinary(buf.array(), buf.arrayOffset() + headerSize(),<a name="line.608"></a>
-<span class="sourceLineNo">609</span>          Math.min(32, buf.limit() - buf.arrayOffset() - headerSize()));<a name="line.609"></a>
-<span class="sourceLineNo">610</span>    } else {<a name="line.610"></a>
-<span class="sourceLineNo">611</span>      ByteBuff bufWithoutHeader = getBufferWithoutHeader();<a name="line.611"></a>
-<span class="sourceLineNo">612</span>      byte[] dataBeginBytes = new byte[Math.min(32,<a name="line.612"></a>
-<span class="sourceLineNo">613</span>          bufWithoutHeader.limit() - bufWithoutHeader.position())];<a name="line.613"></a>
-<span class="sourceLineNo">614</span>      bufWithoutHeader.get(dataBeginBytes);<a name="line.614"></a>
-<span class="sourceLineNo">615</span>      dataBegin = Bytes.toStringBinary(dataBeginBytes);<a name="line.615"></a>
-<span class="sourceLineNo">616</span>    }<a name="line.616"></a>
-<span class="sourceLineNo">617</span>    sb.append(", getOnDiskSizeWithHeader=").append(getOnDiskSizeWithHeader())<a name="line.617"></a>
-<span class="sourceLineNo">618</span>      .append(", totalChecksumBytes=").append(totalChecksumBytes())<a name="line.618"></a>
-<span class="sourceLineNo">619</span>      .append(", isUnpacked=").append(isUnpacked())<a name="line.619"></a>
-<span class="sourceLineNo">620</span>      .append(", buf=[").append(buf).append("]")<a name="line.620"></a>
-<span class="sourceLineNo">621</span>      .append(", dataBeginsWith=").append(dataBegin)<a name="line.621"></a>
-<span class="sourceLineNo">622</span>      .append(", fileContext=").append(fileContext)<a name="line.622"></a>
-<span class="sourceLineNo">623</span>      .append("]");<a name="line.623"></a>
-<span class="sourceLineNo">624</span>    return sb.toString();<a name="line.624"></a>
-<span class="sourceLineNo">625</span>  }<a name="line.625"></a>
-<span class="sourceLineNo">626</span><a name="line.626"></a>
-<span class="sourceLineNo">627</span>  /**<a name="line.627"></a>
-<span class="sourceLineNo">628</span>   * Retrieves the decompressed/decrypted view of this block. An encoded block remains in its<a name="line.628"></a>
-<span class="sourceLineNo">629</span>   * encoded structure. Internal structures are shared between instances where applicable.<a name="line.629"></a>
-<span class="sourceLineNo">630</span>   */<a name="line.630"></a>
-<span class="sourceLineNo">631</span>  HFileBlock unpack(HFileContext fileContext, FSReader reader) throws IOException {<a name="line.631"></a>
-<span class="sourceLineNo">632</span>    if (!fileContext.isCompressedOrEncrypted()) {<a name="line.632"></a>
-<span class="sourceLineNo">633</span>      // TODO: cannot use our own fileContext here because HFileBlock(ByteBuffer, boolean),<a name="line.633"></a>
-<span class="sourceLineNo">634</span>      // which is used for block serialization to L2 cache, does not preserve encoding and<a name="line.634"></a>
-<span class="sourceLineNo">635</span>      // encryption details.<a name="line.635"></a>
-<span class="sourceLineNo">636</span>      return this;<a name="line.636"></a>
-<span class="sourceLineNo">637</span>    }<a name="line.637"></a>
-<span class="sourceLineNo">638</span><a name="line.638"></a>
-<span class="sourceLineNo">639</span>    HFileBlock unpacked = new HFileBlock(this);<a name="line.639"></a>
-<span class="sourceLineNo">640</span>    unpacked.allocateBuffer(); // allocates space for the decompressed block<a name="line.640"></a>
-<span class="sourceLineNo">641</span><a name="line.641"></a>
-<span class="sourceLineNo">642</span>    HFileBlockDecodingContext ctx = blockType == BlockType.ENCODED_DATA ?<a name="line.642"></a>
-<span class="sourceLineNo">643</span>      reader.getBlockDecodingContext() : reader.getDefaultBlockDecodingContext();<a name="line.643"></a>
-<span class="sourceLineNo">644</span><a name="line.644"></a>
-<span class="sourceLineNo">645</span>    ByteBuff dup = this.buf.duplicate();<a name="line.645"></a>
-<span class="sourceLineNo">646</span>    dup.position(this.headerSize());<a name="line.646"></a>
-<span class="sourceLineNo">647</span>    dup = dup.slice();<a name="line.647"></a>
-<span class="sourceLineNo">648</span>    ctx.prepareDecoding(unpacked.getOnDiskSizeWithoutHeader(),<a name="line.648"></a>
-<span class="sourceLineNo">649</span>      unpacked.getUncompressedSizeWithoutHeader(), unpacked.getBufferWithoutHeader(),<a name="line.649"></a>
-<span class="sourceLineNo">650</span>      dup);<a name="line.650"></a>
-<span class="sourceLineNo">651</span>    return unpacked;<a name="line.651"></a>
-<span class="sourceLineNo">652</span>  }<a name="line.652"></a>
-<span class="sourceLineNo">653</span><a name="line.653"></a>
-<span class="sourceLineNo">654</span>  /**<a name="line.654"></a>
-<span class="sourceLineNo">655</span>   * Always allocates a new buffer of the correct size. Copies header bytes<a name="line.655"></a>
-<span class="sourceLineNo">656</span>   * from the existing buffer. Does not change header fields.<a name="line.656"></a>
-<span class="sourceLineNo">657</span>   * Reserve room to keep checksum bytes too.<a name="line.657"></a>
-<span class="sourceLineNo">658</span>   */<a name="line.658"></a>
-<span class="sourceLineNo">659</span>  private void allocateBuffer() {<a name="line.659"></a>
-<span class="sourceLineNo">660</span>    int cksumBytes = totalChecksumBytes();<a name="line.660"></a>
-<span class="sourceLineNo">661</span>    int headerSize = headerSize();<a name="line.661"></a>
-<span class="sourceLineNo">662</span>    int capacityNeeded = headerSize + uncompressedSizeWithoutHeader + cksumBytes;<a name="line.662"></a>
-<span class="sourceLineNo">663</span><a name="line.663"></a>
-<span class="sourceLineNo">664</span>    // TODO we need consider allocating offheap here?<a name="line.664"></a>
-<span class="sourceLineNo">665</span>    ByteBuffer newBuf = ByteBuffer.allocate(capacityNeeded);<a name="line.665"></a>
-<span class="sourceLineNo">666</span><a name="line.666"></a>
-<span class="sourceLineNo">667</span>    // Copy header bytes into newBuf.<a name="line.667"></a>
-<span class="sourceLineNo">668</span>    // newBuf is HBB so no issue in calling array()<a name="line.668"></a>
-<span class="sourceLineNo">669</span>    buf.position(0);<a name="line.669"></a>
-<span class="sourceLineNo">670</span>    buf.get(newBuf.array(), newBuf.arrayOffset(), headerSize);<a name="line.670"></a>
-<span class="sourceLineNo">671</span><a name="line.671"></a>
-<span class="sourceLineNo">672</span>    buf = new SingleByteBuff(newBuf);<a name="line.672"></a>
-<span class="sourceLineNo">673</span>    // set limit to exclude next block's header<a name="line.673"></a>
-<span class="sourceLineNo">674</span>    buf.limit(headerSize + uncompressedSizeWithoutHeader + cksumBytes);<a name="line.674"></a>
-<span class="sourceLineNo">675</span>  }<a name="line.675"></a>
-<span class="sourceLineNo">676</span><a name="line.676"></a>
-<span class="sourceLineNo">677</span>  /**<a name="line.677"></a>
-<span class="sourceLineNo">678</span>   * Return true when this block's buffer has been unpacked, false otherwise. Note this is a<a name="line.678"></a>
-<span class="sourceLineNo">679</span>   * calculated heuristic, not tracked attribute of the block.<a name="line.679"></a>
-<span class="sourceLineNo">680</span>   */<a name="line.680"></a>
-<span class="sourceLineNo">681</span>  public boolean isUnpacked() {<a name="line.681"></a>
-<span class="sourceLineNo">682</span>    final int cksumBytes = totalChecksumBytes();<a name="line.682"></a>
-<span class="sourceLineNo">683</span>    final int headerSize = headerSize();<a name="line.683"></a>
-<span class="sourceLineNo">684</span>    final int expectedCapacity = headerSize + uncompressedSizeWithoutHeader + cksumBytes;<a name="line.684"></a>
-<span class="sourceLineNo">685</span>    final int bufCapacity = buf.capacity();<a name="line.685"></a>
-<span class="sourceLineNo">686</span>    return bufCapacity == expectedCapacity || bufCapacity == expectedCapacity + headerSize;<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>  /** An additional sanity-check in case no compression or encryption is being used. */<a name="line.689"></a>
-<span class="sourceLineNo">690</span>  @VisibleForTesting<a name="line.690"></a>
-<span class="sourceLineNo">691</span>  void sanityCheckUncompressedSize() throws IOException {<a name="line.691"></a>
-<span class="sourceLineNo">692</span>    if (onDiskSizeWithoutHeader != uncompressedSizeWithoutHeader + totalChecksumBytes()) {<a name="line.692"></a>
-<span class="sourceLineNo">693</span>      throw new IOException("Using no compression but "<a name="line.693"></a>
-<span class="sourceLineNo">694</span>          + "onDiskSizeWithoutHeader=" + onDiskSizeWithoutHeader + ", "<a name="line.694"></a>
-<span class="sourceLineNo">695</span>          + "uncompressedSizeWithoutHeader=" + uncompressedSizeWithoutHeader<a name="line.695"></a>
-<span class="sourceLineNo">696</span>          + ", numChecksumbytes=" + totalChecksumBytes());<a name="line.696"></a>
-<span class="sourceLineNo">697</span>    }<a name="line.697"></a>
-<span class="sourceLineNo">698</span>  }<a name="line.698"></a>
-<span class="sourceLineNo">699</span><a name="line.699"></a>
-<span class="sourceLineNo">700</span>  /**<a name="line.700"></a>
-<span class="sourceLineNo">701</span>   * Cannot be {@link #UNSET}. Must be a legitimate value. Used re-making the {@link BlockCacheKey} when<a name="line.701"></a>
-<span class="sourceLineNo">702</span>   * block is returned to the cache.<a name="line.702"></a>
-<span class="sourceLineNo">703</span>   * @return the offset of this block in the file it was read from<a name="line.703"></a>
-<span class="sourceLineNo">704</span>   */<a name="line.704"></a>
-<span class="sourceLineNo">705</span>  long getOffset() {<a name="line.705"></a>
-<span class="sourceLineNo">706</span>    if (offset &lt; 0) {<a name="line.706"></a>
-<span class="sourceLineNo">707</span>      throw new IllegalStateException("HFile block offset not initialized properly");<a name="line.707"></a>
-<span class="sourceLineNo">708</span>    }<a name="line.708"></a>
-<span class="sourceLineNo">709</span>    return offset;<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>   * @return a byte stream reading the data + checksum of this block<a name="line.713"></a>
-<span class="sourceLineNo">714</span>   */<a name="line.714"></a>
-<span class="sourceLineNo">715</span>  DataInputStream getByteStream() {<a name="line.715"></a>
-<span class="sourceLineNo">716</span>    ByteBuff dup = this.buf.duplicate();<a name="line.716"></a>
-<span class="sourceLineNo">717</span>    dup.position(this.headerSize());<a name="line.717"></a>
-<span class="sourceLineNo">718</span>    return new DataInputStream(new ByteBuffInputStream(dup));<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>
-<span class="sourceLineNo">721</span>  @Override<a name="line.721"></a>
-<span class="sourceLineNo">722</span>  public long heapSize() {<a name="line.722"></a>
-<span class="sourceLineNo">723</span>    long size = ClassSize.align(<a name="line.723"></a>
-<span class="sourceLineNo">724</span>        ClassSize.OBJECT +<a name="line.724"></a>
-<span class="sourceLineNo">725</span>        // Block type, multi byte buffer, MemoryType and meta references<a name="line.725"></a>
-<span class="sourceLineNo">726</span>        4 * ClassSize.REFERENCE +<a name="line.726"></a>
-<span class="sourceLineNo">727</span>        // On-disk size, uncompressed size, and next block's on-disk size<a name="line.727"></a>
-<span class="sourceLineNo">728</span>        // bytePerChecksum and onDiskDataSize<a name="line.728"></a>
-<span class="sourceLineNo">729</span>        4 * Bytes.SIZEOF_INT +<a name="line.729"></a>
-<span class="sourceLineNo">730</span>        // This and previous block offset<a name="line.730"></a>
-<span class="sourceLineNo">731</span>        2 * Bytes.SIZEOF_LONG +<a name="line.731"></a>
-<span class="sourceLineNo">732</span>        // Heap size of the meta object. meta will be always not null.<a name="line.732"></a>
-<span class="sourceLineNo">733</span>        fileContext.heapSize()<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>    if (buf != null) {<a name="line.736"></a>
-<span class="sourceLineNo">737</span>      // Deep overhead of the byte buffer. Needs to be aligned separately.<a name="line.737"></a>
-<span class="sourceLineNo">738</span>      size += ClassSize.align(buf.capacity() + MULTI_BYTE_BUFFER_HEAP_SIZE);<a name="line.738"></a>
-<span class="sourceLineNo">739</span>    }<a name="line.739"></a>
-<span class="sourceLineNo">740</span><a name="line.740"></a>
-<span class="sourceLineNo">741</span>    return ClassSize.align(size);<a name="line.741"></a>
-<span class="sourceLineNo">742</span>  }<a name="line.742"></a>
-<span class="sourceLineNo">743</span><a name="line.743"></a>
-<span class="sourceLineNo">744</span>  /**<a name="line.744"></a>
-<span class="sourceLineNo">745</span>   * Read from an input stream at least &lt;code&gt;necessaryLen&lt;/code&gt; and if possible,<a name="line.745"></a>
-<span class="sourceLineNo">746</span>   * &lt;code&gt;extraLen&lt;/code&gt; also if available. Analogous to<a name="line.746"></a>
-<span class="sourceLineNo">747</span>   * {@link IOUtils#readFully(InputStream, byte[], int, int)}, but specifies a<a name="line.747"></a>
-<span class="sourceLineNo">748</span>   * number of "extra" bytes to also optionally read.<a name="line.748"></a>
-<span class="sourceLineNo">749</span>   *<a name="line.749"></a>
-<span class="sourceLineNo">750</span>   * @param in the input stream to read from<a name="line.750"></a>
-<span class="sourceLineNo">751</span>   * @param buf the buffer to read into<a name="line.751"></a>
-<span class="sourceLineNo">752</span>   * @param bufOffset the destination offset in the buffer<a name="line.752"></a>
-<span class="sourceLineNo">753</span>   * @param necessaryLen the number of bytes that are absolutely necessary to read<a name="line.753"></a>
-<span class="sourceLineNo">754</span>   * @param extraLen the number of extra bytes that would be nice to read<a name="line.754"></a>
-<span class="sourceLineNo">755</span>   * @return true if succeeded reading the extra bytes<a name="line.755"></a>
-<span class="sourceLineNo">756</span>   * @throws IOException if failed to read the necessary bytes<a name="line.756"></a>
-<span class="sourceLineNo">757</span>   */<a name="line.757"></a>
-<span class="sourceLineNo">758</span>  static boolean readWithExtra(InputStream in, byte[] buf,<a name="line.758"></a>
-<span class="sourceLineNo">759</span>      int bufOffset, int necessaryLen, int extraLen) throws IOException {<a name="line.759"></a>
-<span class="sourceLineNo">760</span>    int bytesRemaining = necessaryLen + extraLen;<a name="line.760"></a>
-<span class="sourceLineNo">761</span>    while (bytesRemaining &gt; 0) {<a name="line.761"></a>
-<span class="sourceLineNo">762</span>      int ret = in.read(buf, bufOffset, bytesRemaining);<a name="line.762"></a>
-<span class="sourceLineNo">763</span>      if (ret == -1 &amp;&amp; bytesRemaining &lt;= extraLen) {<a name="line.763"></a>
-<span class="sourceLineNo">764</span>        // We could not read the "extra data", but that is OK.<a name="line.764"></a>
-<span class="sourceLineNo">765</span>        break;<a name="line.765"></a>
-<span class="sourceLineNo">766</span>      }<a name="line.766"></a>
-<span class="sourceLineNo">767</span>      if (ret &lt; 0) {<a name="line.767"></a>
-<span class="sourceLineNo">768</span>        throw new IOException("Premature EOF from inputStream (read "<a name="line.768"></a>
-<span class="sourceLineNo">769</span>            + "returned " + ret + ", was trying to read " + necessaryLen<a name="line.769"></a>
-<span class="sourceLineNo">770</span>            + " necessary bytes and " + extraLen + " extra bytes, "<a name="line.770"></a>
-<span class="sourceLineNo">771</span>            + "successfully read "<a name="line.771"></a>
-<span class="sourceLineNo">772</span>            + (necessaryLen + extraLen - bytesRemaining));<a name="line.772"></a>
-<span class="sourceLineNo">773</span>      }<a name="line.773"></a>
-<span class="sourceLineNo">774</span>      bufOffset += ret;<a name="line.774"></a>
-<span class="sourceLineNo">775</span>      bytesRemaining -= ret;<a name="line.775"></a>
-<span class="sourceLineNo">776</span>    }<a name="line.776"></a>
-<span class="sourceLineNo">777</span>    return bytesRemaining &lt;= 0;<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>   * Read from an input stream at least &lt;code&gt;necessaryLen&lt;/code&gt; and if possible,<a name="line.781"></a>
-<span class="sourceLineNo">782</span>   * &lt;code&gt;extraLen&lt;/code&gt; also if available. Analogous to<a name="line.782"></a>
-<span class="sourceLineNo">783</span>   * {@link IOUtils#readFully(InputStream, byte[], int, int)}, but uses<a name="line.783"></a>
-<span class="sourceLineNo">784</span>   * positional read and specifies a number of "extra" bytes that would be<a name="line.784"></a>
-<span class="sourceLineNo">785</span>   * desirable but not absolutely necessary to read.<a name="line.785"></a>
-<span class="sourceLineNo">786</span>   *<a name="line.786"></a>
-<span class="sourceLineNo">787</span>   * @param in the input stream to read from<a name="line.787"></a>
-<span class="sourceLineNo">788</span>   * @param position the position within the stream from which to start reading<a name="line.788"></a>
-<span class="sourceLineNo">789</span>   * @param buf the buffer to read into<a name="line.789"></a>
-<span class="sourceLineNo">790</span>   * @param bufOffset the destination offset in the buffer<a name="line.790"></a>
-<span class="sourceLineNo">791</span>   * @param necessaryLen the number of bytes that are absolutely necessary to<a name="line.791"></a>
-<span class="sourceLineNo">792</span>   *     read<a name="line.792"></a>
-<span class="sourceLineNo">793</span>   * @param extraLen the number of extra bytes that would be nice to read<a name="line.793"></a>
-<span class="sourceLineNo">794</span>   * @return true if and only if extraLen is &gt; 0 and reading those extra bytes<a name="line.794"></a>
-<span class="sourceLineNo">795</span>   *     was successful<a name="line.795"></a>
-<span class="sourceLineNo">796</span>   * @throws IOException if failed to read the necessary bytes<a name="line.796"></a>
-<span class="sourceLineNo">797</span>   */<a name="line.797"></a>
-<span class="sourceLineNo">798</span>  @VisibleForTesting<a name="line.798"></a>
-<span class="sourceLineNo">799</span>  static boolean positionalReadWithExtra(FSDataInputStream in,<a name="line.799"></a>
-<span class="sourceLineNo">800</span>      long position, byte[] buf, int bufOffset, int necessaryLen, int extraLen)<a name="line.800"></a>
-<span class="sourceLineNo">801</span>      throws IOException {<a name="line.801"></a>
-<span class="sourceLineNo">802</span>    int bytesRemaining = necessaryLen + extraLen;<a name="line.802"></a>
-<span class="sourceLineNo">803</span>    int bytesRead = 0;<a name="line.803"></a>
-<span class="sourceLineNo">804</span>    while (bytesRead &lt; necessaryLen) {<a name="line.804"></a>
-<span class="sourceLineNo">805</span>      int ret = in.read(position, buf, bufOffset, bytesRemaining);<a name="line.805"></a>
-<span class="sourceLineNo">806</span>      if (ret &lt; 0) {<a name="line.806"></a>
-<span class="sourceLineNo">807</span>        throw new IOException("Premature EOF from inputStream (positional read "<a name="line.807"></a>
-<span class="sourceLineNo">808</span>            + "returned " + ret + ", was trying to read " + necessaryLen<a name="line.808"></a>
-<span class="sourceLineNo">809</span>            + " necessary bytes and " + extraLen + " extra bytes, "<a name="line.809"></a>
-<span class="sourceLineNo">810</span>            + "successfully read " + bytesRead);<a name="line.810"></a>
-<span class="sourceLineNo">811</span>      }<a name="line.811"></a>
-<span class="sourceLineNo">812</span>      position += ret;<a name="line.812"></a>
-<span class="sourceLineNo">813</span>      bufOffset += ret;<a name="line.813"></a>
-<span class="sourceLineNo">814</span>      bytesRemaining -= ret;<a name="line.814"></a>
-<span class="sourceLineNo">815</span>      bytesRead += ret;<a name="line.815"></a>
-<span class="sourceLineNo">816</span>    }<a name="line.816"></a>
-<span class="sourceLineNo">817</span>    return bytesRead != necessaryLen &amp;&amp; bytesRemaining &lt;= 0;<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>   * Unified version 2 {@link HFile} block writer. The intended usage pattern<a name="line.821"></a>
-<span class="sourceLineNo">822</span>   * is as follows:<a name="line.822"></a>
-<span class="sourceLineNo">823</span>   * &lt;ol&gt;<a name="line.823"></a>
-<span class="sourceLineNo">824</span>   * &lt;li&gt;Construct an {@link HFileBlock.Writer}, providing a compression algorithm.<a name="line.824"></a>
-<span class="sourceLineNo">825</span>   * &lt;li&gt;Call {@link Writer#startWriting} and get a data stream to write to.<a name="line.825"></a>
-<span class="sourceLineNo">826</span>   * &lt;li&gt;Write your data into the stream.<a name="line.826"></a>
-<span class="sourceLineNo">827</span>   * &lt;li&gt;Call Writer#writeHeaderAndData(FSDataOutputStream) as many times as you need to.<a name="line.827"></a>
-<span class="sourceLineNo">828</span>   * store the serialized block into an external stream.<a name="line.828"></a>
-<span class="sourceLineNo">829</span>   * &lt;li&gt;Repeat to write more blocks.<a name="line.829"></a>
-<span class="sourceLineNo">830</span>   * &lt;/ol&gt;<a name="line.830"></a>
-<span class="sourceLineNo">831</span>   * &lt;p&gt;<a name="line.831"></a>
-<span class="sourceLineNo">832</span>   */<a name="line.832"></a>
-<span class="sourceLineNo">833</span>  static class Writer {<a name="line.833"></a>
-<span class="sourceLineNo">834</span>    private enum State {<a name="line.834"></a>
-<span class="sourceLineNo">835</span>      INIT,<a name="line.835"></a>
-<span class="sourceLineNo">836</span>      WRITING,<a name="line.836"></a>
-<span class="sourceLineNo">837</span>      BLOCK_READY<a name="line.837"></a>
-<span class="sourceLineNo">838</span>    }<a name="line.838"></a>
-<span class="sourceLineNo">839</span><a name="line.839"></a>
-<span class="sourceLineNo">840</span>    /** Writer state. Used to ensure the correct usage protocol. */<a name="line.840"></a>
-<span class="sourceLineNo">841</span>    private State state = State.INIT;<a name="line.841"></a>
-<span class="sourceLineNo">842</span><a name="line.842"></a>
-<span class="sourceLineNo">843</span>    /** Data block encoder used for data blocks */<a name="line.843"></a>
-<span class="sourceLineNo">844</span>    private final HFileDataBlockEncoder dataBlockEncoder;<a name="line.844"></a>
-<span class="sourceLineNo">845</span><a name="line.845"></a>
-<span class="sourceLineNo">846</span>    private HFileBlockEncodingContext dataBlockEncodingCtx;<a name="line.846"></a>
+<span class="sourceLineNo">328</span>   *<a name="line.328"></a>
+<span class="sourceLineNo">329</span>   * &lt;p&gt;TODO: The caller presumes no checksumming<a name="line.329"></a>
+<span class="sourceLineNo">330</span>   * required of this block instance since going into cache; checksum already verified on<a name="line.330"></a>
+<span class="sourceLineNo">331</span>   * underlying block data pulled in from filesystem. Is that correct? What if cache is SSD?<a name="line.331"></a>
+<span class="sourceLineNo">332</span>   *<a name="line.332"></a>
+<span class="sourceLineNo">333</span>   * @param blockType the type of this block, see {@link BlockType}<a name="line.333"></a>
+<span class="sourceLineNo">334</span>   * @param onDiskSizeWithoutHeader see {@link #onDiskSizeWithoutHeader}<a name="line.334"></a>
+<span class="sourceLineNo">335</span>   * @param uncompressedSizeWithoutHeader see {@link #uncompressedSizeWithoutHeader}<a name="line.335"></a>
+<span class="sourceLineNo">336</span>   * @param prevBlockOffset see {@link #prevBlockOffset}<a name="line.336"></a>
+<span class="sourceLineNo">337</span>   * @param b block header ({@link HConstants#HFILEBLOCK_HEADER_SIZE} bytes)<a name="line.337"></a>
+<span class="sourceLineNo">338</span>   * @param fillHeader when true, write the first 4 header fields into passed buffer.<a name="line.338"></a>
+<span class="sourceLineNo">339</span>   * @param offset the file offset the block was read from<a name="line.339"></a>
+<span class="sourceLineNo">340</span>   * @param onDiskDataSizeWithHeader see {@link #onDiskDataSizeWithHeader}<a name="line.340"></a>
+<span class="sourceLineNo">341</span>   * @param fileContext HFile meta data<a name="line.341"></a>
+<span class="sourceLineNo">342</span>   */<a name="line.342"></a>
+<span class="sourceLineNo">343</span>  @VisibleForTesting<a name="line.343"></a>
+<span class="sourceLineNo">344</span>  public HFileBlock(BlockType blockType, int onDiskSizeWithoutHeader,<a name="line.344"></a>
+<span class="sourceLineNo">345</span>      int uncompressedSizeWithoutHeader, long prevBlockOffset, ByteBuffer b, boolean fillHeader,<a name="line.345"></a>
+<span class="sourceLineNo">346</span>      long offset, final int nextBlockOnDiskSize, int onDiskDataSizeWithHeader,<a name="line.346"></a>
+<span class="sourceLineNo">347</span>      HFileContext fileContext) {<a name="line.347"></a>
+<span class="sourceLineNo">348</span>    init(blockType, onDiskSizeWithoutHeader, uncompressedSizeWithoutHeader,<a name="line.348"></a>
+<span class="sourceLineNo">349</span>        prevBlockOffset, offset, onDiskDataSizeWithHeader, nextBlockOnDiskSize, fileContext);<a name="line.349"></a>
+<span class="sourceLineNo">350</span>    this.buf = new SingleByteBuff(b);<a name="line.350"></a>
+<span class="sourceLineNo">351</span>    if (fillHeader) {<a name="line.351"></a>
+<span class="sourceLineNo">352</span>      overwriteHeader();<a name="line.352"></a>
+<span class="sourceLineNo">353</span>    }<a name="line.353"></a>
+<span class="sourceLineNo">354</span>    this.buf.rewind();<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">357</span>  /**<a name="line.357"></a>
+<span class="sourceLineNo">358</span>   * Creates a block from an existing buffer starting with a header. Rewinds<a name="line.358"></a>
+<span class="sourceLineNo">359</span>   * and takes ownership of the buffer. By definition of rewind, ignores the<a name="line.359"></a>
+<span class="sourceLineNo">360</span>   * buffer position, but if you slice the buffer beforehand, it will rewind<a name="line.360"></a>
+<span class="sourceLineNo">361</span>   * to that point.<a name="line.361"></a>
+<span class="sourceLineNo">362</span>   * @param buf Has header, content, and trailing checksums if present.<a name="line.362"></a>
+<span class="sourceLineNo">363</span>   */<a name="line.363"></a>
+<span class="sourceLineNo">364</span>  HFileBlock(ByteBuff buf, boolean usesHBaseChecksum, MemoryType memType, final long offset,<a name="line.364"></a>
+<span class="sourceLineNo">365</span>      final int nextBlockOnDiskSize, HFileContext fileContext) throws IOException {<a name="line.365"></a>
+<span class="sourceLineNo">366</span>    buf.rewind();<a name="line.366"></a>
+<span class="sourceLineNo">367</span>    final BlockType blockType = BlockType.read(buf);<a name="line.367"></a>
+<span class="sourceLineNo">368</span>    final int onDiskSizeWithoutHeader = buf.getInt(Header.ON_DISK_SIZE_WITHOUT_HEADER_INDEX);<a name="line.368"></a>
+<span class="sourceLineNo">369</span>    final int uncompressedSizeWithoutHeader =<a name="line.369"></a>
+<span class="sourceLineNo">370</span>        buf.getInt(Header.UNCOMPRESSED_SIZE_WITHOUT_HEADER_INDEX);<a name="line.370"></a>
+<span class="sourceLineNo">371</span>    final long prevBlockOffset = buf.getLong(Header.PREV_BLOCK_OFFSET_INDEX);<a name="line.371"></a>
+<span class="sourceLineNo">372</span>    // This constructor is called when we deserialize a block from cache and when we read a block in<a name="line.372"></a>
+<span class="sourceLineNo">373</span>    // from the fs. fileCache is null when deserialized from cache so need to make up one.<a name="line.373"></a>
+<span class="sourceLineNo">374</span>    HFileContextBuilder fileContextBuilder = fileContext != null?<a name="line.374"></a>
+<span class="sourceLineNo">375</span>        new HFileContextBuilder(fileContext): new HFileContextBuilder();<a name="line.375"></a>
+<span class="sourceLineNo">376</span>    fileContextBuilder.withHBaseCheckSum(usesHBaseChecksum);<a name="line.376"></a>
+<span class="sourceLineNo">377</span>    int onDiskDataSizeWithHeader;<a name="line.377"></a>
+<span class="sourceLineNo">378</span>    if (usesHBaseChecksum) {<a name="line.378"></a>
+<span class="sourceLineNo">379</span>      byte checksumType = buf.get(Header.CHECKSUM_TYPE_INDEX);<a name="line.379"></a>
+<span class="sourceLineNo">380</span>      int bytesPerChecksum = buf.getInt(Header.BYTES_PER_CHECKSUM_INDEX);<a name="line.380"></a>
+<span class="sourceLineNo">381</span>      onDiskDataSizeWithHeader = buf.getInt(Header.ON_DISK_DATA_SIZE_WITH_HEADER_INDEX);<a name="line.381"></a>
+<span class="sourceLineNo">382</span>      // Use the checksum type and bytes per checksum from header, not from filecontext.<a name="line.382"></a>
+<span class="sourceLineNo">383</span>      fileContextBuilder.withChecksumType(ChecksumType.codeToType(checksumType));<a name="line.383"></a>
+<span class="sourceLineNo">384</span>      fileContextBuilder.withBytesPerCheckSum(bytesPerChecksum);<a name="line.384"></a>
+<span class="sourceLineNo">385</span>    } else {<a name="line.385"></a>
+<span class="sourceLineNo">386</span>      fileContextBuilder.withChecksumType(ChecksumType.NULL);<a name="line.386"></a>
+<span class="sourceLineNo">387</span>      fileContextBuilder.withBytesPerCheckSum(0);<a name="line.387"></a>
+<span class="sourceLineNo">388</span>      // Need to fix onDiskDataSizeWithHeader; there are not checksums after-block-data<a name="line.388"></a>
+<span class="sourceLineNo">389</span>      onDiskDataSizeWithHeader = onDiskSizeWithoutHeader + headerSize(usesHBaseChecksum);<a name="line.389"></a>
+<span class="sourceLineNo">390</span>    }<a name="line.390"></a>
+<span class="sourceLineNo">391</span>    fileContext = fileContextBuilder.build();<a name="line.391"></a>
+<span class="sourceLineNo">392</span>    assert usesHBaseChecksum == fileContext.isUseHBaseChecksum();<a name="line.392"></a>
+<span class="sourceLineNo">393</span>    init(blockType, onDiskSizeWithoutHeader, uncompressedSizeWithoutHeader,<a name="line.393"></a>
+<span class="sourceLineNo">394</span>        prevBlockOffset, offset, onDiskDataSizeWithHeader, nextBlockOnDiskSize, fileContext);<a name="line.394"></a>
+<span class="sourceLineNo">395</span>    this.memType = memType;<a name="line.395"></a>
+<span class="sourceLineNo">396</span>    this.offset = offset;<a name="line.396"></a>
+<span class="sourceLineNo">397</span>    this.buf = buf;<a name="line.397"></a>
+<span class="sourceLineNo">398</span>    this.buf.rewind();<a name="line.398"></a>
+<span class="sourceLineNo">399</span>  }<a name="line.399"></a>
+<span class="sourceLineNo">400</span><a name="line.400"></a>
+<span class="sourceLineNo">401</span>  /**<a name="line.401"></a>
+<span class="sourceLineNo">402</span>   * Called from constructors.<a name="line.402"></a>
+<span class="sourceLineNo">403</span>   */<a name="line.403"></a>
+<span class="sourceLineNo">404</span>  private void init(BlockType blockType, int onDiskSizeWithoutHeader,<a name="line.404"></a>
+<span class="sourceLineNo">405</span>      int uncompressedSizeWithoutHeader, long prevBlockOffset,<a name="line.405"></a>
+<span class="sourceLineNo">406</span>      long offset, int onDiskDataSizeWithHeader, final int nextBlockOnDiskSize,<a name="line.406"></a>
+<span class="sourceLineNo">407</span>      HFileContext fileContext) {<a name="line.407"></a>
+<span class="sourceLineNo">408</span>    this.blockType = blockType;<a name="line.408"></a>
+<span class="sourceLineNo">409</span>    this.onDiskSizeWithoutHeader = onDiskSizeWithoutHeader;<a name="line.409"></a>
+<span class="sourceLineNo">410</span>    this.uncompressedSizeWithoutHeader = uncompressedSizeWithoutHeader;<a name="line.410"></a>
+<span class="sourceLineNo">411</span>    this.prevBlockOffset = prevBlockOffset;<a name="line.411"></a>
+<span class="sourceLineNo">412</span>    this.offset = offset;<a name="line.412"></a>
+<span class="sourceLineNo">413</span>    this.onDiskDataSizeWithHeader = onDiskDataSizeWithHeader;<a name="line.413"></a>
+<span class="sourceLineNo">414</span>    this.nextBlockOnDiskSize = nextBlockOnDiskSize;<a name="line.414"></a>
+<span class="sourceLineNo">415</span>    this.fileContext = fileContext;<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">418</span>  /**<a name="line.418"></a>
+<span class="sourceLineNo">419</span>   * Parse total on disk size including header and checksum.<a name="line.419"></a>
+<span class="sourceLineNo">420</span>   * @param headerBuf Header ByteBuffer. Presumed exact size of header.<a name="line.420"></a>
+<span class="sourceLineNo">421</span>   * @param verifyChecksum true if checksum verification is in use.<a name="line.421"></a>
+<span class="sourceLineNo">422</span>   * @return Size of the block with header included.<a name="line.422"></a>
+<span class="sourceLineNo">423</span>   */<a name="line.423"></a>
+<span class="sourceLineNo">424</span>  private static int getOnDiskSizeWithHeader(final ByteBuffer headerBuf,<a name="line.424"></a>
+<span class="sourceLineNo">425</span>      boolean verifyChecksum) {<a name="line.425"></a>
+<span class="sourceLineNo">426</span>    return headerBuf.getInt(Header.ON_DISK_SIZE_WITHOUT_HEADER_INDEX) +<a name="line.426"></a>
+<span class="sourceLineNo">427</span>      headerSize(verifyChecksum);<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>   * @return the on-disk size of the next block (including the header size and any checksums if<a name="line.431"></a>
+<span class="sourceLineNo">432</span>   * present) read by peeking into the next block's header; use as a hint when doing<a name="line.432"></a>
+<span class="sourceLineNo">433</span>   * a read of the next block when scanning or running over a file.<a name="line.433"></a>
+<span class="sourceLineNo">434</span>   */<a name="line.434"></a>
+<span class="sourceLineNo">435</span>  int getNextBlockOnDiskSize() {<a name="line.435"></a>
+<span class="sourceLineNo">436</span>    return nextBlockOnDiskSize;<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>  @Override<a name="line.439"></a>
+<span class="sourceLineNo">440</span>  public BlockType getBlockType() {<a name="line.440"></a>
+<span class="sourceLineNo">441</span>    return blockType;<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>  /** @return get data block encoding id that was used to encode this block */<a name="line.444"></a>
+<span class="sourceLineNo">445</span>  short getDataBlockEncodingId() {<a name="line.445"></a>
+<span class="sourceLineNo">446</span>    if (blockType != BlockType.ENCODED_DATA) {<a name="line.446"></a>
+<span class="sourceLineNo">447</span>      throw new IllegalArgumentException("Querying encoder ID of a block " +<a name="line.447"></a>
+<span class="sourceLineNo">448</span>          "of type other than " + BlockType.ENCODED_DATA + ": " + blockType);<a name="line.448"></a>
+<span class="sourceLineNo">449</span>    }<a name="line.449"></a>
+<span class="sourceLineNo">450</span>    return buf.getShort(headerSize());<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>   * @return the on-disk size of header + data part + checksum.<a name="line.454"></a>
+<span class="sourceLineNo">455</span>   */<a name="line.455"></a>
+<span class="sourceLineNo">456</span>  public int getOnDiskSizeWithHeader() {<a name="line.456"></a>
+<span class="sourceLineNo">457</span>    return onDiskSizeWithoutHeader + headerSize();<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>   * @return the on-disk size of the data part + checksum (header excluded).<a name="line.461"></a>
+<span class="sourceLineNo">462</span>   */<a name="line.462"></a>
+<span class="sourceLineNo">463</span>  int getOnDiskSizeWithoutHeader() {<a name="line.463"></a>
+<span class="sourceLineNo">464</span>    return onDiskSizeWithoutHeader;<a name="line.464"></a>
+<span class="sourceLineNo">465</span>  }<a name="line.465"></a>
+<span class="sourceLineNo">466</span><a name="line.466"></a>
+<span class="sourceLineNo">467</span>  /**<a name="line.467"></a>
+<span class="sourceLineNo">468</span>   * @return the uncompressed size of data part (header and checksum excluded).<a name="line.468"></a>
+<span class="sourceLineNo">469</span>   */<a name="line.469"></a>
+<span class="sourceLineNo">470</span>   int getUncompressedSizeWithoutHeader() {<a name="line.470"></a>
+<span class="sourceLineNo">471</span>    return uncompressedSizeWithoutHeader;<a name="line.471"></a>
+<span class="sourceLineNo">472</span>  }<a name="line.472"></a>
+<span class="sourceLineNo">473</span><a name="line.473"></a>
+<span class="sourceLineNo">474</span>  /**<a name="line.474"></a>
+<span class="sourceLineNo">475</span>   * @return the offset of the previous block of the same type in the file, or<a name="line.475"></a>
+<span class="sourceLineNo">476</span>   *         -1 if unknown<a name="line.476"></a>
+<span class="sourceLineNo">477</span>   */<a name="line.477"></a>
+<span class="sourceLineNo">478</span>  long getPrevBlockOffset() {<a name="line.478"></a>
+<span class="sourceLineNo">479</span>    return prevBlockOffset;<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>   * Rewinds {@code buf} and writes first 4 header fields. {@code buf} position<a name="line.483"></a>
+<span class="sourceLineNo">484</span>   * is modified as side-effect.<a name="line.484"></a>
+<span class="sourceLineNo">485</span>   */<a name="line.485"></a>
+<span class="sourceLineNo">486</span>  private void overwriteHeader() {<a name="line.486"></a>
+<span class="sourceLineNo">487</span>    buf.rewind();<a name="line.487"></a>
+<span class="sourceLineNo">488</span>    blockType.write(buf);<a name="line.488"></a>
+<span class="sourceLineNo">489</span>    buf.putInt(onDiskSizeWithoutHeader);<a name="line.489"></a>
+<span class="sourceLineNo">490</span>    buf.putInt(uncompressedSizeWithoutHeader);<a name="line.490"></a>
+<span class="sourceLineNo">491</span>    buf.putLong(prevBlockOffset);<a name="line.491"></a>
+<span class="sourceLineNo">492</span>    if (this.fileContext.isUseHBaseChecksum()) {<a name="line.492"></a>
+<span class="sourceLineNo">493</span>      buf.put(fileContext.getChecksumType().getCode());<a name="line.493"></a>
+<span class="sourceLineNo">494</span>      buf.putInt(fileContext.getBytesPerChecksum());<a name="line.494"></a>
+<span class="sourceLineNo">495</span>      buf.putInt(onDiskDataSizeWithHeader);<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><a name="line.498"></a>
+<span class="sourceLineNo">499</span>  /**<a name="line.499"></a>
+<span class="sourceLineNo">500</span>   * Returns a buffer that does not include the header or checksum.<a name="line.500"></a>
+<span class="sourceLineNo">501</span>   *<a name="line.501"></a>
+<span class="sourceLineNo">502</span>   * @return the buffer with header skipped and checksum omitted.<a name="line.502"></a>
+<span class="sourceLineNo">503</span>   */<a name="line.503"></a>
+<span class="sourceLineNo">504</span>  public ByteBuff getBufferWithoutHeader() {<a name="line.504"></a>
+<span class="sourceLineNo">505</span>    ByteBuff dup = getBufferReadOnly();<a name="line.505"></a>
+<span class="sourceLineNo">506</span>    // Now set it up so Buffer spans content only -- no header or no checksums.<a name="line.506"></a>
+<span class="sourceLineNo">507</span>    return dup.position(headerSize()).limit(buf.limit() - totalChecksumBytes()).slice();<a name="line.507"></a>
+<span class="sourceLineNo">508</span>  }<a name="line.508"></a>
+<span class="sourceLineNo">509</span><a name="line.509"></a>
+<span class="sourceLineNo">510</span>  /**<a name="line.510"></a>
+<span class="sourceLineNo">511</span>   * Returns a read-only duplicate of the buffer this block stores internally ready to be read.<a name="line.511"></a>
+<span class="sourceLineNo">512</span>   * Clients must not modify the buffer object though they may set position and limit on the<a name="line.512"></a>
+<span class="sourceLineNo">513</span>   * returned buffer since we pass back a duplicate. This method has to be public because it is used<a name="line.513"></a>
+<span class="sourceLineNo">514</span>   * in {@link CompoundBloomFilter} to avoid object creation on every Bloom<a name="line.514"></a>
+<span class="sourceLineNo">515</span>   * filter lookup, but has to be used with caution. Buffer holds header, block content,<a name="line.515"></a>
+<span class="sourceLineNo">516</span>   * and any follow-on checksums if present.<a name="line.516"></a>
+<span class="sourceLineNo">517</span>   *<a name="line.517"></a>
+<span class="sourceLineNo">518</span>   * @return the buffer of this block for read-only operations<a name="line.518"></a>
+<span class="sourceLineNo">519</span>   */<a name="line.519"></a>
+<span class="sourceLineNo">520</span>  public ByteBuff getBufferReadOnly() {<a name="line.520"></a>
+<span class="sourceLineNo">521</span>    // TODO: ByteBuf does not support asReadOnlyBuffer(). Fix.<a name="line.521"></a>
+<span class="sourceLineNo">522</span>    ByteBuff dup = this.buf.duplicate();<a name="line.522"></a>
+<span class="sourceLineNo">523</span>    assert dup.position() == 0;<a name="line.523"></a>
+<span class="sourceLineNo">524</span>    return dup;<a name="line.524"></a>
+<span class="sourceLineNo">525</span>  }<a name="line.525"></a>
+<span class="sourceLineNo">526</span><a name="line.526"></a>
+<span class="sourceLineNo">527</span>  @VisibleForTesting<a name="line.527"></a>
+<span class="sourceLineNo">528</span>  private void sanityCheckAssertion(long valueFromBuf, long valueFromField,<a name="line.528"></a>
+<span class="sourceLineNo">529</span>      String fieldName) throws IOException {<a name="line.529"></a>
+<span class="sourceLineNo">530</span>    if (valueFromBuf != valueFromField) {<a name="line.530"></a>
+<span class="sourceLineNo">531</span>      throw new AssertionError(fieldName + " in the buffer (" + valueFromBuf<a name="line.531"></a>
+<span class="sourceLineNo">532</span>          + ") is different from that in the field (" + valueFromField + ")");<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>  @VisibleForTesting<a name="line.536"></a>
+<span class="sourceLineNo">537</span>  private void sanityCheckAssertion(BlockType valueFromBuf, BlockType valueFromField)<a name="line.537"></a>
+<span class="sourceLineNo">538</span>      throws IOException {<a name="line.538"></a>
+<span class="sourceLineNo">539</span>    if (valueFromBuf != valueFromField) {<a name="line.539"></a>
+<span class="sourceLineNo">540</span>      throw new IOException("Block type stored in the buffer: " +<a name="line.540"></a>
+<span class="sourceLineNo">541</span>        valueFromBuf + ", block type field: " + valueFromField);<a name="line.541"></a>
+<span class="sourceLineNo">542</span>    }<a name="line.542"></a>
+<span class="sourceLineNo">543</span>  }<a name="line.543"></a>
+<span class="sourceLineNo">544</span><a name="line.544"></a>
+<span class="sourceLineNo">545</span>  /**<a name="line.545"></a>
+<span class="sourceLineNo">546</span>   * Checks if the block is internally consistent, i.e. the first<a name="line.546"></a>
+<span class="sourceLineNo">547</span>   * {@link HConstants#HFILEBLOCK_HEADER_SIZE} bytes of the buffer contain a<a name="line.547"></a>
+<span class="sourceLineNo">548</span>   * valid header consistent with the fields. Assumes a packed block structure.<a name="line.548"></a>
+<span class="sourceLineNo">549</span>   * This function is primary for testing and debugging, and is not<a name="line.549"></a>
+<span class="sourceLineNo">550</span>   * thread-safe, because it alters the internal buffer pointer.<a name="line.550"></a>
+<span class="sourceLineNo">551</span>   * Used by tests only.<a name="line.551"></a>
+<span class="sourceLineNo">552</span>   */<a name="line.552"></a>
+<span class="sourceLineNo">553</span>  @VisibleForTesting<a name="line.553"></a>
+<span class="sourceLineNo">554</span>  void sanityCheck() throws IOException {<a name="line.554"></a>
+<span class="sourceLineNo">555</span>    // Duplicate so no side-effects<a name="line.555"></a>
+<span class="sourceLineNo">556</span>    ByteBuff dup = this.buf.duplicate().rewind();<a name="line.556"></a>
+<span class="sourceLineNo">557</span>    sanityCheckAssertion(BlockType.read(dup), blockType);<a name="line.557"></a>
+<span class="sourceLineNo">558</span><a name="line.558"></a>
+<span class="sourceLineNo">559</span>    sanityCheckAssertion(dup.getInt(), onDiskSizeWithoutHeader, "onDiskSizeWithoutHeader");<a name="line.559"></a>
+<span class="sourceLineNo">560</span><a name="line.560"></a>
+<span class="sourceLineNo">561</span>    sanityCheckAssertion(dup.getInt(), uncompressedSizeWithoutHeader,<a name="line.561"></a>
+<span class="sourceLineNo">562</span>        "uncompressedSizeWithoutHeader");<a name="line.562"></a>
+<span class="sourceLineNo">563</span><a name="line.563"></a>
+<span class="sourceLineNo">564</span>    sanityCheckAssertion(dup.getLong(), prevBlockOffset, "prevBlockOffset");<a name="line.564"></a>
+<span class="sourceLineNo">565</span>    if (this.fileContext.isUseHBaseChecksum()) {<a name="line.565"></a>
+<span class="sourceLineNo">566</span>      sanityCheckAssertion(dup.get(), this.fileContext.getChecksumType().getCode(), "checksumType");<a name="line.566"></a>
+<span class="sourceLineNo">567</span>      sanityCheckAssertion(dup.getInt(), this.fileContext.getBytesPerChecksum(),<a name="line.567"></a>
+<span class="sourceLineNo">568</span>          "bytesPerChecksum");<a name="line.568"></a>
+<span class="sourceLineNo">569</span>      sanityCheckAssertion(dup.getInt(), onDiskDataSizeWithHeader, "onDiskDataSizeWithHeader");<a name="line.569"></a>
+<span class="sourceLineNo">570</span>    }<a name="line.570"></a>
+<span class="sourceLineNo">571</span><a name="line.571"></a>
+<span class="sourceLineNo">572</span>    int cksumBytes = totalChecksumBytes();<a name="line.572"></a>
+<span class="sourceLineNo">573</span>    int expectedBufLimit = onDiskDataSizeWithHeader + cksumBytes;<a name="line.573"></a>
+<span class="sourceLineNo">574</span>    if (dup.limit() != expectedBufLimit) {<a name="line.574"></a>
+<span class="sourceLineNo">575</span>      throw new AssertionError("Expected limit " + expectedBufLimit + ", got " + dup.limit());<a name="line.575"></a>
+<span class="sourceLineNo">576</span>    }<a name="line.576"></a>
+<span class="sourceLineNo">577</span><a name="line.577"></a>
+<span class="sourceLineNo">578</span>    // We might optionally allocate HFILEBLOCK_HEADER_SIZE more bytes to read the next<a name="line.578"></a>
+<span class="sourceLineNo">579</span>    // block's header, so there are two sensible values for buffer capacity.<a name="line.579"></a>
+<span class="sourceLineNo">580</span>    int hdrSize = headerSize();<a name="line.580"></a>
+<span class="sourceLineNo">581</span>    if (dup.capacity() != expectedBufLimit &amp;&amp; dup.capacity() != expectedBufLimit + hdrSize) {<a name="line.581"></a>
+<span class="sourceLineNo">582</span>      throw new AssertionError("Invalid buffer capacity: " + dup.capacity() +<a name="line.582"></a>
+<span class="sourceLineNo">583</span>          ", expected " + expectedBufLimit + " or " + (expectedBufLimit + hdrSize));<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>  @Override<a name="line.587"></a>
+<span class="sourceLineNo">588</span>  public String toString() {<a name="line.588"></a>
+<span class="sourceLineNo">589</span>    StringBuilder sb = new StringBuilder()<a name="line.589"></a>
+<span class="sourceLineNo">590</span>      .append("[")<a name="line.590"></a>
+<span class="sourceLineNo">591</span>      .append("blockType=").append(blockType)<a name="line.591"></a>
+<span class="sourceLineNo">592</span>      .append(", fileOffset=").append(offset)<a name="line.592"></a>
+<span class="sourceLineNo">593</span>      .append(", headerSize=").append(headerSize())<a name="line.593"></a>
+<span class="sourceLineNo">594</span>      .append(", onDiskSizeWithoutHeader=").append(onDiskSizeWithoutHeader)<a name="line.594"></a>
+<span class="sourceLineNo">595</span>      .append(", uncompressedSizeWithoutHeader=").append(uncompressedSizeWithoutHeader)<a name="line.595"></a>
+<span class="sourceLineNo">596</span>      .append(", prevBlockOffset=").append(prevBlockOffset)<a name="line.596"></a>
+<span class="sourceLineNo">597</span>      .append(", isUseHBaseChecksum=").append(fileContext.isUseHBaseChecksum());<a name="line.597"></a>
+<span class="sourceLineNo">598</span>    if (fileContext.isUseHBaseChecksum()) {<a name="line.598"></a>
+<span class="sourceLineNo">599</span>      sb.append(", checksumType=").append(ChecksumType.codeToType(this.buf.get(24)))<a name="line.599"></a>
+<span class="sourceLineNo">600</span>        .append(", bytesPerChecksum=").append(this.buf.getInt(24 + 1))<a name="line.600"></a>
+<span class="sourceLineNo">601</span>        .append(", onDiskDataSizeWithHeader=").append(onDiskDataSizeWithHeader);<a name="line.601"></a>
+<span class="sourceLineNo">602</span>    } else {<a name="line.602"></a>
+<span class="sourceLineNo">603</span>      sb.append(", onDiskDataSizeWithHeader=").append(onDiskDataSizeWithHeader)<a name="line.603"></a>
+<span class="sourceLineNo">604</span>        .append("(").append(onDiskSizeWithoutHeader)<a name="line.604"></a>
+<span class="sourceLineNo">605</span>        .append("+").append(HConstants.HFILEBLOCK_HEADER_SIZE_NO_CHECKSUM).append(")");<a name="line.605"></a>
+<span class="sourceLineNo">606</span>    }<a name="line.606"></a>
+<span class="sourceLineNo">607</span>    String dataBegin = null;<a name="line.607"></a>
+<span class="sourceLineNo">608</span>    if (buf.hasArray()) {<a name="line.608"></a>
+<span class="sourceLineNo">609</span>      dataBegin = Bytes.toStringBinary(buf.array(), buf.arrayOffset() + headerSize(),<a name="line.609"></a>
+<span class="sourceLineNo">610</span>          Math.min(32, buf.limit() - buf.arrayOffset() - headerSize()));<a name="line.610"></a>
+<span class="sourceLineNo">611</span>    } else {<a name="line.611"></a>
+<span class="sourceLineNo">612</span>      ByteBuff bufWithoutHeader = getBufferWithoutHeader();<a name="line.612"></a>
+<span class="sourceLineNo">613</span>      byte[] dataBeginBytes = new byte[Math.min(32,<a name="line.613"></a>
+<span class="sourceLineNo">614</span>          bufWithoutHeader.limit() - bufWithoutHeader.position())];<a name="line.614"></a>
+<span class="sourceLineNo">615</span>      bufWithoutHeader.get(dataBeginBytes);<a name="line.615"></a>
+<span class="sourceLineNo">616</span>      dataBegin = Bytes.toStringBinary(dataBeginBytes);<a name="line.616"></a>
+<span class="sourceLineNo">617</span>    }<a name="line.617"></a>
+<span class="sourceLineNo">618</span>    sb.append(", getOnDiskSizeWithHeader=").append(getOnDiskSizeWithHeader())<a name="line.618"></a>
+<span class="sourceLineNo">619</span>      .append(", totalChecksumBytes=").append(totalChecksumBytes())<a name="line.619"></a>
+<span class="sourceLineNo">620</span>      .append(", isUnpacked=").append(isUnpacked())<a name="line.620"></a>
+<span class="sourceLineNo">621</span>      .append(", buf=[").append(buf).append("]")<a name="line.621"></a>
+<span class="sourceLineNo">622</span>      .append(", dataBeginsWith=").append(dataBegin)<a name="line.622"></a>
+<span class="sourceLineNo">623</span>      .append(", fileContext=").append(fileContext)<a name="line.623"></a>
+<span class="sourceLineNo">624</span>      .append(", nextBlockOnDiskSize=").append(nextBlockOnDiskSize)<a name="line.624"></a>
+<span class="sourceLineNo">625</span>      .append("]");<a name="line.625"></a>
+<span class="sourceLineNo">626</span>    return sb.toString();<a name="line.626"></a>
+<span class="sourceLineNo">627</span>  }<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>   * Retrieves the decompressed/decrypted view of this block. An encoded block remains in its<a name="line.630"></a>
+<span class="sourceLineNo">631</span>   * encoded structure. Internal structures are shared between instances where applicable.<a name="line.631"></a>
+<span class="sourceLineNo">632</span>   */<a name="line.632"></a>
+<span class="sourceLineNo">633</span>  HFileBlock unpack(HFileContext fileContext, FSReader reader) throws IOException {<a name="line.633"></a>
+<span class="sourceLineNo">634</span>    if (!fileContext.isCompressedOrEncrypted()) {<a name="line.634"></a>
+<span class="sourceLineNo">635</span>      // TODO: cannot use our own fileContext here because HFileBlock(ByteBuffer, boolean),<a name="line.635"></a>
+<span class="sourceLineNo">636</span>      // which is used for block serialization to L2 cache, does not preserve encoding and<a name="line.636"></a>
+<span class="sourceLineNo">637</span>      // encryption details.<a name="line.637"></a>
+<span class="sourceLineNo">638</span>      return this;<a name="line.638"></a>
+<span class="sourceLineNo">639</span>    }<a name="line.639"></a>
+<span class="sourceLineNo">640</span><a name="line.640"></a>
+<span class="sourceLineNo">641</span>    HFileBlock unpacked = new HFileBlock(this);<a name="line.641"></a>
+<span class="sourceLineNo">642</span>    unpacked.allocateBuffer(); // allocates space for the decompressed block<a name="line.642"></a>
+<span class="sourceLineNo">643</span><a name="line.643"></a>
+<span class="sourceLineNo">644</span>    HFileBlockDecodingContext ctx = blockType == BlockType.ENCODED_DATA ?<a name="line.644"></a>
+<span class="sourceLineNo">645</span>      reader.getBlockDecodingContext() : reader.getDefaultBlockDecodingContext();<a name="line.645"></a>
+<span class="sourceLineNo">646</span><a name="line.646"></a>
+<span class="sourceLineNo">647</span>    ByteBuff dup = this.buf.duplicate();<a name="line.647"></a>
+<span class="sourceLineNo">648</span>    dup.position(this.headerSize());<a name="line.648"></a>
+<span class="sourceLineNo">649</span>    dup = dup.slice();<a name="line.649"></a>
+<span class="sourceLineNo">650</span>    ctx.prepareDecodi

<TRUNCATED>

[39/50] hbase-site git commit: Published site at 26babcf013de696b899d76a3c39434b794440d8d.

Posted by gi...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.BlockIterator.html
----------------------------------------------------------------------
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.BlockIterator.html b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.BlockIterator.html
index 97ceefd..b7b4236 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.BlockIterator.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.BlockIterator.html
@@ -103,8 +103,8 @@
 <span class="sourceLineNo">095</span> * Caches cache whole blocks with trailing checksums if any. We then tag on some metadata, the<a name="line.95"></a>
 <span class="sourceLineNo">096</span> * content of BLOCK_METADATA_SPACE which will be flag on if we are doing 'hbase'<a name="line.96"></a>
 <span class="sourceLineNo">097</span> * checksums and then the offset into the file which is needed when we re-make a cache key<a name="line.97"></a>
-<span class="sourceLineNo">098</span> * when we return the block to the cache as 'done'. See {@link Cacheable#serialize(ByteBuffer)} and<a name="line.98"></a>
-<span class="sourceLineNo">099</span> * {@link Cacheable#getDeserializer()}.<a name="line.99"></a>
+<span class="sourceLineNo">098</span> * when we return the block to the cache as 'done'.<a name="line.98"></a>
+<span class="sourceLineNo">099</span> * See {@link Cacheable#serialize(ByteBuffer, boolean)} and {@link Cacheable#getDeserializer()}.<a name="line.99"></a>
 <span class="sourceLineNo">100</span> *<a name="line.100"></a>
 <span class="sourceLineNo">101</span> * &lt;p&gt;TODO: Should we cache the checksums? Down in Writer#getBlockForCaching(CacheConfig) where<a name="line.101"></a>
 <span class="sourceLineNo">102</span> * we make a block to cache-on-write, there is an attempt at turning off checksums. This is not the<a name="line.102"></a>
@@ -333,1579 +333,1579 @@
 <span class="sourceLineNo">325</span>   * Creates a new {@link HFile} block from the given fields. This constructor<a name="line.325"></a>
 <span class="sourceLineNo">326</span>   * is used only while writing blocks and caching,<a name="line.326"></a>
 <span class="sourceLineNo">327</span>   * and is sitting in a byte buffer and we want to stuff the block into cache.<a name="line.327"></a>
-<span class="sourceLineNo">328</span>   * See {@link Writer#getBlockForCaching(CacheConfig)}.<a name="line.328"></a>
-<span class="sourceLineNo">329</span>   *<a name="line.329"></a>
-<span class="sourceLineNo">330</span>   * &lt;p&gt;TODO: The caller presumes no checksumming<a name="line.330"></a>
-<span class="sourceLineNo">331</span>   * required of this block instance since going into cache; checksum already verified on<a name="line.331"></a>
-<span class="sourceLineNo">332</span>   * underlying block data pulled in from filesystem. Is that correct? What if cache is SSD?<a name="line.332"></a>
-<span class="sourceLineNo">333</span>   *<a name="line.333"></a>
-<span class="sourceLineNo">334</span>   * @param blockType the type of this block, see {@link BlockType}<a name="line.334"></a>
-<span class="sourceLineNo">335</span>   * @param onDiskSizeWithoutHeader see {@link #onDiskSizeWithoutHeader}<a name="line.335"></a>
-<span class="sourceLineNo">336</span>   * @param uncompressedSizeWithoutHeader see {@link #uncompressedSizeWithoutHeader}<a name="line.336"></a>
-<span class="sourceLineNo">337</span>   * @param prevBlockOffset see {@link #prevBlockOffset}<a name="line.337"></a>
-<span class="sourceLineNo">338</span>   * @param b block header ({@link HConstants#HFILEBLOCK_HEADER_SIZE} bytes)<a name="line.338"></a>
-<span class="sourceLineNo">339</span>   * @param fillHeader when true, write the first 4 header fields into passed buffer.<a name="line.339"></a>
-<span class="sourceLineNo">340</span>   * @param offset the file offset the block was read from<a name="line.340"></a>
-<span class="sourceLineNo">341</span>   * @param onDiskDataSizeWithHeader see {@link #onDiskDataSizeWithHeader}<a name="line.341"></a>
-<span class="sourceLineNo">342</span>   * @param fileContext HFile meta data<a name="line.342"></a>
-<span class="sourceLineNo">343</span>   */<a name="line.343"></a>
-<span class="sourceLineNo">344</span>  HFileBlock(BlockType blockType, int onDiskSizeWithoutHeader, int uncompressedSizeWithoutHeader,<a name="line.344"></a>
-<span class="sourceLineNo">345</span>      long prevBlockOffset, ByteBuffer b, boolean fillHeader, long offset,<a name="line.345"></a>
-<span class="sourceLineNo">346</span>      final int nextBlockOnDiskSize, int onDiskDataSizeWithHeader, HFileContext fileContext) {<a name="line.346"></a>
-<span class="sourceLineNo">347</span>    init(blockType, onDiskSizeWithoutHeader, uncompressedSizeWithoutHeader,<a name="line.347"></a>
-<span class="sourceLineNo">348</span>        prevBlockOffset, offset, onDiskDataSizeWithHeader, nextBlockOnDiskSize, fileContext);<a name="line.348"></a>
-<span class="sourceLineNo">349</span>    this.buf = new SingleByteBuff(b);<a name="line.349"></a>
-<span class="sourceLineNo">350</span>    if (fillHeader) {<a name="line.350"></a>
-<span class="sourceLineNo">351</span>      overwriteHeader();<a name="line.351"></a>
-<span class="sourceLineNo">352</span>    }<a name="line.352"></a>
-<span class="sourceLineNo">353</span>    this.buf.rewind();<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>  /**<a name="line.356"></a>
-<span class="sourceLineNo">357</span>   * Creates a block from an existing buffer starting with a header. Rewinds<a name="line.357"></a>
-<span class="sourceLineNo">358</span>   * and takes ownership of the buffer. By definition of rewind, ignores the<a name="line.358"></a>
-<span class="sourceLineNo">359</span>   * buffer position, but if you slice the buffer beforehand, it will rewind<a name="line.359"></a>
-<span class="sourceLineNo">360</span>   * to that point.<a name="line.360"></a>
-<span class="sourceLineNo">361</span>   * @param buf Has header, content, and trailing checksums if present.<a name="line.361"></a>
-<span class="sourceLineNo">362</span>   */<a name="line.362"></a>
-<span class="sourceLineNo">363</span>  HFileBlock(ByteBuff buf, boolean usesHBaseChecksum, MemoryType memType, final long offset,<a name="line.363"></a>
-<span class="sourceLineNo">364</span>      final int nextBlockOnDiskSize, HFileContext fileContext) throws IOException {<a name="line.364"></a>
-<span class="sourceLineNo">365</span>    buf.rewind();<a name="line.365"></a>
-<span class="sourceLineNo">366</span>    final BlockType blockType = BlockType.read(buf);<a name="line.366"></a>
-<span class="sourceLineNo">367</span>    final int onDiskSizeWithoutHeader = buf.getInt(Header.ON_DISK_SIZE_WITHOUT_HEADER_INDEX);<a name="line.367"></a>
-<span class="sourceLineNo">368</span>    final int uncompressedSizeWithoutHeader =<a name="line.368"></a>
-<span class="sourceLineNo">369</span>        buf.getInt(Header.UNCOMPRESSED_SIZE_WITHOUT_HEADER_INDEX);<a name="line.369"></a>
-<span class="sourceLineNo">370</span>    final long prevBlockOffset = buf.getLong(Header.PREV_BLOCK_OFFSET_INDEX);<a name="line.370"></a>
-<span class="sourceLineNo">371</span>    // This constructor is called when we deserialize a block from cache and when we read a block in<a name="line.371"></a>
-<span class="sourceLineNo">372</span>    // from the fs. fileCache is null when deserialized from cache so need to make up one.<a name="line.372"></a>
-<span class="sourceLineNo">373</span>    HFileContextBuilder fileContextBuilder = fileContext != null?<a name="line.373"></a>
-<span class="sourceLineNo">374</span>        new HFileContextBuilder(fileContext): new HFileContextBuilder();<a name="line.374"></a>
-<span class="sourceLineNo">375</span>    fileContextBuilder.withHBaseCheckSum(usesHBaseChecksum);<a name="line.375"></a>
-<span class="sourceLineNo">376</span>    int onDiskDataSizeWithHeader;<a name="line.376"></a>
-<span class="sourceLineNo">377</span>    if (usesHBaseChecksum) {<a name="line.377"></a>
-<span class="sourceLineNo">378</span>      byte checksumType = buf.get(Header.CHECKSUM_TYPE_INDEX);<a name="line.378"></a>
-<span class="sourceLineNo">379</span>      int bytesPerChecksum = buf.getInt(Header.BYTES_PER_CHECKSUM_INDEX);<a name="line.379"></a>
-<span class="sourceLineNo">380</span>      onDiskDataSizeWithHeader = buf.getInt(Header.ON_DISK_DATA_SIZE_WITH_HEADER_INDEX);<a name="line.380"></a>
-<span class="sourceLineNo">381</span>      // Use the checksum type and bytes per checksum from header, not from filecontext.<a name="line.381"></a>
-<span class="sourceLineNo">382</span>      fileContextBuilder.withChecksumType(ChecksumType.codeToType(checksumType));<a name="line.382"></a>
-<span class="sourceLineNo">383</span>      fileContextBuilder.withBytesPerCheckSum(bytesPerChecksum);<a name="line.383"></a>
-<span class="sourceLineNo">384</span>    } else {<a name="line.384"></a>
-<span class="sourceLineNo">385</span>      fileContextBuilder.withChecksumType(ChecksumType.NULL);<a name="line.385"></a>
-<span class="sourceLineNo">386</span>      fileContextBuilder.withBytesPerCheckSum(0);<a name="line.386"></a>
-<span class="sourceLineNo">387</span>      // Need to fix onDiskDataSizeWithHeader; there are not checksums after-block-data<a name="line.387"></a>
-<span class="sourceLineNo">388</span>      onDiskDataSizeWithHeader = onDiskSizeWithoutHeader + headerSize(usesHBaseChecksum);<a name="line.388"></a>
-<span class="sourceLineNo">389</span>    }<a name="line.389"></a>
-<span class="sourceLineNo">390</span>    fileContext = fileContextBuilder.build();<a name="line.390"></a>
-<span class="sourceLineNo">391</span>    assert usesHBaseChecksum == fileContext.isUseHBaseChecksum();<a name="line.391"></a>
-<span class="sourceLineNo">392</span>    init(blockType, onDiskSizeWithoutHeader, uncompressedSizeWithoutHeader,<a name="line.392"></a>
-<span class="sourceLineNo">393</span>        prevBlockOffset, offset, onDiskDataSizeWithHeader, nextBlockOnDiskSize, fileContext);<a name="line.393"></a>
-<span class="sourceLineNo">394</span>    this.memType = memType;<a name="line.394"></a>
-<span class="sourceLineNo">395</span>    this.offset = offset;<a name="line.395"></a>
-<span class="sourceLineNo">396</span>    this.buf = buf;<a name="line.396"></a>
-<span class="sourceLineNo">397</span>    this.buf.rewind();<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>  /**<a name="line.400"></a>
-<span class="sourceLineNo">401</span>   * Called from constructors.<a name="line.401"></a>
-<span class="sourceLineNo">402</span>   */<a name="line.402"></a>
-<span class="sourceLineNo">403</span>  private void init(BlockType blockType, int onDiskSizeWithoutHeader,<a name="line.403"></a>
-<span class="sourceLineNo">404</span>      int uncompressedSizeWithoutHeader, long prevBlockOffset,<a name="line.404"></a>
-<span class="sourceLineNo">405</span>      long offset, int onDiskDataSizeWithHeader, final int nextBlockOnDiskSize,<a name="line.405"></a>
-<span class="sourceLineNo">406</span>      HFileContext fileContext) {<a name="line.406"></a>
-<span class="sourceLineNo">407</span>    this.blockType = blockType;<a name="line.407"></a>
-<span class="sourceLineNo">408</span>    this.onDiskSizeWithoutHeader = onDiskSizeWithoutHeader;<a name="line.408"></a>
-<span class="sourceLineNo">409</span>    this.uncompressedSizeWithoutHeader = uncompressedSizeWithoutHeader;<a name="line.409"></a>
-<span class="sourceLineNo">410</span>    this.prevBlockOffset = prevBlockOffset;<a name="line.410"></a>
-<span class="sourceLineNo">411</span>    this.offset = offset;<a name="line.411"></a>
-<span class="sourceLineNo">412</span>    this.onDiskDataSizeWithHeader = onDiskDataSizeWithHeader;<a name="line.412"></a>
-<span class="sourceLineNo">413</span>    this.nextBlockOnDiskSize = nextBlockOnDiskSize;<a name="line.413"></a>
-<span class="sourceLineNo">414</span>    this.fileContext = fileContext;<a name="line.414"></a>
-<span class="sourceLineNo">415</span>  }<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">418</span>   * Parse total on disk size including header and checksum.<a name="line.418"></a>
-<span class="sourceLineNo">419</span>   * @param headerBuf Header ByteBuffer. Presumed exact size of header.<a name="line.419"></a>
-<span class="sourceLineNo">420</span>   * @param verifyChecksum true if checksum verification is in use.<a name="line.420"></a>
-<span class="sourceLineNo">421</span>   * @return Size of the block with header included.<a name="line.421"></a>
-<span class="sourceLineNo">422</span>   */<a name="line.422"></a>
-<span class="sourceLineNo">423</span>  private static int getOnDiskSizeWithHeader(final ByteBuffer headerBuf,<a name="line.423"></a>
-<span class="sourceLineNo">424</span>      boolean verifyChecksum) {<a name="line.424"></a>
-<span class="sourceLineNo">425</span>    return headerBuf.getInt(Header.ON_DISK_SIZE_WITHOUT_HEADER_INDEX) +<a name="line.425"></a>
-<span class="sourceLineNo">426</span>      headerSize(verifyChecksum);<a name="line.426"></a>
-<span class="sourceLineNo">427</span>  }<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>   * @return the on-disk size of the next block (including the header size and any checksums if<a name="line.430"></a>
-<span class="sourceLineNo">431</span>   * present) read by peeking into the next block's header; use as a hint when doing<a name="line.431"></a>
-<span class="sourceLineNo">432</span>   * a read of the next block when scanning or running over a file.<a name="line.432"></a>
-<span class="sourceLineNo">433</span>   */<a name="line.433"></a>
-<span class="sourceLineNo">434</span>  int getNextBlockOnDiskSize() {<a name="line.434"></a>
-<span class="sourceLineNo">435</span>    return nextBlockOnDiskSize;<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>  @Override<a name="line.438"></a>
-<span class="sourceLineNo">439</span>  public BlockType getBlockType() {<a name="line.439"></a>
-<span class="sourceLineNo">440</span>    return blockType;<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>  /** @return get data block encoding id that was used to encode this block */<a name="line.443"></a>
-<span class="sourceLineNo">444</span>  short getDataBlockEncodingId() {<a name="line.444"></a>
-<span class="sourceLineNo">445</span>    if (blockType != BlockType.ENCODED_DATA) {<a name="line.445"></a>
-<span class="sourceLineNo">446</span>      throw new IllegalArgumentException("Querying encoder ID of a block " +<a name="line.446"></a>
-<span class="sourceLineNo">447</span>          "of type other than " + BlockType.ENCODED_DATA + ": " + blockType);<a name="line.447"></a>
-<span class="sourceLineNo">448</span>    }<a name="line.448"></a>
-<span class="sourceLineNo">449</span>    return buf.getShort(headerSize());<a name="line.449"></a>
-<span class="sourceLineNo">450</span>  }<a name="line.450"></a>
-<span class="sourceLineNo">451</span><a name="line.451"></a>
-<span class="sourceLineNo">452</span>  /**<a name="line.452"></a>
-<span class="sourceLineNo">453</span>   * @return the on-disk size of header + data part + checksum.<a name="line.453"></a>
-<span class="sourceLineNo">454</span>   */<a name="line.454"></a>
-<span class="sourceLineNo">455</span>  public int getOnDiskSizeWithHeader() {<a name="line.455"></a>
-<span class="sourceLineNo">456</span>    return onDiskSizeWithoutHeader + headerSize();<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>   * @return the on-disk size of the data part + checksum (header excluded).<a name="line.460"></a>
-<span class="sourceLineNo">461</span>   */<a name="line.461"></a>
-<span class="sourceLineNo">462</span>  int getOnDiskSizeWithoutHeader() {<a name="line.462"></a>
-<span class="sourceLineNo">463</span>    return onDiskSizeWithoutHeader;<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>  /**<a name="line.466"></a>
-<span class="sourceLineNo">467</span>   * @return the uncompressed size of data part (header and checksum excluded).<a name="line.467"></a>
-<span class="sourceLineNo">468</span>   */<a name="line.468"></a>
-<span class="sourceLineNo">469</span>   int getUncompressedSizeWithoutHeader() {<a name="line.469"></a>
-<span class="sourceLineNo">470</span>    return uncompressedSizeWithoutHeader;<a name="line.470"></a>
-<span class="sourceLineNo">471</span>  }<a name="line.471"></a>
-<span class="sourceLineNo">472</span><a name="line.472"></a>
-<span class="sourceLineNo">473</span>  /**<a name="line.473"></a>
-<span class="sourceLineNo">474</span>   * @return the offset of the previous block of the same type in the file, or<a name="line.474"></a>
-<span class="sourceLineNo">475</span>   *         -1 if unknown<a name="line.475"></a>
-<span class="sourceLineNo">476</span>   */<a name="line.476"></a>
-<span class="sourceLineNo">477</span>  long getPrevBlockOffset() {<a name="line.477"></a>
-<span class="sourceLineNo">478</span>    return prevBlockOffset;<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>   * Rewinds {@code buf} and writes first 4 header fields. {@code buf} position<a name="line.482"></a>
-<span class="sourceLineNo">483</span>   * is modified as side-effect.<a name="line.483"></a>
-<span class="sourceLineNo">484</span>   */<a name="line.484"></a>
-<span class="sourceLineNo">485</span>  private void overwriteHeader() {<a name="line.485"></a>
-<span class="sourceLineNo">486</span>    buf.rewind();<a name="line.486"></a>
-<span class="sourceLineNo">487</span>    blockType.write(buf);<a name="line.487"></a>
-<span class="sourceLineNo">488</span>    buf.putInt(onDiskSizeWithoutHeader);<a name="line.488"></a>
-<span class="sourceLineNo">489</span>    buf.putInt(uncompressedSizeWithoutHeader);<a name="line.489"></a>
-<span class="sourceLineNo">490</span>    buf.putLong(prevBlockOffset);<a name="line.490"></a>
-<span class="sourceLineNo">491</span>    if (this.fileContext.isUseHBaseChecksum()) {<a name="line.491"></a>
-<span class="sourceLineNo">492</span>      buf.put(fileContext.getChecksumType().getCode());<a name="line.492"></a>
-<span class="sourceLineNo">493</span>      buf.putInt(fileContext.getBytesPerChecksum());<a name="line.493"></a>
-<span class="sourceLineNo">494</span>      buf.putInt(onDiskDataSizeWithHeader);<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>  /**<a name="line.498"></a>
-<span class="sourceLineNo">499</span>   * Returns a buffer that does not include the header or checksum.<a name="line.499"></a>
-<span class="sourceLineNo">500</span>   *<a name="line.500"></a>
-<span class="sourceLineNo">501</span>   * @return the buffer with header skipped and checksum omitted.<a name="line.501"></a>
-<span class="sourceLineNo">502</span>   */<a name="line.502"></a>
-<span class="sourceLineNo">503</span>  public ByteBuff getBufferWithoutHeader() {<a name="line.503"></a>
-<span class="sourceLineNo">504</span>    ByteBuff dup = getBufferReadOnly();<a name="line.504"></a>
-<span class="sourceLineNo">505</span>    // Now set it up so Buffer spans content only -- no header or no checksums.<a name="line.505"></a>
-<span class="sourceLineNo">506</span>    return dup.position(headerSize()).limit(buf.limit() - totalChecksumBytes()).slice();<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 a read-only duplicate of the buffer this block stores internally ready to be read.<a name="line.510"></a>
-<span class="sourceLineNo">511</span>   * Clients must not modify the buffer object though they may set position and limit on the<a name="line.511"></a>
-<span class="sourceLineNo">512</span>   * returned buffer since we pass back a duplicate. This method has to be public because it is used<a name="line.512"></a>
-<span class="sourceLineNo">513</span>   * in {@link CompoundBloomFilter} to avoid object creation on every Bloom<a name="line.513"></a>
-<span class="sourceLineNo">514</span>   * filter lookup, but has to be used with caution. Buffer holds header, block content,<a name="line.514"></a>
-<span class="sourceLineNo">515</span>   * and any follow-on checksums if present.<a name="line.515"></a>
-<span class="sourceLineNo">516</span>   *<a name="line.516"></a>
-<span class="sourceLineNo">517</span>   * @return the buffer of this block for read-only operations<a name="line.517"></a>
-<span class="sourceLineNo">518</span>   */<a name="line.518"></a>
-<span class="sourceLineNo">519</span>  public ByteBuff getBufferReadOnly() {<a name="line.519"></a>
-<span class="sourceLineNo">520</span>    // TODO: ByteBuf does not support asReadOnlyBuffer(). Fix.<a name="line.520"></a>
-<span class="sourceLineNo">521</span>    ByteBuff dup = this.buf.duplicate();<a name="line.521"></a>
-<span class="sourceLineNo">522</span>    assert dup.position() == 0;<a name="line.522"></a>
-<span class="sourceLineNo">523</span>    return dup;<a name="line.523"></a>
-<span class="sourceLineNo">524</span>  }<a name="line.524"></a>
-<span class="sourceLineNo">525</span><a name="line.525"></a>
-<span class="sourceLineNo">526</span>  @VisibleForTesting<a name="line.526"></a>
-<span class="sourceLineNo">527</span>  private void sanityCheckAssertion(long valueFromBuf, long valueFromField,<a name="line.527"></a>
-<span class="sourceLineNo">528</span>      String fieldName) throws IOException {<a name="line.528"></a>
-<span class="sourceLineNo">529</span>    if (valueFromBuf != valueFromField) {<a name="line.529"></a>
-<span class="sourceLineNo">530</span>      throw new AssertionError(fieldName + " in the buffer (" + valueFromBuf<a name="line.530"></a>
-<span class="sourceLineNo">531</span>          + ") is different from that in the field (" + valueFromField + ")");<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>  @VisibleForTesting<a name="line.535"></a>
-<span class="sourceLineNo">536</span>  private void sanityCheckAssertion(BlockType valueFromBuf, BlockType valueFromField)<a name="line.536"></a>
-<span class="sourceLineNo">537</span>      throws IOException {<a name="line.537"></a>
-<span class="sourceLineNo">538</span>    if (valueFromBuf != valueFromField) {<a name="line.538"></a>
-<span class="sourceLineNo">539</span>      throw new IOException("Block type stored in the buffer: " +<a name="line.539"></a>
-<span class="sourceLineNo">540</span>        valueFromBuf + ", block type field: " + valueFromField);<a name="line.540"></a>
-<span class="sourceLineNo">541</span>    }<a name="line.541"></a>
-<span class="sourceLineNo">542</span>  }<a name="line.542"></a>
-<span class="sourceLineNo">543</span><a name="line.543"></a>
-<span class="sourceLineNo">544</span>  /**<a name="line.544"></a>
-<span class="sourceLineNo">545</span>   * Checks if the block is internally consistent, i.e. the first<a name="line.545"></a>
-<span class="sourceLineNo">546</span>   * {@link HConstants#HFILEBLOCK_HEADER_SIZE} bytes of the buffer contain a<a name="line.546"></a>
-<span class="sourceLineNo">547</span>   * valid header consistent with the fields. Assumes a packed block structure.<a name="line.547"></a>
-<span class="sourceLineNo">548</span>   * This function is primary for testing and debugging, and is not<a name="line.548"></a>
-<span class="sourceLineNo">549</span>   * thread-safe, because it alters the internal buffer pointer.<a name="line.549"></a>
-<span class="sourceLineNo">550</span>   * Used by tests only.<a name="line.550"></a>
-<span class="sourceLineNo">551</span>   */<a name="line.551"></a>
-<span class="sourceLineNo">552</span>  @VisibleForTesting<a name="line.552"></a>
-<span class="sourceLineNo">553</span>  void sanityCheck() throws IOException {<a name="line.553"></a>
-<span class="sourceLineNo">554</span>    // Duplicate so no side-effects<a name="line.554"></a>
-<span class="sourceLineNo">555</span>    ByteBuff dup = this.buf.duplicate().rewind();<a name="line.555"></a>
-<span class="sourceLineNo">556</span>    sanityCheckAssertion(BlockType.read(dup), blockType);<a name="line.556"></a>
-<span class="sourceLineNo">557</span><a name="line.557"></a>
-<span class="sourceLineNo">558</span>    sanityCheckAssertion(dup.getInt(), onDiskSizeWithoutHeader, "onDiskSizeWithoutHeader");<a name="line.558"></a>
-<span class="sourceLineNo">559</span><a name="line.559"></a>
-<span class="sourceLineNo">560</span>    sanityCheckAssertion(dup.getInt(), uncompressedSizeWithoutHeader,<a name="line.560"></a>
-<span class="sourceLineNo">561</span>        "uncompressedSizeWithoutHeader");<a name="line.561"></a>
-<span class="sourceLineNo">562</span><a name="line.562"></a>
-<span class="sourceLineNo">563</span>    sanityCheckAssertion(dup.getLong(), prevBlockOffset, "prevBlockOffset");<a name="line.563"></a>
-<span class="sourceLineNo">564</span>    if (this.fileContext.isUseHBaseChecksum()) {<a name="line.564"></a>
-<span class="sourceLineNo">565</span>      sanityCheckAssertion(dup.get(), this.fileContext.getChecksumType().getCode(), "checksumType");<a name="line.565"></a>
-<span class="sourceLineNo">566</span>      sanityCheckAssertion(dup.getInt(), this.fileContext.getBytesPerChecksum(),<a name="line.566"></a>
-<span class="sourceLineNo">567</span>          "bytesPerChecksum");<a name="line.567"></a>
-<span class="sourceLineNo">568</span>      sanityCheckAssertion(dup.getInt(), onDiskDataSizeWithHeader, "onDiskDataSizeWithHeader");<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>    int cksumBytes = totalChecksumBytes();<a name="line.571"></a>
-<span class="sourceLineNo">572</span>    int expectedBufLimit = onDiskDataSizeWithHeader + cksumBytes;<a name="line.572"></a>
-<span class="sourceLineNo">573</span>    if (dup.limit() != expectedBufLimit) {<a name="line.573"></a>
-<span class="sourceLineNo">574</span>      throw new AssertionError("Expected limit " + expectedBufLimit + ", got " + dup.limit());<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>    // We might optionally allocate HFILEBLOCK_HEADER_SIZE more bytes to read the next<a name="line.577"></a>
-<span class="sourceLineNo">578</span>    // block's header, so there are two sensible values for buffer capacity.<a name="line.578"></a>
-<span class="sourceLineNo">579</span>    int hdrSize = headerSize();<a name="line.579"></a>
-<span class="sourceLineNo">580</span>    if (dup.capacity() != expectedBufLimit &amp;&amp; dup.capacity() != expectedBufLimit + hdrSize) {<a name="line.580"></a>
-<span class="sourceLineNo">581</span>      throw new AssertionError("Invalid buffer capacity: " + dup.capacity() +<a name="line.581"></a>
-<span class="sourceLineNo">582</span>          ", expected " + expectedBufLimit + " or " + (expectedBufLimit + hdrSize));<a name="line.582"></a>
-<span class="sourceLineNo">583</span>    }<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>  @Override<a name="line.586"></a>
-<span class="sourceLineNo">587</span>  public String toString() {<a name="line.587"></a>
-<span class="sourceLineNo">588</span>    StringBuilder sb = new StringBuilder()<a name="line.588"></a>
-<span class="sourceLineNo">589</span>      .append("[")<a name="line.589"></a>
-<span class="sourceLineNo">590</span>      .append("blockType=").append(blockType)<a name="line.590"></a>
-<span class="sourceLineNo">591</span>      .append(", fileOffset=").append(offset)<a name="line.591"></a>
-<span class="sourceLineNo">592</span>      .append(", headerSize=").append(headerSize())<a name="line.592"></a>
-<span class="sourceLineNo">593</span>      .append(", onDiskSizeWithoutHeader=").append(onDiskSizeWithoutHeader)<a name="line.593"></a>
-<span class="sourceLineNo">594</span>      .append(", uncompressedSizeWithoutHeader=").append(uncompressedSizeWithoutHeader)<a name="line.594"></a>
-<span class="sourceLineNo">595</span>      .append(", prevBlockOffset=").append(prevBlockOffset)<a name="line.595"></a>
-<span class="sourceLineNo">596</span>      .append(", isUseHBaseChecksum=").append(fileContext.isUseHBaseChecksum());<a name="line.596"></a>
-<span class="sourceLineNo">597</span>    if (fileContext.isUseHBaseChecksum()) {<a name="line.597"></a>
-<span class="sourceLineNo">598</span>      sb.append(", checksumType=").append(ChecksumType.codeToType(this.buf.get(24)))<a name="line.598"></a>
-<span class="sourceLineNo">599</span>        .append(", bytesPerChecksum=").append(this.buf.getInt(24 + 1))<a name="line.599"></a>
-<span class="sourceLineNo">600</span>        .append(", onDiskDataSizeWithHeader=").append(onDiskDataSizeWithHeader);<a name="line.600"></a>
-<span class="sourceLineNo">601</span>    } else {<a name="line.601"></a>
-<span class="sourceLineNo">602</span>      sb.append(", onDiskDataSizeWithHeader=").append(onDiskDataSizeWithHeader)<a name="line.602"></a>
-<span class="sourceLineNo">603</span>        .append("(").append(onDiskSizeWithoutHeader)<a name="line.603"></a>
-<span class="sourceLineNo">604</span>        .append("+").append(HConstants.HFILEBLOCK_HEADER_SIZE_NO_CHECKSUM).append(")");<a name="line.604"></a>
-<span class="sourceLineNo">605</span>    }<a name="line.605"></a>
-<span class="sourceLineNo">606</span>    String dataBegin = null;<a name="line.606"></a>
-<span class="sourceLineNo">607</span>    if (buf.hasArray()) {<a name="line.607"></a>
-<span class="sourceLineNo">608</span>      dataBegin = Bytes.toStringBinary(buf.array(), buf.arrayOffset() + headerSize(),<a name="line.608"></a>
-<span class="sourceLineNo">609</span>          Math.min(32, buf.limit() - buf.arrayOffset() - headerSize()));<a name="line.609"></a>
-<span class="sourceLineNo">610</span>    } else {<a name="line.610"></a>
-<span class="sourceLineNo">611</span>      ByteBuff bufWithoutHeader = getBufferWithoutHeader();<a name="line.611"></a>
-<span class="sourceLineNo">612</span>      byte[] dataBeginBytes = new byte[Math.min(32,<a name="line.612"></a>
-<span class="sourceLineNo">613</span>          bufWithoutHeader.limit() - bufWithoutHeader.position())];<a name="line.613"></a>
-<span class="sourceLineNo">614</span>      bufWithoutHeader.get(dataBeginBytes);<a name="line.614"></a>
-<span class="sourceLineNo">615</span>      dataBegin = Bytes.toStringBinary(dataBeginBytes);<a name="line.615"></a>
-<span class="sourceLineNo">616</span>    }<a name="line.616"></a>
-<span class="sourceLineNo">617</span>    sb.append(", getOnDiskSizeWithHeader=").append(getOnDiskSizeWithHeader())<a name="line.617"></a>
-<span class="sourceLineNo">618</span>      .append(", totalChecksumBytes=").append(totalChecksumBytes())<a name="line.618"></a>
-<span class="sourceLineNo">619</span>      .append(", isUnpacked=").append(isUnpacked())<a name="line.619"></a>
-<span class="sourceLineNo">620</span>      .append(", buf=[").append(buf).append("]")<a name="line.620"></a>
-<span class="sourceLineNo">621</span>      .append(", dataBeginsWith=").append(dataBegin)<a name="line.621"></a>
-<span class="sourceLineNo">622</span>      .append(", fileContext=").append(fileContext)<a name="line.622"></a>
-<span class="sourceLineNo">623</span>      .append("]");<a name="line.623"></a>
-<span class="sourceLineNo">624</span>    return sb.toString();<a name="line.624"></a>
-<span class="sourceLineNo">625</span>  }<a name="line.625"></a>
-<span class="sourceLineNo">626</span><a name="line.626"></a>
-<span class="sourceLineNo">627</span>  /**<a name="line.627"></a>
-<span class="sourceLineNo">628</span>   * Retrieves the decompressed/decrypted view of this block. An encoded block remains in its<a name="line.628"></a>
-<span class="sourceLineNo">629</span>   * encoded structure. Internal structures are shared between instances where applicable.<a name="line.629"></a>
-<span class="sourceLineNo">630</span>   */<a name="line.630"></a>
-<span class="sourceLineNo">631</span>  HFileBlock unpack(HFileContext fileContext, FSReader reader) throws IOException {<a name="line.631"></a>
-<span class="sourceLineNo">632</span>    if (!fileContext.isCompressedOrEncrypted()) {<a name="line.632"></a>
-<span class="sourceLineNo">633</span>      // TODO: cannot use our own fileContext here because HFileBlock(ByteBuffer, boolean),<a name="line.633"></a>
-<span class="sourceLineNo">634</span>      // which is used for block serialization to L2 cache, does not preserve encoding and<a name="line.634"></a>
-<span class="sourceLineNo">635</span>      // encryption details.<a name="line.635"></a>
-<span class="sourceLineNo">636</span>      return this;<a name="line.636"></a>
-<span class="sourceLineNo">637</span>    }<a name="line.637"></a>
-<span class="sourceLineNo">638</span><a name="line.638"></a>
-<span class="sourceLineNo">639</span>    HFileBlock unpacked = new HFileBlock(this);<a name="line.639"></a>
-<span class="sourceLineNo">640</span>    unpacked.allocateBuffer(); // allocates space for the decompressed block<a name="line.640"></a>
-<span class="sourceLineNo">641</span><a name="line.641"></a>
-<span class="sourceLineNo">642</span>    HFileBlockDecodingContext ctx = blockType == BlockType.ENCODED_DATA ?<a name="line.642"></a>
-<span class="sourceLineNo">643</span>      reader.getBlockDecodingContext() : reader.getDefaultBlockDecodingContext();<a name="line.643"></a>
-<span class="sourceLineNo">644</span><a name="line.644"></a>
-<span class="sourceLineNo">645</span>    ByteBuff dup = this.buf.duplicate();<a name="line.645"></a>
-<span class="sourceLineNo">646</span>    dup.position(this.headerSize());<a name="line.646"></a>
-<span class="sourceLineNo">647</span>    dup = dup.slice();<a name="line.647"></a>
-<span class="sourceLineNo">648</span>    ctx.prepareDecoding(unpacked.getOnDiskSizeWithoutHeader(),<a name="line.648"></a>
-<span class="sourceLineNo">649</span>      unpacked.getUncompressedSizeWithoutHeader(), unpacked.getBufferWithoutHeader(),<a name="line.649"></a>
-<span class="sourceLineNo">650</span>      dup);<a name="line.650"></a>
-<span class="sourceLineNo">651</span>    return unpacked;<a name="line.651"></a>
-<span class="sourceLineNo">652</span>  }<a name="line.652"></a>
-<span class="sourceLineNo">653</span><a name="line.653"></a>
-<span class="sourceLineNo">654</span>  /**<a name="line.654"></a>
-<span class="sourceLineNo">655</span>   * Always allocates a new buffer of the correct size. Copies header bytes<a name="line.655"></a>
-<span class="sourceLineNo">656</span>   * from the existing buffer. Does not change header fields.<a name="line.656"></a>
-<span class="sourceLineNo">657</span>   * Reserve room to keep checksum bytes too.<a name="line.657"></a>
-<span class="sourceLineNo">658</span>   */<a name="line.658"></a>
-<span class="sourceLineNo">659</span>  private void allocateBuffer() {<a name="line.659"></a>
-<span class="sourceLineNo">660</span>    int cksumBytes = totalChecksumBytes();<a name="line.660"></a>
-<span class="sourceLineNo">661</span>    int headerSize = headerSize();<a name="line.661"></a>
-<span class="sourceLineNo">662</span>    int capacityNeeded = headerSize + uncompressedSizeWithoutHeader + cksumBytes;<a name="line.662"></a>
-<span class="sourceLineNo">663</span><a name="line.663"></a>
-<span class="sourceLineNo">664</span>    // TODO we need consider allocating offheap here?<a name="line.664"></a>
-<span class="sourceLineNo">665</span>    ByteBuffer newBuf = ByteBuffer.allocate(capacityNeeded);<a name="line.665"></a>
-<span class="sourceLineNo">666</span><a name="line.666"></a>
-<span class="sourceLineNo">667</span>    // Copy header bytes into newBuf.<a name="line.667"></a>
-<span class="sourceLineNo">668</span>    // newBuf is HBB so no issue in calling array()<a name="line.668"></a>
-<span class="sourceLineNo">669</span>    buf.position(0);<a name="line.669"></a>
-<span class="sourceLineNo">670</span>    buf.get(newBuf.array(), newBuf.arrayOffset(), headerSize);<a name="line.670"></a>
-<span class="sourceLineNo">671</span><a name="line.671"></a>
-<span class="sourceLineNo">672</span>    buf = new SingleByteBuff(newBuf);<a name="line.672"></a>
-<span class="sourceLineNo">673</span>    // set limit to exclude next block's header<a name="line.673"></a>
-<span class="sourceLineNo">674</span>    buf.limit(headerSize + uncompressedSizeWithoutHeader + cksumBytes);<a name="line.674"></a>
-<span class="sourceLineNo">675</span>  }<a name="line.675"></a>
-<span class="sourceLineNo">676</span><a name="line.676"></a>
-<span class="sourceLineNo">677</span>  /**<a name="line.677"></a>
-<span class="sourceLineNo">678</span>   * Return true when this block's buffer has been unpacked, false otherwise. Note this is a<a name="line.678"></a>
-<span class="sourceLineNo">679</span>   * calculated heuristic, not tracked attribute of the block.<a name="line.679"></a>
-<span class="sourceLineNo">680</span>   */<a name="line.680"></a>
-<span class="sourceLineNo">681</span>  public boolean isUnpacked() {<a name="line.681"></a>
-<span class="sourceLineNo">682</span>    final int cksumBytes = totalChecksumBytes();<a name="line.682"></a>
-<span class="sourceLineNo">683</span>    final int headerSize = headerSize();<a name="line.683"></a>
-<span class="sourceLineNo">684</span>    final int expectedCapacity = headerSize + uncompressedSizeWithoutHeader + cksumBytes;<a name="line.684"></a>
-<span class="sourceLineNo">685</span>    final int bufCapacity = buf.capacity();<a name="line.685"></a>
-<span class="sourceLineNo">686</span>    return bufCapacity == expectedCapacity || bufCapacity == expectedCapacity + headerSize;<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>  /** An additional sanity-check in case no compression or encryption is being used. */<a name="line.689"></a>
-<span class="sourceLineNo">690</span>  @VisibleForTesting<a name="line.690"></a>
-<span class="sourceLineNo">691</span>  void sanityCheckUncompressedSize() throws IOException {<a name="line.691"></a>
-<span class="sourceLineNo">692</span>    if (onDiskSizeWithoutHeader != uncompressedSizeWithoutHeader + totalChecksumBytes()) {<a name="line.692"></a>
-<span class="sourceLineNo">693</span>      throw new IOException("Using no compression but "<a name="line.693"></a>
-<span class="sourceLineNo">694</span>          + "onDiskSizeWithoutHeader=" + onDiskSizeWithoutHeader + ", "<a name="line.694"></a>
-<span class="sourceLineNo">695</span>          + "uncompressedSizeWithoutHeader=" + uncompressedSizeWithoutHeader<a name="line.695"></a>
-<span class="sourceLineNo">696</span>          + ", numChecksumbytes=" + totalChecksumBytes());<a name="line.696"></a>
-<span class="sourceLineNo">697</span>    }<a name="line.697"></a>
-<span class="sourceLineNo">698</span>  }<a name="line.698"></a>
-<span class="sourceLineNo">699</span><a name="line.699"></a>
-<span class="sourceLineNo">700</span>  /**<a name="line.700"></a>
-<span class="sourceLineNo">701</span>   * Cannot be {@link #UNSET}. Must be a legitimate value. Used re-making the {@link BlockCacheKey} when<a name="line.701"></a>
-<span class="sourceLineNo">702</span>   * block is returned to the cache.<a name="line.702"></a>
-<span class="sourceLineNo">703</span>   * @return the offset of this block in the file it was read from<a name="line.703"></a>
-<span class="sourceLineNo">704</span>   */<a name="line.704"></a>
-<span class="sourceLineNo">705</span>  long getOffset() {<a name="line.705"></a>
-<span class="sourceLineNo">706</span>    if (offset &lt; 0) {<a name="line.706"></a>
-<span class="sourceLineNo">707</span>      throw new IllegalStateException("HFile block offset not initialized properly");<a name="line.707"></a>
-<span class="sourceLineNo">708</span>    }<a name="line.708"></a>
-<span class="sourceLineNo">709</span>    return offset;<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>   * @return a byte stream reading the data + checksum of this block<a name="line.713"></a>
-<span class="sourceLineNo">714</span>   */<a name="line.714"></a>
-<span class="sourceLineNo">715</span>  DataInputStream getByteStream() {<a name="line.715"></a>
-<span class="sourceLineNo">716</span>    ByteBuff dup = this.buf.duplicate();<a name="line.716"></a>
-<span class="sourceLineNo">717</span>    dup.position(this.headerSize());<a name="line.717"></a>
-<span class="sourceLineNo">718</span>    return new DataInputStream(new ByteBuffInputStream(dup));<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>
-<span class="sourceLineNo">721</span>  @Override<a name="line.721"></a>
-<span class="sourceLineNo">722</span>  public long heapSize() {<a name="line.722"></a>
-<span class="sourceLineNo">723</span>    long size = ClassSize.align(<a name="line.723"></a>
-<span class="sourceLineNo">724</span>        ClassSize.OBJECT +<a name="line.724"></a>
-<span class="sourceLineNo">725</span>        // Block type, multi byte buffer, MemoryType and meta references<a name="line.725"></a>
-<span class="sourceLineNo">726</span>        4 * ClassSize.REFERENCE +<a name="line.726"></a>
-<span class="sourceLineNo">727</span>        // On-disk size, uncompressed size, and next block's on-disk size<a name="line.727"></a>
-<span class="sourceLineNo">728</span>        // bytePerChecksum and onDiskDataSize<a name="line.728"></a>
-<span class="sourceLineNo">729</span>        4 * Bytes.SIZEOF_INT +<a name="line.729"></a>
-<span class="sourceLineNo">730</span>        // This and previous block offset<a name="line.730"></a>
-<span class="sourceLineNo">731</span>        2 * Bytes.SIZEOF_LONG +<a name="line.731"></a>
-<span class="sourceLineNo">732</span>        // Heap size of the meta object. meta will be always not null.<a name="line.732"></a>
-<span class="sourceLineNo">733</span>        fileContext.heapSize()<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>    if (buf != null) {<a name="line.736"></a>
-<span class="sourceLineNo">737</span>      // Deep overhead of the byte buffer. Needs to be aligned separately.<a name="line.737"></a>
-<span class="sourceLineNo">738</span>      size += ClassSize.align(buf.capacity() + MULTI_BYTE_BUFFER_HEAP_SIZE);<a name="line.738"></a>
-<span class="sourceLineNo">739</span>    }<a name="line.739"></a>
-<span class="sourceLineNo">740</span><a name="line.740"></a>
-<span class="sourceLineNo">741</span>    return ClassSize.align(size);<a name="line.741"></a>
-<span class="sourceLineNo">742</span>  }<a name="line.742"></a>
-<span class="sourceLineNo">743</span><a name="line.743"></a>
-<span class="sourceLineNo">744</span>  /**<a name="line.744"></a>
-<span class="sourceLineNo">745</span>   * Read from an input stream at least &lt;code&gt;necessaryLen&lt;/code&gt; and if possible,<a name="line.745"></a>
-<span class="sourceLineNo">746</span>   * &lt;code&gt;extraLen&lt;/code&gt; also if available. Analogous to<a name="line.746"></a>
-<span class="sourceLineNo">747</span>   * {@link IOUtils#readFully(InputStream, byte[], int, int)}, but specifies a<a name="line.747"></a>
-<span class="sourceLineNo">748</span>   * number of "extra" bytes to also optionally read.<a name="line.748"></a>
-<span class="sourceLineNo">749</span>   *<a name="line.749"></a>
-<span class="sourceLineNo">750</span>   * @param in the input stream to read from<a name="line.750"></a>
-<span class="sourceLineNo">751</span>   * @param buf the buffer to read into<a name="line.751"></a>
-<span class="sourceLineNo">752</span>   * @param bufOffset the destination offset in the buffer<a name="line.752"></a>
-<span class="sourceLineNo">753</span>   * @param necessaryLen the number of bytes that are absolutely necessary to read<a name="line.753"></a>
-<span class="sourceLineNo">754</span>   * @param extraLen the number of extra bytes that would be nice to read<a name="line.754"></a>
-<span class="sourceLineNo">755</span>   * @return true if succeeded reading the extra bytes<a name="line.755"></a>
-<span class="sourceLineNo">756</span>   * @throws IOException if failed to read the necessary bytes<a name="line.756"></a>
-<span class="sourceLineNo">757</span>   */<a name="line.757"></a>
-<span class="sourceLineNo">758</span>  static boolean readWithExtra(InputStream in, byte[] buf,<a name="line.758"></a>
-<span class="sourceLineNo">759</span>      int bufOffset, int necessaryLen, int extraLen) throws IOException {<a name="line.759"></a>
-<span class="sourceLineNo">760</span>    int bytesRemaining = necessaryLen + extraLen;<a name="line.760"></a>
-<span class="sourceLineNo">761</span>    while (bytesRemaining &gt; 0) {<a name="line.761"></a>
-<span class="sourceLineNo">762</span>      int ret = in.read(buf, bufOffset, bytesRemaining);<a name="line.762"></a>
-<span class="sourceLineNo">763</span>      if (ret == -1 &amp;&amp; bytesRemaining &lt;= extraLen) {<a name="line.763"></a>
-<span class="sourceLineNo">764</span>        // We could not read the "extra data", but that is OK.<a name="line.764"></a>
-<span class="sourceLineNo">765</span>        break;<a name="line.765"></a>
-<span class="sourceLineNo">766</span>      }<a name="line.766"></a>
-<span class="sourceLineNo">767</span>      if (ret &lt; 0) {<a name="line.767"></a>
-<span class="sourceLineNo">768</span>        throw new IOException("Premature EOF from inputStream (read "<a name="line.768"></a>
-<span class="sourceLineNo">769</span>            + "returned " + ret + ", was trying to read " + necessaryLen<a name="line.769"></a>
-<span class="sourceLineNo">770</span>            + " necessary bytes and " + extraLen + " extra bytes, "<a name="line.770"></a>
-<span class="sourceLineNo">771</span>            + "successfully read "<a name="line.771"></a>
-<span class="sourceLineNo">772</span>            + (necessaryLen + extraLen - bytesRemaining));<a name="line.772"></a>
-<span class="sourceLineNo">773</span>      }<a name="line.773"></a>
-<span class="sourceLineNo">774</span>      bufOffset += ret;<a name="line.774"></a>
-<span class="sourceLineNo">775</span>      bytesRemaining -= ret;<a name="line.775"></a>
-<span class="sourceLineNo">776</span>    }<a name="line.776"></a>
-<span class="sourceLineNo">777</span>    return bytesRemaining &lt;= 0;<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>   * Read from an input stream at least &lt;code&gt;necessaryLen&lt;/code&gt; and if possible,<a name="line.781"></a>
-<span class="sourceLineNo">782</span>   * &lt;code&gt;extraLen&lt;/code&gt; also if available. Analogous to<a name="line.782"></a>
-<span class="sourceLineNo">783</span>   * {@link IOUtils#readFully(InputStream, byte[], int, int)}, but uses<a name="line.783"></a>
-<span class="sourceLineNo">784</span>   * positional read and specifies a number of "extra" bytes that would be<a name="line.784"></a>
-<span class="sourceLineNo">785</span>   * desirable but not absolutely necessary to read.<a name="line.785"></a>
-<span class="sourceLineNo">786</span>   *<a name="line.786"></a>
-<span class="sourceLineNo">787</span>   * @param in the input stream to read from<a name="line.787"></a>
-<span class="sourceLineNo">788</span>   * @param position the position within the stream from which to start reading<a name="line.788"></a>
-<span class="sourceLineNo">789</span>   * @param buf the buffer to read into<a name="line.789"></a>
-<span class="sourceLineNo">790</span>   * @param bufOffset the destination offset in the buffer<a name="line.790"></a>
-<span class="sourceLineNo">791</span>   * @param necessaryLen the number of bytes that are absolutely necessary to<a name="line.791"></a>
-<span class="sourceLineNo">792</span>   *     read<a name="line.792"></a>
-<span class="sourceLineNo">793</span>   * @param extraLen the number of extra bytes that would be nice to read<a name="line.793"></a>
-<span class="sourceLineNo">794</span>   * @return true if and only if extraLen is &gt; 0 and reading those extra bytes<a name="line.794"></a>
-<span class="sourceLineNo">795</span>   *     was successful<a name="line.795"></a>
-<span class="sourceLineNo">796</span>   * @throws IOException if failed to read the necessary bytes<a name="line.796"></a>
-<span class="sourceLineNo">797</span>   */<a name="line.797"></a>
-<span class="sourceLineNo">798</span>  @VisibleForTesting<a name="line.798"></a>
-<span class="sourceLineNo">799</span>  static boolean positionalReadWithExtra(FSDataInputStream in,<a name="line.799"></a>
-<span class="sourceLineNo">800</span>      long position, byte[] buf, int bufOffset, int necessaryLen, int extraLen)<a name="line.800"></a>
-<span class="sourceLineNo">801</span>      throws IOException {<a name="line.801"></a>
-<span class="sourceLineNo">802</span>    int bytesRemaining = necessaryLen + extraLen;<a name="line.802"></a>
-<span class="sourceLineNo">803</span>    int bytesRead = 0;<a name="line.803"></a>
-<span class="sourceLineNo">804</span>    while (bytesRead &lt; necessaryLen) {<a name="line.804"></a>
-<span class="sourceLineNo">805</span>      int ret = in.read(position, buf, bufOffset, bytesRemaining);<a name="line.805"></a>
-<span class="sourceLineNo">806</span>      if (ret &lt; 0) {<a name="line.806"></a>
-<span class="sourceLineNo">807</span>        throw new IOException("Premature EOF from inputStream (positional read "<a name="line.807"></a>
-<span class="sourceLineNo">808</span>            + "returned " + ret + ", was trying to read " + necessaryLen<a name="line.808"></a>
-<span class="sourceLineNo">809</span>            + " necessary bytes and " + extraLen + " extra bytes, "<a name="line.809"></a>
-<span class="sourceLineNo">810</span>            + "successfully read " + bytesRead);<a name="line.810"></a>
-<span class="sourceLineNo">811</span>      }<a name="line.811"></a>
-<span class="sourceLineNo">812</span>      position += ret;<a name="line.812"></a>
-<span class="sourceLineNo">813</span>      bufOffset += ret;<a name="line.813"></a>
-<span class="sourceLineNo">814</span>      bytesRemaining -= ret;<a name="line.814"></a>
-<span class="sourceLineNo">815</span>      bytesRead += ret;<a name="line.815"></a>
-<span class="sourceLineNo">816</span>    }<a name="line.816"></a>
-<span class="sourceLineNo">817</span>    return bytesRead != necessaryLen &amp;&amp; bytesRemaining &lt;= 0;<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>   * Unified version 2 {@link HFile} block writer. The intended usage pattern<a name="line.821"></a>
-<span class="sourceLineNo">822</span>   * is as follows:<a name="line.822"></a>
-<span class="sourceLineNo">823</span>   * &lt;ol&gt;<a name="line.823"></a>
-<span class="sourceLineNo">824</span>   * &lt;li&gt;Construct an {@link HFileBlock.Writer}, providing a compression algorithm.<a name="line.824"></a>
-<span class="sourceLineNo">825</span>   * &lt;li&gt;Call {@link Writer#startWriting} and get a data stream to write to.<a name="line.825"></a>
-<span class="sourceLineNo">826</span>   * &lt;li&gt;Write your data into the stream.<a name="line.826"></a>
-<span class="sourceLineNo">827</span>   * &lt;li&gt;Call Writer#writeHeaderAndData(FSDataOutputStream) as many times as you need to.<a name="line.827"></a>
-<span class="sourceLineNo">828</span>   * store the serialized block into an external stream.<a name="line.828"></a>
-<span class="sourceLineNo">829</span>   * &lt;li&gt;Repeat to write more blocks.<a name="line.829"></a>
-<span class="sourceLineNo">830</span>   * &lt;/ol&gt;<a name="line.830"></a>
-<span class="sourceLineNo">831</span>   * &lt;p&gt;<a name="line.831"></a>
-<span class="sourceLineNo">832</span>   */<a name="line.832"></a>
-<span class="sourceLineNo">833</span>  static class Writer {<a name="line.833"></a>
-<span class="sourceLineNo">834</span>    private enum State {<a name="line.834"></a>
-<span class="sourceLineNo">835</span>      INIT,<a name="line.835"></a>
-<span class="sourceLineNo">836</span>      WRITING,<a name="line.836"></a>
-<span class="sourceLineNo">837</span>      BLOCK_READY<a name="line.837"></a>
-<span class="sourceLineNo">838</span>    }<a name="line.838"></a>
-<span class="sourceLineNo">839</span><a name="line.839"></a>
-<span class="sourceLineNo">840</span>    /** Writer state. Used to ensure the correct usage protocol. */<a name="line.840"></a>
-<span class="sourceLineNo">841</span>    private State state = State.INIT;<a name="line.841"></a>
-<span class="sourceLineNo">842</span><a name="line.842"></a>
-<span class="sourceLineNo">843</span>    /** Data block encoder used for data blocks */<a name="line.843"></a>
-<span class="sourceLineNo">844</span>    private final HFileDataBlockEncoder dataBlockEncoder;<a name="line.844"></a>
-<span class="sourceLineNo">845</span><a name="line.845"></a>
-<span class="sourceLineNo">846</span>    private HFileBlockEncodingContext dataBlockEncodingCtx;<a name="line.846"></a>
+<span class="sourceLineNo">328</span>   *<a name="line.328"></a>
+<span class="sourceLineNo">329</span>   * &lt;p&gt;TODO: The caller presumes no checksumming<a name="line.329"></a>
+<span class="sourceLineNo">330</span>   * required of this block instance since going into cache; checksum already verified on<a name="line.330"></a>
+<span class="sourceLineNo">331</span>   * underlying block data pulled in from filesystem. Is that correct? What if cache is SSD?<a name="line.331"></a>
+<span class="sourceLineNo">332</span>   *<a name="line.332"></a>
+<span class="sourceLineNo">333</span>   * @param blockType the type of this block, see {@link BlockType}<a name="line.333"></a>
+<span class="sourceLineNo">334</span>   * @param onDiskSizeWithoutHeader see {@link #onDiskSizeWithoutHeader}<a name="line.334"></a>
+<span class="sourceLineNo">335</span>   * @param uncompressedSizeWithoutHeader see {@link #uncompressedSizeWithoutHeader}<a name="line.335"></a>
+<span class="sourceLineNo">336</span>   * @param prevBlockOffset see {@link #prevBlockOffset}<a name="line.336"></a>
+<span class="sourceLineNo">337</span>   * @param b block header ({@link HConstants#HFILEBLOCK_HEADER_SIZE} bytes)<a name="line.337"></a>
+<span class="sourceLineNo">338</span>   * @param fillHeader when true, write the first 4 header fields into passed buffer.<a name="line.338"></a>
+<span class="sourceLineNo">339</span>   * @param offset the file offset the block was read from<a name="line.339"></a>
+<span class="sourceLineNo">340</span>   * @param onDiskDataSizeWithHeader see {@link #onDiskDataSizeWithHeader}<a name="line.340"></a>
+<span class="sourceLineNo">341</span>   * @param fileContext HFile meta data<a name="line.341"></a>
+<span class="sourceLineNo">342</span>   */<a name="line.342"></a>
+<span class="sourceLineNo">343</span>  @VisibleForTesting<a name="line.343"></a>
+<span class="sourceLineNo">344</span>  public HFileBlock(BlockType blockType, int onDiskSizeWithoutHeader,<a name="line.344"></a>
+<span class="sourceLineNo">345</span>      int uncompressedSizeWithoutHeader, long prevBlockOffset, ByteBuffer b, boolean fillHeader,<a name="line.345"></a>
+<span class="sourceLineNo">346</span>      long offset, final int nextBlockOnDiskSize, int onDiskDataSizeWithHeader,<a name="line.346"></a>
+<span class="sourceLineNo">347</span>      HFileContext fileContext) {<a name="line.347"></a>
+<span class="sourceLineNo">348</span>    init(blockType, onDiskSizeWithoutHeader, uncompressedSizeWithoutHeader,<a name="line.348"></a>
+<span class="sourceLineNo">349</span>        prevBlockOffset, offset, onDiskDataSizeWithHeader, nextBlockOnDiskSize, fileContext);<a name="line.349"></a>
+<span class="sourceLineNo">350</span>    this.buf = new SingleByteBuff(b);<a name="line.350"></a>
+<span class="sourceLineNo">351</span>    if (fillHeader) {<a name="line.351"></a>
+<span class="sourceLineNo">352</span>      overwriteHeader();<a name="line.352"></a>
+<span class="sourceLineNo">353</span>    }<a name="line.353"></a>
+<span class="sourceLineNo">354</span>    this.buf.rewind();<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">357</span>  /**<a name="line.357"></a>
+<span class="sourceLineNo">358</span>   * Creates a block from an existing buffer starting with a header. Rewinds<a name="line.358"></a>
+<span class="sourceLineNo">359</span>   * and takes ownership of the buffer. By definition of rewind, ignores the<a name="line.359"></a>
+<span class="sourceLineNo">360</span>   * buffer position, but if you slice the buffer beforehand, it will rewind<a name="line.360"></a>
+<span class="sourceLineNo">361</span>   * to that point.<a name="line.361"></a>
+<span class="sourceLineNo">362</span>   * @param buf Has header, content, and trailing checksums if present.<a name="line.362"></a>
+<span class="sourceLineNo">363</span>   */<a name="line.363"></a>
+<span class="sourceLineNo">364</span>  HFileBlock(ByteBuff buf, boolean usesHBaseChecksum, MemoryType memType, final long offset,<a name="line.364"></a>
+<span class="sourceLineNo">365</span>      final int nextBlockOnDiskSize, HFileContext fileContext) throws IOException {<a name="line.365"></a>
+<span class="sourceLineNo">366</span>    buf.rewind();<a name="line.366"></a>
+<span class="sourceLineNo">367</span>    final BlockType blockType = BlockType.read(buf);<a name="line.367"></a>
+<span class="sourceLineNo">368</span>    final int onDiskSizeWithoutHeader = buf.getInt(Header.ON_DISK_SIZE_WITHOUT_HEADER_INDEX);<a name="line.368"></a>
+<span class="sourceLineNo">369</span>    final int uncompressedSizeWithoutHeader =<a name="line.369"></a>
+<span class="sourceLineNo">370</span>        buf.getInt(Header.UNCOMPRESSED_SIZE_WITHOUT_HEADER_INDEX);<a name="line.370"></a>
+<span class="sourceLineNo">371</span>    final long prevBlockOffset = buf.getLong(Header.PREV_BLOCK_OFFSET_INDEX);<a name="line.371"></a>
+<span class="sourceLineNo">372</span>    // This constructor is called when we deserialize a block from cache and when we read a block in<a name="line.372"></a>
+<span class="sourceLineNo">373</span>    // from the fs. fileCache is null when deserialized from cache so need to make up one.<a name="line.373"></a>
+<span class="sourceLineNo">374</span>    HFileContextBuilder fileContextBuilder = fileContext != null?<a name="line.374"></a>
+<span class="sourceLineNo">375</span>        new HFileContextBuilder(fileContext): new HFileContextBuilder();<a name="line.375"></a>
+<span class="sourceLineNo">376</span>    fileContextBuilder.withHBaseCheckSum(usesHBaseChecksum);<a name="line.376"></a>
+<span class="sourceLineNo">377</span>    int onDiskDataSizeWithHeader;<a name="line.377"></a>
+<span class="sourceLineNo">378</span>    if (usesHBaseChecksum) {<a name="line.378"></a>
+<span class="sourceLineNo">379</span>      byte checksumType = buf.get(Header.CHECKSUM_TYPE_INDEX);<a name="line.379"></a>
+<span class="sourceLineNo">380</span>      int bytesPerChecksum = buf.getInt(Header.BYTES_PER_CHECKSUM_INDEX);<a name="line.380"></a>
+<span class="sourceLineNo">381</span>      onDiskDataSizeWithHeader = buf.getInt(Header.ON_DISK_DATA_SIZE_WITH_HEADER_INDEX);<a name="line.381"></a>
+<span class="sourceLineNo">382</span>      // Use the checksum type and bytes per checksum from header, not from filecontext.<a name="line.382"></a>
+<span class="sourceLineNo">383</span>      fileContextBuilder.withChecksumType(ChecksumType.codeToType(checksumType));<a name="line.383"></a>
+<span class="sourceLineNo">384</span>      fileContextBuilder.withBytesPerCheckSum(bytesPerChecksum);<a name="line.384"></a>
+<span class="sourceLineNo">385</span>    } else {<a name="line.385"></a>
+<span class="sourceLineNo">386</span>      fileContextBuilder.withChecksumType(ChecksumType.NULL);<a name="line.386"></a>
+<span class="sourceLineNo">387</span>      fileContextBuilder.withBytesPerCheckSum(0);<a name="line.387"></a>
+<span class="sourceLineNo">388</span>      // Need to fix onDiskDataSizeWithHeader; there are not checksums after-block-data<a name="line.388"></a>
+<span class="sourceLineNo">389</span>      onDiskDataSizeWithHeader = onDiskSizeWithoutHeader + headerSize(usesHBaseChecksum);<a name="line.389"></a>
+<span class="sourceLineNo">390</span>    }<a name="line.390"></a>
+<span class="sourceLineNo">391</span>    fileContext = fileContextBuilder.build();<a name="line.391"></a>
+<span class="sourceLineNo">392</span>    assert usesHBaseChecksum == fileContext.isUseHBaseChecksum();<a name="line.392"></a>
+<span class="sourceLineNo">393</span>    init(blockType, onDiskSizeWithoutHeader, uncompressedSizeWithoutHeader,<a name="line.393"></a>
+<span class="sourceLineNo">394</span>        prevBlockOffset, offset, onDiskDataSizeWithHeader, nextBlockOnDiskSize, fileContext);<a name="line.394"></a>
+<span class="sourceLineNo">395</span>    this.memType = memType;<a name="line.395"></a>
+<span class="sourceLineNo">396</span>    this.offset = offset;<a name="line.396"></a>
+<span class="sourceLineNo">397</span>    this.buf = buf;<a name="line.397"></a>
+<span class="sourceLineNo">398</span>    this.buf.rewind();<a name="line.398"></a>
+<span class="sourceLineNo">399</span>  }<a name="line.399"></a>
+<span class="sourceLineNo">400</span><a name="line.400"></a>
+<span class="sourceLineNo">401</span>  /**<a name="line.401"></a>
+<span class="sourceLineNo">402</span>   * Called from constructors.<a name="line.402"></a>
+<span class="sourceLineNo">403</span>   */<a name="line.403"></a>
+<span class="sourceLineNo">404</span>  private void init(BlockType blockType, int onDiskSizeWithoutHeader,<a name="line.404"></a>
+<span class="sourceLineNo">405</span>      int uncompressedSizeWithoutHeader, long prevBlockOffset,<a name="line.405"></a>
+<span class="sourceLineNo">406</span>      long offset, int onDiskDataSizeWithHeader, final int nextBlockOnDiskSize,<a name="line.406"></a>
+<span class="sourceLineNo">407</span>      HFileContext fileContext) {<a name="line.407"></a>
+<span class="sourceLineNo">408</span>    this.blockType = blockType;<a name="line.408"></a>
+<span class="sourceLineNo">409</span>    this.onDiskSizeWithoutHeader = onDiskSizeWithoutHeader;<a name="line.409"></a>
+<span class="sourceLineNo">410</span>    this.uncompressedSizeWithoutHeader = uncompressedSizeWithoutHeader;<a name="line.410"></a>
+<span class="sourceLineNo">411</span>    this.prevBlockOffset = prevBlockOffset;<a name="line.411"></a>
+<span class="sourceLineNo">412</span>    this.offset = offset;<a name="line.412"></a>
+<span class="sourceLineNo">413</span>    this.onDiskDataSizeWithHeader = onDiskDataSizeWithHeader;<a name="line.413"></a>
+<span class="sourceLineNo">414</span>    this.nextBlockOnDiskSize = nextBlockOnDiskSize;<a name="line.414"></a>
+<span class="sourceLineNo">415</span>    this.fileContext = fileContext;<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">418</span>  /**<a name="line.418"></a>
+<span class="sourceLineNo">419</span>   * Parse total on disk size including header and checksum.<a name="line.419"></a>
+<span class="sourceLineNo">420</span>   * @param headerBuf Header ByteBuffer. Presumed exact size of header.<a name="line.420"></a>
+<span class="sourceLineNo">421</span>   * @param verifyChecksum true if checksum verification is in use.<a name="line.421"></a>
+<span class="sourceLineNo">422</span>   * @return Size of the block with header included.<a name="line.422"></a>
+<span class="sourceLineNo">423</span>   */<a name="line.423"></a>
+<span class="sourceLineNo">424</span>  private static int getOnDiskSizeWithHeader(final ByteBuffer headerBuf,<a name="line.424"></a>
+<span class="sourceLineNo">425</span>      boolean verifyChecksum) {<a name="line.425"></a>
+<span class="sourceLineNo">426</span>    return headerBuf.getInt(Header.ON_DISK_SIZE_WITHOUT_HEADER_INDEX) +<a name="line.426"></a>
+<span class="sourceLineNo">427</span>      headerSize(verifyChecksum);<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>   * @return the on-disk size of the next block (including the header size and any checksums if<a name="line.431"></a>
+<span class="sourceLineNo">432</span>   * present) read by peeking into the next block's header; use as a hint when doing<a name="line.432"></a>
+<span class="sourceLineNo">433</span>   * a read of the next block when scanning or running over a file.<a name="line.433"></a>
+<span class="sourceLineNo">434</span>   */<a name="line.434"></a>
+<span class="sourceLineNo">435</span>  int getNextBlockOnDiskSize() {<a name="line.435"></a>
+<span class="sourceLineNo">436</span>    return nextBlockOnDiskSize;<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>  @Override<a name="line.439"></a>
+<span class="sourceLineNo">440</span>  public BlockType getBlockType() {<a name="line.440"></a>
+<span class="sourceLineNo">441</span>    return blockType;<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>  /** @return get data block encoding id that was used to encode this block */<a name="line.444"></a>
+<span class="sourceLineNo">445</span>  short getDataBlockEncodingId() {<a name="line.445"></a>
+<span class="sourceLineNo">446</span>    if (blockType != BlockType.ENCODED_DATA) {<a name="line.446"></a>
+<span class="sourceLineNo">447</span>      throw new IllegalArgumentException("Querying encoder ID of a block " +<a name="line.447"></a>
+<span class="sourceLineNo">448</span>          "of type other than " + BlockType.ENCODED_DATA + ": " + blockType);<a name="line.448"></a>
+<span class="sourceLineNo">449</span>    }<a name="line.449"></a>
+<span class="sourceLineNo">450</span>    return buf.getShort(headerSize());<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>   * @return the on-disk size of header + data part + checksum.<a name="line.454"></a>
+<span class="sourceLineNo">455</span>   */<a name="line.455"></a>
+<span class="sourceLineNo">456</span>  public int getOnDiskSizeWithHeader() {<a name="line.456"></a>
+<span class="sourceLineNo">457</span>    return onDiskSizeWithoutHeader + headerSize();<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>   * @return the on-disk size of the data part + checksum (header excluded).<a name="line.461"></a>
+<span class="sourceLineNo">462</span>   */<a name="line.462"></a>
+<span class="sourceLineNo">463</span>  int getOnDiskSizeWithoutHeader() {<a name="line.463"></a>
+<span class="sourceLineNo">464</span>    return onDiskSizeWithoutHeader;<a name="line.464"></a>
+<span class="sourceLineNo">465</span>  }<a name="line.465"></a>
+<span class="sourceLineNo">466</span><a name="line.466"></a>
+<span class="sourceLineNo">467</span>  /**<a name="line.467"></a>
+<span class="sourceLineNo">468</span>   * @return the uncompressed size of data part (header and checksum excluded).<a name="line.468"></a>
+<span class="sourceLineNo">469</span>   */<a name="line.469"></a>
+<span class="sourceLineNo">470</span>   int getUncompressedSizeWithoutHeader() {<a name="line.470"></a>
+<span class="sourceLineNo">471</span>    return uncompressedSizeWithoutHeader;<a name="line.471"></a>
+<span class="sourceLineNo">472</span>  }<a name="line.472"></a>
+<span class="sourceLineNo">473</span><a name="line.473"></a>
+<span class="sourceLineNo">474</span>  /**<a name="line.474"></a>
+<span class="sourceLineNo">475</span>   * @return the offset of the previous block of the same type in the file, or<a name="line.475"></a>
+<span class="sourceLineNo">476</span>   *         -1 if unknown<a name="line.476"></a>
+<span class="sourceLineNo">477</span>   */<a name="line.477"></a>
+<span class="sourceLineNo">478</span>  long getPrevBlockOffset() {<a name="line.478"></a>
+<span class="sourceLineNo">479</span>    return prevBlockOffset;<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>   * Rewinds {@code buf} and writes first 4 header fields. {@code buf} position<a name="line.483"></a>
+<span class="sourceLineNo">484</span>   * is modified as side-effect.<a name="line.484"></a>
+<span class="sourceLineNo">485</span>   */<a name="line.485"></a>
+<span class="sourceLineNo">486</span>  private void overwriteHeader() {<a name="line.486"></a>
+<span class="sourceLineNo">487</span>    buf.rewind();<a name="line.487"></a>
+<span class="sourceLineNo">488</span>    blockType.write(buf);<a name="line.488"></a>
+<span class="sourceLineNo">489</span>    buf.putInt(onDiskSizeWithoutHeader);<a name="line.489"></a>
+<span class="sourceLineNo">490</span>    buf.putInt(uncompressedSizeWithoutHeader);<a name="line.490"></a>
+<span class="sourceLineNo">491</span>    buf.putLong(prevBlockOffset);<a name="line.491"></a>
+<span class="sourceLineNo">492</span>    if (this.fileContext.isUseHBaseChecksum()) {<a name="line.492"></a>
+<span class="sourceLineNo">493</span>      buf.put(fileContext.getChecksumType().getCode());<a name="line.493"></a>
+<span class="sourceLineNo">494</span>      buf.putInt(fileContext.getBytesPerChecksum());<a name="line.494"></a>
+<span class="sourceLineNo">495</span>      buf.putInt(onDiskDataSizeWithHeader);<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><a name="line.498"></a>
+<span class="sourceLineNo">499</span>  /**<a name="line.499"></a>
+<span class="sourceLineNo">500</span>   * Returns a buffer that does not include the header or checksum.<a name="line.500"></a>
+<span class="sourceLineNo">501</span>   *<a name="line.501"></a>
+<span class="sourceLineNo">502</span>   * @return the buffer with header skipped and checksum omitted.<a name="line.502"></a>
+<span class="sourceLineNo">503</span>   */<a name="line.503"></a>
+<span class="sourceLineNo">504</span>  public ByteBuff getBufferWithoutHeader() {<a name="line.504"></a>
+<span class="sourceLineNo">505</span>    ByteBuff dup = getBufferReadOnly();<a name="line.505"></a>
+<span class="sourceLineNo">506</span>    // Now set it up so Buffer spans content only -- no header or no checksums.<a name="line.506"></a>
+<span class="sourceLineNo">507</span>    return dup.position(headerSize()).limit(buf.limit() - totalChecksumBytes()).slice();<a name="line.507"></a>
+<span class="sourceLineNo">508</span>  }<a name="line.508"></a>
+<span class="sourceLineNo">509</span><a name="line.509"></a>
+<span class="sourceLineNo">510</span>  /**<a name="line.510"></a>
+<span class="sourceLineNo">511</span>   * Returns a read-only duplicate of the buffer this block stores internally ready to be read.<a name="line.511"></a>
+<span class="sourceLineNo">512</span>   * Clients must not modify the buffer object though they may set position and limit on the<a name="line.512"></a>
+<span class="sourceLineNo">513</span>   * returned buffer since we pass back a duplicate. This method has to be public because it is used<a name="line.513"></a>
+<span class="sourceLineNo">514</span>   * in {@link CompoundBloomFilter} to avoid object creation on every Bloom<a name="line.514"></a>
+<span class="sourceLineNo">515</span>   * filter lookup, but has to be used with caution. Buffer holds header, block content,<a name="line.515"></a>
+<span class="sourceLineNo">516</span>   * and any follow-on checksums if present.<a name="line.516"></a>
+<span class="sourceLineNo">517</span>   *<a name="line.517"></a>
+<span class="sourceLineNo">518</span>   * @return the buffer of this block for read-only operations<a name="line.518"></a>
+<span class="sourceLineNo">519</span>   */<a name="line.519"></a>
+<span class="sourceLineNo">520</span>  public ByteBuff getBufferReadOnly() {<a name="line.520"></a>
+<span class="sourceLineNo">521</span>    // TODO: ByteBuf does not support asReadOnlyBuffer(). Fix.<a name="line.521"></a>
+<span class="sourceLineNo">522</span>    ByteBuff dup = this.buf.duplicate();<a name="line.522"></a>
+<span class="sourceLineNo">523</span>    assert dup.position() == 0;<a name="line.523"></a>
+<span class="sourceLineNo">524</span>    return dup;<a name="line.524"></a>
+<span class="sourceLineNo">525</span>  }<a name="line.525"></a>
+<span class="sourceLineNo">526</span><a name="line.526"></a>
+<span class="sourceLineNo">527</span>  @VisibleForTesting<a name="line.527"></a>
+<span class="sourceLineNo">528</span>  private void sanityCheckAssertion(long valueFromBuf, long valueFromField,<a name="line.528"></a>
+<span class="sourceLineNo">529</span>      String fieldName) throws IOException {<a name="line.529"></a>
+<span class="sourceLineNo">530</span>    if (valueFromBuf != valueFromField) {<a name="line.530"></a>
+<span class="sourceLineNo">531</span>      throw new AssertionError(fieldName + " in the buffer (" + valueFromBuf<a name="line.531"></a>
+<span class="sourceLineNo">532</span>          + ") is different from that in the field (" + valueFromField + ")");<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>  @VisibleForTesting<a name="line.536"></a>
+<span class="sourceLineNo">537</span>  private void sanityCheckAssertion(BlockType valueFromBuf, BlockType valueFromField)<a name="line.537"></a>
+<span class="sourceLineNo">538</span>      throws IOException {<a name="line.538"></a>
+<span class="sourceLineNo">539</span>    if (valueFromBuf != valueFromField) {<a name="line.539"></a>
+<span class="sourceLineNo">540</span>      throw new IOException("Block type stored in the buffer: " +<a name="line.540"></a>
+<span class="sourceLineNo">541</span>        valueFromBuf + ", block type field: " + valueFromField);<a name="line.541"></a>
+<span class="sourceLineNo">542</span>    }<a name="line.542"></a>
+<span class="sourceLineNo">543</span>  }<a name="line.543"></a>
+<span class="sourceLineNo">544</span><a name="line.544"></a>
+<span class="sourceLineNo">545</span>  /**<a name="line.545"></a>
+<span class="sourceLineNo">546</span>   * Checks if the block is internally consistent, i.e. the first<a name="line.546"></a>
+<span class="sourceLineNo">547</span>   * {@link HConstants#HFILEBLOCK_HEADER_SIZE} bytes of the buffer contain a<a name="line.547"></a>
+<span class="sourceLineNo">548</span>   * valid header consistent with the fields. Assumes a packed block structure.<a name="line.548"></a>
+<span class="sourceLineNo">549</span>   * This function is primary for testing and debugging, and is not<a name="line.549"></a>
+<span class="sourceLineNo">550</span>   * thread-safe, because it alters the internal buffer pointer.<a name="line.550"></a>
+<span class="sourceLineNo">551</span>   * Used by tests only.<a name="line.551"></a>
+<span class="sourceLineNo">552</span>   */<a name="line.552"></a>
+<span class="sourceLineNo">553</span>  @VisibleForTesting<a name="line.553"></a>
+<span class="sourceLineNo">554</span>  void sanityCheck() throws IOException {<a name="line.554"></a>
+<span class="sourceLineNo">555</span>    // Duplicate so no side-effects<a name="line.555"></a>
+<span class="sourceLineNo">556</span>    ByteBuff dup = this.buf.duplicate().rewind();<a name="line.556"></a>
+<span class="sourceLineNo">557</span>    sanityCheckAssertion(BlockType.read(dup), blockType);<a name="line.557"></a>
+<span class="sourceLineNo">558</span><a name="line.558"></a>
+<span class="sourceLineNo">559</span>    sanityCheckAssertion(dup.getInt(), onDiskSizeWithoutHeader, "onDiskSizeWithoutHeader");<a name="line.559"></a>
+<span class="sourceLineNo">560</span><a name="line.560"></a>
+<span class="sourceLineNo">561</span>    sanityCheckAssertion(dup.getInt(), uncompressedSizeWithoutHeader,<a name="line.561"></a>
+<span class="sourceLineNo">562</span>        "uncompressedSizeWithoutHeader");<a name="line.562"></a>
+<span class="sourceLineNo">563</span><a name="line.563"></a>
+<span class="sourceLineNo">564</span>    sanityCheckAssertion(dup.getLong(), prevBlockOffset, "prevBlockOffset");<a name="line.564"></a>
+<span class="sourceLineNo">565</span>    if (this.fileContext.isUseHBaseChecksum()) {<a name="line.565"></a>
+<span class="sourceLineNo">566</span>      sanityCheckAssertion(dup.get(), this.fileContext.getChecksumType().getCode(), "checksumType");<a name="line.566"></a>
+<span class="sourceLineNo">567</span>      sanityCheckAssertion(dup.getInt(), this.fileContext.getBytesPerChecksum(),<a name="line.567"></a>
+<span class="sourceLineNo">568</span>          "bytesPerChecksum");<a name="line.568"></a>
+<span class="sourceLineNo">569</span>      sanityCheckAssertion(dup.getInt(), onDiskDataSizeWithHeader, "onDiskDataSizeWithHeader");<a name="line.569"></a>
+<span class="sourceLineNo">570</span>    }<a name="line.570"></a>
+<span class="sourceLineNo">571</span><a name="line.571"></a>
+<span class="sourceLineNo">572</span>    int cksumBytes = totalChecksumBytes();<a name="line.572"></a>
+<span class="sourceLineNo">573</span>    int expectedBufLimit = onDiskDataSizeWithHeader + cksumBytes;<a name="line.573"></a>
+<span class="sourceLineNo">574</span>    if (dup.limit() != expectedBufLimit) {<a name="line.574"></a>
+<span class="sourceLineNo">575</span>      throw new AssertionError("Expected limit " + expectedBufLimit + ", got " + dup.limit());<a name="line.575"></a>
+<span class="sourceLineNo">576</span>    }<a name="line.576"></a>
+<span class="sourceLineNo">577</span><a name="line.577"></a>
+<span class="sourceLineNo">578</span>    // We might optionally allocate HFILEBLOCK_HEADER_SIZE more bytes to read the next<a name="line.578"></a>
+<span class="sourceLineNo">579</span>    // block's header, so there are two sensible values for buffer capacity.<a name="line.579"></a>
+<span class="sourceLineNo">580</span>    int hdrSize = headerSize();<a name="line.580"></a>
+<span class="sourceLineNo">581</span>    if (dup.capacity() != expectedBufLimit &amp;&amp; dup.capacity() != expectedBufLimit + hdrSize) {<a name="line.581"></a>
+<span class="sourceLineNo">582</span>      throw new AssertionError("Invalid buffer capacity: " + dup.capacity() +<a name="line.582"></a>
+<span class="sourceLineNo">583</span>          ", expected " + expectedBufLimit + " or " + (expectedBufLimit + hdrSize));<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>  @Override<a name="line.587"></a>
+<span class="sourceLineNo">588</span>  public String toString() {<a name="line.588"></a>
+<span class="sourceLineNo">589</span>    StringBuilder sb = new StringBuilder()<a name="line.589"></a>
+<span class="sourceLineNo">590</span>      .append("[")<a name="line.590"></a>
+<span class="sourceLineNo">591</span>      .append("blockType=").append(blockType)<a name="line.591"></a>
+<span class="sourceLineNo">592</span>      .append(", fileOffset=").append(offset)<a name="line.592"></a>
+<span class="sourceLineNo">593</span>      .append(", headerSize=").append(headerSize())<a name="line.593"></a>
+<span class="sourceLineNo">594</span>      .append(", onDiskSizeWithoutHeader=").append(onDiskSizeWithoutHeader)<a name="line.594"></a>
+<span class="sourceLineNo">595</span>      .append(", uncompressedSizeWithoutHeader=").append(uncompressedSizeWithoutHeader)<a name="line.595"></a>
+<span class="sourceLineNo">596</span>      .append(", prevBlockOffset=").append(prevBlockOffset)<a name="line.596"></a>
+<span class="sourceLineNo">597</span>      .append(", isUseHBaseChecksum=").append(fileContext.isUseHBaseChecksum());<a name="line.597"></a>
+<span class="sourceLineNo">598</span>    if (fileContext.isUseHBaseChecksum()) {<a name="line.598"></a>
+<span class="sourceLineNo">599</span>      sb.append(", checksumType=").append(ChecksumType.codeToType(this.buf.get(24)))<a name="line.599"></a>
+<span class="sourceLineNo">600</span>        .append(", bytesPerChecksum=").append(this.buf.getInt(24 + 1))<a name="line.600"></a>
+<span class="sourceLineNo">601</span>        .append(", onDiskDataSizeWithHeader=").append(onDiskDataSizeWithHeader);<a name="line.601"></a>
+<span class="sourceLineNo">602</span>    } else {<a name="line.602"></a>
+<span class="sourceLineNo">603</span>      sb.append(", onDiskDataSizeWithHeader=").append(onDiskDataSizeWithHeader)<a name="line.603"></a>
+<span class="sourceLineNo">604</span>        .append("(").append(onDiskSizeWithoutHeader)<a name="line.604"></a>
+<span class="sourceLineNo">605</span>        .append("+").append(HConstants.HFILEBLOCK_HEADER_SIZE_NO_CHECKSUM).append(")");<a name="line.605"></a>
+<span class="sourceLineNo">606</span>    }<a name="line.606"></a>
+<span class="sourceLineNo">607</span>    String dataBegin = null;<a name="line.607"></a>
+<span class="sourceLineNo">608</span>    if (buf.hasArray()) {<a name="line.608"></a>
+<span class="sourceLineNo">609</span>      dataBegin = Bytes.toStringBinary(buf.array(), buf.arrayOffset() + headerSize(),<a name="line.609"></a>
+<span class="sourceLineNo">610</span>          Math.min(32, buf.limit() - buf.arrayOffset() - headerSize()));<a name="line.610"></a>
+<span class="sourceLineNo">611</span>    } else {<a name="line.611"></a>
+<span class="sourceLineNo">612</span>      ByteBuff bufWithoutHeader = getBufferWithoutHeader();<a name="line.612"></a>
+<span class="sourceLineNo">613</span>      byte[] dataBeginBytes = new byte[Math.min(32,<a name="line.613"></a>
+<span class="sourceLineNo">614</span>          bufWithoutHeader.limit() - bufWithoutHeader.position())];<a name="line.614"></a>
+<span class="sourceLineNo">615</span>      bufWithoutHeader.get(dataBeginBytes);<a name="line.615"></a>
+<span class="sourceLineNo">616</span>      dataBegin = Bytes.toStringBinary(dataBeginBytes);<a name="line.616"></a>
+<span class="sourceLineNo">617</span>    }<a name="line.617"></a>
+<span class="sourceLineNo">618</span>    sb.append(", getOnDiskSizeWithHeader=").append(getOnDiskSizeWithHeader())<a name="line.618"></a>
+<span class="sourceLineNo">619</span>      .append(", totalChecksumBytes=").append(totalChecksumBytes())<a name="line.619"></a>
+<span class="sourceLineNo">620</span>      .append(", isUnpacked=").append(isUnpacked())<a name="line.620"></a>
+<span class="sourceLineNo">621</span>      .append(", buf=[").append(buf).append("]")<a name="line.621"></a>
+<span class="sourceLineNo">622</span>      .append(", dataBeginsWith=").append(dataBegin)<a name="line.622"></a>
+<span class="sourceLineNo">623</span>      .append(", fileContext=").append(fileContext)<a name="line.623"></a>
+<span class="sourceLineNo">624</span>      .append(", nextBlockOnDiskSize=").append(nextBlockOnDiskSize)<a name="line.624"></a>
+<span class="sourceLineNo">625</span>      .append("]");<a name="line.625"></a>
+<span class="sourceLineNo">626</span>    return sb.toString();<a name="line.626"></a>
+<span class="sourceLineNo">627</span>  }<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>   * Retrieves the decompressed/decrypted view of this block. An encoded block remains in its<a name="line.630"></a>
+<span class="sourceLineNo">631</span>   * encoded structure. Internal structures are shared between instances where applicable.<a name="line.631"></a>
+<span class="sourceLineNo">632</span>   */<a name="line.632"></a>
+<span class="sourceLineNo">633</span>  HFileBlock unpack(HFileContext fileContext, FSReader reader) throws IOException {<a name="line.633"></a>
+<span class="sourceLineNo">634</span>    if (!fileContext.isCompressedOrEncrypted()) {<a name="line.634"></a>
+<span class="sourceLineNo">635</span>      // TODO: cannot use our own fileContext here because HFileBlock(ByteBuffer, boolean),<a name="line.635"></a>
+<span class="sourceLineNo">636</span>      // which is used for block serialization to L2 cache, does not preserve encoding and<a name="line.636"></a>
+<span class="sourceLineNo">637</span>      // encryption details.<a name="line.637"></a>
+<span class="sourceLineNo">638</span>      return this;<a name="line.638"></a>
+<span class="sourceLineNo">639</span>    }<a name="line.639"></a>
+<span class="sourceLineNo">640</span><a name="line.640"></a>
+<span class="sourceLineNo">641</span>    HFileBlock unpacked = new HFileBlock(this);<a name="line.641"></a>
+<span class="sourceLineNo">642</span>    unpacked.allocateBuffer(); // allocates space for the decompressed block<a name="line.642"></a>
+<span class="sourceLineNo">643</span><a name="line.643"></a>
+<span class="sourceLineNo">644</span>    HFileBlockDecodingContext ctx = blockType == BlockType.ENCODED_DATA ?<a name="line.644"></a>
+<span class="sourceLineNo">645</span>      reader.getBlockDecodingContext() : reader.getDefaultBlockDecodingContext();<a name="line.645"></a>
+<span class="sourceLineNo">646</span><a name="line.646"></a>
+<span class="sourceLineNo">647</span>    ByteBuff dup = this.buf.duplicate();<a name="line.647"></a>
+<span class="sourceLineNo">648</span>    dup.position(this.headerSize());<a name="line.648"></a>
+<span class="sourceLineNo">649</span>    dup = dup.slice();<a name="line.649"></a>
+<span class="sourceLineNo">650</span>    ctx.prepareD

<TRUNCATED>

[15/50] hbase-site git commit: Published site at 26babcf013de696b899d76a3c39434b794440d8d.

Posted by gi...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html
----------------------------------------------------------------------
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html b/devapidocs/src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html
index cabb570..90f3b1e 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html
@@ -107,660 +107,661 @@
 <span class="sourceLineNo">099</span><a name="line.99"></a>
 <span class="sourceLineNo">100</span>  private Cell lastPeekedCell = null;<a name="line.100"></a>
 <span class="sourceLineNo">101</span><a name="line.101"></a>
-<span class="sourceLineNo">102</span>  /**<a name="line.102"></a>
-<span class="sourceLineNo">103</span>   * Tracks the relevant server side metrics during scans. null when metrics should not be tracked<a name="line.103"></a>
-<span class="sourceLineNo">104</span>   */<a name="line.104"></a>
-<span class="sourceLineNo">105</span>  final ServerSideScanMetrics metrics;<a name="line.105"></a>
-<span class="sourceLineNo">106</span><a name="line.106"></a>
-<span class="sourceLineNo">107</span>  ScannerContext(boolean keepProgress, LimitFields limitsToCopy, boolean trackMetrics) {<a name="line.107"></a>
-<span class="sourceLineNo">108</span>    this.limits = new LimitFields();<a name="line.108"></a>
-<span class="sourceLineNo">109</span>    if (limitsToCopy != null) {<a name="line.109"></a>
-<span class="sourceLineNo">110</span>      this.limits.copy(limitsToCopy);<a name="line.110"></a>
-<span class="sourceLineNo">111</span>    }<a name="line.111"></a>
+<span class="sourceLineNo">102</span>  // Set this to true will have the same behavior with reaching the time limit.<a name="line.102"></a>
+<span class="sourceLineNo">103</span>  // This is used when you want to make the current RSRpcService.scan returns immediately. For<a name="line.103"></a>
+<span class="sourceLineNo">104</span>  // example, when we want to switch from pread to stream, we can only do it after the rpc call is<a name="line.104"></a>
+<span class="sourceLineNo">105</span>  // returned.<a name="line.105"></a>
+<span class="sourceLineNo">106</span>  private boolean returnImmediately;<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>   * Tracks the relevant server side metrics during scans. null when metrics should not be tracked<a name="line.109"></a>
+<span class="sourceLineNo">110</span>   */<a name="line.110"></a>
+<span class="sourceLineNo">111</span>  final ServerSideScanMetrics metrics;<a name="line.111"></a>
 <span class="sourceLineNo">112</span><a name="line.112"></a>
-<span class="sourceLineNo">113</span>    // Progress fields are initialized to 0<a name="line.113"></a>
-<span class="sourceLineNo">114</span>    progress = new ProgressFields(0, 0, 0);<a name="line.114"></a>
-<span class="sourceLineNo">115</span><a name="line.115"></a>
-<span class="sourceLineNo">116</span>    this.keepProgress = keepProgress;<a name="line.116"></a>
-<span class="sourceLineNo">117</span>    this.scannerState = DEFAULT_STATE;<a name="line.117"></a>
-<span class="sourceLineNo">118</span>    this.metrics = trackMetrics ? new ServerSideScanMetrics() : null;<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>  boolean isTrackingMetrics() {<a name="line.121"></a>
-<span class="sourceLineNo">122</span>    return this.metrics != null;<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>   * Get the metrics instance. Should only be called after a call to {@link #isTrackingMetrics()}<a name="line.126"></a>
-<span class="sourceLineNo">127</span>   * has been made to confirm that metrics are indeed being tracked.<a name="line.127"></a>
-<span class="sourceLineNo">128</span>   * @return {@link ServerSideScanMetrics} instance that is tracking metrics for this scan<a name="line.128"></a>
-<span class="sourceLineNo">129</span>   */<a name="line.129"></a>
-<span class="sourceLineNo">130</span>  ServerSideScanMetrics getMetrics() {<a name="line.130"></a>
-<span class="sourceLineNo">131</span>    assert isTrackingMetrics();<a name="line.131"></a>
-<span class="sourceLineNo">132</span>    return this.metrics;<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>   * @return true if the progress tracked so far in this instance will be considered during an<a name="line.136"></a>
-<span class="sourceLineNo">137</span>   *         invocation of {@link InternalScanner#next(java.util.List)} or<a name="line.137"></a>
-<span class="sourceLineNo">138</span>   *         {@link RegionScanner#next(java.util.List)}. false when the progress tracked so far<a name="line.138"></a>
-<span class="sourceLineNo">139</span>   *         should not be considered and should instead be wiped away via {@link #clearProgress()}<a name="line.139"></a>
-<span class="sourceLineNo">140</span>   */<a name="line.140"></a>
-<span class="sourceLineNo">141</span>  boolean getKeepProgress() {<a name="line.141"></a>
-<span class="sourceLineNo">142</span>    return keepProgress;<a name="line.142"></a>
-<span class="sourceLineNo">143</span>  }<a name="line.143"></a>
-<span class="sourceLineNo">144</span><a name="line.144"></a>
-<span class="sourceLineNo">145</span>  void setKeepProgress(boolean keepProgress) {<a name="line.145"></a>
-<span class="sourceLineNo">146</span>    this.keepProgress = keepProgress;<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>   * Progress towards the batch limit has been made. Increment internal tracking of batch progress<a name="line.150"></a>
-<span class="sourceLineNo">151</span>   */<a name="line.151"></a>
-<span class="sourceLineNo">152</span>  void incrementBatchProgress(int batch) {<a name="line.152"></a>
-<span class="sourceLineNo">153</span>    int currentBatch = progress.getBatch();<a name="line.153"></a>
-<span class="sourceLineNo">154</span>    progress.setBatch(currentBatch + batch);<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>   * Progress towards the size limit has been made. Increment internal tracking of size progress<a name="line.158"></a>
-<span class="sourceLineNo">159</span>   */<a name="line.159"></a>
-<span class="sourceLineNo">160</span>  void incrementSizeProgress(long dataSize, long heapSize) {<a name="line.160"></a>
-<span class="sourceLineNo">161</span>    long curDataSize = progress.getDataSize();<a name="line.161"></a>
-<span class="sourceLineNo">162</span>    progress.setDataSize(curDataSize + dataSize);<a name="line.162"></a>
-<span class="sourceLineNo">163</span>    long curHeapSize = progress.getHeapSize();<a name="line.163"></a>
-<span class="sourceLineNo">164</span>    progress.setHeapSize(curHeapSize + heapSize);<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>  int getBatchProgress() {<a name="line.167"></a>
-<span class="sourceLineNo">168</span>    return progress.getBatch();<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>  long getDataSizeProgress() {<a name="line.171"></a>
-<span class="sourceLineNo">172</span>    return progress.getDataSize();<a name="line.172"></a>
-<span class="sourceLineNo">173</span>  }<a name="line.173"></a>
-<span class="sourceLineNo">174</span><a name="line.174"></a>
-<span class="sourceLineNo">175</span>  long getHeapSizeProgress() {<a name="line.175"></a>
-<span class="sourceLineNo">176</span>    return progress.getHeapSize();<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>  void setProgress(int batchProgress, long sizeProgress, long heapSizeProgress) {<a name="line.179"></a>
-<span class="sourceLineNo">180</span>    setBatchProgress(batchProgress);<a name="line.180"></a>
-<span class="sourceLineNo">181</span>    setSizeProgress(sizeProgress, heapSizeProgress);<a name="line.181"></a>
-<span class="sourceLineNo">182</span>  }<a name="line.182"></a>
-<span class="sourceLineNo">183</span><a name="line.183"></a>
-<span class="sourceLineNo">184</span>  void setSizeProgress(long dataSizeProgress, long heapSizeProgress) {<a name="line.184"></a>
-<span class="sourceLineNo">185</span>    progress.setDataSize(dataSizeProgress);<a name="line.185"></a>
-<span class="sourceLineNo">186</span>    progress.setHeapSize(heapSizeProgress);<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>  void setBatchProgress(int batchProgress) {<a name="line.189"></a>
-<span class="sourceLineNo">190</span>    progress.setBatch(batchProgress);<a name="line.190"></a>
-<span class="sourceLineNo">191</span>  }<a name="line.191"></a>
-<span class="sourceLineNo">192</span><a name="line.192"></a>
-<span class="sourceLineNo">193</span>  /**<a name="line.193"></a>
-<span class="sourceLineNo">194</span>   * Clear away any progress that has been made so far. All progress fields are reset to initial<a name="line.194"></a>
-<span class="sourceLineNo">195</span>   * values<a name="line.195"></a>
-<span class="sourceLineNo">196</span>   */<a name="line.196"></a>
-<span class="sourceLineNo">197</span>  void clearProgress() {<a name="line.197"></a>
-<span class="sourceLineNo">198</span>    progress.setFields(0, 0, 0);<a name="line.198"></a>
-<span class="sourceLineNo">199</span>  }<a name="line.199"></a>
-<span class="sourceLineNo">200</span><a name="line.200"></a>
-<span class="sourceLineNo">201</span>  /**<a name="line.201"></a>
-<span class="sourceLineNo">202</span>   * Note that this is not a typical setter. This setter returns the {@link NextState} that was<a name="line.202"></a>
-<span class="sourceLineNo">203</span>   * passed in so that methods can be invoked against the new state. Furthermore, this pattern<a name="line.203"></a>
-<span class="sourceLineNo">204</span>   * allows the {@link NoLimitScannerContext} to cleanly override this setter and simply return the<a name="line.204"></a>
-<span class="sourceLineNo">205</span>   * new state, thus preserving the immutability of {@link NoLimitScannerContext}<a name="line.205"></a>
-<span class="sourceLineNo">206</span>   * @param state<a name="line.206"></a>
-<span class="sourceLineNo">207</span>   * @return The state that was passed in.<a name="line.207"></a>
-<span class="sourceLineNo">208</span>   */<a name="line.208"></a>
-<span class="sourceLineNo">209</span>  NextState setScannerState(NextState state) {<a name="line.209"></a>
-<span class="sourceLineNo">210</span>    if (!NextState.isValidState(state)) {<a name="line.210"></a>
-<span class="sourceLineNo">211</span>      throw new IllegalArgumentException("Cannot set to invalid state: " + state);<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>    this.scannerState = state;<a name="line.214"></a>
-<span class="sourceLineNo">215</span>    return state;<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>  /**<a name="line.218"></a>
-<span class="sourceLineNo">219</span>   * @return true when we have more cells for the current row. This usually because we have reached<a name="line.219"></a>
-<span class="sourceLineNo">220</span>   *         a limit in the middle of a row<a name="line.220"></a>
-<span class="sourceLineNo">221</span>   */<a name="line.221"></a>
-<span class="sourceLineNo">222</span>  boolean mayHaveMoreCellsInRow() {<a name="line.222"></a>
-<span class="sourceLineNo">223</span>    return scannerState == NextState.SIZE_LIMIT_REACHED_MID_ROW ||<a name="line.223"></a>
-<span class="sourceLineNo">224</span>        scannerState == NextState.TIME_LIMIT_REACHED_MID_ROW ||<a name="line.224"></a>
-<span class="sourceLineNo">225</span>        scannerState == NextState.BATCH_LIMIT_REACHED;<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>  /**<a name="line.228"></a>
-<span class="sourceLineNo">229</span>   * @param checkerScope<a name="line.229"></a>
-<span class="sourceLineNo">230</span>   * @return true if the batch limit can be enforced in the checker's scope<a name="line.230"></a>
-<span class="sourceLineNo">231</span>   */<a name="line.231"></a>
-<span class="sourceLineNo">232</span>  boolean hasBatchLimit(LimitScope checkerScope) {<a name="line.232"></a>
-<span class="sourceLineNo">233</span>    return limits.canEnforceBatchLimitFromScope(checkerScope) &amp;&amp; limits.getBatch() &gt; 0;<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>   * @param checkerScope<a name="line.237"></a>
-<span class="sourceLineNo">238</span>   * @return true if the size limit can be enforced in the checker's scope<a name="line.238"></a>
-<span class="sourceLineNo">239</span>   */<a name="line.239"></a>
-<span class="sourceLineNo">240</span>  boolean hasSizeLimit(LimitScope checkerScope) {<a name="line.240"></a>
-<span class="sourceLineNo">241</span>    return limits.canEnforceSizeLimitFromScope(checkerScope)<a name="line.241"></a>
-<span class="sourceLineNo">242</span>        &amp;&amp; (limits.getDataSize() &gt; 0 || limits.getHeapSize() &gt; 0);<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>  /**<a name="line.245"></a>
-<span class="sourceLineNo">246</span>   * @param checkerScope<a name="line.246"></a>
-<span class="sourceLineNo">247</span>   * @return true if the time limit can be enforced in the checker's scope<a name="line.247"></a>
-<span class="sourceLineNo">248</span>   */<a name="line.248"></a>
-<span class="sourceLineNo">249</span>  boolean hasTimeLimit(LimitScope checkerScope) {<a name="line.249"></a>
-<span class="sourceLineNo">250</span>    return limits.canEnforceTimeLimitFromScope(checkerScope) &amp;&amp; limits.getTime() &gt; 0;<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>   * @param checkerScope<a name="line.254"></a>
-<span class="sourceLineNo">255</span>   * @return true if any limit can be enforced within the checker's scope<a name="line.255"></a>
-<span class="sourceLineNo">256</span>   */<a name="line.256"></a>
-<span class="sourceLineNo">257</span>  boolean hasAnyLimit(LimitScope checkerScope) {<a name="line.257"></a>
-<span class="sourceLineNo">258</span>    return hasBatchLimit(checkerScope) || hasSizeLimit(checkerScope) || hasTimeLimit(checkerScope);<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>  /**<a name="line.261"></a>
-<span class="sourceLineNo">262</span>   * @param scope The scope in which the size limit will be enforced<a name="line.262"></a>
+<span class="sourceLineNo">113</span>  ScannerContext(boolean keepProgress, LimitFields limitsToCopy, boolean trackMetrics) {<a name="line.113"></a>
+<span class="sourceLineNo">114</span>    this.limits = new LimitFields();<a name="line.114"></a>
+<span class="sourceLineNo">115</span>    if (limitsToCopy != null) {<a name="line.115"></a>
+<span class="sourceLineNo">116</span>      this.limits.copy(limitsToCopy);<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>    // Progress fields are initialized to 0<a name="line.119"></a>
+<span class="sourceLineNo">120</span>    progress = new ProgressFields(0, 0, 0);<a name="line.120"></a>
+<span class="sourceLineNo">121</span><a name="line.121"></a>
+<span class="sourceLineNo">122</span>    this.keepProgress = keepProgress;<a name="line.122"></a>
+<span class="sourceLineNo">123</span>    this.scannerState = DEFAULT_STATE;<a name="line.123"></a>
+<span class="sourceLineNo">124</span>    this.metrics = trackMetrics ? new ServerSideScanMetrics() : null;<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>  boolean isTrackingMetrics() {<a name="line.127"></a>
+<span class="sourceLineNo">128</span>    return this.metrics != null;<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>   * Get the metrics instance. Should only be called after a call to {@link #isTrackingMetrics()}<a name="line.132"></a>
+<span class="sourceLineNo">133</span>   * has been made to confirm that metrics are indeed being tracked.<a name="line.133"></a>
+<span class="sourceLineNo">134</span>   * @return {@link ServerSideScanMetrics} instance that is tracking metrics for this scan<a name="line.134"></a>
+<span class="sourceLineNo">135</span>   */<a name="line.135"></a>
+<span class="sourceLineNo">136</span>  ServerSideScanMetrics getMetrics() {<a name="line.136"></a>
+<span class="sourceLineNo">137</span>    assert isTrackingMetrics();<a name="line.137"></a>
+<span class="sourceLineNo">138</span>    return this.metrics;<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>   * @return true if the progress tracked so far in this instance will be considered during an<a name="line.142"></a>
+<span class="sourceLineNo">143</span>   *         invocation of {@link InternalScanner#next(java.util.List)} or<a name="line.143"></a>
+<span class="sourceLineNo">144</span>   *         {@link RegionScanner#next(java.util.List)}. false when the progress tracked so far<a name="line.144"></a>
+<span class="sourceLineNo">145</span>   *         should not be considered and should instead be wiped away via {@link #clearProgress()}<a name="line.145"></a>
+<span class="sourceLineNo">146</span>   */<a name="line.146"></a>
+<span class="sourceLineNo">147</span>  boolean getKeepProgress() {<a name="line.147"></a>
+<span class="sourceLineNo">148</span>    return keepProgress;<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>  void setKeepProgress(boolean keepProgress) {<a name="line.151"></a>
+<span class="sourceLineNo">152</span>    this.keepProgress = keepProgress;<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>   * Progress towards the batch limit has been made. Increment internal tracking of batch progress<a name="line.156"></a>
+<span class="sourceLineNo">157</span>   */<a name="line.157"></a>
+<span class="sourceLineNo">158</span>  void incrementBatchProgress(int batch) {<a name="line.158"></a>
+<span class="sourceLineNo">159</span>    int currentBatch = progress.getBatch();<a name="line.159"></a>
+<span class="sourceLineNo">160</span>    progress.setBatch(currentBatch + batch);<a name="line.160"></a>
+<span class="sourceLineNo">161</span>  }<a name="line.161"></a>
+<span class="sourceLineNo">162</span><a name="line.162"></a>
+<span class="sourceLineNo">163</span>  /**<a name="line.163"></a>
+<span class="sourceLineNo">164</span>   * Progress towards the size limit has been made. Increment internal tracking of size progress<a name="line.164"></a>
+<span class="sourceLineNo">165</span>   */<a name="line.165"></a>
+<span class="sourceLineNo">166</span>  void incrementSizeProgress(long dataSize, long heapSize) {<a name="line.166"></a>
+<span class="sourceLineNo">167</span>    long curDataSize = progress.getDataSize();<a name="line.167"></a>
+<span class="sourceLineNo">168</span>    progress.setDataSize(curDataSize + dataSize);<a name="line.168"></a>
+<span class="sourceLineNo">169</span>    long curHeapSize = progress.getHeapSize();<a name="line.169"></a>
+<span class="sourceLineNo">170</span>    progress.setHeapSize(curHeapSize + heapSize);<a name="line.170"></a>
+<span class="sourceLineNo">171</span>  }<a name="line.171"></a>
+<span class="sourceLineNo">172</span><a name="line.172"></a>
+<span class="sourceLineNo">173</span>  int getBatchProgress() {<a name="line.173"></a>
+<span class="sourceLineNo">174</span>    return progress.getBatch();<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>  long getDataSizeProgress() {<a name="line.177"></a>
+<span class="sourceLineNo">178</span>    return progress.getDataSize();<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>  long getHeapSizeProgress() {<a name="line.181"></a>
+<span class="sourceLineNo">182</span>    return progress.getHeapSize();<a name="line.182"></a>
+<span class="sourceLineNo">183</span>  }<a name="line.183"></a>
+<span class="sourceLineNo">184</span><a name="line.184"></a>
+<span class="sourceLineNo">185</span>  void setProgress(int batchProgress, long sizeProgress, long heapSizeProgress) {<a name="line.185"></a>
+<span class="sourceLineNo">186</span>    setBatchProgress(batchProgress);<a name="line.186"></a>
+<span class="sourceLineNo">187</span>    setSizeProgress(sizeProgress, heapSizeProgress);<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>  void setSizeProgress(long dataSizeProgress, long heapSizeProgress) {<a name="line.190"></a>
+<span class="sourceLineNo">191</span>    progress.setDataSize(dataSizeProgress);<a name="line.191"></a>
+<span class="sourceLineNo">192</span>    progress.setHeapSize(heapSizeProgress);<a name="line.192"></a>
+<span class="sourceLineNo">193</span>  }<a name="line.193"></a>
+<span class="sourceLineNo">194</span><a name="line.194"></a>
+<span class="sourceLineNo">195</span>  void setBatchProgress(int batchProgress) {<a name="line.195"></a>
+<span class="sourceLineNo">196</span>    progress.setBatch(batchProgress);<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>   * Clear away any progress that has been made so far. All progress fields are reset to initial<a name="line.200"></a>
+<span class="sourceLineNo">201</span>   * values<a name="line.201"></a>
+<span class="sourceLineNo">202</span>   */<a name="line.202"></a>
+<span class="sourceLineNo">203</span>  void clearProgress() {<a name="line.203"></a>
+<span class="sourceLineNo">204</span>    progress.setFields(0, 0, 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>  /**<a name="line.207"></a>
+<span class="sourceLineNo">208</span>   * Note that this is not a typical setter. This setter returns the {@link NextState} that was<a name="line.208"></a>
+<span class="sourceLineNo">209</span>   * passed in so that methods can be invoked against the new state. Furthermore, this pattern<a name="line.209"></a>
+<span class="sourceLineNo">210</span>   * allows the {@link NoLimitScannerContext} to cleanly override this setter and simply return the<a name="line.210"></a>
+<span class="sourceLineNo">211</span>   * new state, thus preserving the immutability of {@link NoLimitScannerContext}<a name="line.211"></a>
+<span class="sourceLineNo">212</span>   * @param state<a name="line.212"></a>
+<span class="sourceLineNo">213</span>   * @return The state that was passed in.<a name="line.213"></a>
+<span class="sourceLineNo">214</span>   */<a name="line.214"></a>
+<span class="sourceLineNo">215</span>  NextState setScannerState(NextState state) {<a name="line.215"></a>
+<span class="sourceLineNo">216</span>    if (!NextState.isValidState(state)) {<a name="line.216"></a>
+<span class="sourceLineNo">217</span>      throw new IllegalArgumentException("Cannot set to invalid state: " + state);<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>    this.scannerState = state;<a name="line.220"></a>
+<span class="sourceLineNo">221</span>    return state;<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>  /**<a name="line.224"></a>
+<span class="sourceLineNo">225</span>   * @return true when we have more cells for the current row. This usually because we have reached<a name="line.225"></a>
+<span class="sourceLineNo">226</span>   *         a limit in the middle of a row<a name="line.226"></a>
+<span class="sourceLineNo">227</span>   */<a name="line.227"></a>
+<span class="sourceLineNo">228</span>  boolean mayHaveMoreCellsInRow() {<a name="line.228"></a>
+<span class="sourceLineNo">229</span>    return scannerState == NextState.SIZE_LIMIT_REACHED_MID_ROW ||<a name="line.229"></a>
+<span class="sourceLineNo">230</span>        scannerState == NextState.TIME_LIMIT_REACHED_MID_ROW ||<a name="line.230"></a>
+<span class="sourceLineNo">231</span>        scannerState == NextState.BATCH_LIMIT_REACHED;<a name="line.231"></a>
+<span class="sourceLineNo">232</span>  }<a name="line.232"></a>
+<span class="sourceLineNo">233</span><a name="line.233"></a>
+<span class="sourceLineNo">234</span>  /**<a name="line.234"></a>
+<span class="sourceLineNo">235</span>   * @param checkerScope<a name="line.235"></a>
+<span class="sourceLineNo">236</span>   * @return true if the batch limit can be enforced in the checker's scope<a name="line.236"></a>
+<span class="sourceLineNo">237</span>   */<a name="line.237"></a>
+<span class="sourceLineNo">238</span>  boolean hasBatchLimit(LimitScope checkerScope) {<a name="line.238"></a>
+<span class="sourceLineNo">239</span>    return limits.canEnforceBatchLimitFromScope(checkerScope) &amp;&amp; limits.getBatch() &gt; 0;<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>   * @param checkerScope<a name="line.243"></a>
+<span class="sourceLineNo">244</span>   * @return true if the size limit can be enforced in the checker's scope<a name="line.244"></a>
+<span class="sourceLineNo">245</span>   */<a name="line.245"></a>
+<span class="sourceLineNo">246</span>  boolean hasSizeLimit(LimitScope checkerScope) {<a name="line.246"></a>
+<span class="sourceLineNo">247</span>    return limits.canEnforceSizeLimitFromScope(checkerScope)<a name="line.247"></a>
+<span class="sourceLineNo">248</span>        &amp;&amp; (limits.getDataSize() &gt; 0 || limits.getHeapSize() &gt; 0);<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>
+<span class="sourceLineNo">252</span>   * @param checkerScope<a name="line.252"></a>
+<span class="sourceLineNo">253</span>   * @return true if the time limit can be enforced in the checker's scope<a name="line.253"></a>
+<span class="sourceLineNo">254</span>   */<a name="line.254"></a>
+<span class="sourceLineNo">255</span>  boolean hasTimeLimit(LimitScope checkerScope) {<a name="line.255"></a>
+<span class="sourceLineNo">256</span>    return limits.canEnforceTimeLimitFromScope(checkerScope) &amp;&amp;<a name="line.256"></a>
+<span class="sourceLineNo">257</span>      (limits.getTime() &gt; 0 || returnImmediately);<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>   * @param checkerScope<a name="line.261"></a>
+<span class="sourceLineNo">262</span>   * @return true if any limit can be enforced within the checker's scope<a name="line.262"></a>
 <span class="sourceLineNo">263</span>   */<a name="line.263"></a>
-<span class="sourceLineNo">264</span>  void setSizeLimitScope(LimitScope scope) {<a name="line.264"></a>
-<span class="sourceLineNo">265</span>    limits.setSizeScope(scope);<a name="line.265"></a>
+<span class="sourceLineNo">264</span>  boolean hasAnyLimit(LimitScope checkerScope) {<a name="line.264"></a>
+<span class="sourceLineNo">265</span>    return hasBatchLimit(checkerScope) || hasSizeLimit(checkerScope) || hasTimeLimit(checkerScope);<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>  /**<a name="line.268"></a>
-<span class="sourceLineNo">269</span>   * @param scope The scope in which the time limit will be enforced<a name="line.269"></a>
+<span class="sourceLineNo">269</span>   * @param scope The scope in which the size limit will be enforced<a name="line.269"></a>
 <span class="sourceLineNo">270</span>   */<a name="line.270"></a>
-<span class="sourceLineNo">271</span>  void setTimeLimitScope(LimitScope scope) {<a name="line.271"></a>
-<span class="sourceLineNo">272</span>    limits.setTimeScope(scope);<a name="line.272"></a>
+<span class="sourceLineNo">271</span>  void setSizeLimitScope(LimitScope scope) {<a name="line.271"></a>
+<span class="sourceLineNo">272</span>    limits.setSizeScope(scope);<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>  int getBatchLimit() {<a name="line.275"></a>
-<span class="sourceLineNo">276</span>    return limits.getBatch();<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>  long getDataSizeLimit() {<a name="line.279"></a>
-<span class="sourceLineNo">280</span>    return limits.getDataSize();<a name="line.280"></a>
-<span class="sourceLineNo">281</span>  }<a name="line.281"></a>
-<span class="sourceLineNo">282</span><a name="line.282"></a>
-<span class="sourceLineNo">283</span>  long getTimeLimit() {<a name="line.283"></a>
-<span class="sourceLineNo">284</span>    return limits.getTime();<a name="line.284"></a>
-<span class="sourceLineNo">285</span>  }<a name="line.285"></a>
-<span class="sourceLineNo">286</span><a name="line.286"></a>
-<span class="sourceLineNo">287</span>  /**<a name="line.287"></a>
-<span class="sourceLineNo">288</span>   * @param checkerScope The scope that the limit is being checked from<a name="line.288"></a>
-<span class="sourceLineNo">289</span>   * @return true when the limit is enforceable from the checker's scope and it has been reached<a name="line.289"></a>
-<span class="sourceLineNo">290</span>   */<a name="line.290"></a>
-<span class="sourceLineNo">291</span>  boolean checkBatchLimit(LimitScope checkerScope) {<a name="line.291"></a>
-<span class="sourceLineNo">292</span>    return hasBatchLimit(checkerScope) &amp;&amp; progress.getBatch() &gt;= limits.getBatch();<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>  /**<a name="line.295"></a>
-<span class="sourceLineNo">296</span>   * @param checkerScope The scope that the limit is being checked from<a name="line.296"></a>
-<span class="sourceLineNo">297</span>   * @return true when the limit is enforceable from the checker's scope and it has been reached<a name="line.297"></a>
-<span class="sourceLineNo">298</span>   */<a name="line.298"></a>
-<span class="sourceLineNo">299</span>  boolean checkSizeLimit(LimitScope checkerScope) {<a name="line.299"></a>
-<span class="sourceLineNo">300</span>    return hasSizeLimit(checkerScope) &amp;&amp; (progress.getDataSize() &gt;= limits.getDataSize()<a name="line.300"></a>
-<span class="sourceLineNo">301</span>        || progress.getHeapSize() &gt;= limits.getHeapSize());<a name="line.301"></a>
-<span class="sourceLineNo">302</span>  }<a name="line.302"></a>
-<span class="sourceLineNo">303</span><a name="line.303"></a>
-<span class="sourceLineNo">304</span>  /**<a name="line.304"></a>
-<span class="sourceLineNo">305</span>   * @param checkerScope The scope that the limit is being checked from. The time limit is always<a name="line.305"></a>
-<span class="sourceLineNo">306</span>   *          checked against {@link System#currentTimeMillis()}<a name="line.306"></a>
-<span class="sourceLineNo">307</span>   * @return true when the limit is enforceable from the checker's scope and it has been reached<a name="line.307"></a>
-<span class="sourceLineNo">308</span>   */<a name="line.308"></a>
-<span class="sourceLineNo">309</span>  boolean checkTimeLimit(LimitScope checkerScope) {<a name="line.309"></a>
-<span class="sourceLineNo">310</span>    return hasTimeLimit(checkerScope) &amp;&amp; (System.currentTimeMillis() &gt;= limits.getTime());<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>   * @param checkerScope The scope that the limits are being checked from<a name="line.314"></a>
-<span class="sourceLineNo">315</span>   * @return true when some limit is enforceable from the checker's scope and it has been reached<a name="line.315"></a>
-<span class="sourceLineNo">316</span>   */<a name="line.316"></a>
-<span class="sourceLineNo">317</span>  boolean checkAnyLimitReached(LimitScope checkerScope) {<a name="line.317"></a>
-<span class="sourceLineNo">318</span>    return checkSizeLimit(checkerScope) || checkBatchLimit(checkerScope)<a name="line.318"></a>
-<span class="sourceLineNo">319</span>        || checkTimeLimit(checkerScope);<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>  Cell getLastPeekedCell() {<a name="line.322"></a>
-<span class="sourceLineNo">323</span>    return lastPeekedCell;<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>  void setLastPeekedCell(Cell lastPeekedCell) {<a name="line.326"></a>
-<span class="sourceLineNo">327</span>    this.lastPeekedCell = lastPeekedCell;<a name="line.327"></a>
+<span class="sourceLineNo">275</span>  /**<a name="line.275"></a>
+<span class="sourceLineNo">276</span>   * @param scope The scope in which the time limit will be enforced<a name="line.276"></a>
+<span class="sourceLineNo">277</span>   */<a name="line.277"></a>
+<span class="sourceLineNo">278</span>  void setTimeLimitScope(LimitScope scope) {<a name="line.278"></a>
+<span class="sourceLineNo">279</span>    limits.setTimeScope(scope);<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>  int getBatchLimit() {<a name="line.282"></a>
+<span class="sourceLineNo">283</span>    return limits.getBatch();<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>  long getDataSizeLimit() {<a name="line.286"></a>
+<span class="sourceLineNo">287</span>    return limits.getDataSize();<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>  long getTimeLimit() {<a name="line.290"></a>
+<span class="sourceLineNo">291</span>    return limits.getTime();<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>   * @param checkerScope The scope that the limit is being checked from<a name="line.295"></a>
+<span class="sourceLineNo">296</span>   * @return true when the limit is enforceable from the checker's scope and it has been reached<a name="line.296"></a>
+<span class="sourceLineNo">297</span>   */<a name="line.297"></a>
+<span class="sourceLineNo">298</span>  boolean checkBatchLimit(LimitScope checkerScope) {<a name="line.298"></a>
+<span class="sourceLineNo">299</span>    return hasBatchLimit(checkerScope) &amp;&amp; progress.getBatch() &gt;= limits.getBatch();<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 checkerScope The scope that the limit is being checked from<a name="line.303"></a>
+<span class="sourceLineNo">304</span>   * @return true when the limit is enforceable from the checker's scope and it has been reached<a name="line.304"></a>
+<span class="sourceLineNo">305</span>   */<a name="line.305"></a>
+<span class="sourceLineNo">306</span>  boolean checkSizeLimit(LimitScope checkerScope) {<a name="line.306"></a>
+<span class="sourceLineNo">307</span>    return hasSizeLimit(checkerScope) &amp;&amp; (progress.getDataSize() &gt;= limits.getDataSize()<a name="line.307"></a>
+<span class="sourceLineNo">308</span>        || progress.getHeapSize() &gt;= limits.getHeapSize());<a name="line.308"></a>
+<span class="sourceLineNo">309</span>  }<a name="line.309"></a>
+<span class="sourceLineNo">310</span><a name="line.310"></a>
+<span class="sourceLineNo">311</span>  /**<a name="line.311"></a>
+<span class="sourceLineNo">312</span>   * @param checkerScope The scope that the limit is being checked from. The time limit is always<a name="line.312"></a>
+<span class="sourceLineNo">313</span>   *          checked against {@link System#currentTimeMillis()}<a name="line.313"></a>
+<span class="sourceLineNo">314</span>   * @return true when the limit is enforceable from the checker's scope and it has been reached<a name="line.314"></a>
+<span class="sourceLineNo">315</span>   */<a name="line.315"></a>
+<span class="sourceLineNo">316</span>  boolean checkTimeLimit(LimitScope checkerScope) {<a name="line.316"></a>
+<span class="sourceLineNo">317</span>    return hasTimeLimit(checkerScope) &amp;&amp;<a name="line.317"></a>
+<span class="sourceLineNo">318</span>      (returnImmediately || System.currentTimeMillis() &gt;= limits.getTime());<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>   * @param checkerScope The scope that the limits are being checked from<a name="line.322"></a>
+<span class="sourceLineNo">323</span>   * @return true when some limit is enforceable from the checker's scope and it has been reached<a name="line.323"></a>
+<span class="sourceLineNo">324</span>   */<a name="line.324"></a>
+<span class="sourceLineNo">325</span>  boolean checkAnyLimitReached(LimitScope checkerScope) {<a name="line.325"></a>
+<span class="sourceLineNo">326</span>    return checkSizeLimit(checkerScope) || checkBatchLimit(checkerScope)<a name="line.326"></a>
+<span class="sourceLineNo">327</span>        || checkTimeLimit(checkerScope);<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>  @Override<a name="line.330"></a>
-<span class="sourceLineNo">331</span>  public String toString() {<a name="line.331"></a>
-<span class="sourceLineNo">332</span>    StringBuilder sb = new StringBuilder();<a name="line.332"></a>
-<span class="sourceLineNo">333</span>    sb.append("{");<a name="line.333"></a>
-<span class="sourceLineNo">334</span><a name="line.334"></a>
-<span class="sourceLineNo">335</span>    sb.append("limits:");<a name="line.335"></a>
-<span class="sourceLineNo">336</span>    sb.append(limits);<a name="line.336"></a>
+<span class="sourceLineNo">330</span>  Cell getLastPeekedCell() {<a name="line.330"></a>
+<span class="sourceLineNo">331</span>    return lastPeekedCell;<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>  void setLastPeekedCell(Cell lastPeekedCell) {<a name="line.334"></a>
+<span class="sourceLineNo">335</span>    this.lastPeekedCell = lastPeekedCell;<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>    sb.append(", progress:");<a name="line.338"></a>
-<span class="sourceLineNo">339</span>    sb.append(progress);<a name="line.339"></a>
-<span class="sourceLineNo">340</span><a name="line.340"></a>
-<span class="sourceLineNo">341</span>    sb.append(", keepProgress:");<a name="line.341"></a>
-<span class="sourceLineNo">342</span>    sb.append(keepProgress);<a name="line.342"></a>
-<span class="sourceLineNo">343</span><a name="line.343"></a>
-<span class="sourceLineNo">344</span>    sb.append(", state:");<a name="line.344"></a>
-<span class="sourceLineNo">345</span>    sb.append(scannerState);<a name="line.345"></a>
+<span class="sourceLineNo">338</span>  void returnImmediately() {<a name="line.338"></a>
+<span class="sourceLineNo">339</span>    this.returnImmediately = true;<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>  @Override<a name="line.342"></a>
+<span class="sourceLineNo">343</span>  public String toString() {<a name="line.343"></a>
+<span class="sourceLineNo">344</span>    StringBuilder sb = new StringBuilder();<a name="line.344"></a>
+<span class="sourceLineNo">345</span>    sb.append("{");<a name="line.345"></a>
 <span class="sourceLineNo">346</span><a name="line.346"></a>
-<span class="sourceLineNo">347</span>    sb.append("}");<a name="line.347"></a>
-<span class="sourceLineNo">348</span>    return sb.toString();<a name="line.348"></a>
-<span class="sourceLineNo">349</span>  }<a name="line.349"></a>
-<span class="sourceLineNo">350</span><a name="line.350"></a>
-<span class="sourceLineNo">351</span>  public static Builder newBuilder() {<a name="line.351"></a>
-<span class="sourceLineNo">352</span>    return new Builder();<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 static Builder newBuilder(boolean keepProgress) {<a name="line.355"></a>
-<span class="sourceLineNo">356</span>    return new Builder(keepProgress);<a name="line.356"></a>
-<span class="sourceLineNo">357</span>  }<a name="line.357"></a>
+<span class="sourceLineNo">347</span>    sb.append("limits:");<a name="line.347"></a>
+<span class="sourceLineNo">348</span>    sb.append(limits);<a name="line.348"></a>
+<span class="sourceLineNo">349</span><a name="line.349"></a>
+<span class="sourceLineNo">350</span>    sb.append(", progress:");<a name="line.350"></a>
+<span class="sourceLineNo">351</span>    sb.append(progress);<a name="line.351"></a>
+<span class="sourceLineNo">352</span><a name="line.352"></a>
+<span class="sourceLineNo">353</span>    sb.append(", keepProgress:");<a name="line.353"></a>
+<span class="sourceLineNo">354</span>    sb.append(keepProgress);<a name="line.354"></a>
+<span class="sourceLineNo">355</span><a name="line.355"></a>
+<span class="sourceLineNo">356</span>    sb.append(", state:");<a name="line.356"></a>
+<span class="sourceLineNo">357</span>    sb.append(scannerState);<a name="line.357"></a>
 <span class="sourceLineNo">358</span><a name="line.358"></a>
-<span class="sourceLineNo">359</span>  public static final class Builder {<a name="line.359"></a>
-<span class="sourceLineNo">360</span>    boolean keepProgress = DEFAULT_KEEP_PROGRESS;<a name="line.360"></a>
-<span class="sourceLineNo">361</span>    boolean trackMetrics = false;<a name="line.361"></a>
-<span class="sourceLineNo">362</span>    LimitFields limits = new LimitFields();<a name="line.362"></a>
-<span class="sourceLineNo">363</span><a name="line.363"></a>
-<span class="sourceLineNo">364</span>    private Builder() {<a name="line.364"></a>
-<span class="sourceLineNo">365</span>    }<a name="line.365"></a>
+<span class="sourceLineNo">359</span>    sb.append("}");<a name="line.359"></a>
+<span class="sourceLineNo">360</span>    return sb.toString();<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 static Builder newBuilder() {<a name="line.363"></a>
+<span class="sourceLineNo">364</span>    return new Builder();<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>    private Builder(boolean keepProgress) {<a name="line.367"></a>
-<span class="sourceLineNo">368</span>      this.keepProgress = keepProgress;<a name="line.368"></a>
-<span class="sourceLineNo">369</span>    }<a name="line.369"></a>
+<span class="sourceLineNo">367</span>  public static Builder newBuilder(boolean keepProgress) {<a name="line.367"></a>
+<span class="sourceLineNo">368</span>    return new Builder(keepProgress);<a name="line.368"></a>
+<span class="sourceLineNo">369</span>  }<a name="line.369"></a>
 <span class="sourceLineNo">370</span><a name="line.370"></a>
-<span class="sourceLineNo">371</span>    public Builder setKeepProgress(boolean keepProgress) {<a name="line.371"></a>
-<span class="sourceLineNo">372</span>      this.keepProgress = keepProgress;<a name="line.372"></a>
-<span class="sourceLineNo">373</span>      return this;<a name="line.373"></a>
-<span class="sourceLineNo">374</span>    }<a name="line.374"></a>
+<span class="sourceLineNo">371</span>  public static final class Builder {<a name="line.371"></a>
+<span class="sourceLineNo">372</span>    boolean keepProgress = DEFAULT_KEEP_PROGRESS;<a name="line.372"></a>
+<span class="sourceLineNo">373</span>    boolean trackMetrics = false;<a name="line.373"></a>
+<span class="sourceLineNo">374</span>    LimitFields limits = new LimitFields();<a name="line.374"></a>
 <span class="sourceLineNo">375</span><a name="line.375"></a>
-<span class="sourceLineNo">376</span>    public Builder setTrackMetrics(boolean trackMetrics) {<a name="line.376"></a>
-<span class="sourceLineNo">377</span>      this.trackMetrics = trackMetrics;<a name="line.377"></a>
-<span class="sourceLineNo">378</span>      return this;<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 Builder setSizeLimit(LimitScope sizeScope, long dataSizeLimit, long heapSizeLimit) {<a name="line.381"></a>
-<span class="sourceLineNo">382</span>      limits.setDataSize(dataSizeLimit);<a name="line.382"></a>
-<span class="sourceLineNo">383</span>      limits.setHeapSize(heapSizeLimit);<a name="line.383"></a>
-<span class="sourceLineNo">384</span>      limits.setSizeScope(sizeScope);<a name="line.384"></a>
+<span class="sourceLineNo">376</span>    private Builder() {<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>    private Builder(boolean keepProgress) {<a name="line.379"></a>
+<span class="sourceLineNo">380</span>      this.keepProgress = keepProgress;<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>    public Builder setKeepProgress(boolean keepProgress) {<a name="line.383"></a>
+<span class="sourceLineNo">384</span>      this.keepProgress = keepProgress;<a name="line.384"></a>
 <span class="sourceLineNo">385</span>      return this;<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 Builder setTimeLimit(LimitScope timeScope, long timeLimit) {<a name="line.388"></a>
-<span class="sourceLineNo">389</span>      limits.setTime(timeLimit);<a name="line.389"></a>
-<span class="sourceLineNo">390</span>      limits.setTimeScope(timeScope);<a name="line.390"></a>
-<span class="sourceLineNo">391</span>      return this;<a name="line.391"></a>
-<span class="sourceLineNo">392</span>    }<a name="line.392"></a>
-<span class="sourceLineNo">393</span><a name="line.393"></a>
-<span class="sourceLineNo">394</span>    public Builder setBatchLimit(int batchLimit) {<a name="line.394"></a>
-<span class="sourceLineNo">395</span>      limits.setBatch(batchLimit);<a name="line.395"></a>
-<span class="sourceLineNo">396</span>      return this;<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>    public ScannerContext build() {<a name="line.399"></a>
-<span class="sourceLineNo">400</span>      return new ScannerContext(keepProgress, limits, trackMetrics);<a name="line.400"></a>
-<span class="sourceLineNo">401</span>    }<a name="line.401"></a>
-<span class="sourceLineNo">402</span>  }<a name="line.402"></a>
-<span class="sourceLineNo">403</span><a name="line.403"></a>
-<span class="sourceLineNo">404</span>  /**<a name="line.404"></a>
-<span class="sourceLineNo">405</span>   * The possible states a scanner may be in following a call to {@link InternalScanner#next(List)}<a name="line.405"></a>
-<span class="sourceLineNo">406</span>   */<a name="line.406"></a>
-<span class="sourceLineNo">407</span>  public enum NextState {<a name="line.407"></a>
-<span class="sourceLineNo">408</span>    MORE_VALUES(true, false),<a name="line.408"></a>
-<span class="sourceLineNo">409</span>    NO_MORE_VALUES(false, false),<a name="line.409"></a>
-<span class="sourceLineNo">410</span>    SIZE_LIMIT_REACHED(true, true),<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>     * Special case of size limit reached to indicate that the size limit was reached in the middle<a name="line.413"></a>
-<span class="sourceLineNo">414</span>     * of a row and thus a partial results was formed<a name="line.414"></a>
-<span class="sourceLineNo">415</span>     */<a name="line.415"></a>
-<span class="sourceLineNo">416</span>    SIZE_LIMIT_REACHED_MID_ROW(true, true),<a name="line.416"></a>
-<span class="sourceLineNo">417</span>    TIME_LIMIT_REACHED(true, true),<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>     * Special case of time limit reached to indicate that the time limit was reached in the middle<a name="line.420"></a>
-<span class="sourceLineNo">421</span>     * of a row and thus a partial results was formed<a name="line.421"></a>
-<span class="sourceLineNo">422</span>     */<a name="line.422"></a>
-<span class="sourceLineNo">423</span>    TIME_LIMIT_REACHED_MID_ROW(true, true),<a name="line.423"></a>
-<span class="sourceLineNo">424</span>    BATCH_LIMIT_REACHED(true, true);<a name="line.424"></a>
-<span class="sourceLineNo">425</span><a name="line.425"></a>
-<span class="sourceLineNo">426</span>    private final boolean moreValues;<a name="line.426"></a>
-<span class="sourceLineNo">427</span>    private final boolean limitReached;<a name="line.427"></a>
-<span class="sourceLineNo">428</span><a name="line.428"></a>
-<span class="sourceLineNo">429</span>    private NextState(boolean moreValues, boolean limitReached) {<a name="line.429"></a>
-<span class="sourceLineNo">430</span>      this.moreValues = moreValues;<a name="line.430"></a>
-<span class="sourceLineNo">431</span>      this.limitReached = limitReached;<a name="line.431"></a>
-<span class="sourceLineNo">432</span>    }<a name="line.432"></a>
-<span class="sourceLineNo">433</span><a name="line.433"></a>
-<span class="sourceLineNo">434</span>    /**<a name="line.434"></a>
-<span class="sourceLineNo">435</span>     * @return true when the state indicates that more values may follow those that have been<a name="line.435"></a>
-<span class="sourceLineNo">436</span>     *         returned<a name="line.436"></a>
-<span class="sourceLineNo">437</span>     */<a name="line.437"></a>
-<span class="sourceLineNo">438</span>    public boolean hasMoreValues() {<a name="line.438"></a>
-<span class="sourceLineNo">439</span>      return this.moreValues;<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>     * @return true when the state indicates that a limit has been reached and scan should stop<a name="line.443"></a>
-<span class="sourceLineNo">444</span>     */<a name="line.444"></a>
-<span class="sourceLineNo">445</span>    public boolean limitReached() {<a name="line.445"></a>
-<span class="sourceLineNo">446</span>      return this.limitReached;<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>    public static boolean isValidState(NextState state) {<a name="line.449"></a>
-<span class="sourceLineNo">450</span>      return state != null;<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>    public static boolean hasMoreValues(NextState state) {<a name="line.453"></a>
-<span class="sourceLineNo">454</span>      return isValidState(state) &amp;&amp; state.hasMoreValues();<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>  /**<a name="line.458"></a>
-<span class="sourceLineNo">459</span>   * The various scopes where a limit can be enforced. Used to differentiate when a limit should be<a name="line.459"></a>
-<span class="sourceLineNo">460</span>   * enforced or not.<a name="line.460"></a>
-<span class="sourceLineNo">461</span>   */<a name="line.461"></a>
-<span class="sourceLineNo">462</span>  public enum LimitScope {<a name="line.462"></a>
-<span class="sourceLineNo">463</span>    /**<a name="line.463"></a>
-<span class="sourceLineNo">464</span>     * Enforcing a limit between rows means that the limit will not be considered until all the<a name="line.464"></a>
-<span class="sourceLineNo">465</span>     * cells for a particular row have been retrieved<a name="line.465"></a>
-<span class="sourceLineNo">466</span>     */<a name="line.466"></a>
-<span class="sourceLineNo">467</span>    BETWEEN_ROWS(0),<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>     * Enforcing a limit between cells means that the limit will be considered after each full cell<a name="line.470"></a>
-<span class="sourceLineNo">471</span>     * has been retrieved<a name="line.471"></a>
-<span class="sourceLineNo">472</span>     */<a name="line.472"></a>
-<span class="sourceLineNo">473</span>    BETWEEN_CELLS(1);<a name="line.473"></a>
-<span class="sourceLineNo">474</span><a name="line.474"></a>
+<span class="sourceLineNo">388</span>    public Builder setTrackMetrics(boolean trackMetrics) {<a name="line.388"></a>
+<span class="sourceLineNo">389</span>      this.trackMetrics = trackMetrics;<a name="line.389"></a>
+<span class="sourceLineNo">390</span>      return this;<a name="line.390"></a>
+<span class="sourceLineNo">391</span>    }<a name="line.391"></a>
+<span class="sourceLineNo">392</span><a name="line.392"></a>
+<span class="sourceLineNo">393</span>    public Builder setSizeLimit(LimitScope sizeScope, long dataSizeLimit, long heapSizeLimit) {<a name="line.393"></a>
+<span class="sourceLineNo">394</span>      limits.setDataSize(dataSizeLimit);<a name="line.394"></a>
+<span class="sourceLineNo">395</span>      limits.setHeapSize(heapSizeLimit);<a name="line.395"></a>
+<span class="sourceLineNo">396</span>      limits.setSizeScope(sizeScope);<a name="line.396"></a>
+<span class="sourceLineNo">397</span>      return this;<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>    public Builder setTimeLimit(LimitScope timeScope, long timeLimit) {<a name="line.400"></a>
+<span class="sourceLineNo">401</span>      limits.setTime(timeLimit);<a name="line.401"></a>
+<span class="sourceLineNo">402</span>      limits.setTimeScope(timeScope);<a name="line.402"></a>
+<span class="sourceLineNo">403</span>      return this;<a name="line.403"></a>
+<span class="sourceLineNo">404</span>    }<a name="line.404"></a>
+<span class="sourceLineNo">405</span><a name="line.405"></a>
+<span class="sourceLineNo">406</span>    public Builder setBatchLimit(int batchLimit) {<a name="line.406"></a>
+<span class="sourceLineNo">407</span>      limits.setBatch(batchLimit);<a name="line.407"></a>
+<span class="sourceLineNo">408</span>      return this;<a name="line.408"></a>
+<span class="sourceLineNo">409</span>    }<a name="line.409"></a>
+<span class="sourceLineNo">410</span><a name="line.410"></a>
+<span class="sourceLineNo">411</span>    public ScannerContext build() {<a name="line.411"></a>
+<span class="sourceLineNo">412</span>      return new ScannerContext(keepProgress, limits, trackMetrics);<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><a name="line.415"></a>
+<span class="sourceLineNo">416</span>  /**<a name="line.416"></a>
+<span class="sourceLineNo">417</span>   * The possible states a scanner may be in following a call to {@link InternalScanner#next(List)}<a name="line.417"></a>
+<span class="sourceLineNo">418</span>   */<a name="line.418"></a>
+<span class="sourceLineNo">419</span>  public enum NextState {<a name="line.419"></a>
+<span class="sourceLineNo">420</span>    MORE_VALUES(true, false),<a name="line.420"></a>
+<span class="sourceLineNo">421</span>    NO_MORE_VALUES(false, false),<a name="line.421"></a>
+<span class="sourceLineNo">422</span>    SIZE_LIMIT_REACHED(true, true),<a name="line.422"></a>
+<span class="sourceLineNo">423</span><a name="line.423"></a>
+<span class="sourceLineNo">424</span>    /**<a name="line.424"></a>
+<span class="sourceLineNo">425</span>     * Special case of size limit reached to indicate that the size limit was reached in the middle<a name="line.425"></a>
+<span class="sourceLineNo">426</span>     * of a row and thus a partial results was formed<a name="line.426"></a>
+<span class="sourceLineNo">427</span>     */<a name="line.427"></a>
+<span class="sourceLineNo">428</span>    SIZE_LIMIT_REACHED_MID_ROW(true, true),<a name="line.428"></a>
+<span class="sourceLineNo">429</span>    TIME_LIMIT_REACHED(true, true),<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>     * Special case of time limit reached to indicate that the time limit was reached in the middle<a name="line.432"></a>
+<span class="sourceLineNo">433</span>     * of a row and thus a partial results was formed<a name="line.433"></a>
+<span class="sourceLineNo">434</span>     */<a name="line.434"></a>
+<span class="sourceLineNo">435</span>    TIME_LIMIT_REACHED_MID_ROW(true, true),<a name="line.435"></a>
+<span class="sourceLineNo">436</span>    BATCH_LIMIT_REACHED(true, true);<a name="line.436"></a>
+<span class="sourceLineNo">437</span><a name="line.437"></a>
+<span class="sourceLineNo">438</span>    private final boolean moreValues;<a name="line.438"></a>
+<span class="sourceLineNo">439</span>    private final boolean limitReached;<a name="line.439"></a>
+<span class="sourceLineNo">440</span><a name="line.440"></a>
+<span class="sourceLineNo">441</span>    private NextState(boolean moreValues, boolean limitReached) {<a name="line.441"></a>
+<span class="sourceLineNo">442</span>      this.moreValues = moreValues;<a name="line.442"></a>
+<span class="sourceLineNo">443</span>      this.limitReached = limitReached;<a name="line.443"></a>
+<span class="sourceLineNo">444</span>    }<a name="line.444"></a>
+<span class="sourceLineNo">445</span><a name="line.445"></a>
+<span class="sourceLineNo">446</span>    /**<a name="line.446"></a>
+<span class="sourceLineNo">447</span>     * @return true when the state indicates that more values may follow those that have been<a name="line.447"></a>
+<span class="sourceLineNo">448</span>     *         returned<a name="line.448"></a>
+<span class="sourceLineNo">449</span>     */<a name="line.449"></a>
+<span class="sourceLineNo">450</span>    public boolean hasMoreValues() {<a name="line.450"></a>
+<span class="sourceLineNo">451</span>      return this.moreValues;<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>     * @return true when the state indicates that a limit has been reached and scan should stop<a name="line.455"></a>
+<span class="sourceLineNo">456</span>     */<a name="line.456"></a>
+<span class="sourceLineNo">457</span>    public boolean limitReached() {<a name="line.457"></a>
+<span class="sourceLineNo">458</span>      return this.limitReached;<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>    public static boolean isValidState(NextState state) {<a name="line.461"></a>
+<span class="sourceLineNo">462</span>      return state != 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>    public static boolean hasMoreValues(NextState state) {<a name="line.465"></a>
+<span class="sourceLineNo">466</span>      return isValidState(state) &amp;&amp; state.hasMoreValues();<a name="line.466"></a>
+<span class="sourceLineNo">467</span>    }<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>   * The various scopes where a limit can be enforced. Used to differentiate when a limit should be<a name="line.471"></a>
+<span class="sourceLineNo">472</span>   * enforced or not.<a name="line.472"></a>
+<span class="sourceLineNo">473</span>   */<a name="line.473"></a>
+<span class="sourceLineNo">474</span>  public enum LimitScope {<a name="line.474"></a>
 <span class="sourceLineNo">475</span>    /**<a name="line.475"></a>
-<span class="sourceLineNo">476</span>     * When enforcing a limit, we must check that the scope is appropriate for enforcement.<a name="line.476"></a>
-<span class="sourceLineNo">477</span>     * &lt;p&gt;<a name="line.477"></a>
-<span class="sourceLineNo">478</span>     * To communicate this concept, each scope has a depth. A limit will be enforced if the depth of<a name="line.478"></a>
-<span class="sourceLineNo">479</span>     * the checker's scope is less than or equal to the limit's scope. This means that when checking<a name="line.479"></a>
-<span class="sourceLineNo">480</span>     * limits, the checker must know their own scope (i.e. are they checking the limits between<a name="line.480"></a>
-<span class="sourceLineNo">481</span>     * rows, between cells, etc...)<a name="line.481"></a>
-<span class="sourceLineNo">482</span>     */<a name="line.482"></a>
-<span class="sourceLineNo">483</span>    final int depth;<a name="line.483"></a>
-<span class="sourceLineNo">484</span><a name="line.484"></a>
-<span class="sourceLineNo">485</span>    LimitScope(int depth) {<a name="line.485"></a>
-<span class="sourceLineNo">486</span>      this.depth = depth;<a name="line.486"></a>
-<span class="sourceLineNo">487</span>    }<a name="line.487"></a>
-<span class="sourceLineNo">488</span><a name="line.488"></a>
-<span class="sourceLineNo">489</span>    final int depth() {<a name="line.489"></a>
-<span class="sourceLineNo">490</span>      return depth;<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>     * @param checkerScope The scope in which the limit is being checked<a name="line.494"></a>
-<span class="sourceLineNo">495</span>     * @return true when the checker is in a scope that indicates the limit can be enforced. Limits<a name="line.495"></a>
-<span class="sourceLineNo">496</span>     *         can be enforced from "higher or equal" scopes (i.e. the checker's scope is at a<a name="line.496"></a>
-<span class="sourceLineNo">497</span>     *         lesser depth than the limit)<a name="line.497"></a>
-<span class="sourceLineNo">498</span>     */<a name="line.498"></a>
-<span class="sourceLineNo">499</span>    boolean canEnforceLimitFromScope(LimitScope checkerScope) {<a name="line.499"></a>
-<span class="sourceLineNo">500</span>      return checkerScope != null &amp;&amp; checkerScope.depth() &lt;= depth;<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><a name="line.503"></a>
-<span class="sourceLineNo">504</span>  /**<a name="line.504"></a>
-<span class="sourceLineNo">505</span>   * The different fields that can be used as limits in calls to<a name="line.505"></a>
-<span class="sourceLineNo">506</span>   * {@link InternalScanner#next(java.util.List)} and {@link RegionScanner#next(java.util.List)}<a name="line.506"></a>
-<span class="sourceLineNo">507</span>   */<a name="line.507"></a>
-<span class="sourceLineNo">508</span>  private static class LimitFields {<a name="line.508"></a>
-<span class="sourceLineNo">509</span>    /**<a name="line.509"></a>
-<span class="sourceLineNo">510</span>     * Default values of the limit fields. Defined such that if a field does NOT change from its<a name="line.510"></a>
-<span class="sourceLineNo">511</span>     * default, it will not be enforced<a name="line.511"></a>
-<span class="sourceLineNo">512</span>     */<a name="line.512"></a>
-<span class="sourceLineNo">513</span>    private static int DEFAULT_BATCH = -1;<a name="line.513"></a>
-<span class="sourceLineNo">514</span>    private static long DEFAULT_SIZE = -1L;<a name="line.514"></a>
-<span class="sourceLineNo">515</span>    private static long DEFAULT_TIME = -1L;<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>     * Default scope that is assigned to a limit if a scope is not specified.<a name="line.518"></a>
-<span class="sourceLineNo">519</span>     */<a name="line.519"></a>
-<span class="sourceLineNo">520</span>    private static final LimitScope DEFAULT_SCOPE = LimitScope.BETWEEN_ROWS;<a name="line.520"></a>
-<span class="sourceLineNo">521</span><a name="line.521"></a>
-<span class="sourceLineNo">522</span>    // The batch limit will always be enforced between cells, thus, there isn't a field to hold the<a name="line.522"></a>
-<span class="sourceLineNo">523</span>    // batch scope<a name="line.523"></a>
-<span class="sourceLineNo">524</span>    int batch = DEFAULT_BATCH;<a name="line.524"></a>
-<span class="sourceLineNo">525</span><a name="line.525"></a>
-<span class="sourceLineNo">526</span>    LimitScope sizeScope = DEFAULT_SCOPE;<a name="line.526"></a>
-<span class="sourceLineNo">527</span>    // The sum of cell data sizes(key + value). The Cell data might be in on heap or off heap area.<a name="line.527"></a>
-<span class="sourceLineNo">528</span>    long dataSize = DEFAULT_SIZE;<a name="line.528"></a>
-<span class="sourceLineNo">529</span>    // The sum of heap space occupied by all tracked cells. This includes Cell POJO's overhead as<a name="line.529"></a>
-<span class="sourceLineNo">530</span>    // such AND data cells of Cells which are in on heap area.<a name="line.530"></a>
-<span class="sourceLineNo">531</span>    long heapSize = DEFAULT_SIZE;<a name="line.531"></a>
-<span class="sourceLineNo">532</span><a name="line.532"></a>
-<span class="sourceLineNo">533</span>    LimitScope timeScope = DEFAULT_SCOPE;<a name="line.533"></a>
-<span class="sourceLineNo">534</span>    long time = DEFAULT_TIME;<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>     * Fields keep their default values.<a name="line.537"></a>
-<span class="sourceLineNo">538</span>     */<a name="line.538"></a>
-<span class="sourceLineNo">539</span>    LimitFields() {<a name="line.539"></a>
-<span class="sourceLineNo">540</span>    }<a name="line.540"></a>
-<span class="sourceLineNo">541</span><a name="line.541"></a>
-<span class="sourceLineNo">542</span>    LimitFields(int batch, LimitScope sizeScope, long size, long heapSize, LimitScope timeScope,<a name="line.542"></a>
-<span class="sourceLineNo">543</span>        long time) {<a name="line.543"></a>
-<span class="sourceLineNo">544</span>      setFields(batch, sizeScope, size, heapSize, timeScope, time);<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>    void copy(LimitFields limitsToCopy) {<a name="line.547"></a>
-<span class="sourceLineNo">548</span>      if (limitsToCopy != null) {<a name="line.548"></a>
-<span class="sourceLineNo">549</span>        setFields(limitsToCopy.getBatch(), limitsToCopy.getSizeScope(), limitsToCopy.getDataSize(),<a name="line.549"></a>
-<span class="sourceLineNo">550</span>            limitsToCopy.getHeapSize(), limitsToCopy.getTimeScope(), limitsToCopy.getTime());<a name="line.550"></a>
-<span class="sourceLineNo">551</span>      }<a name="line.551"></a>
+<span class="sourceLineNo">476</span>     * Enforcing a limit between rows means that the limit will not be considered until all the<a name="line.476"></a>
+<span class="sourceLineNo">477</span>     * cells for a particular row have been retrieved<a name="line.477"></a>
+<span class="sourceLineNo">478</span>     */<a name="line.478"></a>
+<span class="sourceLineNo">479</span>    BETWEEN_ROWS(0),<a name="line.479"></a>
+<span class="sourceLineNo">480</span><a name="line.480"></a>
+<span class="sourceLineNo">481</span>    /**<a name="line.481"></a>
+<span class="sourceLineNo">482</span>     * Enforcing a limit between cells means that the limit will be considered after each full cell<a name="line.482"></a>
+<span class="sourceLineNo">483</span>     * has been retrieved<a name="line.483"></a>
+<span class="sourceLineNo">484</span>     */<a name="line.484"></a>
+<span class="sourceLineNo">485</span>    BETWEEN_CELLS(1);<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>     * When enforcing a limit, we must check that the scope is appropriate for enforcement.<a name="line.488"></a>
+<span class="sourceLineNo">489</span>     * &lt;p&gt;<a name="line.489"></a>
+<span class="sourceLineNo">490</span>     * To communicate this concept, each scope has a depth. A limit will be enforced if the depth of<a name="line.490"></a>
+<span class="sourceLineNo">491</span>     * the checker's scope is less than or equal to the limit's scope. This means that when checking<a name="line.491"></a>
+<span class="sourceLineNo">492</span>     * limits, the checker must know their own scope (i.e. are they checking the limits between<a name="line.492"></a>
+<span class="sourceLineNo">493</span>     * rows, between cells, etc...)<a name="line.493"></a>
+<span class="sourceLineNo">494</span>     */<a name="line.494"></a>
+<span class="sourceLineNo">495</span>    final int depth;<a name="line.495"></a>
+<span class="sourceLineNo">496</span><a name="line.496"></a>
+<span class="sourceLineNo">497</span>    LimitScope(int depth) {<a name="line.497"></a>
+<span class="sourceLineNo">498</span>      this.depth = depth;<a name="line.498"></a>
+<span class="sourceLineNo">499</span>    }<a name="line.499"></a>
+<span class="sourceLineNo">500</span><a name="line.500"></a>
+<span class="sourceLineNo">501</span>    final int depth() {<a name="line.501"></a>
+<span class="sourceLineNo">502</span>      return depth;<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>    /**<a name="line.505"></a>
+<span class="sourceLineNo">506</span>     * @param checkerScope The scope in which the limit is being checked<a name="line.506"></a>
+<span class="sourceLineNo">507</span>     * @return true when the checker is in a scope that indicates the limit can be enforced. Limits<a name="line.507"></a>
+<span class="sourceLineNo">508</span>     *         can be enforced from "higher or equal" scopes (i.e. the checker's scope is at a<a name="line.508"></a>
+<span class="sourceLineNo">509</span>     *         lesser depth than the limit)<a name="line.509"></a>
+<span class="sourceLineNo">510</span>     */<a name="line.510"></a>
+<span class="sourceLineNo">511</span>    boolean canEnforceLimitFromScope(LimitScope checkerScope) {<a name="line.511"></a>
+<span class="sourceLineNo">512</span>      return checkerScope != null &amp;&amp; checkerScope.depth() &lt;= depth;<a name="line.512"></a>
+<span class="sourceLineNo">513</span>    }<a name="line.513"></a>
+<span class="sourceLineNo">514</span>  }<a name="line.514"></a>
+<span class="sourceLineNo">515</span><a name="line.515"></a>
+<span class="sourceLineNo">516</span>  /**<a name="line.516"></a>
+<span class="sourceLineNo">517</span>   * The different fields that can be used as limits in calls to<a name="line.517"></a>
+<span class="sourceLineNo">518</span>   * {@link InternalScanner#next(java.util.List)} and {@link RegionScanner#next(java.util.List)}<a name="line.518"></a>
+<span class="sourceLineNo">519</span>   */<a name="line.519"></a>
+<span class="sourceLineNo">520</span>  private static class LimitFields {<a name="line.520"></a>
+<span class="sourceLineNo">521</span>    /**<a name="line.521"></a>
+<span class="sourceLineNo">522</span>     * Default values of the limit fields. Defined such that if a field does NOT change from its<a name="line.522"></a>
+<span class="sourceLineNo">523</span>     * default, it will not be enforced<a name="line.523"></a>
+<span class="sourceLineNo">524</span>     */<a name="line.524"></a>
+<span class="sourceLineNo">525</span>    private static int DEFAULT_BATCH = -1;<a name="line.525"></a>
+<span class="sourceLineNo">526</span>    private static long DEFAULT_SIZE = -1L;<a name="line.526"></a>
+<span class="sourceLineNo">527</span>    private static long DEFAULT_TIME = -1L;<a name="line.527"></a>
+<span class="sourceLineNo">528</span><a name="line.528"></a>
+<span class="sourceLineNo">529</span>    /**<a name="line.529"></a>
+<span class="sourceLineNo">530</span>     * Default scope that is assigned to a limit if a scope is not specified.<a name="line.530"></a>
+<span class="sourceLineNo">531</span>     */<a name="line.531"></a>
+<span class="sourceLineNo">532</span>    private static final LimitScope DEFAULT_SCOPE = LimitScope.BETWEEN_ROWS;<a name="line.532"></a>
+<span class="sourceLineNo">533</span><a name="line.533"></a>
+<span class="sourceLineNo">534</span>    // The batch limit will always be enforced between cells, thus, there isn't a field to hold the<a name="line.534"></a>
+<span class="sourceLineNo">535</span>    // batch scope<a name="line.535"></a>
+<span class="sourceLineNo">536</span>    int batch = DEFAULT_BATCH;<a name="line.536"></a>
+<span class="sourceLineNo">537</span><a name="line.537"></a>
+<span class="sourceLineNo">538</span>    LimitScope sizeScope = DEFAULT_SCOPE;<a name="line.538"></a>
+<span class="sourceLineNo">539</span>    // The sum of cell data sizes(key + value). The Cell data might be in on heap or off heap area.<a name="line.539"></a>
+<span class="sourceLineNo">540</span>    long dataSize = DEFAULT_SIZE;<a name="line.540"></a>
+<span class="sourceLineNo">541</span>    // The sum of heap space occupied by all tracked cells. This includes Cell POJO's overhead as<a name="line.541"></a>
+<span class="sourceLineNo">542</span>    // such AND data cells of Cells which are in on heap area.<a name="line.542"></a>
+<span class="sourceLineNo">543</span>    long heapSize = DEFAULT_SIZE;<a name="line.543"></a>
+<span class="sourceLineNo">544</span><a name="line.544"></a>
+<span class="sourceLineNo">545</span>    LimitScope timeScope = DEFAULT_SCOPE;<a name="line.545"></a>
+<span class="sourceLineNo">546</span>    long time = DEFAULT_TIME;<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>     * Fields keep their default values.<a name="line.549"></a>
+<span class="sourceLineNo">550</span>     */<a name="line.550"></a>
+<span class="sourceLineNo">551</span>    LimitFields() {<a name="line.551"></a>
 <span class="sourceLineNo">552</span>    }<a name="line.552"></a>
 <span class="sourceLineNo">553</span><a name="line.553"></a>
-<span class="sourceLineNo">554</span>    /**<a name="line.554"></a>
-<span class="sourceLineNo">555</span>     * Set all fields together.<a name="line.555"></a>
-<span class="sourceLineNo">556</span>     */<a name="line.556"></a>
-<span class="sourceLineNo">557</span>    void setFields(int batch, LimitScope sizeScope, long dataSize, long heapSize,<a name="line.557"></a>
-<span class="sourceLineNo">558</span>        LimitScope timeScope, long time) {<a name="line.558"></a>
-<span class="sourceLineNo">559</span>      setBatch(batch);<a name="line.559"></a>
-<span class="sourceLineNo">560</span>      setSizeScope(sizeScope);<a name="line.560"></a>
-<span class="sourceLineNo">561</span>      setDataSize(dataSize);<a name="line.561"></a>
-<span class="sourceLineNo">562</span>      setHeapSize(heapSize);<a name="line.562"></a>
-<span class="sourceLineNo">563</span>      setTimeScope(timeScope);<a name="line.563"></a>
-<span class="sourceLineNo">564</span>      setTime(time);<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>    int getBatch() {<a name="line.567"></a>
-<span class="sourceLineNo">568</span>      return this.batch;<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>    void setBatch(int batch) {<a name="line.571"></a>
-<span class="sourceLineNo">572</span>      this.batch = batch;<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>    /**<a name="line.575"></a>
-<span class="sourceLineNo">576</span>     * @param checkerScope<a name="line.576"></a>
-<span class="sourceLineNo">577</span>     * @return true when the limit can be enforced from the scope of the checker<a name="line.577"></a>
-<span class="sourceLineNo">578</span>     */<a name="line.578"></a>
-<span class="sourceLineNo">579</span>    boolean canEnforceBatchLimitFromScope(LimitScope checkerScope) {<a name="line.579"></a>
-<span class="sourceLineNo">580</span>      return LimitScope.BETWEEN_CELLS.canEnforceLimitFromScope(checkerScope);<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>    long getDataSize() {<a name="line.583"></a>
-<span class="sourceLineNo">584</span>      return this.dataSize;<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>    long getHeapSize() {<a name="line.587"></a>
-<span class="sourceLineNo">588</span>      return this.heapSize;<a name="line.588"></a>
-<span class="sourceLineNo">589</span>    }<a name="line.589"></a>
-<span class="sourceLineNo">590</span><a name="line.590"></a>
-<span class="sourceLineNo">591</span>    void setDataSize(long dataSize) {<a name="line.591"></a>
-<span class="sourceLineNo">592</span>      this.dataSize = dataSize;<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>    void setHeapSize(long heapSize) {<a name="line.595"></a>
-<span class="sourceLineNo">596</span>      this.heapSize = heapSize;<a name="line.596"></a>
-<span class="sourceLineNo">597</span>    }<a name="line.597"></a>
-<span class="sourceLineNo">598</span><a name="line.598"></a>
-<span class="sourceLineNo">599</span>    /**<a name="line.599"></a>
-<span class="sourceLineNo">600</span>     * @return {@link LimitScope} indicating scope in which the size limit is enforced<a name="line.600"></a>
-<span class="sourceLineNo">601</span>     */<a name="line.601"></a>
-<span class="sourceLineNo">602</span>    LimitScope getSizeScope() {<a name="line.602"></a>
-<span class="sourceLineNo">603</span>      return this.sizeScope;<a name="line.603"></a>
+<span class="sourceLineNo">554</span>    void copy(LimitFields limitsToCopy) {<a name="line.554"></a>
+<span class="sourceLineNo">555</span>      if (limitsToCopy != null) {<a name="line.555"></a>
+<span class="sourceLineNo">556</span>        setFields(limitsToCopy.getBatch(), limitsToCopy.getSizeScope(), limitsToCopy.getDataSize(),<a name="line.556"></a>
+<span class="sourceLineNo">557</span>            limitsToCopy.getHeapSize(), limitsToCopy.getTimeScope(), limitsToCopy.getTime());<a name="line.557"></a>
+<span class="sourceLineNo">558</span>      }<a name="line.558"></a>
+<span class="sourceLineNo">559</span>    }<a name="line.559"></a>
+<span class="sourceLineNo">560</span><a name="line.560"></a>
+<span class="sourceLineNo">561</span>    /**<a name="line.561"></a>
+<span class="sourceLineNo">562</span>     * Set all fields together.<a name="line.562"></a>
+<span class="sourceLineNo">563</span>     */<a name="line.563"></a>
+<span class="sourceLineNo">564</span>    void setFields(int batch, LimitScope sizeScope, long dataSize, long heapSize,<a name="line.564"></a>
+<span class="sourceLineNo">565</span>        LimitScope timeScope, long time) {<a name="line.565"></a>
+<span class="sourceLineNo">566</span>      setBatch(batch);<a name="line.566"></a>
+<span class="sourceLineNo">567</span>      setSizeScope(sizeScope);<a name="line.567"></a>
+<span class="sourceLineNo">568</span>      setDataSize(dataSize);<a name="line.568"></a>
+<span class="sourceLineNo">569</span>      setHeapSize(heapSize);<a name="line.569"></a>
+<span class="sourceLineNo">570</span>      setTimeScope(timeScope);<a name="line.570"></a>
+<span class="sourceLineNo">571</span>      setTime(time);<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>    int getBatch() {<a name="line.574"></a>
+<span class="sourceLineNo">575</span>      return this.batch;<a name="line.575"></a>
+<span class="sourceLineNo">576</span>    }<a name="line.576"></a>
+<span class="sourceLineNo">577</span><a name="line.577"></a>
+<span class="sourceLineNo">578</span>    void setBatch(int batch) {<a name="line.578"></a>
+<span class="sourceLineNo">579</span>      this.batch = batch;<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

<TRUNCATED>

[40/50] hbase-site git commit: Published site at 26babcf013de696b899d76a3c39434b794440d8d.

Posted by gi...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html
----------------------------------------------------------------------
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html
index f8ce32e..f118c08 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/BlockCacheUtil.html
@@ -41,273 +41,305 @@
 <span class="sourceLineNo">033</span>import org.apache.hadoop.conf.Configuration;<a name="line.33"></a>
 <span class="sourceLineNo">034</span>import org.apache.hadoop.hbase.metrics.impl.FastLongHistogram;<a name="line.34"></a>
 <span class="sourceLineNo">035</span>import org.apache.hadoop.hbase.util.Bytes;<a name="line.35"></a>
-<span class="sourceLineNo">036</span><a name="line.36"></a>
-<span class="sourceLineNo">037</span>/**<a name="line.37"></a>
-<span class="sourceLineNo">038</span> * Utilty for aggregating counts in CachedBlocks and toString/toJSON CachedBlocks and BlockCaches.<a name="line.38"></a>
-<span class="sourceLineNo">039</span> * No attempt has been made at making this thread safe.<a name="line.39"></a>
-<span class="sourceLineNo">040</span> */<a name="line.40"></a>
-<span class="sourceLineNo">041</span>@InterfaceAudience.Private<a name="line.41"></a>
-<span class="sourceLineNo">042</span>public class BlockCacheUtil {<a name="line.42"></a>
-<span class="sourceLineNo">043</span><a name="line.43"></a>
-<span class="sourceLineNo">044</span><a name="line.44"></a>
-<span class="sourceLineNo">045</span>  public static final long NANOS_PER_SECOND = 1000000000;<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>   * Needed generating JSON.<a name="line.48"></a>
-<span class="sourceLineNo">049</span>   */<a name="line.49"></a>
-<span class="sourceLineNo">050</span>  private static final ObjectMapper MAPPER = new ObjectMapper();<a name="line.50"></a>
-<span class="sourceLineNo">051</span>  static {<a name="line.51"></a>
-<span class="sourceLineNo">052</span>    MAPPER.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);<a name="line.52"></a>
-<span class="sourceLineNo">053</span>    MAPPER.configure(SerializationFeature.FLUSH_AFTER_WRITE_VALUE, true);<a name="line.53"></a>
-<span class="sourceLineNo">054</span>    MAPPER.configure(SerializationFeature.INDENT_OUTPUT, true);<a name="line.54"></a>
-<span class="sourceLineNo">055</span>  }<a name="line.55"></a>
-<span class="sourceLineNo">056</span><a name="line.56"></a>
-<span class="sourceLineNo">057</span>  /**<a name="line.57"></a>
-<span class="sourceLineNo">058</span>   * @param cb<a name="line.58"></a>
-<span class="sourceLineNo">059</span>   * @return The block content as String.<a name="line.59"></a>
-<span class="sourceLineNo">060</span>   */<a name="line.60"></a>
-<span class="sourceLineNo">061</span>  public static String toString(final CachedBlock cb, final long now) {<a name="line.61"></a>
-<span class="sourceLineNo">062</span>    return "filename=" + cb.getFilename() + ", " + toStringMinusFileName(cb, now);<a name="line.62"></a>
-<span class="sourceLineNo">063</span>  }<a name="line.63"></a>
-<span class="sourceLineNo">064</span><a name="line.64"></a>
-<span class="sourceLineNo">065</span>  /**<a name="line.65"></a>
-<span class="sourceLineNo">066</span>   * Little data structure to hold counts for a file.<a name="line.66"></a>
-<span class="sourceLineNo">067</span>   * Used doing a toJSON.<a name="line.67"></a>
-<span class="sourceLineNo">068</span>   */<a name="line.68"></a>
-<span class="sourceLineNo">069</span>  static class CachedBlockCountsPerFile {<a name="line.69"></a>
-<span class="sourceLineNo">070</span>    private int count = 0;<a name="line.70"></a>
-<span class="sourceLineNo">071</span>    private long size = 0;<a name="line.71"></a>
-<span class="sourceLineNo">072</span>    private int countData = 0;<a name="line.72"></a>
-<span class="sourceLineNo">073</span>    private long sizeData = 0;<a name="line.73"></a>
-<span class="sourceLineNo">074</span>    private final String filename;<a name="line.74"></a>
-<span class="sourceLineNo">075</span><a name="line.75"></a>
-<span class="sourceLineNo">076</span>    CachedBlockCountsPerFile(final String filename) {<a name="line.76"></a>
-<span class="sourceLineNo">077</span>      this.filename = filename;<a name="line.77"></a>
-<span class="sourceLineNo">078</span>    }<a name="line.78"></a>
-<span class="sourceLineNo">079</span><a name="line.79"></a>
-<span class="sourceLineNo">080</span>    public int getCount() {<a name="line.80"></a>
-<span class="sourceLineNo">081</span>      return count;<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>    public long getSize() {<a name="line.84"></a>
-<span class="sourceLineNo">085</span>      return size;<a name="line.85"></a>
-<span class="sourceLineNo">086</span>    }<a name="line.86"></a>
-<span class="sourceLineNo">087</span><a name="line.87"></a>
-<span class="sourceLineNo">088</span>    public int getCountData() {<a name="line.88"></a>
-<span class="sourceLineNo">089</span>      return countData;<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>    public long getSizeData() {<a name="line.92"></a>
-<span class="sourceLineNo">093</span>      return sizeData;<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>    public String getFilename() {<a name="line.96"></a>
-<span class="sourceLineNo">097</span>      return filename;<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>  /**<a name="line.101"></a>
-<span class="sourceLineNo">102</span>   * @param filename<a name="line.102"></a>
-<span class="sourceLineNo">103</span>   * @param blocks<a name="line.103"></a>
-<span class="sourceLineNo">104</span>   * @return A JSON String of &lt;code&gt;filename&lt;/code&gt; and counts of &lt;code&gt;blocks&lt;/code&gt;<a name="line.104"></a>
-<span class="sourceLineNo">105</span>   * @throws JsonGenerationException<a name="line.105"></a>
-<span class="sourceLineNo">106</span>   * @throws JsonMappingException<a name="line.106"></a>
-<span class="sourceLineNo">107</span>   * @throws IOException<a name="line.107"></a>
-<span class="sourceLineNo">108</span>   */<a name="line.108"></a>
-<span class="sourceLineNo">109</span>  public static String toJSON(final String filename, final NavigableSet&lt;CachedBlock&gt; blocks)<a name="line.109"></a>
-<span class="sourceLineNo">110</span>  throws JsonGenerationException, JsonMappingException, IOException {<a name="line.110"></a>
-<span class="sourceLineNo">111</span>    CachedBlockCountsPerFile counts = new CachedBlockCountsPerFile(filename);<a name="line.111"></a>
-<span class="sourceLineNo">112</span>    for (CachedBlock cb: blocks) {<a name="line.112"></a>
-<span class="sourceLineNo">113</span>      counts.count++;<a name="line.113"></a>
-<span class="sourceLineNo">114</span>      counts.size += cb.getSize();<a name="line.114"></a>
-<span class="sourceLineNo">115</span>      BlockType bt = cb.getBlockType();<a name="line.115"></a>
-<span class="sourceLineNo">116</span>      if (bt != null &amp;&amp; bt.isData()) {<a name="line.116"></a>
-<span class="sourceLineNo">117</span>        counts.countData++;<a name="line.117"></a>
-<span class="sourceLineNo">118</span>        counts.sizeData += cb.getSize();<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>    return MAPPER.writeValueAsString(counts);<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>   * @param cbsbf<a name="line.125"></a>
-<span class="sourceLineNo">126</span>   * @return JSON string of &lt;code&gt;cbsf&lt;/code&gt; aggregated<a name="line.126"></a>
-<span class="sourceLineNo">127</span>   * @throws JsonGenerationException<a name="line.127"></a>
-<span class="sourceLineNo">128</span>   * @throws JsonMappingException<a name="line.128"></a>
-<span class="sourceLineNo">129</span>   * @throws IOException<a name="line.129"></a>
-<span class="sourceLineNo">130</span>   */<a name="line.130"></a>
-<span class="sourceLineNo">131</span>  public static String toJSON(final CachedBlocksByFile cbsbf)<a name="line.131"></a>
-<span class="sourceLineNo">132</span>  throws JsonGenerationException, JsonMappingException, IOException {<a name="line.132"></a>
-<span class="sourceLineNo">133</span>    return MAPPER.writeValueAsString(cbsbf);<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>   * @param bc<a name="line.137"></a>
-<span class="sourceLineNo">138</span>   * @return JSON string of &lt;code&gt;bc&lt;/code&gt; content.<a name="line.138"></a>
-<span class="sourceLineNo">139</span>   * @throws JsonGenerationException<a name="line.139"></a>
-<span class="sourceLineNo">140</span>   * @throws JsonMappingException<a name="line.140"></a>
-<span class="sourceLineNo">141</span>   * @throws IOException<a name="line.141"></a>
-<span class="sourceLineNo">142</span>   */<a name="line.142"></a>
-<span class="sourceLineNo">143</span>  public static String toJSON(final BlockCache bc)<a name="line.143"></a>
-<span class="sourceLineNo">144</span>  throws JsonGenerationException, JsonMappingException, IOException {<a name="line.144"></a>
-<span class="sourceLineNo">145</span>    return MAPPER.writeValueAsString(bc);<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>  /**<a name="line.148"></a>
-<span class="sourceLineNo">149</span>   * @param cb<a name="line.149"></a>
-<span class="sourceLineNo">150</span>   * @return The block content of &lt;code&gt;bc&lt;/code&gt; as a String minus the filename.<a name="line.150"></a>
-<span class="sourceLineNo">151</span>   */<a name="line.151"></a>
-<span class="sourceLineNo">152</span>  public static String toStringMinusFileName(final CachedBlock cb, final long now) {<a name="line.152"></a>
-<span class="sourceLineNo">153</span>    return "offset=" + cb.getOffset() +<a name="line.153"></a>
-<span class="sourceLineNo">154</span>      ", size=" + cb.getSize() +<a name="line.154"></a>
-<span class="sourceLineNo">155</span>      ", age=" + (now - cb.getCachedTime()) +<a name="line.155"></a>
-<span class="sourceLineNo">156</span>      ", type=" + cb.getBlockType() +<a name="line.156"></a>
-<span class="sourceLineNo">157</span>      ", priority=" + cb.getBlockPriority();<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>  /**<a name="line.160"></a>
-<span class="sourceLineNo">161</span>   * Get a {@link CachedBlocksByFile} instance and load it up by iterating content in<a name="line.161"></a>
-<span class="sourceLineNo">162</span>   * {@link BlockCache}.<a name="line.162"></a>
-<span class="sourceLineNo">163</span>   * @param conf Used to read configurations<a name="line.163"></a>
-<span class="sourceLineNo">164</span>   * @param bc Block Cache to iterate.<a name="line.164"></a>
-<span class="sourceLineNo">165</span>   * @return Laoded up instance of CachedBlocksByFile<a name="line.165"></a>
-<span class="sourceLineNo">166</span>   */<a name="line.166"></a>
-<span class="sourceLineNo">167</span>  public static CachedBlocksByFile getLoadedCachedBlocksByFile(final Configuration conf,<a name="line.167"></a>
-<span class="sourceLineNo">168</span>      final BlockCache bc) {<a name="line.168"></a>
-<span class="sourceLineNo">169</span>    CachedBlocksByFile cbsbf = new CachedBlocksByFile(conf);<a name="line.169"></a>
-<span class="sourceLineNo">170</span>    for (CachedBlock cb: bc) {<a name="line.170"></a>
-<span class="sourceLineNo">171</span>      if (cbsbf.update(cb)) break;<a name="line.171"></a>
-<span class="sourceLineNo">172</span>    }<a name="line.172"></a>
-<span class="sourceLineNo">173</span>    return cbsbf;<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 static int compareCacheBlock(Cacheable left, Cacheable right) {<a name="line.176"></a>
-<span class="sourceLineNo">177</span>    ByteBuffer l = ByteBuffer.allocate(left.getSerializedLength());<a name="line.177"></a>
-<span class="sourceLineNo">178</span>    left.serialize(l);<a name="line.178"></a>
-<span class="sourceLineNo">179</span>    ByteBuffer r = ByteBuffer.allocate(right.getSerializedLength());<a name="line.179"></a>
-<span class="sourceLineNo">180</span>    right.serialize(r);<a name="line.180"></a>
-<span class="sourceLineNo">181</span>    return Bytes.compareTo(l.array(), l.arrayOffset(), l.limit(),<a name="line.181"></a>
-<span class="sourceLineNo">182</span>        r.array(), r.arrayOffset(), r.limit());<a name="line.182"></a>
-<span class="sourceLineNo">183</span>  }<a name="line.183"></a>
-<span class="sourceLineNo">184</span><a name="line.184"></a>
-<span class="sourceLineNo">185</span>  /**<a name="line.185"></a>
-<span class="sourceLineNo">186</span>   * Use one of these to keep a running account of cached blocks by file.  Throw it away when done.<a name="line.186"></a>
-<span class="sourceLineNo">187</span>   * This is different than metrics in that it is stats on current state of a cache.<a name="line.187"></a>
-<span class="sourceLineNo">188</span>   * See getLoadedCachedBlocksByFile<a name="line.188"></a>
-<span class="sourceLineNo">189</span>   */<a name="line.189"></a>
-<span class="sourceLineNo">190</span>  @JsonIgnoreProperties({"cachedBlockStatsByFile"})<a name="line.190"></a>
-<span class="sourceLineNo">191</span>  public static class CachedBlocksByFile {<a name="line.191"></a>
-<span class="sourceLineNo">192</span>    private int count;<a name="line.192"></a>
-<span class="sourceLineNo">193</span>    private int dataBlockCount;<a name="line.193"></a>
-<span class="sourceLineNo">194</span>    private long size;<a name="line.194"></a>
-<span class="sourceLineNo">195</span>    private long dataSize;<a name="line.195"></a>
-<span class="sourceLineNo">196</span>    private final long now = System.nanoTime();<a name="line.196"></a>
-<span class="sourceLineNo">197</span>    /**<a name="line.197"></a>
-<span class="sourceLineNo">198</span>     * How many blocks to look at before we give up.<a name="line.198"></a>
-<span class="sourceLineNo">199</span>     * There could be many millions of blocks. We don't want the<a name="line.199"></a>
-<span class="sourceLineNo">200</span>     * ui to freeze while we run through 1B blocks... users will<a name="line.200"></a>
-<span class="sourceLineNo">201</span>     * think hbase dead. UI displays warning in red when stats<a name="line.201"></a>
-<span class="sourceLineNo">202</span>     * are incomplete.<a name="line.202"></a>
-<span class="sourceLineNo">203</span>     */<a name="line.203"></a>
-<span class="sourceLineNo">204</span>    private final int max;<a name="line.204"></a>
-<span class="sourceLineNo">205</span>    public static final int DEFAULT_MAX = 1000000;<a name="line.205"></a>
-<span class="sourceLineNo">206</span><a name="line.206"></a>
-<span class="sourceLineNo">207</span>    CachedBlocksByFile() {<a name="line.207"></a>
-<span class="sourceLineNo">208</span>      this(null);<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>    CachedBlocksByFile(final Configuration c) {<a name="line.211"></a>
-<span class="sourceLineNo">212</span>      this.max = c == null? DEFAULT_MAX: c.getInt("hbase.ui.blockcache.by.file.max", DEFAULT_MAX);<a name="line.212"></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> * Utilty for aggregating counts in CachedBlocks and toString/toJSON CachedBlocks and BlockCaches.<a name="line.40"></a>
+<span class="sourceLineNo">041</span> * No attempt has been made at making this thread safe.<a name="line.41"></a>
+<span class="sourceLineNo">042</span> */<a name="line.42"></a>
+<span class="sourceLineNo">043</span>@InterfaceAudience.Private<a name="line.43"></a>
+<span class="sourceLineNo">044</span>public class BlockCacheUtil {<a name="line.44"></a>
+<span class="sourceLineNo">045</span><a name="line.45"></a>
+<span class="sourceLineNo">046</span>  private static final Logger LOG = LoggerFactory.getLogger(BlockCacheUtil.class);<a name="line.46"></a>
+<span class="sourceLineNo">047</span><a name="line.47"></a>
+<span class="sourceLineNo">048</span>  public static final long NANOS_PER_SECOND = 1000000000;<a name="line.48"></a>
+<span class="sourceLineNo">049</span><a name="line.49"></a>
+<span class="sourceLineNo">050</span>  /**<a name="line.50"></a>
+<span class="sourceLineNo">051</span>   * Needed generating JSON.<a name="line.51"></a>
+<span class="sourceLineNo">052</span>   */<a name="line.52"></a>
+<span class="sourceLineNo">053</span>  private static final ObjectMapper MAPPER = new ObjectMapper();<a name="line.53"></a>
+<span class="sourceLineNo">054</span>  static {<a name="line.54"></a>
+<span class="sourceLineNo">055</span>    MAPPER.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);<a name="line.55"></a>
+<span class="sourceLineNo">056</span>    MAPPER.configure(SerializationFeature.FLUSH_AFTER_WRITE_VALUE, true);<a name="line.56"></a>
+<span class="sourceLineNo">057</span>    MAPPER.configure(SerializationFeature.INDENT_OUTPUT, true);<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>  /**<a name="line.60"></a>
+<span class="sourceLineNo">061</span>   * @param cb<a name="line.61"></a>
+<span class="sourceLineNo">062</span>   * @return The block content as String.<a name="line.62"></a>
+<span class="sourceLineNo">063</span>   */<a name="line.63"></a>
+<span class="sourceLineNo">064</span>  public static String toString(final CachedBlock cb, final long now) {<a name="line.64"></a>
+<span class="sourceLineNo">065</span>    return "filename=" + cb.getFilename() + ", " + toStringMinusFileName(cb, now);<a name="line.65"></a>
+<span class="sourceLineNo">066</span>  }<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>   * Little data structure to hold counts for a file.<a name="line.69"></a>
+<span class="sourceLineNo">070</span>   * Used doing a toJSON.<a name="line.70"></a>
+<span class="sourceLineNo">071</span>   */<a name="line.71"></a>
+<span class="sourceLineNo">072</span>  static class CachedBlockCountsPerFile {<a name="line.72"></a>
+<span class="sourceLineNo">073</span>    private int count = 0;<a name="line.73"></a>
+<span class="sourceLineNo">074</span>    private long size = 0;<a name="line.74"></a>
+<span class="sourceLineNo">075</span>    private int countData = 0;<a name="line.75"></a>
+<span class="sourceLineNo">076</span>    private long sizeData = 0;<a name="line.76"></a>
+<span class="sourceLineNo">077</span>    private final String filename;<a name="line.77"></a>
+<span class="sourceLineNo">078</span><a name="line.78"></a>
+<span class="sourceLineNo">079</span>    CachedBlockCountsPerFile(final String filename) {<a name="line.79"></a>
+<span class="sourceLineNo">080</span>      this.filename = filename;<a name="line.80"></a>
+<span class="sourceLineNo">081</span>    }<a name="line.81"></a>
+<span class="sourceLineNo">082</span><a name="line.82"></a>
+<span class="sourceLineNo">083</span>    public int getCount() {<a name="line.83"></a>
+<span class="sourceLineNo">084</span>      return count;<a name="line.84"></a>
+<span class="sourceLineNo">085</span>    }<a name="line.85"></a>
+<span class="sourceLineNo">086</span><a name="line.86"></a>
+<span class="sourceLineNo">087</span>    public long getSize() {<a name="line.87"></a>
+<span class="sourceLineNo">088</span>      return size;<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>    public int getCountData() {<a name="line.91"></a>
+<span class="sourceLineNo">092</span>      return countData;<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>    public long getSizeData() {<a name="line.95"></a>
+<span class="sourceLineNo">096</span>      return sizeData;<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>    public String getFilename() {<a name="line.99"></a>
+<span class="sourceLineNo">100</span>      return filename;<a name="line.100"></a>
+<span class="sourceLineNo">101</span>    }<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>  /**<a name="line.104"></a>
+<span class="sourceLineNo">105</span>   * @param filename<a name="line.105"></a>
+<span class="sourceLineNo">106</span>   * @param blocks<a name="line.106"></a>
+<span class="sourceLineNo">107</span>   * @return A JSON String of &lt;code&gt;filename&lt;/code&gt; and counts of &lt;code&gt;blocks&lt;/code&gt;<a name="line.107"></a>
+<span class="sourceLineNo">108</span>   * @throws JsonGenerationException<a name="line.108"></a>
+<span class="sourceLineNo">109</span>   * @throws JsonMappingException<a name="line.109"></a>
+<span class="sourceLineNo">110</span>   * @throws IOException<a name="line.110"></a>
+<span class="sourceLineNo">111</span>   */<a name="line.111"></a>
+<span class="sourceLineNo">112</span>  public static String toJSON(final String filename, final NavigableSet&lt;CachedBlock&gt; blocks)<a name="line.112"></a>
+<span class="sourceLineNo">113</span>  throws JsonGenerationException, JsonMappingException, IOException {<a name="line.113"></a>
+<span class="sourceLineNo">114</span>    CachedBlockCountsPerFile counts = new CachedBlockCountsPerFile(filename);<a name="line.114"></a>
+<span class="sourceLineNo">115</span>    for (CachedBlock cb: blocks) {<a name="line.115"></a>
+<span class="sourceLineNo">116</span>      counts.count++;<a name="line.116"></a>
+<span class="sourceLineNo">117</span>      counts.size += cb.getSize();<a name="line.117"></a>
+<span class="sourceLineNo">118</span>      BlockType bt = cb.getBlockType();<a name="line.118"></a>
+<span class="sourceLineNo">119</span>      if (bt != null &amp;&amp; bt.isData()) {<a name="line.119"></a>
+<span class="sourceLineNo">120</span>        counts.countData++;<a name="line.120"></a>
+<span class="sourceLineNo">121</span>        counts.sizeData += cb.getSize();<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>    return MAPPER.writeValueAsString(counts);<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>  /**<a name="line.127"></a>
+<span class="sourceLineNo">128</span>   * @param cbsbf<a name="line.128"></a>
+<span class="sourceLineNo">129</span>   * @return JSON string of &lt;code&gt;cbsf&lt;/code&gt; aggregated<a name="line.129"></a>
+<span class="sourceLineNo">130</span>   * @throws JsonGenerationException<a name="line.130"></a>
+<span class="sourceLineNo">131</span>   * @throws JsonMappingException<a name="line.131"></a>
+<span class="sourceLineNo">132</span>   * @throws IOException<a name="line.132"></a>
+<span class="sourceLineNo">133</span>   */<a name="line.133"></a>
+<span class="sourceLineNo">134</span>  public static String toJSON(final CachedBlocksByFile cbsbf)<a name="line.134"></a>
+<span class="sourceLineNo">135</span>  throws JsonGenerationException, JsonMappingException, IOException {<a name="line.135"></a>
+<span class="sourceLineNo">136</span>    return MAPPER.writeValueAsString(cbsbf);<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>   * @param bc<a name="line.140"></a>
+<span class="sourceLineNo">141</span>   * @return JSON string of &lt;code&gt;bc&lt;/code&gt; content.<a name="line.141"></a>
+<span class="sourceLineNo">142</span>   * @throws JsonGenerationException<a name="line.142"></a>
+<span class="sourceLineNo">143</span>   * @throws JsonMappingException<a name="line.143"></a>
+<span class="sourceLineNo">144</span>   * @throws IOException<a name="line.144"></a>
+<span class="sourceLineNo">145</span>   */<a name="line.145"></a>
+<span class="sourceLineNo">146</span>  public static String toJSON(final BlockCache bc)<a name="line.146"></a>
+<span class="sourceLineNo">147</span>  throws JsonGenerationException, JsonMappingException, IOException {<a name="line.147"></a>
+<span class="sourceLineNo">148</span>    return MAPPER.writeValueAsString(bc);<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 name="line.151"></a>
+<span class="sourceLineNo">152</span>   * @param cb<a name="line.152"></a>
+<span class="sourceLineNo">153</span>   * @return The block content of &lt;code&gt;bc&lt;/code&gt; as a String minus the filename.<a name="line.153"></a>
+<span class="sourceLineNo">154</span>   */<a name="line.154"></a>
+<span class="sourceLineNo">155</span>  public static String toStringMinusFileName(final CachedBlock cb, final long now) {<a name="line.155"></a>
+<span class="sourceLineNo">156</span>    return "offset=" + cb.getOffset() +<a name="line.156"></a>
+<span class="sourceLineNo">157</span>      ", size=" + cb.getSize() +<a name="line.157"></a>
+<span class="sourceLineNo">158</span>      ", age=" + (now - cb.getCachedTime()) +<a name="line.158"></a>
+<span class="sourceLineNo">159</span>      ", type=" + cb.getBlockType() +<a name="line.159"></a>
+<span class="sourceLineNo">160</span>      ", priority=" + cb.getBlockPriority();<a name="line.160"></a>
+<span class="sourceLineNo">161</span>  }<a name="line.161"></a>
+<span class="sourceLineNo">162</span><a name="line.162"></a>
+<span class="sourceLineNo">163</span>  /**<a name="line.163"></a>
+<span class="sourceLineNo">164</span>   * Get a {@link CachedBlocksByFile} instance and load it up by iterating content in<a name="line.164"></a>
+<span class="sourceLineNo">165</span>   * {@link BlockCache}.<a name="line.165"></a>
+<span class="sourceLineNo">166</span>   * @param conf Used to read configurations<a name="line.166"></a>
+<span class="sourceLineNo">167</span>   * @param bc Block Cache to iterate.<a name="line.167"></a>
+<span class="sourceLineNo">168</span>   * @return Laoded up instance of CachedBlocksByFile<a name="line.168"></a>
+<span class="sourceLineNo">169</span>   */<a name="line.169"></a>
+<span class="sourceLineNo">170</span>  public static CachedBlocksByFile getLoadedCachedBlocksByFile(final Configuration conf,<a name="line.170"></a>
+<span class="sourceLineNo">171</span>      final BlockCache bc) {<a name="line.171"></a>
+<span class="sourceLineNo">172</span>    CachedBlocksByFile cbsbf = new CachedBlocksByFile(conf);<a name="line.172"></a>
+<span class="sourceLineNo">173</span>    for (CachedBlock cb: bc) {<a name="line.173"></a>
+<span class="sourceLineNo">174</span>      if (cbsbf.update(cb)) break;<a name="line.174"></a>
+<span class="sourceLineNo">175</span>    }<a name="line.175"></a>
+<span class="sourceLineNo">176</span>    return cbsbf;<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>  private static int compareCacheBlock(Cacheable left, Cacheable right,<a name="line.179"></a>
+<span class="sourceLineNo">180</span>                                       boolean includeNextBlockMetadata) {<a name="line.180"></a>
+<span class="sourceLineNo">181</span>    ByteBuffer l = ByteBuffer.allocate(left.getSerializedLength());<a name="line.181"></a>
+<span class="sourceLineNo">182</span>    left.serialize(l, includeNextBlockMetadata);<a name="line.182"></a>
+<span class="sourceLineNo">183</span>    ByteBuffer r = ByteBuffer.allocate(right.getSerializedLength());<a name="line.183"></a>
+<span class="sourceLineNo">184</span>    right.serialize(r, includeNextBlockMetadata);<a name="line.184"></a>
+<span class="sourceLineNo">185</span>    return Bytes.compareTo(l.array(), l.arrayOffset(), l.limit(),<a name="line.185"></a>
+<span class="sourceLineNo">186</span>        r.array(), r.arrayOffset(), r.limit());<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>   * Validate that the existing and newBlock are the same without including the nextBlockMetadata,<a name="line.190"></a>
+<span class="sourceLineNo">191</span>   * if not, throw an exception. If they are the same without the nextBlockMetadata,<a name="line.191"></a>
+<span class="sourceLineNo">192</span>   * return the comparison.<a name="line.192"></a>
+<span class="sourceLineNo">193</span>   *<a name="line.193"></a>
+<span class="sourceLineNo">194</span>   * @param existing block that is existing in the cache.<a name="line.194"></a>
+<span class="sourceLineNo">195</span>   * @param newBlock block that is trying to be cached.<a name="line.195"></a>
+<span class="sourceLineNo">196</span>   * @param cacheKey the cache key of the blocks.<a name="line.196"></a>
+<span class="sourceLineNo">197</span>   * @return comparison of the existing block to the newBlock.<a name="line.197"></a>
+<span class="sourceLineNo">198</span>   */<a name="line.198"></a>
+<span class="sourceLineNo">199</span>  public static int validateBlockAddition(Cacheable existing, Cacheable newBlock,<a name="line.199"></a>
+<span class="sourceLineNo">200</span>                                          BlockCacheKey cacheKey) {<a name="line.200"></a>
+<span class="sourceLineNo">201</span>    int comparison = compareCacheBlock(existing, newBlock, true);<a name="line.201"></a>
+<span class="sourceLineNo">202</span>    if (comparison != 0) {<a name="line.202"></a>
+<span class="sourceLineNo">203</span>      LOG.warn("Cached block contents differ, trying to just compare the block contents " +<a name="line.203"></a>
+<span class="sourceLineNo">204</span>          "without the next block. CacheKey: " + cacheKey);<a name="line.204"></a>
+<span class="sourceLineNo">205</span><a name="line.205"></a>
+<span class="sourceLineNo">206</span>      // compare the contents, if they are not equal, we are in big trouble<a name="line.206"></a>
+<span class="sourceLineNo">207</span>      int comparisonWithoutNextBlockMetadata = compareCacheBlock(existing, newBlock, false);<a name="line.207"></a>
+<span class="sourceLineNo">208</span><a name="line.208"></a>
+<span class="sourceLineNo">209</span>      if (comparisonWithoutNextBlockMetadata != 0) {<a name="line.209"></a>
+<span class="sourceLineNo">210</span>        throw new RuntimeException("Cached block contents differ, which should not have happened."<a name="line.210"></a>
+<span class="sourceLineNo">211</span>            + "cacheKey:" + cacheKey);<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>    /**<a name="line.215"></a>
-<span class="sourceLineNo">216</span>     * Map by filename. use concurent utils because we want our Map and contained blocks sorted.<a name="line.216"></a>
-<span class="sourceLineNo">217</span>     */<a name="line.217"></a>
-<span class="sourceLineNo">218</span>    private NavigableMap&lt;String, NavigableSet&lt;CachedBlock&gt;&gt; cachedBlockByFile = new ConcurrentSkipListMap&lt;&gt;();<a name="line.218"></a>
-<span class="sourceLineNo">219</span>    FastLongHistogram hist = new FastLongHistogram();<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>     * @param cb<a name="line.222"></a>
-<span class="sourceLineNo">223</span>     * @return True if full.... if we won't be adding any more.<a name="line.223"></a>
-<span class="sourceLineNo">224</span>     */<a name="line.224"></a>
-<span class="sourceLineNo">225</span>    public boolean update(final CachedBlock cb) {<a name="line.225"></a>
-<span class="sourceLineNo">226</span>      if (isFull()) return true;<a name="line.226"></a>
-<span class="sourceLineNo">227</span>      NavigableSet&lt;CachedBlock&gt; set = this.cachedBlockByFile.get(cb.getFilename());<a name="line.227"></a>
-<span class="sourceLineNo">228</span>      if (set == null) {<a name="line.228"></a>
-<span class="sourceLineNo">229</span>        set = new ConcurrentSkipListSet&lt;&gt;();<a name="line.229"></a>
-<span class="sourceLineNo">230</span>        this.cachedBlockByFile.put(cb.getFilename(), set);<a name="line.230"></a>
-<span class="sourceLineNo">231</span>      }<a name="line.231"></a>
-<span class="sourceLineNo">232</span>      set.add(cb);<a name="line.232"></a>
-<span class="sourceLineNo">233</span>      this.size += cb.getSize();<a name="line.233"></a>
-<span class="sourceLineNo">234</span>      this.count++;<a name="line.234"></a>
-<span class="sourceLineNo">235</span>      BlockType bt = cb.getBlockType();<a name="line.235"></a>
-<span class="sourceLineNo">236</span>      if (bt != null &amp;&amp; bt.isData()) {<a name="line.236"></a>
-<span class="sourceLineNo">237</span>        this.dataBlockCount++;<a name="line.237"></a>
-<span class="sourceLineNo">238</span>        this.dataSize += cb.getSize();<a name="line.238"></a>
-<span class="sourceLineNo">239</span>      }<a name="line.239"></a>
-<span class="sourceLineNo">240</span>      long age = (this.now - cb.getCachedTime())/NANOS_PER_SECOND;<a name="line.240"></a>
-<span class="sourceLineNo">241</span>      this.hist.add(age, 1);<a name="line.241"></a>
-<span class="sourceLineNo">242</span>      return false;<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>    /**<a name="line.245"></a>
-<span class="sourceLineNo">246</span>     * @return True if full; i.e. there are more items in the cache but we only loaded up<a name="line.246"></a>
-<span class="sourceLineNo">247</span>     * the maximum set in configuration &lt;code&gt;hbase.ui.blockcache.by.file.max&lt;/code&gt;<a name="line.247"></a>
-<span class="sourceLineNo">248</span>     * (Default: DEFAULT_MAX).<a name="line.248"></a>
+<span class="sourceLineNo">214</span>    return comparison;<a name="line.214"></a>
+<span class="sourceLineNo">215</span>  }<a name="line.215"></a>
+<span class="sourceLineNo">216</span><a name="line.216"></a>
+<span class="sourceLineNo">217</span>  /**<a name="line.217"></a>
+<span class="sourceLineNo">218</span>   * Use one of these to keep a running account of cached blocks by file.  Throw it away when done.<a name="line.218"></a>
+<span class="sourceLineNo">219</span>   * This is different than metrics in that it is stats on current state of a cache.<a name="line.219"></a>
+<span class="sourceLineNo">220</span>   * See getLoadedCachedBlocksByFile<a name="line.220"></a>
+<span class="sourceLineNo">221</span>   */<a name="line.221"></a>
+<span class="sourceLineNo">222</span>  @JsonIgnoreProperties({"cachedBlockStatsByFile"})<a name="line.222"></a>
+<span class="sourceLineNo">223</span>  public static class CachedBlocksByFile {<a name="line.223"></a>
+<span class="sourceLineNo">224</span>    private int count;<a name="line.224"></a>
+<span class="sourceLineNo">225</span>    private int dataBlockCount;<a name="line.225"></a>
+<span class="sourceLineNo">226</span>    private long size;<a name="line.226"></a>
+<span class="sourceLineNo">227</span>    private long dataSize;<a name="line.227"></a>
+<span class="sourceLineNo">228</span>    private final long now = System.nanoTime();<a name="line.228"></a>
+<span class="sourceLineNo">229</span>    /**<a name="line.229"></a>
+<span class="sourceLineNo">230</span>     * How many blocks to look at before we give up.<a name="line.230"></a>
+<span class="sourceLineNo">231</span>     * There could be many millions of blocks. We don't want the<a name="line.231"></a>
+<span class="sourceLineNo">232</span>     * ui to freeze while we run through 1B blocks... users will<a name="line.232"></a>
+<span class="sourceLineNo">233</span>     * think hbase dead. UI displays warning in red when stats<a name="line.233"></a>
+<span class="sourceLineNo">234</span>     * are incomplete.<a name="line.234"></a>
+<span class="sourceLineNo">235</span>     */<a name="line.235"></a>
+<span class="sourceLineNo">236</span>    private final int max;<a name="line.236"></a>
+<span class="sourceLineNo">237</span>    public static final int DEFAULT_MAX = 1000000;<a name="line.237"></a>
+<span class="sourceLineNo">238</span><a name="line.238"></a>
+<span class="sourceLineNo">239</span>    CachedBlocksByFile() {<a name="line.239"></a>
+<span class="sourceLineNo">240</span>      this(null);<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>    CachedBlocksByFile(final Configuration c) {<a name="line.243"></a>
+<span class="sourceLineNo">244</span>      this.max = c == null? DEFAULT_MAX: c.getInt("hbase.ui.blockcache.by.file.max", DEFAULT_MAX);<a name="line.244"></a>
+<span class="sourceLineNo">245</span>    }<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>     * Map by filename. use concurent utils because we want our Map and contained blocks sorted.<a name="line.248"></a>
 <span class="sourceLineNo">249</span>     */<a name="line.249"></a>
-<span class="sourceLineNo">250</span>    public boolean isFull() {<a name="line.250"></a>
-<span class="sourceLineNo">251</span>      return this.count &gt;= this.max;<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 NavigableMap&lt;String, NavigableSet&lt;CachedBlock&gt;&gt; getCachedBlockStatsByFile() {<a name="line.254"></a>
-<span class="sourceLineNo">255</span>      return this.cachedBlockByFile;<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 count of blocks in the cache<a name="line.259"></a>
-<span class="sourceLineNo">260</span>     */<a name="line.260"></a>
-<span class="sourceLineNo">261</span>    public int getCount() {<a name="line.261"></a>
-<span class="sourceLineNo">262</span>      return count;<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>    public int getDataCount() {<a name="line.265"></a>
-<span class="sourceLineNo">266</span>      return dataBlockCount;<a name="line.266"></a>
-<span class="sourceLineNo">267</span>    }<a name="line.267"></a>
-<span class="sourceLineNo">268</span><a name="line.268"></a>
-<span class="sourceLineNo">269</span>    /**<a name="line.269"></a>
-<span class="sourceLineNo">270</span>     * @return size of blocks in the cache<a name="line.270"></a>
-<span class="sourceLineNo">271</span>     */<a name="line.271"></a>
-<span class="sourceLineNo">272</span>    public long getSize() {<a name="line.272"></a>
-<span class="sourceLineNo">273</span>      return size;<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>     * @return Size of data.<a name="line.277"></a>
-<span class="sourceLineNo">278</span>     */<a name="line.278"></a>
-<span class="sourceLineNo">279</span>    public long getDataSize() {<a name="line.279"></a>
-<span class="sourceLineNo">280</span>      return dataSize;<a name="line.280"></a>
-<span class="sourceLineNo">281</span>    }<a name="line.281"></a>
-<span class="sourceLineNo">282</span><a name="line.282"></a>
-<span class="sourceLineNo">283</span>    public AgeSnapshot getAgeInCacheSnapshot() {<a name="line.283"></a>
-<span class="sourceLineNo">284</span>      return new AgeSnapshot(this.hist);<a name="line.284"></a>
-<span class="sourceLineNo">285</span>    }<a name="line.285"></a>
-<span class="sourceLineNo">286</span><a name="line.286"></a>
-<span class="sourceLineNo">287</span>    @Override<a name="line.287"></a>
-<span class="sourceLineNo">288</span>    public String toString() {<a name="line.288"></a>
-<span class="sourceLineNo">289</span>      AgeSnapshot snapshot = getAgeInCacheSnapshot();<a name="line.289"></a>
-<span class="sourceLineNo">290</span>      return "count=" + count + ", dataBlockCount=" + dataBlockCount + ", size=" + size +<a name="line.290"></a>
-<span class="sourceLineNo">291</span>          ", dataSize=" + getDataSize() +<a name="line.291"></a>
-<span class="sourceLineNo">292</span>          ", mean age=" + snapshot.getMean() +<a name="line.292"></a>
-<span class="sourceLineNo">293</span>          ", min age=" + snapshot.getMin() +<a name="line.293"></a>
-<span class="sourceLineNo">294</span>          ", max age=" + snapshot.getMax() +<a name="line.294"></a>
-<span class="sourceLineNo">295</span>          ", 75th percentile age="   + snapshot.get75thPercentile() +<a name="line.295"></a>
-<span class="sourceLineNo">296</span>          ", 95th percentile age="   + snapshot.get95thPercentile() +<a name="line.296"></a>
-<span class="sourceLineNo">297</span>          ", 98th percentile age="   + snapshot.get98thPercentile() +<a name="line.297"></a>
-<span class="sourceLineNo">298</span>          ", 99th percentile age="   + snapshot.get99thPercentile() +<a name="line.298"></a>
-<span class="sourceLineNo">299</span>          ", 99.9th percentile age=" + snapshot.get99thPercentile();<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">250</span>    private NavigableMap&lt;String, NavigableSet&lt;CachedBlock&gt;&gt; cachedBlockByFile = new ConcurrentSkipListMap&lt;&gt;();<a name="line.250"></a>
+<span class="sourceLineNo">251</span>    FastLongHistogram hist = new FastLongHistogram();<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>     * @param cb<a name="line.254"></a>
+<span class="sourceLineNo">255</span>     * @return True if full.... if we won't be adding any more.<a name="line.255"></a>
+<span class="sourceLineNo">256</span>     */<a name="line.256"></a>
+<span class="sourceLineNo">257</span>    public boolean update(final CachedBlock cb) {<a name="line.257"></a>
+<span class="sourceLineNo">258</span>      if (isFull()) return true;<a name="line.258"></a>
+<span class="sourceLineNo">259</span>      NavigableSet&lt;CachedBlock&gt; set = this.cachedBlockByFile.get(cb.getFilename());<a name="line.259"></a>
+<span class="sourceLineNo">260</span>      if (set == null) {<a name="line.260"></a>
+<span class="sourceLineNo">261</span>        set = new ConcurrentSkipListSet&lt;&gt;();<a name="line.261"></a>
+<span class="sourceLineNo">262</span>        this.cachedBlockByFile.put(cb.getFilename(), set);<a name="line.262"></a>
+<span class="sourceLineNo">263</span>      }<a name="line.263"></a>
+<span class="sourceLineNo">264</span>      set.add(cb);<a name="line.264"></a>
+<span class="sourceLineNo">265</span>      this.size += cb.getSize();<a name="line.265"></a>
+<span class="sourceLineNo">266</span>      this.count++;<a name="line.266"></a>
+<span class="sourceLineNo">267</span>      BlockType bt = cb.getBlockType();<a name="line.267"></a>
+<span class="sourceLineNo">268</span>      if (bt != null &amp;&amp; bt.isData()) {<a name="line.268"></a>
+<span class="sourceLineNo">269</span>        this.dataBlockCount++;<a name="line.269"></a>
+<span class="sourceLineNo">270</span>        this.dataSize += cb.getSize();<a name="line.270"></a>
+<span class="sourceLineNo">271</span>      }<a name="line.271"></a>
+<span class="sourceLineNo">272</span>      long age = (this.now - cb.getCachedTime())/NANOS_PER_SECOND;<a name="line.272"></a>
+<span class="sourceLineNo">273</span>      this.hist.add(age, 1);<a name="line.273"></a>
+<span class="sourceLineNo">274</span>      return false;<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>     * @return True if full; i.e. there are more items in the cache but we only loaded up<a name="line.278"></a>
+<span class="sourceLineNo">279</span>     * the maximum set in configuration &lt;code&gt;hbase.ui.blockcache.by.file.max&lt;/code&gt;<a name="line.279"></a>
+<span class="sourceLineNo">280</span>     * (Default: DEFAULT_MAX).<a name="line.280"></a>
+<span class="sourceLineNo">281</span>     */<a name="line.281"></a>
+<span class="sourceLineNo">282</span>    public boolean isFull() {<a name="line.282"></a>
+<span class="sourceLineNo">283</span>      return this.count &gt;= this.max;<a name="line.283"></a>
+<span class="sourceLineNo">284</span>    }<a name="line.284"></a>
+<span class="sourceLineNo">285</span><a name="line.285"></a>
+<span class="sourceLineNo">286</span>    public NavigableMap&lt;String, NavigableSet&lt;CachedBlock&gt;&gt; getCachedBlockStatsByFile() {<a name="line.286"></a>
+<span class="sourceLineNo">287</span>      return this.cachedBlockByFile;<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>    /**<a name="line.290"></a>
+<span class="sourceLineNo">291</span>     * @return count of blocks in the cache<a name="line.291"></a>
+<span class="sourceLineNo">292</span>     */<a name="line.292"></a>
+<span class="sourceLineNo">293</span>    public int getCount() {<a name="line.293"></a>
+<span class="sourceLineNo">294</span>      return count;<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 int getDataCount() {<a name="line.297"></a>
+<span class="sourceLineNo">298</span>      return dataBlockCount;<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>     * @return size of blocks in the cache<a name="line.302"></a>
+<span class="sourceLineNo">303</span>     */<a name="line.303"></a>
+<span class="sourceLineNo">304</span>    public long getSize() {<a name="line.304"></a>
+<span class="sourceLineNo">305</span>      return size;<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>     * @return Size of data.<a name="line.309"></a>
+<span class="sourceLineNo">310</span>     */<a name="line.310"></a>
+<span class="sourceLineNo">311</span>    public long getDataSize() {<a name="line.311"></a>
+<span class="sourceLineNo">312</span>      return dataSize;<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>    public AgeSnapshot getAgeInCacheSnapshot() {<a name="line.315"></a>
+<span class="sourceLineNo">316</span>      return new AgeSnapshot(this.hist);<a name="line.316"></a>
+<span class="sourceLineNo">317</span>    }<a name="line.317"></a>
+<span class="sourceLineNo">318</span><a name="line.318"></a>
+<span class="sourceLineNo">319</span>    @Override<a name="line.319"></a>
+<span class="sourceLineNo">320</span>    public String toString() {<a name="line.320"></a>
+<span class="sourceLineNo">321</span>      AgeSnapshot snapshot = getAgeInCacheSnapshot();<a name="line.321"></a>
+<span class="sourceLineNo">322</span>      return "count=" + count + ", dataBlockCount=" + dataBlockCount + ", size=" + size +<a name="line.322"></a>
+<span class="sourceLineNo">323</span>          ", dataSize=" + getDataSize() +<a name="line.323"></a>
+<span class="sourceLineNo">324</span>          ", mean age=" + snapshot.getMean() +<a name="line.324"></a>
+<span class="sourceLineNo">325</span>          ", min age=" + snapshot.getMin() +<a name="line.325"></a>
+<span class="sourceLineNo">326</span>          ", max age=" + snapshot.getMax() +<a name="line.326"></a>
+<span class="sourceLineNo">327</span>          ", 75th percentile age="   + snapshot.get75thPercentile() +<a name="line.327"></a>
+<span class="sourceLineNo">328</span>          ", 95th percentile age="   + snapshot.get95thPercentile() +<a name="line.328"></a>
+<span class="sourceLineNo">329</span>          ", 98th percentile age="   + snapshot.get98thPercentile() +<a name="line.329"></a>
+<span class="sourceLineNo">330</span>          ", 99th percentile age="   + snapshot.get99thPercentile() +<a name="line.330"></a>
+<span class="sourceLineNo">331</span>          ", 99.9th percentile age=" + snapshot.get99thPercentile();<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>
 
 
 

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/Cacheable.MemoryType.html
----------------------------------------------------------------------
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/Cacheable.MemoryType.html b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/Cacheable.MemoryType.html
index 93bab5a..8f57254 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/Cacheable.MemoryType.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/Cacheable.MemoryType.html
@@ -54,36 +54,37 @@
 <span class="sourceLineNo">046</span>  /**<a name="line.46"></a>
 <span class="sourceLineNo">047</span>   * Serializes its data into destination.<a name="line.47"></a>
 <span class="sourceLineNo">048</span>   * @param destination Where to serialize to<a name="line.48"></a>
-<span class="sourceLineNo">049</span>   */<a name="line.49"></a>
-<span class="sourceLineNo">050</span>  void serialize(ByteBuffer destination);<a name="line.50"></a>
-<span class="sourceLineNo">051</span><a name="line.51"></a>
-<span class="sourceLineNo">052</span>  /**<a name="line.52"></a>
-<span class="sourceLineNo">053</span>   * Returns CacheableDeserializer instance which reconstructs original object from ByteBuffer.<a name="line.53"></a>
-<span class="sourceLineNo">054</span>   *<a name="line.54"></a>
-<span class="sourceLineNo">055</span>   * @return CacheableDeserialzer instance.<a name="line.55"></a>
-<span class="sourceLineNo">056</span>   */<a name="line.56"></a>
-<span class="sourceLineNo">057</span>  CacheableDeserializer&lt;Cacheable&gt; getDeserializer();<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>   * @return the block type of this cached HFile block<a name="line.60"></a>
-<span class="sourceLineNo">061</span>   */<a name="line.61"></a>
-<span class="sourceLineNo">062</span>  BlockType getBlockType();<a name="line.62"></a>
-<span class="sourceLineNo">063</span><a name="line.63"></a>
-<span class="sourceLineNo">064</span>  /**<a name="line.64"></a>
-<span class="sourceLineNo">065</span>   * @return the {@code MemoryType} of this Cacheable<a name="line.65"></a>
-<span class="sourceLineNo">066</span>   */<a name="line.66"></a>
-<span class="sourceLineNo">067</span>  MemoryType getMemoryType();<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>   * SHARED means when this Cacheable is read back from cache it refers to the same memory area as<a name="line.70"></a>
-<span class="sourceLineNo">071</span>   * used by the cache for caching it.<a name="line.71"></a>
-<span class="sourceLineNo">072</span>   * EXCLUSIVE means when this Cacheable is read back from cache, the data was copied to an<a name="line.72"></a>
-<span class="sourceLineNo">073</span>   * exclusive memory area of this Cacheable.<a name="line.73"></a>
-<span class="sourceLineNo">074</span>   */<a name="line.74"></a>
-<span class="sourceLineNo">075</span>  public static enum MemoryType {<a name="line.75"></a>
-<span class="sourceLineNo">076</span>    SHARED, EXCLUSIVE<a name="line.76"></a>
-<span class="sourceLineNo">077</span>  }<a name="line.77"></a>
-<span class="sourceLineNo">078</span>}<a name="line.78"></a>
+<span class="sourceLineNo">049</span>   * @param includeNextBlockMetadata Whether to include nextBlockMetadata in the Cache block.<a name="line.49"></a>
+<span class="sourceLineNo">050</span>   */<a name="line.50"></a>
+<span class="sourceLineNo">051</span>  void serialize(ByteBuffer destination, boolean includeNextBlockMetadata);<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>   * Returns CacheableDeserializer instance which reconstructs original object from ByteBuffer.<a name="line.54"></a>
+<span class="sourceLineNo">055</span>   *<a name="line.55"></a>
+<span class="sourceLineNo">056</span>   * @return CacheableDeserialzer instance.<a name="line.56"></a>
+<span class="sourceLineNo">057</span>   */<a name="line.57"></a>
+<span class="sourceLineNo">058</span>  CacheableDeserializer&lt;Cacheable&gt; getDeserializer();<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>   * @return the block type of this cached HFile block<a name="line.61"></a>
+<span class="sourceLineNo">062</span>   */<a name="line.62"></a>
+<span class="sourceLineNo">063</span>  BlockType getBlockType();<a name="line.63"></a>
+<span class="sourceLineNo">064</span><a name="line.64"></a>
+<span class="sourceLineNo">065</span>  /**<a name="line.65"></a>
+<span class="sourceLineNo">066</span>   * @return the {@code MemoryType} of this Cacheable<a name="line.66"></a>
+<span class="sourceLineNo">067</span>   */<a name="line.67"></a>
+<span class="sourceLineNo">068</span>  MemoryType getMemoryType();<a name="line.68"></a>
+<span class="sourceLineNo">069</span><a name="line.69"></a>
+<span class="sourceLineNo">070</span>  /**<a name="line.70"></a>
+<span class="sourceLineNo">071</span>   * SHARED means when this Cacheable is read back from cache it refers to the same memory area as<a name="line.71"></a>
+<span class="sourceLineNo">072</span>   * used by the cache for caching it.<a name="line.72"></a>
+<span class="sourceLineNo">073</span>   * EXCLUSIVE means when this Cacheable is read back from cache, the data was copied to an<a name="line.73"></a>
+<span class="sourceLineNo">074</span>   * exclusive memory area of this Cacheable.<a name="line.74"></a>
+<span class="sourceLineNo">075</span>   */<a name="line.75"></a>
+<span class="sourceLineNo">076</span>  public static enum MemoryType {<a name="line.76"></a>
+<span class="sourceLineNo">077</span>    SHARED, EXCLUSIVE<a name="line.77"></a>
+<span class="sourceLineNo">078</span>  }<a name="line.78"></a>
+<span class="sourceLineNo">079</span>}<a name="line.79"></a>
 
 
 

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/Cacheable.html
----------------------------------------------------------------------
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/Cacheable.html b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/Cacheable.html
index 93bab5a..8f57254 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/Cacheable.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/Cacheable.html
@@ -54,36 +54,37 @@
 <span class="sourceLineNo">046</span>  /**<a name="line.46"></a>
 <span class="sourceLineNo">047</span>   * Serializes its data into destination.<a name="line.47"></a>
 <span class="sourceLineNo">048</span>   * @param destination Where to serialize to<a name="line.48"></a>
-<span class="sourceLineNo">049</span>   */<a name="line.49"></a>
-<span class="sourceLineNo">050</span>  void serialize(ByteBuffer destination);<a name="line.50"></a>
-<span class="sourceLineNo">051</span><a name="line.51"></a>
-<span class="sourceLineNo">052</span>  /**<a name="line.52"></a>
-<span class="sourceLineNo">053</span>   * Returns CacheableDeserializer instance which reconstructs original object from ByteBuffer.<a name="line.53"></a>
-<span class="sourceLineNo">054</span>   *<a name="line.54"></a>
-<span class="sourceLineNo">055</span>   * @return CacheableDeserialzer instance.<a name="line.55"></a>
-<span class="sourceLineNo">056</span>   */<a name="line.56"></a>
-<span class="sourceLineNo">057</span>  CacheableDeserializer&lt;Cacheable&gt; getDeserializer();<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>   * @return the block type of this cached HFile block<a name="line.60"></a>
-<span class="sourceLineNo">061</span>   */<a name="line.61"></a>
-<span class="sourceLineNo">062</span>  BlockType getBlockType();<a name="line.62"></a>
-<span class="sourceLineNo">063</span><a name="line.63"></a>
-<span class="sourceLineNo">064</span>  /**<a name="line.64"></a>
-<span class="sourceLineNo">065</span>   * @return the {@code MemoryType} of this Cacheable<a name="line.65"></a>
-<span class="sourceLineNo">066</span>   */<a name="line.66"></a>
-<span class="sourceLineNo">067</span>  MemoryType getMemoryType();<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>   * SHARED means when this Cacheable is read back from cache it refers to the same memory area as<a name="line.70"></a>
-<span class="sourceLineNo">071</span>   * used by the cache for caching it.<a name="line.71"></a>
-<span class="sourceLineNo">072</span>   * EXCLUSIVE means when this Cacheable is read back from cache, the data was copied to an<a name="line.72"></a>
-<span class="sourceLineNo">073</span>   * exclusive memory area of this Cacheable.<a name="line.73"></a>
-<span class="sourceLineNo">074</span>   */<a name="line.74"></a>
-<span class="sourceLineNo">075</span>  public static enum MemoryType {<a name="line.75"></a>
-<span class="sourceLineNo">076</span>    SHARED, EXCLUSIVE<a name="line.76"></a>
-<span class="sourceLineNo">077</span>  }<a name="line.77"></a>
-<span class="sourceLineNo">078</span>}<a name="line.78"></a>
+<span class="sourceLineNo">049</span>   * @param includeNextBlockMetadata Whether to include nextBlockMetadata in the Cache block.<a name="line.49"></a>
+<span class="sourceLineNo">050</span>   */<a name="line.50"></a>
+<span class="sourceLineNo">051</span>  void serialize(ByteBuffer destination, boolean includeNextBlockMetadata);<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>   * Returns CacheableDeserializer instance which reconstructs original object from ByteBuffer.<a name="line.54"></a>
+<span class="sourceLineNo">055</span>   *<a name="line.55"></a>
+<span class="sourceLineNo">056</span>   * @return CacheableDeserialzer instance.<a name="line.56"></a>
+<span class="sourceLineNo">057</span>   */<a name="line.57"></a>
+<span class="sourceLineNo">058</span>  CacheableDeserializer&lt;Cacheable&gt; getDeserializer();<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>   * @return the block type of this cached HFile block<a name="line.61"></a>
+<span class="sourceLineNo">062</span>   */<a name="line.62"></a>
+<span class="sourceLineNo">063</span>  BlockType getBlockType();<a name="line.63"></a>
+<span class="sourceLineNo">064</span><a name="line.64"></a>
+<span class="sourceLineNo">065</span>  /**<a name="line.65"></a>
+<span class="sourceLineNo">066</span>   * @return the {@code MemoryType} of this Cacheable<a name="line.66"></a>
+<span class="sourceLineNo">067</span>   */<a name="line.67"></a>
+<span class="sourceLineNo">068</span>  MemoryType getMemoryType();<a name="line.68"></a>
+<span class="sourceLineNo">069</span><a name="line.69"></a>
+<span class="sourceLineNo">070</span>  /**<a name="line.70"></a>
+<span class="sourceLineNo">071</span>   * SHARED means when this Cacheable is read back from cache it refers to the same memory area as<a name="line.71"></a>
+<span class="sourceLineNo">072</span>   * used by the cache for caching it.<a name="line.72"></a>
+<span class="sourceLineNo">073</span>   * EXCLUSIVE means when this Cacheable is read back from cache, the data was copied to an<a name="line.73"></a>
+<span class="sourceLineNo">074</span>   * exclusive memory area of this Cacheable.<a name="line.74"></a>
+<span class="sourceLineNo">075</span>   */<a name="line.75"></a>
+<span class="sourceLineNo">076</span>  public static enum MemoryType {<a name="line.76"></a>
+<span class="sourceLineNo">077</span>    SHARED, EXCLUSIVE<a name="line.77"></a>
+<span class="sourceLineNo">078</span>  }<a name="line.78"></a>
+<span class="sourceLineNo">079</span>}<a name="line.79"></a>
 
 
 


[20/50] hbase-site git commit: Published site at 26babcf013de696b899d76a3c39434b794440d8d.

Posted by gi...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.WriterThread.html
----------------------------------------------------------------------
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.WriterThread.html b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.WriterThread.html
index e8070ca..8cb24b3 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.WriterThread.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.WriterThread.html
@@ -433,1254 +433,1261 @@
 <span class="sourceLineNo">425</span>      return;<a name="line.425"></a>
 <span class="sourceLineNo">426</span>    }<a name="line.426"></a>
 <span class="sourceLineNo">427</span><a name="line.427"></a>
-<span class="sourceLineNo">428</span>    if (backingMap.containsKey(cacheKey)) {<a name="line.428"></a>
+<span class="sourceLineNo">428</span>    if (backingMap.containsKey(cacheKey) || ramCache.containsKey(cacheKey)) {<a name="line.428"></a>
 <span class="sourceLineNo">429</span>      Cacheable existingBlock = getBlock(cacheKey, false, false, false);<a name="line.429"></a>
-<span class="sourceLineNo">430</span>      try {<a name="line.430"></a>
-<span class="sourceLineNo">431</span>        if (BlockCacheUtil.compareCacheBlock(cachedItem, existingBlock) != 0) {<a name="line.431"></a>
-<span class="sourceLineNo">432</span>          throw new RuntimeException("Cached block contents differ, which should not have happened."<a name="line.432"></a>
-<span class="sourceLineNo">433</span>              + "cacheKey:" + cacheKey);<a name="line.433"></a>
-<span class="sourceLineNo">434</span>        }<a name="line.434"></a>
-<span class="sourceLineNo">435</span>        String msg = "Caching an already cached block: " + cacheKey;<a name="line.435"></a>
-<span class="sourceLineNo">436</span>        msg += ". This is harmless and can happen in rare cases (see HBASE-8547)";<a name="line.436"></a>
-<span class="sourceLineNo">437</span>        LOG.warn(msg);<a name="line.437"></a>
-<span class="sourceLineNo">438</span>      } finally {<a name="line.438"></a>
-<span class="sourceLineNo">439</span>        // return the block since we need to decrement the count<a name="line.439"></a>
-<span class="sourceLineNo">440</span>        returnBlock(cacheKey, existingBlock);<a name="line.440"></a>
-<span class="sourceLineNo">441</span>      }<a name="line.441"></a>
-<span class="sourceLineNo">442</span>      return;<a name="line.442"></a>
-<span class="sourceLineNo">443</span>    }<a name="line.443"></a>
-<span class="sourceLineNo">444</span><a name="line.444"></a>
-<span class="sourceLineNo">445</span>    /*<a name="line.445"></a>
-<span class="sourceLineNo">446</span>     * Stuff the entry into the RAM cache so it can get drained to the persistent store<a name="line.446"></a>
-<span class="sourceLineNo">447</span>     */<a name="line.447"></a>
-<span class="sourceLineNo">448</span>    RAMQueueEntry re =<a name="line.448"></a>
-<span class="sourceLineNo">449</span>        new RAMQueueEntry(cacheKey, cachedItem, accessCount.incrementAndGet(), inMemory);<a name="line.449"></a>
-<span class="sourceLineNo">450</span>    if (ramCache.putIfAbsent(cacheKey, re) != null) {<a name="line.450"></a>
-<span class="sourceLineNo">451</span>      return;<a name="line.451"></a>
-<span class="sourceLineNo">452</span>    }<a name="line.452"></a>
-<span class="sourceLineNo">453</span>    int queueNum = (cacheKey.hashCode() &amp; 0x7FFFFFFF) % writerQueues.size();<a name="line.453"></a>
-<span class="sourceLineNo">454</span>    BlockingQueue&lt;RAMQueueEntry&gt; bq = writerQueues.get(queueNum);<a name="line.454"></a>
-<span class="sourceLineNo">455</span>    boolean successfulAddition = false;<a name="line.455"></a>
-<span class="sourceLineNo">456</span>    if (wait) {<a name="line.456"></a>
-<span class="sourceLineNo">457</span>      try {<a name="line.457"></a>
-<span class="sourceLineNo">458</span>        successfulAddition = bq.offer(re, DEFAULT_CACHE_WAIT_TIME, TimeUnit.MILLISECONDS);<a name="line.458"></a>
-<span class="sourceLineNo">459</span>      } catch (InterruptedException e) {<a name="line.459"></a>
-<span class="sourceLineNo">460</span>        Thread.currentThread().interrupt();<a name="line.460"></a>
-<span class="sourceLineNo">461</span>      }<a name="line.461"></a>
-<span class="sourceLineNo">462</span>    } else {<a name="line.462"></a>
-<span class="sourceLineNo">463</span>      successfulAddition = bq.offer(re);<a name="line.463"></a>
-<span class="sourceLineNo">464</span>    }<a name="line.464"></a>
-<span class="sourceLineNo">465</span>    if (!successfulAddition) {<a name="line.465"></a>
-<span class="sourceLineNo">466</span>      ramCache.remove(cacheKey);<a name="line.466"></a>
-<span class="sourceLineNo">467</span>      cacheStats.failInsert();<a name="line.467"></a>
-<span class="sourceLineNo">468</span>    } else {<a name="line.468"></a>
-<span class="sourceLineNo">469</span>      this.blockNumber.increment();<a name="line.469"></a>
-<span class="sourceLineNo">470</span>      this.heapSize.add(cachedItem.heapSize());<a name="line.470"></a>
-<span class="sourceLineNo">471</span>      blocksByHFile.add(cacheKey);<a name="line.471"></a>
-<span class="sourceLineNo">472</span>    }<a name="line.472"></a>
-<span class="sourceLineNo">473</span>  }<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>   * Get the buffer of the block with the specified key.<a name="line.476"></a>
-<span class="sourceLineNo">477</span>   * @param key block's cache key<a name="line.477"></a>
-<span class="sourceLineNo">478</span>   * @param caching true if the caller caches blocks on cache misses<a name="line.478"></a>
-<span class="sourceLineNo">479</span>   * @param repeat Whether this is a repeat lookup for the same block<a name="line.479"></a>
-<span class="sourceLineNo">480</span>   * @param updateCacheMetrics Whether we should update cache metrics or not<a name="line.480"></a>
-<span class="sourceLineNo">481</span>   * @return buffer of specified cache key, or null if not in cache<a name="line.481"></a>
-<span class="sourceLineNo">482</span>   */<a name="line.482"></a>
-<span class="sourceLineNo">483</span>  @Override<a name="line.483"></a>
-<span class="sourceLineNo">484</span>  public Cacheable getBlock(BlockCacheKey key, boolean caching, boolean repeat,<a name="line.484"></a>
-<span class="sourceLineNo">485</span>      boolean updateCacheMetrics) {<a name="line.485"></a>
-<span class="sourceLineNo">486</span>    if (!cacheEnabled) {<a name="line.486"></a>
-<span class="sourceLineNo">487</span>      return null;<a name="line.487"></a>
-<span class="sourceLineNo">488</span>    }<a name="line.488"></a>
-<span class="sourceLineNo">489</span>    RAMQueueEntry re = ramCache.get(key);<a name="line.489"></a>
-<span class="sourceLineNo">490</span>    if (re != null) {<a name="line.490"></a>
-<span class="sourceLineNo">491</span>      if (updateCacheMetrics) {<a name="line.491"></a>
-<span class="sourceLineNo">492</span>        cacheStats.hit(caching, key.isPrimary(), key.getBlockType());<a name="line.492"></a>
-<span class="sourceLineNo">493</span>      }<a name="line.493"></a>
-<span class="sourceLineNo">494</span>      re.access(accessCount.incrementAndGet());<a name="line.494"></a>
-<span class="sourceLineNo">495</span>      return re.getData();<a name="line.495"></a>
-<span class="sourceLineNo">496</span>    }<a name="line.496"></a>
-<span class="sourceLineNo">497</span>    BucketEntry bucketEntry = backingMap.get(key);<a name="line.497"></a>
-<span class="sourceLineNo">498</span>    if (bucketEntry != null) {<a name="line.498"></a>
-<span class="sourceLineNo">499</span>      long start = System.nanoTime();<a name="line.499"></a>
-<span class="sourceLineNo">500</span>      ReentrantReadWriteLock lock = offsetLock.getLock(bucketEntry.offset());<a name="line.500"></a>
-<span class="sourceLineNo">501</span>      try {<a name="line.501"></a>
-<span class="sourceLineNo">502</span>        lock.readLock().lock();<a name="line.502"></a>
-<span class="sourceLineNo">503</span>        // We can not read here even if backingMap does contain the given key because its offset<a name="line.503"></a>
-<span class="sourceLineNo">504</span>        // maybe changed. If we lock BlockCacheKey instead of offset, then we can only check<a name="line.504"></a>
-<span class="sourceLineNo">505</span>        // existence here.<a name="line.505"></a>
-<span class="sourceLineNo">506</span>        if (bucketEntry.equals(backingMap.get(key))) {<a name="line.506"></a>
-<span class="sourceLineNo">507</span>          // TODO : change this area - should be removed after server cells and<a name="line.507"></a>
-<span class="sourceLineNo">508</span>          // 12295 are available<a name="line.508"></a>
-<span class="sourceLineNo">509</span>          int len = bucketEntry.getLength();<a name="line.509"></a>
-<span class="sourceLineNo">510</span>          if (LOG.isTraceEnabled()) {<a name="line.510"></a>
-<span class="sourceLineNo">511</span>            LOG.trace("Read offset=" + bucketEntry.offset() + ", len=" + len);<a name="line.511"></a>
-<span class="sourceLineNo">512</span>          }<a name="line.512"></a>
-<span class="sourceLineNo">513</span>          Cacheable cachedBlock = ioEngine.read(bucketEntry.offset(), len,<a name="line.513"></a>
-<span class="sourceLineNo">514</span>              bucketEntry.deserializerReference(this.deserialiserMap));<a name="line.514"></a>
-<span class="sourceLineNo">515</span>          long timeTaken = System.nanoTime() - start;<a name="line.515"></a>
-<span class="sourceLineNo">516</span>          if (updateCacheMetrics) {<a name="line.516"></a>
-<span class="sourceLineNo">517</span>            cacheStats.hit(caching, key.isPrimary(), key.getBlockType());<a name="line.517"></a>
-<span class="sourceLineNo">518</span>            cacheStats.ioHit(timeTaken);<a name="line.518"></a>
+<span class="sourceLineNo">430</span><a name="line.430"></a>
+<span class="sourceLineNo">431</span>      try {<a name="line.431"></a>
+<span class="sourceLineNo">432</span>        int comparison = BlockCacheUtil.validateBlockAddition(existingBlock, cachedItem, cacheKey);<a name="line.432"></a>
+<span class="sourceLineNo">433</span>        if (comparison != 0) {<a name="line.433"></a>
+<span class="sourceLineNo">434</span>          if (comparison &lt; 0) {<a name="line.434"></a>
+<span class="sourceLineNo">435</span>            LOG.warn("Cached block contents differ by nextBlockOnDiskSize. Keeping cached block.");<a name="line.435"></a>
+<span class="sourceLineNo">436</span>            return;<a name="line.436"></a>
+<span class="sourceLineNo">437</span>          } else {<a name="line.437"></a>
+<span class="sourceLineNo">438</span>            LOG.warn("Cached block contents differ by nextBlockOnDiskSize. Caching new block.");<a name="line.438"></a>
+<span class="sourceLineNo">439</span>          }<a name="line.439"></a>
+<span class="sourceLineNo">440</span>        } else {<a name="line.440"></a>
+<span class="sourceLineNo">441</span>          String msg = "Caching an already cached block: " + cacheKey;<a name="line.441"></a>
+<span class="sourceLineNo">442</span>          msg += ". This is harmless and can happen in rare cases (see HBASE-8547)";<a name="line.442"></a>
+<span class="sourceLineNo">443</span>          LOG.warn(msg);<a name="line.443"></a>
+<span class="sourceLineNo">444</span>          return;<a name="line.444"></a>
+<span class="sourceLineNo">445</span>        }<a name="line.445"></a>
+<span class="sourceLineNo">446</span>      } finally {<a name="line.446"></a>
+<span class="sourceLineNo">447</span>        // return the block since we need to decrement the count<a name="line.447"></a>
+<span class="sourceLineNo">448</span>        returnBlock(cacheKey, existingBlock);<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><a name="line.451"></a>
+<span class="sourceLineNo">452</span>    /*<a name="line.452"></a>
+<span class="sourceLineNo">453</span>     * Stuff the entry into the RAM cache so it can get drained to the persistent store<a name="line.453"></a>
+<span class="sourceLineNo">454</span>     */<a name="line.454"></a>
+<span class="sourceLineNo">455</span>    RAMQueueEntry re =<a name="line.455"></a>
+<span class="sourceLineNo">456</span>        new RAMQueueEntry(cacheKey, cachedItem, accessCount.incrementAndGet(), inMemory);<a name="line.456"></a>
+<span class="sourceLineNo">457</span>    if (ramCache.putIfAbsent(cacheKey, re) != null) {<a name="line.457"></a>
+<span class="sourceLineNo">458</span>      return;<a name="line.458"></a>
+<span class="sourceLineNo">459</span>    }<a name="line.459"></a>
+<span class="sourceLineNo">460</span>    int queueNum = (cacheKey.hashCode() &amp; 0x7FFFFFFF) % writerQueues.size();<a name="line.460"></a>
+<span class="sourceLineNo">461</span>    BlockingQueue&lt;RAMQueueEntry&gt; bq = writerQueues.get(queueNum);<a name="line.461"></a>
+<span class="sourceLineNo">462</span>    boolean successfulAddition = false;<a name="line.462"></a>
+<span class="sourceLineNo">463</span>    if (wait) {<a name="line.463"></a>
+<span class="sourceLineNo">464</span>      try {<a name="line.464"></a>
+<span class="sourceLineNo">465</span>        successfulAddition = bq.offer(re, DEFAULT_CACHE_WAIT_TIME, TimeUnit.MILLISECONDS);<a name="line.465"></a>
+<span class="sourceLineNo">466</span>      } catch (InterruptedException e) {<a name="line.466"></a>
+<span class="sourceLineNo">467</span>        Thread.currentThread().interrupt();<a name="line.467"></a>
+<span class="sourceLineNo">468</span>      }<a name="line.468"></a>
+<span class="sourceLineNo">469</span>    } else {<a name="line.469"></a>
+<span class="sourceLineNo">470</span>      successfulAddition = bq.offer(re);<a name="line.470"></a>
+<span class="sourceLineNo">471</span>    }<a name="line.471"></a>
+<span class="sourceLineNo">472</span>    if (!successfulAddition) {<a name="line.472"></a>
+<span class="sourceLineNo">473</span>      ramCache.remove(cacheKey);<a name="line.473"></a>
+<span class="sourceLineNo">474</span>      cacheStats.failInsert();<a name="line.474"></a>
+<span class="sourceLineNo">475</span>    } else {<a name="line.475"></a>
+<span class="sourceLineNo">476</span>      this.blockNumber.increment();<a name="line.476"></a>
+<span class="sourceLineNo">477</span>      this.heapSize.add(cachedItem.heapSize());<a name="line.477"></a>
+<span class="sourceLineNo">478</span>      blocksByHFile.add(cacheKey);<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>  /**<a name="line.482"></a>
+<span class="sourceLineNo">483</span>   * Get the buffer of the block with the specified key.<a name="line.483"></a>
+<span class="sourceLineNo">484</span>   * @param key block's cache key<a name="line.484"></a>
+<span class="sourceLineNo">485</span>   * @param caching true if the caller caches blocks on cache misses<a name="line.485"></a>
+<span class="sourceLineNo">486</span>   * @param repeat Whether this is a repeat lookup for the same block<a name="line.486"></a>
+<span class="sourceLineNo">487</span>   * @param updateCacheMetrics Whether we should update cache metrics or not<a name="line.487"></a>
+<span class="sourceLineNo">488</span>   * @return buffer of specified cache key, or null if not in cache<a name="line.488"></a>
+<span class="sourceLineNo">489</span>   */<a name="line.489"></a>
+<span class="sourceLineNo">490</span>  @Override<a name="line.490"></a>
+<span class="sourceLineNo">491</span>  public Cacheable getBlock(BlockCacheKey key, boolean caching, boolean repeat,<a name="line.491"></a>
+<span class="sourceLineNo">492</span>      boolean updateCacheMetrics) {<a name="line.492"></a>
+<span class="sourceLineNo">493</span>    if (!cacheEnabled) {<a name="line.493"></a>
+<span class="sourceLineNo">494</span>      return null;<a name="line.494"></a>
+<span class="sourceLineNo">495</span>    }<a name="line.495"></a>
+<span class="sourceLineNo">496</span>    RAMQueueEntry re = ramCache.get(key);<a name="line.496"></a>
+<span class="sourceLineNo">497</span>    if (re != null) {<a name="line.497"></a>
+<span class="sourceLineNo">498</span>      if (updateCacheMetrics) {<a name="line.498"></a>
+<span class="sourceLineNo">499</span>        cacheStats.hit(caching, key.isPrimary(), key.getBlockType());<a name="line.499"></a>
+<span class="sourceLineNo">500</span>      }<a name="line.500"></a>
+<span class="sourceLineNo">501</span>      re.access(accessCount.incrementAndGet());<a name="line.501"></a>
+<span class="sourceLineNo">502</span>      return re.getData();<a name="line.502"></a>
+<span class="sourceLineNo">503</span>    }<a name="line.503"></a>
+<span class="sourceLineNo">504</span>    BucketEntry bucketEntry = backingMap.get(key);<a name="line.504"></a>
+<span class="sourceLineNo">505</span>    if (bucketEntry != null) {<a name="line.505"></a>
+<span class="sourceLineNo">506</span>      long start = System.nanoTime();<a name="line.506"></a>
+<span class="sourceLineNo">507</span>      ReentrantReadWriteLock lock = offsetLock.getLock(bucketEntry.offset());<a name="line.507"></a>
+<span class="sourceLineNo">508</span>      try {<a name="line.508"></a>
+<span class="sourceLineNo">509</span>        lock.readLock().lock();<a name="line.509"></a>
+<span class="sourceLineNo">510</span>        // We can not read here even if backingMap does contain the given key because its offset<a name="line.510"></a>
+<span class="sourceLineNo">511</span>        // maybe changed. If we lock BlockCacheKey instead of offset, then we can only check<a name="line.511"></a>
+<span class="sourceLineNo">512</span>        // existence here.<a name="line.512"></a>
+<span class="sourceLineNo">513</span>        if (bucketEntry.equals(backingMap.get(key))) {<a name="line.513"></a>
+<span class="sourceLineNo">514</span>          // TODO : change this area - should be removed after server cells and<a name="line.514"></a>
+<span class="sourceLineNo">515</span>          // 12295 are available<a name="line.515"></a>
+<span class="sourceLineNo">516</span>          int len = bucketEntry.getLength();<a name="line.516"></a>
+<span class="sourceLineNo">517</span>          if (LOG.isTraceEnabled()) {<a name="line.517"></a>
+<span class="sourceLineNo">518</span>            LOG.trace("Read offset=" + bucketEntry.offset() + ", len=" + len);<a name="line.518"></a>
 <span class="sourceLineNo">519</span>          }<a name="line.519"></a>
-<span class="sourceLineNo">520</span>          if (cachedBlock.getMemoryType() == MemoryType.SHARED) {<a name="line.520"></a>
-<span class="sourceLineNo">521</span>            bucketEntry.incrementRefCountAndGet();<a name="line.521"></a>
-<span class="sourceLineNo">522</span>          }<a name="line.522"></a>
-<span class="sourceLineNo">523</span>          bucketEntry.access(accessCount.incrementAndGet());<a name="line.523"></a>
-<span class="sourceLineNo">524</span>          if (this.ioErrorStartTime &gt; 0) {<a name="line.524"></a>
-<span class="sourceLineNo">525</span>            ioErrorStartTime = -1;<a name="line.525"></a>
+<span class="sourceLineNo">520</span>          Cacheable cachedBlock = ioEngine.read(bucketEntry.offset(), len,<a name="line.520"></a>
+<span class="sourceLineNo">521</span>              bucketEntry.deserializerReference(this.deserialiserMap));<a name="line.521"></a>
+<span class="sourceLineNo">522</span>          long timeTaken = System.nanoTime() - start;<a name="line.522"></a>
+<span class="sourceLineNo">523</span>          if (updateCacheMetrics) {<a name="line.523"></a>
+<span class="sourceLineNo">524</span>            cacheStats.hit(caching, key.isPrimary(), key.getBlockType());<a name="line.524"></a>
+<span class="sourceLineNo">525</span>            cacheStats.ioHit(timeTaken);<a name="line.525"></a>
 <span class="sourceLineNo">526</span>          }<a name="line.526"></a>
-<span class="sourceLineNo">527</span>          return cachedBlock;<a name="line.527"></a>
-<span class="sourceLineNo">528</span>        }<a name="line.528"></a>
-<span class="sourceLineNo">529</span>      } catch (IOException ioex) {<a name="line.529"></a>
-<span class="sourceLineNo">530</span>        LOG.error("Failed reading block " + key + " from bucket cache", ioex);<a name="line.530"></a>
-<span class="sourceLineNo">531</span>        checkIOErrorIsTolerated();<a name="line.531"></a>
-<span class="sourceLineNo">532</span>      } finally {<a name="line.532"></a>
-<span class="sourceLineNo">533</span>        lock.readLock().unlock();<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>    if (!repeat &amp;&amp; updateCacheMetrics) {<a name="line.536"></a>
-<span class="sourceLineNo">537</span>      cacheStats.miss(caching, key.isPrimary(), key.getBlockType());<a name="line.537"></a>
-<span class="sourceLineNo">538</span>    }<a name="line.538"></a>
-<span class="sourceLineNo">539</span>    return null;<a name="line.539"></a>
-<span class="sourceLineNo">540</span>  }<a name="line.540"></a>
-<span class="sourceLineNo">541</span><a name="line.541"></a>
-<span class="sourceLineNo">542</span>  @VisibleForTesting<a name="line.542"></a>
-<span class="sourceLineNo">543</span>  void blockEvicted(BlockCacheKey cacheKey, BucketEntry bucketEntry, boolean decrementBlockNumber) {<a name="line.543"></a>
-<span class="sourceLineNo">544</span>    bucketAllocator.freeBlock(bucketEntry.offset());<a name="line.544"></a>
-<span class="sourceLineNo">545</span>    realCacheSize.add(-1 * bucketEntry.getLength());<a name="line.545"></a>
-<span class="sourceLineNo">546</span>    blocksByHFile.remove(cacheKey);<a name="line.546"></a>
-<span class="sourceLineNo">547</span>    if (decrementBlockNumber) {<a name="line.547"></a>
-<span class="sourceLineNo">548</span>      this.blockNumber.decrement();<a name="line.548"></a>
-<span class="sourceLineNo">549</span>    }<a name="line.549"></a>
-<span class="sourceLineNo">550</span>  }<a name="line.550"></a>
-<span class="sourceLineNo">551</span><a name="line.551"></a>
-<span class="sourceLineNo">552</span>  @Override<a name="line.552"></a>
-<span class="sourceLineNo">553</span>  public boolean evictBlock(BlockCacheKey cacheKey) {<a name="line.553"></a>
-<span class="sourceLineNo">554</span>    return evictBlock(cacheKey, true);<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>  // does not check for the ref count. Just tries to evict it if found in the<a name="line.557"></a>
-<span class="sourceLineNo">558</span>  // bucket map<a name="line.558"></a>
-<span class="sourceLineNo">559</span>  private boolean forceEvict(BlockCacheKey cacheKey) {<a name="line.559"></a>
-<span class="sourceLineNo">560</span>    if (!cacheEnabled) {<a name="line.560"></a>
-<span class="sourceLineNo">561</span>      return false;<a name="line.561"></a>
-<span class="sourceLineNo">562</span>    }<a name="line.562"></a>
-<span class="sourceLineNo">563</span>    RAMQueueEntry removedBlock = checkRamCache(cacheKey);<a name="line.563"></a>
-<span class="sourceLineNo">564</span>    BucketEntry bucketEntry = backingMap.get(cacheKey);<a name="line.564"></a>
-<span class="sourceLineNo">565</span>    if (bucketEntry == null) {<a name="line.565"></a>
-<span class="sourceLineNo">566</span>      if (removedBlock != null) {<a name="line.566"></a>
-<span class="sourceLineNo">567</span>        cacheStats.evicted(0, cacheKey.isPrimary());<a name="line.567"></a>
-<span class="sourceLineNo">568</span>        return true;<a name="line.568"></a>
-<span class="sourceLineNo">569</span>      } else {<a name="line.569"></a>
-<span class="sourceLineNo">570</span>        return false;<a name="line.570"></a>
-<span class="sourceLineNo">571</span>      }<a name="line.571"></a>
-<span class="sourceLineNo">572</span>    }<a name="line.572"></a>
-<span class="sourceLineNo">573</span>    ReentrantReadWriteLock lock = offsetLock.getLock(bucketEntry.offset());<a name="line.573"></a>
-<span class="sourceLineNo">574</span>    try {<a name="line.574"></a>
-<span class="sourceLineNo">575</span>      lock.writeLock().lock();<a name="line.575"></a>
-<span class="sourceLineNo">576</span>      if (backingMap.remove(cacheKey, bucketEntry)) {<a name="line.576"></a>
-<span class="sourceLineNo">577</span>        blockEvicted(cacheKey, bucketEntry, removedBlock == null);<a name="line.577"></a>
-<span class="sourceLineNo">578</span>      } else {<a name="line.578"></a>
-<span class="sourceLineNo">579</span>        return false;<a name="line.579"></a>
-<span class="sourceLineNo">580</span>      }<a name="line.580"></a>
-<span class="sourceLineNo">581</span>    } finally {<a name="line.581"></a>
-<span class="sourceLineNo">582</span>      lock.writeLock().unlock();<a name="line.582"></a>
-<span class="sourceLineNo">583</span>    }<a name="line.583"></a>
-<span class="sourceLineNo">584</span>    cacheStats.evicted(bucketEntry.getCachedTime(), cacheKey.isPrimary());<a name="line.584"></a>
-<span class="sourceLineNo">585</span>    return true;<a name="line.585"></a>
-<span class="sourceLineNo">586</span>  }<a name="line.586"></a>
-<span class="sourceLineNo">587</span><a name="line.587"></a>
-<span class="sourceLineNo">588</span>  private RAMQueueEntry checkRamCache(BlockCacheKey cacheKey) {<a name="line.588"></a>
-<span class="sourceLineNo">589</span>    RAMQueueEntry removedBlock = ramCache.remove(cacheKey);<a name="line.589"></a>
-<span class="sourceLineNo">590</span>    if (removedBlock != null) {<a name="line.590"></a>
-<span class="sourceLineNo">591</span>      this.blockNumber.decrement();<a name="line.591"></a>
-<span class="sourceLineNo">592</span>      this.heapSize.add(-1 * removedBlock.getData().heapSize());<a name="line.592"></a>
-<span class="sourceLineNo">593</span>    }<a name="line.593"></a>
-<span class="sourceLineNo">594</span>    return removedBlock;<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>  public boolean evictBlock(BlockCacheKey cacheKey, boolean deletedBlock) {<a name="line.597"></a>
-<span class="sourceLineNo">598</span>    if (!cacheEnabled) {<a name="line.598"></a>
-<span class="sourceLineNo">599</span>      return false;<a name="line.599"></a>
+<span class="sourceLineNo">527</span>          if (cachedBlock.getMemoryType() == MemoryType.SHARED) {<a name="line.527"></a>
+<span class="sourceLineNo">528</span>            bucketEntry.incrementRefCountAndGet();<a name="line.528"></a>
+<span class="sourceLineNo">529</span>          }<a name="line.529"></a>
+<span class="sourceLineNo">530</span>          bucketEntry.access(accessCount.incrementAndGet());<a name="line.530"></a>
+<span class="sourceLineNo">531</span>          if (this.ioErrorStartTime &gt; 0) {<a name="line.531"></a>
+<span class="sourceLineNo">532</span>            ioErrorStartTime = -1;<a name="line.532"></a>
+<span class="sourceLineNo">533</span>          }<a name="line.533"></a>
+<span class="sourceLineNo">534</span>          return cachedBlock;<a name="line.534"></a>
+<span class="sourceLineNo">535</span>        }<a name="line.535"></a>
+<span class="sourceLineNo">536</span>      } catch (IOException ioex) {<a name="line.536"></a>
+<span class="sourceLineNo">537</span>        LOG.error("Failed reading block " + key + " from bucket cache", ioex);<a name="line.537"></a>
+<span class="sourceLineNo">538</span>        checkIOErrorIsTolerated();<a name="line.538"></a>
+<span class="sourceLineNo">539</span>      } finally {<a name="line.539"></a>
+<span class="sourceLineNo">540</span>        lock.readLock().unlock();<a name="line.540"></a>
+<span class="sourceLineNo">541</span>      }<a name="line.541"></a>
+<span class="sourceLineNo">542</span>    }<a name="line.542"></a>
+<span class="sourceLineNo">543</span>    if (!repeat &amp;&amp; updateCacheMetrics) {<a name="line.543"></a>
+<span class="sourceLineNo">544</span>      cacheStats.miss(caching, key.isPrimary(), key.getBlockType());<a name="line.544"></a>
+<span class="sourceLineNo">545</span>    }<a name="line.545"></a>
+<span class="sourceLineNo">546</span>    return null;<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>  @VisibleForTesting<a name="line.549"></a>
+<span class="sourceLineNo">550</span>  void blockEvicted(BlockCacheKey cacheKey, BucketEntry bucketEntry, boolean decrementBlockNumber) {<a name="line.550"></a>
+<span class="sourceLineNo">551</span>    bucketAllocator.freeBlock(bucketEntry.offset());<a name="line.551"></a>
+<span class="sourceLineNo">552</span>    realCacheSize.add(-1 * bucketEntry.getLength());<a name="line.552"></a>
+<span class="sourceLineNo">553</span>    blocksByHFile.remove(cacheKey);<a name="line.553"></a>
+<span class="sourceLineNo">554</span>    if (decrementBlockNumber) {<a name="line.554"></a>
+<span class="sourceLineNo">555</span>      this.blockNumber.decrement();<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>  @Override<a name="line.559"></a>
+<span class="sourceLineNo">560</span>  public boolean evictBlock(BlockCacheKey cacheKey) {<a name="line.560"></a>
+<span class="sourceLineNo">561</span>    return evictBlock(cacheKey, true);<a name="line.561"></a>
+<span class="sourceLineNo">562</span>  }<a name="line.562"></a>
+<span class="sourceLineNo">563</span><a name="line.563"></a>
+<span class="sourceLineNo">564</span>  // does not check for the ref count. Just tries to evict it if found in the<a name="line.564"></a>
+<span class="sourceLineNo">565</span>  // bucket map<a name="line.565"></a>
+<span class="sourceLineNo">566</span>  private boolean forceEvict(BlockCacheKey cacheKey) {<a name="line.566"></a>
+<span class="sourceLineNo">567</span>    if (!cacheEnabled) {<a name="line.567"></a>
+<span class="sourceLineNo">568</span>      return false;<a name="line.568"></a>
+<span class="sourceLineNo">569</span>    }<a name="line.569"></a>
+<span class="sourceLineNo">570</span>    RAMQueueEntry removedBlock = checkRamCache(cacheKey);<a name="line.570"></a>
+<span class="sourceLineNo">571</span>    BucketEntry bucketEntry = backingMap.get(cacheKey);<a name="line.571"></a>
+<span class="sourceLineNo">572</span>    if (bucketEntry == null) {<a name="line.572"></a>
+<span class="sourceLineNo">573</span>      if (removedBlock != null) {<a name="line.573"></a>
+<span class="sourceLineNo">574</span>        cacheStats.evicted(0, cacheKey.isPrimary());<a name="line.574"></a>
+<span class="sourceLineNo">575</span>        return true;<a name="line.575"></a>
+<span class="sourceLineNo">576</span>      } else {<a name="line.576"></a>
+<span class="sourceLineNo">577</span>        return false;<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>    ReentrantReadWriteLock lock = offsetLock.getLock(bucketEntry.offset());<a name="line.580"></a>
+<span class="sourceLineNo">581</span>    try {<a name="line.581"></a>
+<span class="sourceLineNo">582</span>      lock.writeLock().lock();<a name="line.582"></a>
+<span class="sourceLineNo">583</span>      if (backingMap.remove(cacheKey, bucketEntry)) {<a name="line.583"></a>
+<span class="sourceLineNo">584</span>        blockEvicted(cacheKey, bucketEntry, removedBlock == null);<a name="line.584"></a>
+<span class="sourceLineNo">585</span>      } else {<a name="line.585"></a>
+<span class="sourceLineNo">586</span>        return false;<a name="line.586"></a>
+<span class="sourceLineNo">587</span>      }<a name="line.587"></a>
+<span class="sourceLineNo">588</span>    } finally {<a name="line.588"></a>
+<span class="sourceLineNo">589</span>      lock.writeLock().unlock();<a name="line.589"></a>
+<span class="sourceLineNo">590</span>    }<a name="line.590"></a>
+<span class="sourceLineNo">591</span>    cacheStats.evicted(bucketEntry.getCachedTime(), cacheKey.isPrimary());<a name="line.591"></a>
+<span class="sourceLineNo">592</span>    return true;<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>  private RAMQueueEntry checkRamCache(BlockCacheKey cacheKey) {<a name="line.595"></a>
+<span class="sourceLineNo">596</span>    RAMQueueEntry removedBlock = ramCache.remove(cacheKey);<a name="line.596"></a>
+<span class="sourceLineNo">597</span>    if (removedBlock != null) {<a name="line.597"></a>
+<span class="sourceLineNo">598</span>      this.blockNumber.decrement();<a name="line.598"></a>
+<span class="sourceLineNo">599</span>      this.heapSize.add(-1 * removedBlock.getData().heapSize());<a name="line.599"></a>
 <span class="sourceLineNo">600</span>    }<a name="line.600"></a>
-<span class="sourceLineNo">601</span>    RAMQueueEntry removedBlock = checkRamCache(cacheKey);<a name="line.601"></a>
-<span class="sourceLineNo">602</span>    BucketEntry bucketEntry = backingMap.get(cacheKey);<a name="line.602"></a>
-<span class="sourceLineNo">603</span>    if (bucketEntry == null) {<a name="line.603"></a>
-<span class="sourceLineNo">604</span>      if (removedBlock != null) {<a name="line.604"></a>
-<span class="sourceLineNo">605</span>        cacheStats.evicted(0, cacheKey.isPrimary());<a name="line.605"></a>
-<span class="sourceLineNo">606</span>        return true;<a name="line.606"></a>
-<span class="sourceLineNo">607</span>      } else {<a name="line.607"></a>
-<span class="sourceLineNo">608</span>        return false;<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>    ReentrantReadWriteLock lock = offsetLock.getLock(bucketEntry.offset());<a name="line.611"></a>
-<span class="sourceLineNo">612</span>    try {<a name="line.612"></a>
-<span class="sourceLineNo">613</span>      lock.writeLock().lock();<a name="line.613"></a>
-<span class="sourceLineNo">614</span>      int refCount = bucketEntry.getRefCount();<a name="line.614"></a>
-<span class="sourceLineNo">615</span>      if (refCount == 0) {<a name="line.615"></a>
-<span class="sourceLineNo">616</span>        if (backingMap.remove(cacheKey, bucketEntry)) {<a name="line.616"></a>
-<span class="sourceLineNo">617</span>          blockEvicted(cacheKey, bucketEntry, removedBlock == null);<a name="line.617"></a>
-<span class="sourceLineNo">618</span>        } else {<a name="line.618"></a>
-<span class="sourceLineNo">619</span>          return false;<a name="line.619"></a>
-<span class="sourceLineNo">620</span>        }<a name="line.620"></a>
-<span class="sourceLineNo">621</span>      } else {<a name="line.621"></a>
-<span class="sourceLineNo">622</span>        if(!deletedBlock) {<a name="line.622"></a>
-<span class="sourceLineNo">623</span>          if (LOG.isDebugEnabled()) {<a name="line.623"></a>
-<span class="sourceLineNo">624</span>            LOG.debug("This block " + cacheKey + " is still referred by " + refCount<a name="line.624"></a>
-<span class="sourceLineNo">625</span>                + " readers. Can not be freed now");<a name="line.625"></a>
-<span class="sourceLineNo">626</span>          }<a name="line.626"></a>
-<span class="sourceLineNo">627</span>          return false;<a name="line.627"></a>
-<span class="sourceLineNo">628</span>        } else {<a name="line.628"></a>
-<span class="sourceLineNo">629</span>          if (LOG.isDebugEnabled()) {<a name="line.629"></a>
-<span class="sourceLineNo">630</span>            LOG.debug("This block " + cacheKey + " is still referred by " + refCount<a name="line.630"></a>
-<span class="sourceLineNo">631</span>                + " readers. Can not be freed now. Hence will mark this"<a name="line.631"></a>
-<span class="sourceLineNo">632</span>                + " for evicting at a later point");<a name="line.632"></a>
+<span class="sourceLineNo">601</span>    return removedBlock;<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>  public boolean evictBlock(BlockCacheKey cacheKey, boolean deletedBlock) {<a name="line.604"></a>
+<span class="sourceLineNo">605</span>    if (!cacheEnabled) {<a name="line.605"></a>
+<span class="sourceLineNo">606</span>      return false;<a name="line.606"></a>
+<span class="sourceLineNo">607</span>    }<a name="line.607"></a>
+<span class="sourceLineNo">608</span>    RAMQueueEntry removedBlock = checkRamCache(cacheKey);<a name="line.608"></a>
+<span class="sourceLineNo">609</span>    BucketEntry bucketEntry = backingMap.get(cacheKey);<a name="line.609"></a>
+<span class="sourceLineNo">610</span>    if (bucketEntry == null) {<a name="line.610"></a>
+<span class="sourceLineNo">611</span>      if (removedBlock != null) {<a name="line.611"></a>
+<span class="sourceLineNo">612</span>        cacheStats.evicted(0, cacheKey.isPrimary());<a name="line.612"></a>
+<span class="sourceLineNo">613</span>        return true;<a name="line.613"></a>
+<span class="sourceLineNo">614</span>      } else {<a name="line.614"></a>
+<span class="sourceLineNo">615</span>        return false;<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>    ReentrantReadWriteLock lock = offsetLock.getLock(bucketEntry.offset());<a name="line.618"></a>
+<span class="sourceLineNo">619</span>    try {<a name="line.619"></a>
+<span class="sourceLineNo">620</span>      lock.writeLock().lock();<a name="line.620"></a>
+<span class="sourceLineNo">621</span>      int refCount = bucketEntry.getRefCount();<a name="line.621"></a>
+<span class="sourceLineNo">622</span>      if (refCount == 0) {<a name="line.622"></a>
+<span class="sourceLineNo">623</span>        if (backingMap.remove(cacheKey, bucketEntry)) {<a name="line.623"></a>
+<span class="sourceLineNo">624</span>          blockEvicted(cacheKey, bucketEntry, removedBlock == null);<a name="line.624"></a>
+<span class="sourceLineNo">625</span>        } else {<a name="line.625"></a>
+<span class="sourceLineNo">626</span>          return false;<a name="line.626"></a>
+<span class="sourceLineNo">627</span>        }<a name="line.627"></a>
+<span class="sourceLineNo">628</span>      } else {<a name="line.628"></a>
+<span class="sourceLineNo">629</span>        if(!deletedBlock) {<a name="line.629"></a>
+<span class="sourceLineNo">630</span>          if (LOG.isDebugEnabled()) {<a name="line.630"></a>
+<span class="sourceLineNo">631</span>            LOG.debug("This block " + cacheKey + " is still referred by " + refCount<a name="line.631"></a>
+<span class="sourceLineNo">632</span>                + " readers. Can not be freed now");<a name="line.632"></a>
 <span class="sourceLineNo">633</span>          }<a name="line.633"></a>
-<span class="sourceLineNo">634</span>          bucketEntry.markForEvict();<a name="line.634"></a>
-<span class="sourceLineNo">635</span>        }<a name="line.635"></a>
-<span class="sourceLineNo">636</span>      }<a name="line.636"></a>
-<span class="sourceLineNo">637</span>    } finally {<a name="line.637"></a>
-<span class="sourceLineNo">638</span>      lock.writeLock().unlock();<a name="line.638"></a>
-<span class="sourceLineNo">639</span>    }<a name="line.639"></a>
-<span class="sourceLineNo">640</span>    cacheStats.evicted(bucketEntry.getCachedTime(), cacheKey.isPrimary());<a name="line.640"></a>
-<span class="sourceLineNo">641</span>    return true;<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>   * Statistics thread.  Periodically output cache statistics to the log.<a name="line.645"></a>
-<span class="sourceLineNo">646</span>   */<a name="line.646"></a>
-<span class="sourceLineNo">647</span>  private static class StatisticsThread extends Thread {<a name="line.647"></a>
-<span class="sourceLineNo">648</span>    private final BucketCache bucketCache;<a name="line.648"></a>
-<span class="sourceLineNo">649</span><a name="line.649"></a>
-<span class="sourceLineNo">650</span>    public StatisticsThread(BucketCache bucketCache) {<a name="line.650"></a>
-<span class="sourceLineNo">651</span>      super("BucketCacheStatsThread");<a name="line.651"></a>
-<span class="sourceLineNo">652</span>      setDaemon(true);<a name="line.652"></a>
-<span class="sourceLineNo">653</span>      this.bucketCache = bucketCache;<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 void run() {<a name="line.657"></a>
-<span class="sourceLineNo">658</span>      bucketCache.logStats();<a name="line.658"></a>
-<span class="sourceLineNo">659</span>    }<a name="line.659"></a>
-<span class="sourceLineNo">660</span>  }<a name="line.660"></a>
-<span class="sourceLineNo">661</span><a name="line.661"></a>
-<span class="sourceLineNo">662</span>  public void logStats() {<a name="line.662"></a>
-<span class="sourceLineNo">663</span>    long totalSize = bucketAllocator.getTotalSize();<a name="line.663"></a>
-<span class="sourceLineNo">664</span>    long usedSize = bucketAllocator.getUsedSize();<a name="line.664"></a>
-<span class="sourceLineNo">665</span>    long freeSize = totalSize - usedSize;<a name="line.665"></a>
-<span class="sourceLineNo">666</span>    long cacheSize = getRealCacheSize();<a name="line.666"></a>
-<span class="sourceLineNo">667</span>    LOG.info("failedBlockAdditions=" + cacheStats.getFailedInserts() + ", " +<a name="line.667"></a>
-<span class="sourceLineNo">668</span>        "totalSize=" + StringUtils.byteDesc(totalSize) + ", " +<a name="line.668"></a>
-<span class="sourceLineNo">669</span>        "freeSize=" + StringUtils.byteDesc(freeSize) + ", " +<a name="line.669"></a>
-<span class="sourceLineNo">670</span>        "usedSize=" + StringUtils.byteDesc(usedSize) +", " +<a name="line.670"></a>
-<span class="sourceLineNo">671</span>        "cacheSize=" + StringUtils.byteDesc(cacheSize) +", " +<a name="line.671"></a>
-<span class="sourceLineNo">672</span>        "accesses=" + cacheStats.getRequestCount() + ", " +<a name="line.672"></a>
-<span class="sourceLineNo">673</span>        "hits=" + cacheStats.getHitCount() + ", " +<a name="line.673"></a>
-<span class="sourceLineNo">674</span>        "IOhitsPerSecond=" + cacheStats.getIOHitsPerSecond() + ", " +<a name="line.674"></a>
-<span class="sourceLineNo">675</span>        "IOTimePerHit=" + String.format("%.2f", cacheStats.getIOTimePerHit())+ ", " +<a name="line.675"></a>
-<span class="sourceLineNo">676</span>        "hitRatio=" + (cacheStats.getHitCount() == 0 ? "0," :<a name="line.676"></a>
-<span class="sourceLineNo">677</span>          (StringUtils.formatPercent(cacheStats.getHitRatio(), 2)+ ", ")) +<a name="line.677"></a>
-<span class="sourceLineNo">678</span>        "cachingAccesses=" + cacheStats.getRequestCachingCount() + ", " +<a name="line.678"></a>
-<span class="sourceLineNo">679</span>        "cachingHits=" + cacheStats.getHitCachingCount() + ", " +<a name="line.679"></a>
-<span class="sourceLineNo">680</span>        "cachingHitsRatio=" +(cacheStats.getHitCachingCount() == 0 ? "0," :<a name="line.680"></a>
-<span class="sourceLineNo">681</span>          (StringUtils.formatPercent(cacheStats.getHitCachingRatio(), 2)+ ", ")) +<a name="line.681"></a>
-<span class="sourceLineNo">682</span>        "evictions=" + cacheStats.getEvictionCount() + ", " +<a name="line.682"></a>
-<span class="sourceLineNo">683</span>        "evicted=" + cacheStats.getEvictedCount() + ", " +<a name="line.683"></a>
-<span class="sourceLineNo">684</span>        "evictedPerRun=" + cacheStats.evictedPerEviction());<a name="line.684"></a>
-<span class="sourceLineNo">685</span>    cacheStats.reset();<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>  public long getRealCacheSize() {<a name="line.688"></a>
-<span class="sourceLineNo">689</span>    return this.realCacheSize.sum();<a name="line.689"></a>
-<span class="sourceLineNo">690</span>  }<a name="line.690"></a>
-<span class="sourceLineNo">691</span><a name="line.691"></a>
-<span class="sourceLineNo">692</span>  private long acceptableSize() {<a name="line.692"></a>
-<span class="sourceLineNo">693</span>    return (long) Math.floor(bucketAllocator.getTotalSize() * acceptableFactor);<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>  @VisibleForTesting<a name="line.696"></a>
-<span class="sourceLineNo">697</span>  long getPartitionSize(float partitionFactor) {<a name="line.697"></a>
-<span class="sourceLineNo">698</span>    return (long) Math.floor(bucketAllocator.getTotalSize() * partitionFactor * minFactor);<a name="line.698"></a>
-<span class="sourceLineNo">699</span>  }<a name="line.699"></a>
-<span class="sourceLineNo">700</span><a name="line.700"></a>
-<span class="sourceLineNo">701</span>  /**<a name="line.701"></a>
-<span class="sourceLineNo">702</span>   * Return the count of bucketSizeinfos still need free space<a name="line.702"></a>
-<span class="sourceLineNo">703</span>   */<a name="line.703"></a>
-<span class="sourceLineNo">704</span>  private int bucketSizesAboveThresholdCount(float minFactor) {<a name="line.704"></a>
-<span class="sourceLineNo">705</span>    BucketAllocator.IndexStatistics[] stats = bucketAllocator.getIndexStatistics();<a name="line.705"></a>
-<span class="sourceLineNo">706</span>    int fullCount = 0;<a name="line.706"></a>
-<span class="sourceLineNo">707</span>    for (int i = 0; i &lt; stats.length; i++) {<a name="line.707"></a>
-<span class="sourceLineNo">708</span>      long freeGoal = (long) Math.floor(stats[i].totalCount() * (1 - minFactor));<a name="line.708"></a>
-<span class="sourceLineNo">709</span>      freeGoal = Math.max(freeGoal, 1);<a name="line.709"></a>
-<span class="sourceLineNo">710</span>      if (stats[i].freeCount() &lt; freeGoal) {<a name="line.710"></a>
-<span class="sourceLineNo">711</span>        fullCount++;<a name="line.711"></a>
-<span class="sourceLineNo">712</span>      }<a name="line.712"></a>
-<span class="sourceLineNo">713</span>    }<a name="line.713"></a>
-<span class="sourceLineNo">714</span>    return fullCount;<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">717</span>  /**<a name="line.717"></a>
-<span class="sourceLineNo">718</span>   * This method will find the buckets that are minimally occupied<a name="line.718"></a>
-<span class="sourceLineNo">719</span>   * and are not reference counted and will free them completely<a name="line.719"></a>
-<span class="sourceLineNo">720</span>   * without any constraint on the access times of the elements,<a name="line.720"></a>
-<span class="sourceLineNo">721</span>   * and as a process will completely free at most the number of buckets<a name="line.721"></a>
-<span class="sourceLineNo">722</span>   * passed, sometimes it might not due to changing refCounts<a name="line.722"></a>
-<span class="sourceLineNo">723</span>   *<a name="line.723"></a>
-<span class="sourceLineNo">724</span>   * @param completelyFreeBucketsNeeded number of buckets to free<a name="line.724"></a>
-<span class="sourceLineNo">725</span>   **/<a name="line.725"></a>
-<span class="sourceLineNo">726</span>  private void freeEntireBuckets(int completelyFreeBucketsNeeded) {<a name="line.726"></a>
-<span class="sourceLineNo">727</span>    if (completelyFreeBucketsNeeded != 0) {<a name="line.727"></a>
-<span class="sourceLineNo">728</span>      // First we will build a set where the offsets are reference counted, usually<a name="line.728"></a>
-<span class="sourceLineNo">729</span>      // this set is small around O(Handler Count) unless something else is wrong<a name="line.729"></a>
-<span class="sourceLineNo">730</span>      Set&lt;Integer&gt; inUseBuckets = new HashSet&lt;Integer&gt;();<a name="line.730"></a>
-<span class="sourceLineNo">731</span>      for (BucketEntry entry : backingMap.values()) {<a name="line.731"></a>
-<span class="sourceLineNo">732</span>        if (entry.getRefCount() != 0) {<a name="line.732"></a>
-<span class="sourceLineNo">733</span>          inUseBuckets.add(bucketAllocator.getBucketIndex(entry.offset()));<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><a name="line.736"></a>
-<span class="sourceLineNo">737</span>      Set&lt;Integer&gt; candidateBuckets = bucketAllocator.getLeastFilledBuckets(<a name="line.737"></a>
-<span class="sourceLineNo">738</span>          inUseBuckets, completelyFreeBucketsNeeded);<a name="line.738"></a>
-<span class="sourceLineNo">739</span>      for (Map.Entry&lt;BlockCacheKey, BucketEntry&gt; entry : backingMap.entrySet()) {<a name="line.739"></a>
-<span class="sourceLineNo">740</span>        if (candidateBuckets.contains(bucketAllocator<a name="line.740"></a>
-<span class="sourceLineNo">741</span>            .getBucketIndex(entry.getValue().offset()))) {<a name="line.741"></a>
-<span class="sourceLineNo">742</span>          evictBlock(entry.getKey(), false);<a name="line.742"></a>
-<span class="sourceLineNo">743</span>        }<a name="line.743"></a>
-<span class="sourceLineNo">744</span>      }<a name="line.744"></a>
-<span class="sourceLineNo">745</span>    }<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>  /**<a name="line.748"></a>
-<span class="sourceLineNo">749</span>   * Free the space if the used size reaches acceptableSize() or one size block<a name="line.749"></a>
-<span class="sourceLineNo">750</span>   * couldn't be allocated. When freeing the space, we use the LRU algorithm and<a name="line.750"></a>
-<span class="sourceLineNo">751</span>   * ensure there must be some blocks evicted<a name="line.751"></a>
-<span class="sourceLineNo">752</span>   * @param why Why we are being called<a name="line.752"></a>
-<span class="sourceLineNo">753</span>   */<a name="line.753"></a>
-<span class="sourceLineNo">754</span>  private void freeSpace(final String why) {<a name="line.754"></a>
-<span class="sourceLineNo">755</span>    // Ensure only one freeSpace progress at a time<a name="line.755"></a>
-<span class="sourceLineNo">756</span>    if (!freeSpaceLock.tryLock()) {<a name="line.756"></a>
-<span class="sourceLineNo">757</span>      return;<a name="line.757"></a>
-<span class="sourceLineNo">758</span>    }<a name="line.758"></a>
-<span class="sourceLineNo">759</span>    try {<a name="line.759"></a>
-<span class="sourceLineNo">760</span>      freeInProgress = true;<a name="line.760"></a>
-<span class="sourceLineNo">761</span>      long bytesToFreeWithoutExtra = 0;<a name="line.761"></a>
-<span class="sourceLineNo">762</span>      // Calculate free byte for each bucketSizeinfo<a name="line.762"></a>
-<span class="sourceLineNo">763</span>      StringBuilder msgBuffer = LOG.isDebugEnabled()? new StringBuilder(): null;<a name="line.763"></a>
-<span class="sourceLineNo">764</span>      BucketAllocator.IndexStatistics[] stats = bucketAllocator.getIndexStatistics();<a name="line.764"></a>
-<span class="sourceLineNo">765</span>      long[] bytesToFreeForBucket = new long[stats.length];<a name="line.765"></a>
-<span class="sourceLineNo">766</span>      for (int i = 0; i &lt; stats.length; i++) {<a name="line.766"></a>
-<span class="sourceLineNo">767</span>        bytesToFreeForBucket[i] = 0;<a name="line.767"></a>
-<span class="sourceLineNo">768</span>        long freeGoal = (long) Math.floor(stats[i].totalCount() * (1 - minFactor));<a name="line.768"></a>
-<span class="sourceLineNo">769</span>        freeGoal = Math.max(freeGoal, 1);<a name="line.769"></a>
-<span class="sourceLineNo">770</span>        if (stats[i].freeCount() &lt; freeGoal) {<a name="line.770"></a>
-<span class="sourceLineNo">771</span>          bytesToFreeForBucket[i] = stats[i].itemSize() * (freeGoal - stats[i].freeCount());<a name="line.771"></a>
-<span class="sourceLineNo">772</span>          bytesToFreeWithoutExtra += bytesToFreeForBucket[i];<a name="line.772"></a>
-<span class="sourceLineNo">773</span>          if (msgBuffer != null) {<a name="line.773"></a>
-<span class="sourceLineNo">774</span>            msgBuffer.append("Free for bucketSize(" + stats[i].itemSize() + ")="<a name="line.774"></a>
-<span class="sourceLineNo">775</span>              + StringUtils.byteDesc(bytesToFreeForBucket[i]) + ", ");<a name="line.775"></a>
-<span class="sourceLineNo">776</span>          }<a name="line.776"></a>
-<span class="sourceLineNo">777</span>        }<a name="line.777"></a>
-<span class="sourceLineNo">778</span>      }<a name="line.778"></a>
-<span class="sourceLineNo">779</span>      if (msgBuffer != null) {<a name="line.779"></a>
-<span class="sourceLineNo">780</span>        msgBuffer.append("Free for total=" + StringUtils.byteDesc(bytesToFreeWithoutExtra) + ", ");<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>      if (bytesToFreeWithoutExtra &lt;= 0) {<a name="line.783"></a>
-<span class="sourceLineNo">784</span>        return;<a name="line.784"></a>
+<span class="sourceLineNo">634</span>          return false;<a name="line.634"></a>
+<span class="sourceLineNo">635</span>        } else {<a name="line.635"></a>
+<span class="sourceLineNo">636</span>          if (LOG.isDebugEnabled()) {<a name="line.636"></a>
+<span class="sourceLineNo">637</span>            LOG.debug("This block " + cacheKey + " is still referred by " + refCount<a name="line.637"></a>
+<span class="sourceLineNo">638</span>                + " readers. Can not be freed now. Hence will mark this"<a name="line.638"></a>
+<span class="sourceLineNo">639</span>                + " for evicting at a later point");<a name="line.639"></a>
+<span class="sourceLineNo">640</span>          }<a name="line.640"></a>
+<span class="sourceLineNo">641</span>          bucketEntry.markForEvict();<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>    } finally {<a name="line.644"></a>
+<span class="sourceLineNo">645</span>      lock.writeLock().unlock();<a name="line.645"></a>
+<span class="sourceLineNo">646</span>    }<a name="line.646"></a>
+<span class="sourceLineNo">647</span>    cacheStats.evicted(bucketEntry.getCachedTime(), cacheKey.isPrimary());<a name="line.647"></a>
+<span class="sourceLineNo">648</span>    return true;<a name="line.648"></a>
+<span class="sourceLineNo">649</span>  }<a name="line.649"></a>
+<span class="sourceLineNo">650</span><a name="line.650"></a>
+<span class="sourceLineNo">651</span>  /*<a name="line.651"></a>
+<span class="sourceLineNo">652</span>   * Statistics thread.  Periodically output cache statistics to the log.<a name="line.652"></a>
+<span class="sourceLineNo">653</span>   */<a name="line.653"></a>
+<span class="sourceLineNo">654</span>  private static class StatisticsThread extends Thread {<a name="line.654"></a>
+<span class="sourceLineNo">655</span>    private final BucketCache bucketCache;<a name="line.655"></a>
+<span class="sourceLineNo">656</span><a name="line.656"></a>
+<span class="sourceLineNo">657</span>    public StatisticsThread(BucketCache bucketCache) {<a name="line.657"></a>
+<span class="sourceLineNo">658</span>      super("BucketCacheStatsThread");<a name="line.658"></a>
+<span class="sourceLineNo">659</span>      setDaemon(true);<a name="line.659"></a>
+<span class="sourceLineNo">660</span>      this.bucketCache = bucketCache;<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>    @Override<a name="line.663"></a>
+<span class="sourceLineNo">664</span>    public void run() {<a name="line.664"></a>
+<span class="sourceLineNo">665</span>      bucketCache.logStats();<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>  public void logStats() {<a name="line.669"></a>
+<span class="sourceLineNo">670</span>    long totalSize = bucketAllocator.getTotalSize();<a name="line.670"></a>
+<span class="sourceLineNo">671</span>    long usedSize = bucketAllocator.getUsedSize();<a name="line.671"></a>
+<span class="sourceLineNo">672</span>    long freeSize = totalSize - usedSize;<a name="line.672"></a>
+<span class="sourceLineNo">673</span>    long cacheSize = getRealCacheSize();<a name="line.673"></a>
+<span class="sourceLineNo">674</span>    LOG.info("failedBlockAdditions=" + cacheStats.getFailedInserts() + ", " +<a name="line.674"></a>
+<span class="sourceLineNo">675</span>        "totalSize=" + StringUtils.byteDesc(totalSize) + ", " +<a name="line.675"></a>
+<span class="sourceLineNo">676</span>        "freeSize=" + StringUtils.byteDesc(freeSize) + ", " +<a name="line.676"></a>
+<span class="sourceLineNo">677</span>        "usedSize=" + StringUtils.byteDesc(usedSize) +", " +<a name="line.677"></a>
+<span class="sourceLineNo">678</span>        "cacheSize=" + StringUtils.byteDesc(cacheSize) +", " +<a name="line.678"></a>
+<span class="sourceLineNo">679</span>        "accesses=" + cacheStats.getRequestCount() + ", " +<a name="line.679"></a>
+<span class="sourceLineNo">680</span>        "hits=" + cacheStats.getHitCount() + ", " +<a name="line.680"></a>
+<span class="sourceLineNo">681</span>        "IOhitsPerSecond=" + cacheStats.getIOHitsPerSecond() + ", " +<a name="line.681"></a>
+<span class="sourceLineNo">682</span>        "IOTimePerHit=" + String.format("%.2f", cacheStats.getIOTimePerHit())+ ", " +<a name="line.682"></a>
+<span class="sourceLineNo">683</span>        "hitRatio=" + (cacheStats.getHitCount() == 0 ? "0," :<a name="line.683"></a>
+<span class="sourceLineNo">684</span>          (StringUtils.formatPercent(cacheStats.getHitRatio(), 2)+ ", ")) +<a name="line.684"></a>
+<span class="sourceLineNo">685</span>        "cachingAccesses=" + cacheStats.getRequestCachingCount() + ", " +<a name="line.685"></a>
+<span class="sourceLineNo">686</span>        "cachingHits=" + cacheStats.getHitCachingCount() + ", " +<a name="line.686"></a>
+<span class="sourceLineNo">687</span>        "cachingHitsRatio=" +(cacheStats.getHitCachingCount() == 0 ? "0," :<a name="line.687"></a>
+<span class="sourceLineNo">688</span>          (StringUtils.formatPercent(cacheStats.getHitCachingRatio(), 2)+ ", ")) +<a name="line.688"></a>
+<span class="sourceLineNo">689</span>        "evictions=" + cacheStats.getEvictionCount() + ", " +<a name="line.689"></a>
+<span class="sourceLineNo">690</span>        "evicted=" + cacheStats.getEvictedCount() + ", " +<a name="line.690"></a>
+<span class="sourceLineNo">691</span>        "evictedPerRun=" + cacheStats.evictedPerEviction());<a name="line.691"></a>
+<span class="sourceLineNo">692</span>    cacheStats.reset();<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>  public long getRealCacheSize() {<a name="line.695"></a>
+<span class="sourceLineNo">696</span>    return this.realCacheSize.sum();<a name="line.696"></a>
+<span class="sourceLineNo">697</span>  }<a name="line.697"></a>
+<span class="sourceLineNo">698</span><a name="line.698"></a>
+<span class="sourceLineNo">699</span>  private long acceptableSize() {<a name="line.699"></a>
+<span class="sourceLineNo">700</span>    return (long) Math.floor(bucketAllocator.getTotalSize() * acceptableFactor);<a name="line.700"></a>
+<span class="sourceLineNo">701</span>  }<a name="line.701"></a>
+<span class="sourceLineNo">702</span><a name="line.702"></a>
+<span class="sourceLineNo">703</span>  @VisibleForTesting<a name="line.703"></a>
+<span class="sourceLineNo">704</span>  long getPartitionSize(float partitionFactor) {<a name="line.704"></a>
+<span class="sourceLineNo">705</span>    return (long) Math.floor(bucketAllocator.getTotalSize() * partitionFactor * minFactor);<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>   * Return the count of bucketSizeinfos still need free space<a name="line.709"></a>
+<span class="sourceLineNo">710</span>   */<a name="line.710"></a>
+<span class="sourceLineNo">711</span>  private int bucketSizesAboveThresholdCount(float minFactor) {<a name="line.711"></a>
+<span class="sourceLineNo">712</span>    BucketAllocator.IndexStatistics[] stats = bucketAllocator.getIndexStatistics();<a name="line.712"></a>
+<span class="sourceLineNo">713</span>    int fullCount = 0;<a name="line.713"></a>
+<span class="sourceLineNo">714</span>    for (int i = 0; i &lt; stats.length; i++) {<a name="line.714"></a>
+<span class="sourceLineNo">715</span>      long freeGoal = (long) Math.floor(stats[i].totalCount() * (1 - minFactor));<a name="line.715"></a>
+<span class="sourceLineNo">716</span>      freeGoal = Math.max(freeGoal, 1);<a name="line.716"></a>
+<span class="sourceLineNo">717</span>      if (stats[i].freeCount() &lt; freeGoal) {<a name="line.717"></a>
+<span class="sourceLineNo">718</span>        fullCount++;<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>
+<span class="sourceLineNo">721</span>    return fullCount;<a name="line.721"></a>
+<span class="sourceLineNo">722</span>  }<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>   * This method will find the buckets that are minimally occupied<a name="line.725"></a>
+<span class="sourceLineNo">726</span>   * and are not reference counted and will free them completely<a name="line.726"></a>
+<span class="sourceLineNo">727</span>   * without any constraint on the access times of the elements,<a name="line.727"></a>
+<span class="sourceLineNo">728</span>   * and as a process will completely free at most the number of buckets<a name="line.728"></a>
+<span class="sourceLineNo">729</span>   * passed, sometimes it might not due to changing refCounts<a name="line.729"></a>
+<span class="sourceLineNo">730</span>   *<a name="line.730"></a>
+<span class="sourceLineNo">731</span>   * @param completelyFreeBucketsNeeded number of buckets to free<a name="line.731"></a>
+<span class="sourceLineNo">732</span>   **/<a name="line.732"></a>
+<span class="sourceLineNo">733</span>  private void freeEntireBuckets(int completelyFreeBucketsNeeded) {<a name="line.733"></a>
+<span class="sourceLineNo">734</span>    if (completelyFreeBucketsNeeded != 0) {<a name="line.734"></a>
+<span class="sourceLineNo">735</span>      // First we will build a set where the offsets are reference counted, usually<a name="line.735"></a>
+<span class="sourceLineNo">736</span>      // this set is small around O(Handler Count) unless something else is wrong<a name="line.736"></a>
+<span class="sourceLineNo">737</span>      Set&lt;Integer&gt; inUseBuckets = new HashSet&lt;Integer&gt;();<a name="line.737"></a>
+<span class="sourceLineNo">738</span>      for (BucketEntry entry : backingMap.values()) {<a name="line.738"></a>
+<span class="sourceLineNo">739</span>        if (entry.getRefCount() != 0) {<a name="line.739"></a>
+<span class="sourceLineNo">740</span>          inUseBuckets.add(bucketAllocator.getBucketIndex(entry.offset()));<a name="line.740"></a>
+<span class="sourceLineNo">741</span>        }<a name="line.741"></a>
+<span class="sourceLineNo">742</span>      }<a name="line.742"></a>
+<span class="sourceLineNo">743</span><a name="line.743"></a>
+<span class="sourceLineNo">744</span>      Set&lt;Integer&gt; candidateBuckets = bucketAllocator.getLeastFilledBuckets(<a name="line.744"></a>
+<span class="sourceLineNo">745</span>          inUseBuckets, completelyFreeBucketsNeeded);<a name="line.745"></a>
+<span class="sourceLineNo">746</span>      for (Map.Entry&lt;BlockCacheKey, BucketEntry&gt; entry : backingMap.entrySet()) {<a name="line.746"></a>
+<span class="sourceLineNo">747</span>        if (candidateBuckets.contains(bucketAllocator<a name="line.747"></a>
+<span class="sourceLineNo">748</span>            .getBucketIndex(entry.getValue().offset()))) {<a name="line.748"></a>
+<span class="sourceLineNo">749</span>          evictBlock(entry.getKey(), false);<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>  }<a name="line.753"></a>
+<span class="sourceLineNo">754</span><a name="line.754"></a>
+<span class="sourceLineNo">755</span>  /**<a name="line.755"></a>
+<span class="sourceLineNo">756</span>   * Free the space if the used size reaches acceptableSize() or one size block<a name="line.756"></a>
+<span class="sourceLineNo">757</span>   * couldn't be allocated. When freeing the space, we use the LRU algorithm and<a name="line.757"></a>
+<span class="sourceLineNo">758</span>   * ensure there must be some blocks evicted<a name="line.758"></a>
+<span class="sourceLineNo">759</span>   * @param why Why we are being called<a name="line.759"></a>
+<span class="sourceLineNo">760</span>   */<a name="line.760"></a>
+<span class="sourceLineNo">761</span>  private void freeSpace(final String why) {<a name="line.761"></a>
+<span class="sourceLineNo">762</span>    // Ensure only one freeSpace progress at a time<a name="line.762"></a>
+<span class="sourceLineNo">763</span>    if (!freeSpaceLock.tryLock()) {<a name="line.763"></a>
+<span class="sourceLineNo">764</span>      return;<a name="line.764"></a>
+<span class="sourceLineNo">765</span>    }<a name="line.765"></a>
+<span class="sourceLineNo">766</span>    try {<a name="line.766"></a>
+<span class="sourceLineNo">767</span>      freeInProgress = true;<a name="line.767"></a>
+<span class="sourceLineNo">768</span>      long bytesToFreeWithoutExtra = 0;<a name="line.768"></a>
+<span class="sourceLineNo">769</span>      // Calculate free byte for each bucketSizeinfo<a name="line.769"></a>
+<span class="sourceLineNo">770</span>      StringBuilder msgBuffer = LOG.isDebugEnabled()? new StringBuilder(): null;<a name="line.770"></a>
+<span class="sourceLineNo">771</span>      BucketAllocator.IndexStatistics[] stats = bucketAllocator.getIndexStatistics();<a name="line.771"></a>
+<span class="sourceLineNo">772</span>      long[] bytesToFreeForBucket = new long[stats.length];<a name="line.772"></a>
+<span class="sourceLineNo">773</span>      for (int i = 0; i &lt; stats.length; i++) {<a name="line.773"></a>
+<span class="sourceLineNo">774</span>        bytesToFreeForBucket[i] = 0;<a name="line.774"></a>
+<span class="sourceLineNo">775</span>        long freeGoal = (long) Math.floor(stats[i].totalCount() * (1 - minFactor));<a name="line.775"></a>
+<span class="sourceLineNo">776</span>        freeGoal = Math.max(freeGoal, 1);<a name="line.776"></a>
+<span class="sourceLineNo">777</span>        if (stats[i].freeCount() &lt; freeGoal) {<a name="line.777"></a>
+<span class="sourceLineNo">778</span>          bytesToFreeForBucket[i] = stats[i].itemSize() * (freeGoal - stats[i].freeCount());<a name="line.778"></a>
+<span class="sourceLineNo">779</span>          bytesToFreeWithoutExtra += bytesToFreeForBucket[i];<a name="line.779"></a>
+<span class="sourceLineNo">780</span>          if (msgBuffer != null) {<a name="line.780"></a>
+<span class="sourceLineNo">781</span>            msgBuffer.append("Free for bucketSize(" + stats[i].itemSize() + ")="<a name="line.781"></a>
+<span class="sourceLineNo">782</span>              + StringUtils.byteDesc(bytesToFreeForBucket[i]) + ", ");<a name="line.782"></a>
+<span class="sourceLineNo">783</span>          }<a name="line.783"></a>
+<span class="sourceLineNo">784</span>        }<a name="line.784"></a>
 <span class="sourceLineNo">785</span>      }<a name="line.785"></a>
-<span class="sourceLineNo">786</span>      long currentSize = bucketAllocator.getUsedSize();<a name="line.786"></a>
-<span class="sourceLineNo">787</span>      long totalSize = bucketAllocator.getTotalSize();<a name="line.787"></a>
-<span class="sourceLineNo">788</span>      if (LOG.isDebugEnabled() &amp;&amp; msgBuffer != null) {<a name="line.788"></a>
-<span class="sourceLineNo">789</span>        LOG.debug("Free started because \"" + why + "\"; " + msgBuffer.toString() +<a name="line.789"></a>
-<span class="sourceLineNo">790</span>          " of current used=" + StringUtils.byteDesc(currentSize) + ", actual cacheSize=" +<a name="line.790"></a>
-<span class="sourceLineNo">791</span>          StringUtils.byteDesc(realCacheSize.sum()) + ", total=" + StringUtils.byteDesc(totalSize));<a name="line.791"></a>
+<span class="sourceLineNo">786</span>      if (msgBuffer != null) {<a name="line.786"></a>
+<span class="sourceLineNo">787</span>        msgBuffer.append("Free for total=" + StringUtils.byteDesc(bytesToFreeWithoutExtra) + ", ");<a name="line.787"></a>
+<span class="sourceLineNo">788</span>      }<a name="line.788"></a>
+<span class="sourceLineNo">789</span><a name="line.789"></a>
+<span class="sourceLineNo">790</span>      if (bytesToFreeWithoutExtra &lt;= 0) {<a name="line.790"></a>
+<span class="sourceLineNo">791</span>        return;<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>
-<span class="sourceLineNo">794</span>      long bytesToFreeWithExtra = (long) Math.floor(bytesToFreeWithoutExtra<a name="line.794"></a>
-<span class="sourceLineNo">795</span>          * (1 + extraFreeFactor));<a name="line.795"></a>
-<span class="sourceLineNo">796</span><a name="line.796"></a>
-<span class="sourceLineNo">797</span>      // Instantiate priority buckets<a name="line.797"></a>
-<span class="sourceLineNo">798</span>      BucketEntryGroup bucketSingle = new BucketEntryGroup(bytesToFreeWithExtra,<a name="line.798"></a>
-<span class="sourceLineNo">799</span>          blockSize, getPartitionSize(singleFactor));<a name="line.799"></a>
-<span class="sourceLineNo">800</span>      BucketEntryGroup bucketMulti = new BucketEntryGroup(bytesToFreeWithExtra,<a name="line.800"></a>
-<span class="sourceLineNo">801</span>          blockSize, getPartitionSize(multiFactor));<a name="line.801"></a>
-<span class="sourceLineNo">802</span>      BucketEntryGroup bucketMemory = new BucketEntryGroup(bytesToFreeWithExtra,<a name="line.802"></a>
-<span class="sourceLineNo">803</span>          blockSize, getPartitionSize(memoryFactor));<a name="line.803"></a>
-<span class="sourceLineNo">804</span><a name="line.804"></a>
-<span class="sourceLineNo">805</span>      // Scan entire map putting bucket entry into appropriate bucket entry<a name="line.805"></a>
-<span class="sourceLineNo">806</span>      // group<a name="line.806"></a>
-<span class="sourceLineNo">807</span>      for (Map.Entry&lt;BlockCacheKey, BucketEntry&gt; bucketEntryWithKey : backingMap.entrySet()) {<a name="line.807"></a>
-<span class="sourceLineNo">808</span>        switch (bucketEntryWithKey.getValue().getPriority()) {<a name="line.808"></a>
-<span class="sourceLineNo">809</span>          case SINGLE: {<a name="line.809"></a>
-<span class="sourceLineNo">810</span>            bucketSingle.add(bucketEntryWithKey);<a name="line.810"></a>
-<span class="sourceLineNo">811</span>            break;<a name="line.811"></a>
-<span class="sourceLineNo">812</span>          }<a name="line.812"></a>
-<span class="sourceLineNo">813</span>          case MULTI: {<a name="line.813"></a>
-<span class="sourceLineNo">814</span>            bucketMulti.add(bucketEntryWithKey);<a name="line.814"></a>
-<span class="sourceLineNo">815</span>            break;<a name="line.815"></a>
-<span class="sourceLineNo">816</span>          }<a name="line.816"></a>
-<span class="sourceLineNo">817</span>          case MEMORY: {<a name="line.817"></a>
-<span class="sourceLineNo">818</span>            bucketMemory.add(bucketEntryWithKey);<a name="line.818"></a>
-<span class="sourceLineNo">819</span>            break;<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><a name="line.823"></a>
-<span class="sourceLineNo">824</span>      PriorityQueue&lt;BucketEntryGroup&gt; bucketQueue = new PriorityQueue&lt;&gt;(3,<a name="line.824"></a>
-<span class="sourceLineNo">825</span>          Comparator.comparingLong(BucketEntryGroup::overflow));<a name="line.825"></a>
-<span class="sourceLineNo">826</span><a name="line.826"></a>
-<span class="sourceLineNo">827</span>      bucketQueue.add(bucketSingle);<a name="line.827"></a>
-<span class="sourceLineNo">828</span>      bucketQueue.add(bucketMulti);<a name="line.828"></a>
-<span class="sourceLineNo">829</span>      bucketQueue.add(bucketMemory);<a name="line.829"></a>
+<span class="sourceLineNo">793</span>      long currentSize = bucketAllocator.getUsedSize();<a name="line.793"></a>
+<span class="sourceLineNo">794</span>      long totalSize = bucketAllocator.getTotalSize();<a name="line.794"></a>
+<span class="sourceLineNo">795</span>      if (LOG.isDebugEnabled() &amp;&amp; msgBuffer != null) {<a name="line.795"></a>
+<span class="sourceLineNo">796</span>        LOG.debug("Free started because \"" + why + "\"; " + msgBuffer.toString() +<a name="line.796"></a>
+<span class="sourceLineNo">797</span>          " of current used=" + StringUtils.byteDesc(currentSize) + ", actual cacheSize=" +<a name="line.797"></a>
+<span class="sourceLineNo">798</span>          StringUtils.byteDesc(realCacheSize.sum()) + ", total=" + StringUtils.byteDesc(totalSize));<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>      long bytesToFreeWithExtra = (long) Math.floor(bytesToFreeWithoutExtra<a name="line.801"></a>
+<span class="sourceLineNo">802</span>          * (1 + extraFreeFactor));<a name="line.802"></a>
+<span class="sourceLineNo">803</span><a name="line.803"></a>
+<span class="sourceLineNo">804</span>      // Instantiate priority buckets<a name="line.804"></a>
+<span class="sourceLineNo">805</span>      BucketEntryGroup bucketSingle = new BucketEntryGroup(bytesToFreeWithExtra,<a name="line.805"></a>
+<span class="sourceLineNo">806</span>          blockSize, getPartitionSize(singleFactor));<a name="line.806"></a>
+<span class="sourceLineNo">807</span>      BucketEntryGroup bucketMulti = new BucketEntryGroup(bytesToFreeWithExtra,<a name="line.807"></a>
+<span class="sourceLineNo">808</span>          blockSize, getPartitionSize(multiFactor));<a name="line.808"></a>
+<span class="sourceLineNo">809</span>      BucketEntryGroup bucketMemory = new BucketEntryGroup(bytesToFreeWithExtra,<a name="line.809"></a>
+<span class="sourceLineNo">810</span>          blockSize, getPartitionSize(memoryFactor));<a name="line.810"></a>
+<span class="sourceLineNo">811</span><a name="line.811"></a>
+<span class="sourceLineNo">812</span>      // Scan entire map putting bucket entry into appropriate bucket entry<a name="line.812"></a>
+<span class="sourceLineNo">813</span>      // group<a name="line.813"></a>
+<span class="sourceLineNo">814</span>      for (Map.Entry&lt;BlockCacheKey, BucketEntry&gt; bucketEntryWithKey : backingMap.entrySet()) {<a name="line.814"></a>
+<span class="sourceLineNo">815</span>        switch (bucketEntryWithKey.getValue().getPriority()) {<a name="line.815"></a>
+<span class="sourceLineNo">816</span>          case SINGLE: {<a name="line.816"></a>
+<span class="sourceLineNo">817</span>            bucketSingle.add(bucketEntryWithKey);<a name="line.817"></a>
+<span class="sourceLineNo">818</span>            break;<a name="line.818"></a>
+<span class="sourceLineNo">819</span>          }<a name="line.819"></a>
+<span class="sourceLineNo">820</span>          case MULTI: {<a name="line.820"></a>
+<span class="sourceLineNo">821</span>            bucketMulti.add(bucketEntryWithKey);<a name="line.821"></a>
+<span class="sourceLineNo">822</span>            break;<a name="line.822"></a>
+<span class="sourceLineNo">823</span>          }<a name="line.823"></a>
+<span class="sourceLineNo">824</span>          case MEMORY: {<a name="line.824"></a>
+<span class="sourceLineNo">825</span>            bucketMemory.add(bucketEntryWithKey);<a name="line.825"></a>
+<span class="sourceLineNo">826</span>            break;<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">830</span><a name="line.830"></a>
-<span class="sourceLineNo">831</span>      int remainingBuckets = 3;<a name="line.831"></a>
-<span class="sourceLineNo">832</span>      long bytesFreed = 0;<a name="line.832"></a>
+<span class="sourceLineNo">831</span>      PriorityQueue&lt;BucketEntryGroup&gt; bucketQueue = new PriorityQueue&lt;&gt;(3,<a name="line.831"></a>
+<span class="sourceLineNo">832</span>          Comparator.comparingLong(BucketEntryGroup::overflow));<a name="line.832"></a>
 <span class="sourceLineNo">833</span><a name="line.833"></a>
-<span class="sourceLineNo">834</span>      BucketEntryGroup bucketGroup;<a name="line.834"></a>
-<span class="sourceLineNo">835</span>      while ((bucketGroup = bucketQueue.poll()) != null) {<a name="line.835"></a>
-<span class="sourceLineNo">836</span>        long overflow = bucketGroup.overflow();<a name="line.836"></a>
-<span class="sourceLineNo">837</span>        if (overflow &gt; 0) {<a name="line.837"></a>
-<span class="sourceLineNo">838</span>          long bucketBytesToFree = Math.min(overflow,<a name="line.838"></a>
-<span class="sourceLineNo">839</span>              (bytesToFreeWithoutExtra - bytesFreed) / remainingBuckets);<a name="line.839"></a>
-<span class="sourceLineNo">840</span>          bytesFreed += bucketGroup.free(bucketBytesToFree);<a name="line.840"></a>
-<span class="sourceLineNo">841</span>        }<a name="line.841"></a>
-<span class="sourceLineNo">842</span>        remainingBuckets--;<a name="line.842"></a>
-<span class="sourceLineNo">843</span>      }<a name="line.843"></a>
-<span class="sourceLineNo">844</span><a name="line.844"></a>
-<span class="sourceLineNo">845</span>      // Check and free if there are buckets that still need freeing of space<a name="line.845"></a>
-<span class="sourceLineNo">846</span>      if (bucketSizesAboveThresholdCount(minFactor) &gt; 0) {<a name="line.846"></a>
-<span class="sourceLineNo">847</span>        bucketQueue.clear();<a name="line.847"></a>
-<span class="sourceLineNo">848</span>        remainingBuckets = 3;<a name="line.848"></a>
-<span class="sourceLineNo">849</span><a name="line.849"></a>
-<span class="sourceLineNo">850</span>        bucketQueue.add(bucketSingle);<a name="line.850"></a>
-<span class="sourceLineNo">851</span>        bucketQueue.add(bucketMulti);<a name="line.851"></a>
-<span class="sourceLineNo">852</span>        bucketQueue.add(bucketMemory);<a name="line.852"></a>
-<span class="sourceLineNo">853</span><a name="line.853"></a>
-<span class="sourceLineNo">854</span>        while ((bucketGroup = bucketQueue.poll()) != null) {<a name="line.854"></a>
-<span class="sourceLineNo">855</span>          long bucketBytesToFree = (bytesToFreeWithExtra - bytesFreed) / remainingBuckets;<a name="line.855"></a>
-<span class="sourceLineNo">856</span>          bytesFreed += bucketGroup.free(bucketBytesToFree);<a name="line.856"></a>
-<span class="sourceLineNo">857</span>          remainingBuckets--;<a name="line.857"></a>
-<span class="sourceLineNo">858</span>        }<a name="line.858"></a>
-<span class="sourceLineNo">859</span>      }<a name="line.859"></a>
+<span class="sourceLineNo">834</span>      bucketQueue.add(bucketSingle);<a name="line.834"></a>
+<span class="sourceLineNo">835</span>      bucketQueue.add(bucketMulti);<a name="line.835"></a>
+<span class="sourceLineNo">836</span>      bucketQueue.add(bucketMemory);<a name="line.836"></a>
+<span class="sourceLineNo">837</span><a name="line.837"></a>
+<span class="sourceLineNo">838</span>      int remainingBuckets = 3;<a name="line.838"></a>
+<span class="sourceLineNo">839</span>      long bytesFreed = 0;<a name="line.839"></a>
+<span class="sourceLineNo">840</span><a name="line.840"></a>
+<span class="sourceLineNo">841</span>      BucketEntryGroup bucketGroup;<a name="line.841"></a>
+<span class="sourceLineNo">842</span>      while ((bucketGroup = bucketQueue.poll()) != null) {<a name="line.842"></a>
+<span class="sourceLineNo">843</span>        long overflow = bucketGroup.overflow();<a name="line.843"></a>
+<span class="sourceLineNo">844</span>        if (overflow &gt; 0) {<a name="line.844"></a>
+<span class="sourceLineNo">845</span>          long bucketBytesToFree = Math.min(overflow,<a name="line.845"></a>
+<span class="sourceLineNo">846</span>              (bytesToFreeWithoutExtra - bytesFreed) / remainingBuckets);<a name="line.846"></a>
+<span class="sourceLineNo">847</span>          bytesFreed += bucketGroup.free(bucketBytesToFree);<a name="line.847"></a>
+<span class="sourceLineNo">848</span>        }<a name="line.848"></a>
+<span class="sourceLineNo">849</span>        remainingBuckets--;<a name="line.849"></a>
+<span class="sourceLineNo">850</span>      }<a name="line.850"></a>
+<span class="sourceLineNo">851</span><a name="line.851"></a>
+<span class="sourceLineNo">852</span>      // Check and free if there are buckets that still need freeing of space<a name="line.852"></a>
+<span class="sourceLineNo">853</span>      if (bucketSizesAboveThresholdCount(minFactor) &gt; 0) {<a name="line.853"></a>
+<span class="sourceLineNo">854</span>        bucketQueue.clear();<a name="line.854"></a>
+<span class="sourceLineNo">855</span>        remainingBuckets = 3;<a name="line.855"></a>
+<span class="sourceLineNo">856</span><a name="line.856"></a>
+<span class="sourceLineNo">857</span>        bucketQueue.add(bucketSingle);<a name="line.857"></a>
+<span class="sourceLineNo">858</span>        bucketQueue.add(bucketMulti);<a name="line.858"></a>
+<span class="sourceLineNo">859</span>        bucketQueue.add(bucketMemory);<a name="line.859"></a>
 <span class="sourceLineNo">860</span><a name="line.860"></a>
-<span class="sourceLineNo">861</span>      // Even after the above free we might still need freeing because of the<a name="line.861"></a>
-<span class="sourceLineNo">862</span>      // De-fragmentation of the buckets (also called Slab Calcification problem), i.e<a name="line.862"></a>
-<span class="sourceLineNo">863</span>      // there might be some buckets where the occupancy is very sparse and thus are not<a name="line.863"></a>
-<span class="sourceLineNo">864</span>      // yielding the free for the other bucket sizes, the fix for this to evict some<a name="line.864"></a>
-<span class="sourceLineNo">865</span>      // of the buckets, we do this by evicting the buckets that are least fulled<a name="line.865"></a>
-<span class="sourceLineNo">866</span>      freeEntireBuckets(DEFAULT_FREE_ENTIRE_BLOCK_FACTOR *<a name="line.866"></a>
-<span class="sourceLineNo">867</span>          bucketSizesAboveThresholdCount(1.0f));<a name="line.867"></a>
-<span class="sourceLineNo">868</span><a name="line.868"></a>
-<span class="sourceLineNo">869</span>      if (LOG.isDebugEnabled()) {<a name="line.869"></a>
-<span class="sourceLineNo">870</span>        long single = bucketSingle.totalSize();<a name="line.870"></a>
-<span class="sourceLineNo">871</span>        long multi = bucketMulti.totalSize();<a name="line.871"></a>
-<span class="sourceLineNo">872</span>        long memory = bucketMemory.totalSize();<a name="line.872"></a>
-<span class="sourceLineNo">873</span>        if (LOG.isDebugEnabled()) {<a name="line.873"></a>
-<span class="sourceLineNo">874</span>          LOG.debug("Bucket cache free space completed; " + "freed="<a name="line.874"></a>
-<span class="sourceLineNo">875</span>            + StringUtils.byteDesc(bytesFreed) + ", " + "total="<a name="line.875"></a>
-<span class="sourceLineNo">876</span>            + StringUtils.byteDesc(totalSize) + ", " + "single="<a name="line.876"></a>
-<span class="sourceLineNo">877</span>            + StringUtils.byteDesc(single) + ", " + "multi="<a name="line.877"></a>
-<span class="sourceLineNo">878</span>            + StringUtils.byteDesc(multi) + ", " + "memory="<a name="line.878"></a>
-<span class="sourceLineNo">879</span>            + StringUtils.byteDesc(memory));<a name="line.879"></a>
-<span class="sourceLineNo">880</span>        }<a name="line.880"></a>
-<span class="sourceLineNo">881</span>      }<a name="line.881"></a>
-<span class="sourceLineNo">882</span><a name="line.882"></a>
-<span class="sourceLineNo">883</span>    } catch (Throwable t) {<a name="line.883"></a>
-<span class="sourceLineNo">884</span>      LOG.warn("Failed freeing space", t);<a name="line.884"></a>
-<span class="sourceLineNo">885</span>    } finally {<a name="line.885"></a>
-<span class="sourceLineNo">886</span>      cacheStats.evict();<a name="line.886"></a>
-<span class="sourceLineNo">887</span>      freeInProgress = false;<a name="line.887"></a>
-<span class="sourceLineNo">888</span>      freeSpaceLock.unlock();<a name="line.888"></a>
-<span class="sourceLineNo">889</span>    }<a name="line.889"></a>
-<span class="sourceLineNo">890</span>  }<a name="line.890"></a>
-<span class="sourceLineNo">891</span><a name="line.891"></a>
-<span class="sourceLineNo">892</span>  // This handles flushing the RAM cache to IOEngine.<a name="line.892"></a>
-<span class="sourceLineNo">893</span>  @VisibleForTesting<a name="line.893"></a>
-<span class="sourceLineNo">894</span>  class WriterThread extends HasThread {<a name="line.894"></a>
-<span class="sourceLineNo">895</span>    private final BlockingQueue&lt;RAMQueueEntry&gt; inputQueue;<a name="line.895"></a>
-<span class="sourceLineNo">896</span>    private volatile boolean writerEnabled = true;<a name="line.896"></a>
-<span class="sourceLineNo">897</span><a name="line.897"></a>
-<span class="sourceLineNo">898</span>    WriterThread(BlockingQueue&lt;RAMQueueEntry&gt; queue) {<a name="line.898"></a>
-<span class="sourceLineNo">899</span>      super("BucketCacheWriterThread");<a name="line.899"></a>
-<span cl

<TRUNCATED>

[23/50] hbase-site git commit: Published site at 26babcf013de696b899d76a3c39434b794440d8d.

Posted by gi...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html
----------------------------------------------------------------------
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html
index e8070ca..8cb24b3 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html
@@ -433,1254 +433,1261 @@
 <span class="sourceLineNo">425</span>      return;<a name="line.425"></a>
 <span class="sourceLineNo">426</span>    }<a name="line.426"></a>
 <span class="sourceLineNo">427</span><a name="line.427"></a>
-<span class="sourceLineNo">428</span>    if (backingMap.containsKey(cacheKey)) {<a name="line.428"></a>
+<span class="sourceLineNo">428</span>    if (backingMap.containsKey(cacheKey) || ramCache.containsKey(cacheKey)) {<a name="line.428"></a>
 <span class="sourceLineNo">429</span>      Cacheable existingBlock = getBlock(cacheKey, false, false, false);<a name="line.429"></a>
-<span class="sourceLineNo">430</span>      try {<a name="line.430"></a>
-<span class="sourceLineNo">431</span>        if (BlockCacheUtil.compareCacheBlock(cachedItem, existingBlock) != 0) {<a name="line.431"></a>
-<span class="sourceLineNo">432</span>          throw new RuntimeException("Cached block contents differ, which should not have happened."<a name="line.432"></a>
-<span class="sourceLineNo">433</span>              + "cacheKey:" + cacheKey);<a name="line.433"></a>
-<span class="sourceLineNo">434</span>        }<a name="line.434"></a>
-<span class="sourceLineNo">435</span>        String msg = "Caching an already cached block: " + cacheKey;<a name="line.435"></a>
-<span class="sourceLineNo">436</span>        msg += ". This is harmless and can happen in rare cases (see HBASE-8547)";<a name="line.436"></a>
-<span class="sourceLineNo">437</span>        LOG.warn(msg);<a name="line.437"></a>
-<span class="sourceLineNo">438</span>      } finally {<a name="line.438"></a>
-<span class="sourceLineNo">439</span>        // return the block since we need to decrement the count<a name="line.439"></a>
-<span class="sourceLineNo">440</span>        returnBlock(cacheKey, existingBlock);<a name="line.440"></a>
-<span class="sourceLineNo">441</span>      }<a name="line.441"></a>
-<span class="sourceLineNo">442</span>      return;<a name="line.442"></a>
-<span class="sourceLineNo">443</span>    }<a name="line.443"></a>
-<span class="sourceLineNo">444</span><a name="line.444"></a>
-<span class="sourceLineNo">445</span>    /*<a name="line.445"></a>
-<span class="sourceLineNo">446</span>     * Stuff the entry into the RAM cache so it can get drained to the persistent store<a name="line.446"></a>
-<span class="sourceLineNo">447</span>     */<a name="line.447"></a>
-<span class="sourceLineNo">448</span>    RAMQueueEntry re =<a name="line.448"></a>
-<span class="sourceLineNo">449</span>        new RAMQueueEntry(cacheKey, cachedItem, accessCount.incrementAndGet(), inMemory);<a name="line.449"></a>
-<span class="sourceLineNo">450</span>    if (ramCache.putIfAbsent(cacheKey, re) != null) {<a name="line.450"></a>
-<span class="sourceLineNo">451</span>      return;<a name="line.451"></a>
-<span class="sourceLineNo">452</span>    }<a name="line.452"></a>
-<span class="sourceLineNo">453</span>    int queueNum = (cacheKey.hashCode() &amp; 0x7FFFFFFF) % writerQueues.size();<a name="line.453"></a>
-<span class="sourceLineNo">454</span>    BlockingQueue&lt;RAMQueueEntry&gt; bq = writerQueues.get(queueNum);<a name="line.454"></a>
-<span class="sourceLineNo">455</span>    boolean successfulAddition = false;<a name="line.455"></a>
-<span class="sourceLineNo">456</span>    if (wait) {<a name="line.456"></a>
-<span class="sourceLineNo">457</span>      try {<a name="line.457"></a>
-<span class="sourceLineNo">458</span>        successfulAddition = bq.offer(re, DEFAULT_CACHE_WAIT_TIME, TimeUnit.MILLISECONDS);<a name="line.458"></a>
-<span class="sourceLineNo">459</span>      } catch (InterruptedException e) {<a name="line.459"></a>
-<span class="sourceLineNo">460</span>        Thread.currentThread().interrupt();<a name="line.460"></a>
-<span class="sourceLineNo">461</span>      }<a name="line.461"></a>
-<span class="sourceLineNo">462</span>    } else {<a name="line.462"></a>
-<span class="sourceLineNo">463</span>      successfulAddition = bq.offer(re);<a name="line.463"></a>
-<span class="sourceLineNo">464</span>    }<a name="line.464"></a>
-<span class="sourceLineNo">465</span>    if (!successfulAddition) {<a name="line.465"></a>
-<span class="sourceLineNo">466</span>      ramCache.remove(cacheKey);<a name="line.466"></a>
-<span class="sourceLineNo">467</span>      cacheStats.failInsert();<a name="line.467"></a>
-<span class="sourceLineNo">468</span>    } else {<a name="line.468"></a>
-<span class="sourceLineNo">469</span>      this.blockNumber.increment();<a name="line.469"></a>
-<span class="sourceLineNo">470</span>      this.heapSize.add(cachedItem.heapSize());<a name="line.470"></a>
-<span class="sourceLineNo">471</span>      blocksByHFile.add(cacheKey);<a name="line.471"></a>
-<span class="sourceLineNo">472</span>    }<a name="line.472"></a>
-<span class="sourceLineNo">473</span>  }<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>   * Get the buffer of the block with the specified key.<a name="line.476"></a>
-<span class="sourceLineNo">477</span>   * @param key block's cache key<a name="line.477"></a>
-<span class="sourceLineNo">478</span>   * @param caching true if the caller caches blocks on cache misses<a name="line.478"></a>
-<span class="sourceLineNo">479</span>   * @param repeat Whether this is a repeat lookup for the same block<a name="line.479"></a>
-<span class="sourceLineNo">480</span>   * @param updateCacheMetrics Whether we should update cache metrics or not<a name="line.480"></a>
-<span class="sourceLineNo">481</span>   * @return buffer of specified cache key, or null if not in cache<a name="line.481"></a>
-<span class="sourceLineNo">482</span>   */<a name="line.482"></a>
-<span class="sourceLineNo">483</span>  @Override<a name="line.483"></a>
-<span class="sourceLineNo">484</span>  public Cacheable getBlock(BlockCacheKey key, boolean caching, boolean repeat,<a name="line.484"></a>
-<span class="sourceLineNo">485</span>      boolean updateCacheMetrics) {<a name="line.485"></a>
-<span class="sourceLineNo">486</span>    if (!cacheEnabled) {<a name="line.486"></a>
-<span class="sourceLineNo">487</span>      return null;<a name="line.487"></a>
-<span class="sourceLineNo">488</span>    }<a name="line.488"></a>
-<span class="sourceLineNo">489</span>    RAMQueueEntry re = ramCache.get(key);<a name="line.489"></a>
-<span class="sourceLineNo">490</span>    if (re != null) {<a name="line.490"></a>
-<span class="sourceLineNo">491</span>      if (updateCacheMetrics) {<a name="line.491"></a>
-<span class="sourceLineNo">492</span>        cacheStats.hit(caching, key.isPrimary(), key.getBlockType());<a name="line.492"></a>
-<span class="sourceLineNo">493</span>      }<a name="line.493"></a>
-<span class="sourceLineNo">494</span>      re.access(accessCount.incrementAndGet());<a name="line.494"></a>
-<span class="sourceLineNo">495</span>      return re.getData();<a name="line.495"></a>
-<span class="sourceLineNo">496</span>    }<a name="line.496"></a>
-<span class="sourceLineNo">497</span>    BucketEntry bucketEntry = backingMap.get(key);<a name="line.497"></a>
-<span class="sourceLineNo">498</span>    if (bucketEntry != null) {<a name="line.498"></a>
-<span class="sourceLineNo">499</span>      long start = System.nanoTime();<a name="line.499"></a>
-<span class="sourceLineNo">500</span>      ReentrantReadWriteLock lock = offsetLock.getLock(bucketEntry.offset());<a name="line.500"></a>
-<span class="sourceLineNo">501</span>      try {<a name="line.501"></a>
-<span class="sourceLineNo">502</span>        lock.readLock().lock();<a name="line.502"></a>
-<span class="sourceLineNo">503</span>        // We can not read here even if backingMap does contain the given key because its offset<a name="line.503"></a>
-<span class="sourceLineNo">504</span>        // maybe changed. If we lock BlockCacheKey instead of offset, then we can only check<a name="line.504"></a>
-<span class="sourceLineNo">505</span>        // existence here.<a name="line.505"></a>
-<span class="sourceLineNo">506</span>        if (bucketEntry.equals(backingMap.get(key))) {<a name="line.506"></a>
-<span class="sourceLineNo">507</span>          // TODO : change this area - should be removed after server cells and<a name="line.507"></a>
-<span class="sourceLineNo">508</span>          // 12295 are available<a name="line.508"></a>
-<span class="sourceLineNo">509</span>          int len = bucketEntry.getLength();<a name="line.509"></a>
-<span class="sourceLineNo">510</span>          if (LOG.isTraceEnabled()) {<a name="line.510"></a>
-<span class="sourceLineNo">511</span>            LOG.trace("Read offset=" + bucketEntry.offset() + ", len=" + len);<a name="line.511"></a>
-<span class="sourceLineNo">512</span>          }<a name="line.512"></a>
-<span class="sourceLineNo">513</span>          Cacheable cachedBlock = ioEngine.read(bucketEntry.offset(), len,<a name="line.513"></a>
-<span class="sourceLineNo">514</span>              bucketEntry.deserializerReference(this.deserialiserMap));<a name="line.514"></a>
-<span class="sourceLineNo">515</span>          long timeTaken = System.nanoTime() - start;<a name="line.515"></a>
-<span class="sourceLineNo">516</span>          if (updateCacheMetrics) {<a name="line.516"></a>
-<span class="sourceLineNo">517</span>            cacheStats.hit(caching, key.isPrimary(), key.getBlockType());<a name="line.517"></a>
-<span class="sourceLineNo">518</span>            cacheStats.ioHit(timeTaken);<a name="line.518"></a>
+<span class="sourceLineNo">430</span><a name="line.430"></a>
+<span class="sourceLineNo">431</span>      try {<a name="line.431"></a>
+<span class="sourceLineNo">432</span>        int comparison = BlockCacheUtil.validateBlockAddition(existingBlock, cachedItem, cacheKey);<a name="line.432"></a>
+<span class="sourceLineNo">433</span>        if (comparison != 0) {<a name="line.433"></a>
+<span class="sourceLineNo">434</span>          if (comparison &lt; 0) {<a name="line.434"></a>
+<span class="sourceLineNo">435</span>            LOG.warn("Cached block contents differ by nextBlockOnDiskSize. Keeping cached block.");<a name="line.435"></a>
+<span class="sourceLineNo">436</span>            return;<a name="line.436"></a>
+<span class="sourceLineNo">437</span>          } else {<a name="line.437"></a>
+<span class="sourceLineNo">438</span>            LOG.warn("Cached block contents differ by nextBlockOnDiskSize. Caching new block.");<a name="line.438"></a>
+<span class="sourceLineNo">439</span>          }<a name="line.439"></a>
+<span class="sourceLineNo">440</span>        } else {<a name="line.440"></a>
+<span class="sourceLineNo">441</span>          String msg = "Caching an already cached block: " + cacheKey;<a name="line.441"></a>
+<span class="sourceLineNo">442</span>          msg += ". This is harmless and can happen in rare cases (see HBASE-8547)";<a name="line.442"></a>
+<span class="sourceLineNo">443</span>          LOG.warn(msg);<a name="line.443"></a>
+<span class="sourceLineNo">444</span>          return;<a name="line.444"></a>
+<span class="sourceLineNo">445</span>        }<a name="line.445"></a>
+<span class="sourceLineNo">446</span>      } finally {<a name="line.446"></a>
+<span class="sourceLineNo">447</span>        // return the block since we need to decrement the count<a name="line.447"></a>
+<span class="sourceLineNo">448</span>        returnBlock(cacheKey, existingBlock);<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><a name="line.451"></a>
+<span class="sourceLineNo">452</span>    /*<a name="line.452"></a>
+<span class="sourceLineNo">453</span>     * Stuff the entry into the RAM cache so it can get drained to the persistent store<a name="line.453"></a>
+<span class="sourceLineNo">454</span>     */<a name="line.454"></a>
+<span class="sourceLineNo">455</span>    RAMQueueEntry re =<a name="line.455"></a>
+<span class="sourceLineNo">456</span>        new RAMQueueEntry(cacheKey, cachedItem, accessCount.incrementAndGet(), inMemory);<a name="line.456"></a>
+<span class="sourceLineNo">457</span>    if (ramCache.putIfAbsent(cacheKey, re) != null) {<a name="line.457"></a>
+<span class="sourceLineNo">458</span>      return;<a name="line.458"></a>
+<span class="sourceLineNo">459</span>    }<a name="line.459"></a>
+<span class="sourceLineNo">460</span>    int queueNum = (cacheKey.hashCode() &amp; 0x7FFFFFFF) % writerQueues.size();<a name="line.460"></a>
+<span class="sourceLineNo">461</span>    BlockingQueue&lt;RAMQueueEntry&gt; bq = writerQueues.get(queueNum);<a name="line.461"></a>
+<span class="sourceLineNo">462</span>    boolean successfulAddition = false;<a name="line.462"></a>
+<span class="sourceLineNo">463</span>    if (wait) {<a name="line.463"></a>
+<span class="sourceLineNo">464</span>      try {<a name="line.464"></a>
+<span class="sourceLineNo">465</span>        successfulAddition = bq.offer(re, DEFAULT_CACHE_WAIT_TIME, TimeUnit.MILLISECONDS);<a name="line.465"></a>
+<span class="sourceLineNo">466</span>      } catch (InterruptedException e) {<a name="line.466"></a>
+<span class="sourceLineNo">467</span>        Thread.currentThread().interrupt();<a name="line.467"></a>
+<span class="sourceLineNo">468</span>      }<a name="line.468"></a>
+<span class="sourceLineNo">469</span>    } else {<a name="line.469"></a>
+<span class="sourceLineNo">470</span>      successfulAddition = bq.offer(re);<a name="line.470"></a>
+<span class="sourceLineNo">471</span>    }<a name="line.471"></a>
+<span class="sourceLineNo">472</span>    if (!successfulAddition) {<a name="line.472"></a>
+<span class="sourceLineNo">473</span>      ramCache.remove(cacheKey);<a name="line.473"></a>
+<span class="sourceLineNo">474</span>      cacheStats.failInsert();<a name="line.474"></a>
+<span class="sourceLineNo">475</span>    } else {<a name="line.475"></a>
+<span class="sourceLineNo">476</span>      this.blockNumber.increment();<a name="line.476"></a>
+<span class="sourceLineNo">477</span>      this.heapSize.add(cachedItem.heapSize());<a name="line.477"></a>
+<span class="sourceLineNo">478</span>      blocksByHFile.add(cacheKey);<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>  /**<a name="line.482"></a>
+<span class="sourceLineNo">483</span>   * Get the buffer of the block with the specified key.<a name="line.483"></a>
+<span class="sourceLineNo">484</span>   * @param key block's cache key<a name="line.484"></a>
+<span class="sourceLineNo">485</span>   * @param caching true if the caller caches blocks on cache misses<a name="line.485"></a>
+<span class="sourceLineNo">486</span>   * @param repeat Whether this is a repeat lookup for the same block<a name="line.486"></a>
+<span class="sourceLineNo">487</span>   * @param updateCacheMetrics Whether we should update cache metrics or not<a name="line.487"></a>
+<span class="sourceLineNo">488</span>   * @return buffer of specified cache key, or null if not in cache<a name="line.488"></a>
+<span class="sourceLineNo">489</span>   */<a name="line.489"></a>
+<span class="sourceLineNo">490</span>  @Override<a name="line.490"></a>
+<span class="sourceLineNo">491</span>  public Cacheable getBlock(BlockCacheKey key, boolean caching, boolean repeat,<a name="line.491"></a>
+<span class="sourceLineNo">492</span>      boolean updateCacheMetrics) {<a name="line.492"></a>
+<span class="sourceLineNo">493</span>    if (!cacheEnabled) {<a name="line.493"></a>
+<span class="sourceLineNo">494</span>      return null;<a name="line.494"></a>
+<span class="sourceLineNo">495</span>    }<a name="line.495"></a>
+<span class="sourceLineNo">496</span>    RAMQueueEntry re = ramCache.get(key);<a name="line.496"></a>
+<span class="sourceLineNo">497</span>    if (re != null) {<a name="line.497"></a>
+<span class="sourceLineNo">498</span>      if (updateCacheMetrics) {<a name="line.498"></a>
+<span class="sourceLineNo">499</span>        cacheStats.hit(caching, key.isPrimary(), key.getBlockType());<a name="line.499"></a>
+<span class="sourceLineNo">500</span>      }<a name="line.500"></a>
+<span class="sourceLineNo">501</span>      re.access(accessCount.incrementAndGet());<a name="line.501"></a>
+<span class="sourceLineNo">502</span>      return re.getData();<a name="line.502"></a>
+<span class="sourceLineNo">503</span>    }<a name="line.503"></a>
+<span class="sourceLineNo">504</span>    BucketEntry bucketEntry = backingMap.get(key);<a name="line.504"></a>
+<span class="sourceLineNo">505</span>    if (bucketEntry != null) {<a name="line.505"></a>
+<span class="sourceLineNo">506</span>      long start = System.nanoTime();<a name="line.506"></a>
+<span class="sourceLineNo">507</span>      ReentrantReadWriteLock lock = offsetLock.getLock(bucketEntry.offset());<a name="line.507"></a>
+<span class="sourceLineNo">508</span>      try {<a name="line.508"></a>
+<span class="sourceLineNo">509</span>        lock.readLock().lock();<a name="line.509"></a>
+<span class="sourceLineNo">510</span>        // We can not read here even if backingMap does contain the given key because its offset<a name="line.510"></a>
+<span class="sourceLineNo">511</span>        // maybe changed. If we lock BlockCacheKey instead of offset, then we can only check<a name="line.511"></a>
+<span class="sourceLineNo">512</span>        // existence here.<a name="line.512"></a>
+<span class="sourceLineNo">513</span>        if (bucketEntry.equals(backingMap.get(key))) {<a name="line.513"></a>
+<span class="sourceLineNo">514</span>          // TODO : change this area - should be removed after server cells and<a name="line.514"></a>
+<span class="sourceLineNo">515</span>          // 12295 are available<a name="line.515"></a>
+<span class="sourceLineNo">516</span>          int len = bucketEntry.getLength();<a name="line.516"></a>
+<span class="sourceLineNo">517</span>          if (LOG.isTraceEnabled()) {<a name="line.517"></a>
+<span class="sourceLineNo">518</span>            LOG.trace("Read offset=" + bucketEntry.offset() + ", len=" + len);<a name="line.518"></a>
 <span class="sourceLineNo">519</span>          }<a name="line.519"></a>
-<span class="sourceLineNo">520</span>          if (cachedBlock.getMemoryType() == MemoryType.SHARED) {<a name="line.520"></a>
-<span class="sourceLineNo">521</span>            bucketEntry.incrementRefCountAndGet();<a name="line.521"></a>
-<span class="sourceLineNo">522</span>          }<a name="line.522"></a>
-<span class="sourceLineNo">523</span>          bucketEntry.access(accessCount.incrementAndGet());<a name="line.523"></a>
-<span class="sourceLineNo">524</span>          if (this.ioErrorStartTime &gt; 0) {<a name="line.524"></a>
-<span class="sourceLineNo">525</span>            ioErrorStartTime = -1;<a name="line.525"></a>
+<span class="sourceLineNo">520</span>          Cacheable cachedBlock = ioEngine.read(bucketEntry.offset(), len,<a name="line.520"></a>
+<span class="sourceLineNo">521</span>              bucketEntry.deserializerReference(this.deserialiserMap));<a name="line.521"></a>
+<span class="sourceLineNo">522</span>          long timeTaken = System.nanoTime() - start;<a name="line.522"></a>
+<span class="sourceLineNo">523</span>          if (updateCacheMetrics) {<a name="line.523"></a>
+<span class="sourceLineNo">524</span>            cacheStats.hit(caching, key.isPrimary(), key.getBlockType());<a name="line.524"></a>
+<span class="sourceLineNo">525</span>            cacheStats.ioHit(timeTaken);<a name="line.525"></a>
 <span class="sourceLineNo">526</span>          }<a name="line.526"></a>
-<span class="sourceLineNo">527</span>          return cachedBlock;<a name="line.527"></a>
-<span class="sourceLineNo">528</span>        }<a name="line.528"></a>
-<span class="sourceLineNo">529</span>      } catch (IOException ioex) {<a name="line.529"></a>
-<span class="sourceLineNo">530</span>        LOG.error("Failed reading block " + key + " from bucket cache", ioex);<a name="line.530"></a>
-<span class="sourceLineNo">531</span>        checkIOErrorIsTolerated();<a name="line.531"></a>
-<span class="sourceLineNo">532</span>      } finally {<a name="line.532"></a>
-<span class="sourceLineNo">533</span>        lock.readLock().unlock();<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>    if (!repeat &amp;&amp; updateCacheMetrics) {<a name="line.536"></a>
-<span class="sourceLineNo">537</span>      cacheStats.miss(caching, key.isPrimary(), key.getBlockType());<a name="line.537"></a>
-<span class="sourceLineNo">538</span>    }<a name="line.538"></a>
-<span class="sourceLineNo">539</span>    return null;<a name="line.539"></a>
-<span class="sourceLineNo">540</span>  }<a name="line.540"></a>
-<span class="sourceLineNo">541</span><a name="line.541"></a>
-<span class="sourceLineNo">542</span>  @VisibleForTesting<a name="line.542"></a>
-<span class="sourceLineNo">543</span>  void blockEvicted(BlockCacheKey cacheKey, BucketEntry bucketEntry, boolean decrementBlockNumber) {<a name="line.543"></a>
-<span class="sourceLineNo">544</span>    bucketAllocator.freeBlock(bucketEntry.offset());<a name="line.544"></a>
-<span class="sourceLineNo">545</span>    realCacheSize.add(-1 * bucketEntry.getLength());<a name="line.545"></a>
-<span class="sourceLineNo">546</span>    blocksByHFile.remove(cacheKey);<a name="line.546"></a>
-<span class="sourceLineNo">547</span>    if (decrementBlockNumber) {<a name="line.547"></a>
-<span class="sourceLineNo">548</span>      this.blockNumber.decrement();<a name="line.548"></a>
-<span class="sourceLineNo">549</span>    }<a name="line.549"></a>
-<span class="sourceLineNo">550</span>  }<a name="line.550"></a>
-<span class="sourceLineNo">551</span><a name="line.551"></a>
-<span class="sourceLineNo">552</span>  @Override<a name="line.552"></a>
-<span class="sourceLineNo">553</span>  public boolean evictBlock(BlockCacheKey cacheKey) {<a name="line.553"></a>
-<span class="sourceLineNo">554</span>    return evictBlock(cacheKey, true);<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>  // does not check for the ref count. Just tries to evict it if found in the<a name="line.557"></a>
-<span class="sourceLineNo">558</span>  // bucket map<a name="line.558"></a>
-<span class="sourceLineNo">559</span>  private boolean forceEvict(BlockCacheKey cacheKey) {<a name="line.559"></a>
-<span class="sourceLineNo">560</span>    if (!cacheEnabled) {<a name="line.560"></a>
-<span class="sourceLineNo">561</span>      return false;<a name="line.561"></a>
-<span class="sourceLineNo">562</span>    }<a name="line.562"></a>
-<span class="sourceLineNo">563</span>    RAMQueueEntry removedBlock = checkRamCache(cacheKey);<a name="line.563"></a>
-<span class="sourceLineNo">564</span>    BucketEntry bucketEntry = backingMap.get(cacheKey);<a name="line.564"></a>
-<span class="sourceLineNo">565</span>    if (bucketEntry == null) {<a name="line.565"></a>
-<span class="sourceLineNo">566</span>      if (removedBlock != null) {<a name="line.566"></a>
-<span class="sourceLineNo">567</span>        cacheStats.evicted(0, cacheKey.isPrimary());<a name="line.567"></a>
-<span class="sourceLineNo">568</span>        return true;<a name="line.568"></a>
-<span class="sourceLineNo">569</span>      } else {<a name="line.569"></a>
-<span class="sourceLineNo">570</span>        return false;<a name="line.570"></a>
-<span class="sourceLineNo">571</span>      }<a name="line.571"></a>
-<span class="sourceLineNo">572</span>    }<a name="line.572"></a>
-<span class="sourceLineNo">573</span>    ReentrantReadWriteLock lock = offsetLock.getLock(bucketEntry.offset());<a name="line.573"></a>
-<span class="sourceLineNo">574</span>    try {<a name="line.574"></a>
-<span class="sourceLineNo">575</span>      lock.writeLock().lock();<a name="line.575"></a>
-<span class="sourceLineNo">576</span>      if (backingMap.remove(cacheKey, bucketEntry)) {<a name="line.576"></a>
-<span class="sourceLineNo">577</span>        blockEvicted(cacheKey, bucketEntry, removedBlock == null);<a name="line.577"></a>
-<span class="sourceLineNo">578</span>      } else {<a name="line.578"></a>
-<span class="sourceLineNo">579</span>        return false;<a name="line.579"></a>
-<span class="sourceLineNo">580</span>      }<a name="line.580"></a>
-<span class="sourceLineNo">581</span>    } finally {<a name="line.581"></a>
-<span class="sourceLineNo">582</span>      lock.writeLock().unlock();<a name="line.582"></a>
-<span class="sourceLineNo">583</span>    }<a name="line.583"></a>
-<span class="sourceLineNo">584</span>    cacheStats.evicted(bucketEntry.getCachedTime(), cacheKey.isPrimary());<a name="line.584"></a>
-<span class="sourceLineNo">585</span>    return true;<a name="line.585"></a>
-<span class="sourceLineNo">586</span>  }<a name="line.586"></a>
-<span class="sourceLineNo">587</span><a name="line.587"></a>
-<span class="sourceLineNo">588</span>  private RAMQueueEntry checkRamCache(BlockCacheKey cacheKey) {<a name="line.588"></a>
-<span class="sourceLineNo">589</span>    RAMQueueEntry removedBlock = ramCache.remove(cacheKey);<a name="line.589"></a>
-<span class="sourceLineNo">590</span>    if (removedBlock != null) {<a name="line.590"></a>
-<span class="sourceLineNo">591</span>      this.blockNumber.decrement();<a name="line.591"></a>
-<span class="sourceLineNo">592</span>      this.heapSize.add(-1 * removedBlock.getData().heapSize());<a name="line.592"></a>
-<span class="sourceLineNo">593</span>    }<a name="line.593"></a>
-<span class="sourceLineNo">594</span>    return removedBlock;<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>  public boolean evictBlock(BlockCacheKey cacheKey, boolean deletedBlock) {<a name="line.597"></a>
-<span class="sourceLineNo">598</span>    if (!cacheEnabled) {<a name="line.598"></a>
-<span class="sourceLineNo">599</span>      return false;<a name="line.599"></a>
+<span class="sourceLineNo">527</span>          if (cachedBlock.getMemoryType() == MemoryType.SHARED) {<a name="line.527"></a>
+<span class="sourceLineNo">528</span>            bucketEntry.incrementRefCountAndGet();<a name="line.528"></a>
+<span class="sourceLineNo">529</span>          }<a name="line.529"></a>
+<span class="sourceLineNo">530</span>          bucketEntry.access(accessCount.incrementAndGet());<a name="line.530"></a>
+<span class="sourceLineNo">531</span>          if (this.ioErrorStartTime &gt; 0) {<a name="line.531"></a>
+<span class="sourceLineNo">532</span>            ioErrorStartTime = -1;<a name="line.532"></a>
+<span class="sourceLineNo">533</span>          }<a name="line.533"></a>
+<span class="sourceLineNo">534</span>          return cachedBlock;<a name="line.534"></a>
+<span class="sourceLineNo">535</span>        }<a name="line.535"></a>
+<span class="sourceLineNo">536</span>      } catch (IOException ioex) {<a name="line.536"></a>
+<span class="sourceLineNo">537</span>        LOG.error("Failed reading block " + key + " from bucket cache", ioex);<a name="line.537"></a>
+<span class="sourceLineNo">538</span>        checkIOErrorIsTolerated();<a name="line.538"></a>
+<span class="sourceLineNo">539</span>      } finally {<a name="line.539"></a>
+<span class="sourceLineNo">540</span>        lock.readLock().unlock();<a name="line.540"></a>
+<span class="sourceLineNo">541</span>      }<a name="line.541"></a>
+<span class="sourceLineNo">542</span>    }<a name="line.542"></a>
+<span class="sourceLineNo">543</span>    if (!repeat &amp;&amp; updateCacheMetrics) {<a name="line.543"></a>
+<span class="sourceLineNo">544</span>      cacheStats.miss(caching, key.isPrimary(), key.getBlockType());<a name="line.544"></a>
+<span class="sourceLineNo">545</span>    }<a name="line.545"></a>
+<span class="sourceLineNo">546</span>    return null;<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>  @VisibleForTesting<a name="line.549"></a>
+<span class="sourceLineNo">550</span>  void blockEvicted(BlockCacheKey cacheKey, BucketEntry bucketEntry, boolean decrementBlockNumber) {<a name="line.550"></a>
+<span class="sourceLineNo">551</span>    bucketAllocator.freeBlock(bucketEntry.offset());<a name="line.551"></a>
+<span class="sourceLineNo">552</span>    realCacheSize.add(-1 * bucketEntry.getLength());<a name="line.552"></a>
+<span class="sourceLineNo">553</span>    blocksByHFile.remove(cacheKey);<a name="line.553"></a>
+<span class="sourceLineNo">554</span>    if (decrementBlockNumber) {<a name="line.554"></a>
+<span class="sourceLineNo">555</span>      this.blockNumber.decrement();<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>  @Override<a name="line.559"></a>
+<span class="sourceLineNo">560</span>  public boolean evictBlock(BlockCacheKey cacheKey) {<a name="line.560"></a>
+<span class="sourceLineNo">561</span>    return evictBlock(cacheKey, true);<a name="line.561"></a>
+<span class="sourceLineNo">562</span>  }<a name="line.562"></a>
+<span class="sourceLineNo">563</span><a name="line.563"></a>
+<span class="sourceLineNo">564</span>  // does not check for the ref count. Just tries to evict it if found in the<a name="line.564"></a>
+<span class="sourceLineNo">565</span>  // bucket map<a name="line.565"></a>
+<span class="sourceLineNo">566</span>  private boolean forceEvict(BlockCacheKey cacheKey) {<a name="line.566"></a>
+<span class="sourceLineNo">567</span>    if (!cacheEnabled) {<a name="line.567"></a>
+<span class="sourceLineNo">568</span>      return false;<a name="line.568"></a>
+<span class="sourceLineNo">569</span>    }<a name="line.569"></a>
+<span class="sourceLineNo">570</span>    RAMQueueEntry removedBlock = checkRamCache(cacheKey);<a name="line.570"></a>
+<span class="sourceLineNo">571</span>    BucketEntry bucketEntry = backingMap.get(cacheKey);<a name="line.571"></a>
+<span class="sourceLineNo">572</span>    if (bucketEntry == null) {<a name="line.572"></a>
+<span class="sourceLineNo">573</span>      if (removedBlock != null) {<a name="line.573"></a>
+<span class="sourceLineNo">574</span>        cacheStats.evicted(0, cacheKey.isPrimary());<a name="line.574"></a>
+<span class="sourceLineNo">575</span>        return true;<a name="line.575"></a>
+<span class="sourceLineNo">576</span>      } else {<a name="line.576"></a>
+<span class="sourceLineNo">577</span>        return false;<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>    ReentrantReadWriteLock lock = offsetLock.getLock(bucketEntry.offset());<a name="line.580"></a>
+<span class="sourceLineNo">581</span>    try {<a name="line.581"></a>
+<span class="sourceLineNo">582</span>      lock.writeLock().lock();<a name="line.582"></a>
+<span class="sourceLineNo">583</span>      if (backingMap.remove(cacheKey, bucketEntry)) {<a name="line.583"></a>
+<span class="sourceLineNo">584</span>        blockEvicted(cacheKey, bucketEntry, removedBlock == null);<a name="line.584"></a>
+<span class="sourceLineNo">585</span>      } else {<a name="line.585"></a>
+<span class="sourceLineNo">586</span>        return false;<a name="line.586"></a>
+<span class="sourceLineNo">587</span>      }<a name="line.587"></a>
+<span class="sourceLineNo">588</span>    } finally {<a name="line.588"></a>
+<span class="sourceLineNo">589</span>      lock.writeLock().unlock();<a name="line.589"></a>
+<span class="sourceLineNo">590</span>    }<a name="line.590"></a>
+<span class="sourceLineNo">591</span>    cacheStats.evicted(bucketEntry.getCachedTime(), cacheKey.isPrimary());<a name="line.591"></a>
+<span class="sourceLineNo">592</span>    return true;<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>  private RAMQueueEntry checkRamCache(BlockCacheKey cacheKey) {<a name="line.595"></a>
+<span class="sourceLineNo">596</span>    RAMQueueEntry removedBlock = ramCache.remove(cacheKey);<a name="line.596"></a>
+<span class="sourceLineNo">597</span>    if (removedBlock != null) {<a name="line.597"></a>
+<span class="sourceLineNo">598</span>      this.blockNumber.decrement();<a name="line.598"></a>
+<span class="sourceLineNo">599</span>      this.heapSize.add(-1 * removedBlock.getData().heapSize());<a name="line.599"></a>
 <span class="sourceLineNo">600</span>    }<a name="line.600"></a>
-<span class="sourceLineNo">601</span>    RAMQueueEntry removedBlock = checkRamCache(cacheKey);<a name="line.601"></a>
-<span class="sourceLineNo">602</span>    BucketEntry bucketEntry = backingMap.get(cacheKey);<a name="line.602"></a>
-<span class="sourceLineNo">603</span>    if (bucketEntry == null) {<a name="line.603"></a>
-<span class="sourceLineNo">604</span>      if (removedBlock != null) {<a name="line.604"></a>
-<span class="sourceLineNo">605</span>        cacheStats.evicted(0, cacheKey.isPrimary());<a name="line.605"></a>
-<span class="sourceLineNo">606</span>        return true;<a name="line.606"></a>
-<span class="sourceLineNo">607</span>      } else {<a name="line.607"></a>
-<span class="sourceLineNo">608</span>        return false;<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>    ReentrantReadWriteLock lock = offsetLock.getLock(bucketEntry.offset());<a name="line.611"></a>
-<span class="sourceLineNo">612</span>    try {<a name="line.612"></a>
-<span class="sourceLineNo">613</span>      lock.writeLock().lock();<a name="line.613"></a>
-<span class="sourceLineNo">614</span>      int refCount = bucketEntry.getRefCount();<a name="line.614"></a>
-<span class="sourceLineNo">615</span>      if (refCount == 0) {<a name="line.615"></a>
-<span class="sourceLineNo">616</span>        if (backingMap.remove(cacheKey, bucketEntry)) {<a name="line.616"></a>
-<span class="sourceLineNo">617</span>          blockEvicted(cacheKey, bucketEntry, removedBlock == null);<a name="line.617"></a>
-<span class="sourceLineNo">618</span>        } else {<a name="line.618"></a>
-<span class="sourceLineNo">619</span>          return false;<a name="line.619"></a>
-<span class="sourceLineNo">620</span>        }<a name="line.620"></a>
-<span class="sourceLineNo">621</span>      } else {<a name="line.621"></a>
-<span class="sourceLineNo">622</span>        if(!deletedBlock) {<a name="line.622"></a>
-<span class="sourceLineNo">623</span>          if (LOG.isDebugEnabled()) {<a name="line.623"></a>
-<span class="sourceLineNo">624</span>            LOG.debug("This block " + cacheKey + " is still referred by " + refCount<a name="line.624"></a>
-<span class="sourceLineNo">625</span>                + " readers. Can not be freed now");<a name="line.625"></a>
-<span class="sourceLineNo">626</span>          }<a name="line.626"></a>
-<span class="sourceLineNo">627</span>          return false;<a name="line.627"></a>
-<span class="sourceLineNo">628</span>        } else {<a name="line.628"></a>
-<span class="sourceLineNo">629</span>          if (LOG.isDebugEnabled()) {<a name="line.629"></a>
-<span class="sourceLineNo">630</span>            LOG.debug("This block " + cacheKey + " is still referred by " + refCount<a name="line.630"></a>
-<span class="sourceLineNo">631</span>                + " readers. Can not be freed now. Hence will mark this"<a name="line.631"></a>
-<span class="sourceLineNo">632</span>                + " for evicting at a later point");<a name="line.632"></a>
+<span class="sourceLineNo">601</span>    return removedBlock;<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>  public boolean evictBlock(BlockCacheKey cacheKey, boolean deletedBlock) {<a name="line.604"></a>
+<span class="sourceLineNo">605</span>    if (!cacheEnabled) {<a name="line.605"></a>
+<span class="sourceLineNo">606</span>      return false;<a name="line.606"></a>
+<span class="sourceLineNo">607</span>    }<a name="line.607"></a>
+<span class="sourceLineNo">608</span>    RAMQueueEntry removedBlock = checkRamCache(cacheKey);<a name="line.608"></a>
+<span class="sourceLineNo">609</span>    BucketEntry bucketEntry = backingMap.get(cacheKey);<a name="line.609"></a>
+<span class="sourceLineNo">610</span>    if (bucketEntry == null) {<a name="line.610"></a>
+<span class="sourceLineNo">611</span>      if (removedBlock != null) {<a name="line.611"></a>
+<span class="sourceLineNo">612</span>        cacheStats.evicted(0, cacheKey.isPrimary());<a name="line.612"></a>
+<span class="sourceLineNo">613</span>        return true;<a name="line.613"></a>
+<span class="sourceLineNo">614</span>      } else {<a name="line.614"></a>
+<span class="sourceLineNo">615</span>        return false;<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>    ReentrantReadWriteLock lock = offsetLock.getLock(bucketEntry.offset());<a name="line.618"></a>
+<span class="sourceLineNo">619</span>    try {<a name="line.619"></a>
+<span class="sourceLineNo">620</span>      lock.writeLock().lock();<a name="line.620"></a>
+<span class="sourceLineNo">621</span>      int refCount = bucketEntry.getRefCount();<a name="line.621"></a>
+<span class="sourceLineNo">622</span>      if (refCount == 0) {<a name="line.622"></a>
+<span class="sourceLineNo">623</span>        if (backingMap.remove(cacheKey, bucketEntry)) {<a name="line.623"></a>
+<span class="sourceLineNo">624</span>          blockEvicted(cacheKey, bucketEntry, removedBlock == null);<a name="line.624"></a>
+<span class="sourceLineNo">625</span>        } else {<a name="line.625"></a>
+<span class="sourceLineNo">626</span>          return false;<a name="line.626"></a>
+<span class="sourceLineNo">627</span>        }<a name="line.627"></a>
+<span class="sourceLineNo">628</span>      } else {<a name="line.628"></a>
+<span class="sourceLineNo">629</span>        if(!deletedBlock) {<a name="line.629"></a>
+<span class="sourceLineNo">630</span>          if (LOG.isDebugEnabled()) {<a name="line.630"></a>
+<span class="sourceLineNo">631</span>            LOG.debug("This block " + cacheKey + " is still referred by " + refCount<a name="line.631"></a>
+<span class="sourceLineNo">632</span>                + " readers. Can not be freed now");<a name="line.632"></a>
 <span class="sourceLineNo">633</span>          }<a name="line.633"></a>
-<span class="sourceLineNo">634</span>          bucketEntry.markForEvict();<a name="line.634"></a>
-<span class="sourceLineNo">635</span>        }<a name="line.635"></a>
-<span class="sourceLineNo">636</span>      }<a name="line.636"></a>
-<span class="sourceLineNo">637</span>    } finally {<a name="line.637"></a>
-<span class="sourceLineNo">638</span>      lock.writeLock().unlock();<a name="line.638"></a>
-<span class="sourceLineNo">639</span>    }<a name="line.639"></a>
-<span class="sourceLineNo">640</span>    cacheStats.evicted(bucketEntry.getCachedTime(), cacheKey.isPrimary());<a name="line.640"></a>
-<span class="sourceLineNo">641</span>    return true;<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>   * Statistics thread.  Periodically output cache statistics to the log.<a name="line.645"></a>
-<span class="sourceLineNo">646</span>   */<a name="line.646"></a>
-<span class="sourceLineNo">647</span>  private static class StatisticsThread extends Thread {<a name="line.647"></a>
-<span class="sourceLineNo">648</span>    private final BucketCache bucketCache;<a name="line.648"></a>
-<span class="sourceLineNo">649</span><a name="line.649"></a>
-<span class="sourceLineNo">650</span>    public StatisticsThread(BucketCache bucketCache) {<a name="line.650"></a>
-<span class="sourceLineNo">651</span>      super("BucketCacheStatsThread");<a name="line.651"></a>
-<span class="sourceLineNo">652</span>      setDaemon(true);<a name="line.652"></a>
-<span class="sourceLineNo">653</span>      this.bucketCache = bucketCache;<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 void run() {<a name="line.657"></a>
-<span class="sourceLineNo">658</span>      bucketCache.logStats();<a name="line.658"></a>
-<span class="sourceLineNo">659</span>    }<a name="line.659"></a>
-<span class="sourceLineNo">660</span>  }<a name="line.660"></a>
-<span class="sourceLineNo">661</span><a name="line.661"></a>
-<span class="sourceLineNo">662</span>  public void logStats() {<a name="line.662"></a>
-<span class="sourceLineNo">663</span>    long totalSize = bucketAllocator.getTotalSize();<a name="line.663"></a>
-<span class="sourceLineNo">664</span>    long usedSize = bucketAllocator.getUsedSize();<a name="line.664"></a>
-<span class="sourceLineNo">665</span>    long freeSize = totalSize - usedSize;<a name="line.665"></a>
-<span class="sourceLineNo">666</span>    long cacheSize = getRealCacheSize();<a name="line.666"></a>
-<span class="sourceLineNo">667</span>    LOG.info("failedBlockAdditions=" + cacheStats.getFailedInserts() + ", " +<a name="line.667"></a>
-<span class="sourceLineNo">668</span>        "totalSize=" + StringUtils.byteDesc(totalSize) + ", " +<a name="line.668"></a>
-<span class="sourceLineNo">669</span>        "freeSize=" + StringUtils.byteDesc(freeSize) + ", " +<a name="line.669"></a>
-<span class="sourceLineNo">670</span>        "usedSize=" + StringUtils.byteDesc(usedSize) +", " +<a name="line.670"></a>
-<span class="sourceLineNo">671</span>        "cacheSize=" + StringUtils.byteDesc(cacheSize) +", " +<a name="line.671"></a>
-<span class="sourceLineNo">672</span>        "accesses=" + cacheStats.getRequestCount() + ", " +<a name="line.672"></a>
-<span class="sourceLineNo">673</span>        "hits=" + cacheStats.getHitCount() + ", " +<a name="line.673"></a>
-<span class="sourceLineNo">674</span>        "IOhitsPerSecond=" + cacheStats.getIOHitsPerSecond() + ", " +<a name="line.674"></a>
-<span class="sourceLineNo">675</span>        "IOTimePerHit=" + String.format("%.2f", cacheStats.getIOTimePerHit())+ ", " +<a name="line.675"></a>
-<span class="sourceLineNo">676</span>        "hitRatio=" + (cacheStats.getHitCount() == 0 ? "0," :<a name="line.676"></a>
-<span class="sourceLineNo">677</span>          (StringUtils.formatPercent(cacheStats.getHitRatio(), 2)+ ", ")) +<a name="line.677"></a>
-<span class="sourceLineNo">678</span>        "cachingAccesses=" + cacheStats.getRequestCachingCount() + ", " +<a name="line.678"></a>
-<span class="sourceLineNo">679</span>        "cachingHits=" + cacheStats.getHitCachingCount() + ", " +<a name="line.679"></a>
-<span class="sourceLineNo">680</span>        "cachingHitsRatio=" +(cacheStats.getHitCachingCount() == 0 ? "0," :<a name="line.680"></a>
-<span class="sourceLineNo">681</span>          (StringUtils.formatPercent(cacheStats.getHitCachingRatio(), 2)+ ", ")) +<a name="line.681"></a>
-<span class="sourceLineNo">682</span>        "evictions=" + cacheStats.getEvictionCount() + ", " +<a name="line.682"></a>
-<span class="sourceLineNo">683</span>        "evicted=" + cacheStats.getEvictedCount() + ", " +<a name="line.683"></a>
-<span class="sourceLineNo">684</span>        "evictedPerRun=" + cacheStats.evictedPerEviction());<a name="line.684"></a>
-<span class="sourceLineNo">685</span>    cacheStats.reset();<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>  public long getRealCacheSize() {<a name="line.688"></a>
-<span class="sourceLineNo">689</span>    return this.realCacheSize.sum();<a name="line.689"></a>
-<span class="sourceLineNo">690</span>  }<a name="line.690"></a>
-<span class="sourceLineNo">691</span><a name="line.691"></a>
-<span class="sourceLineNo">692</span>  private long acceptableSize() {<a name="line.692"></a>
-<span class="sourceLineNo">693</span>    return (long) Math.floor(bucketAllocator.getTotalSize() * acceptableFactor);<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>  @VisibleForTesting<a name="line.696"></a>
-<span class="sourceLineNo">697</span>  long getPartitionSize(float partitionFactor) {<a name="line.697"></a>
-<span class="sourceLineNo">698</span>    return (long) Math.floor(bucketAllocator.getTotalSize() * partitionFactor * minFactor);<a name="line.698"></a>
-<span class="sourceLineNo">699</span>  }<a name="line.699"></a>
-<span class="sourceLineNo">700</span><a name="line.700"></a>
-<span class="sourceLineNo">701</span>  /**<a name="line.701"></a>
-<span class="sourceLineNo">702</span>   * Return the count of bucketSizeinfos still need free space<a name="line.702"></a>
-<span class="sourceLineNo">703</span>   */<a name="line.703"></a>
-<span class="sourceLineNo">704</span>  private int bucketSizesAboveThresholdCount(float minFactor) {<a name="line.704"></a>
-<span class="sourceLineNo">705</span>    BucketAllocator.IndexStatistics[] stats = bucketAllocator.getIndexStatistics();<a name="line.705"></a>
-<span class="sourceLineNo">706</span>    int fullCount = 0;<a name="line.706"></a>
-<span class="sourceLineNo">707</span>    for (int i = 0; i &lt; stats.length; i++) {<a name="line.707"></a>
-<span class="sourceLineNo">708</span>      long freeGoal = (long) Math.floor(stats[i].totalCount() * (1 - minFactor));<a name="line.708"></a>
-<span class="sourceLineNo">709</span>      freeGoal = Math.max(freeGoal, 1);<a name="line.709"></a>
-<span class="sourceLineNo">710</span>      if (stats[i].freeCount() &lt; freeGoal) {<a name="line.710"></a>
-<span class="sourceLineNo">711</span>        fullCount++;<a name="line.711"></a>
-<span class="sourceLineNo">712</span>      }<a name="line.712"></a>
-<span class="sourceLineNo">713</span>    }<a name="line.713"></a>
-<span class="sourceLineNo">714</span>    return fullCount;<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">717</span>  /**<a name="line.717"></a>
-<span class="sourceLineNo">718</span>   * This method will find the buckets that are minimally occupied<a name="line.718"></a>
-<span class="sourceLineNo">719</span>   * and are not reference counted and will free them completely<a name="line.719"></a>
-<span class="sourceLineNo">720</span>   * without any constraint on the access times of the elements,<a name="line.720"></a>
-<span class="sourceLineNo">721</span>   * and as a process will completely free at most the number of buckets<a name="line.721"></a>
-<span class="sourceLineNo">722</span>   * passed, sometimes it might not due to changing refCounts<a name="line.722"></a>
-<span class="sourceLineNo">723</span>   *<a name="line.723"></a>
-<span class="sourceLineNo">724</span>   * @param completelyFreeBucketsNeeded number of buckets to free<a name="line.724"></a>
-<span class="sourceLineNo">725</span>   **/<a name="line.725"></a>
-<span class="sourceLineNo">726</span>  private void freeEntireBuckets(int completelyFreeBucketsNeeded) {<a name="line.726"></a>
-<span class="sourceLineNo">727</span>    if (completelyFreeBucketsNeeded != 0) {<a name="line.727"></a>
-<span class="sourceLineNo">728</span>      // First we will build a set where the offsets are reference counted, usually<a name="line.728"></a>
-<span class="sourceLineNo">729</span>      // this set is small around O(Handler Count) unless something else is wrong<a name="line.729"></a>
-<span class="sourceLineNo">730</span>      Set&lt;Integer&gt; inUseBuckets = new HashSet&lt;Integer&gt;();<a name="line.730"></a>
-<span class="sourceLineNo">731</span>      for (BucketEntry entry : backingMap.values()) {<a name="line.731"></a>
-<span class="sourceLineNo">732</span>        if (entry.getRefCount() != 0) {<a name="line.732"></a>
-<span class="sourceLineNo">733</span>          inUseBuckets.add(bucketAllocator.getBucketIndex(entry.offset()));<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><a name="line.736"></a>
-<span class="sourceLineNo">737</span>      Set&lt;Integer&gt; candidateBuckets = bucketAllocator.getLeastFilledBuckets(<a name="line.737"></a>
-<span class="sourceLineNo">738</span>          inUseBuckets, completelyFreeBucketsNeeded);<a name="line.738"></a>
-<span class="sourceLineNo">739</span>      for (Map.Entry&lt;BlockCacheKey, BucketEntry&gt; entry : backingMap.entrySet()) {<a name="line.739"></a>
-<span class="sourceLineNo">740</span>        if (candidateBuckets.contains(bucketAllocator<a name="line.740"></a>
-<span class="sourceLineNo">741</span>            .getBucketIndex(entry.getValue().offset()))) {<a name="line.741"></a>
-<span class="sourceLineNo">742</span>          evictBlock(entry.getKey(), false);<a name="line.742"></a>
-<span class="sourceLineNo">743</span>        }<a name="line.743"></a>
-<span class="sourceLineNo">744</span>      }<a name="line.744"></a>
-<span class="sourceLineNo">745</span>    }<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>  /**<a name="line.748"></a>
-<span class="sourceLineNo">749</span>   * Free the space if the used size reaches acceptableSize() or one size block<a name="line.749"></a>
-<span class="sourceLineNo">750</span>   * couldn't be allocated. When freeing the space, we use the LRU algorithm and<a name="line.750"></a>
-<span class="sourceLineNo">751</span>   * ensure there must be some blocks evicted<a name="line.751"></a>
-<span class="sourceLineNo">752</span>   * @param why Why we are being called<a name="line.752"></a>
-<span class="sourceLineNo">753</span>   */<a name="line.753"></a>
-<span class="sourceLineNo">754</span>  private void freeSpace(final String why) {<a name="line.754"></a>
-<span class="sourceLineNo">755</span>    // Ensure only one freeSpace progress at a time<a name="line.755"></a>
-<span class="sourceLineNo">756</span>    if (!freeSpaceLock.tryLock()) {<a name="line.756"></a>
-<span class="sourceLineNo">757</span>      return;<a name="line.757"></a>
-<span class="sourceLineNo">758</span>    }<a name="line.758"></a>
-<span class="sourceLineNo">759</span>    try {<a name="line.759"></a>
-<span class="sourceLineNo">760</span>      freeInProgress = true;<a name="line.760"></a>
-<span class="sourceLineNo">761</span>      long bytesToFreeWithoutExtra = 0;<a name="line.761"></a>
-<span class="sourceLineNo">762</span>      // Calculate free byte for each bucketSizeinfo<a name="line.762"></a>
-<span class="sourceLineNo">763</span>      StringBuilder msgBuffer = LOG.isDebugEnabled()? new StringBuilder(): null;<a name="line.763"></a>
-<span class="sourceLineNo">764</span>      BucketAllocator.IndexStatistics[] stats = bucketAllocator.getIndexStatistics();<a name="line.764"></a>
-<span class="sourceLineNo">765</span>      long[] bytesToFreeForBucket = new long[stats.length];<a name="line.765"></a>
-<span class="sourceLineNo">766</span>      for (int i = 0; i &lt; stats.length; i++) {<a name="line.766"></a>
-<span class="sourceLineNo">767</span>        bytesToFreeForBucket[i] = 0;<a name="line.767"></a>
-<span class="sourceLineNo">768</span>        long freeGoal = (long) Math.floor(stats[i].totalCount() * (1 - minFactor));<a name="line.768"></a>
-<span class="sourceLineNo">769</span>        freeGoal = Math.max(freeGoal, 1);<a name="line.769"></a>
-<span class="sourceLineNo">770</span>        if (stats[i].freeCount() &lt; freeGoal) {<a name="line.770"></a>
-<span class="sourceLineNo">771</span>          bytesToFreeForBucket[i] = stats[i].itemSize() * (freeGoal - stats[i].freeCount());<a name="line.771"></a>
-<span class="sourceLineNo">772</span>          bytesToFreeWithoutExtra += bytesToFreeForBucket[i];<a name="line.772"></a>
-<span class="sourceLineNo">773</span>          if (msgBuffer != null) {<a name="line.773"></a>
-<span class="sourceLineNo">774</span>            msgBuffer.append("Free for bucketSize(" + stats[i].itemSize() + ")="<a name="line.774"></a>
-<span class="sourceLineNo">775</span>              + StringUtils.byteDesc(bytesToFreeForBucket[i]) + ", ");<a name="line.775"></a>
-<span class="sourceLineNo">776</span>          }<a name="line.776"></a>
-<span class="sourceLineNo">777</span>        }<a name="line.777"></a>
-<span class="sourceLineNo">778</span>      }<a name="line.778"></a>
-<span class="sourceLineNo">779</span>      if (msgBuffer != null) {<a name="line.779"></a>
-<span class="sourceLineNo">780</span>        msgBuffer.append("Free for total=" + StringUtils.byteDesc(bytesToFreeWithoutExtra) + ", ");<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>      if (bytesToFreeWithoutExtra &lt;= 0) {<a name="line.783"></a>
-<span class="sourceLineNo">784</span>        return;<a name="line.784"></a>
+<span class="sourceLineNo">634</span>          return false;<a name="line.634"></a>
+<span class="sourceLineNo">635</span>        } else {<a name="line.635"></a>
+<span class="sourceLineNo">636</span>          if (LOG.isDebugEnabled()) {<a name="line.636"></a>
+<span class="sourceLineNo">637</span>            LOG.debug("This block " + cacheKey + " is still referred by " + refCount<a name="line.637"></a>
+<span class="sourceLineNo">638</span>                + " readers. Can not be freed now. Hence will mark this"<a name="line.638"></a>
+<span class="sourceLineNo">639</span>                + " for evicting at a later point");<a name="line.639"></a>
+<span class="sourceLineNo">640</span>          }<a name="line.640"></a>
+<span class="sourceLineNo">641</span>          bucketEntry.markForEvict();<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>    } finally {<a name="line.644"></a>
+<span class="sourceLineNo">645</span>      lock.writeLock().unlock();<a name="line.645"></a>
+<span class="sourceLineNo">646</span>    }<a name="line.646"></a>
+<span class="sourceLineNo">647</span>    cacheStats.evicted(bucketEntry.getCachedTime(), cacheKey.isPrimary());<a name="line.647"></a>
+<span class="sourceLineNo">648</span>    return true;<a name="line.648"></a>
+<span class="sourceLineNo">649</span>  }<a name="line.649"></a>
+<span class="sourceLineNo">650</span><a name="line.650"></a>
+<span class="sourceLineNo">651</span>  /*<a name="line.651"></a>
+<span class="sourceLineNo">652</span>   * Statistics thread.  Periodically output cache statistics to the log.<a name="line.652"></a>
+<span class="sourceLineNo">653</span>   */<a name="line.653"></a>
+<span class="sourceLineNo">654</span>  private static class StatisticsThread extends Thread {<a name="line.654"></a>
+<span class="sourceLineNo">655</span>    private final BucketCache bucketCache;<a name="line.655"></a>
+<span class="sourceLineNo">656</span><a name="line.656"></a>
+<span class="sourceLineNo">657</span>    public StatisticsThread(BucketCache bucketCache) {<a name="line.657"></a>
+<span class="sourceLineNo">658</span>      super("BucketCacheStatsThread");<a name="line.658"></a>
+<span class="sourceLineNo">659</span>      setDaemon(true);<a name="line.659"></a>
+<span class="sourceLineNo">660</span>      this.bucketCache = bucketCache;<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>    @Override<a name="line.663"></a>
+<span class="sourceLineNo">664</span>    public void run() {<a name="line.664"></a>
+<span class="sourceLineNo">665</span>      bucketCache.logStats();<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>  public void logStats() {<a name="line.669"></a>
+<span class="sourceLineNo">670</span>    long totalSize = bucketAllocator.getTotalSize();<a name="line.670"></a>
+<span class="sourceLineNo">671</span>    long usedSize = bucketAllocator.getUsedSize();<a name="line.671"></a>
+<span class="sourceLineNo">672</span>    long freeSize = totalSize - usedSize;<a name="line.672"></a>
+<span class="sourceLineNo">673</span>    long cacheSize = getRealCacheSize();<a name="line.673"></a>
+<span class="sourceLineNo">674</span>    LOG.info("failedBlockAdditions=" + cacheStats.getFailedInserts() + ", " +<a name="line.674"></a>
+<span class="sourceLineNo">675</span>        "totalSize=" + StringUtils.byteDesc(totalSize) + ", " +<a name="line.675"></a>
+<span class="sourceLineNo">676</span>        "freeSize=" + StringUtils.byteDesc(freeSize) + ", " +<a name="line.676"></a>
+<span class="sourceLineNo">677</span>        "usedSize=" + StringUtils.byteDesc(usedSize) +", " +<a name="line.677"></a>
+<span class="sourceLineNo">678</span>        "cacheSize=" + StringUtils.byteDesc(cacheSize) +", " +<a name="line.678"></a>
+<span class="sourceLineNo">679</span>        "accesses=" + cacheStats.getRequestCount() + ", " +<a name="line.679"></a>
+<span class="sourceLineNo">680</span>        "hits=" + cacheStats.getHitCount() + ", " +<a name="line.680"></a>
+<span class="sourceLineNo">681</span>        "IOhitsPerSecond=" + cacheStats.getIOHitsPerSecond() + ", " +<a name="line.681"></a>
+<span class="sourceLineNo">682</span>        "IOTimePerHit=" + String.format("%.2f", cacheStats.getIOTimePerHit())+ ", " +<a name="line.682"></a>
+<span class="sourceLineNo">683</span>        "hitRatio=" + (cacheStats.getHitCount() == 0 ? "0," :<a name="line.683"></a>
+<span class="sourceLineNo">684</span>          (StringUtils.formatPercent(cacheStats.getHitRatio(), 2)+ ", ")) +<a name="line.684"></a>
+<span class="sourceLineNo">685</span>        "cachingAccesses=" + cacheStats.getRequestCachingCount() + ", " +<a name="line.685"></a>
+<span class="sourceLineNo">686</span>        "cachingHits=" + cacheStats.getHitCachingCount() + ", " +<a name="line.686"></a>
+<span class="sourceLineNo">687</span>        "cachingHitsRatio=" +(cacheStats.getHitCachingCount() == 0 ? "0," :<a name="line.687"></a>
+<span class="sourceLineNo">688</span>          (StringUtils.formatPercent(cacheStats.getHitCachingRatio(), 2)+ ", ")) +<a name="line.688"></a>
+<span class="sourceLineNo">689</span>        "evictions=" + cacheStats.getEvictionCount() + ", " +<a name="line.689"></a>
+<span class="sourceLineNo">690</span>        "evicted=" + cacheStats.getEvictedCount() + ", " +<a name="line.690"></a>
+<span class="sourceLineNo">691</span>        "evictedPerRun=" + cacheStats.evictedPerEviction());<a name="line.691"></a>
+<span class="sourceLineNo">692</span>    cacheStats.reset();<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>  public long getRealCacheSize() {<a name="line.695"></a>
+<span class="sourceLineNo">696</span>    return this.realCacheSize.sum();<a name="line.696"></a>
+<span class="sourceLineNo">697</span>  }<a name="line.697"></a>
+<span class="sourceLineNo">698</span><a name="line.698"></a>
+<span class="sourceLineNo">699</span>  private long acceptableSize() {<a name="line.699"></a>
+<span class="sourceLineNo">700</span>    return (long) Math.floor(bucketAllocator.getTotalSize() * acceptableFactor);<a name="line.700"></a>
+<span class="sourceLineNo">701</span>  }<a name="line.701"></a>
+<span class="sourceLineNo">702</span><a name="line.702"></a>
+<span class="sourceLineNo">703</span>  @VisibleForTesting<a name="line.703"></a>
+<span class="sourceLineNo">704</span>  long getPartitionSize(float partitionFactor) {<a name="line.704"></a>
+<span class="sourceLineNo">705</span>    return (long) Math.floor(bucketAllocator.getTotalSize() * partitionFactor * minFactor);<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>   * Return the count of bucketSizeinfos still need free space<a name="line.709"></a>
+<span class="sourceLineNo">710</span>   */<a name="line.710"></a>
+<span class="sourceLineNo">711</span>  private int bucketSizesAboveThresholdCount(float minFactor) {<a name="line.711"></a>
+<span class="sourceLineNo">712</span>    BucketAllocator.IndexStatistics[] stats = bucketAllocator.getIndexStatistics();<a name="line.712"></a>
+<span class="sourceLineNo">713</span>    int fullCount = 0;<a name="line.713"></a>
+<span class="sourceLineNo">714</span>    for (int i = 0; i &lt; stats.length; i++) {<a name="line.714"></a>
+<span class="sourceLineNo">715</span>      long freeGoal = (long) Math.floor(stats[i].totalCount() * (1 - minFactor));<a name="line.715"></a>
+<span class="sourceLineNo">716</span>      freeGoal = Math.max(freeGoal, 1);<a name="line.716"></a>
+<span class="sourceLineNo">717</span>      if (stats[i].freeCount() &lt; freeGoal) {<a name="line.717"></a>
+<span class="sourceLineNo">718</span>        fullCount++;<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>
+<span class="sourceLineNo">721</span>    return fullCount;<a name="line.721"></a>
+<span class="sourceLineNo">722</span>  }<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>   * This method will find the buckets that are minimally occupied<a name="line.725"></a>
+<span class="sourceLineNo">726</span>   * and are not reference counted and will free them completely<a name="line.726"></a>
+<span class="sourceLineNo">727</span>   * without any constraint on the access times of the elements,<a name="line.727"></a>
+<span class="sourceLineNo">728</span>   * and as a process will completely free at most the number of buckets<a name="line.728"></a>
+<span class="sourceLineNo">729</span>   * passed, sometimes it might not due to changing refCounts<a name="line.729"></a>
+<span class="sourceLineNo">730</span>   *<a name="line.730"></a>
+<span class="sourceLineNo">731</span>   * @param completelyFreeBucketsNeeded number of buckets to free<a name="line.731"></a>
+<span class="sourceLineNo">732</span>   **/<a name="line.732"></a>
+<span class="sourceLineNo">733</span>  private void freeEntireBuckets(int completelyFreeBucketsNeeded) {<a name="line.733"></a>
+<span class="sourceLineNo">734</span>    if (completelyFreeBucketsNeeded != 0) {<a name="line.734"></a>
+<span class="sourceLineNo">735</span>      // First we will build a set where the offsets are reference counted, usually<a name="line.735"></a>
+<span class="sourceLineNo">736</span>      // this set is small around O(Handler Count) unless something else is wrong<a name="line.736"></a>
+<span class="sourceLineNo">737</span>      Set&lt;Integer&gt; inUseBuckets = new HashSet&lt;Integer&gt;();<a name="line.737"></a>
+<span class="sourceLineNo">738</span>      for (BucketEntry entry : backingMap.values()) {<a name="line.738"></a>
+<span class="sourceLineNo">739</span>        if (entry.getRefCount() != 0) {<a name="line.739"></a>
+<span class="sourceLineNo">740</span>          inUseBuckets.add(bucketAllocator.getBucketIndex(entry.offset()));<a name="line.740"></a>
+<span class="sourceLineNo">741</span>        }<a name="line.741"></a>
+<span class="sourceLineNo">742</span>      }<a name="line.742"></a>
+<span class="sourceLineNo">743</span><a name="line.743"></a>
+<span class="sourceLineNo">744</span>      Set&lt;Integer&gt; candidateBuckets = bucketAllocator.getLeastFilledBuckets(<a name="line.744"></a>
+<span class="sourceLineNo">745</span>          inUseBuckets, completelyFreeBucketsNeeded);<a name="line.745"></a>
+<span class="sourceLineNo">746</span>      for (Map.Entry&lt;BlockCacheKey, BucketEntry&gt; entry : backingMap.entrySet()) {<a name="line.746"></a>
+<span class="sourceLineNo">747</span>        if (candidateBuckets.contains(bucketAllocator<a name="line.747"></a>
+<span class="sourceLineNo">748</span>            .getBucketIndex(entry.getValue().offset()))) {<a name="line.748"></a>
+<span class="sourceLineNo">749</span>          evictBlock(entry.getKey(), false);<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>  }<a name="line.753"></a>
+<span class="sourceLineNo">754</span><a name="line.754"></a>
+<span class="sourceLineNo">755</span>  /**<a name="line.755"></a>
+<span class="sourceLineNo">756</span>   * Free the space if the used size reaches acceptableSize() or one size block<a name="line.756"></a>
+<span class="sourceLineNo">757</span>   * couldn't be allocated. When freeing the space, we use the LRU algorithm and<a name="line.757"></a>
+<span class="sourceLineNo">758</span>   * ensure there must be some blocks evicted<a name="line.758"></a>
+<span class="sourceLineNo">759</span>   * @param why Why we are being called<a name="line.759"></a>
+<span class="sourceLineNo">760</span>   */<a name="line.760"></a>
+<span class="sourceLineNo">761</span>  private void freeSpace(final String why) {<a name="line.761"></a>
+<span class="sourceLineNo">762</span>    // Ensure only one freeSpace progress at a time<a name="line.762"></a>
+<span class="sourceLineNo">763</span>    if (!freeSpaceLock.tryLock()) {<a name="line.763"></a>
+<span class="sourceLineNo">764</span>      return;<a name="line.764"></a>
+<span class="sourceLineNo">765</span>    }<a name="line.765"></a>
+<span class="sourceLineNo">766</span>    try {<a name="line.766"></a>
+<span class="sourceLineNo">767</span>      freeInProgress = true;<a name="line.767"></a>
+<span class="sourceLineNo">768</span>      long bytesToFreeWithoutExtra = 0;<a name="line.768"></a>
+<span class="sourceLineNo">769</span>      // Calculate free byte for each bucketSizeinfo<a name="line.769"></a>
+<span class="sourceLineNo">770</span>      StringBuilder msgBuffer = LOG.isDebugEnabled()? new StringBuilder(): null;<a name="line.770"></a>
+<span class="sourceLineNo">771</span>      BucketAllocator.IndexStatistics[] stats = bucketAllocator.getIndexStatistics();<a name="line.771"></a>
+<span class="sourceLineNo">772</span>      long[] bytesToFreeForBucket = new long[stats.length];<a name="line.772"></a>
+<span class="sourceLineNo">773</span>      for (int i = 0; i &lt; stats.length; i++) {<a name="line.773"></a>
+<span class="sourceLineNo">774</span>        bytesToFreeForBucket[i] = 0;<a name="line.774"></a>
+<span class="sourceLineNo">775</span>        long freeGoal = (long) Math.floor(stats[i].totalCount() * (1 - minFactor));<a name="line.775"></a>
+<span class="sourceLineNo">776</span>        freeGoal = Math.max(freeGoal, 1);<a name="line.776"></a>
+<span class="sourceLineNo">777</span>        if (stats[i].freeCount() &lt; freeGoal) {<a name="line.777"></a>
+<span class="sourceLineNo">778</span>          bytesToFreeForBucket[i] = stats[i].itemSize() * (freeGoal - stats[i].freeCount());<a name="line.778"></a>
+<span class="sourceLineNo">779</span>          bytesToFreeWithoutExtra += bytesToFreeForBucket[i];<a name="line.779"></a>
+<span class="sourceLineNo">780</span>          if (msgBuffer != null) {<a name="line.780"></a>
+<span class="sourceLineNo">781</span>            msgBuffer.append("Free for bucketSize(" + stats[i].itemSize() + ")="<a name="line.781"></a>
+<span class="sourceLineNo">782</span>              + StringUtils.byteDesc(bytesToFreeForBucket[i]) + ", ");<a name="line.782"></a>
+<span class="sourceLineNo">783</span>          }<a name="line.783"></a>
+<span class="sourceLineNo">784</span>        }<a name="line.784"></a>
 <span class="sourceLineNo">785</span>      }<a name="line.785"></a>
-<span class="sourceLineNo">786</span>      long currentSize = bucketAllocator.getUsedSize();<a name="line.786"></a>
-<span class="sourceLineNo">787</span>      long totalSize = bucketAllocator.getTotalSize();<a name="line.787"></a>
-<span class="sourceLineNo">788</span>      if (LOG.isDebugEnabled() &amp;&amp; msgBuffer != null) {<a name="line.788"></a>
-<span class="sourceLineNo">789</span>        LOG.debug("Free started because \"" + why + "\"; " + msgBuffer.toString() +<a name="line.789"></a>
-<span class="sourceLineNo">790</span>          " of current used=" + StringUtils.byteDesc(currentSize) + ", actual cacheSize=" +<a name="line.790"></a>
-<span class="sourceLineNo">791</span>          StringUtils.byteDesc(realCacheSize.sum()) + ", total=" + StringUtils.byteDesc(totalSize));<a name="line.791"></a>
+<span class="sourceLineNo">786</span>      if (msgBuffer != null) {<a name="line.786"></a>
+<span class="sourceLineNo">787</span>        msgBuffer.append("Free for total=" + StringUtils.byteDesc(bytesToFreeWithoutExtra) + ", ");<a name="line.787"></a>
+<span class="sourceLineNo">788</span>      }<a name="line.788"></a>
+<span class="sourceLineNo">789</span><a name="line.789"></a>
+<span class="sourceLineNo">790</span>      if (bytesToFreeWithoutExtra &lt;= 0) {<a name="line.790"></a>
+<span class="sourceLineNo">791</span>        return;<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>
-<span class="sourceLineNo">794</span>      long bytesToFreeWithExtra = (long) Math.floor(bytesToFreeWithoutExtra<a name="line.794"></a>
-<span class="sourceLineNo">795</span>          * (1 + extraFreeFactor));<a name="line.795"></a>
-<span class="sourceLineNo">796</span><a name="line.796"></a>
-<span class="sourceLineNo">797</span>      // Instantiate priority buckets<a name="line.797"></a>
-<span class="sourceLineNo">798</span>      BucketEntryGroup bucketSingle = new BucketEntryGroup(bytesToFreeWithExtra,<a name="line.798"></a>
-<span class="sourceLineNo">799</span>          blockSize, getPartitionSize(singleFactor));<a name="line.799"></a>
-<span class="sourceLineNo">800</span>      BucketEntryGroup bucketMulti = new BucketEntryGroup(bytesToFreeWithExtra,<a name="line.800"></a>
-<span class="sourceLineNo">801</span>          blockSize, getPartitionSize(multiFactor));<a name="line.801"></a>
-<span class="sourceLineNo">802</span>      BucketEntryGroup bucketMemory = new BucketEntryGroup(bytesToFreeWithExtra,<a name="line.802"></a>
-<span class="sourceLineNo">803</span>          blockSize, getPartitionSize(memoryFactor));<a name="line.803"></a>
-<span class="sourceLineNo">804</span><a name="line.804"></a>
-<span class="sourceLineNo">805</span>      // Scan entire map putting bucket entry into appropriate bucket entry<a name="line.805"></a>
-<span class="sourceLineNo">806</span>      // group<a name="line.806"></a>
-<span class="sourceLineNo">807</span>      for (Map.Entry&lt;BlockCacheKey, BucketEntry&gt; bucketEntryWithKey : backingMap.entrySet()) {<a name="line.807"></a>
-<span class="sourceLineNo">808</span>        switch (bucketEntryWithKey.getValue().getPriority()) {<a name="line.808"></a>
-<span class="sourceLineNo">809</span>          case SINGLE: {<a name="line.809"></a>
-<span class="sourceLineNo">810</span>            bucketSingle.add(bucketEntryWithKey);<a name="line.810"></a>
-<span class="sourceLineNo">811</span>            break;<a name="line.811"></a>
-<span class="sourceLineNo">812</span>          }<a name="line.812"></a>
-<span class="sourceLineNo">813</span>          case MULTI: {<a name="line.813"></a>
-<span class="sourceLineNo">814</span>            bucketMulti.add(bucketEntryWithKey);<a name="line.814"></a>
-<span class="sourceLineNo">815</span>            break;<a name="line.815"></a>
-<span class="sourceLineNo">816</span>          }<a name="line.816"></a>
-<span class="sourceLineNo">817</span>          case MEMORY: {<a name="line.817"></a>
-<span class="sourceLineNo">818</span>            bucketMemory.add(bucketEntryWithKey);<a name="line.818"></a>
-<span class="sourceLineNo">819</span>            break;<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><a name="line.823"></a>
-<span class="sourceLineNo">824</span>      PriorityQueue&lt;BucketEntryGroup&gt; bucketQueue = new PriorityQueue&lt;&gt;(3,<a name="line.824"></a>
-<span class="sourceLineNo">825</span>          Comparator.comparingLong(BucketEntryGroup::overflow));<a name="line.825"></a>
-<span class="sourceLineNo">826</span><a name="line.826"></a>
-<span class="sourceLineNo">827</span>      bucketQueue.add(bucketSingle);<a name="line.827"></a>
-<span class="sourceLineNo">828</span>      bucketQueue.add(bucketMulti);<a name="line.828"></a>
-<span class="sourceLineNo">829</span>      bucketQueue.add(bucketMemory);<a name="line.829"></a>
+<span class="sourceLineNo">793</span>      long currentSize = bucketAllocator.getUsedSize();<a name="line.793"></a>
+<span class="sourceLineNo">794</span>      long totalSize = bucketAllocator.getTotalSize();<a name="line.794"></a>
+<span class="sourceLineNo">795</span>      if (LOG.isDebugEnabled() &amp;&amp; msgBuffer != null) {<a name="line.795"></a>
+<span class="sourceLineNo">796</span>        LOG.debug("Free started because \"" + why + "\"; " + msgBuffer.toString() +<a name="line.796"></a>
+<span class="sourceLineNo">797</span>          " of current used=" + StringUtils.byteDesc(currentSize) + ", actual cacheSize=" +<a name="line.797"></a>
+<span class="sourceLineNo">798</span>          StringUtils.byteDesc(realCacheSize.sum()) + ", total=" + StringUtils.byteDesc(totalSize));<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>      long bytesToFreeWithExtra = (long) Math.floor(bytesToFreeWithoutExtra<a name="line.801"></a>
+<span class="sourceLineNo">802</span>          * (1 + extraFreeFactor));<a name="line.802"></a>
+<span class="sourceLineNo">803</span><a name="line.803"></a>
+<span class="sourceLineNo">804</span>      // Instantiate priority buckets<a name="line.804"></a>
+<span class="sourceLineNo">805</span>      BucketEntryGroup bucketSingle = new BucketEntryGroup(bytesToFreeWithExtra,<a name="line.805"></a>
+<span class="sourceLineNo">806</span>          blockSize, getPartitionSize(singleFactor));<a name="line.806"></a>
+<span class="sourceLineNo">807</span>      BucketEntryGroup bucketMulti = new BucketEntryGroup(bytesToFreeWithExtra,<a name="line.807"></a>
+<span class="sourceLineNo">808</span>          blockSize, getPartitionSize(multiFactor));<a name="line.808"></a>
+<span class="sourceLineNo">809</span>      BucketEntryGroup bucketMemory = new BucketEntryGroup(bytesToFreeWithExtra,<a name="line.809"></a>
+<span class="sourceLineNo">810</span>          blockSize, getPartitionSize(memoryFactor));<a name="line.810"></a>
+<span class="sourceLineNo">811</span><a name="line.811"></a>
+<span class="sourceLineNo">812</span>      // Scan entire map putting bucket entry into appropriate bucket entry<a name="line.812"></a>
+<span class="sourceLineNo">813</span>      // group<a name="line.813"></a>
+<span class="sourceLineNo">814</span>      for (Map.Entry&lt;BlockCacheKey, BucketEntry&gt; bucketEntryWithKey : backingMap.entrySet()) {<a name="line.814"></a>
+<span class="sourceLineNo">815</span>        switch (bucketEntryWithKey.getValue().getPriority()) {<a name="line.815"></a>
+<span class="sourceLineNo">816</span>          case SINGLE: {<a name="line.816"></a>
+<span class="sourceLineNo">817</span>            bucketSingle.add(bucketEntryWithKey);<a name="line.817"></a>
+<span class="sourceLineNo">818</span>            break;<a name="line.818"></a>
+<span class="sourceLineNo">819</span>          }<a name="line.819"></a>
+<span class="sourceLineNo">820</span>          case MULTI: {<a name="line.820"></a>
+<span class="sourceLineNo">821</span>            bucketMulti.add(bucketEntryWithKey);<a name="line.821"></a>
+<span class="sourceLineNo">822</span>            break;<a name="line.822"></a>
+<span class="sourceLineNo">823</span>          }<a name="line.823"></a>
+<span class="sourceLineNo">824</span>          case MEMORY: {<a name="line.824"></a>
+<span class="sourceLineNo">825</span>            bucketMemory.add(bucketEntryWithKey);<a name="line.825"></a>
+<span class="sourceLineNo">826</span>            break;<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">830</span><a name="line.830"></a>
-<span class="sourceLineNo">831</span>      int remainingBuckets = 3;<a name="line.831"></a>
-<span class="sourceLineNo">832</span>      long bytesFreed = 0;<a name="line.832"></a>
+<span class="sourceLineNo">831</span>      PriorityQueue&lt;BucketEntryGroup&gt; bucketQueue = new PriorityQueue&lt;&gt;(3,<a name="line.831"></a>
+<span class="sourceLineNo">832</span>          Comparator.comparingLong(BucketEntryGroup::overflow));<a name="line.832"></a>
 <span class="sourceLineNo">833</span><a name="line.833"></a>
-<span class="sourceLineNo">834</span>      BucketEntryGroup bucketGroup;<a name="line.834"></a>
-<span class="sourceLineNo">835</span>      while ((bucketGroup = bucketQueue.poll()) != null) {<a name="line.835"></a>
-<span class="sourceLineNo">836</span>        long overflow = bucketGroup.overflow();<a name="line.836"></a>
-<span class="sourceLineNo">837</span>        if (overflow &gt; 0) {<a name="line.837"></a>
-<span class="sourceLineNo">838</span>          long bucketBytesToFree = Math.min(overflow,<a name="line.838"></a>
-<span class="sourceLineNo">839</span>              (bytesToFreeWithoutExtra - bytesFreed) / remainingBuckets);<a name="line.839"></a>
-<span class="sourceLineNo">840</span>          bytesFreed += bucketGroup.free(bucketBytesToFree);<a name="line.840"></a>
-<span class="sourceLineNo">841</span>        }<a name="line.841"></a>
-<span class="sourceLineNo">842</span>        remainingBuckets--;<a name="line.842"></a>
-<span class="sourceLineNo">843</span>      }<a name="line.843"></a>
-<span class="sourceLineNo">844</span><a name="line.844"></a>
-<span class="sourceLineNo">845</span>      // Check and free if there are buckets that still need freeing of space<a name="line.845"></a>
-<span class="sourceLineNo">846</span>      if (bucketSizesAboveThresholdCount(minFactor) &gt; 0) {<a name="line.846"></a>
-<span class="sourceLineNo">847</span>        bucketQueue.clear();<a name="line.847"></a>
-<span class="sourceLineNo">848</span>        remainingBuckets = 3;<a name="line.848"></a>
-<span class="sourceLineNo">849</span><a name="line.849"></a>
-<span class="sourceLineNo">850</span>        bucketQueue.add(bucketSingle);<a name="line.850"></a>
-<span class="sourceLineNo">851</span>        bucketQueue.add(bucketMulti);<a name="line.851"></a>
-<span class="sourceLineNo">852</span>        bucketQueue.add(bucketMemory);<a name="line.852"></a>
-<span class="sourceLineNo">853</span><a name="line.853"></a>
-<span class="sourceLineNo">854</span>        while ((bucketGroup = bucketQueue.poll()) != null) {<a name="line.854"></a>
-<span class="sourceLineNo">855</span>          long bucketBytesToFree = (bytesToFreeWithExtra - bytesFreed) / remainingBuckets;<a name="line.855"></a>
-<span class="sourceLineNo">856</span>          bytesFreed += bucketGroup.free(bucketBytesToFree);<a name="line.856"></a>
-<span class="sourceLineNo">857</span>          remainingBuckets--;<a name="line.857"></a>
-<span class="sourceLineNo">858</span>        }<a name="line.858"></a>
-<span class="sourceLineNo">859</span>      }<a name="line.859"></a>
+<span class="sourceLineNo">834</span>      bucketQueue.add(bucketSingle);<a name="line.834"></a>
+<span class="sourceLineNo">835</span>      bucketQueue.add(bucketMulti);<a name="line.835"></a>
+<span class="sourceLineNo">836</span>      bucketQueue.add(bucketMemory);<a name="line.836"></a>
+<span class="sourceLineNo">837</span><a name="line.837"></a>
+<span class="sourceLineNo">838</span>      int remainingBuckets = 3;<a name="line.838"></a>
+<span class="sourceLineNo">839</span>      long bytesFreed = 0;<a name="line.839"></a>
+<span class="sourceLineNo">840</span><a name="line.840"></a>
+<span class="sourceLineNo">841</span>      BucketEntryGroup bucketGroup;<a name="line.841"></a>
+<span class="sourceLineNo">842</span>      while ((bucketGroup = bucketQueue.poll()) != null) {<a name="line.842"></a>
+<span class="sourceLineNo">843</span>        long overflow = bucketGroup.overflow();<a name="line.843"></a>
+<span class="sourceLineNo">844</span>        if (overflow &gt; 0) {<a name="line.844"></a>
+<span class="sourceLineNo">845</span>          long bucketBytesToFree = Math.min(overflow,<a name="line.845"></a>
+<span class="sourceLineNo">846</span>              (bytesToFreeWithoutExtra - bytesFreed) / remainingBuckets);<a name="line.846"></a>
+<span class="sourceLineNo">847</span>          bytesFreed += bucketGroup.free(bucketBytesToFree);<a name="line.847"></a>
+<span class="sourceLineNo">848</span>        }<a name="line.848"></a>
+<span class="sourceLineNo">849</span>        remainingBuckets--;<a name="line.849"></a>
+<span class="sourceLineNo">850</span>      }<a name="line.850"></a>
+<span class="sourceLineNo">851</span><a name="line.851"></a>
+<span class="sourceLineNo">852</span>      // Check and free if there are buckets that still need freeing of space<a name="line.852"></a>
+<span class="sourceLineNo">853</span>      if (bucketSizesAboveThresholdCount(minFactor) &gt; 0) {<a name="line.853"></a>
+<span class="sourceLineNo">854</span>        bucketQueue.clear();<a name="line.854"></a>
+<span class="sourceLineNo">855</span>        remainingBuckets = 3;<a name="line.855"></a>
+<span class="sourceLineNo">856</span><a name="line.856"></a>
+<span class="sourceLineNo">857</span>        bucketQueue.add(bucketSingle);<a name="line.857"></a>
+<span class="sourceLineNo">858</span>        bucketQueue.add(bucketMulti);<a name="line.858"></a>
+<span class="sourceLineNo">859</span>        bucketQueue.add(bucketMemory);<a name="line.859"></a>
 <span class="sourceLineNo">860</span><a name="line.860"></a>
-<span class="sourceLineNo">861</span>      // Even after the above free we might still need freeing because of the<a name="line.861"></a>
-<span class="sourceLineNo">862</span>      // De-fragmentation of the buckets (also called Slab Calcification problem), i.e<a name="line.862"></a>
-<span class="sourceLineNo">863</span>      // there might be some buckets where the occupancy is very sparse and thus are not<a name="line.863"></a>
-<span class="sourceLineNo">864</span>      // yielding the free for the other bucket sizes, the fix for this to evict some<a name="line.864"></a>
-<span class="sourceLineNo">865</span>      // of the buckets, we do this by evicting the buckets that are least fulled<a name="line.865"></a>
-<span class="sourceLineNo">866</span>      freeEntireBuckets(DEFAULT_FREE_ENTIRE_BLOCK_FACTOR *<a name="line.866"></a>
-<span class="sourceLineNo">867</span>          bucketSizesAboveThresholdCount(1.0f));<a name="line.867"></a>
-<span class="sourceLineNo">868</span><a name="line.868"></a>
-<span class="sourceLineNo">869</span>      if (LOG.isDebugEnabled()) {<a name="line.869"></a>
-<span class="sourceLineNo">870</span>        long single = bucketSingle.totalSize();<a name="line.870"></a>
-<span class="sourceLineNo">871</span>        long multi = bucketMulti.totalSize();<a name="line.871"></a>
-<span class="sourceLineNo">872</span>        long memory = bucketMemory.totalSize();<a name="line.872"></a>
-<span class="sourceLineNo">873</span>        if (LOG.isDebugEnabled()) {<a name="line.873"></a>
-<span class="sourceLineNo">874</span>          LOG.debug("Bucket cache free space completed; " + "freed="<a name="line.874"></a>
-<span class="sourceLineNo">875</span>            + StringUtils.byteDesc(bytesFreed) + ", " + "total="<a name="line.875"></a>
-<span class="sourceLineNo">876</span>            + StringUtils.byteDesc(totalSize) + ", " + "single="<a name="line.876"></a>
-<span class="sourceLineNo">877</span>            + StringUtils.byteDesc(single) + ", " + "multi="<a name="line.877"></a>
-<span class="sourceLineNo">878</span>            + StringUtils.byteDesc(multi) + ", " + "memory="<a name="line.878"></a>
-<span class="sourceLineNo">879</span>            + StringUtils.byteDesc(memory));<a name="line.879"></a>
-<span class="sourceLineNo">880</span>        }<a name="line.880"></a>
-<span class="sourceLineNo">881</span>      }<a name="line.881"></a>
-<span class="sourceLineNo">882</span><a name="line.882"></a>
-<span class="sourceLineNo">883</span>    } catch (Throwable t) {<a name="line.883"></a>
-<span class="sourceLineNo">884</span>      LOG.warn("Failed freeing space", t);<a name="line.884"></a>
-<span class="sourceLineNo">885</span>    } finally {<a name="line.885"></a>
-<span class="sourceLineNo">886</span>      cacheStats.evict();<a name="line.886"></a>
-<span class="sourceLineNo">887</span>      freeInProgress = false;<a name="line.887"></a>
-<span class="sourceLineNo">888</span>      freeSpaceLock.unlock();<a name="line.888"></a>
-<span class="sourceLineNo">889</span>    }<a name="line.889"></a>
-<span class="sourceLineNo">890</span>  }<a name="line.890"></a>
-<span class="sourceLineNo">891</span><a name="line.891"></a>
-<span class="sourceLineNo">892</span>  // This handles flushing the RAM cache to IOEngine.<a name="line.892"></a>
-<span class="sourceLineNo">893</span>  @VisibleForTesting<a name="line.893"></a>
-<span class="sourceLineNo">894</span>  class WriterThread extends HasThread {<a name="line.894"></a>
-<span class="sourceLineNo">895</span>    private final BlockingQueue&lt;RAMQueueEntry&gt; inputQueue;<a name="line.895"></a>
-<span class="sourceLineNo">896</span>    private volatile boolean writerEnabled = true;<a name="line.896"></a>
-<span class="sourceLineNo">897</span><a name="line.897"></a>
-<span class="sourceLineNo">898</span>    WriterThread(BlockingQueue&lt;RAMQueueEntry&gt; queue) {<a name="line.898"></a>
-<span class="sourceLineNo">899</span>      super("BucketCacheWriterThread");<a name="line.899"></a>
-<sp

<TRUNCATED>

[31/50] hbase-site git commit: Published site at 26babcf013de696b899d76a3c39434b794440d8d.

Posted by gi...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase-site/blob/da4482ac/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html
----------------------------------------------------------------------
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html
index 97ceefd..b7b4236 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/HFileBlock.html
@@ -103,8 +103,8 @@
 <span class="sourceLineNo">095</span> * Caches cache whole blocks with trailing checksums if any. We then tag on some metadata, the<a name="line.95"></a>
 <span class="sourceLineNo">096</span> * content of BLOCK_METADATA_SPACE which will be flag on if we are doing 'hbase'<a name="line.96"></a>
 <span class="sourceLineNo">097</span> * checksums and then the offset into the file which is needed when we re-make a cache key<a name="line.97"></a>
-<span class="sourceLineNo">098</span> * when we return the block to the cache as 'done'. See {@link Cacheable#serialize(ByteBuffer)} and<a name="line.98"></a>
-<span class="sourceLineNo">099</span> * {@link Cacheable#getDeserializer()}.<a name="line.99"></a>
+<span class="sourceLineNo">098</span> * when we return the block to the cache as 'done'.<a name="line.98"></a>
+<span class="sourceLineNo">099</span> * See {@link Cacheable#serialize(ByteBuffer, boolean)} and {@link Cacheable#getDeserializer()}.<a name="line.99"></a>
 <span class="sourceLineNo">100</span> *<a name="line.100"></a>
 <span class="sourceLineNo">101</span> * &lt;p&gt;TODO: Should we cache the checksums? Down in Writer#getBlockForCaching(CacheConfig) where<a name="line.101"></a>
 <span class="sourceLineNo">102</span> * we make a block to cache-on-write, there is an attempt at turning off checksums. This is not the<a name="line.102"></a>
@@ -333,1579 +333,1579 @@
 <span class="sourceLineNo">325</span>   * Creates a new {@link HFile} block from the given fields. This constructor<a name="line.325"></a>
 <span class="sourceLineNo">326</span>   * is used only while writing blocks and caching,<a name="line.326"></a>
 <span class="sourceLineNo">327</span>   * and is sitting in a byte buffer and we want to stuff the block into cache.<a name="line.327"></a>
-<span class="sourceLineNo">328</span>   * See {@link Writer#getBlockForCaching(CacheConfig)}.<a name="line.328"></a>
-<span class="sourceLineNo">329</span>   *<a name="line.329"></a>
-<span class="sourceLineNo">330</span>   * &lt;p&gt;TODO: The caller presumes no checksumming<a name="line.330"></a>
-<span class="sourceLineNo">331</span>   * required of this block instance since going into cache; checksum already verified on<a name="line.331"></a>
-<span class="sourceLineNo">332</span>   * underlying block data pulled in from filesystem. Is that correct? What if cache is SSD?<a name="line.332"></a>
-<span class="sourceLineNo">333</span>   *<a name="line.333"></a>
-<span class="sourceLineNo">334</span>   * @param blockType the type of this block, see {@link BlockType}<a name="line.334"></a>
-<span class="sourceLineNo">335</span>   * @param onDiskSizeWithoutHeader see {@link #onDiskSizeWithoutHeader}<a name="line.335"></a>
-<span class="sourceLineNo">336</span>   * @param uncompressedSizeWithoutHeader see {@link #uncompressedSizeWithoutHeader}<a name="line.336"></a>
-<span class="sourceLineNo">337</span>   * @param prevBlockOffset see {@link #prevBlockOffset}<a name="line.337"></a>
-<span class="sourceLineNo">338</span>   * @param b block header ({@link HConstants#HFILEBLOCK_HEADER_SIZE} bytes)<a name="line.338"></a>
-<span class="sourceLineNo">339</span>   * @param fillHeader when true, write the first 4 header fields into passed buffer.<a name="line.339"></a>
-<span class="sourceLineNo">340</span>   * @param offset the file offset the block was read from<a name="line.340"></a>
-<span class="sourceLineNo">341</span>   * @param onDiskDataSizeWithHeader see {@link #onDiskDataSizeWithHeader}<a name="line.341"></a>
-<span class="sourceLineNo">342</span>   * @param fileContext HFile meta data<a name="line.342"></a>
-<span class="sourceLineNo">343</span>   */<a name="line.343"></a>
-<span class="sourceLineNo">344</span>  HFileBlock(BlockType blockType, int onDiskSizeWithoutHeader, int uncompressedSizeWithoutHeader,<a name="line.344"></a>
-<span class="sourceLineNo">345</span>      long prevBlockOffset, ByteBuffer b, boolean fillHeader, long offset,<a name="line.345"></a>
-<span class="sourceLineNo">346</span>      final int nextBlockOnDiskSize, int onDiskDataSizeWithHeader, HFileContext fileContext) {<a name="line.346"></a>
-<span class="sourceLineNo">347</span>    init(blockType, onDiskSizeWithoutHeader, uncompressedSizeWithoutHeader,<a name="line.347"></a>
-<span class="sourceLineNo">348</span>        prevBlockOffset, offset, onDiskDataSizeWithHeader, nextBlockOnDiskSize, fileContext);<a name="line.348"></a>
-<span class="sourceLineNo">349</span>    this.buf = new SingleByteBuff(b);<a name="line.349"></a>
-<span class="sourceLineNo">350</span>    if (fillHeader) {<a name="line.350"></a>
-<span class="sourceLineNo">351</span>      overwriteHeader();<a name="line.351"></a>
-<span class="sourceLineNo">352</span>    }<a name="line.352"></a>
-<span class="sourceLineNo">353</span>    this.buf.rewind();<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>  /**<a name="line.356"></a>
-<span class="sourceLineNo">357</span>   * Creates a block from an existing buffer starting with a header. Rewinds<a name="line.357"></a>
-<span class="sourceLineNo">358</span>   * and takes ownership of the buffer. By definition of rewind, ignores the<a name="line.358"></a>
-<span class="sourceLineNo">359</span>   * buffer position, but if you slice the buffer beforehand, it will rewind<a name="line.359"></a>
-<span class="sourceLineNo">360</span>   * to that point.<a name="line.360"></a>
-<span class="sourceLineNo">361</span>   * @param buf Has header, content, and trailing checksums if present.<a name="line.361"></a>
-<span class="sourceLineNo">362</span>   */<a name="line.362"></a>
-<span class="sourceLineNo">363</span>  HFileBlock(ByteBuff buf, boolean usesHBaseChecksum, MemoryType memType, final long offset,<a name="line.363"></a>
-<span class="sourceLineNo">364</span>      final int nextBlockOnDiskSize, HFileContext fileContext) throws IOException {<a name="line.364"></a>
-<span class="sourceLineNo">365</span>    buf.rewind();<a name="line.365"></a>
-<span class="sourceLineNo">366</span>    final BlockType blockType = BlockType.read(buf);<a name="line.366"></a>
-<span class="sourceLineNo">367</span>    final int onDiskSizeWithoutHeader = buf.getInt(Header.ON_DISK_SIZE_WITHOUT_HEADER_INDEX);<a name="line.367"></a>
-<span class="sourceLineNo">368</span>    final int uncompressedSizeWithoutHeader =<a name="line.368"></a>
-<span class="sourceLineNo">369</span>        buf.getInt(Header.UNCOMPRESSED_SIZE_WITHOUT_HEADER_INDEX);<a name="line.369"></a>
-<span class="sourceLineNo">370</span>    final long prevBlockOffset = buf.getLong(Header.PREV_BLOCK_OFFSET_INDEX);<a name="line.370"></a>
-<span class="sourceLineNo">371</span>    // This constructor is called when we deserialize a block from cache and when we read a block in<a name="line.371"></a>
-<span class="sourceLineNo">372</span>    // from the fs. fileCache is null when deserialized from cache so need to make up one.<a name="line.372"></a>
-<span class="sourceLineNo">373</span>    HFileContextBuilder fileContextBuilder = fileContext != null?<a name="line.373"></a>
-<span class="sourceLineNo">374</span>        new HFileContextBuilder(fileContext): new HFileContextBuilder();<a name="line.374"></a>
-<span class="sourceLineNo">375</span>    fileContextBuilder.withHBaseCheckSum(usesHBaseChecksum);<a name="line.375"></a>
-<span class="sourceLineNo">376</span>    int onDiskDataSizeWithHeader;<a name="line.376"></a>
-<span class="sourceLineNo">377</span>    if (usesHBaseChecksum) {<a name="line.377"></a>
-<span class="sourceLineNo">378</span>      byte checksumType = buf.get(Header.CHECKSUM_TYPE_INDEX);<a name="line.378"></a>
-<span class="sourceLineNo">379</span>      int bytesPerChecksum = buf.getInt(Header.BYTES_PER_CHECKSUM_INDEX);<a name="line.379"></a>
-<span class="sourceLineNo">380</span>      onDiskDataSizeWithHeader = buf.getInt(Header.ON_DISK_DATA_SIZE_WITH_HEADER_INDEX);<a name="line.380"></a>
-<span class="sourceLineNo">381</span>      // Use the checksum type and bytes per checksum from header, not from filecontext.<a name="line.381"></a>
-<span class="sourceLineNo">382</span>      fileContextBuilder.withChecksumType(ChecksumType.codeToType(checksumType));<a name="line.382"></a>
-<span class="sourceLineNo">383</span>      fileContextBuilder.withBytesPerCheckSum(bytesPerChecksum);<a name="line.383"></a>
-<span class="sourceLineNo">384</span>    } else {<a name="line.384"></a>
-<span class="sourceLineNo">385</span>      fileContextBuilder.withChecksumType(ChecksumType.NULL);<a name="line.385"></a>
-<span class="sourceLineNo">386</span>      fileContextBuilder.withBytesPerCheckSum(0);<a name="line.386"></a>
-<span class="sourceLineNo">387</span>      // Need to fix onDiskDataSizeWithHeader; there are not checksums after-block-data<a name="line.387"></a>
-<span class="sourceLineNo">388</span>      onDiskDataSizeWithHeader = onDiskSizeWithoutHeader + headerSize(usesHBaseChecksum);<a name="line.388"></a>
-<span class="sourceLineNo">389</span>    }<a name="line.389"></a>
-<span class="sourceLineNo">390</span>    fileContext = fileContextBuilder.build();<a name="line.390"></a>
-<span class="sourceLineNo">391</span>    assert usesHBaseChecksum == fileContext.isUseHBaseChecksum();<a name="line.391"></a>
-<span class="sourceLineNo">392</span>    init(blockType, onDiskSizeWithoutHeader, uncompressedSizeWithoutHeader,<a name="line.392"></a>
-<span class="sourceLineNo">393</span>        prevBlockOffset, offset, onDiskDataSizeWithHeader, nextBlockOnDiskSize, fileContext);<a name="line.393"></a>
-<span class="sourceLineNo">394</span>    this.memType = memType;<a name="line.394"></a>
-<span class="sourceLineNo">395</span>    this.offset = offset;<a name="line.395"></a>
-<span class="sourceLineNo">396</span>    this.buf = buf;<a name="line.396"></a>
-<span class="sourceLineNo">397</span>    this.buf.rewind();<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>  /**<a name="line.400"></a>
-<span class="sourceLineNo">401</span>   * Called from constructors.<a name="line.401"></a>
-<span class="sourceLineNo">402</span>   */<a name="line.402"></a>
-<span class="sourceLineNo">403</span>  private void init(BlockType blockType, int onDiskSizeWithoutHeader,<a name="line.403"></a>
-<span class="sourceLineNo">404</span>      int uncompressedSizeWithoutHeader, long prevBlockOffset,<a name="line.404"></a>
-<span class="sourceLineNo">405</span>      long offset, int onDiskDataSizeWithHeader, final int nextBlockOnDiskSize,<a name="line.405"></a>
-<span class="sourceLineNo">406</span>      HFileContext fileContext) {<a name="line.406"></a>
-<span class="sourceLineNo">407</span>    this.blockType = blockType;<a name="line.407"></a>
-<span class="sourceLineNo">408</span>    this.onDiskSizeWithoutHeader = onDiskSizeWithoutHeader;<a name="line.408"></a>
-<span class="sourceLineNo">409</span>    this.uncompressedSizeWithoutHeader = uncompressedSizeWithoutHeader;<a name="line.409"></a>
-<span class="sourceLineNo">410</span>    this.prevBlockOffset = prevBlockOffset;<a name="line.410"></a>
-<span class="sourceLineNo">411</span>    this.offset = offset;<a name="line.411"></a>
-<span class="sourceLineNo">412</span>    this.onDiskDataSizeWithHeader = onDiskDataSizeWithHeader;<a name="line.412"></a>
-<span class="sourceLineNo">413</span>    this.nextBlockOnDiskSize = nextBlockOnDiskSize;<a name="line.413"></a>
-<span class="sourceLineNo">414</span>    this.fileContext = fileContext;<a name="line.414"></a>
-<span class="sourceLineNo">415</span>  }<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">418</span>   * Parse total on disk size including header and checksum.<a name="line.418"></a>
-<span class="sourceLineNo">419</span>   * @param headerBuf Header ByteBuffer. Presumed exact size of header.<a name="line.419"></a>
-<span class="sourceLineNo">420</span>   * @param verifyChecksum true if checksum verification is in use.<a name="line.420"></a>
-<span class="sourceLineNo">421</span>   * @return Size of the block with header included.<a name="line.421"></a>
-<span class="sourceLineNo">422</span>   */<a name="line.422"></a>
-<span class="sourceLineNo">423</span>  private static int getOnDiskSizeWithHeader(final ByteBuffer headerBuf,<a name="line.423"></a>
-<span class="sourceLineNo">424</span>      boolean verifyChecksum) {<a name="line.424"></a>
-<span class="sourceLineNo">425</span>    return headerBuf.getInt(Header.ON_DISK_SIZE_WITHOUT_HEADER_INDEX) +<a name="line.425"></a>
-<span class="sourceLineNo">426</span>      headerSize(verifyChecksum);<a name="line.426"></a>
-<span class="sourceLineNo">427</span>  }<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>   * @return the on-disk size of the next block (including the header size and any checksums if<a name="line.430"></a>
-<span class="sourceLineNo">431</span>   * present) read by peeking into the next block's header; use as a hint when doing<a name="line.431"></a>
-<span class="sourceLineNo">432</span>   * a read of the next block when scanning or running over a file.<a name="line.432"></a>
-<span class="sourceLineNo">433</span>   */<a name="line.433"></a>
-<span class="sourceLineNo">434</span>  int getNextBlockOnDiskSize() {<a name="line.434"></a>
-<span class="sourceLineNo">435</span>    return nextBlockOnDiskSize;<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>  @Override<a name="line.438"></a>
-<span class="sourceLineNo">439</span>  public BlockType getBlockType() {<a name="line.439"></a>
-<span class="sourceLineNo">440</span>    return blockType;<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>  /** @return get data block encoding id that was used to encode this block */<a name="line.443"></a>
-<span class="sourceLineNo">444</span>  short getDataBlockEncodingId() {<a name="line.444"></a>
-<span class="sourceLineNo">445</span>    if (blockType != BlockType.ENCODED_DATA) {<a name="line.445"></a>
-<span class="sourceLineNo">446</span>      throw new IllegalArgumentException("Querying encoder ID of a block " +<a name="line.446"></a>
-<span class="sourceLineNo">447</span>          "of type other than " + BlockType.ENCODED_DATA + ": " + blockType);<a name="line.447"></a>
-<span class="sourceLineNo">448</span>    }<a name="line.448"></a>
-<span class="sourceLineNo">449</span>    return buf.getShort(headerSize());<a name="line.449"></a>
-<span class="sourceLineNo">450</span>  }<a name="line.450"></a>
-<span class="sourceLineNo">451</span><a name="line.451"></a>
-<span class="sourceLineNo">452</span>  /**<a name="line.452"></a>
-<span class="sourceLineNo">453</span>   * @return the on-disk size of header + data part + checksum.<a name="line.453"></a>
-<span class="sourceLineNo">454</span>   */<a name="line.454"></a>
-<span class="sourceLineNo">455</span>  public int getOnDiskSizeWithHeader() {<a name="line.455"></a>
-<span class="sourceLineNo">456</span>    return onDiskSizeWithoutHeader + headerSize();<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>   * @return the on-disk size of the data part + checksum (header excluded).<a name="line.460"></a>
-<span class="sourceLineNo">461</span>   */<a name="line.461"></a>
-<span class="sourceLineNo">462</span>  int getOnDiskSizeWithoutHeader() {<a name="line.462"></a>
-<span class="sourceLineNo">463</span>    return onDiskSizeWithoutHeader;<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>  /**<a name="line.466"></a>
-<span class="sourceLineNo">467</span>   * @return the uncompressed size of data part (header and checksum excluded).<a name="line.467"></a>
-<span class="sourceLineNo">468</span>   */<a name="line.468"></a>
-<span class="sourceLineNo">469</span>   int getUncompressedSizeWithoutHeader() {<a name="line.469"></a>
-<span class="sourceLineNo">470</span>    return uncompressedSizeWithoutHeader;<a name="line.470"></a>
-<span class="sourceLineNo">471</span>  }<a name="line.471"></a>
-<span class="sourceLineNo">472</span><a name="line.472"></a>
-<span class="sourceLineNo">473</span>  /**<a name="line.473"></a>
-<span class="sourceLineNo">474</span>   * @return the offset of the previous block of the same type in the file, or<a name="line.474"></a>
-<span class="sourceLineNo">475</span>   *         -1 if unknown<a name="line.475"></a>
-<span class="sourceLineNo">476</span>   */<a name="line.476"></a>
-<span class="sourceLineNo">477</span>  long getPrevBlockOffset() {<a name="line.477"></a>
-<span class="sourceLineNo">478</span>    return prevBlockOffset;<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>   * Rewinds {@code buf} and writes first 4 header fields. {@code buf} position<a name="line.482"></a>
-<span class="sourceLineNo">483</span>   * is modified as side-effect.<a name="line.483"></a>
-<span class="sourceLineNo">484</span>   */<a name="line.484"></a>
-<span class="sourceLineNo">485</span>  private void overwriteHeader() {<a name="line.485"></a>
-<span class="sourceLineNo">486</span>    buf.rewind();<a name="line.486"></a>
-<span class="sourceLineNo">487</span>    blockType.write(buf);<a name="line.487"></a>
-<span class="sourceLineNo">488</span>    buf.putInt(onDiskSizeWithoutHeader);<a name="line.488"></a>
-<span class="sourceLineNo">489</span>    buf.putInt(uncompressedSizeWithoutHeader);<a name="line.489"></a>
-<span class="sourceLineNo">490</span>    buf.putLong(prevBlockOffset);<a name="line.490"></a>
-<span class="sourceLineNo">491</span>    if (this.fileContext.isUseHBaseChecksum()) {<a name="line.491"></a>
-<span class="sourceLineNo">492</span>      buf.put(fileContext.getChecksumType().getCode());<a name="line.492"></a>
-<span class="sourceLineNo">493</span>      buf.putInt(fileContext.getBytesPerChecksum());<a name="line.493"></a>
-<span class="sourceLineNo">494</span>      buf.putInt(onDiskDataSizeWithHeader);<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>  /**<a name="line.498"></a>
-<span class="sourceLineNo">499</span>   * Returns a buffer that does not include the header or checksum.<a name="line.499"></a>
-<span class="sourceLineNo">500</span>   *<a name="line.500"></a>
-<span class="sourceLineNo">501</span>   * @return the buffer with header skipped and checksum omitted.<a name="line.501"></a>
-<span class="sourceLineNo">502</span>   */<a name="line.502"></a>
-<span class="sourceLineNo">503</span>  public ByteBuff getBufferWithoutHeader() {<a name="line.503"></a>
-<span class="sourceLineNo">504</span>    ByteBuff dup = getBufferReadOnly();<a name="line.504"></a>
-<span class="sourceLineNo">505</span>    // Now set it up so Buffer spans content only -- no header or no checksums.<a name="line.505"></a>
-<span class="sourceLineNo">506</span>    return dup.position(headerSize()).limit(buf.limit() - totalChecksumBytes()).slice();<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 a read-only duplicate of the buffer this block stores internally ready to be read.<a name="line.510"></a>
-<span class="sourceLineNo">511</span>   * Clients must not modify the buffer object though they may set position and limit on the<a name="line.511"></a>
-<span class="sourceLineNo">512</span>   * returned buffer since we pass back a duplicate. This method has to be public because it is used<a name="line.512"></a>
-<span class="sourceLineNo">513</span>   * in {@link CompoundBloomFilter} to avoid object creation on every Bloom<a name="line.513"></a>
-<span class="sourceLineNo">514</span>   * filter lookup, but has to be used with caution. Buffer holds header, block content,<a name="line.514"></a>
-<span class="sourceLineNo">515</span>   * and any follow-on checksums if present.<a name="line.515"></a>
-<span class="sourceLineNo">516</span>   *<a name="line.516"></a>
-<span class="sourceLineNo">517</span>   * @return the buffer of this block for read-only operations<a name="line.517"></a>
-<span class="sourceLineNo">518</span>   */<a name="line.518"></a>
-<span class="sourceLineNo">519</span>  public ByteBuff getBufferReadOnly() {<a name="line.519"></a>
-<span class="sourceLineNo">520</span>    // TODO: ByteBuf does not support asReadOnlyBuffer(). Fix.<a name="line.520"></a>
-<span class="sourceLineNo">521</span>    ByteBuff dup = this.buf.duplicate();<a name="line.521"></a>
-<span class="sourceLineNo">522</span>    assert dup.position() == 0;<a name="line.522"></a>
-<span class="sourceLineNo">523</span>    return dup;<a name="line.523"></a>
-<span class="sourceLineNo">524</span>  }<a name="line.524"></a>
-<span class="sourceLineNo">525</span><a name="line.525"></a>
-<span class="sourceLineNo">526</span>  @VisibleForTesting<a name="line.526"></a>
-<span class="sourceLineNo">527</span>  private void sanityCheckAssertion(long valueFromBuf, long valueFromField,<a name="line.527"></a>
-<span class="sourceLineNo">528</span>      String fieldName) throws IOException {<a name="line.528"></a>
-<span class="sourceLineNo">529</span>    if (valueFromBuf != valueFromField) {<a name="line.529"></a>
-<span class="sourceLineNo">530</span>      throw new AssertionError(fieldName + " in the buffer (" + valueFromBuf<a name="line.530"></a>
-<span class="sourceLineNo">531</span>          + ") is different from that in the field (" + valueFromField + ")");<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>  @VisibleForTesting<a name="line.535"></a>
-<span class="sourceLineNo">536</span>  private void sanityCheckAssertion(BlockType valueFromBuf, BlockType valueFromField)<a name="line.536"></a>
-<span class="sourceLineNo">537</span>      throws IOException {<a name="line.537"></a>
-<span class="sourceLineNo">538</span>    if (valueFromBuf != valueFromField) {<a name="line.538"></a>
-<span class="sourceLineNo">539</span>      throw new IOException("Block type stored in the buffer: " +<a name="line.539"></a>
-<span class="sourceLineNo">540</span>        valueFromBuf + ", block type field: " + valueFromField);<a name="line.540"></a>
-<span class="sourceLineNo">541</span>    }<a name="line.541"></a>
-<span class="sourceLineNo">542</span>  }<a name="line.542"></a>
-<span class="sourceLineNo">543</span><a name="line.543"></a>
-<span class="sourceLineNo">544</span>  /**<a name="line.544"></a>
-<span class="sourceLineNo">545</span>   * Checks if the block is internally consistent, i.e. the first<a name="line.545"></a>
-<span class="sourceLineNo">546</span>   * {@link HConstants#HFILEBLOCK_HEADER_SIZE} bytes of the buffer contain a<a name="line.546"></a>
-<span class="sourceLineNo">547</span>   * valid header consistent with the fields. Assumes a packed block structure.<a name="line.547"></a>
-<span class="sourceLineNo">548</span>   * This function is primary for testing and debugging, and is not<a name="line.548"></a>
-<span class="sourceLineNo">549</span>   * thread-safe, because it alters the internal buffer pointer.<a name="line.549"></a>
-<span class="sourceLineNo">550</span>   * Used by tests only.<a name="line.550"></a>
-<span class="sourceLineNo">551</span>   */<a name="line.551"></a>
-<span class="sourceLineNo">552</span>  @VisibleForTesting<a name="line.552"></a>
-<span class="sourceLineNo">553</span>  void sanityCheck() throws IOException {<a name="line.553"></a>
-<span class="sourceLineNo">554</span>    // Duplicate so no side-effects<a name="line.554"></a>
-<span class="sourceLineNo">555</span>    ByteBuff dup = this.buf.duplicate().rewind();<a name="line.555"></a>
-<span class="sourceLineNo">556</span>    sanityCheckAssertion(BlockType.read(dup), blockType);<a name="line.556"></a>
-<span class="sourceLineNo">557</span><a name="line.557"></a>
-<span class="sourceLineNo">558</span>    sanityCheckAssertion(dup.getInt(), onDiskSizeWithoutHeader, "onDiskSizeWithoutHeader");<a name="line.558"></a>
-<span class="sourceLineNo">559</span><a name="line.559"></a>
-<span class="sourceLineNo">560</span>    sanityCheckAssertion(dup.getInt(), uncompressedSizeWithoutHeader,<a name="line.560"></a>
-<span class="sourceLineNo">561</span>        "uncompressedSizeWithoutHeader");<a name="line.561"></a>
-<span class="sourceLineNo">562</span><a name="line.562"></a>
-<span class="sourceLineNo">563</span>    sanityCheckAssertion(dup.getLong(), prevBlockOffset, "prevBlockOffset");<a name="line.563"></a>
-<span class="sourceLineNo">564</span>    if (this.fileContext.isUseHBaseChecksum()) {<a name="line.564"></a>
-<span class="sourceLineNo">565</span>      sanityCheckAssertion(dup.get(), this.fileContext.getChecksumType().getCode(), "checksumType");<a name="line.565"></a>
-<span class="sourceLineNo">566</span>      sanityCheckAssertion(dup.getInt(), this.fileContext.getBytesPerChecksum(),<a name="line.566"></a>
-<span class="sourceLineNo">567</span>          "bytesPerChecksum");<a name="line.567"></a>
-<span class="sourceLineNo">568</span>      sanityCheckAssertion(dup.getInt(), onDiskDataSizeWithHeader, "onDiskDataSizeWithHeader");<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>    int cksumBytes = totalChecksumBytes();<a name="line.571"></a>
-<span class="sourceLineNo">572</span>    int expectedBufLimit = onDiskDataSizeWithHeader + cksumBytes;<a name="line.572"></a>
-<span class="sourceLineNo">573</span>    if (dup.limit() != expectedBufLimit) {<a name="line.573"></a>
-<span class="sourceLineNo">574</span>      throw new AssertionError("Expected limit " + expectedBufLimit + ", got " + dup.limit());<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>    // We might optionally allocate HFILEBLOCK_HEADER_SIZE more bytes to read the next<a name="line.577"></a>
-<span class="sourceLineNo">578</span>    // block's header, so there are two sensible values for buffer capacity.<a name="line.578"></a>
-<span class="sourceLineNo">579</span>    int hdrSize = headerSize();<a name="line.579"></a>
-<span class="sourceLineNo">580</span>    if (dup.capacity() != expectedBufLimit &amp;&amp; dup.capacity() != expectedBufLimit + hdrSize) {<a name="line.580"></a>
-<span class="sourceLineNo">581</span>      throw new AssertionError("Invalid buffer capacity: " + dup.capacity() +<a name="line.581"></a>
-<span class="sourceLineNo">582</span>          ", expected " + expectedBufLimit + " or " + (expectedBufLimit + hdrSize));<a name="line.582"></a>
-<span class="sourceLineNo">583</span>    }<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>  @Override<a name="line.586"></a>
-<span class="sourceLineNo">587</span>  public String toString() {<a name="line.587"></a>
-<span class="sourceLineNo">588</span>    StringBuilder sb = new StringBuilder()<a name="line.588"></a>
-<span class="sourceLineNo">589</span>      .append("[")<a name="line.589"></a>
-<span class="sourceLineNo">590</span>      .append("blockType=").append(blockType)<a name="line.590"></a>
-<span class="sourceLineNo">591</span>      .append(", fileOffset=").append(offset)<a name="line.591"></a>
-<span class="sourceLineNo">592</span>      .append(", headerSize=").append(headerSize())<a name="line.592"></a>
-<span class="sourceLineNo">593</span>      .append(", onDiskSizeWithoutHeader=").append(onDiskSizeWithoutHeader)<a name="line.593"></a>
-<span class="sourceLineNo">594</span>      .append(", uncompressedSizeWithoutHeader=").append(uncompressedSizeWithoutHeader)<a name="line.594"></a>
-<span class="sourceLineNo">595</span>      .append(", prevBlockOffset=").append(prevBlockOffset)<a name="line.595"></a>
-<span class="sourceLineNo">596</span>      .append(", isUseHBaseChecksum=").append(fileContext.isUseHBaseChecksum());<a name="line.596"></a>
-<span class="sourceLineNo">597</span>    if (fileContext.isUseHBaseChecksum()) {<a name="line.597"></a>
-<span class="sourceLineNo">598</span>      sb.append(", checksumType=").append(ChecksumType.codeToType(this.buf.get(24)))<a name="line.598"></a>
-<span class="sourceLineNo">599</span>        .append(", bytesPerChecksum=").append(this.buf.getInt(24 + 1))<a name="line.599"></a>
-<span class="sourceLineNo">600</span>        .append(", onDiskDataSizeWithHeader=").append(onDiskDataSizeWithHeader);<a name="line.600"></a>
-<span class="sourceLineNo">601</span>    } else {<a name="line.601"></a>
-<span class="sourceLineNo">602</span>      sb.append(", onDiskDataSizeWithHeader=").append(onDiskDataSizeWithHeader)<a name="line.602"></a>
-<span class="sourceLineNo">603</span>        .append("(").append(onDiskSizeWithoutHeader)<a name="line.603"></a>
-<span class="sourceLineNo">604</span>        .append("+").append(HConstants.HFILEBLOCK_HEADER_SIZE_NO_CHECKSUM).append(")");<a name="line.604"></a>
-<span class="sourceLineNo">605</span>    }<a name="line.605"></a>
-<span class="sourceLineNo">606</span>    String dataBegin = null;<a name="line.606"></a>
-<span class="sourceLineNo">607</span>    if (buf.hasArray()) {<a name="line.607"></a>
-<span class="sourceLineNo">608</span>      dataBegin = Bytes.toStringBinary(buf.array(), buf.arrayOffset() + headerSize(),<a name="line.608"></a>
-<span class="sourceLineNo">609</span>          Math.min(32, buf.limit() - buf.arrayOffset() - headerSize()));<a name="line.609"></a>
-<span class="sourceLineNo">610</span>    } else {<a name="line.610"></a>
-<span class="sourceLineNo">611</span>      ByteBuff bufWithoutHeader = getBufferWithoutHeader();<a name="line.611"></a>
-<span class="sourceLineNo">612</span>      byte[] dataBeginBytes = new byte[Math.min(32,<a name="line.612"></a>
-<span class="sourceLineNo">613</span>          bufWithoutHeader.limit() - bufWithoutHeader.position())];<a name="line.613"></a>
-<span class="sourceLineNo">614</span>      bufWithoutHeader.get(dataBeginBytes);<a name="line.614"></a>
-<span class="sourceLineNo">615</span>      dataBegin = Bytes.toStringBinary(dataBeginBytes);<a name="line.615"></a>
-<span class="sourceLineNo">616</span>    }<a name="line.616"></a>
-<span class="sourceLineNo">617</span>    sb.append(", getOnDiskSizeWithHeader=").append(getOnDiskSizeWithHeader())<a name="line.617"></a>
-<span class="sourceLineNo">618</span>      .append(", totalChecksumBytes=").append(totalChecksumBytes())<a name="line.618"></a>
-<span class="sourceLineNo">619</span>      .append(", isUnpacked=").append(isUnpacked())<a name="line.619"></a>
-<span class="sourceLineNo">620</span>      .append(", buf=[").append(buf).append("]")<a name="line.620"></a>
-<span class="sourceLineNo">621</span>      .append(", dataBeginsWith=").append(dataBegin)<a name="line.621"></a>
-<span class="sourceLineNo">622</span>      .append(", fileContext=").append(fileContext)<a name="line.622"></a>
-<span class="sourceLineNo">623</span>      .append("]");<a name="line.623"></a>
-<span class="sourceLineNo">624</span>    return sb.toString();<a name="line.624"></a>
-<span class="sourceLineNo">625</span>  }<a name="line.625"></a>
-<span class="sourceLineNo">626</span><a name="line.626"></a>
-<span class="sourceLineNo">627</span>  /**<a name="line.627"></a>
-<span class="sourceLineNo">628</span>   * Retrieves the decompressed/decrypted view of this block. An encoded block remains in its<a name="line.628"></a>
-<span class="sourceLineNo">629</span>   * encoded structure. Internal structures are shared between instances where applicable.<a name="line.629"></a>
-<span class="sourceLineNo">630</span>   */<a name="line.630"></a>
-<span class="sourceLineNo">631</span>  HFileBlock unpack(HFileContext fileContext, FSReader reader) throws IOException {<a name="line.631"></a>
-<span class="sourceLineNo">632</span>    if (!fileContext.isCompressedOrEncrypted()) {<a name="line.632"></a>
-<span class="sourceLineNo">633</span>      // TODO: cannot use our own fileContext here because HFileBlock(ByteBuffer, boolean),<a name="line.633"></a>
-<span class="sourceLineNo">634</span>      // which is used for block serialization to L2 cache, does not preserve encoding and<a name="line.634"></a>
-<span class="sourceLineNo">635</span>      // encryption details.<a name="line.635"></a>
-<span class="sourceLineNo">636</span>      return this;<a name="line.636"></a>
-<span class="sourceLineNo">637</span>    }<a name="line.637"></a>
-<span class="sourceLineNo">638</span><a name="line.638"></a>
-<span class="sourceLineNo">639</span>    HFileBlock unpacked = new HFileBlock(this);<a name="line.639"></a>
-<span class="sourceLineNo">640</span>    unpacked.allocateBuffer(); // allocates space for the decompressed block<a name="line.640"></a>
-<span class="sourceLineNo">641</span><a name="line.641"></a>
-<span class="sourceLineNo">642</span>    HFileBlockDecodingContext ctx = blockType == BlockType.ENCODED_DATA ?<a name="line.642"></a>
-<span class="sourceLineNo">643</span>      reader.getBlockDecodingContext() : reader.getDefaultBlockDecodingContext();<a name="line.643"></a>
-<span class="sourceLineNo">644</span><a name="line.644"></a>
-<span class="sourceLineNo">645</span>    ByteBuff dup = this.buf.duplicate();<a name="line.645"></a>
-<span class="sourceLineNo">646</span>    dup.position(this.headerSize());<a name="line.646"></a>
-<span class="sourceLineNo">647</span>    dup = dup.slice();<a name="line.647"></a>
-<span class="sourceLineNo">648</span>    ctx.prepareDecoding(unpacked.getOnDiskSizeWithoutHeader(),<a name="line.648"></a>
-<span class="sourceLineNo">649</span>      unpacked.getUncompressedSizeWithoutHeader(), unpacked.getBufferWithoutHeader(),<a name="line.649"></a>
-<span class="sourceLineNo">650</span>      dup);<a name="line.650"></a>
-<span class="sourceLineNo">651</span>    return unpacked;<a name="line.651"></a>
-<span class="sourceLineNo">652</span>  }<a name="line.652"></a>
-<span class="sourceLineNo">653</span><a name="line.653"></a>
-<span class="sourceLineNo">654</span>  /**<a name="line.654"></a>
-<span class="sourceLineNo">655</span>   * Always allocates a new buffer of the correct size. Copies header bytes<a name="line.655"></a>
-<span class="sourceLineNo">656</span>   * from the existing buffer. Does not change header fields.<a name="line.656"></a>
-<span class="sourceLineNo">657</span>   * Reserve room to keep checksum bytes too.<a name="line.657"></a>
-<span class="sourceLineNo">658</span>   */<a name="line.658"></a>
-<span class="sourceLineNo">659</span>  private void allocateBuffer() {<a name="line.659"></a>
-<span class="sourceLineNo">660</span>    int cksumBytes = totalChecksumBytes();<a name="line.660"></a>
-<span class="sourceLineNo">661</span>    int headerSize = headerSize();<a name="line.661"></a>
-<span class="sourceLineNo">662</span>    int capacityNeeded = headerSize + uncompressedSizeWithoutHeader + cksumBytes;<a name="line.662"></a>
-<span class="sourceLineNo">663</span><a name="line.663"></a>
-<span class="sourceLineNo">664</span>    // TODO we need consider allocating offheap here?<a name="line.664"></a>
-<span class="sourceLineNo">665</span>    ByteBuffer newBuf = ByteBuffer.allocate(capacityNeeded);<a name="line.665"></a>
-<span class="sourceLineNo">666</span><a name="line.666"></a>
-<span class="sourceLineNo">667</span>    // Copy header bytes into newBuf.<a name="line.667"></a>
-<span class="sourceLineNo">668</span>    // newBuf is HBB so no issue in calling array()<a name="line.668"></a>
-<span class="sourceLineNo">669</span>    buf.position(0);<a name="line.669"></a>
-<span class="sourceLineNo">670</span>    buf.get(newBuf.array(), newBuf.arrayOffset(), headerSize);<a name="line.670"></a>
-<span class="sourceLineNo">671</span><a name="line.671"></a>
-<span class="sourceLineNo">672</span>    buf = new SingleByteBuff(newBuf);<a name="line.672"></a>
-<span class="sourceLineNo">673</span>    // set limit to exclude next block's header<a name="line.673"></a>
-<span class="sourceLineNo">674</span>    buf.limit(headerSize + uncompressedSizeWithoutHeader + cksumBytes);<a name="line.674"></a>
-<span class="sourceLineNo">675</span>  }<a name="line.675"></a>
-<span class="sourceLineNo">676</span><a name="line.676"></a>
-<span class="sourceLineNo">677</span>  /**<a name="line.677"></a>
-<span class="sourceLineNo">678</span>   * Return true when this block's buffer has been unpacked, false otherwise. Note this is a<a name="line.678"></a>
-<span class="sourceLineNo">679</span>   * calculated heuristic, not tracked attribute of the block.<a name="line.679"></a>
-<span class="sourceLineNo">680</span>   */<a name="line.680"></a>
-<span class="sourceLineNo">681</span>  public boolean isUnpacked() {<a name="line.681"></a>
-<span class="sourceLineNo">682</span>    final int cksumBytes = totalChecksumBytes();<a name="line.682"></a>
-<span class="sourceLineNo">683</span>    final int headerSize = headerSize();<a name="line.683"></a>
-<span class="sourceLineNo">684</span>    final int expectedCapacity = headerSize + uncompressedSizeWithoutHeader + cksumBytes;<a name="line.684"></a>
-<span class="sourceLineNo">685</span>    final int bufCapacity = buf.capacity();<a name="line.685"></a>
-<span class="sourceLineNo">686</span>    return bufCapacity == expectedCapacity || bufCapacity == expectedCapacity + headerSize;<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>  /** An additional sanity-check in case no compression or encryption is being used. */<a name="line.689"></a>
-<span class="sourceLineNo">690</span>  @VisibleForTesting<a name="line.690"></a>
-<span class="sourceLineNo">691</span>  void sanityCheckUncompressedSize() throws IOException {<a name="line.691"></a>
-<span class="sourceLineNo">692</span>    if (onDiskSizeWithoutHeader != uncompressedSizeWithoutHeader + totalChecksumBytes()) {<a name="line.692"></a>
-<span class="sourceLineNo">693</span>      throw new IOException("Using no compression but "<a name="line.693"></a>
-<span class="sourceLineNo">694</span>          + "onDiskSizeWithoutHeader=" + onDiskSizeWithoutHeader + ", "<a name="line.694"></a>
-<span class="sourceLineNo">695</span>          + "uncompressedSizeWithoutHeader=" + uncompressedSizeWithoutHeader<a name="line.695"></a>
-<span class="sourceLineNo">696</span>          + ", numChecksumbytes=" + totalChecksumBytes());<a name="line.696"></a>
-<span class="sourceLineNo">697</span>    }<a name="line.697"></a>
-<span class="sourceLineNo">698</span>  }<a name="line.698"></a>
-<span class="sourceLineNo">699</span><a name="line.699"></a>
-<span class="sourceLineNo">700</span>  /**<a name="line.700"></a>
-<span class="sourceLineNo">701</span>   * Cannot be {@link #UNSET}. Must be a legitimate value. Used re-making the {@link BlockCacheKey} when<a name="line.701"></a>
-<span class="sourceLineNo">702</span>   * block is returned to the cache.<a name="line.702"></a>
-<span class="sourceLineNo">703</span>   * @return the offset of this block in the file it was read from<a name="line.703"></a>
-<span class="sourceLineNo">704</span>   */<a name="line.704"></a>
-<span class="sourceLineNo">705</span>  long getOffset() {<a name="line.705"></a>
-<span class="sourceLineNo">706</span>    if (offset &lt; 0) {<a name="line.706"></a>
-<span class="sourceLineNo">707</span>      throw new IllegalStateException("HFile block offset not initialized properly");<a name="line.707"></a>
-<span class="sourceLineNo">708</span>    }<a name="line.708"></a>
-<span class="sourceLineNo">709</span>    return offset;<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>   * @return a byte stream reading the data + checksum of this block<a name="line.713"></a>
-<span class="sourceLineNo">714</span>   */<a name="line.714"></a>
-<span class="sourceLineNo">715</span>  DataInputStream getByteStream() {<a name="line.715"></a>
-<span class="sourceLineNo">716</span>    ByteBuff dup = this.buf.duplicate();<a name="line.716"></a>
-<span class="sourceLineNo">717</span>    dup.position(this.headerSize());<a name="line.717"></a>
-<span class="sourceLineNo">718</span>    return new DataInputStream(new ByteBuffInputStream(dup));<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>
-<span class="sourceLineNo">721</span>  @Override<a name="line.721"></a>
-<span class="sourceLineNo">722</span>  public long heapSize() {<a name="line.722"></a>
-<span class="sourceLineNo">723</span>    long size = ClassSize.align(<a name="line.723"></a>
-<span class="sourceLineNo">724</span>        ClassSize.OBJECT +<a name="line.724"></a>
-<span class="sourceLineNo">725</span>        // Block type, multi byte buffer, MemoryType and meta references<a name="line.725"></a>
-<span class="sourceLineNo">726</span>        4 * ClassSize.REFERENCE +<a name="line.726"></a>
-<span class="sourceLineNo">727</span>        // On-disk size, uncompressed size, and next block's on-disk size<a name="line.727"></a>
-<span class="sourceLineNo">728</span>        // bytePerChecksum and onDiskDataSize<a name="line.728"></a>
-<span class="sourceLineNo">729</span>        4 * Bytes.SIZEOF_INT +<a name="line.729"></a>
-<span class="sourceLineNo">730</span>        // This and previous block offset<a name="line.730"></a>
-<span class="sourceLineNo">731</span>        2 * Bytes.SIZEOF_LONG +<a name="line.731"></a>
-<span class="sourceLineNo">732</span>        // Heap size of the meta object. meta will be always not null.<a name="line.732"></a>
-<span class="sourceLineNo">733</span>        fileContext.heapSize()<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>    if (buf != null) {<a name="line.736"></a>
-<span class="sourceLineNo">737</span>      // Deep overhead of the byte buffer. Needs to be aligned separately.<a name="line.737"></a>
-<span class="sourceLineNo">738</span>      size += ClassSize.align(buf.capacity() + MULTI_BYTE_BUFFER_HEAP_SIZE);<a name="line.738"></a>
-<span class="sourceLineNo">739</span>    }<a name="line.739"></a>
-<span class="sourceLineNo">740</span><a name="line.740"></a>
-<span class="sourceLineNo">741</span>    return ClassSize.align(size);<a name="line.741"></a>
-<span class="sourceLineNo">742</span>  }<a name="line.742"></a>
-<span class="sourceLineNo">743</span><a name="line.743"></a>
-<span class="sourceLineNo">744</span>  /**<a name="line.744"></a>
-<span class="sourceLineNo">745</span>   * Read from an input stream at least &lt;code&gt;necessaryLen&lt;/code&gt; and if possible,<a name="line.745"></a>
-<span class="sourceLineNo">746</span>   * &lt;code&gt;extraLen&lt;/code&gt; also if available. Analogous to<a name="line.746"></a>
-<span class="sourceLineNo">747</span>   * {@link IOUtils#readFully(InputStream, byte[], int, int)}, but specifies a<a name="line.747"></a>
-<span class="sourceLineNo">748</span>   * number of "extra" bytes to also optionally read.<a name="line.748"></a>
-<span class="sourceLineNo">749</span>   *<a name="line.749"></a>
-<span class="sourceLineNo">750</span>   * @param in the input stream to read from<a name="line.750"></a>
-<span class="sourceLineNo">751</span>   * @param buf the buffer to read into<a name="line.751"></a>
-<span class="sourceLineNo">752</span>   * @param bufOffset the destination offset in the buffer<a name="line.752"></a>
-<span class="sourceLineNo">753</span>   * @param necessaryLen the number of bytes that are absolutely necessary to read<a name="line.753"></a>
-<span class="sourceLineNo">754</span>   * @param extraLen the number of extra bytes that would be nice to read<a name="line.754"></a>
-<span class="sourceLineNo">755</span>   * @return true if succeeded reading the extra bytes<a name="line.755"></a>
-<span class="sourceLineNo">756</span>   * @throws IOException if failed to read the necessary bytes<a name="line.756"></a>
-<span class="sourceLineNo">757</span>   */<a name="line.757"></a>
-<span class="sourceLineNo">758</span>  static boolean readWithExtra(InputStream in, byte[] buf,<a name="line.758"></a>
-<span class="sourceLineNo">759</span>      int bufOffset, int necessaryLen, int extraLen) throws IOException {<a name="line.759"></a>
-<span class="sourceLineNo">760</span>    int bytesRemaining = necessaryLen + extraLen;<a name="line.760"></a>
-<span class="sourceLineNo">761</span>    while (bytesRemaining &gt; 0) {<a name="line.761"></a>
-<span class="sourceLineNo">762</span>      int ret = in.read(buf, bufOffset, bytesRemaining);<a name="line.762"></a>
-<span class="sourceLineNo">763</span>      if (ret == -1 &amp;&amp; bytesRemaining &lt;= extraLen) {<a name="line.763"></a>
-<span class="sourceLineNo">764</span>        // We could not read the "extra data", but that is OK.<a name="line.764"></a>
-<span class="sourceLineNo">765</span>        break;<a name="line.765"></a>
-<span class="sourceLineNo">766</span>      }<a name="line.766"></a>
-<span class="sourceLineNo">767</span>      if (ret &lt; 0) {<a name="line.767"></a>
-<span class="sourceLineNo">768</span>        throw new IOException("Premature EOF from inputStream (read "<a name="line.768"></a>
-<span class="sourceLineNo">769</span>            + "returned " + ret + ", was trying to read " + necessaryLen<a name="line.769"></a>
-<span class="sourceLineNo">770</span>            + " necessary bytes and " + extraLen + " extra bytes, "<a name="line.770"></a>
-<span class="sourceLineNo">771</span>            + "successfully read "<a name="line.771"></a>
-<span class="sourceLineNo">772</span>            + (necessaryLen + extraLen - bytesRemaining));<a name="line.772"></a>
-<span class="sourceLineNo">773</span>      }<a name="line.773"></a>
-<span class="sourceLineNo">774</span>      bufOffset += ret;<a name="line.774"></a>
-<span class="sourceLineNo">775</span>      bytesRemaining -= ret;<a name="line.775"></a>
-<span class="sourceLineNo">776</span>    }<a name="line.776"></a>
-<span class="sourceLineNo">777</span>    return bytesRemaining &lt;= 0;<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>   * Read from an input stream at least &lt;code&gt;necessaryLen&lt;/code&gt; and if possible,<a name="line.781"></a>
-<span class="sourceLineNo">782</span>   * &lt;code&gt;extraLen&lt;/code&gt; also if available. Analogous to<a name="line.782"></a>
-<span class="sourceLineNo">783</span>   * {@link IOUtils#readFully(InputStream, byte[], int, int)}, but uses<a name="line.783"></a>
-<span class="sourceLineNo">784</span>   * positional read and specifies a number of "extra" bytes that would be<a name="line.784"></a>
-<span class="sourceLineNo">785</span>   * desirable but not absolutely necessary to read.<a name="line.785"></a>
-<span class="sourceLineNo">786</span>   *<a name="line.786"></a>
-<span class="sourceLineNo">787</span>   * @param in the input stream to read from<a name="line.787"></a>
-<span class="sourceLineNo">788</span>   * @param position the position within the stream from which to start reading<a name="line.788"></a>
-<span class="sourceLineNo">789</span>   * @param buf the buffer to read into<a name="line.789"></a>
-<span class="sourceLineNo">790</span>   * @param bufOffset the destination offset in the buffer<a name="line.790"></a>
-<span class="sourceLineNo">791</span>   * @param necessaryLen the number of bytes that are absolutely necessary to<a name="line.791"></a>
-<span class="sourceLineNo">792</span>   *     read<a name="line.792"></a>
-<span class="sourceLineNo">793</span>   * @param extraLen the number of extra bytes that would be nice to read<a name="line.793"></a>
-<span class="sourceLineNo">794</span>   * @return true if and only if extraLen is &gt; 0 and reading those extra bytes<a name="line.794"></a>
-<span class="sourceLineNo">795</span>   *     was successful<a name="line.795"></a>
-<span class="sourceLineNo">796</span>   * @throws IOException if failed to read the necessary bytes<a name="line.796"></a>
-<span class="sourceLineNo">797</span>   */<a name="line.797"></a>
-<span class="sourceLineNo">798</span>  @VisibleForTesting<a name="line.798"></a>
-<span class="sourceLineNo">799</span>  static boolean positionalReadWithExtra(FSDataInputStream in,<a name="line.799"></a>
-<span class="sourceLineNo">800</span>      long position, byte[] buf, int bufOffset, int necessaryLen, int extraLen)<a name="line.800"></a>
-<span class="sourceLineNo">801</span>      throws IOException {<a name="line.801"></a>
-<span class="sourceLineNo">802</span>    int bytesRemaining = necessaryLen + extraLen;<a name="line.802"></a>
-<span class="sourceLineNo">803</span>    int bytesRead = 0;<a name="line.803"></a>
-<span class="sourceLineNo">804</span>    while (bytesRead &lt; necessaryLen) {<a name="line.804"></a>
-<span class="sourceLineNo">805</span>      int ret = in.read(position, buf, bufOffset, bytesRemaining);<a name="line.805"></a>
-<span class="sourceLineNo">806</span>      if (ret &lt; 0) {<a name="line.806"></a>
-<span class="sourceLineNo">807</span>        throw new IOException("Premature EOF from inputStream (positional read "<a name="line.807"></a>
-<span class="sourceLineNo">808</span>            + "returned " + ret + ", was trying to read " + necessaryLen<a name="line.808"></a>
-<span class="sourceLineNo">809</span>            + " necessary bytes and " + extraLen + " extra bytes, "<a name="line.809"></a>
-<span class="sourceLineNo">810</span>            + "successfully read " + bytesRead);<a name="line.810"></a>
-<span class="sourceLineNo">811</span>      }<a name="line.811"></a>
-<span class="sourceLineNo">812</span>      position += ret;<a name="line.812"></a>
-<span class="sourceLineNo">813</span>      bufOffset += ret;<a name="line.813"></a>
-<span class="sourceLineNo">814</span>      bytesRemaining -= ret;<a name="line.814"></a>
-<span class="sourceLineNo">815</span>      bytesRead += ret;<a name="line.815"></a>
-<span class="sourceLineNo">816</span>    }<a name="line.816"></a>
-<span class="sourceLineNo">817</span>    return bytesRead != necessaryLen &amp;&amp; bytesRemaining &lt;= 0;<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>   * Unified version 2 {@link HFile} block writer. The intended usage pattern<a name="line.821"></a>
-<span class="sourceLineNo">822</span>   * is as follows:<a name="line.822"></a>
-<span class="sourceLineNo">823</span>   * &lt;ol&gt;<a name="line.823"></a>
-<span class="sourceLineNo">824</span>   * &lt;li&gt;Construct an {@link HFileBlock.Writer}, providing a compression algorithm.<a name="line.824"></a>
-<span class="sourceLineNo">825</span>   * &lt;li&gt;Call {@link Writer#startWriting} and get a data stream to write to.<a name="line.825"></a>
-<span class="sourceLineNo">826</span>   * &lt;li&gt;Write your data into the stream.<a name="line.826"></a>
-<span class="sourceLineNo">827</span>   * &lt;li&gt;Call Writer#writeHeaderAndData(FSDataOutputStream) as many times as you need to.<a name="line.827"></a>
-<span class="sourceLineNo">828</span>   * store the serialized block into an external stream.<a name="line.828"></a>
-<span class="sourceLineNo">829</span>   * &lt;li&gt;Repeat to write more blocks.<a name="line.829"></a>
-<span class="sourceLineNo">830</span>   * &lt;/ol&gt;<a name="line.830"></a>
-<span class="sourceLineNo">831</span>   * &lt;p&gt;<a name="line.831"></a>
-<span class="sourceLineNo">832</span>   */<a name="line.832"></a>
-<span class="sourceLineNo">833</span>  static class Writer {<a name="line.833"></a>
-<span class="sourceLineNo">834</span>    private enum State {<a name="line.834"></a>
-<span class="sourceLineNo">835</span>      INIT,<a name="line.835"></a>
-<span class="sourceLineNo">836</span>      WRITING,<a name="line.836"></a>
-<span class="sourceLineNo">837</span>      BLOCK_READY<a name="line.837"></a>
-<span class="sourceLineNo">838</span>    }<a name="line.838"></a>
-<span class="sourceLineNo">839</span><a name="line.839"></a>
-<span class="sourceLineNo">840</span>    /** Writer state. Used to ensure the correct usage protocol. */<a name="line.840"></a>
-<span class="sourceLineNo">841</span>    private State state = State.INIT;<a name="line.841"></a>
-<span class="sourceLineNo">842</span><a name="line.842"></a>
-<span class="sourceLineNo">843</span>    /** Data block encoder used for data blocks */<a name="line.843"></a>
-<span class="sourceLineNo">844</span>    private final HFileDataBlockEncoder dataBlockEncoder;<a name="line.844"></a>
-<span class="sourceLineNo">845</span><a name="line.845"></a>
-<span class="sourceLineNo">846</span>    private HFileBlockEncodingContext dataBlockEncodingCtx;<a name="line.846"></a>
+<span class="sourceLineNo">328</span>   *<a name="line.328"></a>
+<span class="sourceLineNo">329</span>   * &lt;p&gt;TODO: The caller presumes no checksumming<a name="line.329"></a>
+<span class="sourceLineNo">330</span>   * required of this block instance since going into cache; checksum already verified on<a name="line.330"></a>
+<span class="sourceLineNo">331</span>   * underlying block data pulled in from filesystem. Is that correct? What if cache is SSD?<a name="line.331"></a>
+<span class="sourceLineNo">332</span>   *<a name="line.332"></a>
+<span class="sourceLineNo">333</span>   * @param blockType the type of this block, see {@link BlockType}<a name="line.333"></a>
+<span class="sourceLineNo">334</span>   * @param onDiskSizeWithoutHeader see {@link #onDiskSizeWithoutHeader}<a name="line.334"></a>
+<span class="sourceLineNo">335</span>   * @param uncompressedSizeWithoutHeader see {@link #uncompressedSizeWithoutHeader}<a name="line.335"></a>
+<span class="sourceLineNo">336</span>   * @param prevBlockOffset see {@link #prevBlockOffset}<a name="line.336"></a>
+<span class="sourceLineNo">337</span>   * @param b block header ({@link HConstants#HFILEBLOCK_HEADER_SIZE} bytes)<a name="line.337"></a>
+<span class="sourceLineNo">338</span>   * @param fillHeader when true, write the first 4 header fields into passed buffer.<a name="line.338"></a>
+<span class="sourceLineNo">339</span>   * @param offset the file offset the block was read from<a name="line.339"></a>
+<span class="sourceLineNo">340</span>   * @param onDiskDataSizeWithHeader see {@link #onDiskDataSizeWithHeader}<a name="line.340"></a>
+<span class="sourceLineNo">341</span>   * @param fileContext HFile meta data<a name="line.341"></a>
+<span class="sourceLineNo">342</span>   */<a name="line.342"></a>
+<span class="sourceLineNo">343</span>  @VisibleForTesting<a name="line.343"></a>
+<span class="sourceLineNo">344</span>  public HFileBlock(BlockType blockType, int onDiskSizeWithoutHeader,<a name="line.344"></a>
+<span class="sourceLineNo">345</span>      int uncompressedSizeWithoutHeader, long prevBlockOffset, ByteBuffer b, boolean fillHeader,<a name="line.345"></a>
+<span class="sourceLineNo">346</span>      long offset, final int nextBlockOnDiskSize, int onDiskDataSizeWithHeader,<a name="line.346"></a>
+<span class="sourceLineNo">347</span>      HFileContext fileContext) {<a name="line.347"></a>
+<span class="sourceLineNo">348</span>    init(blockType, onDiskSizeWithoutHeader, uncompressedSizeWithoutHeader,<a name="line.348"></a>
+<span class="sourceLineNo">349</span>        prevBlockOffset, offset, onDiskDataSizeWithHeader, nextBlockOnDiskSize, fileContext);<a name="line.349"></a>
+<span class="sourceLineNo">350</span>    this.buf = new SingleByteBuff(b);<a name="line.350"></a>
+<span class="sourceLineNo">351</span>    if (fillHeader) {<a name="line.351"></a>
+<span class="sourceLineNo">352</span>      overwriteHeader();<a name="line.352"></a>
+<span class="sourceLineNo">353</span>    }<a name="line.353"></a>
+<span class="sourceLineNo">354</span>    this.buf.rewind();<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">357</span>  /**<a name="line.357"></a>
+<span class="sourceLineNo">358</span>   * Creates a block from an existing buffer starting with a header. Rewinds<a name="line.358"></a>
+<span class="sourceLineNo">359</span>   * and takes ownership of the buffer. By definition of rewind, ignores the<a name="line.359"></a>
+<span class="sourceLineNo">360</span>   * buffer position, but if you slice the buffer beforehand, it will rewind<a name="line.360"></a>
+<span class="sourceLineNo">361</span>   * to that point.<a name="line.361"></a>
+<span class="sourceLineNo">362</span>   * @param buf Has header, content, and trailing checksums if present.<a name="line.362"></a>
+<span class="sourceLineNo">363</span>   */<a name="line.363"></a>
+<span class="sourceLineNo">364</span>  HFileBlock(ByteBuff buf, boolean usesHBaseChecksum, MemoryType memType, final long offset,<a name="line.364"></a>
+<span class="sourceLineNo">365</span>      final int nextBlockOnDiskSize, HFileContext fileContext) throws IOException {<a name="line.365"></a>
+<span class="sourceLineNo">366</span>    buf.rewind();<a name="line.366"></a>
+<span class="sourceLineNo">367</span>    final BlockType blockType = BlockType.read(buf);<a name="line.367"></a>
+<span class="sourceLineNo">368</span>    final int onDiskSizeWithoutHeader = buf.getInt(Header.ON_DISK_SIZE_WITHOUT_HEADER_INDEX);<a name="line.368"></a>
+<span class="sourceLineNo">369</span>    final int uncompressedSizeWithoutHeader =<a name="line.369"></a>
+<span class="sourceLineNo">370</span>        buf.getInt(Header.UNCOMPRESSED_SIZE_WITHOUT_HEADER_INDEX);<a name="line.370"></a>
+<span class="sourceLineNo">371</span>    final long prevBlockOffset = buf.getLong(Header.PREV_BLOCK_OFFSET_INDEX);<a name="line.371"></a>
+<span class="sourceLineNo">372</span>    // This constructor is called when we deserialize a block from cache and when we read a block in<a name="line.372"></a>
+<span class="sourceLineNo">373</span>    // from the fs. fileCache is null when deserialized from cache so need to make up one.<a name="line.373"></a>
+<span class="sourceLineNo">374</span>    HFileContextBuilder fileContextBuilder = fileContext != null?<a name="line.374"></a>
+<span class="sourceLineNo">375</span>        new HFileContextBuilder(fileContext): new HFileContextBuilder();<a name="line.375"></a>
+<span class="sourceLineNo">376</span>    fileContextBuilder.withHBaseCheckSum(usesHBaseChecksum);<a name="line.376"></a>
+<span class="sourceLineNo">377</span>    int onDiskDataSizeWithHeader;<a name="line.377"></a>
+<span class="sourceLineNo">378</span>    if (usesHBaseChecksum) {<a name="line.378"></a>
+<span class="sourceLineNo">379</span>      byte checksumType = buf.get(Header.CHECKSUM_TYPE_INDEX);<a name="line.379"></a>
+<span class="sourceLineNo">380</span>      int bytesPerChecksum = buf.getInt(Header.BYTES_PER_CHECKSUM_INDEX);<a name="line.380"></a>
+<span class="sourceLineNo">381</span>      onDiskDataSizeWithHeader = buf.getInt(Header.ON_DISK_DATA_SIZE_WITH_HEADER_INDEX);<a name="line.381"></a>
+<span class="sourceLineNo">382</span>      // Use the checksum type and bytes per checksum from header, not from filecontext.<a name="line.382"></a>
+<span class="sourceLineNo">383</span>      fileContextBuilder.withChecksumType(ChecksumType.codeToType(checksumType));<a name="line.383"></a>
+<span class="sourceLineNo">384</span>      fileContextBuilder.withBytesPerCheckSum(bytesPerChecksum);<a name="line.384"></a>
+<span class="sourceLineNo">385</span>    } else {<a name="line.385"></a>
+<span class="sourceLineNo">386</span>      fileContextBuilder.withChecksumType(ChecksumType.NULL);<a name="line.386"></a>
+<span class="sourceLineNo">387</span>      fileContextBuilder.withBytesPerCheckSum(0);<a name="line.387"></a>
+<span class="sourceLineNo">388</span>      // Need to fix onDiskDataSizeWithHeader; there are not checksums after-block-data<a name="line.388"></a>
+<span class="sourceLineNo">389</span>      onDiskDataSizeWithHeader = onDiskSizeWithoutHeader + headerSize(usesHBaseChecksum);<a name="line.389"></a>
+<span class="sourceLineNo">390</span>    }<a name="line.390"></a>
+<span class="sourceLineNo">391</span>    fileContext = fileContextBuilder.build();<a name="line.391"></a>
+<span class="sourceLineNo">392</span>    assert usesHBaseChecksum == fileContext.isUseHBaseChecksum();<a name="line.392"></a>
+<span class="sourceLineNo">393</span>    init(blockType, onDiskSizeWithoutHeader, uncompressedSizeWithoutHeader,<a name="line.393"></a>
+<span class="sourceLineNo">394</span>        prevBlockOffset, offset, onDiskDataSizeWithHeader, nextBlockOnDiskSize, fileContext);<a name="line.394"></a>
+<span class="sourceLineNo">395</span>    this.memType = memType;<a name="line.395"></a>
+<span class="sourceLineNo">396</span>    this.offset = offset;<a name="line.396"></a>
+<span class="sourceLineNo">397</span>    this.buf = buf;<a name="line.397"></a>
+<span class="sourceLineNo">398</span>    this.buf.rewind();<a name="line.398"></a>
+<span class="sourceLineNo">399</span>  }<a name="line.399"></a>
+<span class="sourceLineNo">400</span><a name="line.400"></a>
+<span class="sourceLineNo">401</span>  /**<a name="line.401"></a>
+<span class="sourceLineNo">402</span>   * Called from constructors.<a name="line.402"></a>
+<span class="sourceLineNo">403</span>   */<a name="line.403"></a>
+<span class="sourceLineNo">404</span>  private void init(BlockType blockType, int onDiskSizeWithoutHeader,<a name="line.404"></a>
+<span class="sourceLineNo">405</span>      int uncompressedSizeWithoutHeader, long prevBlockOffset,<a name="line.405"></a>
+<span class="sourceLineNo">406</span>      long offset, int onDiskDataSizeWithHeader, final int nextBlockOnDiskSize,<a name="line.406"></a>
+<span class="sourceLineNo">407</span>      HFileContext fileContext) {<a name="line.407"></a>
+<span class="sourceLineNo">408</span>    this.blockType = blockType;<a name="line.408"></a>
+<span class="sourceLineNo">409</span>    this.onDiskSizeWithoutHeader = onDiskSizeWithoutHeader;<a name="line.409"></a>
+<span class="sourceLineNo">410</span>    this.uncompressedSizeWithoutHeader = uncompressedSizeWithoutHeader;<a name="line.410"></a>
+<span class="sourceLineNo">411</span>    this.prevBlockOffset = prevBlockOffset;<a name="line.411"></a>
+<span class="sourceLineNo">412</span>    this.offset = offset;<a name="line.412"></a>
+<span class="sourceLineNo">413</span>    this.onDiskDataSizeWithHeader = onDiskDataSizeWithHeader;<a name="line.413"></a>
+<span class="sourceLineNo">414</span>    this.nextBlockOnDiskSize = nextBlockOnDiskSize;<a name="line.414"></a>
+<span class="sourceLineNo">415</span>    this.fileContext = fileContext;<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">418</span>  /**<a name="line.418"></a>
+<span class="sourceLineNo">419</span>   * Parse total on disk size including header and checksum.<a name="line.419"></a>
+<span class="sourceLineNo">420</span>   * @param headerBuf Header ByteBuffer. Presumed exact size of header.<a name="line.420"></a>
+<span class="sourceLineNo">421</span>   * @param verifyChecksum true if checksum verification is in use.<a name="line.421"></a>
+<span class="sourceLineNo">422</span>   * @return Size of the block with header included.<a name="line.422"></a>
+<span class="sourceLineNo">423</span>   */<a name="line.423"></a>
+<span class="sourceLineNo">424</span>  private static int getOnDiskSizeWithHeader(final ByteBuffer headerBuf,<a name="line.424"></a>
+<span class="sourceLineNo">425</span>      boolean verifyChecksum) {<a name="line.425"></a>
+<span class="sourceLineNo">426</span>    return headerBuf.getInt(Header.ON_DISK_SIZE_WITHOUT_HEADER_INDEX) +<a name="line.426"></a>
+<span class="sourceLineNo">427</span>      headerSize(verifyChecksum);<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>   * @return the on-disk size of the next block (including the header size and any checksums if<a name="line.431"></a>
+<span class="sourceLineNo">432</span>   * present) read by peeking into the next block's header; use as a hint when doing<a name="line.432"></a>
+<span class="sourceLineNo">433</span>   * a read of the next block when scanning or running over a file.<a name="line.433"></a>
+<span class="sourceLineNo">434</span>   */<a name="line.434"></a>
+<span class="sourceLineNo">435</span>  int getNextBlockOnDiskSize() {<a name="line.435"></a>
+<span class="sourceLineNo">436</span>    return nextBlockOnDiskSize;<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>  @Override<a name="line.439"></a>
+<span class="sourceLineNo">440</span>  public BlockType getBlockType() {<a name="line.440"></a>
+<span class="sourceLineNo">441</span>    return blockType;<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>  /** @return get data block encoding id that was used to encode this block */<a name="line.444"></a>
+<span class="sourceLineNo">445</span>  short getDataBlockEncodingId() {<a name="line.445"></a>
+<span class="sourceLineNo">446</span>    if (blockType != BlockType.ENCODED_DATA) {<a name="line.446"></a>
+<span class="sourceLineNo">447</span>      throw new IllegalArgumentException("Querying encoder ID of a block " +<a name="line.447"></a>
+<span class="sourceLineNo">448</span>          "of type other than " + BlockType.ENCODED_DATA + ": " + blockType);<a name="line.448"></a>
+<span class="sourceLineNo">449</span>    }<a name="line.449"></a>
+<span class="sourceLineNo">450</span>    return buf.getShort(headerSize());<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>   * @return the on-disk size of header + data part + checksum.<a name="line.454"></a>
+<span class="sourceLineNo">455</span>   */<a name="line.455"></a>
+<span class="sourceLineNo">456</span>  public int getOnDiskSizeWithHeader() {<a name="line.456"></a>
+<span class="sourceLineNo">457</span>    return onDiskSizeWithoutHeader + headerSize();<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>   * @return the on-disk size of the data part + checksum (header excluded).<a name="line.461"></a>
+<span class="sourceLineNo">462</span>   */<a name="line.462"></a>
+<span class="sourceLineNo">463</span>  int getOnDiskSizeWithoutHeader() {<a name="line.463"></a>
+<span class="sourceLineNo">464</span>    return onDiskSizeWithoutHeader;<a name="line.464"></a>
+<span class="sourceLineNo">465</span>  }<a name="line.465"></a>
+<span class="sourceLineNo">466</span><a name="line.466"></a>
+<span class="sourceLineNo">467</span>  /**<a name="line.467"></a>
+<span class="sourceLineNo">468</span>   * @return the uncompressed size of data part (header and checksum excluded).<a name="line.468"></a>
+<span class="sourceLineNo">469</span>   */<a name="line.469"></a>
+<span class="sourceLineNo">470</span>   int getUncompressedSizeWithoutHeader() {<a name="line.470"></a>
+<span class="sourceLineNo">471</span>    return uncompressedSizeWithoutHeader;<a name="line.471"></a>
+<span class="sourceLineNo">472</span>  }<a name="line.472"></a>
+<span class="sourceLineNo">473</span><a name="line.473"></a>
+<span class="sourceLineNo">474</span>  /**<a name="line.474"></a>
+<span class="sourceLineNo">475</span>   * @return the offset of the previous block of the same type in the file, or<a name="line.475"></a>
+<span class="sourceLineNo">476</span>   *         -1 if unknown<a name="line.476"></a>
+<span class="sourceLineNo">477</span>   */<a name="line.477"></a>
+<span class="sourceLineNo">478</span>  long getPrevBlockOffset() {<a name="line.478"></a>
+<span class="sourceLineNo">479</span>    return prevBlockOffset;<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>   * Rewinds {@code buf} and writes first 4 header fields. {@code buf} position<a name="line.483"></a>
+<span class="sourceLineNo">484</span>   * is modified as side-effect.<a name="line.484"></a>
+<span class="sourceLineNo">485</span>   */<a name="line.485"></a>
+<span class="sourceLineNo">486</span>  private void overwriteHeader() {<a name="line.486"></a>
+<span class="sourceLineNo">487</span>    buf.rewind();<a name="line.487"></a>
+<span class="sourceLineNo">488</span>    blockType.write(buf);<a name="line.488"></a>
+<span class="sourceLineNo">489</span>    buf.putInt(onDiskSizeWithoutHeader);<a name="line.489"></a>
+<span class="sourceLineNo">490</span>    buf.putInt(uncompressedSizeWithoutHeader);<a name="line.490"></a>
+<span class="sourceLineNo">491</span>    buf.putLong(prevBlockOffset);<a name="line.491"></a>
+<span class="sourceLineNo">492</span>    if (this.fileContext.isUseHBaseChecksum()) {<a name="line.492"></a>
+<span class="sourceLineNo">493</span>      buf.put(fileContext.getChecksumType().getCode());<a name="line.493"></a>
+<span class="sourceLineNo">494</span>      buf.putInt(fileContext.getBytesPerChecksum());<a name="line.494"></a>
+<span class="sourceLineNo">495</span>      buf.putInt(onDiskDataSizeWithHeader);<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><a name="line.498"></a>
+<span class="sourceLineNo">499</span>  /**<a name="line.499"></a>
+<span class="sourceLineNo">500</span>   * Returns a buffer that does not include the header or checksum.<a name="line.500"></a>
+<span class="sourceLineNo">501</span>   *<a name="line.501"></a>
+<span class="sourceLineNo">502</span>   * @return the buffer with header skipped and checksum omitted.<a name="line.502"></a>
+<span class="sourceLineNo">503</span>   */<a name="line.503"></a>
+<span class="sourceLineNo">504</span>  public ByteBuff getBufferWithoutHeader() {<a name="line.504"></a>
+<span class="sourceLineNo">505</span>    ByteBuff dup = getBufferReadOnly();<a name="line.505"></a>
+<span class="sourceLineNo">506</span>    // Now set it up so Buffer spans content only -- no header or no checksums.<a name="line.506"></a>
+<span class="sourceLineNo">507</span>    return dup.position(headerSize()).limit(buf.limit() - totalChecksumBytes()).slice();<a name="line.507"></a>
+<span class="sourceLineNo">508</span>  }<a name="line.508"></a>
+<span class="sourceLineNo">509</span><a name="line.509"></a>
+<span class="sourceLineNo">510</span>  /**<a name="line.510"></a>
+<span class="sourceLineNo">511</span>   * Returns a read-only duplicate of the buffer this block stores internally ready to be read.<a name="line.511"></a>
+<span class="sourceLineNo">512</span>   * Clients must not modify the buffer object though they may set position and limit on the<a name="line.512"></a>
+<span class="sourceLineNo">513</span>   * returned buffer since we pass back a duplicate. This method has to be public because it is used<a name="line.513"></a>
+<span class="sourceLineNo">514</span>   * in {@link CompoundBloomFilter} to avoid object creation on every Bloom<a name="line.514"></a>
+<span class="sourceLineNo">515</span>   * filter lookup, but has to be used with caution. Buffer holds header, block content,<a name="line.515"></a>
+<span class="sourceLineNo">516</span>   * and any follow-on checksums if present.<a name="line.516"></a>
+<span class="sourceLineNo">517</span>   *<a name="line.517"></a>
+<span class="sourceLineNo">518</span>   * @return the buffer of this block for read-only operations<a name="line.518"></a>
+<span class="sourceLineNo">519</span>   */<a name="line.519"></a>
+<span class="sourceLineNo">520</span>  public ByteBuff getBufferReadOnly() {<a name="line.520"></a>
+<span class="sourceLineNo">521</span>    // TODO: ByteBuf does not support asReadOnlyBuffer(). Fix.<a name="line.521"></a>
+<span class="sourceLineNo">522</span>    ByteBuff dup = this.buf.duplicate();<a name="line.522"></a>
+<span class="sourceLineNo">523</span>    assert dup.position() == 0;<a name="line.523"></a>
+<span class="sourceLineNo">524</span>    return dup;<a name="line.524"></a>
+<span class="sourceLineNo">525</span>  }<a name="line.525"></a>
+<span class="sourceLineNo">526</span><a name="line.526"></a>
+<span class="sourceLineNo">527</span>  @VisibleForTesting<a name="line.527"></a>
+<span class="sourceLineNo">528</span>  private void sanityCheckAssertion(long valueFromBuf, long valueFromField,<a name="line.528"></a>
+<span class="sourceLineNo">529</span>      String fieldName) throws IOException {<a name="line.529"></a>
+<span class="sourceLineNo">530</span>    if (valueFromBuf != valueFromField) {<a name="line.530"></a>
+<span class="sourceLineNo">531</span>      throw new AssertionError(fieldName + " in the buffer (" + valueFromBuf<a name="line.531"></a>
+<span class="sourceLineNo">532</span>          + ") is different from that in the field (" + valueFromField + ")");<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>  @VisibleForTesting<a name="line.536"></a>
+<span class="sourceLineNo">537</span>  private void sanityCheckAssertion(BlockType valueFromBuf, BlockType valueFromField)<a name="line.537"></a>
+<span class="sourceLineNo">538</span>      throws IOException {<a name="line.538"></a>
+<span class="sourceLineNo">539</span>    if (valueFromBuf != valueFromField) {<a name="line.539"></a>
+<span class="sourceLineNo">540</span>      throw new IOException("Block type stored in the buffer: " +<a name="line.540"></a>
+<span class="sourceLineNo">541</span>        valueFromBuf + ", block type field: " + valueFromField);<a name="line.541"></a>
+<span class="sourceLineNo">542</span>    }<a name="line.542"></a>
+<span class="sourceLineNo">543</span>  }<a name="line.543"></a>
+<span class="sourceLineNo">544</span><a name="line.544"></a>
+<span class="sourceLineNo">545</span>  /**<a name="line.545"></a>
+<span class="sourceLineNo">546</span>   * Checks if the block is internally consistent, i.e. the first<a name="line.546"></a>
+<span class="sourceLineNo">547</span>   * {@link HConstants#HFILEBLOCK_HEADER_SIZE} bytes of the buffer contain a<a name="line.547"></a>
+<span class="sourceLineNo">548</span>   * valid header consistent with the fields. Assumes a packed block structure.<a name="line.548"></a>
+<span class="sourceLineNo">549</span>   * This function is primary for testing and debugging, and is not<a name="line.549"></a>
+<span class="sourceLineNo">550</span>   * thread-safe, because it alters the internal buffer pointer.<a name="line.550"></a>
+<span class="sourceLineNo">551</span>   * Used by tests only.<a name="line.551"></a>
+<span class="sourceLineNo">552</span>   */<a name="line.552"></a>
+<span class="sourceLineNo">553</span>  @VisibleForTesting<a name="line.553"></a>
+<span class="sourceLineNo">554</span>  void sanityCheck() throws IOException {<a name="line.554"></a>
+<span class="sourceLineNo">555</span>    // Duplicate so no side-effects<a name="line.555"></a>
+<span class="sourceLineNo">556</span>    ByteBuff dup = this.buf.duplicate().rewind();<a name="line.556"></a>
+<span class="sourceLineNo">557</span>    sanityCheckAssertion(BlockType.read(dup), blockType);<a name="line.557"></a>
+<span class="sourceLineNo">558</span><a name="line.558"></a>
+<span class="sourceLineNo">559</span>    sanityCheckAssertion(dup.getInt(), onDiskSizeWithoutHeader, "onDiskSizeWithoutHeader");<a name="line.559"></a>
+<span class="sourceLineNo">560</span><a name="line.560"></a>
+<span class="sourceLineNo">561</span>    sanityCheckAssertion(dup.getInt(), uncompressedSizeWithoutHeader,<a name="line.561"></a>
+<span class="sourceLineNo">562</span>        "uncompressedSizeWithoutHeader");<a name="line.562"></a>
+<span class="sourceLineNo">563</span><a name="line.563"></a>
+<span class="sourceLineNo">564</span>    sanityCheckAssertion(dup.getLong(), prevBlockOffset, "prevBlockOffset");<a name="line.564"></a>
+<span class="sourceLineNo">565</span>    if (this.fileContext.isUseHBaseChecksum()) {<a name="line.565"></a>
+<span class="sourceLineNo">566</span>      sanityCheckAssertion(dup.get(), this.fileContext.getChecksumType().getCode(), "checksumType");<a name="line.566"></a>
+<span class="sourceLineNo">567</span>      sanityCheckAssertion(dup.getInt(), this.fileContext.getBytesPerChecksum(),<a name="line.567"></a>
+<span class="sourceLineNo">568</span>          "bytesPerChecksum");<a name="line.568"></a>
+<span class="sourceLineNo">569</span>      sanityCheckAssertion(dup.getInt(), onDiskDataSizeWithHeader, "onDiskDataSizeWithHeader");<a name="line.569"></a>
+<span class="sourceLineNo">570</span>    }<a name="line.570"></a>
+<span class="sourceLineNo">571</span><a name="line.571"></a>
+<span class="sourceLineNo">572</span>    int cksumBytes = totalChecksumBytes();<a name="line.572"></a>
+<span class="sourceLineNo">573</span>    int expectedBufLimit = onDiskDataSizeWithHeader + cksumBytes;<a name="line.573"></a>
+<span class="sourceLineNo">574</span>    if (dup.limit() != expectedBufLimit) {<a name="line.574"></a>
+<span class="sourceLineNo">575</span>      throw new AssertionError("Expected limit " + expectedBufLimit + ", got " + dup.limit());<a name="line.575"></a>
+<span class="sourceLineNo">576</span>    }<a name="line.576"></a>
+<span class="sourceLineNo">577</span><a name="line.577"></a>
+<span class="sourceLineNo">578</span>    // We might optionally allocate HFILEBLOCK_HEADER_SIZE more bytes to read the next<a name="line.578"></a>
+<span class="sourceLineNo">579</span>    // block's header, so there are two sensible values for buffer capacity.<a name="line.579"></a>
+<span class="sourceLineNo">580</span>    int hdrSize = headerSize();<a name="line.580"></a>
+<span class="sourceLineNo">581</span>    if (dup.capacity() != expectedBufLimit &amp;&amp; dup.capacity() != expectedBufLimit + hdrSize) {<a name="line.581"></a>
+<span class="sourceLineNo">582</span>      throw new AssertionError("Invalid buffer capacity: " + dup.capacity() +<a name="line.582"></a>
+<span class="sourceLineNo">583</span>          ", expected " + expectedBufLimit + " or " + (expectedBufLimit + hdrSize));<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>  @Override<a name="line.587"></a>
+<span class="sourceLineNo">588</span>  public String toString() {<a name="line.588"></a>
+<span class="sourceLineNo">589</span>    StringBuilder sb = new StringBuilder()<a name="line.589"></a>
+<span class="sourceLineNo">590</span>      .append("[")<a name="line.590"></a>
+<span class="sourceLineNo">591</span>      .append("blockType=").append(blockType)<a name="line.591"></a>
+<span class="sourceLineNo">592</span>      .append(", fileOffset=").append(offset)<a name="line.592"></a>
+<span class="sourceLineNo">593</span>      .append(", headerSize=").append(headerSize())<a name="line.593"></a>
+<span class="sourceLineNo">594</span>      .append(", onDiskSizeWithoutHeader=").append(onDiskSizeWithoutHeader)<a name="line.594"></a>
+<span class="sourceLineNo">595</span>      .append(", uncompressedSizeWithoutHeader=").append(uncompressedSizeWithoutHeader)<a name="line.595"></a>
+<span class="sourceLineNo">596</span>      .append(", prevBlockOffset=").append(prevBlockOffset)<a name="line.596"></a>
+<span class="sourceLineNo">597</span>      .append(", isUseHBaseChecksum=").append(fileContext.isUseHBaseChecksum());<a name="line.597"></a>
+<span class="sourceLineNo">598</span>    if (fileContext.isUseHBaseChecksum()) {<a name="line.598"></a>
+<span class="sourceLineNo">599</span>      sb.append(", checksumType=").append(ChecksumType.codeToType(this.buf.get(24)))<a name="line.599"></a>
+<span class="sourceLineNo">600</span>        .append(", bytesPerChecksum=").append(this.buf.getInt(24 + 1))<a name="line.600"></a>
+<span class="sourceLineNo">601</span>        .append(", onDiskDataSizeWithHeader=").append(onDiskDataSizeWithHeader);<a name="line.601"></a>
+<span class="sourceLineNo">602</span>    } else {<a name="line.602"></a>
+<span class="sourceLineNo">603</span>      sb.append(", onDiskDataSizeWithHeader=").append(onDiskDataSizeWithHeader)<a name="line.603"></a>
+<span class="sourceLineNo">604</span>        .append("(").append(onDiskSizeWithoutHeader)<a name="line.604"></a>
+<span class="sourceLineNo">605</span>        .append("+").append(HConstants.HFILEBLOCK_HEADER_SIZE_NO_CHECKSUM).append(")");<a name="line.605"></a>
+<span class="sourceLineNo">606</span>    }<a name="line.606"></a>
+<span class="sourceLineNo">607</span>    String dataBegin = null;<a name="line.607"></a>
+<span class="sourceLineNo">608</span>    if (buf.hasArray()) {<a name="line.608"></a>
+<span class="sourceLineNo">609</span>      dataBegin = Bytes.toStringBinary(buf.array(), buf.arrayOffset() + headerSize(),<a name="line.609"></a>
+<span class="sourceLineNo">610</span>          Math.min(32, buf.limit() - buf.arrayOffset() - headerSize()));<a name="line.610"></a>
+<span class="sourceLineNo">611</span>    } else {<a name="line.611"></a>
+<span class="sourceLineNo">612</span>      ByteBuff bufWithoutHeader = getBufferWithoutHeader();<a name="line.612"></a>
+<span class="sourceLineNo">613</span>      byte[] dataBeginBytes = new byte[Math.min(32,<a name="line.613"></a>
+<span class="sourceLineNo">614</span>          bufWithoutHeader.limit() - bufWithoutHeader.position())];<a name="line.614"></a>
+<span class="sourceLineNo">615</span>      bufWithoutHeader.get(dataBeginBytes);<a name="line.615"></a>
+<span class="sourceLineNo">616</span>      dataBegin = Bytes.toStringBinary(dataBeginBytes);<a name="line.616"></a>
+<span class="sourceLineNo">617</span>    }<a name="line.617"></a>
+<span class="sourceLineNo">618</span>    sb.append(", getOnDiskSizeWithHeader=").append(getOnDiskSizeWithHeader())<a name="line.618"></a>
+<span class="sourceLineNo">619</span>      .append(", totalChecksumBytes=").append(totalChecksumBytes())<a name="line.619"></a>
+<span class="sourceLineNo">620</span>      .append(", isUnpacked=").append(isUnpacked())<a name="line.620"></a>
+<span class="sourceLineNo">621</span>      .append(", buf=[").append(buf).append("]")<a name="line.621"></a>
+<span class="sourceLineNo">622</span>      .append(", dataBeginsWith=").append(dataBegin)<a name="line.622"></a>
+<span class="sourceLineNo">623</span>      .append(", fileContext=").append(fileContext)<a name="line.623"></a>
+<span class="sourceLineNo">624</span>      .append(", nextBlockOnDiskSize=").append(nextBlockOnDiskSize)<a name="line.624"></a>
+<span class="sourceLineNo">625</span>      .append("]");<a name="line.625"></a>
+<span class="sourceLineNo">626</span>    return sb.toString();<a name="line.626"></a>
+<span class="sourceLineNo">627</span>  }<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>   * Retrieves the decompressed/decrypted view of this block. An encoded block remains in its<a name="line.630"></a>
+<span class="sourceLineNo">631</span>   * encoded structure. Internal structures are shared between instances where applicable.<a name="line.631"></a>
+<span class="sourceLineNo">632</span>   */<a name="line.632"></a>
+<span class="sourceLineNo">633</span>  HFileBlock unpack(HFileContext fileContext, FSReader reader) throws IOException {<a name="line.633"></a>
+<span class="sourceLineNo">634</span>    if (!fileContext.isCompressedOrEncrypted()) {<a name="line.634"></a>
+<span class="sourceLineNo">635</span>      // TODO: cannot use our own fileContext here because HFileBlock(ByteBuffer, boolean),<a name="line.635"></a>
+<span class="sourceLineNo">636</span>      // which is used for block serialization to L2 cache, does not preserve encoding and<a name="line.636"></a>
+<span class="sourceLineNo">637</span>      // encryption details.<a name="line.637"></a>
+<span class="sourceLineNo">638</span>      return this;<a name="line.638"></a>
+<span class="sourceLineNo">639</span>    }<a name="line.639"></a>
+<span class="sourceLineNo">640</span><a name="line.640"></a>
+<span class="sourceLineNo">641</span>    HFileBlock unpacked = new HFileBlock(this);<a name="line.641"></a>
+<span class="sourceLineNo">642</span>    unpacked.allocateBuffer(); // allocates space for the decompressed block<a name="line.642"></a>
+<span class="sourceLineNo">643</span><a name="line.643"></a>
+<span class="sourceLineNo">644</span>    HFileBlockDecodingContext ctx = blockType == BlockType.ENCODED_DATA ?<a name="line.644"></a>
+<span class="sourceLineNo">645</span>      reader.getBlockDecodingContext() : reader.getDefaultBlockDecodingContext();<a name="line.645"></a>
+<span class="sourceLineNo">646</span><a name="line.646"></a>
+<span class="sourceLineNo">647</span>    ByteBuff dup = this.buf.duplicate();<a name="line.647"></a>
+<span class="sourceLineNo">648</span>    dup.position(this.headerSize());<a name="line.648"></a>
+<span class="sourceLineNo">649</span>    dup = dup.slice();<a name="line.649"></a>
+<span class="sourceLineNo">650</span>    ctx.prepareDecoding(unpacked.getOnDiskSizeWithoutHeader(),<a name="line.650"></a>


<TRUNCATED>