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 2020/04/26 14:45:03 UTC
[hbase-site] branch asf-site updated: Published site at
ec0d9d767e697c8d6726d15bf06ce9a19a756263.
This is an automated email from the ASF dual-hosted git repository.
git-site-role pushed a commit to branch asf-site
in repository https://gitbox.apache.org/repos/asf/hbase-site.git
The following commit(s) were added to refs/heads/asf-site by this push:
new 4b4f57b Published site at ec0d9d767e697c8d6726d15bf06ce9a19a756263.
4b4f57b is described below
commit 4b4f57bb659f5793dd9735aa4191aae373cd397d
Author: jenkins <bu...@apache.org>
AuthorDate: Sun Apr 26 14:44:51 2020 +0000
Published site at ec0d9d767e697c8d6726d15bf06ce9a19a756263.
---
acid-semantics.html | 2 +-
apache_hbase_reference_guide.pdf | 4 +-
book.html | 2 +-
bulk-loads.html | 2 +-
checkstyle-aggregate.html | 76 +--
checkstyle.rss | 4 +-
coc.html | 2 +-
dependencies.html | 2 +-
dependency-convergence.html | 2 +-
dependency-info.html | 2 +-
dependency-management.html | 2 +-
devapidocs/constant-values.html | 4 +-
devapidocs/index-all.html | 4 +-
.../bucket/BucketAllocator.IndexStatistics.html | 30 +-
.../hbase/io/hfile/bucket/BucketAllocator.html | 56 +-
.../hbase/security/AbstractHBaseSaslRpcClient.html | 27 +-
.../security/NettyHBaseSaslRpcClientHandler.html | 6 +-
.../src-html/org/apache/hadoop/hbase/Version.html | 4 +-
.../io/hfile/bucket/BucketAllocator.Bucket.html | 705 +++++++++++----------
.../bucket/BucketAllocator.BucketSizeInfo.html | 705 +++++++++++----------
.../bucket/BucketAllocator.IndexStatistics.html | 705 +++++++++++----------
.../hbase/io/hfile/bucket/BucketAllocator.html | 705 +++++++++++----------
.../hbase/security/AbstractHBaseSaslRpcClient.html | 58 +-
.../security/NettyHBaseSaslRpcClientHandler.html | 128 ++--
downloads.html | 2 +-
export_control.html | 2 +-
index.html | 2 +-
issue-tracking.html | 2 +-
mail-lists.html | 2 +-
metrics.html | 2 +-
old_news.html | 2 +-
plugin-management.html | 2 +-
plugins.html | 2 +-
poweredbyhbase.html | 2 +-
project-info.html | 2 +-
project-reports.html | 2 +-
project-summary.html | 2 +-
pseudo-distributed.html | 2 +-
replication.html | 2 +-
resources.html | 2 +-
source-repository.html | 2 +-
sponsors.html | 2 +-
supportingprojects.html | 2 +-
team-list.html | 2 +-
44 files changed, 1622 insertions(+), 1655 deletions(-)
diff --git a/acid-semantics.html b/acid-semantics.html
index 83e143a..321cac7 100644
--- a/acid-semantics.html
+++ b/acid-semantics.html
@@ -467,7 +467,7 @@
<div class="row">
<p>Copyright ©2007–2020
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-25</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-26</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/apache_hbase_reference_guide.pdf b/apache_hbase_reference_guide.pdf
index ceca3eb..187aa65 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.rc.2, based on Prawn 2.2.2)
/Producer (Apache HBase Team)
-/ModDate (D:20200425192308+00'00')
-/CreationDate (D:20200425193428+00'00')
+/ModDate (D:20200426143116+00'00')
+/CreationDate (D:20200426144210+00'00')
>>
endobj
2 0 obj
diff --git a/book.html b/book.html
index 5ed8146..6b11adc 100644
--- a/book.html
+++ b/book.html
@@ -45211,7 +45211,7 @@ org/apache/hadoop/hbase/security/access/AccessControlClient.revoke:(Lorg/apache/
<div id="footer">
<div id="footer-text">
Version 3.0.0-SNAPSHOT<br>
-Last updated 2020-04-25 19:23:08 UTC
+Last updated 2020-04-26 14:31:16 UTC
</div>
</div>
<script type="text/x-mathjax-config">
diff --git a/bulk-loads.html b/bulk-loads.html
index 9c1e6d8..4250226 100644
--- a/bulk-loads.html
+++ b/bulk-loads.html
@@ -172,7 +172,7 @@
<div class="row">
<p>Copyright ©2007–2020
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-25</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-26</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/checkstyle-aggregate.html b/checkstyle-aggregate.html
index edc2d72..739112f 100644
--- a/checkstyle-aggregate.html
+++ b/checkstyle-aggregate.html
@@ -169,7 +169,7 @@
<td>4232</td>
<td>0</td>
<td>0</td>
-<td>9911</td></tr></table></div>
+<td>9907</td></tr></table></div>
<div class="section">
<h2><a name="Files"></a>Files</h2>
<table border="0" class="table table-striped">
@@ -6112,7 +6112,7 @@
<td><a href="#org.apache.hadoop.hbase.security.NettyHBaseSaslRpcClientHandler.java">org/apache/hadoop/hbase/security/NettyHBaseSaslRpcClientHandler.java</a></td>
<td>0</td>
<td>0</td>
-<td>6</td></tr>
+<td>2</td></tr>
<tr class="a">
<td><a href="#org.apache.hadoop.hbase.security.SaslChallengeDecoder.java">org/apache/hadoop/hbase/security/SaslChallengeDecoder.java</a></td>
<td>0</td>
@@ -7463,12 +7463,12 @@
<td><a class="externalLink" href="http://checkstyle.sourceforge.net/config_javadoc.html#JavadocTagContinuationIndentation">JavadocTagContinuationIndentation</a>
<ul>
<li>offset: <tt>"2"</tt></li></ul></td>
-<td>595</td>
+<td>596</td>
<td><img src="images/icon_error_sml.gif" alt="" /> 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>2529</td>
+<td>2528</td>
<td><img src="images/icon_error_sml.gif" alt="" /> Error</td></tr>
<tr class="b">
<td>misc</td>
@@ -7491,7 +7491,7 @@
<ul>
<li>max: <tt>"100"</tt></li>
<li>ignorePattern: <tt>"^package.*|^import.*|a href|href|http://|https://|ftp://|org.apache.thrift.|com.google.protobuf.|hbase.protobuf.generated"</tt></li></ul></td>
-<td>954</td>
+<td>950</td>
<td><img src="images/icon_error_sml.gif" alt="" /> Error</td></tr>
<tr class="b">
<td></td>
@@ -8496,7 +8496,7 @@
<tr class="a">
<td><img src="images/icon_error_sml.gif" alt="" /> Error</td>
<td>javadoc</td>
-<td>NonEmptyAtclauseDescription</td>
+<td>JavadocTagContinuationIndentation</td>
<td>Javadoc comment at column 33 has parse error. Details: no viable alternative at input '<Map.Entry<' while parsing HTML_ELEMENT</td>
<td>642</td></tr>
<tr class="b">
@@ -32774,109 +32774,109 @@
<td>misc</td>
<td>ArrayTypeStyle</td>
<td>Array brackets at illegal position.</td>
-<td>274</td></tr>
+<td>275</td></tr>
<tr class="b">
<td><img src="images/icon_error_sml.gif" alt="" /> Error</td>
<td>indentation</td>
<td>Indentation</td>
<td>'array initialization' child has incorrect indentation level 6, expected level should be one of the following: 4, 54.</td>
-<td>275</td></tr>
+<td>276</td></tr>
<tr class="a">
<td><img src="images/icon_error_sml.gif" alt="" /> Error</td>
<td>indentation</td>
<td>Indentation</td>
<td>'array initialization' child has incorrect indentation level 6, expected level should be one of the following: 4, 54.</td>
-<td>276</td></tr>
+<td>277</td></tr>
<tr class="b">
<td><img src="images/icon_error_sml.gif" alt="" /> Error</td>
<td>indentation</td>
<td>Indentation</td>
<td>'array initialization' child has incorrect indentation level 6, expected level should be one of the following: 4, 54.</td>
-<td>277</td></tr>
+<td>278</td></tr>
<tr class="a">
<td><img src="images/icon_error_sml.gif" alt="" /> Error</td>
<td>indentation</td>
<td>Indentation</td>
<td>'array initialization' child has incorrect indentation level 6, expected level should be one of the following: 4, 54.</td>
-<td>278</td></tr>
+<td>279</td></tr>
<tr class="b">
<td><img src="images/icon_error_sml.gif" alt="" /> Error</td>
<td>blocks</td>
<td>NeedBraces</td>
<td>'for' construct must use '{}'s.</td>
-<td>285</td></tr>
+<td>286</td></tr>
<tr class="a">
<td><img src="images/icon_error_sml.gif" alt="" /> Error</td>
<td>blocks</td>
<td>NeedBraces</td>
<td>'if' construct must use '{}'s.</td>
-<td>286</td></tr>
+<td>287</td></tr>
<tr class="b">
<td><img src="images/icon_error_sml.gif" alt="" /> Error</td>
<td>blocks</td>
<td>NeedBraces</td>
<td>'if' construct must use '{}'s.</td>
-<td>312</td></tr>
+<td>313</td></tr>
<tr class="a">
<td><img src="images/icon_error_sml.gif" alt="" /> Error</td>
<td>javadoc</td>
<td>NonEmptyAtclauseDescription</td>
<td>At-clause should have a non-empty description.</td>
-<td>339</td></tr>
+<td>340</td></tr>
<tr class="b">
<td><img src="images/icon_error_sml.gif" alt="" /> Error</td>
<td>blocks</td>
<td>NeedBraces</td>
<td>'if' construct must use '{}'s.</td>
-<td>414</td></tr>
+<td>415</td></tr>
<tr class="a">
<td><img src="images/icon_error_sml.gif" alt="" /> Error</td>
<td>javadoc</td>
<td>NonEmptyAtclauseDescription</td>
<td>At-clause should have a non-empty description.</td>
-<td>436</td></tr>
+<td>437</td></tr>
<tr class="b">
<td><img src="images/icon_error_sml.gif" alt="" /> Error</td>
<td>javadoc</td>
<td>NonEmptyAtclauseDescription</td>
<td>At-clause should have a non-empty description.</td>
-<td>437</td></tr>
+<td>438</td></tr>
<tr class="a">
<td><img src="images/icon_error_sml.gif" alt="" /> Error</td>
<td>blocks</td>
<td>NeedBraces</td>
<td>'if' construct must use '{}'s.</td>
-<td>452</td></tr>
+<td>453</td></tr>
<tr class="b">
<td><img src="images/icon_error_sml.gif" alt="" /> Error</td>
<td>blocks</td>
<td>NeedBraces</td>
<td>'if' construct must use '{}'s.</td>
-<td>461</td></tr>
+<td>462</td></tr>
<tr class="a">
<td><img src="images/icon_error_sml.gif" alt="" /> Error</td>
<td>blocks</td>
<td>NeedBraces</td>
<td>'for' construct must use '{}'s.</td>
-<td>570</td></tr>
+<td>571</td></tr>
<tr class="b">
<td><img src="images/icon_error_sml.gif" alt="" /> Error</td>
<td>misc</td>
<td>ArrayTypeStyle</td>
<td>Array brackets at illegal position.</td>
-<td>575</td></tr>
+<td>576</td></tr>
<tr class="a">
<td><img src="images/icon_error_sml.gif" alt="" /> Error</td>
<td>blocks</td>
<td>NeedBraces</td>
<td>'for' construct must use '{}'s.</td>
-<td>577</td></tr>
+<td>578</td></tr>
<tr class="b">
<td><img src="images/icon_error_sml.gif" alt="" /> Error</td>
<td>whitespace</td>
<td>ParenPad</td>
<td>')' is preceded with whitespace.</td>
-<td>610</td></tr></table></div>
+<td>611</td></tr></table></div>
<div class="section">
<h3 id="org.apache.hadoop.hbase.io.hfile.bucket.BucketCache.java">org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.java</h3>
<table border="0" class="table table-striped">
@@ -65885,31 +65885,7 @@
<td>imports</td>
<td>ImportOrder</td>
<td>Wrong order for 'org.apache.hadoop.hbase.ipc.FallbackDisallowedException' import.</td>
-<td>34</td></tr>
-<tr class="a">
-<td><img src="images/icon_error_sml.gif" alt="" /> Error</td>
-<td>sizes</td>
-<td>LineLength</td>
-<td>Line is longer than 100 characters (found 116).</td>
-<td>133</td></tr>
-<tr class="b">
-<td><img src="images/icon_error_sml.gif" alt="" /> Error</td>
-<td>sizes</td>
-<td>LineLength</td>
-<td>Line is longer than 100 characters (found 119).</td>
-<td>134</td></tr>
-<tr class="a">
-<td><img src="images/icon_error_sml.gif" alt="" /> Error</td>
-<td>sizes</td>
-<td>LineLength</td>
-<td>Line is longer than 100 characters (found 116).</td>
-<td>135</td></tr>
-<tr class="b">
-<td><img src="images/icon_error_sml.gif" alt="" /> Error</td>
-<td>sizes</td>
-<td>LineLength</td>
-<td>Line is longer than 100 characters (found 111).</td>
-<td>136</td></tr></table></div>
+<td>34</td></tr></table></div>
<div class="section">
<h3 id="org.apache.hadoop.hbase.security.SaslChallengeDecoder.java">org/apache/hadoop/hbase/security/SaslChallengeDecoder.java</h3>
<table border="0" class="table table-striped">
@@ -79904,7 +79880,7 @@
<div class="row">
<p>Copyright ©2007–2020
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-25</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-26</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/checkstyle.rss b/checkstyle.rss
index d15ef75..a98f55b 100644
--- a/checkstyle.rss
+++ b/checkstyle.rss
@@ -26,7 +26,7 @@ under the License.
<copyright>©2007 - 2020 The Apache Software Foundation</copyright>
<item>
<title>File: 4232,
- Errors: 9911,
+ Errors: 9907,
Warnings: 0,
Infos: 0
</title>
@@ -54207,7 +54207,7 @@ under the License.
0
</td>
<td>
- 6
+ 2
</td>
</tr>
<tr>
diff --git a/coc.html b/coc.html
index d3fdb7d..86ffd96 100644
--- a/coc.html
+++ b/coc.html
@@ -241,7 +241,7 @@ email to <a class="externalLink" href="mailto:private@hbase.apache.org">the priv
<div class="row">
<p>Copyright ©2007–2020
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-25</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-26</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/dependencies.html b/dependencies.html
index 7a73261..3eabebe 100644
--- a/dependencies.html
+++ b/dependencies.html
@@ -313,7 +313,7 @@
<div class="row">
<p>Copyright ©2007–2020
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-25</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-26</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/dependency-convergence.html b/dependency-convergence.html
index 6bded75..c2c0878 100644
--- a/dependency-convergence.html
+++ b/dependency-convergence.html
@@ -757,7 +757,7 @@
<div class="row">
<p>Copyright ©2007–2020
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-25</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-26</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/dependency-info.html b/dependency-info.html
index 23a9523..d925fd5 100644
--- a/dependency-info.html
+++ b/dependency-info.html
@@ -194,7 +194,7 @@
<div class="row">
<p>Copyright ©2007–2020
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-25</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-26</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/dependency-management.html b/dependency-management.html
index 9682bb9..6230bc0 100644
--- a/dependency-management.html
+++ b/dependency-management.html
@@ -1068,7 +1068,7 @@
<div class="row">
<p>Copyright ©2007–2020
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-25</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-26</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/devapidocs/constant-values.html b/devapidocs/constant-values.html
index cc81d52..480f249 100644
--- a/devapidocs/constant-values.html
+++ b/devapidocs/constant-values.html
@@ -4165,14 +4165,14 @@
<!-- -->
</a><code>public static final <a href="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>"Sat Apr 25 19:30:56 UTC 2020"</code></td>
+<td class="colLast"><code>"Sun Apr 26 14:38:40 UTC 2020"</code></td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a name="org.apache.hadoop.hbase.Version.revision">
<!-- -->
</a><code>public static final <a href="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>"e6cc5eb2f0623f02eaa3542308fc3d82fd3abd9f"</code></td>
+<td class="colLast"><code>"ec0d9d767e697c8d6726d15bf06ce9a19a756263"</code></td>
</tr>
<tr class="altColor">
<td class="colFirst"><a name="org.apache.hadoop.hbase.Version.srcChecksum">
diff --git a/devapidocs/index-all.html b/devapidocs/index-all.html
index 122621a..716a790 100644
--- a/devapidocs/index-all.html
+++ b/devapidocs/index-all.html
@@ -42518,8 +42518,8 @@
<dd> </dd>
<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/security/AbstractHBaseSaslRpcClient.html#getInitialResponse--">getInitialResponse()</a></span> - Method in class org.apache.hadoop.hbase.security.<a href="org/apache/hadoop/hbase/security/AbstractHBaseSaslRpcClient.html" title="class in org.apache.hadoop.hbase.security">AbstractHBaseSaslRpcClient</a></dt>
<dd>
-<div class="block">Computes the initial response a client sends to a server to begin the SASL
- challenge/response handshake.</div>
+<div class="block">Computes the initial response a client sends to a server to begin the SASL challenge/response
+ handshake.</div>
</dd>
<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/master/assignment/GCMergedRegionsProcedure.html#getInitialState--">getInitialState()</a></span> - Method in class org.apache.hadoop.hbase.master.assignment.<a href="org/apache/hadoop/hbase/master/assignment/GCMergedRegionsProcedure.html" title="class in org.apache.hadoop.hbase.master.assignment">GCMergedRegionsProcedure</a></dt>
<dd>
diff --git a/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.IndexStatistics.html b/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.IndexStatistics.html
index ae6cd95..e715db2 100644
--- a/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.IndexStatistics.html
+++ b/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.IndexStatistics.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/BucketAllocator.html#line.494">BucketAllocator.IndexStatistics</a>
+<pre>static class <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.495">BucketAllocator.IndexStatistics</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>
@@ -248,7 +248,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>freeCount</h4>
-<pre>private long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.IndexStatistics.html#line.495">freeCount</a></pre>
+<pre>private long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.IndexStatistics.html#line.496">freeCount</a></pre>
</li>
</ul>
<a name="usedCount">
@@ -257,7 +257,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>usedCount</h4>
-<pre>private long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.IndexStatistics.html#line.495">usedCount</a></pre>
+<pre>private long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.IndexStatistics.html#line.496">usedCount</a></pre>
</li>
</ul>
<a name="itemSize">
@@ -266,7 +266,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>itemSize</h4>
-<pre>private long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.IndexStatistics.html#line.495">itemSize</a></pre>
+<pre>private long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.IndexStatistics.html#line.496">itemSize</a></pre>
</li>
</ul>
<a name="totalCount">
@@ -275,7 +275,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockListLast">
<li class="blockList">
<h4>totalCount</h4>
-<pre>private long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.IndexStatistics.html#line.495">totalCount</a></pre>
+<pre>private long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.IndexStatistics.html#line.496">totalCount</a></pre>
</li>
</ul>
</li>
@@ -292,7 +292,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>IndexStatistics</h4>
-<pre>public <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.IndexStatistics.html#line.525">IndexStatistics</a>(long free,
+<pre>public <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.IndexStatistics.html#line.526">IndexStatistics</a>(long free,
long used,
long itemSize)</pre>
</li>
@@ -303,7 +303,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockListLast">
<li class="blockList">
<h4>IndexStatistics</h4>
-<pre>public <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.IndexStatistics.html#line.529">IndexStatistics</a>()</pre>
+<pre>public <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.IndexStatistics.html#line.530">IndexStatistics</a>()</pre>
</li>
</ul>
</li>
@@ -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>freeCount</h4>
-<pre>public long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.IndexStatistics.html#line.497">freeCount</a>()</pre>
+<pre>public long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.IndexStatistics.html#line.498">freeCount</a>()</pre>
</li>
</ul>
<a name="usedCount--">
@@ -329,7 +329,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>usedCount</h4>
-<pre>public long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.IndexStatistics.html#line.501">usedCount</a>()</pre>
+<pre>public long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.IndexStatistics.html#line.502">usedCount</a>()</pre>
</li>
</ul>
<a name="totalCount--">
@@ -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>totalCount</h4>
-<pre>public long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.IndexStatistics.html#line.505">totalCount</a>()</pre>
+<pre>public long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.IndexStatistics.html#line.506">totalCount</a>()</pre>
</li>
</ul>
<a name="freeBytes--">
@@ -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>freeBytes</h4>
-<pre>public long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.IndexStatistics.html#line.509">freeBytes</a>()</pre>
+<pre>public long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.IndexStatistics.html#line.510">freeBytes</a>()</pre>
</li>
</ul>
<a name="usedBytes--">
@@ -356,7 +356,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>usedBytes</h4>
-<pre>public long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.IndexStatistics.html#line.513">usedBytes</a>()</pre>
+<pre>public long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.IndexStatistics.html#line.514">usedBytes</a>()</pre>
</li>
</ul>
<a name="totalBytes--">
@@ -365,7 +365,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>totalBytes</h4>
-<pre>public long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.IndexStatistics.html#line.517">totalBytes</a>()</pre>
+<pre>public long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.IndexStatistics.html#line.518">totalBytes</a>()</pre>
</li>
</ul>
<a name="itemSize--">
@@ -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>itemSize</h4>
-<pre>public long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.IndexStatistics.html#line.521">itemSize</a>()</pre>
+<pre>public long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.IndexStatistics.html#line.522">itemSize</a>()</pre>
</li>
</ul>
<a name="setTo-long-long-long-">
@@ -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>setTo</h4>
-<pre>public void <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.IndexStatistics.html#line.533">setTo</a>(long free,
+<pre>public void <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.IndexStatistics.html#line.534">setTo</a>(long free,
long used,
long itemSize)</pre>
</li>
diff --git a/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html b/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html
index 1e1efd2..4f030f2 100644
--- a/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html
+++ b/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html
@@ -363,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>DEFAULT_BUCKET_SIZES</h4>
-<pre>private static final int[] <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.274">DEFAULT_BUCKET_SIZES</a></pre>
+<pre>private static final int[] <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.275">DEFAULT_BUCKET_SIZES</a></pre>
</li>
</ul>
<a name="FEWEST_ITEMS_IN_BUCKET">
@@ -372,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>FEWEST_ITEMS_IN_BUCKET</h4>
-<pre>public static final int <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.294">FEWEST_ITEMS_IN_BUCKET</a></pre>
+<pre>public static final int <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.295">FEWEST_ITEMS_IN_BUCKET</a></pre>
<div class="block">So, what is the minimum amount of items we'll tolerate in a single bucket?</div>
<dl>
<dt><span class="seeLabel">See Also:</span></dt>
@@ -386,7 +386,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>bucketSizes</h4>
-<pre>private final int[] <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.296">bucketSizes</a></pre>
+<pre>private final int[] <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.297">bucketSizes</a></pre>
</li>
</ul>
<a name="bigItemSize">
@@ -395,7 +395,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>bigItemSize</h4>
-<pre>private final int <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.297">bigItemSize</a></pre>
+<pre>private final int <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.298">bigItemSize</a></pre>
</li>
</ul>
<a name="bucketCapacity">
@@ -404,7 +404,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>bucketCapacity</h4>
-<pre>private final long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.299">bucketCapacity</a></pre>
+<pre>private final long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.300">bucketCapacity</a></pre>
</li>
</ul>
<a name="buckets">
@@ -413,7 +413,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>buckets</h4>
-<pre>private <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.Bucket.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketAllocator.Bucket</a>[] <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.300">buckets</a></pre>
+<pre>private <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.Bucket.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketAllocator.Bucket</a>[] <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.301">buckets</a></pre>
</li>
</ul>
<a name="bucketSizeInfos">
@@ -422,7 +422,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>bucketSizeInfos</h4>
-<pre>private <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.BucketSizeInfo.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketAllocator.BucketSizeInfo</a>[] <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.301">bucketSizeInfos</a></pre>
+<pre>private <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.BucketSizeInfo.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketAllocator.BucketSizeInfo</a>[] <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.302">bucketSizeInfos</a></pre>
</li>
</ul>
<a name="totalSize">
@@ -431,7 +431,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>totalSize</h4>
-<pre>private final long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.302">totalSize</a></pre>
+<pre>private final long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.303">totalSize</a></pre>
</li>
</ul>
<a name="usedSize">
@@ -440,7 +440,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockListLast">
<li class="blockList">
<h4>usedSize</h4>
-<pre>private transient long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.303">usedSize</a></pre>
+<pre>private transient long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.304">usedSize</a></pre>
</li>
</ul>
</li>
@@ -457,7 +457,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>BucketAllocator</h4>
-<pre><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.305">BucketAllocator</a>(long availableSpace,
+<pre><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.306">BucketAllocator</a>(long availableSpace,
int[] bucketSizes)
throws <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocatorException.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketAllocatorException</a></pre>
<dl>
@@ -472,7 +472,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockListLast">
<li class="blockList">
<h4>BucketAllocator</h4>
-<pre><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.341">BucketAllocator</a>(long availableSpace,
+<pre><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.342">BucketAllocator</a>(long availableSpace,
int[] bucketSizes,
<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><<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/BucketEntry.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketEntry</a>> map,
<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> realCacheSize)
@@ -503,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>roundUpToBucketSizeInfo</h4>
-<pre>public <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.BucketSizeInfo.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketAllocator.BucketSizeInfo</a> <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.284">roundUpToBucketSizeInfo</a>(int blockSize)</pre>
+<pre>public <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.BucketSizeInfo.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketAllocator.BucketSizeInfo</a> <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.285">roundUpToBucketSizeInfo</a>(int blockSize)</pre>
<div class="block">Round up the given block size to bucket size, and get the corresponding
BucketSizeInfo</div>
</li>
@@ -514,7 +514,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 <a href="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/BucketAllocator.html#line.410">toString</a>()</pre>
+<pre>public <a href="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/BucketAllocator.html#line.411">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> in class <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>
@@ -527,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>getUsedSize</h4>
-<pre>public long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.421">getUsedSize</a>()</pre>
+<pre>public long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.422">getUsedSize</a>()</pre>
</li>
</ul>
<a name="getFreeSize--">
@@ -536,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>getFreeSize</h4>
-<pre>public long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.425">getFreeSize</a>()</pre>
+<pre>public long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.426">getFreeSize</a>()</pre>
</li>
</ul>
<a name="getTotalSize--">
@@ -545,7 +545,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>getTotalSize</h4>
-<pre>public long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.429">getTotalSize</a>()</pre>
+<pre>public long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.430">getTotalSize</a>()</pre>
</li>
</ul>
<a name="allocateBlock-int-">
@@ -554,7 +554,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>allocateBlock</h4>
-<pre>public long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.440">allocateBlock</a>(int blockSize)
+<pre>public long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.441">allocateBlock</a>(int blockSize)
throws <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/CacheFullException.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">CacheFullException</a>,
<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocatorException.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketAllocatorException</a></pre>
<div class="block">Allocate a block with specified size. Return the offset</div>
@@ -575,7 +575,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>grabGlobalCompletelyFreeBucket</h4>
-<pre>private <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.Bucket.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketAllocator.Bucket</a> <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.458">grabGlobalCompletelyFreeBucket</a>()</pre>
+<pre>private <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.Bucket.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketAllocator.Bucket</a> <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.459">grabGlobalCompletelyFreeBucket</a>()</pre>
</li>
</ul>
<a name="freeBlock-long-">
@@ -584,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>freeBlock</h4>
-<pre>public int <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.471">freeBlock</a>(long offset)</pre>
+<pre>public int <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.472">freeBlock</a>(long offset)</pre>
<div class="block">Free a block with the offset</div>
<dl>
<dt><span class="paramLabel">Parameters:</span></dt>
@@ -600,7 +600,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>sizeIndexOfAllocation</h4>
-<pre>public int <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.480">sizeIndexOfAllocation</a>(long offset)</pre>
+<pre>public int <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.481">sizeIndexOfAllocation</a>(long offset)</pre>
</li>
</ul>
<a name="sizeOfAllocation-long-">
@@ -609,7 +609,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>sizeOfAllocation</h4>
-<pre>public int <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.487">sizeOfAllocation</a>(long offset)</pre>
+<pre>public int <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.488">sizeOfAllocation</a>(long offset)</pre>
</li>
</ul>
<a name="getBuckets--">
@@ -618,7 +618,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>getBuckets</h4>
-<pre>public <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.Bucket.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketAllocator.Bucket</a>[] <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.541">getBuckets</a>()</pre>
+<pre>public <a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.Bucket.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketAllocator.Bucket</a>[] <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.542">getBuckets</a>()</pre>
</li>
</ul>
<a name="logStatistics--">
@@ -627,7 +627,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>logStatistics</h4>
-<pre>void <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.545">logStatistics</a>()</pre>
+<pre>void <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.546">logStatistics</a>()</pre>
</li>
</ul>
<a name="getIndexStatistics-org.apache.hadoop.hbase.io.hfile.bucket.BucketAllocator.IndexStatistics-">
@@ -636,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>getIndexStatistics</h4>
-<pre><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.IndexStatistics.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketAllocator.IndexStatistics</a>[] <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.557">getIndexStatistics</a>(<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.IndexStatistics.html" title="class in org.apache.hadoop.hbas [...]
+<pre><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.IndexStatistics.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketAllocator.IndexStatistics</a>[] <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.558">getIndexStatistics</a>(<a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.IndexStatistics.html" title="class in org.apache.hadoop.hbas [...]
</li>
</ul>
<a name="getIndexStatistics--">
@@ -645,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>getIndexStatistics</h4>
-<pre><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.IndexStatistics.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketAllocator.IndexStatistics</a>[] <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.568">getIndexStatistics</a>()</pre>
+<pre><a href="../../../../../../../org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.IndexStatistics.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketAllocator.IndexStatistics</a>[] <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.569">getIndexStatistics</a>()</pre>
</li>
</ul>
<a name="freeBlock-long:A-">
@@ -654,7 +654,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>freeBlock</h4>
-<pre>public long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.575">freeBlock</a>(long[] freeList)</pre>
+<pre>public long <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.576">freeBlock</a>(long[] freeList)</pre>
</li>
</ul>
<a name="getBucketIndex-long-">
@@ -663,7 +663,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>getBucketIndex</h4>
-<pre>public int <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.582">getBucketIndex</a>(long offset)</pre>
+<pre>public int <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.583">getBucketIndex</a>(long offset)</pre>
</li>
</ul>
<a name="getLeastFilledBuckets-java.util.Set-int-">
@@ -672,7 +672,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockListLast">
<li class="blockList">
<h4>getLeastFilledBuckets</h4>
-<pre>public <a href="https://docs.oracle.com/javase/8/docs/api/java/util/Set.html?is-external=true" title="class or interface in java.util">Set</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>> <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.597">getLeastFilledBuckets</a>(<a href="https://docs.oracle.com/javase/8/docs/ [...]
+<pre>public <a href="https://docs.oracle.com/javase/8/docs/api/java/util/Set.html?is-external=true" title="class or interface in java.util">Set</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>> <a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html#line.598">getLeastFilledBuckets</a>(<a href="https://docs.oracle.com/javase/8/docs/ [...]
int bucketCount)</pre>
<div class="block">Returns a set of indices of the buckets that are least filled
excluding the offsets, we also the fully free buckets for the
diff --git a/devapidocs/org/apache/hadoop/hbase/security/AbstractHBaseSaslRpcClient.html b/devapidocs/org/apache/hadoop/hbase/security/AbstractHBaseSaslRpcClient.html
index bfacda2..8baf3dc 100644
--- a/devapidocs/org/apache/hadoop/hbase/security/AbstractHBaseSaslRpcClient.html
+++ b/devapidocs/org/apache/hadoop/hbase/security/AbstractHBaseSaslRpcClient.html
@@ -222,8 +222,8 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<tr id="i2" class="altColor">
<td class="colFirst"><code>byte[]</code></td>
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/security/AbstractHBaseSaslRpcClient.html#getInitialResponse--">getInitialResponse</a></span>()</code>
-<div class="block">Computes the initial response a client sends to a server to begin the SASL
- challenge/response handshake.</div>
+<div class="block">Computes the initial response a client sends to a server to begin the SASL challenge/response
+ handshake.</div>
</td>
</tr>
<tr id="i3" class="rowColor">
@@ -366,20 +366,15 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>getInitialResponse</h4>
-<pre>public byte[] <a href="../../../../../src-html/org/apache/hadoop/hbase/security/AbstractHBaseSaslRpcClient.html#line.104">getInitialResponse</a>()
+<pre>public byte[] <a href="../../../../../src-html/org/apache/hadoop/hbase/security/AbstractHBaseSaslRpcClient.html#line.98">getInitialResponse</a>()
throws <a href="https://docs.oracle.com/javase/8/docs/api/javax/security/sasl/SaslException.html?is-external=true" title="class or interface in javax.security.sasl">SaslException</a></pre>
-<div class="block">Computes the initial response a client sends to a server to begin the SASL
- challenge/response handshake. If the client's SASL mechanism does not require
- that an initial response is sent to begin the handshake, this method will return
- a null byte array, indicating no initial response needs to be sent by this client.
-
- It is unclear as to whether all SASL implementations will return a non-empty initial
- response, so this implementation is written such that this is allowed. All known
- SASL mechanism implementations in the JDK provide non-empty initial responses.</div>
+<div class="block">Computes the initial response a client sends to a server to begin the SASL challenge/response
+ handshake. If the client's SASL mechanism does not have an initial response, an empty token
+ will be returned without querying the evaluateChallenge method, as an authentication processing
+ must be started by client.</div>
<dl>
<dt><span class="returnLabel">Returns:</span></dt>
-<dd>The client's initial response to send the server (which may be empty), or null
- if this implementation does not require an initial response to be sent.</dd>
+<dd>The client's initial response to send the server (which may be empty).</dd>
<dt><span class="throwsLabel">Throws:</span></dt>
<dd><code><a href="https://docs.oracle.com/javase/8/docs/api/javax/security/sasl/SaslException.html?is-external=true" title="class or interface in javax.security.sasl">SaslException</a></code></dd>
</dl>
@@ -391,7 +386,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>isComplete</h4>
-<pre>public boolean <a href="../../../../../src-html/org/apache/hadoop/hbase/security/AbstractHBaseSaslRpcClient.html#line.111">isComplete</a>()</pre>
+<pre>public boolean <a href="../../../../../src-html/org/apache/hadoop/hbase/security/AbstractHBaseSaslRpcClient.html#line.105">isComplete</a>()</pre>
</li>
</ul>
<a name="evaluateChallenge-byte:A-">
@@ -400,7 +395,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>evaluateChallenge</h4>
-<pre>public byte[] <a href="../../../../../src-html/org/apache/hadoop/hbase/security/AbstractHBaseSaslRpcClient.html#line.115">evaluateChallenge</a>(byte[] challenge)
+<pre>public byte[] <a href="../../../../../src-html/org/apache/hadoop/hbase/security/AbstractHBaseSaslRpcClient.html#line.109">evaluateChallenge</a>(byte[] challenge)
throws <a href="https://docs.oracle.com/javase/8/docs/api/javax/security/sasl/SaslException.html?is-external=true" title="class or interface in javax.security.sasl">SaslException</a></pre>
<dl>
<dt><span class="throwsLabel">Throws:</span></dt>
@@ -414,7 +409,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockListLast">
<li class="blockList">
<h4>dispose</h4>
-<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/security/AbstractHBaseSaslRpcClient.html#line.120">dispose</a>()</pre>
+<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/security/AbstractHBaseSaslRpcClient.html#line.114">dispose</a>()</pre>
<div class="block">Release resources used by wrapped saslClient</div>
</li>
</ul>
diff --git a/devapidocs/org/apache/hadoop/hbase/security/NettyHBaseSaslRpcClientHandler.html b/devapidocs/org/apache/hadoop/hbase/security/NettyHBaseSaslRpcClientHandler.html
index 9678d3a..55f4bf2 100644
--- a/devapidocs/org/apache/hadoop/hbase/security/NettyHBaseSaslRpcClientHandler.html
+++ b/devapidocs/org/apache/hadoop/hbase/security/NettyHBaseSaslRpcClientHandler.html
@@ -482,7 +482,7 @@ extends org.apache.hbase.thirdparty.io.netty.channel.SimpleChannelInboundHandler
<ul class="blockList">
<li class="blockList">
<h4>channelRead0</h4>
-<pre>protected void <a href="../../../../../src-html/org/apache/hadoop/hbase/security/NettyHBaseSaslRpcClientHandler.html#line.145">channelRead0</a>(org.apache.hbase.thirdparty.io.netty.channel.ChannelHandlerContext ctx,
+<pre>protected void <a href="../../../../../src-html/org/apache/hadoop/hbase/security/NettyHBaseSaslRpcClientHandler.html#line.143">channelRead0</a>(org.apache.hbase.thirdparty.io.netty.channel.ChannelHandlerContext ctx,
org.apache.hbase.thirdparty.io.netty.buffer.ByteBuf msg)
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>
@@ -499,7 +499,7 @@ extends org.apache.hbase.thirdparty.io.netty.channel.SimpleChannelInboundHandler
<ul class="blockList">
<li class="blockList">
<h4>channelInactive</h4>
-<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/security/NettyHBaseSaslRpcClientHandler.html#line.175">channelInactive</a>(org.apache.hbase.thirdparty.io.netty.channel.ChannelHandlerContext ctx)
+<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/security/NettyHBaseSaslRpcClientHandler.html#line.173">channelInactive</a>(org.apache.hbase.thirdparty.io.netty.channel.ChannelHandlerContext ctx)
throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
<dl>
<dt><span class="overrideSpecifyLabel">Specified by:</span></dt>
@@ -517,7 +517,7 @@ extends org.apache.hbase.thirdparty.io.netty.channel.SimpleChannelInboundHandler
<ul class="blockListLast">
<li class="blockList">
<h4>exceptionCaught</h4>
-<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/security/NettyHBaseSaslRpcClientHandler.html#line.182">exceptionCaught</a>(org.apache.hbase.thirdparty.io.netty.channel.ChannelHandlerContext ctx,
+<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/security/NettyHBaseSaslRpcClientHandler.html#line.180">exceptionCaught</a>(org.apache.hbase.thirdparty.io.netty.channel.ChannelHandlerContext ctx,
<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Throwable.html?is-external=true" title="class or interface in java.lang">Throwable</a> cause)</pre>
<dl>
<dt><span class="overrideSpecifyLabel">Specified by:</span></dt>
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/Version.html b/devapidocs/src-html/org/apache/hadoop/hbase/Version.html
index 3716a84..84b90bb 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/Version.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/Version.html
@@ -18,9 +18,9 @@
<span class="sourceLineNo">010</span> justification="Intentional; to be modified in test")<a name="line.10"></a>
<span class="sourceLineNo">011</span>public class Version {<a name="line.11"></a>
<span class="sourceLineNo">012</span> public static final String version = new String("3.0.0-SNAPSHOT");<a name="line.12"></a>
-<span class="sourceLineNo">013</span> public static final String revision = "e6cc5eb2f0623f02eaa3542308fc3d82fd3abd9f";<a name="line.13"></a>
+<span class="sourceLineNo">013</span> public static final String revision = "ec0d9d767e697c8d6726d15bf06ce9a19a756263";<a name="line.13"></a>
<span class="sourceLineNo">014</span> public static final String user = "jenkins";<a name="line.14"></a>
-<span class="sourceLineNo">015</span> public static final String date = "Sat Apr 25 19:30:56 UTC 2020";<a name="line.15"></a>
+<span class="sourceLineNo">015</span> public static final String date = "Sun Apr 26 14:38:40 UTC 2020";<a name="line.15"></a>
<span class="sourceLineNo">016</span> public static final String url = "git://jenkins-websites-he-de.apache.org/home/jenkins/jenkins-slave/workspace/hbase_generate_website/hbase";<a name="line.16"></a>
<span class="sourceLineNo">017</span> public static final String srcChecksum = "(stdin)=";<a name="line.17"></a>
<span class="sourceLineNo">018</span>}<a name="line.18"></a>
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.Bucket.html b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.Bucket.html
index a3cd853..0a4475b 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.Bucket.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.Bucket.html
@@ -277,358 +277,359 @@
<span class="sourceLineNo">269</span><a name="line.269"></a>
<span class="sourceLineNo">270</span> // Default block size in hbase is 64K, so we choose more sizes near 64K, you'd better<a name="line.270"></a>
<span class="sourceLineNo">271</span> // reset it according to your cluster's block size distribution<a name="line.271"></a>
-<span class="sourceLineNo">272</span> // TODO Support the view of block size distribution statistics<a name="line.272"></a>
-<span class="sourceLineNo">273</span> // TODO: Why we add the extra 1024 bytes? Slop?<a name="line.273"></a>
-<span class="sourceLineNo">274</span> private static final int DEFAULT_BUCKET_SIZES[] = { 4 * 1024 + 1024, 8 * 1024 + 1024,<a name="line.274"></a>
-<span class="sourceLineNo">275</span> 16 * 1024 + 1024, 32 * 1024 + 1024, 40 * 1024 + 1024, 48 * 1024 + 1024,<a name="line.275"></a>
-<span class="sourceLineNo">276</span> 56 * 1024 + 1024, 64 * 1024 + 1024, 96 * 1024 + 1024, 128 * 1024 + 1024,<a name="line.276"></a>
-<span class="sourceLineNo">277</span> 192 * 1024 + 1024, 256 * 1024 + 1024, 384 * 1024 + 1024,<a name="line.277"></a>
-<span class="sourceLineNo">278</span> 512 * 1024 + 1024 };<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> * Round up the given block size to bucket size, and get the corresponding<a name="line.281"></a>
-<span class="sourceLineNo">282</span> * BucketSizeInfo<a name="line.282"></a>
-<span class="sourceLineNo">283</span> */<a name="line.283"></a>
-<span class="sourceLineNo">284</span> public BucketSizeInfo roundUpToBucketSizeInfo(int blockSize) {<a name="line.284"></a>
-<span class="sourceLineNo">285</span> for (int i = 0; i < bucketSizes.length; ++i)<a name="line.285"></a>
-<span class="sourceLineNo">286</span> if (blockSize <= bucketSizes[i])<a name="line.286"></a>
-<span class="sourceLineNo">287</span> return bucketSizeInfos[i];<a name="line.287"></a>
-<span class="sourceLineNo">288</span> return null;<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> /**<a name="line.291"></a>
-<span class="sourceLineNo">292</span> * So, what is the minimum amount of items we'll tolerate in a single bucket?<a name="line.292"></a>
-<span class="sourceLineNo">293</span> */<a name="line.293"></a>
-<span class="sourceLineNo">294</span> static public final int FEWEST_ITEMS_IN_BUCKET = 4;<a name="line.294"></a>
-<span class="sourceLineNo">295</span><a name="line.295"></a>
-<span class="sourceLineNo">296</span> private final int[] bucketSizes;<a name="line.296"></a>
-<span class="sourceLineNo">297</span> private final int bigItemSize;<a name="line.297"></a>
-<span class="sourceLineNo">298</span> // The capacity size for each bucket<a name="line.298"></a>
-<span class="sourceLineNo">299</span> private final long bucketCapacity;<a name="line.299"></a>
-<span class="sourceLineNo">300</span> private Bucket[] buckets;<a name="line.300"></a>
-<span class="sourceLineNo">301</span> private BucketSizeInfo[] bucketSizeInfos;<a name="line.301"></a>
-<span class="sourceLineNo">302</span> private final long totalSize;<a name="line.302"></a>
-<span class="sourceLineNo">303</span> private transient long usedSize = 0;<a name="line.303"></a>
-<span class="sourceLineNo">304</span><a name="line.304"></a>
-<span class="sourceLineNo">305</span> BucketAllocator(long availableSpace, int[] bucketSizes)<a name="line.305"></a>
-<span class="sourceLineNo">306</span> throws BucketAllocatorException {<a name="line.306"></a>
-<span class="sourceLineNo">307</span> this.bucketSizes = bucketSizes == null ? DEFAULT_BUCKET_SIZES : bucketSizes;<a name="line.307"></a>
-<span class="sourceLineNo">308</span> Arrays.sort(this.bucketSizes);<a name="line.308"></a>
-<span class="sourceLineNo">309</span> this.bigItemSize = Ints.max(this.bucketSizes);<a name="line.309"></a>
-<span class="sourceLineNo">310</span> this.bucketCapacity = FEWEST_ITEMS_IN_BUCKET * (long) bigItemSize;<a name="line.310"></a>
-<span class="sourceLineNo">311</span> buckets = new Bucket[(int) (availableSpace / bucketCapacity)];<a name="line.311"></a>
-<span class="sourceLineNo">312</span> if (buckets.length < this.bucketSizes.length)<a name="line.312"></a>
-<span class="sourceLineNo">313</span> throw new BucketAllocatorException("Bucket allocator size too small (" + buckets.length +<a name="line.313"></a>
-<span class="sourceLineNo">314</span> "); must have room for at least " + this.bucketSizes.length + " buckets");<a name="line.314"></a>
-<span class="sourceLineNo">315</span> bucketSizeInfos = new BucketSizeInfo[this.bucketSizes.length];<a name="line.315"></a>
-<span class="sourceLineNo">316</span> for (int i = 0; i < this.bucketSizes.length; ++i) {<a name="line.316"></a>
-<span class="sourceLineNo">317</span> bucketSizeInfos[i] = new BucketSizeInfo(i);<a name="line.317"></a>
-<span class="sourceLineNo">318</span> }<a name="line.318"></a>
-<span class="sourceLineNo">319</span> for (int i = 0; i < buckets.length; ++i) {<a name="line.319"></a>
-<span class="sourceLineNo">320</span> buckets[i] = new Bucket(bucketCapacity * i);<a name="line.320"></a>
-<span class="sourceLineNo">321</span> bucketSizeInfos[i < this.bucketSizes.length ? i : this.bucketSizes.length - 1]<a name="line.321"></a>
-<span class="sourceLineNo">322</span> .instantiateBucket(buckets[i]);<a name="line.322"></a>
-<span class="sourceLineNo">323</span> }<a name="line.323"></a>
-<span class="sourceLineNo">324</span> this.totalSize = ((long) buckets.length) * bucketCapacity;<a name="line.324"></a>
-<span class="sourceLineNo">325</span> if (LOG.isInfoEnabled()) {<a name="line.325"></a>
-<span class="sourceLineNo">326</span> LOG.info("Cache totalSize=" + this.totalSize + ", buckets=" + this.buckets.length +<a name="line.326"></a>
-<span class="sourceLineNo">327</span> ", bucket capacity=" + this.bucketCapacity +<a name="line.327"></a>
-<span class="sourceLineNo">328</span> "=(" + FEWEST_ITEMS_IN_BUCKET + "*" + this.bigItemSize + ")=" +<a name="line.328"></a>
-<span class="sourceLineNo">329</span> "(FEWEST_ITEMS_IN_BUCKET*(largest configured bucketcache size))");<a name="line.329"></a>
-<span class="sourceLineNo">330</span> }<a name="line.330"></a>
-<span class="sourceLineNo">331</span> }<a name="line.331"></a>
-<span class="sourceLineNo">332</span><a name="line.332"></a>
-<span class="sourceLineNo">333</span> /**<a name="line.333"></a>
-<span class="sourceLineNo">334</span> * Rebuild the allocator's data structures from a persisted map.<a name="line.334"></a>
-<span class="sourceLineNo">335</span> * @param availableSpace capacity of cache<a name="line.335"></a>
-<span class="sourceLineNo">336</span> * @param map A map stores the block key and BucketEntry(block's meta data<a name="line.336"></a>
-<span class="sourceLineNo">337</span> * like offset, length)<a name="line.337"></a>
-<span class="sourceLineNo">338</span> * @param realCacheSize cached data size statistics for bucket cache<a name="line.338"></a>
-<span class="sourceLineNo">339</span> * @throws BucketAllocatorException<a name="line.339"></a>
-<span class="sourceLineNo">340</span> */<a name="line.340"></a>
-<span class="sourceLineNo">341</span> BucketAllocator(long availableSpace, int[] bucketSizes, Map<BlockCacheKey, BucketEntry> map,<a name="line.341"></a>
-<span class="sourceLineNo">342</span> LongAdder realCacheSize) throws BucketAllocatorException {<a name="line.342"></a>
-<span class="sourceLineNo">343</span> this(availableSpace, bucketSizes);<a name="line.343"></a>
-<span class="sourceLineNo">344</span><a name="line.344"></a>
-<span class="sourceLineNo">345</span> // each bucket has an offset, sizeindex. probably the buckets are too big<a name="line.345"></a>
-<span class="sourceLineNo">346</span> // in our default state. so what we do is reconfigure them according to what<a name="line.346"></a>
-<span class="sourceLineNo">347</span> // we've found. we can only reconfigure each bucket once; if more than once,<a name="line.347"></a>
-<span class="sourceLineNo">348</span> // we know there's a bug, so we just log the info, throw, and start again...<a name="line.348"></a>
-<span class="sourceLineNo">349</span> boolean[] reconfigured = new boolean[buckets.length];<a name="line.349"></a>
-<span class="sourceLineNo">350</span> int sizeNotMatchedCount = 0;<a name="line.350"></a>
-<span class="sourceLineNo">351</span> int insufficientCapacityCount = 0;<a name="line.351"></a>
-<span class="sourceLineNo">352</span> Iterator<Map.Entry<BlockCacheKey, BucketEntry>> iterator = map.entrySet().iterator();<a name="line.352"></a>
-<span class="sourceLineNo">353</span> while (iterator.hasNext()) {<a name="line.353"></a>
-<span class="sourceLineNo">354</span> Map.Entry<BlockCacheKey, BucketEntry> entry = iterator.next();<a name="line.354"></a>
-<span class="sourceLineNo">355</span> long foundOffset = entry.getValue().offset();<a name="line.355"></a>
-<span class="sourceLineNo">356</span> int foundLen = entry.getValue().getLength();<a name="line.356"></a>
-<span class="sourceLineNo">357</span> int bucketSizeIndex = -1;<a name="line.357"></a>
-<span class="sourceLineNo">358</span> for (int i = 0; i < this.bucketSizes.length; ++i) {<a name="line.358"></a>
-<span class="sourceLineNo">359</span> if (foundLen <= this.bucketSizes[i]) {<a name="line.359"></a>
-<span class="sourceLineNo">360</span> bucketSizeIndex = i;<a name="line.360"></a>
-<span class="sourceLineNo">361</span> break;<a name="line.361"></a>
-<span class="sourceLineNo">362</span> }<a name="line.362"></a>
-<span class="sourceLineNo">363</span> }<a name="line.363"></a>
-<span class="sourceLineNo">364</span> if (bucketSizeIndex == -1) {<a name="line.364"></a>
-<span class="sourceLineNo">365</span> sizeNotMatchedCount++;<a name="line.365"></a>
-<span class="sourceLineNo">366</span> iterator.remove();<a name="line.366"></a>
-<span class="sourceLineNo">367</span> continue;<a name="line.367"></a>
-<span class="sourceLineNo">368</span> }<a name="line.368"></a>
-<span class="sourceLineNo">369</span> int bucketNo = (int) (foundOffset / bucketCapacity);<a name="line.369"></a>
-<span class="sourceLineNo">370</span> if (bucketNo < 0 || bucketNo >= buckets.length) {<a name="line.370"></a>
-<span class="sourceLineNo">371</span> insufficientCapacityCount++;<a name="line.371"></a>
-<span class="sourceLineNo">372</span> iterator.remove();<a name="line.372"></a>
-<span class="sourceLineNo">373</span> continue;<a name="line.373"></a>
-<span class="sourceLineNo">374</span> }<a name="line.374"></a>
-<span class="sourceLineNo">375</span> Bucket b = buckets[bucketNo];<a name="line.375"></a>
-<span class="sourceLineNo">376</span> if (reconfigured[bucketNo]) {<a name="line.376"></a>
-<span class="sourceLineNo">377</span> if (b.sizeIndex() != bucketSizeIndex) {<a name="line.377"></a>
-<span class="sourceLineNo">378</span> throw new BucketAllocatorException("Inconsistent allocation in bucket map;");<a name="line.378"></a>
-<span class="sourceLineNo">379</span> }<a name="line.379"></a>
-<span class="sourceLineNo">380</span> } else {<a name="line.380"></a>
-<span class="sourceLineNo">381</span> if (!b.isCompletelyFree()) {<a name="line.381"></a>
-<span class="sourceLineNo">382</span> throw new BucketAllocatorException(<a name="line.382"></a>
-<span class="sourceLineNo">383</span> "Reconfiguring bucket " + bucketNo + " but it's already allocated; corrupt data");<a name="line.383"></a>
-<span class="sourceLineNo">384</span> }<a name="line.384"></a>
-<span class="sourceLineNo">385</span> // Need to remove the bucket from whichever list it's currently in at<a name="line.385"></a>
-<span class="sourceLineNo">386</span> // the moment...<a name="line.386"></a>
-<span class="sourceLineNo">387</span> BucketSizeInfo bsi = bucketSizeInfos[bucketSizeIndex];<a name="line.387"></a>
-<span class="sourceLineNo">388</span> BucketSizeInfo oldbsi = bucketSizeInfos[b.sizeIndex()];<a name="line.388"></a>
-<span class="sourceLineNo">389</span> oldbsi.removeBucket(b);<a name="line.389"></a>
-<span class="sourceLineNo">390</span> bsi.instantiateBucket(b);<a name="line.390"></a>
-<span class="sourceLineNo">391</span> reconfigured[bucketNo] = true;<a name="line.391"></a>
-<span class="sourceLineNo">392</span> }<a name="line.392"></a>
-<span class="sourceLineNo">393</span> realCacheSize.add(foundLen);<a name="line.393"></a>
-<span class="sourceLineNo">394</span> buckets[bucketNo].addAllocation(foundOffset);<a name="line.394"></a>
-<span class="sourceLineNo">395</span> usedSize += buckets[bucketNo].getItemAllocationSize();<a name="line.395"></a>
-<span class="sourceLineNo">396</span> bucketSizeInfos[bucketSizeIndex].blockAllocated(b);<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> if (sizeNotMatchedCount > 0) {<a name="line.399"></a>
-<span class="sourceLineNo">400</span> LOG.warn("There are " + sizeNotMatchedCount + " blocks which can't be rebuilt because " +<a name="line.400"></a>
-<span class="sourceLineNo">401</span> "there is no matching bucket size for these blocks");<a name="line.401"></a>
-<span class="sourceLineNo">402</span> }<a name="line.402"></a>
-<span class="sourceLineNo">403</span> if (insufficientCapacityCount > 0) {<a name="line.403"></a>
-<span class="sourceLineNo">404</span> LOG.warn("There are " + insufficientCapacityCount + " blocks which can't be rebuilt - "<a name="line.404"></a>
-<span class="sourceLineNo">405</span> + "did you shrink the cache?");<a name="line.405"></a>
-<span class="sourceLineNo">406</span> }<a name="line.406"></a>
-<span class="sourceLineNo">407</span> }<a name="line.407"></a>
-<span class="sourceLineNo">408</span><a name="line.408"></a>
-<span class="sourceLineNo">409</span> @Override<a name="line.409"></a>
-<span class="sourceLineNo">410</span> public String toString() {<a name="line.410"></a>
-<span class="sourceLineNo">411</span> StringBuilder sb = new StringBuilder(1024);<a name="line.411"></a>
-<span class="sourceLineNo">412</span> for (int i = 0; i < buckets.length; ++i) {<a name="line.412"></a>
-<span class="sourceLineNo">413</span> Bucket b = buckets[i];<a name="line.413"></a>
-<span class="sourceLineNo">414</span> if (i > 0) sb.append(", ");<a name="line.414"></a>
-<span class="sourceLineNo">415</span> sb.append("bucket.").append(i).append(": size=").append(b.getItemAllocationSize());<a name="line.415"></a>
-<span class="sourceLineNo">416</span> sb.append(", freeCount=").append(b.freeCount()).append(", used=").append(b.usedCount());<a name="line.416"></a>
-<span class="sourceLineNo">417</span> }<a name="line.417"></a>
-<span class="sourceLineNo">418</span> return sb.toString();<a name="line.418"></a>
-<span class="sourceLineNo">419</span> }<a name="line.419"></a>
-<span class="sourceLineNo">420</span><a name="line.420"></a>
-<span class="sourceLineNo">421</span> public long getUsedSize() {<a name="line.421"></a>
-<span class="sourceLineNo">422</span> return this.usedSize;<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> public long getFreeSize() {<a name="line.425"></a>
-<span class="sourceLineNo">426</span> return this.totalSize - getUsedSize();<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> public long getTotalSize() {<a name="line.429"></a>
-<span class="sourceLineNo">430</span> return this.totalSize;<a name="line.430"></a>
-<span class="sourceLineNo">431</span> }<a name="line.431"></a>
-<span class="sourceLineNo">432</span><a name="line.432"></a>
-<span class="sourceLineNo">433</span> /**<a name="line.433"></a>
-<span class="sourceLineNo">434</span> * Allocate a block with specified size. Return the offset<a name="line.434"></a>
-<span class="sourceLineNo">435</span> * @param blockSize size of block<a name="line.435"></a>
-<span class="sourceLineNo">436</span> * @throws BucketAllocatorException<a name="line.436"></a>
-<span class="sourceLineNo">437</span> * @throws CacheFullException<a name="line.437"></a>
-<span class="sourceLineNo">438</span> * @return the offset in the IOEngine<a name="line.438"></a>
-<span class="sourceLineNo">439</span> */<a name="line.439"></a>
-<span class="sourceLineNo">440</span> public synchronized long allocateBlock(int blockSize) throws CacheFullException,<a name="line.440"></a>
-<span class="sourceLineNo">441</span> BucketAllocatorException {<a name="line.441"></a>
-<span class="sourceLineNo">442</span> assert blockSize > 0;<a name="line.442"></a>
-<span class="sourceLineNo">443</span> BucketSizeInfo bsi = roundUpToBucketSizeInfo(blockSize);<a name="line.443"></a>
-<span class="sourceLineNo">444</span> if (bsi == null) {<a name="line.444"></a>
-<span class="sourceLineNo">445</span> throw new BucketAllocatorException("Allocation too big size=" + blockSize +<a name="line.445"></a>
-<span class="sourceLineNo">446</span> "; adjust BucketCache sizes " + BlockCacheFactory.BUCKET_CACHE_BUCKETS_KEY +<a name="line.446"></a>
-<span class="sourceLineNo">447</span> " to accomodate if size seems reasonable and you want it cached.");<a name="line.447"></a>
-<span class="sourceLineNo">448</span> }<a name="line.448"></a>
-<span class="sourceLineNo">449</span> long offset = bsi.allocateBlock();<a name="line.449"></a>
-<span class="sourceLineNo">450</span><a name="line.450"></a>
-<span class="sourceLineNo">451</span> // Ask caller to free up space and try again!<a name="line.451"></a>
-<span class="sourceLineNo">452</span> if (offset < 0)<a name="line.452"></a>
-<span class="sourceLineNo">453</span> throw new CacheFullException(blockSize, bsi.sizeIndex());<a name="line.453"></a>
-<span class="sourceLineNo">454</span> usedSize += bucketSizes[bsi.sizeIndex()];<a name="line.454"></a>
-<span class="sourceLineNo">455</span> return offset;<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> private Bucket grabGlobalCompletelyFreeBucket() {<a name="line.458"></a>
-<span class="sourceLineNo">459</span> for (BucketSizeInfo bsi : bucketSizeInfos) {<a name="line.459"></a>
-<span class="sourceLineNo">460</span> Bucket b = bsi.findAndRemoveCompletelyFreeBucket();<a name="line.460"></a>
-<span class="sourceLineNo">461</span> if (b != null) return b;<a name="line.461"></a>
-<span class="sourceLineNo">462</span> }<a name="line.462"></a>
-<span class="sourceLineNo">463</span> return null;<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> * Free a block with the offset<a name="line.467"></a>
-<span class="sourceLineNo">468</span> * @param offset block's offset<a name="line.468"></a>
-<span class="sourceLineNo">469</span> * @return size freed<a name="line.469"></a>
-<span class="sourceLineNo">470</span> */<a name="line.470"></a>
-<span class="sourceLineNo">471</span> public synchronized int freeBlock(long offset) {<a name="line.471"></a>
-<span class="sourceLineNo">472</span> int bucketNo = (int) (offset / bucketCapacity);<a name="line.472"></a>
-<span class="sourceLineNo">473</span> assert bucketNo >= 0 && bucketNo < buckets.length;<a name="line.473"></a>
-<span class="sourceLineNo">474</span> Bucket targetBucket = buckets[bucketNo];<a name="line.474"></a>
-<span class="sourceLineNo">475</span> bucketSizeInfos[targetBucket.sizeIndex()].freeBlock(targetBucket, offset);<a name="line.475"></a>
-<span class="sourceLineNo">476</span> usedSize -= targetBucket.getItemAllocationSize();<a name="line.476"></a>
-<span class="sourceLineNo">477</span> return targetBucket.getItemAllocationSize();<a name="line.477"></a>
-<span class="sourceLineNo">478</span> }<a name="line.478"></a>
-<span class="sourceLineNo">479</span><a name="line.479"></a>
-<span class="sourceLineNo">480</span> public int sizeIndexOfAllocation(long offset) {<a name="line.480"></a>
-<span class="sourceLineNo">481</span> int bucketNo = (int) (offset / bucketCapacity);<a name="line.481"></a>
-<span class="sourceLineNo">482</span> assert bucketNo >= 0 && bucketNo < buckets.length;<a name="line.482"></a>
-<span class="sourceLineNo">483</span> Bucket targetBucket = buckets[bucketNo];<a name="line.483"></a>
-<span class="sourceLineNo">484</span> return targetBucket.sizeIndex();<a name="line.484"></a>
-<span class="sourceLineNo">485</span> }<a name="line.485"></a>
-<span class="sourceLineNo">486</span><a name="line.486"></a>
-<span class="sourceLineNo">487</span> public int sizeOfAllocation(long offset) {<a name="line.487"></a>
-<span class="sourceLineNo">488</span> int bucketNo = (int) (offset / bucketCapacity);<a name="line.488"></a>
-<span class="sourceLineNo">489</span> assert bucketNo >= 0 && bucketNo < buckets.length;<a name="line.489"></a>
-<span class="sourceLineNo">490</span> Bucket targetBucket = buckets[bucketNo];<a name="line.490"></a>
-<span class="sourceLineNo">491</span> return targetBucket.getItemAllocationSize();<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> static class IndexStatistics {<a name="line.494"></a>
-<span class="sourceLineNo">495</span> private long freeCount, usedCount, itemSize, totalCount;<a name="line.495"></a>
-<span class="sourceLineNo">496</span><a name="line.496"></a>
-<span class="sourceLineNo">497</span> public long freeCount() {<a name="line.497"></a>
-<span class="sourceLineNo">498</span> return freeCount;<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> public long usedCount() {<a name="line.501"></a>
-<span class="sourceLineNo">502</span> return usedCount;<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> public long totalCount() {<a name="line.505"></a>
-<span class="sourceLineNo">506</span> return totalCount;<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> public long freeBytes() {<a name="line.509"></a>
-<span class="sourceLineNo">510</span> return freeCount * itemSize;<a name="line.510"></a>
-<span class="sourceLineNo">511</span> }<a name="line.511"></a>
-<span class="sourceLineNo">512</span><a name="line.512"></a>
-<span class="sourceLineNo">513</span> public long usedBytes() {<a name="line.513"></a>
-<span class="sourceLineNo">514</span> return usedCount * itemSize;<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> public long totalBytes() {<a name="line.517"></a>
-<span class="sourceLineNo">518</span> return totalCount * itemSize;<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> public long itemSize() {<a name="line.521"></a>
-<span class="sourceLineNo">522</span> return itemSize;<a name="line.522"></a>
-<span class="sourceLineNo">523</span> }<a name="line.523"></a>
-<span class="sourceLineNo">524</span><a name="line.524"></a>
-<span class="sourceLineNo">525</span> public IndexStatistics(long free, long used, long itemSize) {<a name="line.525"></a>
-<span class="sourceLineNo">526</span> setTo(free, used, itemSize);<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> public IndexStatistics() {<a name="line.529"></a>
-<span class="sourceLineNo">530</span> setTo(-1, -1, 0);<a name="line.530"></a>
-<span class="sourceLineNo">531</span> }<a name="line.531"></a>
-<span class="sourceLineNo">532</span><a name="line.532"></a>
-<span class="sourceLineNo">533</span> public void setTo(long free, long used, long itemSize) {<a name="line.533"></a>
-<span class="sourceLineNo">534</span> this.itemSize = itemSize;<a name="line.534"></a>
-<span class="sourceLineNo">535</span> this.freeCount = free;<a name="line.535"></a>
-<span class="sourceLineNo">536</span> this.usedCount = used;<a name="line.536"></a>
-<span class="sourceLineNo">537</span> this.totalCount = free + used;<a name="line.537"></a>
-<span class="sourceLineNo">538</span> }<a name="line.538"></a>
-<span class="sourceLineNo">539</span> }<a name="line.539"></a>
-<span class="sourceLineNo">540</span><a name="line.540"></a>
-<span class="sourceLineNo">541</span> public Bucket [] getBuckets() {<a name="line.541"></a>
-<span class="sourceLineNo">542</span> return this.buckets;<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> void logStatistics() {<a name="line.545"></a>
-<span class="sourceLineNo">546</span> IndexStatistics total = new IndexStatistics();<a name="line.546"></a>
-<span class="sourceLineNo">547</span> IndexStatistics[] stats = getIndexStatistics(total);<a name="line.547"></a>
-<span class="sourceLineNo">548</span> LOG.info("Bucket allocator statistics follow:\n");<a name="line.548"></a>
-<span class="sourceLineNo">549</span> LOG.info(" Free bytes=" + total.freeBytes() + "+; used bytes="<a name="line.549"></a>
-<span class="sourceLineNo">550</span> + total.usedBytes() + "; total bytes=" + total.totalBytes());<a name="line.550"></a>
-<span class="sourceLineNo">551</span> for (IndexStatistics s : stats) {<a name="line.551"></a>
-<span class="sourceLineNo">552</span> LOG.info(" Object size " + s.itemSize() + " used=" + s.usedCount()<a name="line.552"></a>
-<span class="sourceLineNo">553</span> + "; free=" + s.freeCount() + "; total=" + s.totalCount());<a name="line.553"></a>
-<span class="sourceLineNo">554</span> }<a name="line.554"></a>
-<span class="sourceLineNo">555</span> }<a name="line.555"></a>
-<span class="sourceLineNo">556</span><a name="line.556"></a>
-<span class="sourceLineNo">557</span> IndexStatistics[] getIndexStatistics(IndexStatistics grandTotal) {<a name="line.557"></a>
-<span class="sourceLineNo">558</span> IndexStatistics[] stats = getIndexStatistics();<a name="line.558"></a>
-<span class="sourceLineNo">559</span> long totalfree = 0, totalused = 0;<a name="line.559"></a>
-<span class="sourceLineNo">560</span> for (IndexStatistics stat : stats) {<a name="line.560"></a>
-<span class="sourceLineNo">561</span> totalfree += stat.freeBytes();<a name="line.561"></a>
-<span class="sourceLineNo">562</span> totalused += stat.usedBytes();<a name="line.562"></a>
-<span class="sourceLineNo">563</span> }<a name="line.563"></a>
-<span class="sourceLineNo">564</span> grandTotal.setTo(totalfree, totalused, 1);<a name="line.564"></a>
-<span class="sourceLineNo">565</span> return stats;<a name="line.565"></a>
-<span class="sourceLineNo">566</span> }<a name="line.566"></a>
-<span class="sourceLineNo">567</span><a name="line.567"></a>
-<span class="sourceLineNo">568</span> IndexStatistics[] getIndexStatistics() {<a name="line.568"></a>
-<span class="sourceLineNo">569</span> IndexStatistics[] stats = new IndexStatistics[bucketSizes.length];<a name="line.569"></a>
-<span class="sourceLineNo">570</span> for (int i = 0; i < stats.length; ++i)<a name="line.570"></a>
-<span class="sourceLineNo">571</span> stats[i] = bucketSizeInfos[i].statistics();<a name="line.571"></a>
-<span class="sourceLineNo">572</span> return stats;<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> public long freeBlock(long freeList[]) {<a name="line.575"></a>
-<span class="sourceLineNo">576</span> long sz = 0;<a name="line.576"></a>
-<span class="sourceLineNo">577</span> for (int i = 0; i < freeList.length; ++i)<a name="line.577"></a>
-<span class="sourceLineNo">578</span> sz += freeBlock(freeList[i]);<a name="line.578"></a>
-<span class="sourceLineNo">579</span> return sz;<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> public int getBucketIndex(long offset) {<a name="line.582"></a>
-<span class="sourceLineNo">583</span> return (int) (offset / bucketCapacity);<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> * Returns a set of indices of the buckets that are least filled<a name="line.587"></a>
-<span class="sourceLineNo">588</span> * excluding the offsets, we also the fully free buckets for the<a name="line.588"></a>
-<span class="sourceLineNo">589</span> * BucketSizes where everything is empty and they only have one<a name="line.589"></a>
-<span class="sourceLineNo">590</span> * completely free bucket as a reserved<a name="line.590"></a>
-<span class="sourceLineNo">591</span> *<a name="line.591"></a>
-<span class="sourceLineNo">592</span> * @param excludedBuckets the buckets that need to be excluded due to<a name="line.592"></a>
-<span class="sourceLineNo">593</span> * currently being in used<a name="line.593"></a>
-<span class="sourceLineNo">594</span> * @param bucketCount max Number of buckets to return<a name="line.594"></a>
-<span class="sourceLineNo">595</span> * @return set of bucket indices which could be used for eviction<a name="line.595"></a>
-<span class="sourceLineNo">596</span> */<a name="line.596"></a>
-<span class="sourceLineNo">597</span> public Set<Integer> getLeastFilledBuckets(Set<Integer> excludedBuckets,<a name="line.597"></a>
-<span class="sourceLineNo">598</span> int bucketCount) {<a name="line.598"></a>
-<span class="sourceLineNo">599</span> Queue<Integer> queue = MinMaxPriorityQueue.<Integer>orderedBy(<a name="line.599"></a>
-<span class="sourceLineNo">600</span> new Comparator<Integer>() {<a name="line.600"></a>
-<span class="sourceLineNo">601</span> @Override<a name="line.601"></a>
-<span class="sourceLineNo">602</span> public int compare(Integer left, Integer right) {<a name="line.602"></a>
-<span class="sourceLineNo">603</span> // We will always get instantiated buckets<a name="line.603"></a>
-<span class="sourceLineNo">604</span> return Float.compare(<a name="line.604"></a>
-<span class="sourceLineNo">605</span> ((float) buckets[left].usedCount) / buckets[left].itemCount,<a name="line.605"></a>
-<span class="sourceLineNo">606</span> ((float) buckets[right].usedCount) / buckets[right].itemCount);<a name="line.606"></a>
-<span class="sourceLineNo">607</span> }<a name="line.607"></a>
-<span class="sourceLineNo">608</span> }).maximumSize(bucketCount).create();<a name="line.608"></a>
-<span class="sourceLineNo">609</span><a name="line.609"></a>
-<span class="sourceLineNo">610</span> for (int i = 0; i < buckets.length; i ++ ) {<a name="line.610"></a>
-<span class="sourceLineNo">611</span> if (!excludedBuckets.contains(i) && !buckets[i].isUninstantiated() &&<a name="line.611"></a>
-<span class="sourceLineNo">612</span> // Avoid the buckets that are the only buckets for a sizeIndex<a name="line.612"></a>
-<span class="sourceLineNo">613</span> bucketSizeInfos[buckets[i].sizeIndex()].bucketList.size() != 1) {<a name="line.613"></a>
-<span class="sourceLineNo">614</span> queue.add(i);<a name="line.614"></a>
-<span class="sourceLineNo">615</span> }<a name="line.615"></a>
-<span class="sourceLineNo">616</span> }<a name="line.616"></a>
-<span class="sourceLineNo">617</span><a name="line.617"></a>
-<span class="sourceLineNo">618</span> Set<Integer> result = new HashSet<>(bucketCount);<a name="line.618"></a>
-<span class="sourceLineNo">619</span> result.addAll(queue);<a name="line.619"></a>
-<span class="sourceLineNo">620</span><a name="line.620"></a>
-<span class="sourceLineNo">621</span> return result;<a name="line.621"></a>
-<span class="sourceLineNo">622</span> }<a name="line.622"></a>
-<span class="sourceLineNo">623</span>}<a name="line.623"></a>
+<span class="sourceLineNo">272</span> // The real block size in hfile maybe a little larger than the size we configured ,<a name="line.272"></a>
+<span class="sourceLineNo">273</span> // so we need add extra 1024 bytes for fit.<a name="line.273"></a>
+<span class="sourceLineNo">274</span> // TODO Support the view of block size distribution statistics<a name="line.274"></a>
+<span class="sourceLineNo">275</span> private static final int DEFAULT_BUCKET_SIZES[] = { 4 * 1024 + 1024, 8 * 1024 + 1024,<a name="line.275"></a>
+<span class="sourceLineNo">276</span> 16 * 1024 + 1024, 32 * 1024 + 1024, 40 * 1024 + 1024, 48 * 1024 + 1024,<a name="line.276"></a>
+<span class="sourceLineNo">277</span> 56 * 1024 + 1024, 64 * 1024 + 1024, 96 * 1024 + 1024, 128 * 1024 + 1024,<a name="line.277"></a>
+<span class="sourceLineNo">278</span> 192 * 1024 + 1024, 256 * 1024 + 1024, 384 * 1024 + 1024,<a name="line.278"></a>
+<span class="sourceLineNo">279</span> 512 * 1024 + 1024 };<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> * Round up the given block size to bucket size, and get the corresponding<a name="line.282"></a>
+<span class="sourceLineNo">283</span> * BucketSizeInfo<a name="line.283"></a>
+<span class="sourceLineNo">284</span> */<a name="line.284"></a>
+<span class="sourceLineNo">285</span> public BucketSizeInfo roundUpToBucketSizeInfo(int blockSize) {<a name="line.285"></a>
+<span class="sourceLineNo">286</span> for (int i = 0; i < bucketSizes.length; ++i)<a name="line.286"></a>
+<span class="sourceLineNo">287</span> if (blockSize <= bucketSizes[i])<a name="line.287"></a>
+<span class="sourceLineNo">288</span> return bucketSizeInfos[i];<a name="line.288"></a>
+<span class="sourceLineNo">289</span> return null;<a name="line.289"></a>
+<span class="sourceLineNo">290</span> }<a name="line.290"></a>
+<span class="sourceLineNo">291</span><a name="line.291"></a>
+<span class="sourceLineNo">292</span> /**<a name="line.292"></a>
+<span class="sourceLineNo">293</span> * So, what is the minimum amount of items we'll tolerate in a single bucket?<a name="line.293"></a>
+<span class="sourceLineNo">294</span> */<a name="line.294"></a>
+<span class="sourceLineNo">295</span> static public final int FEWEST_ITEMS_IN_BUCKET = 4;<a name="line.295"></a>
+<span class="sourceLineNo">296</span><a name="line.296"></a>
+<span class="sourceLineNo">297</span> private final int[] bucketSizes;<a name="line.297"></a>
+<span class="sourceLineNo">298</span> private final int bigItemSize;<a name="line.298"></a>
+<span class="sourceLineNo">299</span> // The capacity size for each bucket<a name="line.299"></a>
+<span class="sourceLineNo">300</span> private final long bucketCapacity;<a name="line.300"></a>
+<span class="sourceLineNo">301</span> private Bucket[] buckets;<a name="line.301"></a>
+<span class="sourceLineNo">302</span> private BucketSizeInfo[] bucketSizeInfos;<a name="line.302"></a>
+<span class="sourceLineNo">303</span> private final long totalSize;<a name="line.303"></a>
+<span class="sourceLineNo">304</span> private transient long usedSize = 0;<a name="line.304"></a>
+<span class="sourceLineNo">305</span><a name="line.305"></a>
+<span class="sourceLineNo">306</span> BucketAllocator(long availableSpace, int[] bucketSizes)<a name="line.306"></a>
+<span class="sourceLineNo">307</span> throws BucketAllocatorException {<a name="line.307"></a>
+<span class="sourceLineNo">308</span> this.bucketSizes = bucketSizes == null ? DEFAULT_BUCKET_SIZES : bucketSizes;<a name="line.308"></a>
+<span class="sourceLineNo">309</span> Arrays.sort(this.bucketSizes);<a name="line.309"></a>
+<span class="sourceLineNo">310</span> this.bigItemSize = Ints.max(this.bucketSizes);<a name="line.310"></a>
+<span class="sourceLineNo">311</span> this.bucketCapacity = FEWEST_ITEMS_IN_BUCKET * (long) bigItemSize;<a name="line.311"></a>
+<span class="sourceLineNo">312</span> buckets = new Bucket[(int) (availableSpace / bucketCapacity)];<a name="line.312"></a>
+<span class="sourceLineNo">313</span> if (buckets.length < this.bucketSizes.length)<a name="line.313"></a>
+<span class="sourceLineNo">314</span> throw new BucketAllocatorException("Bucket allocator size too small (" + buckets.length +<a name="line.314"></a>
+<span class="sourceLineNo">315</span> "); must have room for at least " + this.bucketSizes.length + " buckets");<a name="line.315"></a>
+<span class="sourceLineNo">316</span> bucketSizeInfos = new BucketSizeInfo[this.bucketSizes.length];<a name="line.316"></a>
+<span class="sourceLineNo">317</span> for (int i = 0; i < this.bucketSizes.length; ++i) {<a name="line.317"></a>
+<span class="sourceLineNo">318</span> bucketSizeInfos[i] = new BucketSizeInfo(i);<a name="line.318"></a>
+<span class="sourceLineNo">319</span> }<a name="line.319"></a>
+<span class="sourceLineNo">320</span> for (int i = 0; i < buckets.length; ++i) {<a name="line.320"></a>
+<span class="sourceLineNo">321</span> buckets[i] = new Bucket(bucketCapacity * i);<a name="line.321"></a>
+<span class="sourceLineNo">322</span> bucketSizeInfos[i < this.bucketSizes.length ? i : this.bucketSizes.length - 1]<a name="line.322"></a>
+<span class="sourceLineNo">323</span> .instantiateBucket(buckets[i]);<a name="line.323"></a>
+<span class="sourceLineNo">324</span> }<a name="line.324"></a>
+<span class="sourceLineNo">325</span> this.totalSize = ((long) buckets.length) * bucketCapacity;<a name="line.325"></a>
+<span class="sourceLineNo">326</span> if (LOG.isInfoEnabled()) {<a name="line.326"></a>
+<span class="sourceLineNo">327</span> LOG.info("Cache totalSize=" + this.totalSize + ", buckets=" + this.buckets.length +<a name="line.327"></a>
+<span class="sourceLineNo">328</span> ", bucket capacity=" + this.bucketCapacity +<a name="line.328"></a>
+<span class="sourceLineNo">329</span> "=(" + FEWEST_ITEMS_IN_BUCKET + "*" + this.bigItemSize + ")=" +<a name="line.329"></a>
+<span class="sourceLineNo">330</span> "(FEWEST_ITEMS_IN_BUCKET*(largest configured bucketcache size))");<a name="line.330"></a>
+<span class="sourceLineNo">331</span> }<a name="line.331"></a>
+<span class="sourceLineNo">332</span> }<a name="line.332"></a>
+<span class="sourceLineNo">333</span><a name="line.333"></a>
+<span class="sourceLineNo">334</span> /**<a name="line.334"></a>
+<span class="sourceLineNo">335</span> * Rebuild the allocator's data structures from a persisted map.<a name="line.335"></a>
+<span class="sourceLineNo">336</span> * @param availableSpace capacity of cache<a name="line.336"></a>
+<span class="sourceLineNo">337</span> * @param map A map stores the block key and BucketEntry(block's meta data<a name="line.337"></a>
+<span class="sourceLineNo">338</span> * like offset, length)<a name="line.338"></a>
+<span class="sourceLineNo">339</span> * @param realCacheSize cached data size statistics for bucket cache<a name="line.339"></a>
+<span class="sourceLineNo">340</span> * @throws BucketAllocatorException<a name="line.340"></a>
+<span class="sourceLineNo">341</span> */<a name="line.341"></a>
+<span class="sourceLineNo">342</span> BucketAllocator(long availableSpace, int[] bucketSizes, Map<BlockCacheKey, BucketEntry> map,<a name="line.342"></a>
+<span class="sourceLineNo">343</span> LongAdder realCacheSize) throws BucketAllocatorException {<a name="line.343"></a>
+<span class="sourceLineNo">344</span> this(availableSpace, bucketSizes);<a name="line.344"></a>
+<span class="sourceLineNo">345</span><a name="line.345"></a>
+<span class="sourceLineNo">346</span> // each bucket has an offset, sizeindex. probably the buckets are too big<a name="line.346"></a>
+<span class="sourceLineNo">347</span> // in our default state. so what we do is reconfigure them according to what<a name="line.347"></a>
+<span class="sourceLineNo">348</span> // we've found. we can only reconfigure each bucket once; if more than once,<a name="line.348"></a>
+<span class="sourceLineNo">349</span> // we know there's a bug, so we just log the info, throw, and start again...<a name="line.349"></a>
+<span class="sourceLineNo">350</span> boolean[] reconfigured = new boolean[buckets.length];<a name="line.350"></a>
+<span class="sourceLineNo">351</span> int sizeNotMatchedCount = 0;<a name="line.351"></a>
+<span class="sourceLineNo">352</span> int insufficientCapacityCount = 0;<a name="line.352"></a>
+<span class="sourceLineNo">353</span> Iterator<Map.Entry<BlockCacheKey, BucketEntry>> iterator = map.entrySet().iterator();<a name="line.353"></a>
+<span class="sourceLineNo">354</span> while (iterator.hasNext()) {<a name="line.354"></a>
+<span class="sourceLineNo">355</span> Map.Entry<BlockCacheKey, BucketEntry> entry = iterator.next();<a name="line.355"></a>
+<span class="sourceLineNo">356</span> long foundOffset = entry.getValue().offset();<a name="line.356"></a>
+<span class="sourceLineNo">357</span> int foundLen = entry.getValue().getLength();<a name="line.357"></a>
+<span class="sourceLineNo">358</span> int bucketSizeIndex = -1;<a name="line.358"></a>
+<span class="sourceLineNo">359</span> for (int i = 0; i < this.bucketSizes.length; ++i) {<a name="line.359"></a>
+<span class="sourceLineNo">360</span> if (foundLen <= this.bucketSizes[i]) {<a name="line.360"></a>
+<span class="sourceLineNo">361</span> bucketSizeIndex = i;<a name="line.361"></a>
+<span class="sourceLineNo">362</span> break;<a name="line.362"></a>
+<span class="sourceLineNo">363</span> }<a name="line.363"></a>
+<span class="sourceLineNo">364</span> }<a name="line.364"></a>
+<span class="sourceLineNo">365</span> if (bucketSizeIndex == -1) {<a name="line.365"></a>
+<span class="sourceLineNo">366</span> sizeNotMatchedCount++;<a name="line.366"></a>
+<span class="sourceLineNo">367</span> iterator.remove();<a name="line.367"></a>
+<span class="sourceLineNo">368</span> continue;<a name="line.368"></a>
+<span class="sourceLineNo">369</span> }<a name="line.369"></a>
+<span class="sourceLineNo">370</span> int bucketNo = (int) (foundOffset / bucketCapacity);<a name="line.370"></a>
+<span class="sourceLineNo">371</span> if (bucketNo < 0 || bucketNo >= buckets.length) {<a name="line.371"></a>
+<span class="sourceLineNo">372</span> insufficientCapacityCount++;<a name="line.372"></a>
+<span class="sourceLineNo">373</span> iterator.remove();<a name="line.373"></a>
+<span class="sourceLineNo">374</span> continue;<a name="line.374"></a>
+<span class="sourceLineNo">375</span> }<a name="line.375"></a>
+<span class="sourceLineNo">376</span> Bucket b = buckets[bucketNo];<a name="line.376"></a>
+<span class="sourceLineNo">377</span> if (reconfigured[bucketNo]) {<a name="line.377"></a>
+<span class="sourceLineNo">378</span> if (b.sizeIndex() != bucketSizeIndex) {<a name="line.378"></a>
+<span class="sourceLineNo">379</span> throw new BucketAllocatorException("Inconsistent allocation in bucket map;");<a name="line.379"></a>
+<span class="sourceLineNo">380</span> }<a name="line.380"></a>
+<span class="sourceLineNo">381</span> } else {<a name="line.381"></a>
+<span class="sourceLineNo">382</span> if (!b.isCompletelyFree()) {<a name="line.382"></a>
+<span class="sourceLineNo">383</span> throw new BucketAllocatorException(<a name="line.383"></a>
+<span class="sourceLineNo">384</span> "Reconfiguring bucket " + bucketNo + " but it's already allocated; corrupt data");<a name="line.384"></a>
+<span class="sourceLineNo">385</span> }<a name="line.385"></a>
+<span class="sourceLineNo">386</span> // Need to remove the bucket from whichever list it's currently in at<a name="line.386"></a>
+<span class="sourceLineNo">387</span> // the moment...<a name="line.387"></a>
+<span class="sourceLineNo">388</span> BucketSizeInfo bsi = bucketSizeInfos[bucketSizeIndex];<a name="line.388"></a>
+<span class="sourceLineNo">389</span> BucketSizeInfo oldbsi = bucketSizeInfos[b.sizeIndex()];<a name="line.389"></a>
+<span class="sourceLineNo">390</span> oldbsi.removeBucket(b);<a name="line.390"></a>
+<span class="sourceLineNo">391</span> bsi.instantiateBucket(b);<a name="line.391"></a>
+<span class="sourceLineNo">392</span> reconfigured[bucketNo] = true;<a name="line.392"></a>
+<span class="sourceLineNo">393</span> }<a name="line.393"></a>
+<span class="sourceLineNo">394</span> realCacheSize.add(foundLen);<a name="line.394"></a>
+<span class="sourceLineNo">395</span> buckets[bucketNo].addAllocation(foundOffset);<a name="line.395"></a>
+<span class="sourceLineNo">396</span> usedSize += buckets[bucketNo].getItemAllocationSize();<a name="line.396"></a>
+<span class="sourceLineNo">397</span> bucketSizeInfos[bucketSizeIndex].blockAllocated(b);<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> if (sizeNotMatchedCount > 0) {<a name="line.400"></a>
+<span class="sourceLineNo">401</span> LOG.warn("There are " + sizeNotMatchedCount + " blocks which can't be rebuilt because " +<a name="line.401"></a>
+<span class="sourceLineNo">402</span> "there is no matching bucket size for these blocks");<a name="line.402"></a>
+<span class="sourceLineNo">403</span> }<a name="line.403"></a>
+<span class="sourceLineNo">404</span> if (insufficientCapacityCount > 0) {<a name="line.404"></a>
+<span class="sourceLineNo">405</span> LOG.warn("There are " + insufficientCapacityCount + " blocks which can't be rebuilt - "<a name="line.405"></a>
+<span class="sourceLineNo">406</span> + "did you shrink the cache?");<a name="line.406"></a>
+<span class="sourceLineNo">407</span> }<a name="line.407"></a>
+<span class="sourceLineNo">408</span> }<a name="line.408"></a>
+<span class="sourceLineNo">409</span><a name="line.409"></a>
+<span class="sourceLineNo">410</span> @Override<a name="line.410"></a>
+<span class="sourceLineNo">411</span> public String toString() {<a name="line.411"></a>
+<span class="sourceLineNo">412</span> StringBuilder sb = new StringBuilder(1024);<a name="line.412"></a>
+<span class="sourceLineNo">413</span> for (int i = 0; i < buckets.length; ++i) {<a name="line.413"></a>
+<span class="sourceLineNo">414</span> Bucket b = buckets[i];<a name="line.414"></a>
+<span class="sourceLineNo">415</span> if (i > 0) sb.append(", ");<a name="line.415"></a>
+<span class="sourceLineNo">416</span> sb.append("bucket.").append(i).append(": size=").append(b.getItemAllocationSize());<a name="line.416"></a>
+<span class="sourceLineNo">417</span> sb.append(", freeCount=").append(b.freeCount()).append(", used=").append(b.usedCount());<a name="line.417"></a>
+<span class="sourceLineNo">418</span> }<a name="line.418"></a>
+<span class="sourceLineNo">419</span> return sb.toString();<a name="line.419"></a>
+<span class="sourceLineNo">420</span> }<a name="line.420"></a>
+<span class="sourceLineNo">421</span><a name="line.421"></a>
+<span class="sourceLineNo">422</span> public long getUsedSize() {<a name="line.422"></a>
+<span class="sourceLineNo">423</span> return this.usedSize;<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> public long getFreeSize() {<a name="line.426"></a>
+<span class="sourceLineNo">427</span> return this.totalSize - getUsedSize();<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> public long getTotalSize() {<a name="line.430"></a>
+<span class="sourceLineNo">431</span> return this.totalSize;<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> * Allocate a block with specified size. Return the offset<a name="line.435"></a>
+<span class="sourceLineNo">436</span> * @param blockSize size of block<a name="line.436"></a>
+<span class="sourceLineNo">437</span> * @throws BucketAllocatorException<a name="line.437"></a>
+<span class="sourceLineNo">438</span> * @throws CacheFullException<a name="line.438"></a>
+<span class="sourceLineNo">439</span> * @return the offset in the IOEngine<a name="line.439"></a>
+<span class="sourceLineNo">440</span> */<a name="line.440"></a>
+<span class="sourceLineNo">441</span> public synchronized long allocateBlock(int blockSize) throws CacheFullException,<a name="line.441"></a>
+<span class="sourceLineNo">442</span> BucketAllocatorException {<a name="line.442"></a>
+<span class="sourceLineNo">443</span> assert blockSize > 0;<a name="line.443"></a>
+<span class="sourceLineNo">444</span> BucketSizeInfo bsi = roundUpToBucketSizeInfo(blockSize);<a name="line.444"></a>
+<span class="sourceLineNo">445</span> if (bsi == null) {<a name="line.445"></a>
+<span class="sourceLineNo">446</span> throw new BucketAllocatorException("Allocation too big size=" + blockSize +<a name="line.446"></a>
+<span class="sourceLineNo">447</span> "; adjust BucketCache sizes " + BlockCacheFactory.BUCKET_CACHE_BUCKETS_KEY +<a name="line.447"></a>
+<span class="sourceLineNo">448</span> " to accomodate if size seems reasonable and you want it cached.");<a name="line.448"></a>
+<span class="sourceLineNo">449</span> }<a name="line.449"></a>
+<span class="sourceLineNo">450</span> long offset = bsi.allocateBlock();<a name="line.450"></a>
+<span class="sourceLineNo">451</span><a name="line.451"></a>
+<span class="sourceLineNo">452</span> // Ask caller to free up space and try again!<a name="line.452"></a>
+<span class="sourceLineNo">453</span> if (offset < 0)<a name="line.453"></a>
+<span class="sourceLineNo">454</span> throw new CacheFullException(blockSize, bsi.sizeIndex());<a name="line.454"></a>
+<span class="sourceLineNo">455</span> usedSize += bucketSizes[bsi.sizeIndex()];<a name="line.455"></a>
+<span class="sourceLineNo">456</span> return offset;<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> private Bucket grabGlobalCompletelyFreeBucket() {<a name="line.459"></a>
+<span class="sourceLineNo">460</span> for (BucketSizeInfo bsi : bucketSizeInfos) {<a name="line.460"></a>
+<span class="sourceLineNo">461</span> Bucket b = bsi.findAndRemoveCompletelyFreeBucket();<a name="line.461"></a>
+<span class="sourceLineNo">462</span> if (b != null) return b;<a name="line.462"></a>
+<span class="sourceLineNo">463</span> }<a name="line.463"></a>
+<span class="sourceLineNo">464</span> return null;<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> * Free a block with the offset<a name="line.468"></a>
+<span class="sourceLineNo">469</span> * @param offset block's offset<a name="line.469"></a>
+<span class="sourceLineNo">470</span> * @return size freed<a name="line.470"></a>
+<span class="sourceLineNo">471</span> */<a name="line.471"></a>
+<span class="sourceLineNo">472</span> public synchronized int freeBlock(long offset) {<a name="line.472"></a>
+<span class="sourceLineNo">473</span> int bucketNo = (int) (offset / bucketCapacity);<a name="line.473"></a>
+<span class="sourceLineNo">474</span> assert bucketNo >= 0 && bucketNo < buckets.length;<a name="line.474"></a>
+<span class="sourceLineNo">475</span> Bucket targetBucket = buckets[bucketNo];<a name="line.475"></a>
+<span class="sourceLineNo">476</span> bucketSizeInfos[targetBucket.sizeIndex()].freeBlock(targetBucket, offset);<a name="line.476"></a>
+<span class="sourceLineNo">477</span> usedSize -= targetBucket.getItemAllocationSize();<a name="line.477"></a>
+<span class="sourceLineNo">478</span> return targetBucket.getItemAllocationSize();<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> public int sizeIndexOfAllocation(long offset) {<a name="line.481"></a>
+<span class="sourceLineNo">482</span> int bucketNo = (int) (offset / bucketCapacity);<a name="line.482"></a>
+<span class="sourceLineNo">483</span> assert bucketNo >= 0 && bucketNo < buckets.length;<a name="line.483"></a>
+<span class="sourceLineNo">484</span> Bucket targetBucket = buckets[bucketNo];<a name="line.484"></a>
+<span class="sourceLineNo">485</span> return targetBucket.sizeIndex();<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> public int sizeOfAllocation(long offset) {<a name="line.488"></a>
+<span class="sourceLineNo">489</span> int bucketNo = (int) (offset / bucketCapacity);<a name="line.489"></a>
+<span class="sourceLineNo">490</span> assert bucketNo >= 0 && bucketNo < buckets.length;<a name="line.490"></a>
+<span class="sourceLineNo">491</span> Bucket targetBucket = buckets[bucketNo];<a name="line.491"></a>
+<span class="sourceLineNo">492</span> return targetBucket.getItemAllocationSize();<a name="line.492"></a>
+<span class="sourceLineNo">493</span> }<a name="line.493"></a>
+<span class="sourceLineNo">494</span><a name="line.494"></a>
+<span class="sourceLineNo">495</span> static class IndexStatistics {<a name="line.495"></a>
+<span class="sourceLineNo">496</span> private long freeCount, usedCount, itemSize, totalCount;<a name="line.496"></a>
+<span class="sourceLineNo">497</span><a name="line.497"></a>
+<span class="sourceLineNo">498</span> public long freeCount() {<a name="line.498"></a>
+<span class="sourceLineNo">499</span> return freeCount;<a name="line.499"></a>
+<span class="sourceLineNo">500</span> }<a name="line.500"></a>
+<span class="sourceLineNo">501</span><a name="line.501"></a>
+<span class="sourceLineNo">502</span> public long usedCount() {<a name="line.502"></a>
+<span class="sourceLineNo">503</span> return usedCount;<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> public long totalCount() {<a name="line.506"></a>
+<span class="sourceLineNo">507</span> return totalCount;<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> public long freeBytes() {<a name="line.510"></a>
+<span class="sourceLineNo">511</span> return freeCount * itemSize;<a name="line.511"></a>
+<span class="sourceLineNo">512</span> }<a name="line.512"></a>
+<span class="sourceLineNo">513</span><a name="line.513"></a>
+<span class="sourceLineNo">514</span> public long usedBytes() {<a name="line.514"></a>
+<span class="sourceLineNo">515</span> return usedCount * itemSize;<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> public long totalBytes() {<a name="line.518"></a>
+<span class="sourceLineNo">519</span> return totalCount * itemSize;<a name="line.519"></a>
+<span class="sourceLineNo">520</span> }<a name="line.520"></a>
+<span class="sourceLineNo">521</span><a name="line.521"></a>
+<span class="sourceLineNo">522</span> public long itemSize() {<a name="line.522"></a>
+<span class="sourceLineNo">523</span> return itemSize;<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> public IndexStatistics(long free, long used, long itemSize) {<a name="line.526"></a>
+<span class="sourceLineNo">527</span> setTo(free, used, itemSize);<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> public IndexStatistics() {<a name="line.530"></a>
+<span class="sourceLineNo">531</span> setTo(-1, -1, 0);<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> public void setTo(long free, long used, long itemSize) {<a name="line.534"></a>
+<span class="sourceLineNo">535</span> this.itemSize = itemSize;<a name="line.535"></a>
+<span class="sourceLineNo">536</span> this.freeCount = free;<a name="line.536"></a>
+<span class="sourceLineNo">537</span> this.usedCount = used;<a name="line.537"></a>
+<span class="sourceLineNo">538</span> this.totalCount = free + used;<a name="line.538"></a>
+<span class="sourceLineNo">539</span> }<a name="line.539"></a>
+<span class="sourceLineNo">540</span> }<a name="line.540"></a>
+<span class="sourceLineNo">541</span><a name="line.541"></a>
+<span class="sourceLineNo">542</span> public Bucket [] getBuckets() {<a name="line.542"></a>
+<span class="sourceLineNo">543</span> return this.buckets;<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> void logStatistics() {<a name="line.546"></a>
+<span class="sourceLineNo">547</span> IndexStatistics total = new IndexStatistics();<a name="line.547"></a>
+<span class="sourceLineNo">548</span> IndexStatistics[] stats = getIndexStatistics(total);<a name="line.548"></a>
+<span class="sourceLineNo">549</span> LOG.info("Bucket allocator statistics follow:\n");<a name="line.549"></a>
+<span class="sourceLineNo">550</span> LOG.info(" Free bytes=" + total.freeBytes() + "+; used bytes="<a name="line.550"></a>
+<span class="sourceLineNo">551</span> + total.usedBytes() + "; total bytes=" + total.totalBytes());<a name="line.551"></a>
+<span class="sourceLineNo">552</span> for (IndexStatistics s : stats) {<a name="line.552"></a>
+<span class="sourceLineNo">553</span> LOG.info(" Object size " + s.itemSize() + " used=" + s.usedCount()<a name="line.553"></a>
+<span class="sourceLineNo">554</span> + "; free=" + s.freeCount() + "; total=" + s.totalCount());<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><a name="line.557"></a>
+<span class="sourceLineNo">558</span> IndexStatistics[] getIndexStatistics(IndexStatistics grandTotal) {<a name="line.558"></a>
+<span class="sourceLineNo">559</span> IndexStatistics[] stats = getIndexStatistics();<a name="line.559"></a>
+<span class="sourceLineNo">560</span> long totalfree = 0, totalused = 0;<a name="line.560"></a>
+<span class="sourceLineNo">561</span> for (IndexStatistics stat : stats) {<a name="line.561"></a>
+<span class="sourceLineNo">562</span> totalfree += stat.freeBytes();<a name="line.562"></a>
+<span class="sourceLineNo">563</span> totalused += stat.usedBytes();<a name="line.563"></a>
+<span class="sourceLineNo">564</span> }<a name="line.564"></a>
+<span class="sourceLineNo">565</span> grandTotal.setTo(totalfree, totalused, 1);<a name="line.565"></a>
+<span class="sourceLineNo">566</span> return stats;<a name="line.566"></a>
+<span class="sourceLineNo">567</span> }<a name="line.567"></a>
+<span class="sourceLineNo">568</span><a name="line.568"></a>
+<span class="sourceLineNo">569</span> IndexStatistics[] getIndexStatistics() {<a name="line.569"></a>
+<span class="sourceLineNo">570</span> IndexStatistics[] stats = new IndexStatistics[bucketSizes.length];<a name="line.570"></a>
+<span class="sourceLineNo">571</span> for (int i = 0; i < stats.length; ++i)<a name="line.571"></a>
+<span class="sourceLineNo">572</span> stats[i] = bucketSizeInfos[i].statistics();<a name="line.572"></a>
+<span class="sourceLineNo">573</span> return stats;<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> public long freeBlock(long freeList[]) {<a name="line.576"></a>
+<span class="sourceLineNo">577</span> long sz = 0;<a name="line.577"></a>
+<span class="sourceLineNo">578</span> for (int i = 0; i < freeList.length; ++i)<a name="line.578"></a>
+<span class="sourceLineNo">579</span> sz += freeBlock(freeList[i]);<a name="line.579"></a>
+<span class="sourceLineNo">580</span> return sz;<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> public int getBucketIndex(long offset) {<a name="line.583"></a>
+<span class="sourceLineNo">584</span> return (int) (offset / bucketCapacity);<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> /**<a name="line.587"></a>
+<span class="sourceLineNo">588</span> * Returns a set of indices of the buckets that are least filled<a name="line.588"></a>
+<span class="sourceLineNo">589</span> * excluding the offsets, we also the fully free buckets for the<a name="line.589"></a>
+<span class="sourceLineNo">590</span> * BucketSizes where everything is empty and they only have one<a name="line.590"></a>
+<span class="sourceLineNo">591</span> * completely free bucket as a reserved<a name="line.591"></a>
+<span class="sourceLineNo">592</span> *<a name="line.592"></a>
+<span class="sourceLineNo">593</span> * @param excludedBuckets the buckets that need to be excluded due to<a name="line.593"></a>
+<span class="sourceLineNo">594</span> * currently being in used<a name="line.594"></a>
+<span class="sourceLineNo">595</span> * @param bucketCount max Number of buckets to return<a name="line.595"></a>
+<span class="sourceLineNo">596</span> * @return set of bucket indices which could be used for eviction<a name="line.596"></a>
+<span class="sourceLineNo">597</span> */<a name="line.597"></a>
+<span class="sourceLineNo">598</span> public Set<Integer> getLeastFilledBuckets(Set<Integer> excludedBuckets,<a name="line.598"></a>
+<span class="sourceLineNo">599</span> int bucketCount) {<a name="line.599"></a>
+<span class="sourceLineNo">600</span> Queue<Integer> queue = MinMaxPriorityQueue.<Integer>orderedBy(<a name="line.600"></a>
+<span class="sourceLineNo">601</span> new Comparator<Integer>() {<a name="line.601"></a>
+<span class="sourceLineNo">602</span> @Override<a name="line.602"></a>
+<span class="sourceLineNo">603</span> public int compare(Integer left, Integer right) {<a name="line.603"></a>
+<span class="sourceLineNo">604</span> // We will always get instantiated buckets<a name="line.604"></a>
+<span class="sourceLineNo">605</span> return Float.compare(<a name="line.605"></a>
+<span class="sourceLineNo">606</span> ((float) buckets[left].usedCount) / buckets[left].itemCount,<a name="line.606"></a>
+<span class="sourceLineNo">607</span> ((float) buckets[right].usedCount) / buckets[right].itemCount);<a name="line.607"></a>
+<span class="sourceLineNo">608</span> }<a name="line.608"></a>
+<span class="sourceLineNo">609</span> }).maximumSize(bucketCount).create();<a name="line.609"></a>
+<span class="sourceLineNo">610</span><a name="line.610"></a>
+<span class="sourceLineNo">611</span> for (int i = 0; i < buckets.length; i ++ ) {<a name="line.611"></a>
+<span class="sourceLineNo">612</span> if (!excludedBuckets.contains(i) && !buckets[i].isUninstantiated() &&<a name="line.612"></a>
+<span class="sourceLineNo">613</span> // Avoid the buckets that are the only buckets for a sizeIndex<a name="line.613"></a>
+<span class="sourceLineNo">614</span> bucketSizeInfos[buckets[i].sizeIndex()].bucketList.size() != 1) {<a name="line.614"></a>
+<span class="sourceLineNo">615</span> queue.add(i);<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><a name="line.618"></a>
+<span class="sourceLineNo">619</span> Set<Integer> result = new HashSet<>(bucketCount);<a name="line.619"></a>
+<span class="sourceLineNo">620</span> result.addAll(queue);<a name="line.620"></a>
+<span class="sourceLineNo">621</span><a name="line.621"></a>
+<span class="sourceLineNo">622</span> return result;<a name="line.622"></a>
+<span class="sourceLineNo">623</span> }<a name="line.623"></a>
+<span class="sourceLineNo">624</span>}<a name="line.624"></a>
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.BucketSizeInfo.html b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.BucketSizeInfo.html
index a3cd853..0a4475b 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.BucketSizeInfo.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.BucketSizeInfo.html
@@ -277,358 +277,359 @@
<span class="sourceLineNo">269</span><a name="line.269"></a>
<span class="sourceLineNo">270</span> // Default block size in hbase is 64K, so we choose more sizes near 64K, you'd better<a name="line.270"></a>
<span class="sourceLineNo">271</span> // reset it according to your cluster's block size distribution<a name="line.271"></a>
-<span class="sourceLineNo">272</span> // TODO Support the view of block size distribution statistics<a name="line.272"></a>
-<span class="sourceLineNo">273</span> // TODO: Why we add the extra 1024 bytes? Slop?<a name="line.273"></a>
-<span class="sourceLineNo">274</span> private static final int DEFAULT_BUCKET_SIZES[] = { 4 * 1024 + 1024, 8 * 1024 + 1024,<a name="line.274"></a>
-<span class="sourceLineNo">275</span> 16 * 1024 + 1024, 32 * 1024 + 1024, 40 * 1024 + 1024, 48 * 1024 + 1024,<a name="line.275"></a>
-<span class="sourceLineNo">276</span> 56 * 1024 + 1024, 64 * 1024 + 1024, 96 * 1024 + 1024, 128 * 1024 + 1024,<a name="line.276"></a>
-<span class="sourceLineNo">277</span> 192 * 1024 + 1024, 256 * 1024 + 1024, 384 * 1024 + 1024,<a name="line.277"></a>
-<span class="sourceLineNo">278</span> 512 * 1024 + 1024 };<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> * Round up the given block size to bucket size, and get the corresponding<a name="line.281"></a>
-<span class="sourceLineNo">282</span> * BucketSizeInfo<a name="line.282"></a>
-<span class="sourceLineNo">283</span> */<a name="line.283"></a>
-<span class="sourceLineNo">284</span> public BucketSizeInfo roundUpToBucketSizeInfo(int blockSize) {<a name="line.284"></a>
-<span class="sourceLineNo">285</span> for (int i = 0; i < bucketSizes.length; ++i)<a name="line.285"></a>
-<span class="sourceLineNo">286</span> if (blockSize <= bucketSizes[i])<a name="line.286"></a>
-<span class="sourceLineNo">287</span> return bucketSizeInfos[i];<a name="line.287"></a>
-<span class="sourceLineNo">288</span> return null;<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> /**<a name="line.291"></a>
-<span class="sourceLineNo">292</span> * So, what is the minimum amount of items we'll tolerate in a single bucket?<a name="line.292"></a>
-<span class="sourceLineNo">293</span> */<a name="line.293"></a>
-<span class="sourceLineNo">294</span> static public final int FEWEST_ITEMS_IN_BUCKET = 4;<a name="line.294"></a>
-<span class="sourceLineNo">295</span><a name="line.295"></a>
-<span class="sourceLineNo">296</span> private final int[] bucketSizes;<a name="line.296"></a>
-<span class="sourceLineNo">297</span> private final int bigItemSize;<a name="line.297"></a>
-<span class="sourceLineNo">298</span> // The capacity size for each bucket<a name="line.298"></a>
-<span class="sourceLineNo">299</span> private final long bucketCapacity;<a name="line.299"></a>
-<span class="sourceLineNo">300</span> private Bucket[] buckets;<a name="line.300"></a>
-<span class="sourceLineNo">301</span> private BucketSizeInfo[] bucketSizeInfos;<a name="line.301"></a>
-<span class="sourceLineNo">302</span> private final long totalSize;<a name="line.302"></a>
-<span class="sourceLineNo">303</span> private transient long usedSize = 0;<a name="line.303"></a>
-<span class="sourceLineNo">304</span><a name="line.304"></a>
-<span class="sourceLineNo">305</span> BucketAllocator(long availableSpace, int[] bucketSizes)<a name="line.305"></a>
-<span class="sourceLineNo">306</span> throws BucketAllocatorException {<a name="line.306"></a>
-<span class="sourceLineNo">307</span> this.bucketSizes = bucketSizes == null ? DEFAULT_BUCKET_SIZES : bucketSizes;<a name="line.307"></a>
-<span class="sourceLineNo">308</span> Arrays.sort(this.bucketSizes);<a name="line.308"></a>
-<span class="sourceLineNo">309</span> this.bigItemSize = Ints.max(this.bucketSizes);<a name="line.309"></a>
-<span class="sourceLineNo">310</span> this.bucketCapacity = FEWEST_ITEMS_IN_BUCKET * (long) bigItemSize;<a name="line.310"></a>
-<span class="sourceLineNo">311</span> buckets = new Bucket[(int) (availableSpace / bucketCapacity)];<a name="line.311"></a>
-<span class="sourceLineNo">312</span> if (buckets.length < this.bucketSizes.length)<a name="line.312"></a>
-<span class="sourceLineNo">313</span> throw new BucketAllocatorException("Bucket allocator size too small (" + buckets.length +<a name="line.313"></a>
-<span class="sourceLineNo">314</span> "); must have room for at least " + this.bucketSizes.length + " buckets");<a name="line.314"></a>
-<span class="sourceLineNo">315</span> bucketSizeInfos = new BucketSizeInfo[this.bucketSizes.length];<a name="line.315"></a>
-<span class="sourceLineNo">316</span> for (int i = 0; i < this.bucketSizes.length; ++i) {<a name="line.316"></a>
-<span class="sourceLineNo">317</span> bucketSizeInfos[i] = new BucketSizeInfo(i);<a name="line.317"></a>
-<span class="sourceLineNo">318</span> }<a name="line.318"></a>
-<span class="sourceLineNo">319</span> for (int i = 0; i < buckets.length; ++i) {<a name="line.319"></a>
-<span class="sourceLineNo">320</span> buckets[i] = new Bucket(bucketCapacity * i);<a name="line.320"></a>
-<span class="sourceLineNo">321</span> bucketSizeInfos[i < this.bucketSizes.length ? i : this.bucketSizes.length - 1]<a name="line.321"></a>
-<span class="sourceLineNo">322</span> .instantiateBucket(buckets[i]);<a name="line.322"></a>
-<span class="sourceLineNo">323</span> }<a name="line.323"></a>
-<span class="sourceLineNo">324</span> this.totalSize = ((long) buckets.length) * bucketCapacity;<a name="line.324"></a>
-<span class="sourceLineNo">325</span> if (LOG.isInfoEnabled()) {<a name="line.325"></a>
-<span class="sourceLineNo">326</span> LOG.info("Cache totalSize=" + this.totalSize + ", buckets=" + this.buckets.length +<a name="line.326"></a>
-<span class="sourceLineNo">327</span> ", bucket capacity=" + this.bucketCapacity +<a name="line.327"></a>
-<span class="sourceLineNo">328</span> "=(" + FEWEST_ITEMS_IN_BUCKET + "*" + this.bigItemSize + ")=" +<a name="line.328"></a>
-<span class="sourceLineNo">329</span> "(FEWEST_ITEMS_IN_BUCKET*(largest configured bucketcache size))");<a name="line.329"></a>
-<span class="sourceLineNo">330</span> }<a name="line.330"></a>
-<span class="sourceLineNo">331</span> }<a name="line.331"></a>
-<span class="sourceLineNo">332</span><a name="line.332"></a>
-<span class="sourceLineNo">333</span> /**<a name="line.333"></a>
-<span class="sourceLineNo">334</span> * Rebuild the allocator's data structures from a persisted map.<a name="line.334"></a>
-<span class="sourceLineNo">335</span> * @param availableSpace capacity of cache<a name="line.335"></a>
-<span class="sourceLineNo">336</span> * @param map A map stores the block key and BucketEntry(block's meta data<a name="line.336"></a>
-<span class="sourceLineNo">337</span> * like offset, length)<a name="line.337"></a>
-<span class="sourceLineNo">338</span> * @param realCacheSize cached data size statistics for bucket cache<a name="line.338"></a>
-<span class="sourceLineNo">339</span> * @throws BucketAllocatorException<a name="line.339"></a>
-<span class="sourceLineNo">340</span> */<a name="line.340"></a>
-<span class="sourceLineNo">341</span> BucketAllocator(long availableSpace, int[] bucketSizes, Map<BlockCacheKey, BucketEntry> map,<a name="line.341"></a>
-<span class="sourceLineNo">342</span> LongAdder realCacheSize) throws BucketAllocatorException {<a name="line.342"></a>
-<span class="sourceLineNo">343</span> this(availableSpace, bucketSizes);<a name="line.343"></a>
-<span class="sourceLineNo">344</span><a name="line.344"></a>
-<span class="sourceLineNo">345</span> // each bucket has an offset, sizeindex. probably the buckets are too big<a name="line.345"></a>
-<span class="sourceLineNo">346</span> // in our default state. so what we do is reconfigure them according to what<a name="line.346"></a>
-<span class="sourceLineNo">347</span> // we've found. we can only reconfigure each bucket once; if more than once,<a name="line.347"></a>
-<span class="sourceLineNo">348</span> // we know there's a bug, so we just log the info, throw, and start again...<a name="line.348"></a>
-<span class="sourceLineNo">349</span> boolean[] reconfigured = new boolean[buckets.length];<a name="line.349"></a>
-<span class="sourceLineNo">350</span> int sizeNotMatchedCount = 0;<a name="line.350"></a>
-<span class="sourceLineNo">351</span> int insufficientCapacityCount = 0;<a name="line.351"></a>
-<span class="sourceLineNo">352</span> Iterator<Map.Entry<BlockCacheKey, BucketEntry>> iterator = map.entrySet().iterator();<a name="line.352"></a>
-<span class="sourceLineNo">353</span> while (iterator.hasNext()) {<a name="line.353"></a>
-<span class="sourceLineNo">354</span> Map.Entry<BlockCacheKey, BucketEntry> entry = iterator.next();<a name="line.354"></a>
-<span class="sourceLineNo">355</span> long foundOffset = entry.getValue().offset();<a name="line.355"></a>
-<span class="sourceLineNo">356</span> int foundLen = entry.getValue().getLength();<a name="line.356"></a>
-<span class="sourceLineNo">357</span> int bucketSizeIndex = -1;<a name="line.357"></a>
-<span class="sourceLineNo">358</span> for (int i = 0; i < this.bucketSizes.length; ++i) {<a name="line.358"></a>
-<span class="sourceLineNo">359</span> if (foundLen <= this.bucketSizes[i]) {<a name="line.359"></a>
-<span class="sourceLineNo">360</span> bucketSizeIndex = i;<a name="line.360"></a>
-<span class="sourceLineNo">361</span> break;<a name="line.361"></a>
-<span class="sourceLineNo">362</span> }<a name="line.362"></a>
-<span class="sourceLineNo">363</span> }<a name="line.363"></a>
-<span class="sourceLineNo">364</span> if (bucketSizeIndex == -1) {<a name="line.364"></a>
-<span class="sourceLineNo">365</span> sizeNotMatchedCount++;<a name="line.365"></a>
-<span class="sourceLineNo">366</span> iterator.remove();<a name="line.366"></a>
-<span class="sourceLineNo">367</span> continue;<a name="line.367"></a>
-<span class="sourceLineNo">368</span> }<a name="line.368"></a>
-<span class="sourceLineNo">369</span> int bucketNo = (int) (foundOffset / bucketCapacity);<a name="line.369"></a>
-<span class="sourceLineNo">370</span> if (bucketNo < 0 || bucketNo >= buckets.length) {<a name="line.370"></a>
-<span class="sourceLineNo">371</span> insufficientCapacityCount++;<a name="line.371"></a>
-<span class="sourceLineNo">372</span> iterator.remove();<a name="line.372"></a>
-<span class="sourceLineNo">373</span> continue;<a name="line.373"></a>
-<span class="sourceLineNo">374</span> }<a name="line.374"></a>
-<span class="sourceLineNo">375</span> Bucket b = buckets[bucketNo];<a name="line.375"></a>
-<span class="sourceLineNo">376</span> if (reconfigured[bucketNo]) {<a name="line.376"></a>
-<span class="sourceLineNo">377</span> if (b.sizeIndex() != bucketSizeIndex) {<a name="line.377"></a>
-<span class="sourceLineNo">378</span> throw new BucketAllocatorException("Inconsistent allocation in bucket map;");<a name="line.378"></a>
-<span class="sourceLineNo">379</span> }<a name="line.379"></a>
-<span class="sourceLineNo">380</span> } else {<a name="line.380"></a>
-<span class="sourceLineNo">381</span> if (!b.isCompletelyFree()) {<a name="line.381"></a>
-<span class="sourceLineNo">382</span> throw new BucketAllocatorException(<a name="line.382"></a>
-<span class="sourceLineNo">383</span> "Reconfiguring bucket " + bucketNo + " but it's already allocated; corrupt data");<a name="line.383"></a>
-<span class="sourceLineNo">384</span> }<a name="line.384"></a>
-<span class="sourceLineNo">385</span> // Need to remove the bucket from whichever list it's currently in at<a name="line.385"></a>
-<span class="sourceLineNo">386</span> // the moment...<a name="line.386"></a>
-<span class="sourceLineNo">387</span> BucketSizeInfo bsi = bucketSizeInfos[bucketSizeIndex];<a name="line.387"></a>
-<span class="sourceLineNo">388</span> BucketSizeInfo oldbsi = bucketSizeInfos[b.sizeIndex()];<a name="line.388"></a>
-<span class="sourceLineNo">389</span> oldbsi.removeBucket(b);<a name="line.389"></a>
-<span class="sourceLineNo">390</span> bsi.instantiateBucket(b);<a name="line.390"></a>
-<span class="sourceLineNo">391</span> reconfigured[bucketNo] = true;<a name="line.391"></a>
-<span class="sourceLineNo">392</span> }<a name="line.392"></a>
-<span class="sourceLineNo">393</span> realCacheSize.add(foundLen);<a name="line.393"></a>
-<span class="sourceLineNo">394</span> buckets[bucketNo].addAllocation(foundOffset);<a name="line.394"></a>
-<span class="sourceLineNo">395</span> usedSize += buckets[bucketNo].getItemAllocationSize();<a name="line.395"></a>
-<span class="sourceLineNo">396</span> bucketSizeInfos[bucketSizeIndex].blockAllocated(b);<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> if (sizeNotMatchedCount > 0) {<a name="line.399"></a>
-<span class="sourceLineNo">400</span> LOG.warn("There are " + sizeNotMatchedCount + " blocks which can't be rebuilt because " +<a name="line.400"></a>
-<span class="sourceLineNo">401</span> "there is no matching bucket size for these blocks");<a name="line.401"></a>
-<span class="sourceLineNo">402</span> }<a name="line.402"></a>
-<span class="sourceLineNo">403</span> if (insufficientCapacityCount > 0) {<a name="line.403"></a>
-<span class="sourceLineNo">404</span> LOG.warn("There are " + insufficientCapacityCount + " blocks which can't be rebuilt - "<a name="line.404"></a>
-<span class="sourceLineNo">405</span> + "did you shrink the cache?");<a name="line.405"></a>
-<span class="sourceLineNo">406</span> }<a name="line.406"></a>
-<span class="sourceLineNo">407</span> }<a name="line.407"></a>
-<span class="sourceLineNo">408</span><a name="line.408"></a>
-<span class="sourceLineNo">409</span> @Override<a name="line.409"></a>
-<span class="sourceLineNo">410</span> public String toString() {<a name="line.410"></a>
-<span class="sourceLineNo">411</span> StringBuilder sb = new StringBuilder(1024);<a name="line.411"></a>
-<span class="sourceLineNo">412</span> for (int i = 0; i < buckets.length; ++i) {<a name="line.412"></a>
-<span class="sourceLineNo">413</span> Bucket b = buckets[i];<a name="line.413"></a>
-<span class="sourceLineNo">414</span> if (i > 0) sb.append(", ");<a name="line.414"></a>
-<span class="sourceLineNo">415</span> sb.append("bucket.").append(i).append(": size=").append(b.getItemAllocationSize());<a name="line.415"></a>
-<span class="sourceLineNo">416</span> sb.append(", freeCount=").append(b.freeCount()).append(", used=").append(b.usedCount());<a name="line.416"></a>
-<span class="sourceLineNo">417</span> }<a name="line.417"></a>
-<span class="sourceLineNo">418</span> return sb.toString();<a name="line.418"></a>
-<span class="sourceLineNo">419</span> }<a name="line.419"></a>
-<span class="sourceLineNo">420</span><a name="line.420"></a>
-<span class="sourceLineNo">421</span> public long getUsedSize() {<a name="line.421"></a>
-<span class="sourceLineNo">422</span> return this.usedSize;<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> public long getFreeSize() {<a name="line.425"></a>
-<span class="sourceLineNo">426</span> return this.totalSize - getUsedSize();<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> public long getTotalSize() {<a name="line.429"></a>
-<span class="sourceLineNo">430</span> return this.totalSize;<a name="line.430"></a>
-<span class="sourceLineNo">431</span> }<a name="line.431"></a>
-<span class="sourceLineNo">432</span><a name="line.432"></a>
-<span class="sourceLineNo">433</span> /**<a name="line.433"></a>
-<span class="sourceLineNo">434</span> * Allocate a block with specified size. Return the offset<a name="line.434"></a>
-<span class="sourceLineNo">435</span> * @param blockSize size of block<a name="line.435"></a>
-<span class="sourceLineNo">436</span> * @throws BucketAllocatorException<a name="line.436"></a>
-<span class="sourceLineNo">437</span> * @throws CacheFullException<a name="line.437"></a>
-<span class="sourceLineNo">438</span> * @return the offset in the IOEngine<a name="line.438"></a>
-<span class="sourceLineNo">439</span> */<a name="line.439"></a>
-<span class="sourceLineNo">440</span> public synchronized long allocateBlock(int blockSize) throws CacheFullException,<a name="line.440"></a>
-<span class="sourceLineNo">441</span> BucketAllocatorException {<a name="line.441"></a>
-<span class="sourceLineNo">442</span> assert blockSize > 0;<a name="line.442"></a>
-<span class="sourceLineNo">443</span> BucketSizeInfo bsi = roundUpToBucketSizeInfo(blockSize);<a name="line.443"></a>
-<span class="sourceLineNo">444</span> if (bsi == null) {<a name="line.444"></a>
-<span class="sourceLineNo">445</span> throw new BucketAllocatorException("Allocation too big size=" + blockSize +<a name="line.445"></a>
-<span class="sourceLineNo">446</span> "; adjust BucketCache sizes " + BlockCacheFactory.BUCKET_CACHE_BUCKETS_KEY +<a name="line.446"></a>
-<span class="sourceLineNo">447</span> " to accomodate if size seems reasonable and you want it cached.");<a name="line.447"></a>
-<span class="sourceLineNo">448</span> }<a name="line.448"></a>
-<span class="sourceLineNo">449</span> long offset = bsi.allocateBlock();<a name="line.449"></a>
-<span class="sourceLineNo">450</span><a name="line.450"></a>
-<span class="sourceLineNo">451</span> // Ask caller to free up space and try again!<a name="line.451"></a>
-<span class="sourceLineNo">452</span> if (offset < 0)<a name="line.452"></a>
-<span class="sourceLineNo">453</span> throw new CacheFullException(blockSize, bsi.sizeIndex());<a name="line.453"></a>
-<span class="sourceLineNo">454</span> usedSize += bucketSizes[bsi.sizeIndex()];<a name="line.454"></a>
-<span class="sourceLineNo">455</span> return offset;<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> private Bucket grabGlobalCompletelyFreeBucket() {<a name="line.458"></a>
-<span class="sourceLineNo">459</span> for (BucketSizeInfo bsi : bucketSizeInfos) {<a name="line.459"></a>
-<span class="sourceLineNo">460</span> Bucket b = bsi.findAndRemoveCompletelyFreeBucket();<a name="line.460"></a>
-<span class="sourceLineNo">461</span> if (b != null) return b;<a name="line.461"></a>
-<span class="sourceLineNo">462</span> }<a name="line.462"></a>
-<span class="sourceLineNo">463</span> return null;<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> * Free a block with the offset<a name="line.467"></a>
-<span class="sourceLineNo">468</span> * @param offset block's offset<a name="line.468"></a>
-<span class="sourceLineNo">469</span> * @return size freed<a name="line.469"></a>
-<span class="sourceLineNo">470</span> */<a name="line.470"></a>
-<span class="sourceLineNo">471</span> public synchronized int freeBlock(long offset) {<a name="line.471"></a>
-<span class="sourceLineNo">472</span> int bucketNo = (int) (offset / bucketCapacity);<a name="line.472"></a>
-<span class="sourceLineNo">473</span> assert bucketNo >= 0 && bucketNo < buckets.length;<a name="line.473"></a>
-<span class="sourceLineNo">474</span> Bucket targetBucket = buckets[bucketNo];<a name="line.474"></a>
-<span class="sourceLineNo">475</span> bucketSizeInfos[targetBucket.sizeIndex()].freeBlock(targetBucket, offset);<a name="line.475"></a>
-<span class="sourceLineNo">476</span> usedSize -= targetBucket.getItemAllocationSize();<a name="line.476"></a>
-<span class="sourceLineNo">477</span> return targetBucket.getItemAllocationSize();<a name="line.477"></a>
-<span class="sourceLineNo">478</span> }<a name="line.478"></a>
-<span class="sourceLineNo">479</span><a name="line.479"></a>
-<span class="sourceLineNo">480</span> public int sizeIndexOfAllocation(long offset) {<a name="line.480"></a>
-<span class="sourceLineNo">481</span> int bucketNo = (int) (offset / bucketCapacity);<a name="line.481"></a>
-<span class="sourceLineNo">482</span> assert bucketNo >= 0 && bucketNo < buckets.length;<a name="line.482"></a>
-<span class="sourceLineNo">483</span> Bucket targetBucket = buckets[bucketNo];<a name="line.483"></a>
-<span class="sourceLineNo">484</span> return targetBucket.sizeIndex();<a name="line.484"></a>
-<span class="sourceLineNo">485</span> }<a name="line.485"></a>
-<span class="sourceLineNo">486</span><a name="line.486"></a>
-<span class="sourceLineNo">487</span> public int sizeOfAllocation(long offset) {<a name="line.487"></a>
-<span class="sourceLineNo">488</span> int bucketNo = (int) (offset / bucketCapacity);<a name="line.488"></a>
-<span class="sourceLineNo">489</span> assert bucketNo >= 0 && bucketNo < buckets.length;<a name="line.489"></a>
-<span class="sourceLineNo">490</span> Bucket targetBucket = buckets[bucketNo];<a name="line.490"></a>
-<span class="sourceLineNo">491</span> return targetBucket.getItemAllocationSize();<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> static class IndexStatistics {<a name="line.494"></a>
-<span class="sourceLineNo">495</span> private long freeCount, usedCount, itemSize, totalCount;<a name="line.495"></a>
-<span class="sourceLineNo">496</span><a name="line.496"></a>
-<span class="sourceLineNo">497</span> public long freeCount() {<a name="line.497"></a>
-<span class="sourceLineNo">498</span> return freeCount;<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> public long usedCount() {<a name="line.501"></a>
-<span class="sourceLineNo">502</span> return usedCount;<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> public long totalCount() {<a name="line.505"></a>
-<span class="sourceLineNo">506</span> return totalCount;<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> public long freeBytes() {<a name="line.509"></a>
-<span class="sourceLineNo">510</span> return freeCount * itemSize;<a name="line.510"></a>
-<span class="sourceLineNo">511</span> }<a name="line.511"></a>
-<span class="sourceLineNo">512</span><a name="line.512"></a>
-<span class="sourceLineNo">513</span> public long usedBytes() {<a name="line.513"></a>
-<span class="sourceLineNo">514</span> return usedCount * itemSize;<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> public long totalBytes() {<a name="line.517"></a>
-<span class="sourceLineNo">518</span> return totalCount * itemSize;<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> public long itemSize() {<a name="line.521"></a>
-<span class="sourceLineNo">522</span> return itemSize;<a name="line.522"></a>
-<span class="sourceLineNo">523</span> }<a name="line.523"></a>
-<span class="sourceLineNo">524</span><a name="line.524"></a>
-<span class="sourceLineNo">525</span> public IndexStatistics(long free, long used, long itemSize) {<a name="line.525"></a>
-<span class="sourceLineNo">526</span> setTo(free, used, itemSize);<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> public IndexStatistics() {<a name="line.529"></a>
-<span class="sourceLineNo">530</span> setTo(-1, -1, 0);<a name="line.530"></a>
-<span class="sourceLineNo">531</span> }<a name="line.531"></a>
-<span class="sourceLineNo">532</span><a name="line.532"></a>
-<span class="sourceLineNo">533</span> public void setTo(long free, long used, long itemSize) {<a name="line.533"></a>
-<span class="sourceLineNo">534</span> this.itemSize = itemSize;<a name="line.534"></a>
-<span class="sourceLineNo">535</span> this.freeCount = free;<a name="line.535"></a>
-<span class="sourceLineNo">536</span> this.usedCount = used;<a name="line.536"></a>
-<span class="sourceLineNo">537</span> this.totalCount = free + used;<a name="line.537"></a>
-<span class="sourceLineNo">538</span> }<a name="line.538"></a>
-<span class="sourceLineNo">539</span> }<a name="line.539"></a>
-<span class="sourceLineNo">540</span><a name="line.540"></a>
-<span class="sourceLineNo">541</span> public Bucket [] getBuckets() {<a name="line.541"></a>
-<span class="sourceLineNo">542</span> return this.buckets;<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> void logStatistics() {<a name="line.545"></a>
-<span class="sourceLineNo">546</span> IndexStatistics total = new IndexStatistics();<a name="line.546"></a>
-<span class="sourceLineNo">547</span> IndexStatistics[] stats = getIndexStatistics(total);<a name="line.547"></a>
-<span class="sourceLineNo">548</span> LOG.info("Bucket allocator statistics follow:\n");<a name="line.548"></a>
-<span class="sourceLineNo">549</span> LOG.info(" Free bytes=" + total.freeBytes() + "+; used bytes="<a name="line.549"></a>
-<span class="sourceLineNo">550</span> + total.usedBytes() + "; total bytes=" + total.totalBytes());<a name="line.550"></a>
-<span class="sourceLineNo">551</span> for (IndexStatistics s : stats) {<a name="line.551"></a>
-<span class="sourceLineNo">552</span> LOG.info(" Object size " + s.itemSize() + " used=" + s.usedCount()<a name="line.552"></a>
-<span class="sourceLineNo">553</span> + "; free=" + s.freeCount() + "; total=" + s.totalCount());<a name="line.553"></a>
-<span class="sourceLineNo">554</span> }<a name="line.554"></a>
-<span class="sourceLineNo">555</span> }<a name="line.555"></a>
-<span class="sourceLineNo">556</span><a name="line.556"></a>
-<span class="sourceLineNo">557</span> IndexStatistics[] getIndexStatistics(IndexStatistics grandTotal) {<a name="line.557"></a>
-<span class="sourceLineNo">558</span> IndexStatistics[] stats = getIndexStatistics();<a name="line.558"></a>
-<span class="sourceLineNo">559</span> long totalfree = 0, totalused = 0;<a name="line.559"></a>
-<span class="sourceLineNo">560</span> for (IndexStatistics stat : stats) {<a name="line.560"></a>
-<span class="sourceLineNo">561</span> totalfree += stat.freeBytes();<a name="line.561"></a>
-<span class="sourceLineNo">562</span> totalused += stat.usedBytes();<a name="line.562"></a>
-<span class="sourceLineNo">563</span> }<a name="line.563"></a>
-<span class="sourceLineNo">564</span> grandTotal.setTo(totalfree, totalused, 1);<a name="line.564"></a>
-<span class="sourceLineNo">565</span> return stats;<a name="line.565"></a>
-<span class="sourceLineNo">566</span> }<a name="line.566"></a>
-<span class="sourceLineNo">567</span><a name="line.567"></a>
-<span class="sourceLineNo">568</span> IndexStatistics[] getIndexStatistics() {<a name="line.568"></a>
-<span class="sourceLineNo">569</span> IndexStatistics[] stats = new IndexStatistics[bucketSizes.length];<a name="line.569"></a>
-<span class="sourceLineNo">570</span> for (int i = 0; i < stats.length; ++i)<a name="line.570"></a>
-<span class="sourceLineNo">571</span> stats[i] = bucketSizeInfos[i].statistics();<a name="line.571"></a>
-<span class="sourceLineNo">572</span> return stats;<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> public long freeBlock(long freeList[]) {<a name="line.575"></a>
-<span class="sourceLineNo">576</span> long sz = 0;<a name="line.576"></a>
-<span class="sourceLineNo">577</span> for (int i = 0; i < freeList.length; ++i)<a name="line.577"></a>
-<span class="sourceLineNo">578</span> sz += freeBlock(freeList[i]);<a name="line.578"></a>
-<span class="sourceLineNo">579</span> return sz;<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> public int getBucketIndex(long offset) {<a name="line.582"></a>
-<span class="sourceLineNo">583</span> return (int) (offset / bucketCapacity);<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> * Returns a set of indices of the buckets that are least filled<a name="line.587"></a>
-<span class="sourceLineNo">588</span> * excluding the offsets, we also the fully free buckets for the<a name="line.588"></a>
-<span class="sourceLineNo">589</span> * BucketSizes where everything is empty and they only have one<a name="line.589"></a>
-<span class="sourceLineNo">590</span> * completely free bucket as a reserved<a name="line.590"></a>
-<span class="sourceLineNo">591</span> *<a name="line.591"></a>
-<span class="sourceLineNo">592</span> * @param excludedBuckets the buckets that need to be excluded due to<a name="line.592"></a>
-<span class="sourceLineNo">593</span> * currently being in used<a name="line.593"></a>
-<span class="sourceLineNo">594</span> * @param bucketCount max Number of buckets to return<a name="line.594"></a>
-<span class="sourceLineNo">595</span> * @return set of bucket indices which could be used for eviction<a name="line.595"></a>
-<span class="sourceLineNo">596</span> */<a name="line.596"></a>
-<span class="sourceLineNo">597</span> public Set<Integer> getLeastFilledBuckets(Set<Integer> excludedBuckets,<a name="line.597"></a>
-<span class="sourceLineNo">598</span> int bucketCount) {<a name="line.598"></a>
-<span class="sourceLineNo">599</span> Queue<Integer> queue = MinMaxPriorityQueue.<Integer>orderedBy(<a name="line.599"></a>
-<span class="sourceLineNo">600</span> new Comparator<Integer>() {<a name="line.600"></a>
-<span class="sourceLineNo">601</span> @Override<a name="line.601"></a>
-<span class="sourceLineNo">602</span> public int compare(Integer left, Integer right) {<a name="line.602"></a>
-<span class="sourceLineNo">603</span> // We will always get instantiated buckets<a name="line.603"></a>
-<span class="sourceLineNo">604</span> return Float.compare(<a name="line.604"></a>
-<span class="sourceLineNo">605</span> ((float) buckets[left].usedCount) / buckets[left].itemCount,<a name="line.605"></a>
-<span class="sourceLineNo">606</span> ((float) buckets[right].usedCount) / buckets[right].itemCount);<a name="line.606"></a>
-<span class="sourceLineNo">607</span> }<a name="line.607"></a>
-<span class="sourceLineNo">608</span> }).maximumSize(bucketCount).create();<a name="line.608"></a>
-<span class="sourceLineNo">609</span><a name="line.609"></a>
-<span class="sourceLineNo">610</span> for (int i = 0; i < buckets.length; i ++ ) {<a name="line.610"></a>
-<span class="sourceLineNo">611</span> if (!excludedBuckets.contains(i) && !buckets[i].isUninstantiated() &&<a name="line.611"></a>
-<span class="sourceLineNo">612</span> // Avoid the buckets that are the only buckets for a sizeIndex<a name="line.612"></a>
-<span class="sourceLineNo">613</span> bucketSizeInfos[buckets[i].sizeIndex()].bucketList.size() != 1) {<a name="line.613"></a>
-<span class="sourceLineNo">614</span> queue.add(i);<a name="line.614"></a>
-<span class="sourceLineNo">615</span> }<a name="line.615"></a>
-<span class="sourceLineNo">616</span> }<a name="line.616"></a>
-<span class="sourceLineNo">617</span><a name="line.617"></a>
-<span class="sourceLineNo">618</span> Set<Integer> result = new HashSet<>(bucketCount);<a name="line.618"></a>
-<span class="sourceLineNo">619</span> result.addAll(queue);<a name="line.619"></a>
-<span class="sourceLineNo">620</span><a name="line.620"></a>
-<span class="sourceLineNo">621</span> return result;<a name="line.621"></a>
-<span class="sourceLineNo">622</span> }<a name="line.622"></a>
-<span class="sourceLineNo">623</span>}<a name="line.623"></a>
+<span class="sourceLineNo">272</span> // The real block size in hfile maybe a little larger than the size we configured ,<a name="line.272"></a>
+<span class="sourceLineNo">273</span> // so we need add extra 1024 bytes for fit.<a name="line.273"></a>
+<span class="sourceLineNo">274</span> // TODO Support the view of block size distribution statistics<a name="line.274"></a>
+<span class="sourceLineNo">275</span> private static final int DEFAULT_BUCKET_SIZES[] = { 4 * 1024 + 1024, 8 * 1024 + 1024,<a name="line.275"></a>
+<span class="sourceLineNo">276</span> 16 * 1024 + 1024, 32 * 1024 + 1024, 40 * 1024 + 1024, 48 * 1024 + 1024,<a name="line.276"></a>
+<span class="sourceLineNo">277</span> 56 * 1024 + 1024, 64 * 1024 + 1024, 96 * 1024 + 1024, 128 * 1024 + 1024,<a name="line.277"></a>
+<span class="sourceLineNo">278</span> 192 * 1024 + 1024, 256 * 1024 + 1024, 384 * 1024 + 1024,<a name="line.278"></a>
+<span class="sourceLineNo">279</span> 512 * 1024 + 1024 };<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> * Round up the given block size to bucket size, and get the corresponding<a name="line.282"></a>
+<span class="sourceLineNo">283</span> * BucketSizeInfo<a name="line.283"></a>
+<span class="sourceLineNo">284</span> */<a name="line.284"></a>
+<span class="sourceLineNo">285</span> public BucketSizeInfo roundUpToBucketSizeInfo(int blockSize) {<a name="line.285"></a>
+<span class="sourceLineNo">286</span> for (int i = 0; i < bucketSizes.length; ++i)<a name="line.286"></a>
+<span class="sourceLineNo">287</span> if (blockSize <= bucketSizes[i])<a name="line.287"></a>
+<span class="sourceLineNo">288</span> return bucketSizeInfos[i];<a name="line.288"></a>
+<span class="sourceLineNo">289</span> return null;<a name="line.289"></a>
+<span class="sourceLineNo">290</span> }<a name="line.290"></a>
+<span class="sourceLineNo">291</span><a name="line.291"></a>
+<span class="sourceLineNo">292</span> /**<a name="line.292"></a>
+<span class="sourceLineNo">293</span> * So, what is the minimum amount of items we'll tolerate in a single bucket?<a name="line.293"></a>
+<span class="sourceLineNo">294</span> */<a name="line.294"></a>
+<span class="sourceLineNo">295</span> static public final int FEWEST_ITEMS_IN_BUCKET = 4;<a name="line.295"></a>
+<span class="sourceLineNo">296</span><a name="line.296"></a>
+<span class="sourceLineNo">297</span> private final int[] bucketSizes;<a name="line.297"></a>
+<span class="sourceLineNo">298</span> private final int bigItemSize;<a name="line.298"></a>
+<span class="sourceLineNo">299</span> // The capacity size for each bucket<a name="line.299"></a>
+<span class="sourceLineNo">300</span> private final long bucketCapacity;<a name="line.300"></a>
+<span class="sourceLineNo">301</span> private Bucket[] buckets;<a name="line.301"></a>
+<span class="sourceLineNo">302</span> private BucketSizeInfo[] bucketSizeInfos;<a name="line.302"></a>
+<span class="sourceLineNo">303</span> private final long totalSize;<a name="line.303"></a>
+<span class="sourceLineNo">304</span> private transient long usedSize = 0;<a name="line.304"></a>
+<span class="sourceLineNo">305</span><a name="line.305"></a>
+<span class="sourceLineNo">306</span> BucketAllocator(long availableSpace, int[] bucketSizes)<a name="line.306"></a>
+<span class="sourceLineNo">307</span> throws BucketAllocatorException {<a name="line.307"></a>
+<span class="sourceLineNo">308</span> this.bucketSizes = bucketSizes == null ? DEFAULT_BUCKET_SIZES : bucketSizes;<a name="line.308"></a>
+<span class="sourceLineNo">309</span> Arrays.sort(this.bucketSizes);<a name="line.309"></a>
+<span class="sourceLineNo">310</span> this.bigItemSize = Ints.max(this.bucketSizes);<a name="line.310"></a>
+<span class="sourceLineNo">311</span> this.bucketCapacity = FEWEST_ITEMS_IN_BUCKET * (long) bigItemSize;<a name="line.311"></a>
+<span class="sourceLineNo">312</span> buckets = new Bucket[(int) (availableSpace / bucketCapacity)];<a name="line.312"></a>
+<span class="sourceLineNo">313</span> if (buckets.length < this.bucketSizes.length)<a name="line.313"></a>
+<span class="sourceLineNo">314</span> throw new BucketAllocatorException("Bucket allocator size too small (" + buckets.length +<a name="line.314"></a>
+<span class="sourceLineNo">315</span> "); must have room for at least " + this.bucketSizes.length + " buckets");<a name="line.315"></a>
+<span class="sourceLineNo">316</span> bucketSizeInfos = new BucketSizeInfo[this.bucketSizes.length];<a name="line.316"></a>
+<span class="sourceLineNo">317</span> for (int i = 0; i < this.bucketSizes.length; ++i) {<a name="line.317"></a>
+<span class="sourceLineNo">318</span> bucketSizeInfos[i] = new BucketSizeInfo(i);<a name="line.318"></a>
+<span class="sourceLineNo">319</span> }<a name="line.319"></a>
+<span class="sourceLineNo">320</span> for (int i = 0; i < buckets.length; ++i) {<a name="line.320"></a>
+<span class="sourceLineNo">321</span> buckets[i] = new Bucket(bucketCapacity * i);<a name="line.321"></a>
+<span class="sourceLineNo">322</span> bucketSizeInfos[i < this.bucketSizes.length ? i : this.bucketSizes.length - 1]<a name="line.322"></a>
+<span class="sourceLineNo">323</span> .instantiateBucket(buckets[i]);<a name="line.323"></a>
+<span class="sourceLineNo">324</span> }<a name="line.324"></a>
+<span class="sourceLineNo">325</span> this.totalSize = ((long) buckets.length) * bucketCapacity;<a name="line.325"></a>
+<span class="sourceLineNo">326</span> if (LOG.isInfoEnabled()) {<a name="line.326"></a>
+<span class="sourceLineNo">327</span> LOG.info("Cache totalSize=" + this.totalSize + ", buckets=" + this.buckets.length +<a name="line.327"></a>
+<span class="sourceLineNo">328</span> ", bucket capacity=" + this.bucketCapacity +<a name="line.328"></a>
+<span class="sourceLineNo">329</span> "=(" + FEWEST_ITEMS_IN_BUCKET + "*" + this.bigItemSize + ")=" +<a name="line.329"></a>
+<span class="sourceLineNo">330</span> "(FEWEST_ITEMS_IN_BUCKET*(largest configured bucketcache size))");<a name="line.330"></a>
+<span class="sourceLineNo">331</span> }<a name="line.331"></a>
+<span class="sourceLineNo">332</span> }<a name="line.332"></a>
+<span class="sourceLineNo">333</span><a name="line.333"></a>
+<span class="sourceLineNo">334</span> /**<a name="line.334"></a>
+<span class="sourceLineNo">335</span> * Rebuild the allocator's data structures from a persisted map.<a name="line.335"></a>
+<span class="sourceLineNo">336</span> * @param availableSpace capacity of cache<a name="line.336"></a>
+<span class="sourceLineNo">337</span> * @param map A map stores the block key and BucketEntry(block's meta data<a name="line.337"></a>
+<span class="sourceLineNo">338</span> * like offset, length)<a name="line.338"></a>
+<span class="sourceLineNo">339</span> * @param realCacheSize cached data size statistics for bucket cache<a name="line.339"></a>
+<span class="sourceLineNo">340</span> * @throws BucketAllocatorException<a name="line.340"></a>
+<span class="sourceLineNo">341</span> */<a name="line.341"></a>
+<span class="sourceLineNo">342</span> BucketAllocator(long availableSpace, int[] bucketSizes, Map<BlockCacheKey, BucketEntry> map,<a name="line.342"></a>
+<span class="sourceLineNo">343</span> LongAdder realCacheSize) throws BucketAllocatorException {<a name="line.343"></a>
+<span class="sourceLineNo">344</span> this(availableSpace, bucketSizes);<a name="line.344"></a>
+<span class="sourceLineNo">345</span><a name="line.345"></a>
+<span class="sourceLineNo">346</span> // each bucket has an offset, sizeindex. probably the buckets are too big<a name="line.346"></a>
+<span class="sourceLineNo">347</span> // in our default state. so what we do is reconfigure them according to what<a name="line.347"></a>
+<span class="sourceLineNo">348</span> // we've found. we can only reconfigure each bucket once; if more than once,<a name="line.348"></a>
+<span class="sourceLineNo">349</span> // we know there's a bug, so we just log the info, throw, and start again...<a name="line.349"></a>
+<span class="sourceLineNo">350</span> boolean[] reconfigured = new boolean[buckets.length];<a name="line.350"></a>
+<span class="sourceLineNo">351</span> int sizeNotMatchedCount = 0;<a name="line.351"></a>
+<span class="sourceLineNo">352</span> int insufficientCapacityCount = 0;<a name="line.352"></a>
+<span class="sourceLineNo">353</span> Iterator<Map.Entry<BlockCacheKey, BucketEntry>> iterator = map.entrySet().iterator();<a name="line.353"></a>
+<span class="sourceLineNo">354</span> while (iterator.hasNext()) {<a name="line.354"></a>
+<span class="sourceLineNo">355</span> Map.Entry<BlockCacheKey, BucketEntry> entry = iterator.next();<a name="line.355"></a>
+<span class="sourceLineNo">356</span> long foundOffset = entry.getValue().offset();<a name="line.356"></a>
+<span class="sourceLineNo">357</span> int foundLen = entry.getValue().getLength();<a name="line.357"></a>
+<span class="sourceLineNo">358</span> int bucketSizeIndex = -1;<a name="line.358"></a>
+<span class="sourceLineNo">359</span> for (int i = 0; i < this.bucketSizes.length; ++i) {<a name="line.359"></a>
+<span class="sourceLineNo">360</span> if (foundLen <= this.bucketSizes[i]) {<a name="line.360"></a>
+<span class="sourceLineNo">361</span> bucketSizeIndex = i;<a name="line.361"></a>
+<span class="sourceLineNo">362</span> break;<a name="line.362"></a>
+<span class="sourceLineNo">363</span> }<a name="line.363"></a>
+<span class="sourceLineNo">364</span> }<a name="line.364"></a>
+<span class="sourceLineNo">365</span> if (bucketSizeIndex == -1) {<a name="line.365"></a>
+<span class="sourceLineNo">366</span> sizeNotMatchedCount++;<a name="line.366"></a>
+<span class="sourceLineNo">367</span> iterator.remove();<a name="line.367"></a>
+<span class="sourceLineNo">368</span> continue;<a name="line.368"></a>
+<span class="sourceLineNo">369</span> }<a name="line.369"></a>
+<span class="sourceLineNo">370</span> int bucketNo = (int) (foundOffset / bucketCapacity);<a name="line.370"></a>
+<span class="sourceLineNo">371</span> if (bucketNo < 0 || bucketNo >= buckets.length) {<a name="line.371"></a>
+<span class="sourceLineNo">372</span> insufficientCapacityCount++;<a name="line.372"></a>
+<span class="sourceLineNo">373</span> iterator.remove();<a name="line.373"></a>
+<span class="sourceLineNo">374</span> continue;<a name="line.374"></a>
+<span class="sourceLineNo">375</span> }<a name="line.375"></a>
+<span class="sourceLineNo">376</span> Bucket b = buckets[bucketNo];<a name="line.376"></a>
+<span class="sourceLineNo">377</span> if (reconfigured[bucketNo]) {<a name="line.377"></a>
+<span class="sourceLineNo">378</span> if (b.sizeIndex() != bucketSizeIndex) {<a name="line.378"></a>
+<span class="sourceLineNo">379</span> throw new BucketAllocatorException("Inconsistent allocation in bucket map;");<a name="line.379"></a>
+<span class="sourceLineNo">380</span> }<a name="line.380"></a>
+<span class="sourceLineNo">381</span> } else {<a name="line.381"></a>
+<span class="sourceLineNo">382</span> if (!b.isCompletelyFree()) {<a name="line.382"></a>
+<span class="sourceLineNo">383</span> throw new BucketAllocatorException(<a name="line.383"></a>
+<span class="sourceLineNo">384</span> "Reconfiguring bucket " + bucketNo + " but it's already allocated; corrupt data");<a name="line.384"></a>
+<span class="sourceLineNo">385</span> }<a name="line.385"></a>
+<span class="sourceLineNo">386</span> // Need to remove the bucket from whichever list it's currently in at<a name="line.386"></a>
+<span class="sourceLineNo">387</span> // the moment...<a name="line.387"></a>
+<span class="sourceLineNo">388</span> BucketSizeInfo bsi = bucketSizeInfos[bucketSizeIndex];<a name="line.388"></a>
+<span class="sourceLineNo">389</span> BucketSizeInfo oldbsi = bucketSizeInfos[b.sizeIndex()];<a name="line.389"></a>
+<span class="sourceLineNo">390</span> oldbsi.removeBucket(b);<a name="line.390"></a>
+<span class="sourceLineNo">391</span> bsi.instantiateBucket(b);<a name="line.391"></a>
+<span class="sourceLineNo">392</span> reconfigured[bucketNo] = true;<a name="line.392"></a>
+<span class="sourceLineNo">393</span> }<a name="line.393"></a>
+<span class="sourceLineNo">394</span> realCacheSize.add(foundLen);<a name="line.394"></a>
+<span class="sourceLineNo">395</span> buckets[bucketNo].addAllocation(foundOffset);<a name="line.395"></a>
+<span class="sourceLineNo">396</span> usedSize += buckets[bucketNo].getItemAllocationSize();<a name="line.396"></a>
+<span class="sourceLineNo">397</span> bucketSizeInfos[bucketSizeIndex].blockAllocated(b);<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> if (sizeNotMatchedCount > 0) {<a name="line.400"></a>
+<span class="sourceLineNo">401</span> LOG.warn("There are " + sizeNotMatchedCount + " blocks which can't be rebuilt because " +<a name="line.401"></a>
+<span class="sourceLineNo">402</span> "there is no matching bucket size for these blocks");<a name="line.402"></a>
+<span class="sourceLineNo">403</span> }<a name="line.403"></a>
+<span class="sourceLineNo">404</span> if (insufficientCapacityCount > 0) {<a name="line.404"></a>
+<span class="sourceLineNo">405</span> LOG.warn("There are " + insufficientCapacityCount + " blocks which can't be rebuilt - "<a name="line.405"></a>
+<span class="sourceLineNo">406</span> + "did you shrink the cache?");<a name="line.406"></a>
+<span class="sourceLineNo">407</span> }<a name="line.407"></a>
+<span class="sourceLineNo">408</span> }<a name="line.408"></a>
+<span class="sourceLineNo">409</span><a name="line.409"></a>
+<span class="sourceLineNo">410</span> @Override<a name="line.410"></a>
+<span class="sourceLineNo">411</span> public String toString() {<a name="line.411"></a>
+<span class="sourceLineNo">412</span> StringBuilder sb = new StringBuilder(1024);<a name="line.412"></a>
+<span class="sourceLineNo">413</span> for (int i = 0; i < buckets.length; ++i) {<a name="line.413"></a>
+<span class="sourceLineNo">414</span> Bucket b = buckets[i];<a name="line.414"></a>
+<span class="sourceLineNo">415</span> if (i > 0) sb.append(", ");<a name="line.415"></a>
+<span class="sourceLineNo">416</span> sb.append("bucket.").append(i).append(": size=").append(b.getItemAllocationSize());<a name="line.416"></a>
+<span class="sourceLineNo">417</span> sb.append(", freeCount=").append(b.freeCount()).append(", used=").append(b.usedCount());<a name="line.417"></a>
+<span class="sourceLineNo">418</span> }<a name="line.418"></a>
+<span class="sourceLineNo">419</span> return sb.toString();<a name="line.419"></a>
+<span class="sourceLineNo">420</span> }<a name="line.420"></a>
+<span class="sourceLineNo">421</span><a name="line.421"></a>
+<span class="sourceLineNo">422</span> public long getUsedSize() {<a name="line.422"></a>
+<span class="sourceLineNo">423</span> return this.usedSize;<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> public long getFreeSize() {<a name="line.426"></a>
+<span class="sourceLineNo">427</span> return this.totalSize - getUsedSize();<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> public long getTotalSize() {<a name="line.430"></a>
+<span class="sourceLineNo">431</span> return this.totalSize;<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> * Allocate a block with specified size. Return the offset<a name="line.435"></a>
+<span class="sourceLineNo">436</span> * @param blockSize size of block<a name="line.436"></a>
+<span class="sourceLineNo">437</span> * @throws BucketAllocatorException<a name="line.437"></a>
+<span class="sourceLineNo">438</span> * @throws CacheFullException<a name="line.438"></a>
+<span class="sourceLineNo">439</span> * @return the offset in the IOEngine<a name="line.439"></a>
+<span class="sourceLineNo">440</span> */<a name="line.440"></a>
+<span class="sourceLineNo">441</span> public synchronized long allocateBlock(int blockSize) throws CacheFullException,<a name="line.441"></a>
+<span class="sourceLineNo">442</span> BucketAllocatorException {<a name="line.442"></a>
+<span class="sourceLineNo">443</span> assert blockSize > 0;<a name="line.443"></a>
+<span class="sourceLineNo">444</span> BucketSizeInfo bsi = roundUpToBucketSizeInfo(blockSize);<a name="line.444"></a>
+<span class="sourceLineNo">445</span> if (bsi == null) {<a name="line.445"></a>
+<span class="sourceLineNo">446</span> throw new BucketAllocatorException("Allocation too big size=" + blockSize +<a name="line.446"></a>
+<span class="sourceLineNo">447</span> "; adjust BucketCache sizes " + BlockCacheFactory.BUCKET_CACHE_BUCKETS_KEY +<a name="line.447"></a>
+<span class="sourceLineNo">448</span> " to accomodate if size seems reasonable and you want it cached.");<a name="line.448"></a>
+<span class="sourceLineNo">449</span> }<a name="line.449"></a>
+<span class="sourceLineNo">450</span> long offset = bsi.allocateBlock();<a name="line.450"></a>
+<span class="sourceLineNo">451</span><a name="line.451"></a>
+<span class="sourceLineNo">452</span> // Ask caller to free up space and try again!<a name="line.452"></a>
+<span class="sourceLineNo">453</span> if (offset < 0)<a name="line.453"></a>
+<span class="sourceLineNo">454</span> throw new CacheFullException(blockSize, bsi.sizeIndex());<a name="line.454"></a>
+<span class="sourceLineNo">455</span> usedSize += bucketSizes[bsi.sizeIndex()];<a name="line.455"></a>
+<span class="sourceLineNo">456</span> return offset;<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> private Bucket grabGlobalCompletelyFreeBucket() {<a name="line.459"></a>
+<span class="sourceLineNo">460</span> for (BucketSizeInfo bsi : bucketSizeInfos) {<a name="line.460"></a>
+<span class="sourceLineNo">461</span> Bucket b = bsi.findAndRemoveCompletelyFreeBucket();<a name="line.461"></a>
+<span class="sourceLineNo">462</span> if (b != null) return b;<a name="line.462"></a>
+<span class="sourceLineNo">463</span> }<a name="line.463"></a>
+<span class="sourceLineNo">464</span> return null;<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> * Free a block with the offset<a name="line.468"></a>
+<span class="sourceLineNo">469</span> * @param offset block's offset<a name="line.469"></a>
+<span class="sourceLineNo">470</span> * @return size freed<a name="line.470"></a>
+<span class="sourceLineNo">471</span> */<a name="line.471"></a>
+<span class="sourceLineNo">472</span> public synchronized int freeBlock(long offset) {<a name="line.472"></a>
+<span class="sourceLineNo">473</span> int bucketNo = (int) (offset / bucketCapacity);<a name="line.473"></a>
+<span class="sourceLineNo">474</span> assert bucketNo >= 0 && bucketNo < buckets.length;<a name="line.474"></a>
+<span class="sourceLineNo">475</span> Bucket targetBucket = buckets[bucketNo];<a name="line.475"></a>
+<span class="sourceLineNo">476</span> bucketSizeInfos[targetBucket.sizeIndex()].freeBlock(targetBucket, offset);<a name="line.476"></a>
+<span class="sourceLineNo">477</span> usedSize -= targetBucket.getItemAllocationSize();<a name="line.477"></a>
+<span class="sourceLineNo">478</span> return targetBucket.getItemAllocationSize();<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> public int sizeIndexOfAllocation(long offset) {<a name="line.481"></a>
+<span class="sourceLineNo">482</span> int bucketNo = (int) (offset / bucketCapacity);<a name="line.482"></a>
+<span class="sourceLineNo">483</span> assert bucketNo >= 0 && bucketNo < buckets.length;<a name="line.483"></a>
+<span class="sourceLineNo">484</span> Bucket targetBucket = buckets[bucketNo];<a name="line.484"></a>
+<span class="sourceLineNo">485</span> return targetBucket.sizeIndex();<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> public int sizeOfAllocation(long offset) {<a name="line.488"></a>
+<span class="sourceLineNo">489</span> int bucketNo = (int) (offset / bucketCapacity);<a name="line.489"></a>
+<span class="sourceLineNo">490</span> assert bucketNo >= 0 && bucketNo < buckets.length;<a name="line.490"></a>
+<span class="sourceLineNo">491</span> Bucket targetBucket = buckets[bucketNo];<a name="line.491"></a>
+<span class="sourceLineNo">492</span> return targetBucket.getItemAllocationSize();<a name="line.492"></a>
+<span class="sourceLineNo">493</span> }<a name="line.493"></a>
+<span class="sourceLineNo">494</span><a name="line.494"></a>
+<span class="sourceLineNo">495</span> static class IndexStatistics {<a name="line.495"></a>
+<span class="sourceLineNo">496</span> private long freeCount, usedCount, itemSize, totalCount;<a name="line.496"></a>
+<span class="sourceLineNo">497</span><a name="line.497"></a>
+<span class="sourceLineNo">498</span> public long freeCount() {<a name="line.498"></a>
+<span class="sourceLineNo">499</span> return freeCount;<a name="line.499"></a>
+<span class="sourceLineNo">500</span> }<a name="line.500"></a>
+<span class="sourceLineNo">501</span><a name="line.501"></a>
+<span class="sourceLineNo">502</span> public long usedCount() {<a name="line.502"></a>
+<span class="sourceLineNo">503</span> return usedCount;<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> public long totalCount() {<a name="line.506"></a>
+<span class="sourceLineNo">507</span> return totalCount;<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> public long freeBytes() {<a name="line.510"></a>
+<span class="sourceLineNo">511</span> return freeCount * itemSize;<a name="line.511"></a>
+<span class="sourceLineNo">512</span> }<a name="line.512"></a>
+<span class="sourceLineNo">513</span><a name="line.513"></a>
+<span class="sourceLineNo">514</span> public long usedBytes() {<a name="line.514"></a>
+<span class="sourceLineNo">515</span> return usedCount * itemSize;<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> public long totalBytes() {<a name="line.518"></a>
+<span class="sourceLineNo">519</span> return totalCount * itemSize;<a name="line.519"></a>
+<span class="sourceLineNo">520</span> }<a name="line.520"></a>
+<span class="sourceLineNo">521</span><a name="line.521"></a>
+<span class="sourceLineNo">522</span> public long itemSize() {<a name="line.522"></a>
+<span class="sourceLineNo">523</span> return itemSize;<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> public IndexStatistics(long free, long used, long itemSize) {<a name="line.526"></a>
+<span class="sourceLineNo">527</span> setTo(free, used, itemSize);<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> public IndexStatistics() {<a name="line.530"></a>
+<span class="sourceLineNo">531</span> setTo(-1, -1, 0);<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> public void setTo(long free, long used, long itemSize) {<a name="line.534"></a>
+<span class="sourceLineNo">535</span> this.itemSize = itemSize;<a name="line.535"></a>
+<span class="sourceLineNo">536</span> this.freeCount = free;<a name="line.536"></a>
+<span class="sourceLineNo">537</span> this.usedCount = used;<a name="line.537"></a>
+<span class="sourceLineNo">538</span> this.totalCount = free + used;<a name="line.538"></a>
+<span class="sourceLineNo">539</span> }<a name="line.539"></a>
+<span class="sourceLineNo">540</span> }<a name="line.540"></a>
+<span class="sourceLineNo">541</span><a name="line.541"></a>
+<span class="sourceLineNo">542</span> public Bucket [] getBuckets() {<a name="line.542"></a>
+<span class="sourceLineNo">543</span> return this.buckets;<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> void logStatistics() {<a name="line.546"></a>
+<span class="sourceLineNo">547</span> IndexStatistics total = new IndexStatistics();<a name="line.547"></a>
+<span class="sourceLineNo">548</span> IndexStatistics[] stats = getIndexStatistics(total);<a name="line.548"></a>
+<span class="sourceLineNo">549</span> LOG.info("Bucket allocator statistics follow:\n");<a name="line.549"></a>
+<span class="sourceLineNo">550</span> LOG.info(" Free bytes=" + total.freeBytes() + "+; used bytes="<a name="line.550"></a>
+<span class="sourceLineNo">551</span> + total.usedBytes() + "; total bytes=" + total.totalBytes());<a name="line.551"></a>
+<span class="sourceLineNo">552</span> for (IndexStatistics s : stats) {<a name="line.552"></a>
+<span class="sourceLineNo">553</span> LOG.info(" Object size " + s.itemSize() + " used=" + s.usedCount()<a name="line.553"></a>
+<span class="sourceLineNo">554</span> + "; free=" + s.freeCount() + "; total=" + s.totalCount());<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><a name="line.557"></a>
+<span class="sourceLineNo">558</span> IndexStatistics[] getIndexStatistics(IndexStatistics grandTotal) {<a name="line.558"></a>
+<span class="sourceLineNo">559</span> IndexStatistics[] stats = getIndexStatistics();<a name="line.559"></a>
+<span class="sourceLineNo">560</span> long totalfree = 0, totalused = 0;<a name="line.560"></a>
+<span class="sourceLineNo">561</span> for (IndexStatistics stat : stats) {<a name="line.561"></a>
+<span class="sourceLineNo">562</span> totalfree += stat.freeBytes();<a name="line.562"></a>
+<span class="sourceLineNo">563</span> totalused += stat.usedBytes();<a name="line.563"></a>
+<span class="sourceLineNo">564</span> }<a name="line.564"></a>
+<span class="sourceLineNo">565</span> grandTotal.setTo(totalfree, totalused, 1);<a name="line.565"></a>
+<span class="sourceLineNo">566</span> return stats;<a name="line.566"></a>
+<span class="sourceLineNo">567</span> }<a name="line.567"></a>
+<span class="sourceLineNo">568</span><a name="line.568"></a>
+<span class="sourceLineNo">569</span> IndexStatistics[] getIndexStatistics() {<a name="line.569"></a>
+<span class="sourceLineNo">570</span> IndexStatistics[] stats = new IndexStatistics[bucketSizes.length];<a name="line.570"></a>
+<span class="sourceLineNo">571</span> for (int i = 0; i < stats.length; ++i)<a name="line.571"></a>
+<span class="sourceLineNo">572</span> stats[i] = bucketSizeInfos[i].statistics();<a name="line.572"></a>
+<span class="sourceLineNo">573</span> return stats;<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> public long freeBlock(long freeList[]) {<a name="line.576"></a>
+<span class="sourceLineNo">577</span> long sz = 0;<a name="line.577"></a>
+<span class="sourceLineNo">578</span> for (int i = 0; i < freeList.length; ++i)<a name="line.578"></a>
+<span class="sourceLineNo">579</span> sz += freeBlock(freeList[i]);<a name="line.579"></a>
+<span class="sourceLineNo">580</span> return sz;<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> public int getBucketIndex(long offset) {<a name="line.583"></a>
+<span class="sourceLineNo">584</span> return (int) (offset / bucketCapacity);<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> /**<a name="line.587"></a>
+<span class="sourceLineNo">588</span> * Returns a set of indices of the buckets that are least filled<a name="line.588"></a>
+<span class="sourceLineNo">589</span> * excluding the offsets, we also the fully free buckets for the<a name="line.589"></a>
+<span class="sourceLineNo">590</span> * BucketSizes where everything is empty and they only have one<a name="line.590"></a>
+<span class="sourceLineNo">591</span> * completely free bucket as a reserved<a name="line.591"></a>
+<span class="sourceLineNo">592</span> *<a name="line.592"></a>
+<span class="sourceLineNo">593</span> * @param excludedBuckets the buckets that need to be excluded due to<a name="line.593"></a>
+<span class="sourceLineNo">594</span> * currently being in used<a name="line.594"></a>
+<span class="sourceLineNo">595</span> * @param bucketCount max Number of buckets to return<a name="line.595"></a>
+<span class="sourceLineNo">596</span> * @return set of bucket indices which could be used for eviction<a name="line.596"></a>
+<span class="sourceLineNo">597</span> */<a name="line.597"></a>
+<span class="sourceLineNo">598</span> public Set<Integer> getLeastFilledBuckets(Set<Integer> excludedBuckets,<a name="line.598"></a>
+<span class="sourceLineNo">599</span> int bucketCount) {<a name="line.599"></a>
+<span class="sourceLineNo">600</span> Queue<Integer> queue = MinMaxPriorityQueue.<Integer>orderedBy(<a name="line.600"></a>
+<span class="sourceLineNo">601</span> new Comparator<Integer>() {<a name="line.601"></a>
+<span class="sourceLineNo">602</span> @Override<a name="line.602"></a>
+<span class="sourceLineNo">603</span> public int compare(Integer left, Integer right) {<a name="line.603"></a>
+<span class="sourceLineNo">604</span> // We will always get instantiated buckets<a name="line.604"></a>
+<span class="sourceLineNo">605</span> return Float.compare(<a name="line.605"></a>
+<span class="sourceLineNo">606</span> ((float) buckets[left].usedCount) / buckets[left].itemCount,<a name="line.606"></a>
+<span class="sourceLineNo">607</span> ((float) buckets[right].usedCount) / buckets[right].itemCount);<a name="line.607"></a>
+<span class="sourceLineNo">608</span> }<a name="line.608"></a>
+<span class="sourceLineNo">609</span> }).maximumSize(bucketCount).create();<a name="line.609"></a>
+<span class="sourceLineNo">610</span><a name="line.610"></a>
+<span class="sourceLineNo">611</span> for (int i = 0; i < buckets.length; i ++ ) {<a name="line.611"></a>
+<span class="sourceLineNo">612</span> if (!excludedBuckets.contains(i) && !buckets[i].isUninstantiated() &&<a name="line.612"></a>
+<span class="sourceLineNo">613</span> // Avoid the buckets that are the only buckets for a sizeIndex<a name="line.613"></a>
+<span class="sourceLineNo">614</span> bucketSizeInfos[buckets[i].sizeIndex()].bucketList.size() != 1) {<a name="line.614"></a>
+<span class="sourceLineNo">615</span> queue.add(i);<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><a name="line.618"></a>
+<span class="sourceLineNo">619</span> Set<Integer> result = new HashSet<>(bucketCount);<a name="line.619"></a>
+<span class="sourceLineNo">620</span> result.addAll(queue);<a name="line.620"></a>
+<span class="sourceLineNo">621</span><a name="line.621"></a>
+<span class="sourceLineNo">622</span> return result;<a name="line.622"></a>
+<span class="sourceLineNo">623</span> }<a name="line.623"></a>
+<span class="sourceLineNo">624</span>}<a name="line.624"></a>
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.IndexStatistics.html b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.IndexStatistics.html
index a3cd853..0a4475b 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.IndexStatistics.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.IndexStatistics.html
@@ -277,358 +277,359 @@
<span class="sourceLineNo">269</span><a name="line.269"></a>
<span class="sourceLineNo">270</span> // Default block size in hbase is 64K, so we choose more sizes near 64K, you'd better<a name="line.270"></a>
<span class="sourceLineNo">271</span> // reset it according to your cluster's block size distribution<a name="line.271"></a>
-<span class="sourceLineNo">272</span> // TODO Support the view of block size distribution statistics<a name="line.272"></a>
-<span class="sourceLineNo">273</span> // TODO: Why we add the extra 1024 bytes? Slop?<a name="line.273"></a>
-<span class="sourceLineNo">274</span> private static final int DEFAULT_BUCKET_SIZES[] = { 4 * 1024 + 1024, 8 * 1024 + 1024,<a name="line.274"></a>
-<span class="sourceLineNo">275</span> 16 * 1024 + 1024, 32 * 1024 + 1024, 40 * 1024 + 1024, 48 * 1024 + 1024,<a name="line.275"></a>
-<span class="sourceLineNo">276</span> 56 * 1024 + 1024, 64 * 1024 + 1024, 96 * 1024 + 1024, 128 * 1024 + 1024,<a name="line.276"></a>
-<span class="sourceLineNo">277</span> 192 * 1024 + 1024, 256 * 1024 + 1024, 384 * 1024 + 1024,<a name="line.277"></a>
-<span class="sourceLineNo">278</span> 512 * 1024 + 1024 };<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> * Round up the given block size to bucket size, and get the corresponding<a name="line.281"></a>
-<span class="sourceLineNo">282</span> * BucketSizeInfo<a name="line.282"></a>
-<span class="sourceLineNo">283</span> */<a name="line.283"></a>
-<span class="sourceLineNo">284</span> public BucketSizeInfo roundUpToBucketSizeInfo(int blockSize) {<a name="line.284"></a>
-<span class="sourceLineNo">285</span> for (int i = 0; i < bucketSizes.length; ++i)<a name="line.285"></a>
-<span class="sourceLineNo">286</span> if (blockSize <= bucketSizes[i])<a name="line.286"></a>
-<span class="sourceLineNo">287</span> return bucketSizeInfos[i];<a name="line.287"></a>
-<span class="sourceLineNo">288</span> return null;<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> /**<a name="line.291"></a>
-<span class="sourceLineNo">292</span> * So, what is the minimum amount of items we'll tolerate in a single bucket?<a name="line.292"></a>
-<span class="sourceLineNo">293</span> */<a name="line.293"></a>
-<span class="sourceLineNo">294</span> static public final int FEWEST_ITEMS_IN_BUCKET = 4;<a name="line.294"></a>
-<span class="sourceLineNo">295</span><a name="line.295"></a>
-<span class="sourceLineNo">296</span> private final int[] bucketSizes;<a name="line.296"></a>
-<span class="sourceLineNo">297</span> private final int bigItemSize;<a name="line.297"></a>
-<span class="sourceLineNo">298</span> // The capacity size for each bucket<a name="line.298"></a>
-<span class="sourceLineNo">299</span> private final long bucketCapacity;<a name="line.299"></a>
-<span class="sourceLineNo">300</span> private Bucket[] buckets;<a name="line.300"></a>
-<span class="sourceLineNo">301</span> private BucketSizeInfo[] bucketSizeInfos;<a name="line.301"></a>
-<span class="sourceLineNo">302</span> private final long totalSize;<a name="line.302"></a>
-<span class="sourceLineNo">303</span> private transient long usedSize = 0;<a name="line.303"></a>
-<span class="sourceLineNo">304</span><a name="line.304"></a>
-<span class="sourceLineNo">305</span> BucketAllocator(long availableSpace, int[] bucketSizes)<a name="line.305"></a>
-<span class="sourceLineNo">306</span> throws BucketAllocatorException {<a name="line.306"></a>
-<span class="sourceLineNo">307</span> this.bucketSizes = bucketSizes == null ? DEFAULT_BUCKET_SIZES : bucketSizes;<a name="line.307"></a>
-<span class="sourceLineNo">308</span> Arrays.sort(this.bucketSizes);<a name="line.308"></a>
-<span class="sourceLineNo">309</span> this.bigItemSize = Ints.max(this.bucketSizes);<a name="line.309"></a>
-<span class="sourceLineNo">310</span> this.bucketCapacity = FEWEST_ITEMS_IN_BUCKET * (long) bigItemSize;<a name="line.310"></a>
-<span class="sourceLineNo">311</span> buckets = new Bucket[(int) (availableSpace / bucketCapacity)];<a name="line.311"></a>
-<span class="sourceLineNo">312</span> if (buckets.length < this.bucketSizes.length)<a name="line.312"></a>
-<span class="sourceLineNo">313</span> throw new BucketAllocatorException("Bucket allocator size too small (" + buckets.length +<a name="line.313"></a>
-<span class="sourceLineNo">314</span> "); must have room for at least " + this.bucketSizes.length + " buckets");<a name="line.314"></a>
-<span class="sourceLineNo">315</span> bucketSizeInfos = new BucketSizeInfo[this.bucketSizes.length];<a name="line.315"></a>
-<span class="sourceLineNo">316</span> for (int i = 0; i < this.bucketSizes.length; ++i) {<a name="line.316"></a>
-<span class="sourceLineNo">317</span> bucketSizeInfos[i] = new BucketSizeInfo(i);<a name="line.317"></a>
-<span class="sourceLineNo">318</span> }<a name="line.318"></a>
-<span class="sourceLineNo">319</span> for (int i = 0; i < buckets.length; ++i) {<a name="line.319"></a>
-<span class="sourceLineNo">320</span> buckets[i] = new Bucket(bucketCapacity * i);<a name="line.320"></a>
-<span class="sourceLineNo">321</span> bucketSizeInfos[i < this.bucketSizes.length ? i : this.bucketSizes.length - 1]<a name="line.321"></a>
-<span class="sourceLineNo">322</span> .instantiateBucket(buckets[i]);<a name="line.322"></a>
-<span class="sourceLineNo">323</span> }<a name="line.323"></a>
-<span class="sourceLineNo">324</span> this.totalSize = ((long) buckets.length) * bucketCapacity;<a name="line.324"></a>
-<span class="sourceLineNo">325</span> if (LOG.isInfoEnabled()) {<a name="line.325"></a>
-<span class="sourceLineNo">326</span> LOG.info("Cache totalSize=" + this.totalSize + ", buckets=" + this.buckets.length +<a name="line.326"></a>
-<span class="sourceLineNo">327</span> ", bucket capacity=" + this.bucketCapacity +<a name="line.327"></a>
-<span class="sourceLineNo">328</span> "=(" + FEWEST_ITEMS_IN_BUCKET + "*" + this.bigItemSize + ")=" +<a name="line.328"></a>
-<span class="sourceLineNo">329</span> "(FEWEST_ITEMS_IN_BUCKET*(largest configured bucketcache size))");<a name="line.329"></a>
-<span class="sourceLineNo">330</span> }<a name="line.330"></a>
-<span class="sourceLineNo">331</span> }<a name="line.331"></a>
-<span class="sourceLineNo">332</span><a name="line.332"></a>
-<span class="sourceLineNo">333</span> /**<a name="line.333"></a>
-<span class="sourceLineNo">334</span> * Rebuild the allocator's data structures from a persisted map.<a name="line.334"></a>
-<span class="sourceLineNo">335</span> * @param availableSpace capacity of cache<a name="line.335"></a>
-<span class="sourceLineNo">336</span> * @param map A map stores the block key and BucketEntry(block's meta data<a name="line.336"></a>
-<span class="sourceLineNo">337</span> * like offset, length)<a name="line.337"></a>
-<span class="sourceLineNo">338</span> * @param realCacheSize cached data size statistics for bucket cache<a name="line.338"></a>
-<span class="sourceLineNo">339</span> * @throws BucketAllocatorException<a name="line.339"></a>
-<span class="sourceLineNo">340</span> */<a name="line.340"></a>
-<span class="sourceLineNo">341</span> BucketAllocator(long availableSpace, int[] bucketSizes, Map<BlockCacheKey, BucketEntry> map,<a name="line.341"></a>
-<span class="sourceLineNo">342</span> LongAdder realCacheSize) throws BucketAllocatorException {<a name="line.342"></a>
-<span class="sourceLineNo">343</span> this(availableSpace, bucketSizes);<a name="line.343"></a>
-<span class="sourceLineNo">344</span><a name="line.344"></a>
-<span class="sourceLineNo">345</span> // each bucket has an offset, sizeindex. probably the buckets are too big<a name="line.345"></a>
-<span class="sourceLineNo">346</span> // in our default state. so what we do is reconfigure them according to what<a name="line.346"></a>
-<span class="sourceLineNo">347</span> // we've found. we can only reconfigure each bucket once; if more than once,<a name="line.347"></a>
-<span class="sourceLineNo">348</span> // we know there's a bug, so we just log the info, throw, and start again...<a name="line.348"></a>
-<span class="sourceLineNo">349</span> boolean[] reconfigured = new boolean[buckets.length];<a name="line.349"></a>
-<span class="sourceLineNo">350</span> int sizeNotMatchedCount = 0;<a name="line.350"></a>
-<span class="sourceLineNo">351</span> int insufficientCapacityCount = 0;<a name="line.351"></a>
-<span class="sourceLineNo">352</span> Iterator<Map.Entry<BlockCacheKey, BucketEntry>> iterator = map.entrySet().iterator();<a name="line.352"></a>
-<span class="sourceLineNo">353</span> while (iterator.hasNext()) {<a name="line.353"></a>
-<span class="sourceLineNo">354</span> Map.Entry<BlockCacheKey, BucketEntry> entry = iterator.next();<a name="line.354"></a>
-<span class="sourceLineNo">355</span> long foundOffset = entry.getValue().offset();<a name="line.355"></a>
-<span class="sourceLineNo">356</span> int foundLen = entry.getValue().getLength();<a name="line.356"></a>
-<span class="sourceLineNo">357</span> int bucketSizeIndex = -1;<a name="line.357"></a>
-<span class="sourceLineNo">358</span> for (int i = 0; i < this.bucketSizes.length; ++i) {<a name="line.358"></a>
-<span class="sourceLineNo">359</span> if (foundLen <= this.bucketSizes[i]) {<a name="line.359"></a>
-<span class="sourceLineNo">360</span> bucketSizeIndex = i;<a name="line.360"></a>
-<span class="sourceLineNo">361</span> break;<a name="line.361"></a>
-<span class="sourceLineNo">362</span> }<a name="line.362"></a>
-<span class="sourceLineNo">363</span> }<a name="line.363"></a>
-<span class="sourceLineNo">364</span> if (bucketSizeIndex == -1) {<a name="line.364"></a>
-<span class="sourceLineNo">365</span> sizeNotMatchedCount++;<a name="line.365"></a>
-<span class="sourceLineNo">366</span> iterator.remove();<a name="line.366"></a>
-<span class="sourceLineNo">367</span> continue;<a name="line.367"></a>
-<span class="sourceLineNo">368</span> }<a name="line.368"></a>
-<span class="sourceLineNo">369</span> int bucketNo = (int) (foundOffset / bucketCapacity);<a name="line.369"></a>
-<span class="sourceLineNo">370</span> if (bucketNo < 0 || bucketNo >= buckets.length) {<a name="line.370"></a>
-<span class="sourceLineNo">371</span> insufficientCapacityCount++;<a name="line.371"></a>
-<span class="sourceLineNo">372</span> iterator.remove();<a name="line.372"></a>
-<span class="sourceLineNo">373</span> continue;<a name="line.373"></a>
-<span class="sourceLineNo">374</span> }<a name="line.374"></a>
-<span class="sourceLineNo">375</span> Bucket b = buckets[bucketNo];<a name="line.375"></a>
-<span class="sourceLineNo">376</span> if (reconfigured[bucketNo]) {<a name="line.376"></a>
-<span class="sourceLineNo">377</span> if (b.sizeIndex() != bucketSizeIndex) {<a name="line.377"></a>
-<span class="sourceLineNo">378</span> throw new BucketAllocatorException("Inconsistent allocation in bucket map;");<a name="line.378"></a>
-<span class="sourceLineNo">379</span> }<a name="line.379"></a>
-<span class="sourceLineNo">380</span> } else {<a name="line.380"></a>
-<span class="sourceLineNo">381</span> if (!b.isCompletelyFree()) {<a name="line.381"></a>
-<span class="sourceLineNo">382</span> throw new BucketAllocatorException(<a name="line.382"></a>
-<span class="sourceLineNo">383</span> "Reconfiguring bucket " + bucketNo + " but it's already allocated; corrupt data");<a name="line.383"></a>
-<span class="sourceLineNo">384</span> }<a name="line.384"></a>
-<span class="sourceLineNo">385</span> // Need to remove the bucket from whichever list it's currently in at<a name="line.385"></a>
-<span class="sourceLineNo">386</span> // the moment...<a name="line.386"></a>
-<span class="sourceLineNo">387</span> BucketSizeInfo bsi = bucketSizeInfos[bucketSizeIndex];<a name="line.387"></a>
-<span class="sourceLineNo">388</span> BucketSizeInfo oldbsi = bucketSizeInfos[b.sizeIndex()];<a name="line.388"></a>
-<span class="sourceLineNo">389</span> oldbsi.removeBucket(b);<a name="line.389"></a>
-<span class="sourceLineNo">390</span> bsi.instantiateBucket(b);<a name="line.390"></a>
-<span class="sourceLineNo">391</span> reconfigured[bucketNo] = true;<a name="line.391"></a>
-<span class="sourceLineNo">392</span> }<a name="line.392"></a>
-<span class="sourceLineNo">393</span> realCacheSize.add(foundLen);<a name="line.393"></a>
-<span class="sourceLineNo">394</span> buckets[bucketNo].addAllocation(foundOffset);<a name="line.394"></a>
-<span class="sourceLineNo">395</span> usedSize += buckets[bucketNo].getItemAllocationSize();<a name="line.395"></a>
-<span class="sourceLineNo">396</span> bucketSizeInfos[bucketSizeIndex].blockAllocated(b);<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> if (sizeNotMatchedCount > 0) {<a name="line.399"></a>
-<span class="sourceLineNo">400</span> LOG.warn("There are " + sizeNotMatchedCount + " blocks which can't be rebuilt because " +<a name="line.400"></a>
-<span class="sourceLineNo">401</span> "there is no matching bucket size for these blocks");<a name="line.401"></a>
-<span class="sourceLineNo">402</span> }<a name="line.402"></a>
-<span class="sourceLineNo">403</span> if (insufficientCapacityCount > 0) {<a name="line.403"></a>
-<span class="sourceLineNo">404</span> LOG.warn("There are " + insufficientCapacityCount + " blocks which can't be rebuilt - "<a name="line.404"></a>
-<span class="sourceLineNo">405</span> + "did you shrink the cache?");<a name="line.405"></a>
-<span class="sourceLineNo">406</span> }<a name="line.406"></a>
-<span class="sourceLineNo">407</span> }<a name="line.407"></a>
-<span class="sourceLineNo">408</span><a name="line.408"></a>
-<span class="sourceLineNo">409</span> @Override<a name="line.409"></a>
-<span class="sourceLineNo">410</span> public String toString() {<a name="line.410"></a>
-<span class="sourceLineNo">411</span> StringBuilder sb = new StringBuilder(1024);<a name="line.411"></a>
-<span class="sourceLineNo">412</span> for (int i = 0; i < buckets.length; ++i) {<a name="line.412"></a>
-<span class="sourceLineNo">413</span> Bucket b = buckets[i];<a name="line.413"></a>
-<span class="sourceLineNo">414</span> if (i > 0) sb.append(", ");<a name="line.414"></a>
-<span class="sourceLineNo">415</span> sb.append("bucket.").append(i).append(": size=").append(b.getItemAllocationSize());<a name="line.415"></a>
-<span class="sourceLineNo">416</span> sb.append(", freeCount=").append(b.freeCount()).append(", used=").append(b.usedCount());<a name="line.416"></a>
-<span class="sourceLineNo">417</span> }<a name="line.417"></a>
-<span class="sourceLineNo">418</span> return sb.toString();<a name="line.418"></a>
-<span class="sourceLineNo">419</span> }<a name="line.419"></a>
-<span class="sourceLineNo">420</span><a name="line.420"></a>
-<span class="sourceLineNo">421</span> public long getUsedSize() {<a name="line.421"></a>
-<span class="sourceLineNo">422</span> return this.usedSize;<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> public long getFreeSize() {<a name="line.425"></a>
-<span class="sourceLineNo">426</span> return this.totalSize - getUsedSize();<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> public long getTotalSize() {<a name="line.429"></a>
-<span class="sourceLineNo">430</span> return this.totalSize;<a name="line.430"></a>
-<span class="sourceLineNo">431</span> }<a name="line.431"></a>
-<span class="sourceLineNo">432</span><a name="line.432"></a>
-<span class="sourceLineNo">433</span> /**<a name="line.433"></a>
-<span class="sourceLineNo">434</span> * Allocate a block with specified size. Return the offset<a name="line.434"></a>
-<span class="sourceLineNo">435</span> * @param blockSize size of block<a name="line.435"></a>
-<span class="sourceLineNo">436</span> * @throws BucketAllocatorException<a name="line.436"></a>
-<span class="sourceLineNo">437</span> * @throws CacheFullException<a name="line.437"></a>
-<span class="sourceLineNo">438</span> * @return the offset in the IOEngine<a name="line.438"></a>
-<span class="sourceLineNo">439</span> */<a name="line.439"></a>
-<span class="sourceLineNo">440</span> public synchronized long allocateBlock(int blockSize) throws CacheFullException,<a name="line.440"></a>
-<span class="sourceLineNo">441</span> BucketAllocatorException {<a name="line.441"></a>
-<span class="sourceLineNo">442</span> assert blockSize > 0;<a name="line.442"></a>
-<span class="sourceLineNo">443</span> BucketSizeInfo bsi = roundUpToBucketSizeInfo(blockSize);<a name="line.443"></a>
-<span class="sourceLineNo">444</span> if (bsi == null) {<a name="line.444"></a>
-<span class="sourceLineNo">445</span> throw new BucketAllocatorException("Allocation too big size=" + blockSize +<a name="line.445"></a>
-<span class="sourceLineNo">446</span> "; adjust BucketCache sizes " + BlockCacheFactory.BUCKET_CACHE_BUCKETS_KEY +<a name="line.446"></a>
-<span class="sourceLineNo">447</span> " to accomodate if size seems reasonable and you want it cached.");<a name="line.447"></a>
-<span class="sourceLineNo">448</span> }<a name="line.448"></a>
-<span class="sourceLineNo">449</span> long offset = bsi.allocateBlock();<a name="line.449"></a>
-<span class="sourceLineNo">450</span><a name="line.450"></a>
-<span class="sourceLineNo">451</span> // Ask caller to free up space and try again!<a name="line.451"></a>
-<span class="sourceLineNo">452</span> if (offset < 0)<a name="line.452"></a>
-<span class="sourceLineNo">453</span> throw new CacheFullException(blockSize, bsi.sizeIndex());<a name="line.453"></a>
-<span class="sourceLineNo">454</span> usedSize += bucketSizes[bsi.sizeIndex()];<a name="line.454"></a>
-<span class="sourceLineNo">455</span> return offset;<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> private Bucket grabGlobalCompletelyFreeBucket() {<a name="line.458"></a>
-<span class="sourceLineNo">459</span> for (BucketSizeInfo bsi : bucketSizeInfos) {<a name="line.459"></a>
-<span class="sourceLineNo">460</span> Bucket b = bsi.findAndRemoveCompletelyFreeBucket();<a name="line.460"></a>
-<span class="sourceLineNo">461</span> if (b != null) return b;<a name="line.461"></a>
-<span class="sourceLineNo">462</span> }<a name="line.462"></a>
-<span class="sourceLineNo">463</span> return null;<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> * Free a block with the offset<a name="line.467"></a>
-<span class="sourceLineNo">468</span> * @param offset block's offset<a name="line.468"></a>
-<span class="sourceLineNo">469</span> * @return size freed<a name="line.469"></a>
-<span class="sourceLineNo">470</span> */<a name="line.470"></a>
-<span class="sourceLineNo">471</span> public synchronized int freeBlock(long offset) {<a name="line.471"></a>
-<span class="sourceLineNo">472</span> int bucketNo = (int) (offset / bucketCapacity);<a name="line.472"></a>
-<span class="sourceLineNo">473</span> assert bucketNo >= 0 && bucketNo < buckets.length;<a name="line.473"></a>
-<span class="sourceLineNo">474</span> Bucket targetBucket = buckets[bucketNo];<a name="line.474"></a>
-<span class="sourceLineNo">475</span> bucketSizeInfos[targetBucket.sizeIndex()].freeBlock(targetBucket, offset);<a name="line.475"></a>
-<span class="sourceLineNo">476</span> usedSize -= targetBucket.getItemAllocationSize();<a name="line.476"></a>
-<span class="sourceLineNo">477</span> return targetBucket.getItemAllocationSize();<a name="line.477"></a>
-<span class="sourceLineNo">478</span> }<a name="line.478"></a>
-<span class="sourceLineNo">479</span><a name="line.479"></a>
-<span class="sourceLineNo">480</span> public int sizeIndexOfAllocation(long offset) {<a name="line.480"></a>
-<span class="sourceLineNo">481</span> int bucketNo = (int) (offset / bucketCapacity);<a name="line.481"></a>
-<span class="sourceLineNo">482</span> assert bucketNo >= 0 && bucketNo < buckets.length;<a name="line.482"></a>
-<span class="sourceLineNo">483</span> Bucket targetBucket = buckets[bucketNo];<a name="line.483"></a>
-<span class="sourceLineNo">484</span> return targetBucket.sizeIndex();<a name="line.484"></a>
-<span class="sourceLineNo">485</span> }<a name="line.485"></a>
-<span class="sourceLineNo">486</span><a name="line.486"></a>
-<span class="sourceLineNo">487</span> public int sizeOfAllocation(long offset) {<a name="line.487"></a>
-<span class="sourceLineNo">488</span> int bucketNo = (int) (offset / bucketCapacity);<a name="line.488"></a>
-<span class="sourceLineNo">489</span> assert bucketNo >= 0 && bucketNo < buckets.length;<a name="line.489"></a>
-<span class="sourceLineNo">490</span> Bucket targetBucket = buckets[bucketNo];<a name="line.490"></a>
-<span class="sourceLineNo">491</span> return targetBucket.getItemAllocationSize();<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> static class IndexStatistics {<a name="line.494"></a>
-<span class="sourceLineNo">495</span> private long freeCount, usedCount, itemSize, totalCount;<a name="line.495"></a>
-<span class="sourceLineNo">496</span><a name="line.496"></a>
-<span class="sourceLineNo">497</span> public long freeCount() {<a name="line.497"></a>
-<span class="sourceLineNo">498</span> return freeCount;<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> public long usedCount() {<a name="line.501"></a>
-<span class="sourceLineNo">502</span> return usedCount;<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> public long totalCount() {<a name="line.505"></a>
-<span class="sourceLineNo">506</span> return totalCount;<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> public long freeBytes() {<a name="line.509"></a>
-<span class="sourceLineNo">510</span> return freeCount * itemSize;<a name="line.510"></a>
-<span class="sourceLineNo">511</span> }<a name="line.511"></a>
-<span class="sourceLineNo">512</span><a name="line.512"></a>
-<span class="sourceLineNo">513</span> public long usedBytes() {<a name="line.513"></a>
-<span class="sourceLineNo">514</span> return usedCount * itemSize;<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> public long totalBytes() {<a name="line.517"></a>
-<span class="sourceLineNo">518</span> return totalCount * itemSize;<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> public long itemSize() {<a name="line.521"></a>
-<span class="sourceLineNo">522</span> return itemSize;<a name="line.522"></a>
-<span class="sourceLineNo">523</span> }<a name="line.523"></a>
-<span class="sourceLineNo">524</span><a name="line.524"></a>
-<span class="sourceLineNo">525</span> public IndexStatistics(long free, long used, long itemSize) {<a name="line.525"></a>
-<span class="sourceLineNo">526</span> setTo(free, used, itemSize);<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> public IndexStatistics() {<a name="line.529"></a>
-<span class="sourceLineNo">530</span> setTo(-1, -1, 0);<a name="line.530"></a>
-<span class="sourceLineNo">531</span> }<a name="line.531"></a>
-<span class="sourceLineNo">532</span><a name="line.532"></a>
-<span class="sourceLineNo">533</span> public void setTo(long free, long used, long itemSize) {<a name="line.533"></a>
-<span class="sourceLineNo">534</span> this.itemSize = itemSize;<a name="line.534"></a>
-<span class="sourceLineNo">535</span> this.freeCount = free;<a name="line.535"></a>
-<span class="sourceLineNo">536</span> this.usedCount = used;<a name="line.536"></a>
-<span class="sourceLineNo">537</span> this.totalCount = free + used;<a name="line.537"></a>
-<span class="sourceLineNo">538</span> }<a name="line.538"></a>
-<span class="sourceLineNo">539</span> }<a name="line.539"></a>
-<span class="sourceLineNo">540</span><a name="line.540"></a>
-<span class="sourceLineNo">541</span> public Bucket [] getBuckets() {<a name="line.541"></a>
-<span class="sourceLineNo">542</span> return this.buckets;<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> void logStatistics() {<a name="line.545"></a>
-<span class="sourceLineNo">546</span> IndexStatistics total = new IndexStatistics();<a name="line.546"></a>
-<span class="sourceLineNo">547</span> IndexStatistics[] stats = getIndexStatistics(total);<a name="line.547"></a>
-<span class="sourceLineNo">548</span> LOG.info("Bucket allocator statistics follow:\n");<a name="line.548"></a>
-<span class="sourceLineNo">549</span> LOG.info(" Free bytes=" + total.freeBytes() + "+; used bytes="<a name="line.549"></a>
-<span class="sourceLineNo">550</span> + total.usedBytes() + "; total bytes=" + total.totalBytes());<a name="line.550"></a>
-<span class="sourceLineNo">551</span> for (IndexStatistics s : stats) {<a name="line.551"></a>
-<span class="sourceLineNo">552</span> LOG.info(" Object size " + s.itemSize() + " used=" + s.usedCount()<a name="line.552"></a>
-<span class="sourceLineNo">553</span> + "; free=" + s.freeCount() + "; total=" + s.totalCount());<a name="line.553"></a>
-<span class="sourceLineNo">554</span> }<a name="line.554"></a>
-<span class="sourceLineNo">555</span> }<a name="line.555"></a>
-<span class="sourceLineNo">556</span><a name="line.556"></a>
-<span class="sourceLineNo">557</span> IndexStatistics[] getIndexStatistics(IndexStatistics grandTotal) {<a name="line.557"></a>
-<span class="sourceLineNo">558</span> IndexStatistics[] stats = getIndexStatistics();<a name="line.558"></a>
-<span class="sourceLineNo">559</span> long totalfree = 0, totalused = 0;<a name="line.559"></a>
-<span class="sourceLineNo">560</span> for (IndexStatistics stat : stats) {<a name="line.560"></a>
-<span class="sourceLineNo">561</span> totalfree += stat.freeBytes();<a name="line.561"></a>
-<span class="sourceLineNo">562</span> totalused += stat.usedBytes();<a name="line.562"></a>
-<span class="sourceLineNo">563</span> }<a name="line.563"></a>
-<span class="sourceLineNo">564</span> grandTotal.setTo(totalfree, totalused, 1);<a name="line.564"></a>
-<span class="sourceLineNo">565</span> return stats;<a name="line.565"></a>
-<span class="sourceLineNo">566</span> }<a name="line.566"></a>
-<span class="sourceLineNo">567</span><a name="line.567"></a>
-<span class="sourceLineNo">568</span> IndexStatistics[] getIndexStatistics() {<a name="line.568"></a>
-<span class="sourceLineNo">569</span> IndexStatistics[] stats = new IndexStatistics[bucketSizes.length];<a name="line.569"></a>
-<span class="sourceLineNo">570</span> for (int i = 0; i < stats.length; ++i)<a name="line.570"></a>
-<span class="sourceLineNo">571</span> stats[i] = bucketSizeInfos[i].statistics();<a name="line.571"></a>
-<span class="sourceLineNo">572</span> return stats;<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> public long freeBlock(long freeList[]) {<a name="line.575"></a>
-<span class="sourceLineNo">576</span> long sz = 0;<a name="line.576"></a>
-<span class="sourceLineNo">577</span> for (int i = 0; i < freeList.length; ++i)<a name="line.577"></a>
-<span class="sourceLineNo">578</span> sz += freeBlock(freeList[i]);<a name="line.578"></a>
-<span class="sourceLineNo">579</span> return sz;<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> public int getBucketIndex(long offset) {<a name="line.582"></a>
-<span class="sourceLineNo">583</span> return (int) (offset / bucketCapacity);<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> * Returns a set of indices of the buckets that are least filled<a name="line.587"></a>
-<span class="sourceLineNo">588</span> * excluding the offsets, we also the fully free buckets for the<a name="line.588"></a>
-<span class="sourceLineNo">589</span> * BucketSizes where everything is empty and they only have one<a name="line.589"></a>
-<span class="sourceLineNo">590</span> * completely free bucket as a reserved<a name="line.590"></a>
-<span class="sourceLineNo">591</span> *<a name="line.591"></a>
-<span class="sourceLineNo">592</span> * @param excludedBuckets the buckets that need to be excluded due to<a name="line.592"></a>
-<span class="sourceLineNo">593</span> * currently being in used<a name="line.593"></a>
-<span class="sourceLineNo">594</span> * @param bucketCount max Number of buckets to return<a name="line.594"></a>
-<span class="sourceLineNo">595</span> * @return set of bucket indices which could be used for eviction<a name="line.595"></a>
-<span class="sourceLineNo">596</span> */<a name="line.596"></a>
-<span class="sourceLineNo">597</span> public Set<Integer> getLeastFilledBuckets(Set<Integer> excludedBuckets,<a name="line.597"></a>
-<span class="sourceLineNo">598</span> int bucketCount) {<a name="line.598"></a>
-<span class="sourceLineNo">599</span> Queue<Integer> queue = MinMaxPriorityQueue.<Integer>orderedBy(<a name="line.599"></a>
-<span class="sourceLineNo">600</span> new Comparator<Integer>() {<a name="line.600"></a>
-<span class="sourceLineNo">601</span> @Override<a name="line.601"></a>
-<span class="sourceLineNo">602</span> public int compare(Integer left, Integer right) {<a name="line.602"></a>
-<span class="sourceLineNo">603</span> // We will always get instantiated buckets<a name="line.603"></a>
-<span class="sourceLineNo">604</span> return Float.compare(<a name="line.604"></a>
-<span class="sourceLineNo">605</span> ((float) buckets[left].usedCount) / buckets[left].itemCount,<a name="line.605"></a>
-<span class="sourceLineNo">606</span> ((float) buckets[right].usedCount) / buckets[right].itemCount);<a name="line.606"></a>
-<span class="sourceLineNo">607</span> }<a name="line.607"></a>
-<span class="sourceLineNo">608</span> }).maximumSize(bucketCount).create();<a name="line.608"></a>
-<span class="sourceLineNo">609</span><a name="line.609"></a>
-<span class="sourceLineNo">610</span> for (int i = 0; i < buckets.length; i ++ ) {<a name="line.610"></a>
-<span class="sourceLineNo">611</span> if (!excludedBuckets.contains(i) && !buckets[i].isUninstantiated() &&<a name="line.611"></a>
-<span class="sourceLineNo">612</span> // Avoid the buckets that are the only buckets for a sizeIndex<a name="line.612"></a>
-<span class="sourceLineNo">613</span> bucketSizeInfos[buckets[i].sizeIndex()].bucketList.size() != 1) {<a name="line.613"></a>
-<span class="sourceLineNo">614</span> queue.add(i);<a name="line.614"></a>
-<span class="sourceLineNo">615</span> }<a name="line.615"></a>
-<span class="sourceLineNo">616</span> }<a name="line.616"></a>
-<span class="sourceLineNo">617</span><a name="line.617"></a>
-<span class="sourceLineNo">618</span> Set<Integer> result = new HashSet<>(bucketCount);<a name="line.618"></a>
-<span class="sourceLineNo">619</span> result.addAll(queue);<a name="line.619"></a>
-<span class="sourceLineNo">620</span><a name="line.620"></a>
-<span class="sourceLineNo">621</span> return result;<a name="line.621"></a>
-<span class="sourceLineNo">622</span> }<a name="line.622"></a>
-<span class="sourceLineNo">623</span>}<a name="line.623"></a>
+<span class="sourceLineNo">272</span> // The real block size in hfile maybe a little larger than the size we configured ,<a name="line.272"></a>
+<span class="sourceLineNo">273</span> // so we need add extra 1024 bytes for fit.<a name="line.273"></a>
+<span class="sourceLineNo">274</span> // TODO Support the view of block size distribution statistics<a name="line.274"></a>
+<span class="sourceLineNo">275</span> private static final int DEFAULT_BUCKET_SIZES[] = { 4 * 1024 + 1024, 8 * 1024 + 1024,<a name="line.275"></a>
+<span class="sourceLineNo">276</span> 16 * 1024 + 1024, 32 * 1024 + 1024, 40 * 1024 + 1024, 48 * 1024 + 1024,<a name="line.276"></a>
+<span class="sourceLineNo">277</span> 56 * 1024 + 1024, 64 * 1024 + 1024, 96 * 1024 + 1024, 128 * 1024 + 1024,<a name="line.277"></a>
+<span class="sourceLineNo">278</span> 192 * 1024 + 1024, 256 * 1024 + 1024, 384 * 1024 + 1024,<a name="line.278"></a>
+<span class="sourceLineNo">279</span> 512 * 1024 + 1024 };<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> * Round up the given block size to bucket size, and get the corresponding<a name="line.282"></a>
+<span class="sourceLineNo">283</span> * BucketSizeInfo<a name="line.283"></a>
+<span class="sourceLineNo">284</span> */<a name="line.284"></a>
+<span class="sourceLineNo">285</span> public BucketSizeInfo roundUpToBucketSizeInfo(int blockSize) {<a name="line.285"></a>
+<span class="sourceLineNo">286</span> for (int i = 0; i < bucketSizes.length; ++i)<a name="line.286"></a>
+<span class="sourceLineNo">287</span> if (blockSize <= bucketSizes[i])<a name="line.287"></a>
+<span class="sourceLineNo">288</span> return bucketSizeInfos[i];<a name="line.288"></a>
+<span class="sourceLineNo">289</span> return null;<a name="line.289"></a>
+<span class="sourceLineNo">290</span> }<a name="line.290"></a>
+<span class="sourceLineNo">291</span><a name="line.291"></a>
+<span class="sourceLineNo">292</span> /**<a name="line.292"></a>
+<span class="sourceLineNo">293</span> * So, what is the minimum amount of items we'll tolerate in a single bucket?<a name="line.293"></a>
+<span class="sourceLineNo">294</span> */<a name="line.294"></a>
+<span class="sourceLineNo">295</span> static public final int FEWEST_ITEMS_IN_BUCKET = 4;<a name="line.295"></a>
+<span class="sourceLineNo">296</span><a name="line.296"></a>
+<span class="sourceLineNo">297</span> private final int[] bucketSizes;<a name="line.297"></a>
+<span class="sourceLineNo">298</span> private final int bigItemSize;<a name="line.298"></a>
+<span class="sourceLineNo">299</span> // The capacity size for each bucket<a name="line.299"></a>
+<span class="sourceLineNo">300</span> private final long bucketCapacity;<a name="line.300"></a>
+<span class="sourceLineNo">301</span> private Bucket[] buckets;<a name="line.301"></a>
+<span class="sourceLineNo">302</span> private BucketSizeInfo[] bucketSizeInfos;<a name="line.302"></a>
+<span class="sourceLineNo">303</span> private final long totalSize;<a name="line.303"></a>
+<span class="sourceLineNo">304</span> private transient long usedSize = 0;<a name="line.304"></a>
+<span class="sourceLineNo">305</span><a name="line.305"></a>
+<span class="sourceLineNo">306</span> BucketAllocator(long availableSpace, int[] bucketSizes)<a name="line.306"></a>
+<span class="sourceLineNo">307</span> throws BucketAllocatorException {<a name="line.307"></a>
+<span class="sourceLineNo">308</span> this.bucketSizes = bucketSizes == null ? DEFAULT_BUCKET_SIZES : bucketSizes;<a name="line.308"></a>
+<span class="sourceLineNo">309</span> Arrays.sort(this.bucketSizes);<a name="line.309"></a>
+<span class="sourceLineNo">310</span> this.bigItemSize = Ints.max(this.bucketSizes);<a name="line.310"></a>
+<span class="sourceLineNo">311</span> this.bucketCapacity = FEWEST_ITEMS_IN_BUCKET * (long) bigItemSize;<a name="line.311"></a>
+<span class="sourceLineNo">312</span> buckets = new Bucket[(int) (availableSpace / bucketCapacity)];<a name="line.312"></a>
+<span class="sourceLineNo">313</span> if (buckets.length < this.bucketSizes.length)<a name="line.313"></a>
+<span class="sourceLineNo">314</span> throw new BucketAllocatorException("Bucket allocator size too small (" + buckets.length +<a name="line.314"></a>
+<span class="sourceLineNo">315</span> "); must have room for at least " + this.bucketSizes.length + " buckets");<a name="line.315"></a>
+<span class="sourceLineNo">316</span> bucketSizeInfos = new BucketSizeInfo[this.bucketSizes.length];<a name="line.316"></a>
+<span class="sourceLineNo">317</span> for (int i = 0; i < this.bucketSizes.length; ++i) {<a name="line.317"></a>
+<span class="sourceLineNo">318</span> bucketSizeInfos[i] = new BucketSizeInfo(i);<a name="line.318"></a>
+<span class="sourceLineNo">319</span> }<a name="line.319"></a>
+<span class="sourceLineNo">320</span> for (int i = 0; i < buckets.length; ++i) {<a name="line.320"></a>
+<span class="sourceLineNo">321</span> buckets[i] = new Bucket(bucketCapacity * i);<a name="line.321"></a>
+<span class="sourceLineNo">322</span> bucketSizeInfos[i < this.bucketSizes.length ? i : this.bucketSizes.length - 1]<a name="line.322"></a>
+<span class="sourceLineNo">323</span> .instantiateBucket(buckets[i]);<a name="line.323"></a>
+<span class="sourceLineNo">324</span> }<a name="line.324"></a>
+<span class="sourceLineNo">325</span> this.totalSize = ((long) buckets.length) * bucketCapacity;<a name="line.325"></a>
+<span class="sourceLineNo">326</span> if (LOG.isInfoEnabled()) {<a name="line.326"></a>
+<span class="sourceLineNo">327</span> LOG.info("Cache totalSize=" + this.totalSize + ", buckets=" + this.buckets.length +<a name="line.327"></a>
+<span class="sourceLineNo">328</span> ", bucket capacity=" + this.bucketCapacity +<a name="line.328"></a>
+<span class="sourceLineNo">329</span> "=(" + FEWEST_ITEMS_IN_BUCKET + "*" + this.bigItemSize + ")=" +<a name="line.329"></a>
+<span class="sourceLineNo">330</span> "(FEWEST_ITEMS_IN_BUCKET*(largest configured bucketcache size))");<a name="line.330"></a>
+<span class="sourceLineNo">331</span> }<a name="line.331"></a>
+<span class="sourceLineNo">332</span> }<a name="line.332"></a>
+<span class="sourceLineNo">333</span><a name="line.333"></a>
+<span class="sourceLineNo">334</span> /**<a name="line.334"></a>
+<span class="sourceLineNo">335</span> * Rebuild the allocator's data structures from a persisted map.<a name="line.335"></a>
+<span class="sourceLineNo">336</span> * @param availableSpace capacity of cache<a name="line.336"></a>
+<span class="sourceLineNo">337</span> * @param map A map stores the block key and BucketEntry(block's meta data<a name="line.337"></a>
+<span class="sourceLineNo">338</span> * like offset, length)<a name="line.338"></a>
+<span class="sourceLineNo">339</span> * @param realCacheSize cached data size statistics for bucket cache<a name="line.339"></a>
+<span class="sourceLineNo">340</span> * @throws BucketAllocatorException<a name="line.340"></a>
+<span class="sourceLineNo">341</span> */<a name="line.341"></a>
+<span class="sourceLineNo">342</span> BucketAllocator(long availableSpace, int[] bucketSizes, Map<BlockCacheKey, BucketEntry> map,<a name="line.342"></a>
+<span class="sourceLineNo">343</span> LongAdder realCacheSize) throws BucketAllocatorException {<a name="line.343"></a>
+<span class="sourceLineNo">344</span> this(availableSpace, bucketSizes);<a name="line.344"></a>
+<span class="sourceLineNo">345</span><a name="line.345"></a>
+<span class="sourceLineNo">346</span> // each bucket has an offset, sizeindex. probably the buckets are too big<a name="line.346"></a>
+<span class="sourceLineNo">347</span> // in our default state. so what we do is reconfigure them according to what<a name="line.347"></a>
+<span class="sourceLineNo">348</span> // we've found. we can only reconfigure each bucket once; if more than once,<a name="line.348"></a>
+<span class="sourceLineNo">349</span> // we know there's a bug, so we just log the info, throw, and start again...<a name="line.349"></a>
+<span class="sourceLineNo">350</span> boolean[] reconfigured = new boolean[buckets.length];<a name="line.350"></a>
+<span class="sourceLineNo">351</span> int sizeNotMatchedCount = 0;<a name="line.351"></a>
+<span class="sourceLineNo">352</span> int insufficientCapacityCount = 0;<a name="line.352"></a>
+<span class="sourceLineNo">353</span> Iterator<Map.Entry<BlockCacheKey, BucketEntry>> iterator = map.entrySet().iterator();<a name="line.353"></a>
+<span class="sourceLineNo">354</span> while (iterator.hasNext()) {<a name="line.354"></a>
+<span class="sourceLineNo">355</span> Map.Entry<BlockCacheKey, BucketEntry> entry = iterator.next();<a name="line.355"></a>
+<span class="sourceLineNo">356</span> long foundOffset = entry.getValue().offset();<a name="line.356"></a>
+<span class="sourceLineNo">357</span> int foundLen = entry.getValue().getLength();<a name="line.357"></a>
+<span class="sourceLineNo">358</span> int bucketSizeIndex = -1;<a name="line.358"></a>
+<span class="sourceLineNo">359</span> for (int i = 0; i < this.bucketSizes.length; ++i) {<a name="line.359"></a>
+<span class="sourceLineNo">360</span> if (foundLen <= this.bucketSizes[i]) {<a name="line.360"></a>
+<span class="sourceLineNo">361</span> bucketSizeIndex = i;<a name="line.361"></a>
+<span class="sourceLineNo">362</span> break;<a name="line.362"></a>
+<span class="sourceLineNo">363</span> }<a name="line.363"></a>
+<span class="sourceLineNo">364</span> }<a name="line.364"></a>
+<span class="sourceLineNo">365</span> if (bucketSizeIndex == -1) {<a name="line.365"></a>
+<span class="sourceLineNo">366</span> sizeNotMatchedCount++;<a name="line.366"></a>
+<span class="sourceLineNo">367</span> iterator.remove();<a name="line.367"></a>
+<span class="sourceLineNo">368</span> continue;<a name="line.368"></a>
+<span class="sourceLineNo">369</span> }<a name="line.369"></a>
+<span class="sourceLineNo">370</span> int bucketNo = (int) (foundOffset / bucketCapacity);<a name="line.370"></a>
+<span class="sourceLineNo">371</span> if (bucketNo < 0 || bucketNo >= buckets.length) {<a name="line.371"></a>
+<span class="sourceLineNo">372</span> insufficientCapacityCount++;<a name="line.372"></a>
+<span class="sourceLineNo">373</span> iterator.remove();<a name="line.373"></a>
+<span class="sourceLineNo">374</span> continue;<a name="line.374"></a>
+<span class="sourceLineNo">375</span> }<a name="line.375"></a>
+<span class="sourceLineNo">376</span> Bucket b = buckets[bucketNo];<a name="line.376"></a>
+<span class="sourceLineNo">377</span> if (reconfigured[bucketNo]) {<a name="line.377"></a>
+<span class="sourceLineNo">378</span> if (b.sizeIndex() != bucketSizeIndex) {<a name="line.378"></a>
+<span class="sourceLineNo">379</span> throw new BucketAllocatorException("Inconsistent allocation in bucket map;");<a name="line.379"></a>
+<span class="sourceLineNo">380</span> }<a name="line.380"></a>
+<span class="sourceLineNo">381</span> } else {<a name="line.381"></a>
+<span class="sourceLineNo">382</span> if (!b.isCompletelyFree()) {<a name="line.382"></a>
+<span class="sourceLineNo">383</span> throw new BucketAllocatorException(<a name="line.383"></a>
+<span class="sourceLineNo">384</span> "Reconfiguring bucket " + bucketNo + " but it's already allocated; corrupt data");<a name="line.384"></a>
+<span class="sourceLineNo">385</span> }<a name="line.385"></a>
+<span class="sourceLineNo">386</span> // Need to remove the bucket from whichever list it's currently in at<a name="line.386"></a>
+<span class="sourceLineNo">387</span> // the moment...<a name="line.387"></a>
+<span class="sourceLineNo">388</span> BucketSizeInfo bsi = bucketSizeInfos[bucketSizeIndex];<a name="line.388"></a>
+<span class="sourceLineNo">389</span> BucketSizeInfo oldbsi = bucketSizeInfos[b.sizeIndex()];<a name="line.389"></a>
+<span class="sourceLineNo">390</span> oldbsi.removeBucket(b);<a name="line.390"></a>
+<span class="sourceLineNo">391</span> bsi.instantiateBucket(b);<a name="line.391"></a>
+<span class="sourceLineNo">392</span> reconfigured[bucketNo] = true;<a name="line.392"></a>
+<span class="sourceLineNo">393</span> }<a name="line.393"></a>
+<span class="sourceLineNo">394</span> realCacheSize.add(foundLen);<a name="line.394"></a>
+<span class="sourceLineNo">395</span> buckets[bucketNo].addAllocation(foundOffset);<a name="line.395"></a>
+<span class="sourceLineNo">396</span> usedSize += buckets[bucketNo].getItemAllocationSize();<a name="line.396"></a>
+<span class="sourceLineNo">397</span> bucketSizeInfos[bucketSizeIndex].blockAllocated(b);<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> if (sizeNotMatchedCount > 0) {<a name="line.400"></a>
+<span class="sourceLineNo">401</span> LOG.warn("There are " + sizeNotMatchedCount + " blocks which can't be rebuilt because " +<a name="line.401"></a>
+<span class="sourceLineNo">402</span> "there is no matching bucket size for these blocks");<a name="line.402"></a>
+<span class="sourceLineNo">403</span> }<a name="line.403"></a>
+<span class="sourceLineNo">404</span> if (insufficientCapacityCount > 0) {<a name="line.404"></a>
+<span class="sourceLineNo">405</span> LOG.warn("There are " + insufficientCapacityCount + " blocks which can't be rebuilt - "<a name="line.405"></a>
+<span class="sourceLineNo">406</span> + "did you shrink the cache?");<a name="line.406"></a>
+<span class="sourceLineNo">407</span> }<a name="line.407"></a>
+<span class="sourceLineNo">408</span> }<a name="line.408"></a>
+<span class="sourceLineNo">409</span><a name="line.409"></a>
+<span class="sourceLineNo">410</span> @Override<a name="line.410"></a>
+<span class="sourceLineNo">411</span> public String toString() {<a name="line.411"></a>
+<span class="sourceLineNo">412</span> StringBuilder sb = new StringBuilder(1024);<a name="line.412"></a>
+<span class="sourceLineNo">413</span> for (int i = 0; i < buckets.length; ++i) {<a name="line.413"></a>
+<span class="sourceLineNo">414</span> Bucket b = buckets[i];<a name="line.414"></a>
+<span class="sourceLineNo">415</span> if (i > 0) sb.append(", ");<a name="line.415"></a>
+<span class="sourceLineNo">416</span> sb.append("bucket.").append(i).append(": size=").append(b.getItemAllocationSize());<a name="line.416"></a>
+<span class="sourceLineNo">417</span> sb.append(", freeCount=").append(b.freeCount()).append(", used=").append(b.usedCount());<a name="line.417"></a>
+<span class="sourceLineNo">418</span> }<a name="line.418"></a>
+<span class="sourceLineNo">419</span> return sb.toString();<a name="line.419"></a>
+<span class="sourceLineNo">420</span> }<a name="line.420"></a>
+<span class="sourceLineNo">421</span><a name="line.421"></a>
+<span class="sourceLineNo">422</span> public long getUsedSize() {<a name="line.422"></a>
+<span class="sourceLineNo">423</span> return this.usedSize;<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> public long getFreeSize() {<a name="line.426"></a>
+<span class="sourceLineNo">427</span> return this.totalSize - getUsedSize();<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> public long getTotalSize() {<a name="line.430"></a>
+<span class="sourceLineNo">431</span> return this.totalSize;<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> * Allocate a block with specified size. Return the offset<a name="line.435"></a>
+<span class="sourceLineNo">436</span> * @param blockSize size of block<a name="line.436"></a>
+<span class="sourceLineNo">437</span> * @throws BucketAllocatorException<a name="line.437"></a>
+<span class="sourceLineNo">438</span> * @throws CacheFullException<a name="line.438"></a>
+<span class="sourceLineNo">439</span> * @return the offset in the IOEngine<a name="line.439"></a>
+<span class="sourceLineNo">440</span> */<a name="line.440"></a>
+<span class="sourceLineNo">441</span> public synchronized long allocateBlock(int blockSize) throws CacheFullException,<a name="line.441"></a>
+<span class="sourceLineNo">442</span> BucketAllocatorException {<a name="line.442"></a>
+<span class="sourceLineNo">443</span> assert blockSize > 0;<a name="line.443"></a>
+<span class="sourceLineNo">444</span> BucketSizeInfo bsi = roundUpToBucketSizeInfo(blockSize);<a name="line.444"></a>
+<span class="sourceLineNo">445</span> if (bsi == null) {<a name="line.445"></a>
+<span class="sourceLineNo">446</span> throw new BucketAllocatorException("Allocation too big size=" + blockSize +<a name="line.446"></a>
+<span class="sourceLineNo">447</span> "; adjust BucketCache sizes " + BlockCacheFactory.BUCKET_CACHE_BUCKETS_KEY +<a name="line.447"></a>
+<span class="sourceLineNo">448</span> " to accomodate if size seems reasonable and you want it cached.");<a name="line.448"></a>
+<span class="sourceLineNo">449</span> }<a name="line.449"></a>
+<span class="sourceLineNo">450</span> long offset = bsi.allocateBlock();<a name="line.450"></a>
+<span class="sourceLineNo">451</span><a name="line.451"></a>
+<span class="sourceLineNo">452</span> // Ask caller to free up space and try again!<a name="line.452"></a>
+<span class="sourceLineNo">453</span> if (offset < 0)<a name="line.453"></a>
+<span class="sourceLineNo">454</span> throw new CacheFullException(blockSize, bsi.sizeIndex());<a name="line.454"></a>
+<span class="sourceLineNo">455</span> usedSize += bucketSizes[bsi.sizeIndex()];<a name="line.455"></a>
+<span class="sourceLineNo">456</span> return offset;<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> private Bucket grabGlobalCompletelyFreeBucket() {<a name="line.459"></a>
+<span class="sourceLineNo">460</span> for (BucketSizeInfo bsi : bucketSizeInfos) {<a name="line.460"></a>
+<span class="sourceLineNo">461</span> Bucket b = bsi.findAndRemoveCompletelyFreeBucket();<a name="line.461"></a>
+<span class="sourceLineNo">462</span> if (b != null) return b;<a name="line.462"></a>
+<span class="sourceLineNo">463</span> }<a name="line.463"></a>
+<span class="sourceLineNo">464</span> return null;<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> * Free a block with the offset<a name="line.468"></a>
+<span class="sourceLineNo">469</span> * @param offset block's offset<a name="line.469"></a>
+<span class="sourceLineNo">470</span> * @return size freed<a name="line.470"></a>
+<span class="sourceLineNo">471</span> */<a name="line.471"></a>
+<span class="sourceLineNo">472</span> public synchronized int freeBlock(long offset) {<a name="line.472"></a>
+<span class="sourceLineNo">473</span> int bucketNo = (int) (offset / bucketCapacity);<a name="line.473"></a>
+<span class="sourceLineNo">474</span> assert bucketNo >= 0 && bucketNo < buckets.length;<a name="line.474"></a>
+<span class="sourceLineNo">475</span> Bucket targetBucket = buckets[bucketNo];<a name="line.475"></a>
+<span class="sourceLineNo">476</span> bucketSizeInfos[targetBucket.sizeIndex()].freeBlock(targetBucket, offset);<a name="line.476"></a>
+<span class="sourceLineNo">477</span> usedSize -= targetBucket.getItemAllocationSize();<a name="line.477"></a>
+<span class="sourceLineNo">478</span> return targetBucket.getItemAllocationSize();<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> public int sizeIndexOfAllocation(long offset) {<a name="line.481"></a>
+<span class="sourceLineNo">482</span> int bucketNo = (int) (offset / bucketCapacity);<a name="line.482"></a>
+<span class="sourceLineNo">483</span> assert bucketNo >= 0 && bucketNo < buckets.length;<a name="line.483"></a>
+<span class="sourceLineNo">484</span> Bucket targetBucket = buckets[bucketNo];<a name="line.484"></a>
+<span class="sourceLineNo">485</span> return targetBucket.sizeIndex();<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> public int sizeOfAllocation(long offset) {<a name="line.488"></a>
+<span class="sourceLineNo">489</span> int bucketNo = (int) (offset / bucketCapacity);<a name="line.489"></a>
+<span class="sourceLineNo">490</span> assert bucketNo >= 0 && bucketNo < buckets.length;<a name="line.490"></a>
+<span class="sourceLineNo">491</span> Bucket targetBucket = buckets[bucketNo];<a name="line.491"></a>
+<span class="sourceLineNo">492</span> return targetBucket.getItemAllocationSize();<a name="line.492"></a>
+<span class="sourceLineNo">493</span> }<a name="line.493"></a>
+<span class="sourceLineNo">494</span><a name="line.494"></a>
+<span class="sourceLineNo">495</span> static class IndexStatistics {<a name="line.495"></a>
+<span class="sourceLineNo">496</span> private long freeCount, usedCount, itemSize, totalCount;<a name="line.496"></a>
+<span class="sourceLineNo">497</span><a name="line.497"></a>
+<span class="sourceLineNo">498</span> public long freeCount() {<a name="line.498"></a>
+<span class="sourceLineNo">499</span> return freeCount;<a name="line.499"></a>
+<span class="sourceLineNo">500</span> }<a name="line.500"></a>
+<span class="sourceLineNo">501</span><a name="line.501"></a>
+<span class="sourceLineNo">502</span> public long usedCount() {<a name="line.502"></a>
+<span class="sourceLineNo">503</span> return usedCount;<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> public long totalCount() {<a name="line.506"></a>
+<span class="sourceLineNo">507</span> return totalCount;<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> public long freeBytes() {<a name="line.510"></a>
+<span class="sourceLineNo">511</span> return freeCount * itemSize;<a name="line.511"></a>
+<span class="sourceLineNo">512</span> }<a name="line.512"></a>
+<span class="sourceLineNo">513</span><a name="line.513"></a>
+<span class="sourceLineNo">514</span> public long usedBytes() {<a name="line.514"></a>
+<span class="sourceLineNo">515</span> return usedCount * itemSize;<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> public long totalBytes() {<a name="line.518"></a>
+<span class="sourceLineNo">519</span> return totalCount * itemSize;<a name="line.519"></a>
+<span class="sourceLineNo">520</span> }<a name="line.520"></a>
+<span class="sourceLineNo">521</span><a name="line.521"></a>
+<span class="sourceLineNo">522</span> public long itemSize() {<a name="line.522"></a>
+<span class="sourceLineNo">523</span> return itemSize;<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> public IndexStatistics(long free, long used, long itemSize) {<a name="line.526"></a>
+<span class="sourceLineNo">527</span> setTo(free, used, itemSize);<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> public IndexStatistics() {<a name="line.530"></a>
+<span class="sourceLineNo">531</span> setTo(-1, -1, 0);<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> public void setTo(long free, long used, long itemSize) {<a name="line.534"></a>
+<span class="sourceLineNo">535</span> this.itemSize = itemSize;<a name="line.535"></a>
+<span class="sourceLineNo">536</span> this.freeCount = free;<a name="line.536"></a>
+<span class="sourceLineNo">537</span> this.usedCount = used;<a name="line.537"></a>
+<span class="sourceLineNo">538</span> this.totalCount = free + used;<a name="line.538"></a>
+<span class="sourceLineNo">539</span> }<a name="line.539"></a>
+<span class="sourceLineNo">540</span> }<a name="line.540"></a>
+<span class="sourceLineNo">541</span><a name="line.541"></a>
+<span class="sourceLineNo">542</span> public Bucket [] getBuckets() {<a name="line.542"></a>
+<span class="sourceLineNo">543</span> return this.buckets;<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> void logStatistics() {<a name="line.546"></a>
+<span class="sourceLineNo">547</span> IndexStatistics total = new IndexStatistics();<a name="line.547"></a>
+<span class="sourceLineNo">548</span> IndexStatistics[] stats = getIndexStatistics(total);<a name="line.548"></a>
+<span class="sourceLineNo">549</span> LOG.info("Bucket allocator statistics follow:\n");<a name="line.549"></a>
+<span class="sourceLineNo">550</span> LOG.info(" Free bytes=" + total.freeBytes() + "+; used bytes="<a name="line.550"></a>
+<span class="sourceLineNo">551</span> + total.usedBytes() + "; total bytes=" + total.totalBytes());<a name="line.551"></a>
+<span class="sourceLineNo">552</span> for (IndexStatistics s : stats) {<a name="line.552"></a>
+<span class="sourceLineNo">553</span> LOG.info(" Object size " + s.itemSize() + " used=" + s.usedCount()<a name="line.553"></a>
+<span class="sourceLineNo">554</span> + "; free=" + s.freeCount() + "; total=" + s.totalCount());<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><a name="line.557"></a>
+<span class="sourceLineNo">558</span> IndexStatistics[] getIndexStatistics(IndexStatistics grandTotal) {<a name="line.558"></a>
+<span class="sourceLineNo">559</span> IndexStatistics[] stats = getIndexStatistics();<a name="line.559"></a>
+<span class="sourceLineNo">560</span> long totalfree = 0, totalused = 0;<a name="line.560"></a>
+<span class="sourceLineNo">561</span> for (IndexStatistics stat : stats) {<a name="line.561"></a>
+<span class="sourceLineNo">562</span> totalfree += stat.freeBytes();<a name="line.562"></a>
+<span class="sourceLineNo">563</span> totalused += stat.usedBytes();<a name="line.563"></a>
+<span class="sourceLineNo">564</span> }<a name="line.564"></a>
+<span class="sourceLineNo">565</span> grandTotal.setTo(totalfree, totalused, 1);<a name="line.565"></a>
+<span class="sourceLineNo">566</span> return stats;<a name="line.566"></a>
+<span class="sourceLineNo">567</span> }<a name="line.567"></a>
+<span class="sourceLineNo">568</span><a name="line.568"></a>
+<span class="sourceLineNo">569</span> IndexStatistics[] getIndexStatistics() {<a name="line.569"></a>
+<span class="sourceLineNo">570</span> IndexStatistics[] stats = new IndexStatistics[bucketSizes.length];<a name="line.570"></a>
+<span class="sourceLineNo">571</span> for (int i = 0; i < stats.length; ++i)<a name="line.571"></a>
+<span class="sourceLineNo">572</span> stats[i] = bucketSizeInfos[i].statistics();<a name="line.572"></a>
+<span class="sourceLineNo">573</span> return stats;<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> public long freeBlock(long freeList[]) {<a name="line.576"></a>
+<span class="sourceLineNo">577</span> long sz = 0;<a name="line.577"></a>
+<span class="sourceLineNo">578</span> for (int i = 0; i < freeList.length; ++i)<a name="line.578"></a>
+<span class="sourceLineNo">579</span> sz += freeBlock(freeList[i]);<a name="line.579"></a>
+<span class="sourceLineNo">580</span> return sz;<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> public int getBucketIndex(long offset) {<a name="line.583"></a>
+<span class="sourceLineNo">584</span> return (int) (offset / bucketCapacity);<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> /**<a name="line.587"></a>
+<span class="sourceLineNo">588</span> * Returns a set of indices of the buckets that are least filled<a name="line.588"></a>
+<span class="sourceLineNo">589</span> * excluding the offsets, we also the fully free buckets for the<a name="line.589"></a>
+<span class="sourceLineNo">590</span> * BucketSizes where everything is empty and they only have one<a name="line.590"></a>
+<span class="sourceLineNo">591</span> * completely free bucket as a reserved<a name="line.591"></a>
+<span class="sourceLineNo">592</span> *<a name="line.592"></a>
+<span class="sourceLineNo">593</span> * @param excludedBuckets the buckets that need to be excluded due to<a name="line.593"></a>
+<span class="sourceLineNo">594</span> * currently being in used<a name="line.594"></a>
+<span class="sourceLineNo">595</span> * @param bucketCount max Number of buckets to return<a name="line.595"></a>
+<span class="sourceLineNo">596</span> * @return set of bucket indices which could be used for eviction<a name="line.596"></a>
+<span class="sourceLineNo">597</span> */<a name="line.597"></a>
+<span class="sourceLineNo">598</span> public Set<Integer> getLeastFilledBuckets(Set<Integer> excludedBuckets,<a name="line.598"></a>
+<span class="sourceLineNo">599</span> int bucketCount) {<a name="line.599"></a>
+<span class="sourceLineNo">600</span> Queue<Integer> queue = MinMaxPriorityQueue.<Integer>orderedBy(<a name="line.600"></a>
+<span class="sourceLineNo">601</span> new Comparator<Integer>() {<a name="line.601"></a>
+<span class="sourceLineNo">602</span> @Override<a name="line.602"></a>
+<span class="sourceLineNo">603</span> public int compare(Integer left, Integer right) {<a name="line.603"></a>
+<span class="sourceLineNo">604</span> // We will always get instantiated buckets<a name="line.604"></a>
+<span class="sourceLineNo">605</span> return Float.compare(<a name="line.605"></a>
+<span class="sourceLineNo">606</span> ((float) buckets[left].usedCount) / buckets[left].itemCount,<a name="line.606"></a>
+<span class="sourceLineNo">607</span> ((float) buckets[right].usedCount) / buckets[right].itemCount);<a name="line.607"></a>
+<span class="sourceLineNo">608</span> }<a name="line.608"></a>
+<span class="sourceLineNo">609</span> }).maximumSize(bucketCount).create();<a name="line.609"></a>
+<span class="sourceLineNo">610</span><a name="line.610"></a>
+<span class="sourceLineNo">611</span> for (int i = 0; i < buckets.length; i ++ ) {<a name="line.611"></a>
+<span class="sourceLineNo">612</span> if (!excludedBuckets.contains(i) && !buckets[i].isUninstantiated() &&<a name="line.612"></a>
+<span class="sourceLineNo">613</span> // Avoid the buckets that are the only buckets for a sizeIndex<a name="line.613"></a>
+<span class="sourceLineNo">614</span> bucketSizeInfos[buckets[i].sizeIndex()].bucketList.size() != 1) {<a name="line.614"></a>
+<span class="sourceLineNo">615</span> queue.add(i);<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><a name="line.618"></a>
+<span class="sourceLineNo">619</span> Set<Integer> result = new HashSet<>(bucketCount);<a name="line.619"></a>
+<span class="sourceLineNo">620</span> result.addAll(queue);<a name="line.620"></a>
+<span class="sourceLineNo">621</span><a name="line.621"></a>
+<span class="sourceLineNo">622</span> return result;<a name="line.622"></a>
+<span class="sourceLineNo">623</span> }<a name="line.623"></a>
+<span class="sourceLineNo">624</span>}<a name="line.624"></a>
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html
index a3cd853..0a4475b 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketAllocator.html
@@ -277,358 +277,359 @@
<span class="sourceLineNo">269</span><a name="line.269"></a>
<span class="sourceLineNo">270</span> // Default block size in hbase is 64K, so we choose more sizes near 64K, you'd better<a name="line.270"></a>
<span class="sourceLineNo">271</span> // reset it according to your cluster's block size distribution<a name="line.271"></a>
-<span class="sourceLineNo">272</span> // TODO Support the view of block size distribution statistics<a name="line.272"></a>
-<span class="sourceLineNo">273</span> // TODO: Why we add the extra 1024 bytes? Slop?<a name="line.273"></a>
-<span class="sourceLineNo">274</span> private static final int DEFAULT_BUCKET_SIZES[] = { 4 * 1024 + 1024, 8 * 1024 + 1024,<a name="line.274"></a>
-<span class="sourceLineNo">275</span> 16 * 1024 + 1024, 32 * 1024 + 1024, 40 * 1024 + 1024, 48 * 1024 + 1024,<a name="line.275"></a>
-<span class="sourceLineNo">276</span> 56 * 1024 + 1024, 64 * 1024 + 1024, 96 * 1024 + 1024, 128 * 1024 + 1024,<a name="line.276"></a>
-<span class="sourceLineNo">277</span> 192 * 1024 + 1024, 256 * 1024 + 1024, 384 * 1024 + 1024,<a name="line.277"></a>
-<span class="sourceLineNo">278</span> 512 * 1024 + 1024 };<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> * Round up the given block size to bucket size, and get the corresponding<a name="line.281"></a>
-<span class="sourceLineNo">282</span> * BucketSizeInfo<a name="line.282"></a>
-<span class="sourceLineNo">283</span> */<a name="line.283"></a>
-<span class="sourceLineNo">284</span> public BucketSizeInfo roundUpToBucketSizeInfo(int blockSize) {<a name="line.284"></a>
-<span class="sourceLineNo">285</span> for (int i = 0; i < bucketSizes.length; ++i)<a name="line.285"></a>
-<span class="sourceLineNo">286</span> if (blockSize <= bucketSizes[i])<a name="line.286"></a>
-<span class="sourceLineNo">287</span> return bucketSizeInfos[i];<a name="line.287"></a>
-<span class="sourceLineNo">288</span> return null;<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> /**<a name="line.291"></a>
-<span class="sourceLineNo">292</span> * So, what is the minimum amount of items we'll tolerate in a single bucket?<a name="line.292"></a>
-<span class="sourceLineNo">293</span> */<a name="line.293"></a>
-<span class="sourceLineNo">294</span> static public final int FEWEST_ITEMS_IN_BUCKET = 4;<a name="line.294"></a>
-<span class="sourceLineNo">295</span><a name="line.295"></a>
-<span class="sourceLineNo">296</span> private final int[] bucketSizes;<a name="line.296"></a>
-<span class="sourceLineNo">297</span> private final int bigItemSize;<a name="line.297"></a>
-<span class="sourceLineNo">298</span> // The capacity size for each bucket<a name="line.298"></a>
-<span class="sourceLineNo">299</span> private final long bucketCapacity;<a name="line.299"></a>
-<span class="sourceLineNo">300</span> private Bucket[] buckets;<a name="line.300"></a>
-<span class="sourceLineNo">301</span> private BucketSizeInfo[] bucketSizeInfos;<a name="line.301"></a>
-<span class="sourceLineNo">302</span> private final long totalSize;<a name="line.302"></a>
-<span class="sourceLineNo">303</span> private transient long usedSize = 0;<a name="line.303"></a>
-<span class="sourceLineNo">304</span><a name="line.304"></a>
-<span class="sourceLineNo">305</span> BucketAllocator(long availableSpace, int[] bucketSizes)<a name="line.305"></a>
-<span class="sourceLineNo">306</span> throws BucketAllocatorException {<a name="line.306"></a>
-<span class="sourceLineNo">307</span> this.bucketSizes = bucketSizes == null ? DEFAULT_BUCKET_SIZES : bucketSizes;<a name="line.307"></a>
-<span class="sourceLineNo">308</span> Arrays.sort(this.bucketSizes);<a name="line.308"></a>
-<span class="sourceLineNo">309</span> this.bigItemSize = Ints.max(this.bucketSizes);<a name="line.309"></a>
-<span class="sourceLineNo">310</span> this.bucketCapacity = FEWEST_ITEMS_IN_BUCKET * (long) bigItemSize;<a name="line.310"></a>
-<span class="sourceLineNo">311</span> buckets = new Bucket[(int) (availableSpace / bucketCapacity)];<a name="line.311"></a>
-<span class="sourceLineNo">312</span> if (buckets.length < this.bucketSizes.length)<a name="line.312"></a>
-<span class="sourceLineNo">313</span> throw new BucketAllocatorException("Bucket allocator size too small (" + buckets.length +<a name="line.313"></a>
-<span class="sourceLineNo">314</span> "); must have room for at least " + this.bucketSizes.length + " buckets");<a name="line.314"></a>
-<span class="sourceLineNo">315</span> bucketSizeInfos = new BucketSizeInfo[this.bucketSizes.length];<a name="line.315"></a>
-<span class="sourceLineNo">316</span> for (int i = 0; i < this.bucketSizes.length; ++i) {<a name="line.316"></a>
-<span class="sourceLineNo">317</span> bucketSizeInfos[i] = new BucketSizeInfo(i);<a name="line.317"></a>
-<span class="sourceLineNo">318</span> }<a name="line.318"></a>
-<span class="sourceLineNo">319</span> for (int i = 0; i < buckets.length; ++i) {<a name="line.319"></a>
-<span class="sourceLineNo">320</span> buckets[i] = new Bucket(bucketCapacity * i);<a name="line.320"></a>
-<span class="sourceLineNo">321</span> bucketSizeInfos[i < this.bucketSizes.length ? i : this.bucketSizes.length - 1]<a name="line.321"></a>
-<span class="sourceLineNo">322</span> .instantiateBucket(buckets[i]);<a name="line.322"></a>
-<span class="sourceLineNo">323</span> }<a name="line.323"></a>
-<span class="sourceLineNo">324</span> this.totalSize = ((long) buckets.length) * bucketCapacity;<a name="line.324"></a>
-<span class="sourceLineNo">325</span> if (LOG.isInfoEnabled()) {<a name="line.325"></a>
-<span class="sourceLineNo">326</span> LOG.info("Cache totalSize=" + this.totalSize + ", buckets=" + this.buckets.length +<a name="line.326"></a>
-<span class="sourceLineNo">327</span> ", bucket capacity=" + this.bucketCapacity +<a name="line.327"></a>
-<span class="sourceLineNo">328</span> "=(" + FEWEST_ITEMS_IN_BUCKET + "*" + this.bigItemSize + ")=" +<a name="line.328"></a>
-<span class="sourceLineNo">329</span> "(FEWEST_ITEMS_IN_BUCKET*(largest configured bucketcache size))");<a name="line.329"></a>
-<span class="sourceLineNo">330</span> }<a name="line.330"></a>
-<span class="sourceLineNo">331</span> }<a name="line.331"></a>
-<span class="sourceLineNo">332</span><a name="line.332"></a>
-<span class="sourceLineNo">333</span> /**<a name="line.333"></a>
-<span class="sourceLineNo">334</span> * Rebuild the allocator's data structures from a persisted map.<a name="line.334"></a>
-<span class="sourceLineNo">335</span> * @param availableSpace capacity of cache<a name="line.335"></a>
-<span class="sourceLineNo">336</span> * @param map A map stores the block key and BucketEntry(block's meta data<a name="line.336"></a>
-<span class="sourceLineNo">337</span> * like offset, length)<a name="line.337"></a>
-<span class="sourceLineNo">338</span> * @param realCacheSize cached data size statistics for bucket cache<a name="line.338"></a>
-<span class="sourceLineNo">339</span> * @throws BucketAllocatorException<a name="line.339"></a>
-<span class="sourceLineNo">340</span> */<a name="line.340"></a>
-<span class="sourceLineNo">341</span> BucketAllocator(long availableSpace, int[] bucketSizes, Map<BlockCacheKey, BucketEntry> map,<a name="line.341"></a>
-<span class="sourceLineNo">342</span> LongAdder realCacheSize) throws BucketAllocatorException {<a name="line.342"></a>
-<span class="sourceLineNo">343</span> this(availableSpace, bucketSizes);<a name="line.343"></a>
-<span class="sourceLineNo">344</span><a name="line.344"></a>
-<span class="sourceLineNo">345</span> // each bucket has an offset, sizeindex. probably the buckets are too big<a name="line.345"></a>
-<span class="sourceLineNo">346</span> // in our default state. so what we do is reconfigure them according to what<a name="line.346"></a>
-<span class="sourceLineNo">347</span> // we've found. we can only reconfigure each bucket once; if more than once,<a name="line.347"></a>
-<span class="sourceLineNo">348</span> // we know there's a bug, so we just log the info, throw, and start again...<a name="line.348"></a>
-<span class="sourceLineNo">349</span> boolean[] reconfigured = new boolean[buckets.length];<a name="line.349"></a>
-<span class="sourceLineNo">350</span> int sizeNotMatchedCount = 0;<a name="line.350"></a>
-<span class="sourceLineNo">351</span> int insufficientCapacityCount = 0;<a name="line.351"></a>
-<span class="sourceLineNo">352</span> Iterator<Map.Entry<BlockCacheKey, BucketEntry>> iterator = map.entrySet().iterator();<a name="line.352"></a>
-<span class="sourceLineNo">353</span> while (iterator.hasNext()) {<a name="line.353"></a>
-<span class="sourceLineNo">354</span> Map.Entry<BlockCacheKey, BucketEntry> entry = iterator.next();<a name="line.354"></a>
-<span class="sourceLineNo">355</span> long foundOffset = entry.getValue().offset();<a name="line.355"></a>
-<span class="sourceLineNo">356</span> int foundLen = entry.getValue().getLength();<a name="line.356"></a>
-<span class="sourceLineNo">357</span> int bucketSizeIndex = -1;<a name="line.357"></a>
-<span class="sourceLineNo">358</span> for (int i = 0; i < this.bucketSizes.length; ++i) {<a name="line.358"></a>
-<span class="sourceLineNo">359</span> if (foundLen <= this.bucketSizes[i]) {<a name="line.359"></a>
-<span class="sourceLineNo">360</span> bucketSizeIndex = i;<a name="line.360"></a>
-<span class="sourceLineNo">361</span> break;<a name="line.361"></a>
-<span class="sourceLineNo">362</span> }<a name="line.362"></a>
-<span class="sourceLineNo">363</span> }<a name="line.363"></a>
-<span class="sourceLineNo">364</span> if (bucketSizeIndex == -1) {<a name="line.364"></a>
-<span class="sourceLineNo">365</span> sizeNotMatchedCount++;<a name="line.365"></a>
-<span class="sourceLineNo">366</span> iterator.remove();<a name="line.366"></a>
-<span class="sourceLineNo">367</span> continue;<a name="line.367"></a>
-<span class="sourceLineNo">368</span> }<a name="line.368"></a>
-<span class="sourceLineNo">369</span> int bucketNo = (int) (foundOffset / bucketCapacity);<a name="line.369"></a>
-<span class="sourceLineNo">370</span> if (bucketNo < 0 || bucketNo >= buckets.length) {<a name="line.370"></a>
-<span class="sourceLineNo">371</span> insufficientCapacityCount++;<a name="line.371"></a>
-<span class="sourceLineNo">372</span> iterator.remove();<a name="line.372"></a>
-<span class="sourceLineNo">373</span> continue;<a name="line.373"></a>
-<span class="sourceLineNo">374</span> }<a name="line.374"></a>
-<span class="sourceLineNo">375</span> Bucket b = buckets[bucketNo];<a name="line.375"></a>
-<span class="sourceLineNo">376</span> if (reconfigured[bucketNo]) {<a name="line.376"></a>
-<span class="sourceLineNo">377</span> if (b.sizeIndex() != bucketSizeIndex) {<a name="line.377"></a>
-<span class="sourceLineNo">378</span> throw new BucketAllocatorException("Inconsistent allocation in bucket map;");<a name="line.378"></a>
-<span class="sourceLineNo">379</span> }<a name="line.379"></a>
-<span class="sourceLineNo">380</span> } else {<a name="line.380"></a>
-<span class="sourceLineNo">381</span> if (!b.isCompletelyFree()) {<a name="line.381"></a>
-<span class="sourceLineNo">382</span> throw new BucketAllocatorException(<a name="line.382"></a>
-<span class="sourceLineNo">383</span> "Reconfiguring bucket " + bucketNo + " but it's already allocated; corrupt data");<a name="line.383"></a>
-<span class="sourceLineNo">384</span> }<a name="line.384"></a>
-<span class="sourceLineNo">385</span> // Need to remove the bucket from whichever list it's currently in at<a name="line.385"></a>
-<span class="sourceLineNo">386</span> // the moment...<a name="line.386"></a>
-<span class="sourceLineNo">387</span> BucketSizeInfo bsi = bucketSizeInfos[bucketSizeIndex];<a name="line.387"></a>
-<span class="sourceLineNo">388</span> BucketSizeInfo oldbsi = bucketSizeInfos[b.sizeIndex()];<a name="line.388"></a>
-<span class="sourceLineNo">389</span> oldbsi.removeBucket(b);<a name="line.389"></a>
-<span class="sourceLineNo">390</span> bsi.instantiateBucket(b);<a name="line.390"></a>
-<span class="sourceLineNo">391</span> reconfigured[bucketNo] = true;<a name="line.391"></a>
-<span class="sourceLineNo">392</span> }<a name="line.392"></a>
-<span class="sourceLineNo">393</span> realCacheSize.add(foundLen);<a name="line.393"></a>
-<span class="sourceLineNo">394</span> buckets[bucketNo].addAllocation(foundOffset);<a name="line.394"></a>
-<span class="sourceLineNo">395</span> usedSize += buckets[bucketNo].getItemAllocationSize();<a name="line.395"></a>
-<span class="sourceLineNo">396</span> bucketSizeInfos[bucketSizeIndex].blockAllocated(b);<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> if (sizeNotMatchedCount > 0) {<a name="line.399"></a>
-<span class="sourceLineNo">400</span> LOG.warn("There are " + sizeNotMatchedCount + " blocks which can't be rebuilt because " +<a name="line.400"></a>
-<span class="sourceLineNo">401</span> "there is no matching bucket size for these blocks");<a name="line.401"></a>
-<span class="sourceLineNo">402</span> }<a name="line.402"></a>
-<span class="sourceLineNo">403</span> if (insufficientCapacityCount > 0) {<a name="line.403"></a>
-<span class="sourceLineNo">404</span> LOG.warn("There are " + insufficientCapacityCount + " blocks which can't be rebuilt - "<a name="line.404"></a>
-<span class="sourceLineNo">405</span> + "did you shrink the cache?");<a name="line.405"></a>
-<span class="sourceLineNo">406</span> }<a name="line.406"></a>
-<span class="sourceLineNo">407</span> }<a name="line.407"></a>
-<span class="sourceLineNo">408</span><a name="line.408"></a>
-<span class="sourceLineNo">409</span> @Override<a name="line.409"></a>
-<span class="sourceLineNo">410</span> public String toString() {<a name="line.410"></a>
-<span class="sourceLineNo">411</span> StringBuilder sb = new StringBuilder(1024);<a name="line.411"></a>
-<span class="sourceLineNo">412</span> for (int i = 0; i < buckets.length; ++i) {<a name="line.412"></a>
-<span class="sourceLineNo">413</span> Bucket b = buckets[i];<a name="line.413"></a>
-<span class="sourceLineNo">414</span> if (i > 0) sb.append(", ");<a name="line.414"></a>
-<span class="sourceLineNo">415</span> sb.append("bucket.").append(i).append(": size=").append(b.getItemAllocationSize());<a name="line.415"></a>
-<span class="sourceLineNo">416</span> sb.append(", freeCount=").append(b.freeCount()).append(", used=").append(b.usedCount());<a name="line.416"></a>
-<span class="sourceLineNo">417</span> }<a name="line.417"></a>
-<span class="sourceLineNo">418</span> return sb.toString();<a name="line.418"></a>
-<span class="sourceLineNo">419</span> }<a name="line.419"></a>
-<span class="sourceLineNo">420</span><a name="line.420"></a>
-<span class="sourceLineNo">421</span> public long getUsedSize() {<a name="line.421"></a>
-<span class="sourceLineNo">422</span> return this.usedSize;<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> public long getFreeSize() {<a name="line.425"></a>
-<span class="sourceLineNo">426</span> return this.totalSize - getUsedSize();<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> public long getTotalSize() {<a name="line.429"></a>
-<span class="sourceLineNo">430</span> return this.totalSize;<a name="line.430"></a>
-<span class="sourceLineNo">431</span> }<a name="line.431"></a>
-<span class="sourceLineNo">432</span><a name="line.432"></a>
-<span class="sourceLineNo">433</span> /**<a name="line.433"></a>
-<span class="sourceLineNo">434</span> * Allocate a block with specified size. Return the offset<a name="line.434"></a>
-<span class="sourceLineNo">435</span> * @param blockSize size of block<a name="line.435"></a>
-<span class="sourceLineNo">436</span> * @throws BucketAllocatorException<a name="line.436"></a>
-<span class="sourceLineNo">437</span> * @throws CacheFullException<a name="line.437"></a>
-<span class="sourceLineNo">438</span> * @return the offset in the IOEngine<a name="line.438"></a>
-<span class="sourceLineNo">439</span> */<a name="line.439"></a>
-<span class="sourceLineNo">440</span> public synchronized long allocateBlock(int blockSize) throws CacheFullException,<a name="line.440"></a>
-<span class="sourceLineNo">441</span> BucketAllocatorException {<a name="line.441"></a>
-<span class="sourceLineNo">442</span> assert blockSize > 0;<a name="line.442"></a>
-<span class="sourceLineNo">443</span> BucketSizeInfo bsi = roundUpToBucketSizeInfo(blockSize);<a name="line.443"></a>
-<span class="sourceLineNo">444</span> if (bsi == null) {<a name="line.444"></a>
-<span class="sourceLineNo">445</span> throw new BucketAllocatorException("Allocation too big size=" + blockSize +<a name="line.445"></a>
-<span class="sourceLineNo">446</span> "; adjust BucketCache sizes " + BlockCacheFactory.BUCKET_CACHE_BUCKETS_KEY +<a name="line.446"></a>
-<span class="sourceLineNo">447</span> " to accomodate if size seems reasonable and you want it cached.");<a name="line.447"></a>
-<span class="sourceLineNo">448</span> }<a name="line.448"></a>
-<span class="sourceLineNo">449</span> long offset = bsi.allocateBlock();<a name="line.449"></a>
-<span class="sourceLineNo">450</span><a name="line.450"></a>
-<span class="sourceLineNo">451</span> // Ask caller to free up space and try again!<a name="line.451"></a>
-<span class="sourceLineNo">452</span> if (offset < 0)<a name="line.452"></a>
-<span class="sourceLineNo">453</span> throw new CacheFullException(blockSize, bsi.sizeIndex());<a name="line.453"></a>
-<span class="sourceLineNo">454</span> usedSize += bucketSizes[bsi.sizeIndex()];<a name="line.454"></a>
-<span class="sourceLineNo">455</span> return offset;<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> private Bucket grabGlobalCompletelyFreeBucket() {<a name="line.458"></a>
-<span class="sourceLineNo">459</span> for (BucketSizeInfo bsi : bucketSizeInfos) {<a name="line.459"></a>
-<span class="sourceLineNo">460</span> Bucket b = bsi.findAndRemoveCompletelyFreeBucket();<a name="line.460"></a>
-<span class="sourceLineNo">461</span> if (b != null) return b;<a name="line.461"></a>
-<span class="sourceLineNo">462</span> }<a name="line.462"></a>
-<span class="sourceLineNo">463</span> return null;<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> * Free a block with the offset<a name="line.467"></a>
-<span class="sourceLineNo">468</span> * @param offset block's offset<a name="line.468"></a>
-<span class="sourceLineNo">469</span> * @return size freed<a name="line.469"></a>
-<span class="sourceLineNo">470</span> */<a name="line.470"></a>
-<span class="sourceLineNo">471</span> public synchronized int freeBlock(long offset) {<a name="line.471"></a>
-<span class="sourceLineNo">472</span> int bucketNo = (int) (offset / bucketCapacity);<a name="line.472"></a>
-<span class="sourceLineNo">473</span> assert bucketNo >= 0 && bucketNo < buckets.length;<a name="line.473"></a>
-<span class="sourceLineNo">474</span> Bucket targetBucket = buckets[bucketNo];<a name="line.474"></a>
-<span class="sourceLineNo">475</span> bucketSizeInfos[targetBucket.sizeIndex()].freeBlock(targetBucket, offset);<a name="line.475"></a>
-<span class="sourceLineNo">476</span> usedSize -= targetBucket.getItemAllocationSize();<a name="line.476"></a>
-<span class="sourceLineNo">477</span> return targetBucket.getItemAllocationSize();<a name="line.477"></a>
-<span class="sourceLineNo">478</span> }<a name="line.478"></a>
-<span class="sourceLineNo">479</span><a name="line.479"></a>
-<span class="sourceLineNo">480</span> public int sizeIndexOfAllocation(long offset) {<a name="line.480"></a>
-<span class="sourceLineNo">481</span> int bucketNo = (int) (offset / bucketCapacity);<a name="line.481"></a>
-<span class="sourceLineNo">482</span> assert bucketNo >= 0 && bucketNo < buckets.length;<a name="line.482"></a>
-<span class="sourceLineNo">483</span> Bucket targetBucket = buckets[bucketNo];<a name="line.483"></a>
-<span class="sourceLineNo">484</span> return targetBucket.sizeIndex();<a name="line.484"></a>
-<span class="sourceLineNo">485</span> }<a name="line.485"></a>
-<span class="sourceLineNo">486</span><a name="line.486"></a>
-<span class="sourceLineNo">487</span> public int sizeOfAllocation(long offset) {<a name="line.487"></a>
-<span class="sourceLineNo">488</span> int bucketNo = (int) (offset / bucketCapacity);<a name="line.488"></a>
-<span class="sourceLineNo">489</span> assert bucketNo >= 0 && bucketNo < buckets.length;<a name="line.489"></a>
-<span class="sourceLineNo">490</span> Bucket targetBucket = buckets[bucketNo];<a name="line.490"></a>
-<span class="sourceLineNo">491</span> return targetBucket.getItemAllocationSize();<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> static class IndexStatistics {<a name="line.494"></a>
-<span class="sourceLineNo">495</span> private long freeCount, usedCount, itemSize, totalCount;<a name="line.495"></a>
-<span class="sourceLineNo">496</span><a name="line.496"></a>
-<span class="sourceLineNo">497</span> public long freeCount() {<a name="line.497"></a>
-<span class="sourceLineNo">498</span> return freeCount;<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> public long usedCount() {<a name="line.501"></a>
-<span class="sourceLineNo">502</span> return usedCount;<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> public long totalCount() {<a name="line.505"></a>
-<span class="sourceLineNo">506</span> return totalCount;<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> public long freeBytes() {<a name="line.509"></a>
-<span class="sourceLineNo">510</span> return freeCount * itemSize;<a name="line.510"></a>
-<span class="sourceLineNo">511</span> }<a name="line.511"></a>
-<span class="sourceLineNo">512</span><a name="line.512"></a>
-<span class="sourceLineNo">513</span> public long usedBytes() {<a name="line.513"></a>
-<span class="sourceLineNo">514</span> return usedCount * itemSize;<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> public long totalBytes() {<a name="line.517"></a>
-<span class="sourceLineNo">518</span> return totalCount * itemSize;<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> public long itemSize() {<a name="line.521"></a>
-<span class="sourceLineNo">522</span> return itemSize;<a name="line.522"></a>
-<span class="sourceLineNo">523</span> }<a name="line.523"></a>
-<span class="sourceLineNo">524</span><a name="line.524"></a>
-<span class="sourceLineNo">525</span> public IndexStatistics(long free, long used, long itemSize) {<a name="line.525"></a>
-<span class="sourceLineNo">526</span> setTo(free, used, itemSize);<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> public IndexStatistics() {<a name="line.529"></a>
-<span class="sourceLineNo">530</span> setTo(-1, -1, 0);<a name="line.530"></a>
-<span class="sourceLineNo">531</span> }<a name="line.531"></a>
-<span class="sourceLineNo">532</span><a name="line.532"></a>
-<span class="sourceLineNo">533</span> public void setTo(long free, long used, long itemSize) {<a name="line.533"></a>
-<span class="sourceLineNo">534</span> this.itemSize = itemSize;<a name="line.534"></a>
-<span class="sourceLineNo">535</span> this.freeCount = free;<a name="line.535"></a>
-<span class="sourceLineNo">536</span> this.usedCount = used;<a name="line.536"></a>
-<span class="sourceLineNo">537</span> this.totalCount = free + used;<a name="line.537"></a>
-<span class="sourceLineNo">538</span> }<a name="line.538"></a>
-<span class="sourceLineNo">539</span> }<a name="line.539"></a>
-<span class="sourceLineNo">540</span><a name="line.540"></a>
-<span class="sourceLineNo">541</span> public Bucket [] getBuckets() {<a name="line.541"></a>
-<span class="sourceLineNo">542</span> return this.buckets;<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> void logStatistics() {<a name="line.545"></a>
-<span class="sourceLineNo">546</span> IndexStatistics total = new IndexStatistics();<a name="line.546"></a>
-<span class="sourceLineNo">547</span> IndexStatistics[] stats = getIndexStatistics(total);<a name="line.547"></a>
-<span class="sourceLineNo">548</span> LOG.info("Bucket allocator statistics follow:\n");<a name="line.548"></a>
-<span class="sourceLineNo">549</span> LOG.info(" Free bytes=" + total.freeBytes() + "+; used bytes="<a name="line.549"></a>
-<span class="sourceLineNo">550</span> + total.usedBytes() + "; total bytes=" + total.totalBytes());<a name="line.550"></a>
-<span class="sourceLineNo">551</span> for (IndexStatistics s : stats) {<a name="line.551"></a>
-<span class="sourceLineNo">552</span> LOG.info(" Object size " + s.itemSize() + " used=" + s.usedCount()<a name="line.552"></a>
-<span class="sourceLineNo">553</span> + "; free=" + s.freeCount() + "; total=" + s.totalCount());<a name="line.553"></a>
-<span class="sourceLineNo">554</span> }<a name="line.554"></a>
-<span class="sourceLineNo">555</span> }<a name="line.555"></a>
-<span class="sourceLineNo">556</span><a name="line.556"></a>
-<span class="sourceLineNo">557</span> IndexStatistics[] getIndexStatistics(IndexStatistics grandTotal) {<a name="line.557"></a>
-<span class="sourceLineNo">558</span> IndexStatistics[] stats = getIndexStatistics();<a name="line.558"></a>
-<span class="sourceLineNo">559</span> long totalfree = 0, totalused = 0;<a name="line.559"></a>
-<span class="sourceLineNo">560</span> for (IndexStatistics stat : stats) {<a name="line.560"></a>
-<span class="sourceLineNo">561</span> totalfree += stat.freeBytes();<a name="line.561"></a>
-<span class="sourceLineNo">562</span> totalused += stat.usedBytes();<a name="line.562"></a>
-<span class="sourceLineNo">563</span> }<a name="line.563"></a>
-<span class="sourceLineNo">564</span> grandTotal.setTo(totalfree, totalused, 1);<a name="line.564"></a>
-<span class="sourceLineNo">565</span> return stats;<a name="line.565"></a>
-<span class="sourceLineNo">566</span> }<a name="line.566"></a>
-<span class="sourceLineNo">567</span><a name="line.567"></a>
-<span class="sourceLineNo">568</span> IndexStatistics[] getIndexStatistics() {<a name="line.568"></a>
-<span class="sourceLineNo">569</span> IndexStatistics[] stats = new IndexStatistics[bucketSizes.length];<a name="line.569"></a>
-<span class="sourceLineNo">570</span> for (int i = 0; i < stats.length; ++i)<a name="line.570"></a>
-<span class="sourceLineNo">571</span> stats[i] = bucketSizeInfos[i].statistics();<a name="line.571"></a>
-<span class="sourceLineNo">572</span> return stats;<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> public long freeBlock(long freeList[]) {<a name="line.575"></a>
-<span class="sourceLineNo">576</span> long sz = 0;<a name="line.576"></a>
-<span class="sourceLineNo">577</span> for (int i = 0; i < freeList.length; ++i)<a name="line.577"></a>
-<span class="sourceLineNo">578</span> sz += freeBlock(freeList[i]);<a name="line.578"></a>
-<span class="sourceLineNo">579</span> return sz;<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> public int getBucketIndex(long offset) {<a name="line.582"></a>
-<span class="sourceLineNo">583</span> return (int) (offset / bucketCapacity);<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> * Returns a set of indices of the buckets that are least filled<a name="line.587"></a>
-<span class="sourceLineNo">588</span> * excluding the offsets, we also the fully free buckets for the<a name="line.588"></a>
-<span class="sourceLineNo">589</span> * BucketSizes where everything is empty and they only have one<a name="line.589"></a>
-<span class="sourceLineNo">590</span> * completely free bucket as a reserved<a name="line.590"></a>
-<span class="sourceLineNo">591</span> *<a name="line.591"></a>
-<span class="sourceLineNo">592</span> * @param excludedBuckets the buckets that need to be excluded due to<a name="line.592"></a>
-<span class="sourceLineNo">593</span> * currently being in used<a name="line.593"></a>
-<span class="sourceLineNo">594</span> * @param bucketCount max Number of buckets to return<a name="line.594"></a>
-<span class="sourceLineNo">595</span> * @return set of bucket indices which could be used for eviction<a name="line.595"></a>
-<span class="sourceLineNo">596</span> */<a name="line.596"></a>
-<span class="sourceLineNo">597</span> public Set<Integer> getLeastFilledBuckets(Set<Integer> excludedBuckets,<a name="line.597"></a>
-<span class="sourceLineNo">598</span> int bucketCount) {<a name="line.598"></a>
-<span class="sourceLineNo">599</span> Queue<Integer> queue = MinMaxPriorityQueue.<Integer>orderedBy(<a name="line.599"></a>
-<span class="sourceLineNo">600</span> new Comparator<Integer>() {<a name="line.600"></a>
-<span class="sourceLineNo">601</span> @Override<a name="line.601"></a>
-<span class="sourceLineNo">602</span> public int compare(Integer left, Integer right) {<a name="line.602"></a>
-<span class="sourceLineNo">603</span> // We will always get instantiated buckets<a name="line.603"></a>
-<span class="sourceLineNo">604</span> return Float.compare(<a name="line.604"></a>
-<span class="sourceLineNo">605</span> ((float) buckets[left].usedCount) / buckets[left].itemCount,<a name="line.605"></a>
-<span class="sourceLineNo">606</span> ((float) buckets[right].usedCount) / buckets[right].itemCount);<a name="line.606"></a>
-<span class="sourceLineNo">607</span> }<a name="line.607"></a>
-<span class="sourceLineNo">608</span> }).maximumSize(bucketCount).create();<a name="line.608"></a>
-<span class="sourceLineNo">609</span><a name="line.609"></a>
-<span class="sourceLineNo">610</span> for (int i = 0; i < buckets.length; i ++ ) {<a name="line.610"></a>
-<span class="sourceLineNo">611</span> if (!excludedBuckets.contains(i) && !buckets[i].isUninstantiated() &&<a name="line.611"></a>
-<span class="sourceLineNo">612</span> // Avoid the buckets that are the only buckets for a sizeIndex<a name="line.612"></a>
-<span class="sourceLineNo">613</span> bucketSizeInfos[buckets[i].sizeIndex()].bucketList.size() != 1) {<a name="line.613"></a>
-<span class="sourceLineNo">614</span> queue.add(i);<a name="line.614"></a>
-<span class="sourceLineNo">615</span> }<a name="line.615"></a>
-<span class="sourceLineNo">616</span> }<a name="line.616"></a>
-<span class="sourceLineNo">617</span><a name="line.617"></a>
-<span class="sourceLineNo">618</span> Set<Integer> result = new HashSet<>(bucketCount);<a name="line.618"></a>
-<span class="sourceLineNo">619</span> result.addAll(queue);<a name="line.619"></a>
-<span class="sourceLineNo">620</span><a name="line.620"></a>
-<span class="sourceLineNo">621</span> return result;<a name="line.621"></a>
-<span class="sourceLineNo">622</span> }<a name="line.622"></a>
-<span class="sourceLineNo">623</span>}<a name="line.623"></a>
+<span class="sourceLineNo">272</span> // The real block size in hfile maybe a little larger than the size we configured ,<a name="line.272"></a>
+<span class="sourceLineNo">273</span> // so we need add extra 1024 bytes for fit.<a name="line.273"></a>
+<span class="sourceLineNo">274</span> // TODO Support the view of block size distribution statistics<a name="line.274"></a>
+<span class="sourceLineNo">275</span> private static final int DEFAULT_BUCKET_SIZES[] = { 4 * 1024 + 1024, 8 * 1024 + 1024,<a name="line.275"></a>
+<span class="sourceLineNo">276</span> 16 * 1024 + 1024, 32 * 1024 + 1024, 40 * 1024 + 1024, 48 * 1024 + 1024,<a name="line.276"></a>
+<span class="sourceLineNo">277</span> 56 * 1024 + 1024, 64 * 1024 + 1024, 96 * 1024 + 1024, 128 * 1024 + 1024,<a name="line.277"></a>
+<span class="sourceLineNo">278</span> 192 * 1024 + 1024, 256 * 1024 + 1024, 384 * 1024 + 1024,<a name="line.278"></a>
+<span class="sourceLineNo">279</span> 512 * 1024 + 1024 };<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> * Round up the given block size to bucket size, and get the corresponding<a name="line.282"></a>
+<span class="sourceLineNo">283</span> * BucketSizeInfo<a name="line.283"></a>
+<span class="sourceLineNo">284</span> */<a name="line.284"></a>
+<span class="sourceLineNo">285</span> public BucketSizeInfo roundUpToBucketSizeInfo(int blockSize) {<a name="line.285"></a>
+<span class="sourceLineNo">286</span> for (int i = 0; i < bucketSizes.length; ++i)<a name="line.286"></a>
+<span class="sourceLineNo">287</span> if (blockSize <= bucketSizes[i])<a name="line.287"></a>
+<span class="sourceLineNo">288</span> return bucketSizeInfos[i];<a name="line.288"></a>
+<span class="sourceLineNo">289</span> return null;<a name="line.289"></a>
+<span class="sourceLineNo">290</span> }<a name="line.290"></a>
+<span class="sourceLineNo">291</span><a name="line.291"></a>
+<span class="sourceLineNo">292</span> /**<a name="line.292"></a>
+<span class="sourceLineNo">293</span> * So, what is the minimum amount of items we'll tolerate in a single bucket?<a name="line.293"></a>
+<span class="sourceLineNo">294</span> */<a name="line.294"></a>
+<span class="sourceLineNo">295</span> static public final int FEWEST_ITEMS_IN_BUCKET = 4;<a name="line.295"></a>
+<span class="sourceLineNo">296</span><a name="line.296"></a>
+<span class="sourceLineNo">297</span> private final int[] bucketSizes;<a name="line.297"></a>
+<span class="sourceLineNo">298</span> private final int bigItemSize;<a name="line.298"></a>
+<span class="sourceLineNo">299</span> // The capacity size for each bucket<a name="line.299"></a>
+<span class="sourceLineNo">300</span> private final long bucketCapacity;<a name="line.300"></a>
+<span class="sourceLineNo">301</span> private Bucket[] buckets;<a name="line.301"></a>
+<span class="sourceLineNo">302</span> private BucketSizeInfo[] bucketSizeInfos;<a name="line.302"></a>
+<span class="sourceLineNo">303</span> private final long totalSize;<a name="line.303"></a>
+<span class="sourceLineNo">304</span> private transient long usedSize = 0;<a name="line.304"></a>
+<span class="sourceLineNo">305</span><a name="line.305"></a>
+<span class="sourceLineNo">306</span> BucketAllocator(long availableSpace, int[] bucketSizes)<a name="line.306"></a>
+<span class="sourceLineNo">307</span> throws BucketAllocatorException {<a name="line.307"></a>
+<span class="sourceLineNo">308</span> this.bucketSizes = bucketSizes == null ? DEFAULT_BUCKET_SIZES : bucketSizes;<a name="line.308"></a>
+<span class="sourceLineNo">309</span> Arrays.sort(this.bucketSizes);<a name="line.309"></a>
+<span class="sourceLineNo">310</span> this.bigItemSize = Ints.max(this.bucketSizes);<a name="line.310"></a>
+<span class="sourceLineNo">311</span> this.bucketCapacity = FEWEST_ITEMS_IN_BUCKET * (long) bigItemSize;<a name="line.311"></a>
+<span class="sourceLineNo">312</span> buckets = new Bucket[(int) (availableSpace / bucketCapacity)];<a name="line.312"></a>
+<span class="sourceLineNo">313</span> if (buckets.length < this.bucketSizes.length)<a name="line.313"></a>
+<span class="sourceLineNo">314</span> throw new BucketAllocatorException("Bucket allocator size too small (" + buckets.length +<a name="line.314"></a>
+<span class="sourceLineNo">315</span> "); must have room for at least " + this.bucketSizes.length + " buckets");<a name="line.315"></a>
+<span class="sourceLineNo">316</span> bucketSizeInfos = new BucketSizeInfo[this.bucketSizes.length];<a name="line.316"></a>
+<span class="sourceLineNo">317</span> for (int i = 0; i < this.bucketSizes.length; ++i) {<a name="line.317"></a>
+<span class="sourceLineNo">318</span> bucketSizeInfos[i] = new BucketSizeInfo(i);<a name="line.318"></a>
+<span class="sourceLineNo">319</span> }<a name="line.319"></a>
+<span class="sourceLineNo">320</span> for (int i = 0; i < buckets.length; ++i) {<a name="line.320"></a>
+<span class="sourceLineNo">321</span> buckets[i] = new Bucket(bucketCapacity * i);<a name="line.321"></a>
+<span class="sourceLineNo">322</span> bucketSizeInfos[i < this.bucketSizes.length ? i : this.bucketSizes.length - 1]<a name="line.322"></a>
+<span class="sourceLineNo">323</span> .instantiateBucket(buckets[i]);<a name="line.323"></a>
+<span class="sourceLineNo">324</span> }<a name="line.324"></a>
+<span class="sourceLineNo">325</span> this.totalSize = ((long) buckets.length) * bucketCapacity;<a name="line.325"></a>
+<span class="sourceLineNo">326</span> if (LOG.isInfoEnabled()) {<a name="line.326"></a>
+<span class="sourceLineNo">327</span> LOG.info("Cache totalSize=" + this.totalSize + ", buckets=" + this.buckets.length +<a name="line.327"></a>
+<span class="sourceLineNo">328</span> ", bucket capacity=" + this.bucketCapacity +<a name="line.328"></a>
+<span class="sourceLineNo">329</span> "=(" + FEWEST_ITEMS_IN_BUCKET + "*" + this.bigItemSize + ")=" +<a name="line.329"></a>
+<span class="sourceLineNo">330</span> "(FEWEST_ITEMS_IN_BUCKET*(largest configured bucketcache size))");<a name="line.330"></a>
+<span class="sourceLineNo">331</span> }<a name="line.331"></a>
+<span class="sourceLineNo">332</span> }<a name="line.332"></a>
+<span class="sourceLineNo">333</span><a name="line.333"></a>
+<span class="sourceLineNo">334</span> /**<a name="line.334"></a>
+<span class="sourceLineNo">335</span> * Rebuild the allocator's data structures from a persisted map.<a name="line.335"></a>
+<span class="sourceLineNo">336</span> * @param availableSpace capacity of cache<a name="line.336"></a>
+<span class="sourceLineNo">337</span> * @param map A map stores the block key and BucketEntry(block's meta data<a name="line.337"></a>
+<span class="sourceLineNo">338</span> * like offset, length)<a name="line.338"></a>
+<span class="sourceLineNo">339</span> * @param realCacheSize cached data size statistics for bucket cache<a name="line.339"></a>
+<span class="sourceLineNo">340</span> * @throws BucketAllocatorException<a name="line.340"></a>
+<span class="sourceLineNo">341</span> */<a name="line.341"></a>
+<span class="sourceLineNo">342</span> BucketAllocator(long availableSpace, int[] bucketSizes, Map<BlockCacheKey, BucketEntry> map,<a name="line.342"></a>
+<span class="sourceLineNo">343</span> LongAdder realCacheSize) throws BucketAllocatorException {<a name="line.343"></a>
+<span class="sourceLineNo">344</span> this(availableSpace, bucketSizes);<a name="line.344"></a>
+<span class="sourceLineNo">345</span><a name="line.345"></a>
+<span class="sourceLineNo">346</span> // each bucket has an offset, sizeindex. probably the buckets are too big<a name="line.346"></a>
+<span class="sourceLineNo">347</span> // in our default state. so what we do is reconfigure them according to what<a name="line.347"></a>
+<span class="sourceLineNo">348</span> // we've found. we can only reconfigure each bucket once; if more than once,<a name="line.348"></a>
+<span class="sourceLineNo">349</span> // we know there's a bug, so we just log the info, throw, and start again...<a name="line.349"></a>
+<span class="sourceLineNo">350</span> boolean[] reconfigured = new boolean[buckets.length];<a name="line.350"></a>
+<span class="sourceLineNo">351</span> int sizeNotMatchedCount = 0;<a name="line.351"></a>
+<span class="sourceLineNo">352</span> int insufficientCapacityCount = 0;<a name="line.352"></a>
+<span class="sourceLineNo">353</span> Iterator<Map.Entry<BlockCacheKey, BucketEntry>> iterator = map.entrySet().iterator();<a name="line.353"></a>
+<span class="sourceLineNo">354</span> while (iterator.hasNext()) {<a name="line.354"></a>
+<span class="sourceLineNo">355</span> Map.Entry<BlockCacheKey, BucketEntry> entry = iterator.next();<a name="line.355"></a>
+<span class="sourceLineNo">356</span> long foundOffset = entry.getValue().offset();<a name="line.356"></a>
+<span class="sourceLineNo">357</span> int foundLen = entry.getValue().getLength();<a name="line.357"></a>
+<span class="sourceLineNo">358</span> int bucketSizeIndex = -1;<a name="line.358"></a>
+<span class="sourceLineNo">359</span> for (int i = 0; i < this.bucketSizes.length; ++i) {<a name="line.359"></a>
+<span class="sourceLineNo">360</span> if (foundLen <= this.bucketSizes[i]) {<a name="line.360"></a>
+<span class="sourceLineNo">361</span> bucketSizeIndex = i;<a name="line.361"></a>
+<span class="sourceLineNo">362</span> break;<a name="line.362"></a>
+<span class="sourceLineNo">363</span> }<a name="line.363"></a>
+<span class="sourceLineNo">364</span> }<a name="line.364"></a>
+<span class="sourceLineNo">365</span> if (bucketSizeIndex == -1) {<a name="line.365"></a>
+<span class="sourceLineNo">366</span> sizeNotMatchedCount++;<a name="line.366"></a>
+<span class="sourceLineNo">367</span> iterator.remove();<a name="line.367"></a>
+<span class="sourceLineNo">368</span> continue;<a name="line.368"></a>
+<span class="sourceLineNo">369</span> }<a name="line.369"></a>
+<span class="sourceLineNo">370</span> int bucketNo = (int) (foundOffset / bucketCapacity);<a name="line.370"></a>
+<span class="sourceLineNo">371</span> if (bucketNo < 0 || bucketNo >= buckets.length) {<a name="line.371"></a>
+<span class="sourceLineNo">372</span> insufficientCapacityCount++;<a name="line.372"></a>
+<span class="sourceLineNo">373</span> iterator.remove();<a name="line.373"></a>
+<span class="sourceLineNo">374</span> continue;<a name="line.374"></a>
+<span class="sourceLineNo">375</span> }<a name="line.375"></a>
+<span class="sourceLineNo">376</span> Bucket b = buckets[bucketNo];<a name="line.376"></a>
+<span class="sourceLineNo">377</span> if (reconfigured[bucketNo]) {<a name="line.377"></a>
+<span class="sourceLineNo">378</span> if (b.sizeIndex() != bucketSizeIndex) {<a name="line.378"></a>
+<span class="sourceLineNo">379</span> throw new BucketAllocatorException("Inconsistent allocation in bucket map;");<a name="line.379"></a>
+<span class="sourceLineNo">380</span> }<a name="line.380"></a>
+<span class="sourceLineNo">381</span> } else {<a name="line.381"></a>
+<span class="sourceLineNo">382</span> if (!b.isCompletelyFree()) {<a name="line.382"></a>
+<span class="sourceLineNo">383</span> throw new BucketAllocatorException(<a name="line.383"></a>
+<span class="sourceLineNo">384</span> "Reconfiguring bucket " + bucketNo + " but it's already allocated; corrupt data");<a name="line.384"></a>
+<span class="sourceLineNo">385</span> }<a name="line.385"></a>
+<span class="sourceLineNo">386</span> // Need to remove the bucket from whichever list it's currently in at<a name="line.386"></a>
+<span class="sourceLineNo">387</span> // the moment...<a name="line.387"></a>
+<span class="sourceLineNo">388</span> BucketSizeInfo bsi = bucketSizeInfos[bucketSizeIndex];<a name="line.388"></a>
+<span class="sourceLineNo">389</span> BucketSizeInfo oldbsi = bucketSizeInfos[b.sizeIndex()];<a name="line.389"></a>
+<span class="sourceLineNo">390</span> oldbsi.removeBucket(b);<a name="line.390"></a>
+<span class="sourceLineNo">391</span> bsi.instantiateBucket(b);<a name="line.391"></a>
+<span class="sourceLineNo">392</span> reconfigured[bucketNo] = true;<a name="line.392"></a>
+<span class="sourceLineNo">393</span> }<a name="line.393"></a>
+<span class="sourceLineNo">394</span> realCacheSize.add(foundLen);<a name="line.394"></a>
+<span class="sourceLineNo">395</span> buckets[bucketNo].addAllocation(foundOffset);<a name="line.395"></a>
+<span class="sourceLineNo">396</span> usedSize += buckets[bucketNo].getItemAllocationSize();<a name="line.396"></a>
+<span class="sourceLineNo">397</span> bucketSizeInfos[bucketSizeIndex].blockAllocated(b);<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> if (sizeNotMatchedCount > 0) {<a name="line.400"></a>
+<span class="sourceLineNo">401</span> LOG.warn("There are " + sizeNotMatchedCount + " blocks which can't be rebuilt because " +<a name="line.401"></a>
+<span class="sourceLineNo">402</span> "there is no matching bucket size for these blocks");<a name="line.402"></a>
+<span class="sourceLineNo">403</span> }<a name="line.403"></a>
+<span class="sourceLineNo">404</span> if (insufficientCapacityCount > 0) {<a name="line.404"></a>
+<span class="sourceLineNo">405</span> LOG.warn("There are " + insufficientCapacityCount + " blocks which can't be rebuilt - "<a name="line.405"></a>
+<span class="sourceLineNo">406</span> + "did you shrink the cache?");<a name="line.406"></a>
+<span class="sourceLineNo">407</span> }<a name="line.407"></a>
+<span class="sourceLineNo">408</span> }<a name="line.408"></a>
+<span class="sourceLineNo">409</span><a name="line.409"></a>
+<span class="sourceLineNo">410</span> @Override<a name="line.410"></a>
+<span class="sourceLineNo">411</span> public String toString() {<a name="line.411"></a>
+<span class="sourceLineNo">412</span> StringBuilder sb = new StringBuilder(1024);<a name="line.412"></a>
+<span class="sourceLineNo">413</span> for (int i = 0; i < buckets.length; ++i) {<a name="line.413"></a>
+<span class="sourceLineNo">414</span> Bucket b = buckets[i];<a name="line.414"></a>
+<span class="sourceLineNo">415</span> if (i > 0) sb.append(", ");<a name="line.415"></a>
+<span class="sourceLineNo">416</span> sb.append("bucket.").append(i).append(": size=").append(b.getItemAllocationSize());<a name="line.416"></a>
+<span class="sourceLineNo">417</span> sb.append(", freeCount=").append(b.freeCount()).append(", used=").append(b.usedCount());<a name="line.417"></a>
+<span class="sourceLineNo">418</span> }<a name="line.418"></a>
+<span class="sourceLineNo">419</span> return sb.toString();<a name="line.419"></a>
+<span class="sourceLineNo">420</span> }<a name="line.420"></a>
+<span class="sourceLineNo">421</span><a name="line.421"></a>
+<span class="sourceLineNo">422</span> public long getUsedSize() {<a name="line.422"></a>
+<span class="sourceLineNo">423</span> return this.usedSize;<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> public long getFreeSize() {<a name="line.426"></a>
+<span class="sourceLineNo">427</span> return this.totalSize - getUsedSize();<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> public long getTotalSize() {<a name="line.430"></a>
+<span class="sourceLineNo">431</span> return this.totalSize;<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> * Allocate a block with specified size. Return the offset<a name="line.435"></a>
+<span class="sourceLineNo">436</span> * @param blockSize size of block<a name="line.436"></a>
+<span class="sourceLineNo">437</span> * @throws BucketAllocatorException<a name="line.437"></a>
+<span class="sourceLineNo">438</span> * @throws CacheFullException<a name="line.438"></a>
+<span class="sourceLineNo">439</span> * @return the offset in the IOEngine<a name="line.439"></a>
+<span class="sourceLineNo">440</span> */<a name="line.440"></a>
+<span class="sourceLineNo">441</span> public synchronized long allocateBlock(int blockSize) throws CacheFullException,<a name="line.441"></a>
+<span class="sourceLineNo">442</span> BucketAllocatorException {<a name="line.442"></a>
+<span class="sourceLineNo">443</span> assert blockSize > 0;<a name="line.443"></a>
+<span class="sourceLineNo">444</span> BucketSizeInfo bsi = roundUpToBucketSizeInfo(blockSize);<a name="line.444"></a>
+<span class="sourceLineNo">445</span> if (bsi == null) {<a name="line.445"></a>
+<span class="sourceLineNo">446</span> throw new BucketAllocatorException("Allocation too big size=" + blockSize +<a name="line.446"></a>
+<span class="sourceLineNo">447</span> "; adjust BucketCache sizes " + BlockCacheFactory.BUCKET_CACHE_BUCKETS_KEY +<a name="line.447"></a>
+<span class="sourceLineNo">448</span> " to accomodate if size seems reasonable and you want it cached.");<a name="line.448"></a>
+<span class="sourceLineNo">449</span> }<a name="line.449"></a>
+<span class="sourceLineNo">450</span> long offset = bsi.allocateBlock();<a name="line.450"></a>
+<span class="sourceLineNo">451</span><a name="line.451"></a>
+<span class="sourceLineNo">452</span> // Ask caller to free up space and try again!<a name="line.452"></a>
+<span class="sourceLineNo">453</span> if (offset < 0)<a name="line.453"></a>
+<span class="sourceLineNo">454</span> throw new CacheFullException(blockSize, bsi.sizeIndex());<a name="line.454"></a>
+<span class="sourceLineNo">455</span> usedSize += bucketSizes[bsi.sizeIndex()];<a name="line.455"></a>
+<span class="sourceLineNo">456</span> return offset;<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> private Bucket grabGlobalCompletelyFreeBucket() {<a name="line.459"></a>
+<span class="sourceLineNo">460</span> for (BucketSizeInfo bsi : bucketSizeInfos) {<a name="line.460"></a>
+<span class="sourceLineNo">461</span> Bucket b = bsi.findAndRemoveCompletelyFreeBucket();<a name="line.461"></a>
+<span class="sourceLineNo">462</span> if (b != null) return b;<a name="line.462"></a>
+<span class="sourceLineNo">463</span> }<a name="line.463"></a>
+<span class="sourceLineNo">464</span> return null;<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> * Free a block with the offset<a name="line.468"></a>
+<span class="sourceLineNo">469</span> * @param offset block's offset<a name="line.469"></a>
+<span class="sourceLineNo">470</span> * @return size freed<a name="line.470"></a>
+<span class="sourceLineNo">471</span> */<a name="line.471"></a>
+<span class="sourceLineNo">472</span> public synchronized int freeBlock(long offset) {<a name="line.472"></a>
+<span class="sourceLineNo">473</span> int bucketNo = (int) (offset / bucketCapacity);<a name="line.473"></a>
+<span class="sourceLineNo">474</span> assert bucketNo >= 0 && bucketNo < buckets.length;<a name="line.474"></a>
+<span class="sourceLineNo">475</span> Bucket targetBucket = buckets[bucketNo];<a name="line.475"></a>
+<span class="sourceLineNo">476</span> bucketSizeInfos[targetBucket.sizeIndex()].freeBlock(targetBucket, offset);<a name="line.476"></a>
+<span class="sourceLineNo">477</span> usedSize -= targetBucket.getItemAllocationSize();<a name="line.477"></a>
+<span class="sourceLineNo">478</span> return targetBucket.getItemAllocationSize();<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> public int sizeIndexOfAllocation(long offset) {<a name="line.481"></a>
+<span class="sourceLineNo">482</span> int bucketNo = (int) (offset / bucketCapacity);<a name="line.482"></a>
+<span class="sourceLineNo">483</span> assert bucketNo >= 0 && bucketNo < buckets.length;<a name="line.483"></a>
+<span class="sourceLineNo">484</span> Bucket targetBucket = buckets[bucketNo];<a name="line.484"></a>
+<span class="sourceLineNo">485</span> return targetBucket.sizeIndex();<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> public int sizeOfAllocation(long offset) {<a name="line.488"></a>
+<span class="sourceLineNo">489</span> int bucketNo = (int) (offset / bucketCapacity);<a name="line.489"></a>
+<span class="sourceLineNo">490</span> assert bucketNo >= 0 && bucketNo < buckets.length;<a name="line.490"></a>
+<span class="sourceLineNo">491</span> Bucket targetBucket = buckets[bucketNo];<a name="line.491"></a>
+<span class="sourceLineNo">492</span> return targetBucket.getItemAllocationSize();<a name="line.492"></a>
+<span class="sourceLineNo">493</span> }<a name="line.493"></a>
+<span class="sourceLineNo">494</span><a name="line.494"></a>
+<span class="sourceLineNo">495</span> static class IndexStatistics {<a name="line.495"></a>
+<span class="sourceLineNo">496</span> private long freeCount, usedCount, itemSize, totalCount;<a name="line.496"></a>
+<span class="sourceLineNo">497</span><a name="line.497"></a>
+<span class="sourceLineNo">498</span> public long freeCount() {<a name="line.498"></a>
+<span class="sourceLineNo">499</span> return freeCount;<a name="line.499"></a>
+<span class="sourceLineNo">500</span> }<a name="line.500"></a>
+<span class="sourceLineNo">501</span><a name="line.501"></a>
+<span class="sourceLineNo">502</span> public long usedCount() {<a name="line.502"></a>
+<span class="sourceLineNo">503</span> return usedCount;<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> public long totalCount() {<a name="line.506"></a>
+<span class="sourceLineNo">507</span> return totalCount;<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> public long freeBytes() {<a name="line.510"></a>
+<span class="sourceLineNo">511</span> return freeCount * itemSize;<a name="line.511"></a>
+<span class="sourceLineNo">512</span> }<a name="line.512"></a>
+<span class="sourceLineNo">513</span><a name="line.513"></a>
+<span class="sourceLineNo">514</span> public long usedBytes() {<a name="line.514"></a>
+<span class="sourceLineNo">515</span> return usedCount * itemSize;<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> public long totalBytes() {<a name="line.518"></a>
+<span class="sourceLineNo">519</span> return totalCount * itemSize;<a name="line.519"></a>
+<span class="sourceLineNo">520</span> }<a name="line.520"></a>
+<span class="sourceLineNo">521</span><a name="line.521"></a>
+<span class="sourceLineNo">522</span> public long itemSize() {<a name="line.522"></a>
+<span class="sourceLineNo">523</span> return itemSize;<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> public IndexStatistics(long free, long used, long itemSize) {<a name="line.526"></a>
+<span class="sourceLineNo">527</span> setTo(free, used, itemSize);<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> public IndexStatistics() {<a name="line.530"></a>
+<span class="sourceLineNo">531</span> setTo(-1, -1, 0);<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> public void setTo(long free, long used, long itemSize) {<a name="line.534"></a>
+<span class="sourceLineNo">535</span> this.itemSize = itemSize;<a name="line.535"></a>
+<span class="sourceLineNo">536</span> this.freeCount = free;<a name="line.536"></a>
+<span class="sourceLineNo">537</span> this.usedCount = used;<a name="line.537"></a>
+<span class="sourceLineNo">538</span> this.totalCount = free + used;<a name="line.538"></a>
+<span class="sourceLineNo">539</span> }<a name="line.539"></a>
+<span class="sourceLineNo">540</span> }<a name="line.540"></a>
+<span class="sourceLineNo">541</span><a name="line.541"></a>
+<span class="sourceLineNo">542</span> public Bucket [] getBuckets() {<a name="line.542"></a>
+<span class="sourceLineNo">543</span> return this.buckets;<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> void logStatistics() {<a name="line.546"></a>
+<span class="sourceLineNo">547</span> IndexStatistics total = new IndexStatistics();<a name="line.547"></a>
+<span class="sourceLineNo">548</span> IndexStatistics[] stats = getIndexStatistics(total);<a name="line.548"></a>
+<span class="sourceLineNo">549</span> LOG.info("Bucket allocator statistics follow:\n");<a name="line.549"></a>
+<span class="sourceLineNo">550</span> LOG.info(" Free bytes=" + total.freeBytes() + "+; used bytes="<a name="line.550"></a>
+<span class="sourceLineNo">551</span> + total.usedBytes() + "; total bytes=" + total.totalBytes());<a name="line.551"></a>
+<span class="sourceLineNo">552</span> for (IndexStatistics s : stats) {<a name="line.552"></a>
+<span class="sourceLineNo">553</span> LOG.info(" Object size " + s.itemSize() + " used=" + s.usedCount()<a name="line.553"></a>
+<span class="sourceLineNo">554</span> + "; free=" + s.freeCount() + "; total=" + s.totalCount());<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><a name="line.557"></a>
+<span class="sourceLineNo">558</span> IndexStatistics[] getIndexStatistics(IndexStatistics grandTotal) {<a name="line.558"></a>
+<span class="sourceLineNo">559</span> IndexStatistics[] stats = getIndexStatistics();<a name="line.559"></a>
+<span class="sourceLineNo">560</span> long totalfree = 0, totalused = 0;<a name="line.560"></a>
+<span class="sourceLineNo">561</span> for (IndexStatistics stat : stats) {<a name="line.561"></a>
+<span class="sourceLineNo">562</span> totalfree += stat.freeBytes();<a name="line.562"></a>
+<span class="sourceLineNo">563</span> totalused += stat.usedBytes();<a name="line.563"></a>
+<span class="sourceLineNo">564</span> }<a name="line.564"></a>
+<span class="sourceLineNo">565</span> grandTotal.setTo(totalfree, totalused, 1);<a name="line.565"></a>
+<span class="sourceLineNo">566</span> return stats;<a name="line.566"></a>
+<span class="sourceLineNo">567</span> }<a name="line.567"></a>
+<span class="sourceLineNo">568</span><a name="line.568"></a>
+<span class="sourceLineNo">569</span> IndexStatistics[] getIndexStatistics() {<a name="line.569"></a>
+<span class="sourceLineNo">570</span> IndexStatistics[] stats = new IndexStatistics[bucketSizes.length];<a name="line.570"></a>
+<span class="sourceLineNo">571</span> for (int i = 0; i < stats.length; ++i)<a name="line.571"></a>
+<span class="sourceLineNo">572</span> stats[i] = bucketSizeInfos[i].statistics();<a name="line.572"></a>
+<span class="sourceLineNo">573</span> return stats;<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> public long freeBlock(long freeList[]) {<a name="line.576"></a>
+<span class="sourceLineNo">577</span> long sz = 0;<a name="line.577"></a>
+<span class="sourceLineNo">578</span> for (int i = 0; i < freeList.length; ++i)<a name="line.578"></a>
+<span class="sourceLineNo">579</span> sz += freeBlock(freeList[i]);<a name="line.579"></a>
+<span class="sourceLineNo">580</span> return sz;<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> public int getBucketIndex(long offset) {<a name="line.583"></a>
+<span class="sourceLineNo">584</span> return (int) (offset / bucketCapacity);<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> /**<a name="line.587"></a>
+<span class="sourceLineNo">588</span> * Returns a set of indices of the buckets that are least filled<a name="line.588"></a>
+<span class="sourceLineNo">589</span> * excluding the offsets, we also the fully free buckets for the<a name="line.589"></a>
+<span class="sourceLineNo">590</span> * BucketSizes where everything is empty and they only have one<a name="line.590"></a>
+<span class="sourceLineNo">591</span> * completely free bucket as a reserved<a name="line.591"></a>
+<span class="sourceLineNo">592</span> *<a name="line.592"></a>
+<span class="sourceLineNo">593</span> * @param excludedBuckets the buckets that need to be excluded due to<a name="line.593"></a>
+<span class="sourceLineNo">594</span> * currently being in used<a name="line.594"></a>
+<span class="sourceLineNo">595</span> * @param bucketCount max Number of buckets to return<a name="line.595"></a>
+<span class="sourceLineNo">596</span> * @return set of bucket indices which could be used for eviction<a name="line.596"></a>
+<span class="sourceLineNo">597</span> */<a name="line.597"></a>
+<span class="sourceLineNo">598</span> public Set<Integer> getLeastFilledBuckets(Set<Integer> excludedBuckets,<a name="line.598"></a>
+<span class="sourceLineNo">599</span> int bucketCount) {<a name="line.599"></a>
+<span class="sourceLineNo">600</span> Queue<Integer> queue = MinMaxPriorityQueue.<Integer>orderedBy(<a name="line.600"></a>
+<span class="sourceLineNo">601</span> new Comparator<Integer>() {<a name="line.601"></a>
+<span class="sourceLineNo">602</span> @Override<a name="line.602"></a>
+<span class="sourceLineNo">603</span> public int compare(Integer left, Integer right) {<a name="line.603"></a>
+<span class="sourceLineNo">604</span> // We will always get instantiated buckets<a name="line.604"></a>
+<span class="sourceLineNo">605</span> return Float.compare(<a name="line.605"></a>
+<span class="sourceLineNo">606</span> ((float) buckets[left].usedCount) / buckets[left].itemCount,<a name="line.606"></a>
+<span class="sourceLineNo">607</span> ((float) buckets[right].usedCount) / buckets[right].itemCount);<a name="line.607"></a>
+<span class="sourceLineNo">608</span> }<a name="line.608"></a>
+<span class="sourceLineNo">609</span> }).maximumSize(bucketCount).create();<a name="line.609"></a>
+<span class="sourceLineNo">610</span><a name="line.610"></a>
+<span class="sourceLineNo">611</span> for (int i = 0; i < buckets.length; i ++ ) {<a name="line.611"></a>
+<span class="sourceLineNo">612</span> if (!excludedBuckets.contains(i) && !buckets[i].isUninstantiated() &&<a name="line.612"></a>
+<span class="sourceLineNo">613</span> // Avoid the buckets that are the only buckets for a sizeIndex<a name="line.613"></a>
+<span class="sourceLineNo">614</span> bucketSizeInfos[buckets[i].sizeIndex()].bucketList.size() != 1) {<a name="line.614"></a>
+<span class="sourceLineNo">615</span> queue.add(i);<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><a name="line.618"></a>
+<span class="sourceLineNo">619</span> Set<Integer> result = new HashSet<>(bucketCount);<a name="line.619"></a>
+<span class="sourceLineNo">620</span> result.addAll(queue);<a name="line.620"></a>
+<span class="sourceLineNo">621</span><a name="line.621"></a>
+<span class="sourceLineNo">622</span> return result;<a name="line.622"></a>
+<span class="sourceLineNo">623</span> }<a name="line.623"></a>
+<span class="sourceLineNo">624</span>}<a name="line.624"></a>
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/security/AbstractHBaseSaslRpcClient.html b/devapidocs/src-html/org/apache/hadoop/hbase/security/AbstractHBaseSaslRpcClient.html
index 3189932..7e4176b 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/security/AbstractHBaseSaslRpcClient.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/security/AbstractHBaseSaslRpcClient.html
@@ -97,38 +97,32 @@
<span class="sourceLineNo">089</span> }<a name="line.89"></a>
<span class="sourceLineNo">090</span><a name="line.90"></a>
<span class="sourceLineNo">091</span> /**<a name="line.91"></a>
-<span class="sourceLineNo">092</span> * Computes the initial response a client sends to a server to begin the SASL<a name="line.92"></a>
-<span class="sourceLineNo">093</span> * challenge/response handshake. If the client's SASL mechanism does not require<a name="line.93"></a>
-<span class="sourceLineNo">094</span> * that an initial response is sent to begin the handshake, this method will return<a name="line.94"></a>
-<span class="sourceLineNo">095</span> * a null byte array, indicating no initial response needs to be sent by this client.<a name="line.95"></a>
-<span class="sourceLineNo">096</span> *<a name="line.96"></a>
-<span class="sourceLineNo">097</span> * It is unclear as to whether all SASL implementations will return a non-empty initial<a name="line.97"></a>
-<span class="sourceLineNo">098</span> * response, so this implementation is written such that this is allowed. All known<a name="line.98"></a>
-<span class="sourceLineNo">099</span> * SASL mechanism implementations in the JDK provide non-empty initial responses.<a name="line.99"></a>
-<span class="sourceLineNo">100</span> *<a name="line.100"></a>
-<span class="sourceLineNo">101</span> * @return The client's initial response to send the server (which may be empty), or null<a name="line.101"></a>
-<span class="sourceLineNo">102</span> * if this implementation does not require an initial response to be sent.<a name="line.102"></a>
-<span class="sourceLineNo">103</span> */<a name="line.103"></a>
-<span class="sourceLineNo">104</span> public byte[] getInitialResponse() throws SaslException {<a name="line.104"></a>
-<span class="sourceLineNo">105</span> if (saslClient.hasInitialResponse()) {<a name="line.105"></a>
-<span class="sourceLineNo">106</span> return saslClient.evaluateChallenge(EMPTY_TOKEN);<a name="line.106"></a>
-<span class="sourceLineNo">107</span> }<a name="line.107"></a>
-<span class="sourceLineNo">108</span> return null;<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> public boolean isComplete() {<a name="line.111"></a>
-<span class="sourceLineNo">112</span> return saslClient.isComplete();<a name="line.112"></a>
-<span class="sourceLineNo">113</span> }<a name="line.113"></a>
-<span class="sourceLineNo">114</span><a name="line.114"></a>
-<span class="sourceLineNo">115</span> public byte[] evaluateChallenge(byte[] challenge) throws SaslException {<a name="line.115"></a>
-<span class="sourceLineNo">116</span> return saslClient.evaluateChallenge(challenge);<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> /** Release resources used by wrapped saslClient */<a name="line.119"></a>
-<span class="sourceLineNo">120</span> public void dispose() {<a name="line.120"></a>
-<span class="sourceLineNo">121</span> SaslUtil.safeDispose(saslClient);<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">092</span> * Computes the initial response a client sends to a server to begin the SASL challenge/response<a name="line.92"></a>
+<span class="sourceLineNo">093</span> * handshake. If the client's SASL mechanism does not have an initial response, an empty token<a name="line.93"></a>
+<span class="sourceLineNo">094</span> * will be returned without querying the evaluateChallenge method, as an authentication processing<a name="line.94"></a>
+<span class="sourceLineNo">095</span> * must be started by client.<a name="line.95"></a>
+<span class="sourceLineNo">096</span> * @return The client's initial response to send the server (which may be empty).<a name="line.96"></a>
+<span class="sourceLineNo">097</span> */<a name="line.97"></a>
+<span class="sourceLineNo">098</span> public byte[] getInitialResponse() throws SaslException {<a name="line.98"></a>
+<span class="sourceLineNo">099</span> if (saslClient.hasInitialResponse()) {<a name="line.99"></a>
+<span class="sourceLineNo">100</span> return saslClient.evaluateChallenge(EMPTY_TOKEN);<a name="line.100"></a>
+<span class="sourceLineNo">101</span> }<a name="line.101"></a>
+<span class="sourceLineNo">102</span> return EMPTY_TOKEN;<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> public boolean isComplete() {<a name="line.105"></a>
+<span class="sourceLineNo">106</span> return saslClient.isComplete();<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> public byte[] evaluateChallenge(byte[] challenge) throws SaslException {<a name="line.109"></a>
+<span class="sourceLineNo">110</span> return saslClient.evaluateChallenge(challenge);<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> /** Release resources used by wrapped saslClient */<a name="line.113"></a>
+<span class="sourceLineNo">114</span> public void dispose() {<a name="line.114"></a>
+<span class="sourceLineNo">115</span> SaslUtil.safeDispose(saslClient);<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>
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/security/NettyHBaseSaslRpcClientHandler.html b/devapidocs/src-html/org/apache/hadoop/hbase/security/NettyHBaseSaslRpcClientHandler.html
index de09133..a8bf835 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/security/NettyHBaseSaslRpcClientHandler.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/security/NettyHBaseSaslRpcClientHandler.html
@@ -127,71 +127,69 @@
<span class="sourceLineNo">119</span> return saslRpcClient.getInitialResponse();<a name="line.119"></a>
<span class="sourceLineNo">120</span> }<a name="line.120"></a>
<span class="sourceLineNo">121</span> });<a name="line.121"></a>
-<span class="sourceLineNo">122</span> if (initialResponse != null) {<a name="line.122"></a>
-<span class="sourceLineNo">123</span> writeResponse(ctx, initialResponse);<a name="line.123"></a>
-<span class="sourceLineNo">124</span> } else {<a name="line.124"></a>
-<span class="sourceLineNo">125</span> LOG.trace("SASL initialResponse was null, not sending response to server.");<a name="line.125"></a>
-<span class="sourceLineNo">126</span> }<a name="line.126"></a>
-<span class="sourceLineNo">127</span> // HBASE-23881 We do not want to check if the SaslClient thinks the handshake is<a name="line.127"></a>
-<span class="sourceLineNo">128</span> // complete as, at this point, we've not heard a back from the server with it's reply<a name="line.128"></a>
-<span class="sourceLineNo">129</span> // to our first challenge response. We should wait for at least one reply<a name="line.129"></a>
-<span class="sourceLineNo">130</span> // from the server before calling negotiation complete.<a name="line.130"></a>
-<span class="sourceLineNo">131</span> //<a name="line.131"></a>
-<span class="sourceLineNo">132</span> // Each SASL mechanism has its own handshake. Some mechanisms calculate a single client buffer<a name="line.132"></a>
-<span class="sourceLineNo">133</span> // to be sent to the server while others have multiple exchanges to negotiate authentication. GSSAPI(Kerberos)<a name="line.133"></a>
-<span class="sourceLineNo">134</span> // and DIGEST-MD5 both are examples of mechanisms which have multiple steps. Mechanisms which have multiple steps<a name="line.134"></a>
-<span class="sourceLineNo">135</span> // will not return true on `SaslClient#isComplete()` until the handshake has fully completed. Mechanisms which<a name="line.135"></a>
-<span class="sourceLineNo">136</span> // only send a single buffer may return true on `isComplete()` after that initial response is calculated.<a name="line.136"></a>
-<span class="sourceLineNo">137</span> } catch (Exception e) {<a name="line.137"></a>
-<span class="sourceLineNo">138</span> // the exception thrown by handlerAdded will not be passed to the exceptionCaught below<a name="line.138"></a>
-<span class="sourceLineNo">139</span> // because netty will remove a handler if handlerAdded throws an exception.<a name="line.139"></a>
-<span class="sourceLineNo">140</span> exceptionCaught(ctx, e);<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>
-<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> protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {<a name="line.145"></a>
-<span class="sourceLineNo">146</span> int len = msg.readInt();<a name="line.146"></a>
-<span class="sourceLineNo">147</span> if (len == SaslUtil.SWITCH_TO_SIMPLE_AUTH) {<a name="line.147"></a>
-<span class="sourceLineNo">148</span> saslRpcClient.dispose();<a name="line.148"></a>
-<span class="sourceLineNo">149</span> if (saslRpcClient.fallbackAllowed) {<a name="line.149"></a>
-<span class="sourceLineNo">150</span> saslPromise.trySuccess(false);<a name="line.150"></a>
-<span class="sourceLineNo">151</span> } else {<a name="line.151"></a>
-<span class="sourceLineNo">152</span> saslPromise.tryFailure(new FallbackDisallowedException());<a name="line.152"></a>
-<span class="sourceLineNo">153</span> }<a name="line.153"></a>
-<span class="sourceLineNo">154</span> return;<a name="line.154"></a>
-<span class="sourceLineNo">155</span> }<a name="line.155"></a>
-<span class="sourceLineNo">156</span> LOG.trace("Reading input token size={} for processing by initSASLContext", len);<a name="line.156"></a>
-<span class="sourceLineNo">157</span> final byte[] challenge = new byte[len];<a name="line.157"></a>
-<span class="sourceLineNo">158</span> msg.readBytes(challenge);<a name="line.158"></a>
-<span class="sourceLineNo">159</span> byte[] response = ugi.doAs(new PrivilegedExceptionAction<byte[]>() {<a name="line.159"></a>
-<span class="sourceLineNo">160</span><a name="line.160"></a>
-<span class="sourceLineNo">161</span> @Override<a name="line.161"></a>
-<span class="sourceLineNo">162</span> public byte[] run() throws Exception {<a name="line.162"></a>
-<span class="sourceLineNo">163</span> return saslRpcClient.evaluateChallenge(challenge);<a name="line.163"></a>
-<span class="sourceLineNo">164</span> }<a name="line.164"></a>
-<span class="sourceLineNo">165</span> });<a name="line.165"></a>
-<span class="sourceLineNo">166</span> if (response != null) {<a name="line.166"></a>
-<span class="sourceLineNo">167</span> writeResponse(ctx, response);<a name="line.167"></a>
-<span class="sourceLineNo">168</span> } else {<a name="line.168"></a>
-<span class="sourceLineNo">169</span> LOG.trace("SASL challenge response was empty, not sending response to server.");<a name="line.169"></a>
-<span class="sourceLineNo">170</span> }<a name="line.170"></a>
-<span class="sourceLineNo">171</span> tryComplete(ctx);<a name="line.171"></a>
-<span class="sourceLineNo">172</span> }<a name="line.172"></a>
-<span class="sourceLineNo">173</span><a name="line.173"></a>
-<span class="sourceLineNo">174</span> @Override<a name="line.174"></a>
-<span class="sourceLineNo">175</span> public void channelInactive(ChannelHandlerContext ctx) throws Exception {<a name="line.175"></a>
-<span class="sourceLineNo">176</span> saslRpcClient.dispose();<a name="line.176"></a>
-<span class="sourceLineNo">177</span> saslPromise.tryFailure(new ConnectionClosedException("Connection closed"));<a name="line.177"></a>
-<span class="sourceLineNo">178</span> ctx.fireChannelInactive();<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> @Override<a name="line.181"></a>
-<span class="sourceLineNo">182</span> public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {<a name="line.182"></a>
-<span class="sourceLineNo">183</span> saslRpcClient.dispose();<a name="line.183"></a>
-<span class="sourceLineNo">184</span> saslPromise.tryFailure(cause);<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">122</span> assert initialResponse != null;<a name="line.122"></a>
+<span class="sourceLineNo">123</span> writeResponse(ctx, initialResponse);<a name="line.123"></a>
+<span class="sourceLineNo">124</span> // HBASE-23881 We do not want to check if the SaslClient thinks the handshake is<a name="line.124"></a>
+<span class="sourceLineNo">125</span> // complete as, at this point, we've not heard a back from the server with it's reply<a name="line.125"></a>
+<span class="sourceLineNo">126</span> // to our first challenge response. We should wait for at least one reply<a name="line.126"></a>
+<span class="sourceLineNo">127</span> // from the server before calling negotiation complete.<a name="line.127"></a>
+<span class="sourceLineNo">128</span> //<a name="line.128"></a>
+<span class="sourceLineNo">129</span> // Each SASL mechanism has its own handshake. Some mechanisms calculate a single client buffer<a name="line.129"></a>
+<span class="sourceLineNo">130</span> // to be sent to the server while others have multiple exchanges to negotiate authentication.<a name="line.130"></a>
+<span class="sourceLineNo">131</span> // GSSAPI(Kerberos) and DIGEST-MD5 both are examples of mechanisms which have multiple steps.<a name="line.131"></a>
+<span class="sourceLineNo">132</span> // Mechanisms which have multiple steps will not return true on `SaslClient#isComplete()`<a name="line.132"></a>
+<span class="sourceLineNo">133</span> // until the handshake has fully completed. Mechanisms which only send a single buffer may<a name="line.133"></a>
+<span class="sourceLineNo">134</span> // return true on `isComplete()` after that initial response is calculated.<a name="line.134"></a>
+<span class="sourceLineNo">135</span> } catch (Exception e) {<a name="line.135"></a>
+<span class="sourceLineNo">136</span> // the exception thrown by handlerAdded will not be passed to the exceptionCaught below<a name="line.136"></a>
+<span class="sourceLineNo">137</span> // because netty will remove a handler if handlerAdded throws an exception.<a name="line.137"></a>
+<span class="sourceLineNo">138</span> exceptionCaught(ctx, e);<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> @Override<a name="line.142"></a>
+<span class="sourceLineNo">143</span> protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {<a name="line.143"></a>
+<span class="sourceLineNo">144</span> int len = msg.readInt();<a name="line.144"></a>
+<span class="sourceLineNo">145</span> if (len == SaslUtil.SWITCH_TO_SIMPLE_AUTH) {<a name="line.145"></a>
+<span class="sourceLineNo">146</span> saslRpcClient.dispose();<a name="line.146"></a>
+<span class="sourceLineNo">147</span> if (saslRpcClient.fallbackAllowed) {<a name="line.147"></a>
+<span class="sourceLineNo">148</span> saslPromise.trySuccess(false);<a name="line.148"></a>
+<span class="sourceLineNo">149</span> } else {<a name="line.149"></a>
+<span class="sourceLineNo">150</span> saslPromise.tryFailure(new FallbackDisallowedException());<a name="line.150"></a>
+<span class="sourceLineNo">151</span> }<a name="line.151"></a>
+<span class="sourceLineNo">152</span> return;<a name="line.152"></a>
+<span class="sourceLineNo">153</span> }<a name="line.153"></a>
+<span class="sourceLineNo">154</span> LOG.trace("Reading input token size={} for processing by initSASLContext", len);<a name="line.154"></a>
+<span class="sourceLineNo">155</span> final byte[] challenge = new byte[len];<a name="line.155"></a>
+<span class="sourceLineNo">156</span> msg.readBytes(challenge);<a name="line.156"></a>
+<span class="sourceLineNo">157</span> byte[] response = ugi.doAs(new PrivilegedExceptionAction<byte[]>() {<a name="line.157"></a>
+<span class="sourceLineNo">158</span><a name="line.158"></a>
+<span class="sourceLineNo">159</span> @Override<a name="line.159"></a>
+<span class="sourceLineNo">160</span> public byte[] run() throws Exception {<a name="line.160"></a>
+<span class="sourceLineNo">161</span> return saslRpcClient.evaluateChallenge(challenge);<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> if (response != null) {<a name="line.164"></a>
+<span class="sourceLineNo">165</span> writeResponse(ctx, response);<a name="line.165"></a>
+<span class="sourceLineNo">166</span> } else {<a name="line.166"></a>
+<span class="sourceLineNo">167</span> LOG.trace("SASL challenge response was empty, not sending response to server.");<a name="line.167"></a>
+<span class="sourceLineNo">168</span> }<a name="line.168"></a>
+<span class="sourceLineNo">169</span> tryComplete(ctx);<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> @Override<a name="line.172"></a>
+<span class="sourceLineNo">173</span> public void channelInactive(ChannelHandlerContext ctx) throws Exception {<a name="line.173"></a>
+<span class="sourceLineNo">174</span> saslRpcClient.dispose();<a name="line.174"></a>
+<span class="sourceLineNo">175</span> saslPromise.tryFailure(new ConnectionClosedException("Connection closed"));<a name="line.175"></a>
+<span class="sourceLineNo">176</span> ctx.fireChannelInactive();<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> @Override<a name="line.179"></a>
+<span class="sourceLineNo">180</span> public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {<a name="line.180"></a>
+<span class="sourceLineNo">181</span> saslRpcClient.dispose();<a name="line.181"></a>
+<span class="sourceLineNo">182</span> saslPromise.tryFailure(cause);<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>
diff --git a/downloads.html b/downloads.html
index 627fba2..1ca1d70 100644
--- a/downloads.html
+++ b/downloads.html
@@ -465,7 +465,7 @@
<div class="row">
<p>Copyright ©2007–2020
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-25</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-26</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/export_control.html b/export_control.html
index 562b268..7b4382b 100644
--- a/export_control.html
+++ b/export_control.html
@@ -197,7 +197,7 @@ for more details.</p>
<div class="row">
<p>Copyright ©2007–2020
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-25</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-26</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/index.html b/index.html
index c8eb3d6..f51a117 100644
--- a/index.html
+++ b/index.html
@@ -275,7 +275,7 @@
<div class="row">
<p>Copyright ©2007–2020
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-25</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-26</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/issue-tracking.html b/issue-tracking.html
index 24be858..a6425f4 100644
--- a/issue-tracking.html
+++ b/issue-tracking.html
@@ -169,7 +169,7 @@
<div class="row">
<p>Copyright ©2007–2020
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-25</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-26</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/mail-lists.html b/mail-lists.html
index 7443c24..c007552 100644
--- a/mail-lists.html
+++ b/mail-lists.html
@@ -229,7 +229,7 @@
<div class="row">
<p>Copyright ©2007–2020
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-25</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-26</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/metrics.html b/metrics.html
index d24d72f..9014ee5 100644
--- a/metrics.html
+++ b/metrics.html
@@ -325,7 +325,7 @@ export HBASE_REGIONSERVER_OPTS="$HBASE_JMX_OPTS -Dcom.sun.management.jmxrem
<div class="row">
<p>Copyright ©2007–2020
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-25</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-26</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/old_news.html b/old_news.html
index 459654c..61012fc 100644
--- a/old_news.html
+++ b/old_news.html
@@ -316,7 +316,7 @@
<div class="row">
<p>Copyright ©2007–2020
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-25</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-26</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/plugin-management.html b/plugin-management.html
index f2a786b..597d850 100644
--- a/plugin-management.html
+++ b/plugin-management.html
@@ -321,7 +321,7 @@
<div class="row">
<p>Copyright ©2007–2020
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-25</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-26</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/plugins.html b/plugins.html
index 51b020c..09167cd 100644
--- a/plugins.html
+++ b/plugins.html
@@ -248,7 +248,7 @@
<div class="row">
<p>Copyright ©2007–2020
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-25</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-26</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/poweredbyhbase.html b/poweredbyhbase.html
index 343d8c4..7f5cf63 100644
--- a/poweredbyhbase.html
+++ b/poweredbyhbase.html
@@ -650,7 +650,7 @@
<div class="row">
<p>Copyright ©2007–2020
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-25</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-26</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/project-info.html b/project-info.html
index dc4e25f..7e84730 100644
--- a/project-info.html
+++ b/project-info.html
@@ -210,7 +210,7 @@
<div class="row">
<p>Copyright ©2007–2020
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-25</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-26</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/project-reports.html b/project-reports.html
index 14ec730..250e47a 100644
--- a/project-reports.html
+++ b/project-reports.html
@@ -186,7 +186,7 @@
<div class="row">
<p>Copyright ©2007–2020
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-25</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-26</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/project-summary.html b/project-summary.html
index c049c05..07367de 100644
--- a/project-summary.html
+++ b/project-summary.html
@@ -212,7 +212,7 @@
<div class="row">
<p>Copyright ©2007–2020
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-25</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-26</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/pseudo-distributed.html b/pseudo-distributed.html
index ebe3c10..99d1b0b 100644
--- a/pseudo-distributed.html
+++ b/pseudo-distributed.html
@@ -174,7 +174,7 @@ Running Apache HBase (TM) in pseudo-distributed mode
<div class="row">
<p>Copyright ©2007–2020
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-25</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-26</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/replication.html b/replication.html
index 6c869b0..f666245 100644
--- a/replication.html
+++ b/replication.html
@@ -169,7 +169,7 @@
<div class="row">
<p>Copyright ©2007–2020
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-25</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-26</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/resources.html b/resources.html
index 93a8b7f..c8c5959 100644
--- a/resources.html
+++ b/resources.html
@@ -197,7 +197,7 @@
<div class="row">
<p>Copyright ©2007–2020
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-25</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-26</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/source-repository.html b/source-repository.html
index 64c980f..e73297f 100644
--- a/source-repository.html
+++ b/source-repository.html
@@ -180,7 +180,7 @@
<div class="row">
<p>Copyright ©2007–2020
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-25</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-26</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/sponsors.html b/sponsors.html
index 0728939..59c125a 100644
--- a/sponsors.html
+++ b/sponsors.html
@@ -199,7 +199,7 @@
<div class="row">
<p>Copyright ©2007–2020
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-25</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-26</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/supportingprojects.html b/supportingprojects.html
index efc562d..9a6e0fc 100644
--- a/supportingprojects.html
+++ b/supportingprojects.html
@@ -390,7 +390,7 @@
<div class="row">
<p>Copyright ©2007–2020
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-25</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-26</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/team-list.html b/team-list.html
index af45236..0e94b87 100644
--- a/team-list.html
+++ b/team-list.html
@@ -701,7 +701,7 @@
<div class="row">
<p>Copyright ©2007–2020
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-25</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2020-04-26</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>