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 2026/02/03 14:52:03 UTC
(hbase-site) branch asf-site updated: Published site at 4411cde5a83d265f65b8edcfdacab79cd391ddec.
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 55859c922e4 Published site at 4411cde5a83d265f65b8edcfdacab79cd391ddec.
55859c922e4 is described below
commit 55859c922e45e78eb7071978d62a91a0421774ef
Author: jenkins <bu...@apache.org>
AuthorDate: Tue Feb 3 14:51:36 2026 +0000
Published site at 4411cde5a83d265f65b8edcfdacab79cd391ddec.
---
apache_hbase_reference_guide.pdf | 4 +-
book.html | 2 +-
checkstyle-aggregate.html | 20 +-
dependency-convergence.html | 2 +-
dependency-info.html | 2 +-
dependency-management.html | 2 +-
.../hfile/bucket/BucketCache.BucketEntryGroup.html | 18 +-
.../io/hfile/bucket/BucketCache.RAMCache.html | 22 +-
.../io/hfile/bucket/BucketCache.RAMQueueEntry.html | 28 +-
.../hadoop/hbase/io/hfile/bucket/BucketCache.html | 104 +-
.../hfile/bucket/BucketCache.BucketEntryGroup.html | 1776 ++---
.../io/hfile/bucket/BucketCache.CacheState.html | 1776 ++---
.../io/hfile/bucket/BucketCache.RAMCache.html | 1776 ++---
.../io/hfile/bucket/BucketCache.RAMQueueEntry.html | 1776 ++---
.../hfile/bucket/BucketCache.StatisticsThread.html | 1776 ++---
.../io/hfile/bucket/BucketCache.WriterThread.html | 1776 ++---
.../hadoop/hbase/io/hfile/bucket/BucketCache.html | 1776 ++---
hbase-website/dependency-convergence.html | 2 +-
hbase-website/dependency-info.html | 2 +-
hbase-website/dependency-management.html | 2 +-
hbase-website/index.html | 2 +-
hbase-website/issue-management.html | 2 +-
hbase-website/licenses.html | 2 +-
hbase-website/mailing-lists.html | 2 +-
hbase-website/plugin-management.html | 2 +-
hbase-website/plugins.html | 2 +-
hbase-website/project-info.html | 2 +-
hbase-website/scm.html | 2 +-
hbase-website/summary.html | 2 +-
hbase-website/team.html | 2 +-
issue-management.html | 2 +-
licenses.html | 2 +-
mailing-lists.html | 2 +-
plugin-management.html | 2 +-
plugins.html | 2 +-
project-info.html | 2 +-
project-reports.html | 2 +-
scm.html | 2 +-
summary.html | 2 +-
team.html | 2 +-
testapidocs/index-all.html | 54 +-
testapidocs/member-search-index.js | 2 +-
.../hadoop/hbase/class-use/HBaseClassTestRule.html | 112 +-
.../class-use/HBaseParameterizedTestTemplate.html | 21 +-
.../org/apache/hadoop/hbase/package-use.html | 51 +-
.../org/apache/hadoop/hbase/rest/DummyFilter.html | 2 +-
.../apache/hadoop/hbase/rest/RowResourceBase.html | 18 +-
.../apache/hadoop/hbase/rest/TestDeleteRow.html | 203 +-
.../hadoop/hbase/rest/TestGZIPResponseWrapper.html | 172 +-
.../hadoop/hbase/rest/TestGetAndPutResource.html | 1504 ++--
.../apache/hadoop/hbase/rest/TestGzipFilter.html | 246 +-
.../hadoop/hbase/rest/TestMultiRowResource.html | 741 +-
.../hbase/rest/TestNamespacesInstanceResource.html | 843 ++-
.../hadoop/hbase/rest/TestNamespacesResource.html | 334 +-
.../hadoop/hbase/rest/TestRESTServerSSL.html | 362 +-
.../hadoop/hbase/rest/TestResourceFilter.html | 87 +-
.../hadoop/hbase/rest/TestScannerResource.html | 998 ++-
.../hadoop/hbase/rest/TestScannersWithFilters.html | 1931 +++--
.../hadoop/hbase/rest/TestScannersWithLabels.html | 424 +-
.../hadoop/hbase/rest/TestSchemaResource.html | 436 +-
.../hadoop/hbase/rest/TestSecureRESTServer.html | 807 +-
.../hbase/rest/TestSecurityHeadersFilter.html | 157 +-
.../hadoop/hbase/rest/TestStatusResource.html | 215 +-
.../hadoop/hbase/rest/TestTableResource.html | 464 +-
...tTableScan.ClientSideCellSetModel.Listener.html | 1324 ++--
.../rest/TestTableScan.ClientSideCellSetModel.html | 1324 ++--
.../hbase/rest/TestTableScan.CustomFilter.html | 1324 ++--
.../apache/hadoop/hbase/rest/TestTableScan.html | 1324 ++--
.../hadoop/hbase/rest/TestVersionResource.html | 328 +-
.../hbase/rest/client/TestRemoteAdminRetries.html | 276 +-
.../hbase/rest/client/TestRemoteHTableRetries.html | 322 +-
.../hadoop/hbase/rest/client/TestRemoteTable.html | 1457 ++--
.../hadoop/hbase/rest/client/TestXmlParsing.html | 125 +-
testdevapidocs/allclasses-index.html | 7793 ++++++++++----------
testdevapidocs/constant-values.html | 37 +
testdevapidocs/index-all.html | 117 +-
testdevapidocs/member-search-index.js | 2 +-
.../hadoop/hbase/class-use/HBaseClassTestRule.html | 192 +-
.../class-use/HBaseParameterizedTestTemplate.html | 21 +-
.../bucket/TestBucketCacheEmptyPersistence.html} | 158 +-
.../class-use/TestBucketCacheEmptyPersistence.html | 62 +
.../hbase/io/hfile/bucket/package-summary.html | 59 +-
.../hadoop/hbase/io/hfile/bucket/package-tree.html | 1 +
.../org/apache/hadoop/hbase/package-use.html | 16 +-
.../apache/hadoop/hbase/rest/RowResourceBase.html | 12 +-
.../apache/hadoop/hbase/rest/TestDeleteRow.html | 41 +-
.../hadoop/hbase/rest/TestGZIPResponseWrapper.html | 38 +-
.../hadoop/hbase/rest/TestGetAndPutResource.html | 113 +-
.../apache/hadoop/hbase/rest/TestGzipFilter.html | 73 +-
.../hadoop/hbase/rest/TestMultiRowResource.html | 138 +-
.../hbase/rest/TestNamespacesInstanceResource.html | 176 +-
.../hadoop/hbase/rest/TestNamespacesResource.html | 78 +-
.../hadoop/hbase/rest/TestRESTServerSSL.html | 105 +-
.../hadoop/hbase/rest/TestResourceFilter.html | 41 +-
.../hadoop/hbase/rest/TestScannerResource.html | 118 +-
.../hadoop/hbase/rest/TestScannersWithFilters.html | 154 +-
.../hadoop/hbase/rest/TestScannersWithLabels.html | 130 +-
.../hadoop/hbase/rest/TestSchemaResource.html | 99 +-
.../TestSecureRESTServer.EmptyCredentials.html | 10 +-
.../hadoop/hbase/rest/TestSecureRESTServer.html | 141 +-
.../hbase/rest/TestSecurityHeadersFilter.html | 41 +-
.../hadoop/hbase/rest/TestStatusResource.html | 61 +-
.../hadoop/hbase/rest/TestTableResource.html | 109 +-
...tTableScan.ClientSideCellSetModel.Listener.html | 4 +-
.../rest/TestTableScan.ClientSideCellSetModel.html | 12 +-
.../hbase/rest/TestTableScan.CustomFilter.html | 10 +-
.../apache/hadoop/hbase/rest/TestTableScan.html | 130 +-
.../hadoop/hbase/rest/TestVersionResource.html | 71 +-
.../TestRemoteAdminRetries.CallExecutor.html | 4 +-
.../hbase/rest/client/TestRemoteAdminRetries.html | 76 +-
.../TestRemoteHTableRetries.CallExecutor.html | 4 +-
.../hbase/rest/client/TestRemoteHTableRetries.html | 105 +-
.../hadoop/hbase/rest/client/TestRemoteTable.html | 170 +-
.../hadoop/hbase/rest/client/TestXmlParsing.html | 26 +-
.../hadoop/hbase/rest/model/TestCellModel.html | 51 +-
.../hadoop/hbase/rest/model/TestCellSetModel.html | 77 +-
.../hbase/rest/model/TestColumnSchemaModel.html | 3 +-
.../hadoop/hbase/rest/model/TestModelBase.html | 18 +-
.../rest/model/TestNamespacesInstanceModel.html | 43 +-
.../hbase/rest/model/TestNamespacesModel.html | 41 +-
.../hadoop/hbase/rest/model/TestRowModel.html | 48 +-
.../hadoop/hbase/rest/model/TestScannerModel.html | 99 +-
.../rest/model/TestStorageClusterStatusModel.html | 34 +-
.../rest/model/TestStorageClusterVersionModel.html | 27 +-
.../hbase/rest/model/TestTableInfoModel.html | 57 +-
.../hbase/rest/model/TestTableListModel.html | 32 +-
.../hbase/rest/model/TestTableRegionModel.html | 57 +-
.../hbase/rest/model/TestTableSchemaModel.html | 56 +-
.../hadoop/hbase/rest/model/TestVersionModel.html | 48 +-
testdevapidocs/overview-tree.html | 1 +
.../bucket/TestBucketCacheEmptyPersistence.html | 243 +
.../org/apache/hadoop/hbase/rest/DummyFilter.html | 2 +-
.../apache/hadoop/hbase/rest/RowResourceBase.html | 18 +-
.../apache/hadoop/hbase/rest/TestDeleteRow.html | 203 +-
.../hadoop/hbase/rest/TestGZIPResponseWrapper.html | 172 +-
.../hadoop/hbase/rest/TestGetAndPutResource.html | 1504 ++--
.../apache/hadoop/hbase/rest/TestGzipFilter.html | 246 +-
.../hadoop/hbase/rest/TestMultiRowResource.html | 741 +-
.../hbase/rest/TestNamespacesInstanceResource.html | 843 ++-
.../hadoop/hbase/rest/TestNamespacesResource.html | 334 +-
.../hadoop/hbase/rest/TestRESTServerSSL.html | 362 +-
.../hadoop/hbase/rest/TestResourceFilter.html | 87 +-
.../hadoop/hbase/rest/TestScannerResource.html | 998 ++-
.../hadoop/hbase/rest/TestScannersWithFilters.html | 1931 +++--
.../hadoop/hbase/rest/TestScannersWithLabels.html | 424 +-
.../hadoop/hbase/rest/TestSchemaResource.html | 436 +-
.../TestSecureRESTServer.EmptyCredentials.html | 807 +-
.../hadoop/hbase/rest/TestSecureRESTServer.html | 807 +-
.../hbase/rest/TestSecurityHeadersFilter.html | 157 +-
.../hadoop/hbase/rest/TestStatusResource.html | 215 +-
.../hadoop/hbase/rest/TestTableResource.html | 464 +-
...tTableScan.ClientSideCellSetModel.Listener.html | 1324 ++--
.../rest/TestTableScan.ClientSideCellSetModel.html | 1324 ++--
.../hbase/rest/TestTableScan.CustomFilter.html | 1324 ++--
.../apache/hadoop/hbase/rest/TestTableScan.html | 1324 ++--
.../hadoop/hbase/rest/TestVersionResource.html | 328 +-
.../TestRemoteAdminRetries.CallExecutor.html | 276 +-
.../hbase/rest/client/TestRemoteAdminRetries.html | 276 +-
.../TestRemoteHTableRetries.CallExecutor.html | 322 +-
.../hbase/rest/client/TestRemoteHTableRetries.html | 322 +-
.../hadoop/hbase/rest/client/TestRemoteTable.html | 1457 ++--
.../hadoop/hbase/rest/client/TestXmlParsing.html | 125 +-
.../hadoop/hbase/rest/model/TestCellModel.html | 166 +-
.../hadoop/hbase/rest/model/TestCellSetModel.html | 222 +-
.../hbase/rest/model/TestColumnSchemaModel.html | 24 +-
.../hadoop/hbase/rest/model/TestModelBase.html | 4 +-
.../rest/model/TestNamespacesInstanceModel.html | 157 +-
.../hbase/rest/model/TestNamespacesModel.html | 131 +-
.../hadoop/hbase/rest/model/TestRowModel.html | 149 +-
.../hadoop/hbase/rest/model/TestScannerModel.html | 367 +-
.../rest/model/TestStorageClusterStatusModel.html | 253 +-
.../rest/model/TestStorageClusterVersionModel.html | 75 +-
.../hbase/rest/model/TestTableInfoModel.html | 146 +-
.../hbase/rest/model/TestTableListModel.html | 91 +-
.../hbase/rest/model/TestTableRegionModel.html | 141 +-
.../hbase/rest/model/TestTableSchemaModel.html | 186 +-
.../hadoop/hbase/rest/model/TestVersionModel.html | 123 +-
testdevapidocs/type-search-index.js | 2 +-
178 files changed, 31766 insertions(+), 31977 deletions(-)
diff --git a/apache_hbase_reference_guide.pdf b/apache_hbase_reference_guide.pdf
index aca9722a91e..58ab8538c66 100644
--- a/apache_hbase_reference_guide.pdf
+++ b/apache_hbase_reference_guide.pdf
@@ -5,8 +5,8 @@
/Author (Apache HBase Team)
/Creator (Asciidoctor PDF 2.0.6, based on Prawn 2.4.0)
/Producer (Apache HBase Team)
-/ModDate (D:20260131143120+00'00')
-/CreationDate (D:20260131144554+00'00')
+/ModDate (D:20260203143214+00'00')
+/CreationDate (D:20260203144710+00'00')
>>
endobj
2 0 obj
diff --git a/book.html b/book.html
index 8d1939b33b1..2e83c6b5cf9 100644
--- a/book.html
+++ b/book.html
@@ -50183,7 +50183,7 @@ org/apache/hadoop/hbase/security/access/AccessControlClient.revoke:(Lorg/apache/
<div id="footer">
<div id="footer-text">
Version 4.0.0-alpha-1-SNAPSHOT<br>
-Last updated 2026-01-31 14:31:20 UTC
+Last updated 2026-02-03 14:32:14 UTC
</div>
</div>
<script type="text/x-mathjax-config">
diff --git a/checkstyle-aggregate.html b/checkstyle-aggregate.html
index 488b9411414..0408800dbd6 100644
--- a/checkstyle-aggregate.html
+++ b/checkstyle-aggregate.html
@@ -2,7 +2,7 @@
<!--
- | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-checkstyle-plugin:3.6.0:checkstyle-aggregate at 01/31/26
+ | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-checkstyle-plugin:3.6.0:checkstyle-aggregate at 02/03/26
| Rendered using Apache Maven Fluido Skin 2.0.0-M9
-->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
@@ -109,7 +109,7 @@
<th><img src="images/icon_warning_sml.gif" /> Warnings</th>
<th><img src="images/icon_error_sml.gif" /> Errors</th></tr>
<tr class="b">
-<td>5227</td>
+<td>5228</td>
<td>0</td>
<td>0</td>
<td>1861</td></tr></table></section><section><a id="Files"></a>
@@ -9467,31 +9467,31 @@
<td>blocks</td>
<td>NeedBraces</td>
<td>'for' construct must use '{}'s.</td>
-<td>1809</td></tr>
+<td>1823</td></tr>
<tr class="b">
<td><img src="images/icon_error_sml.gif" /> Error</td>
<td>blocks</td>
<td>NeedBraces</td>
<td>'for' construct must use '{}'s.</td>
-<td>1825</td></tr>
+<td>1839</td></tr>
<tr class="a">
<td><img src="images/icon_error_sml.gif" /> Error</td>
<td>coding</td>
<td>NoFinalizer</td>
<td>Avoid using finalizer method.</td>
-<td>1859</td></tr>
+<td>1873</td></tr>
<tr class="b">
<td><img src="images/icon_error_sml.gif" /> Error</td>
<td>blocks</td>
<td>NeedBraces</td>
<td>'if' construct must use '{}'s.</td>
-<td>2176</td></tr>
+<td>2190</td></tr>
<tr class="a">
<td><img src="images/icon_error_sml.gif" /> Error</td>
<td>blocks</td>
<td>NeedBraces</td>
<td>'if' construct must use '{}'s.</td>
-<td>2179</td></tr></table></section><section><a id="org.2Fapache.2Fhadoop.2Fhbase.2Fio.2Fhfile.2Fbucket.2FFileIOEngine.java"></a>
+<td>2193</td></tr></table></section><section><a id="org.2Fapache.2Fhadoop.2Fhbase.2Fio.2Fhfile.2Fbucket.2FFileIOEngine.java"></a>
<h3>org/apache/hadoop/hbase/io/hfile/bucket/FileIOEngine.java</h3>
<table class="table table-striped">
<tr class="a">
@@ -16195,7 +16195,7 @@
<td>design</td>
<td>FinalClass</td>
<td>Class EmptyCredentials should be declared as final.</td>
-<td>446</td></tr></table></section><section><a id="org.2Fapache.2Fhadoop.2Fhbase.2Frest.2Fclient.2FClient.java"></a>
+<td>441</td></tr></table></section><section><a id="org.2Fapache.2Fhadoop.2Fhbase.2Frest.2Fclient.2FClient.java"></a>
<h3>org/apache/hadoop/hbase/rest/client/Client.java</h3>
<table class="table table-striped">
<tr class="a">
@@ -16401,13 +16401,13 @@
<td>sizes</td>
<td>LineLength</td>
<td>Line is longer than 100 characters (found 117).</td>
-<td>58</td></tr>
+<td>55</td></tr>
<tr class="a">
<td><img src="images/icon_error_sml.gif" /> Error</td>
<td>sizes</td>
<td>LineLength</td>
<td>Line is longer than 100 characters (found 112).</td>
-<td>59</td></tr></table></section><section><a id="org.2Fapache.2Fhadoop.2Fhbase.2Frest.2Fmodel.2FVersionModel.java"></a>
+<td>56</td></tr></table></section><section><a id="org.2Fapache.2Fhadoop.2Fhbase.2Frest.2Fmodel.2FVersionModel.java"></a>
<h3>org/apache/hadoop/hbase/rest/model/VersionModel.java</h3>
<table class="table table-striped">
<tr class="a">
diff --git a/dependency-convergence.html b/dependency-convergence.html
index e38a0f591ae..ca28778fa73 100644
--- a/dependency-convergence.html
+++ b/dependency-convergence.html
@@ -2,7 +2,7 @@
<!--
- | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:dependency-convergence at 01/31/26
+ | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:dependency-convergence at 02/03/26
| Rendered using Apache Maven Fluido Skin 2.0.0-M9
-->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
diff --git a/dependency-info.html b/dependency-info.html
index 0831c733508..f7d696f3ef3 100644
--- a/dependency-info.html
+++ b/dependency-info.html
@@ -2,7 +2,7 @@
<!--
- | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:dependency-info at 01/31/26
+ | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:dependency-info at 02/03/26
| Rendered using Apache Maven Fluido Skin 2.0.0-M9
-->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
diff --git a/dependency-management.html b/dependency-management.html
index 2333a2babd7..379b8862018 100644
--- a/dependency-management.html
+++ b/dependency-management.html
@@ -2,7 +2,7 @@
<!--
- | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:dependency-management at 01/31/26
+ | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:dependency-management at 02/03/26
| Rendered using Apache Maven Fluido Skin 2.0.0-M9
-->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
diff --git a/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntryGroup.html b/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntryGroup.html
index 2bc921aa660..35a7b6659f4 100644
--- a/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntryGroup.html
+++ b/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntryGroup.html
@@ -81,7 +81,7 @@ loadScripts(document, 'script');</script>
<dd><a href="BucketCache.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketCache</a></dd>
</dl>
<hr>
-<div class="type-signature"><span class="modifiers">private class </span><span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1958">BucketCache.BucketEntryGroup</a></span>
+<div class="type-signature"><span class="modifiers">private class </span><span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1972">BucketCache.BucketEntryGroup</a></span>
<span class="extends-implements">extends <a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Object.html" title="class or interface in java.lang" class="external-link">Object</a></span></div>
<div class="block">Used to group bucket entries into priority buckets. There will be a BucketEntryGroup for each
priority (single, multi, memory). Once bucketed, the eviction algorithm takes the appropriate
@@ -168,19 +168,19 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="queue">
<h3>queue</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type"><a href="CachedEntryQueue.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">CachedEntryQueue</a></span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntryGroup.html#line-1960">queue</a></span></div>
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type"><a href="CachedEntryQueue.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">CachedEntryQueue</a></span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntryGroup.html#line-1974">queue</a></span></div>
</section>
</li>
<li>
<section class="detail" id="totalSize">
<h3>totalSize</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">long</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntryGroup.html#line-1961">totalSize</a></span></div>
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">long</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntryGroup.html#line-1975">totalSize</a></span></div>
</section>
</li>
<li>
<section class="detail" id="bucketSize">
<h3>bucketSize</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">long</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntryGroup.html#line-1962">bucketSize</a></span></div>
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">long</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntryGroup.html#line-1976">bucketSize</a></span></div>
</section>
</li>
</ul>
@@ -194,7 +194,7 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="<init>(long,long,long)">
<h3>BucketEntryGroup</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntryGroup.html#line-1964">BucketEntryGroup</a></span><wbr><span class="parameters">(long bytesToFree,
+<div class="member-signature"><span class="modifiers">public</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntryGroup.html#line-1978">BucketEntryGroup</a></span><wbr><span class="parameters">(long bytesToFree,
long blockSize,
long bucketSize)</span></div>
</section>
@@ -210,25 +210,25 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="add(java.util.Map.Entry)">
<h3>add</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntryGroup.html#line-1970">add</a></span><wbr><span class="parameters">(<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Map.Entry.html" title="class or interface in java.util" class="external-link">Map.Entry</a><<a hr [...]
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntryGroup.html#line-1984">add</a></span><wbr><span class="parameters">(<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Map.Entry.html" title="class or interface in java.util" class="external-link">Map.Entry</a><<a hr [...]
</section>
</li>
<li>
<section class="detail" id="free(long)">
<h3>free</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">long</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntryGroup.html#line-1975">free</a></span><wbr><span class="parameters">(long toFree)</span></div>
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">long</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntryGroup.html#line-1989">free</a></span><wbr><span class="parameters">(long toFree)</span></div>
</section>
</li>
<li>
<section class="detail" id="overflow()">
<h3>overflow</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">long</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntryGroup.html#line-1993">overflow</a></span>()</div>
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">long</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntryGroup.html#line-2007">overflow</a></span>()</div>
</section>
</li>
<li>
<section class="detail" id="totalSize()">
<h3>totalSize</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">long</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntryGroup.html#line-1997">totalSize</a></span>()</div>
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">long</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntryGroup.html#line-2011">totalSize</a></span>()</div>
</section>
</li>
</ul>
diff --git a/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMCache.html b/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMCache.html
index f811557f751..78dcd1aaf95 100644
--- a/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMCache.html
+++ b/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMCache.html
@@ -81,7 +81,7 @@ loadScripts(document, 'script');</script>
<dd><a href="BucketCache.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketCache</a></dd>
</dl>
<hr>
-<div class="type-signature"><span class="modifiers">static class </span><span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-2267">BucketCache.RAMCache</a></span>
+<div class="type-signature"><span class="modifiers">static class </span><span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-2281">BucketCache.RAMCache</a></span>
<span class="extends-implements">extends <a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Object.html" title="class or interface in java.lang" class="external-link">Object</a></span></div>
<div class="block">Wrapped the delegate ConcurrentMap with maintaining its block's reference count.</div>
</section>
@@ -183,7 +183,7 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="delegate">
<h3>delegate</h3>
-<div class="member-signature"><span class="modifiers">final</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/ConcurrentHashMap.html" title="class or interface in java.util.concurrent" class="external-link">ConcurrentHashMap</a><<a href="../BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a>,<wbr><a href="BucketCache.RAMQueueEntry.html" title="class in org.apache.hadoop.h [...]
+<div class="member-signature"><span class="modifiers">final</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/ConcurrentHashMap.html" title="class or interface in java.util.concurrent" class="external-link">ConcurrentHashMap</a><<a href="../BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a>,<wbr><a href="BucketCache.RAMQueueEntry.html" title="class in org.apache.hadoop.h [...]
<div class="block">Defined the map as <a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/ConcurrentHashMap.html" title="class or interface in java.util.concurrent" class="external-link"><code>ConcurrentHashMap</code></a> explicitly here, because in
<a href="#get(org.apache.hadoop.hbase.io.hfile.BlockCacheKey)"><code>get(BlockCacheKey)</code></a> and
<a href="#putIfAbsent(org.apache.hadoop.hbase.io.hfile.BlockCacheKey,org.apache.hadoop.hbase.io.hfile.bucket.BucketCache.RAMQueueEntry)"><code>putIfAbsent(BlockCacheKey, BucketCache.RAMQueueEntry)</code></a> , we need to guarantee
@@ -204,7 +204,7 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="<init>()">
<h3>RAMCache</h3>
-<div class="member-signature"><span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMCache.html#line-2267">RAMCache</a></span>()</div>
+<div class="member-signature"><span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMCache.html#line-2281">RAMCache</a></span>()</div>
</section>
</li>
</ul>
@@ -218,19 +218,19 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="containsKey(org.apache.hadoop.hbase.io.hfile.BlockCacheKey)">
<h3>containsKey</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMCache.html#line-2279">containsKey</a></span><wbr><span class="parameters">(<a href="../BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a> key)</span></div>
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMCache.html#line-2293">containsKey</a></span><wbr><span class="parameters">(<a href="../BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a> key)</span></div>
</section>
</li>
<li>
<section class="detail" id="get(org.apache.hadoop.hbase.io.hfile.BlockCacheKey)">
<h3>get</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type"><a href="BucketCache.RAMQueueEntry.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketCache.RAMQueueEntry</a></span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMCache.html#line-2283">get</a></span><wbr><span class="parameters">(<a href="../BlockCacheKey.html" title="class in org.apache.hadoop [...]
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type"><a href="BucketCache.RAMQueueEntry.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketCache.RAMQueueEntry</a></span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMCache.html#line-2297">get</a></span><wbr><span class="parameters">(<a href="../BlockCacheKey.html" title="class in org.apache.hadoop [...]
</section>
</li>
<li>
<section class="detail" id="putIfAbsent(org.apache.hadoop.hbase.io.hfile.BlockCacheKey,org.apache.hadoop.hbase.io.hfile.bucket.BucketCache.RAMQueueEntry)">
<h3>putIfAbsent</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type"><a href="BucketCache.RAMQueueEntry.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketCache.RAMQueueEntry</a></span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMCache.html#line-2297">putIfAbsent</a></span><wbr><span class="parameters">(<a href="../BlockCacheKey.html" title="class in org.apach [...]
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type"><a href="BucketCache.RAMQueueEntry.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketCache.RAMQueueEntry</a></span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMCache.html#line-2311">putIfAbsent</a></span><wbr><span class="parameters">(<a href="../BlockCacheKey.html" title="class in org.apach [...]
<a href="BucketCache.RAMQueueEntry.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketCache.RAMQueueEntry</a> entry)</span></div>
<div class="block">Return the previous associated value, or null if absent. It has the same meaning as
<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/ConcurrentMap.html#putIfAbsent(K,V)" title="class or interface in java.util.concurrent" class="external-link"><code>ConcurrentMap.putIfAbsent(Object, Object)</code></a></div>
@@ -239,13 +239,13 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="remove(org.apache.hadoop.hbase.io.hfile.BlockCacheKey)">
<h3>remove</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMCache.html#line-2308">remove</a></span><wbr><span class="parameters">(<a href="../BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a> key)</span></div>
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMCache.html#line-2322">remove</a></span><wbr><span class="parameters">(<a href="../BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a> key)</span></div>
</section>
</li>
<li>
<section class="detail" id="remove(org.apache.hadoop.hbase.io.hfile.BlockCacheKey,java.util.function.Consumer)">
<h3>remove</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMCache.html#line-2319">remove</a></span><wbr><span class="parameters">(<a href="../BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a> key,
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMCache.html#line-2333">remove</a></span><wbr><span class="parameters">(<a href="../BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a> key,
<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/function/Consumer.html" title="class or interface in java.util.function" class="external-link">Consumer</a><<a href="BucketCache.RAMQueueEntry.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketCache.RAMQueueEntry</a>> action)</span></div>
<div class="block">Defined an <a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/function/Consumer.html" title="class or interface in java.util.function" class="external-link"><code>Consumer</code></a> here, because once the removed entry release its reference count,
then it's ByteBuffers may be recycled and accessing it outside this method will be thrown an
@@ -256,19 +256,19 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="isEmpty()">
<h3>isEmpty</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMCache.html#line-2328">isEmpty</a></span>()</div>
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMCache.html#line-2342">isEmpty</a></span>()</div>
</section>
</li>
<li>
<section class="detail" id="clear()">
<h3>clear</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMCache.html#line-2332">clear</a></span>()</div>
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMCache.html#line-2346">clear</a></span>()</div>
</section>
</li>
<li>
<section class="detail" id="hasBlocksForFile(java.lang.String)">
<h3>hasBlocksForFile</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMCache.html#line-2341">hasBlocksForFile</a></span><wbr><span class="parameters">(<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a> f [...]
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMCache.html#line-2355">hasBlocksForFile</a></span><wbr><span class="parameters">(<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a> f [...]
</section>
</li>
</ul>
diff --git a/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html b/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html
index 0269a61ca55..66de5e192e5 100644
--- a/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html
+++ b/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html
@@ -81,7 +81,7 @@ loadScripts(document, 'script');</script>
<dd><a href="BucketCache.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketCache</a></dd>
</dl>
<hr>
-<div class="type-signature"><span class="modifiers">static class </span><span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-2005">BucketCache.RAMQueueEntry</a></span>
+<div class="type-signature"><span class="modifiers">static class </span><span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-2019">BucketCache.RAMQueueEntry</a></span>
<span class="extends-implements">extends <a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Object.html" title="class or interface in java.lang" class="external-link">Object</a></span></div>
<div class="block">Block Entry stored in the memory with key,data and so on</div>
</section>
@@ -189,37 +189,37 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="key">
<h3>key</h3>
-<div class="member-signature"><span class="modifiers">private final</span> <span class="return-type"><a href="../BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a></span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html#line-2006">key</a></span></div>
+<div class="member-signature"><span class="modifiers">private final</span> <span class="return-type"><a href="../BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a></span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html#line-2020">key</a></span></div>
</section>
</li>
<li>
<section class="detail" id="data">
<h3>data</h3>
-<div class="member-signature"><span class="modifiers">private final</span> <span class="return-type"><a href="../Cacheable.html" title="interface in org.apache.hadoop.hbase.io.hfile">Cacheable</a></span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html#line-2007">data</a></span></div>
+<div class="member-signature"><span class="modifiers">private final</span> <span class="return-type"><a href="../Cacheable.html" title="interface in org.apache.hadoop.hbase.io.hfile">Cacheable</a></span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html#line-2021">data</a></span></div>
</section>
</li>
<li>
<section class="detail" id="accessCounter">
<h3>accessCounter</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">long</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html#line-2008">accessCounter</a></span></div>
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">long</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html#line-2022">accessCounter</a></span></div>
</section>
</li>
<li>
<section class="detail" id="inMemory">
<h3>inMemory</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html#line-2009">inMemory</a></span></div>
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html#line-2023">inMemory</a></span></div>
</section>
</li>
<li>
<section class="detail" id="isCachePersistent">
<h3>isCachePersistent</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html#line-2010">isCachePersistent</a></span></div>
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html#line-2024">isCachePersistent</a></span></div>
</section>
</li>
<li>
<section class="detail" id="isPrefetch">
<h3>isPrefetch</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html#line-2012">isPrefetch</a></span></div>
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html#line-2026">isPrefetch</a></span></div>
</section>
</li>
</ul>
@@ -233,7 +233,7 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="<init>(org.apache.hadoop.hbase.io.hfile.BlockCacheKey,org.apache.hadoop.hbase.io.hfile.Cacheable,long,boolean,boolean,boolean)">
<h3>RAMQueueEntry</h3>
-<div class="member-signature"><span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html#line-2014">RAMQueueEntry</a></span><wbr><span class="parameters">(<a href="../BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a> bck,
+<div class="member-signature"><span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html#line-2028">RAMQueueEntry</a></span><wbr><span class="parameters">(<a href="../BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a> bck,
<a href="../Cacheable.html" title="interface in org.apache.hadoop.hbase.io.hfile">Cacheable</a> data,
long accessCounter,
boolean inMemory,
@@ -252,37 +252,37 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="getData()">
<h3>getData</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type"><a href="../Cacheable.html" title="interface in org.apache.hadoop.hbase.io.hfile">Cacheable</a></span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html#line-2024">getData</a></span>()</div>
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type"><a href="../Cacheable.html" title="interface in org.apache.hadoop.hbase.io.hfile">Cacheable</a></span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html#line-2038">getData</a></span>()</div>
</section>
</li>
<li>
<section class="detail" id="getKey()">
<h3>getKey</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type"><a href="../BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a></span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html#line-2028">getKey</a></span>()</div>
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type"><a href="../BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a></span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html#line-2042">getKey</a></span>()</div>
</section>
</li>
<li>
<section class="detail" id="isPrefetch()">
<h3>isPrefetch</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html#line-2032">isPrefetch</a></span>()</div>
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html#line-2046">isPrefetch</a></span>()</div>
</section>
</li>
<li>
<section class="detail" id="access(long)">
<h3>access</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html#line-2036">access</a></span><wbr><span class="parameters">(long accessCounter)</span></div>
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html#line-2050">access</a></span><wbr><span class="parameters">(long accessCounter)</span></div>
</section>
</li>
<li>
<section class="detail" id="getByteBuffAllocator()">
<h3>getByteBuffAllocator</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type"><a href="../../ByteBuffAllocator.html" title="class in org.apache.hadoop.hbase.io">ByteBuffAllocator</a></span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html#line-2040">getByteBuffAllocator</a></span>()</div>
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type"><a href="../../ByteBuffAllocator.html" title="class in org.apache.hadoop.hbase.io">ByteBuffAllocator</a></span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html#line-2054">getByteBuffAllocator</a></span>()</div>
</section>
</li>
<li>
<section class="detail" id="writeToCache(org.apache.hadoop.hbase.io.hfile.bucket.IOEngine,org.apache.hadoop.hbase.io.hfile.bucket.BucketAllocator,java.util.concurrent.atomic.LongAdder,java.util.function.Function,java.nio.ByteBuffer,java.lang.Long)">
<h3>writeToCache</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type"><a href="BucketEntry.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketEntry</a></span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html#line-2047">writeToCache</a></span><wbr><span class="parameters">(<a href="IOEngine.html" title="interface in org.apache.hadoop.hbase.io.hfile.bu [...]
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type"><a href="BucketEntry.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketEntry</a></span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html#line-2061">writeToCache</a></span><wbr><span class="parameters">(<a href="IOEngine.html" title="interface in org.apache.hadoop.hbase.io.hfile.bu [...]
<a href="BucketAllocator.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketAllocator</a> alloc,
<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/atomic/LongAdder.html" title="class or interface in java.util.concurrent.atomic" class="external-link">LongAdder</a> realCacheSize,
<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/function/Function.html" title="class or interface in java.util.function" class="external-link">Function</a><<a href="BucketEntry.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketEntry</a>,<wbr><a href="../../ByteBuffAllocator.Recycler.html" title="interface in org.apache.hadoop.hbase.io">ByteBuffAllocator.Recycler</a>> createRecycler,
diff --git a/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html b/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html
index 66ad5e1979e..89a42984b7a 100644
--- a/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html
+++ b/devapidocs/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html
@@ -2299,19 +2299,19 @@ implements <a href="../BlockCache.html" title="interface in org.apache.hadoop.hb
<li>
<section class="detail" id="updateRegionSizeMapWhileRetrievingFromFile()">
<h3>updateRegionSizeMapWhileRetrievingFromFile</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1634">updateRegionSizeMapWhileRetrievingFromFile</a></span>()</div>
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1641">updateRegionSizeMapWhileRetrievingFromFile</a></span>()</div>
</section>
</li>
<li>
<section class="detail" id="dumpPrefetchList()">
<h3>dumpPrefetchList</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1650">dumpPrefetchList</a></span>()</div>
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1657">dumpPrefetchList</a></span>()</div>
</section>
</li>
<li>
<section class="detail" id="verifyCapacityAndClasses(long,java.lang.String,java.lang.String)">
<h3>verifyCapacityAndClasses</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1657">verifyCapacityAndClasses</a></span><wbr><span class="parameters">(long capacitySize,
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1664">verifyCapacityAndClasses</a></span><wbr><span class="parameters">(long capacitySize,
<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a> ioclass,
<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a> mapclass)</span>
throws <span class="exceptions"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/IOException.html" title="class or interface in java.io" class="external-link">IOException</a></span></div>
@@ -2324,13 +2324,13 @@ implements <a href="../BlockCache.html" title="interface in org.apache.hadoop.hb
<li>
<section class="detail" id="verifyFileIntegrity(org.apache.hadoop.hbase.shaded.protobuf.generated.BucketCacheProtos.BucketCacheEntry)">
<h3>verifyFileIntegrity</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1673">verifyFileIntegrity</a></span><wbr><span class="parameters">(org.apache.hadoop.hbase.shaded.protobuf.generated.BucketCacheProtos.BucketCacheEntry proto)</span></div>
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1680">verifyFileIntegrity</a></span><wbr><span class="parameters">(org.apache.hadoop.hbase.shaded.protobuf.generated.BucketCacheProtos.BucketCacheEntry proto)</span></div>
</section>
</li>
<li>
<section class="detail" id="updateCacheIndex(org.apache.hadoop.hbase.shaded.protobuf.generated.BucketCacheProtos.BackingMap,java.util.Map)">
<h3>updateCacheIndex</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1715">updateCacheIndex</a></span><wbr><span class="parameters">(org.apache.hadoop.hbase.shaded.protobuf.generated.BucketCacheProtos.BackingMap chunk,
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1722">updateCacheIndex</a></span><wbr><span class="parameters">(org.apache.hadoop.hbase.shaded.protobuf.generated.BucketCacheProtos.BackingMap chunk,
<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Map.html" title="class or interface in java.util" class="external-link">Map</a><<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Integer.html" title="class or interface in java.lang" class="external-link">Integer</a>,<wbr><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link"> [...]
throws <span class="exceptions"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/IOException.html" title="class or interface in java.io" class="external-link">IOException</a></span></div>
<dl class="notes">
@@ -2342,7 +2342,7 @@ implements <a href="../BlockCache.html" title="interface in org.apache.hadoop.hb
<li>
<section class="detail" id="parsePB(org.apache.hadoop.hbase.shaded.protobuf.generated.BucketCacheProtos.BucketCacheEntry)">
<h3>parsePB</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1723">parsePB</a></span><wbr><span class="parameters">(org.apache.hadoop.hbase.shaded.protobuf.generated.BucketCacheProtos.BucketCacheEntry proto)</span>
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1730">parsePB</a></span><wbr><span class="parameters">(org.apache.hadoop.hbase.shaded.protobuf.generated.BucketCacheProtos.BucketCacheEntry proto)</span>
throws <span class="exceptions"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/IOException.html" title="class or interface in java.io" class="external-link">IOException</a></span></div>
<dl class="notes">
<dt>Throws:</dt>
@@ -2353,7 +2353,7 @@ implements <a href="../BlockCache.html" title="interface in org.apache.hadoop.hb
<li>
<section class="detail" id="persistChunkedBackingMap(java.io.FileOutputStream)">
<h3>persistChunkedBackingMap</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1740">persistChunkedBackingMap</a></span><wbr><span class="parameters">(<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/FileOutputStream.html" title="class or interface in java.io" class="external-link">FileOutputStre [...]
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1747">persistChunkedBackingMap</a></span><wbr><span class="parameters">(<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/FileOutputStream.html" title="class or interface in java.io" class="external-link">FileOutputStre [...]
throws <span class="exceptions"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/IOException.html" title="class or interface in java.io" class="external-link">IOException</a></span></div>
<dl class="notes">
<dt>Throws:</dt>
@@ -2364,7 +2364,7 @@ implements <a href="../BlockCache.html" title="interface in org.apache.hadoop.hb
<li>
<section class="detail" id="retrieveChunkedBackingMap(java.io.FileInputStream)">
<h3>retrieveChunkedBackingMap</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1753">retrieveChunkedBackingMap</a></span><wbr><span class="parameters">(<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/FileInputStream.html" title="class or interface in java.io" class="external-link">FileInputStrea [...]
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1760">retrieveChunkedBackingMap</a></span><wbr><span class="parameters">(<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/FileInputStream.html" title="class or interface in java.io" class="external-link">FileInputStrea [...]
throws <span class="exceptions"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/IOException.html" title="class or interface in java.io" class="external-link">IOException</a></span></div>
<dl class="notes">
<dt>Throws:</dt>
@@ -2375,7 +2375,7 @@ implements <a href="../BlockCache.html" title="interface in org.apache.hadoop.hb
<li>
<section class="detail" id="checkIOErrorIsTolerated()">
<h3>checkIOErrorIsTolerated</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1783">checkIOErrorIsTolerated</a></span>()</div>
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1797">checkIOErrorIsTolerated</a></span>()</div>
<div class="block">Check whether we tolerate IO error this time. If the duration of IOEngine throwing errors
exceeds ioErrorsDurationTimeTolerated, we will disable the cache</div>
</section>
@@ -2383,14 +2383,14 @@ implements <a href="../BlockCache.html" title="interface in org.apache.hadoop.hb
<li>
<section class="detail" id="disableCache()">
<h3>disableCache</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1801">disableCache</a></span>()</div>
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1815">disableCache</a></span>()</div>
<div class="block">Used to shut down the cache -or- turn it off in the case of something broken.</div>
</section>
</li>
<li>
<section class="detail" id="join()">
<h3>join</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1824">join</a></span>()
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1838">join</a></span>()
throws <span class="exceptions"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/InterruptedException.html" title="class or interface in java.lang" class="external-link">InterruptedException</a></span></div>
<dl class="notes">
<dt>Throws:</dt>
@@ -2401,7 +2401,7 @@ implements <a href="../BlockCache.html" title="interface in org.apache.hadoop.hb
<li>
<section class="detail" id="shutdown()">
<h3>shutdown</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1829">shutdown</a></span>()</div>
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1843">shutdown</a></span>()</div>
<div class="block"><span class="descfrm-type-label">Description copied from interface: <code><a href="../BlockCache.html#shutdown()">BlockCache</a></code></span></div>
<div class="block">Shutdown the cache.</div>
<dl class="notes">
@@ -2413,7 +2413,7 @@ implements <a href="../BlockCache.html" title="interface in org.apache.hadoop.hb
<li>
<section class="detail" id="finalize()">
<h3>finalize</h3>
-<div class="member-signature"><span class="modifiers">protected</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1859">finalize</a></span>()</div>
+<div class="member-signature"><span class="modifiers">protected</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1873">finalize</a></span>()</div>
<div class="block">Needed mostly for UTs that might run in the same VM and create different BucketCache instances
on different UT methods.</div>
<dl class="notes">
@@ -2425,7 +2425,7 @@ implements <a href="../BlockCache.html" title="interface in org.apache.hadoop.hb
<li>
<section class="detail" id="getStats()">
<h3>getStats</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type"><a href="../CacheStats.html" title="class in org.apache.hadoop.hbase.io.hfile">CacheStats</a></span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1866">getStats</a></span>()</div>
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type"><a href="../CacheStats.html" title="class in org.apache.hadoop.hbase.io.hfile">CacheStats</a></span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1880">getStats</a></span>()</div>
<div class="block"><span class="descfrm-type-label">Description copied from interface: <code><a href="../BlockCache.html#getStats()">BlockCache</a></code></span></div>
<div class="block">Get the statistics for this block cache.</div>
<dl class="notes">
@@ -2437,13 +2437,13 @@ implements <a href="../BlockCache.html" title="interface in org.apache.hadoop.hb
<li>
<section class="detail" id="getAllocator()">
<h3>getAllocator</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type"><a href="BucketAllocator.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketAllocator</a></span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1871">getAllocator</a></span>()</div>
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type"><a href="BucketAllocator.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketAllocator</a></span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1885">getAllocator</a></span>()</div>
</section>
</li>
<li>
<section class="detail" id="heapSize()">
<h3>heapSize</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">long</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1875">heapSize</a></span>()</div>
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">long</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1889">heapSize</a></span>()</div>
<div class="block"><span class="descfrm-type-label">Description copied from interface: <code><a href="../../HeapSize.html#heapSize()">HeapSize</a></code></span></div>
<div class="block">Return the approximate 'exclusive deep size' of implementing object. Includes count of payload
and hosting object sizings.</div>
@@ -2456,7 +2456,7 @@ implements <a href="../BlockCache.html" title="interface in org.apache.hadoop.hb
<li>
<section class="detail" id="size()">
<h3>size</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">long</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1880">size</a></span>()</div>
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">long</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1894">size</a></span>()</div>
<div class="block"><span class="descfrm-type-label">Description copied from interface: <code><a href="../BlockCache.html#size()">BlockCache</a></code></span></div>
<div class="block">Returns the total size of the block cache, in bytes.</div>
<dl class="notes">
@@ -2470,7 +2470,7 @@ implements <a href="../BlockCache.html" title="interface in org.apache.hadoop.hb
<li>
<section class="detail" id="getCurrentDataSize()">
<h3>getCurrentDataSize</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">long</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1885">getCurrentDataSize</a></span>()</div>
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">long</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1899">getCurrentDataSize</a></span>()</div>
<div class="block"><span class="descfrm-type-label">Description copied from interface: <code><a href="../BlockCache.html#getCurrentDataSize()">BlockCache</a></code></span></div>
<div class="block">Returns the occupied size of data blocks, in bytes.</div>
<dl class="notes">
@@ -2484,7 +2484,7 @@ implements <a href="../BlockCache.html" title="interface in org.apache.hadoop.hb
<li>
<section class="detail" id="getFreeSize()">
<h3>getFreeSize</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">long</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1890">getFreeSize</a></span>()</div>
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">long</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1904">getFreeSize</a></span>()</div>
<div class="block"><span class="descfrm-type-label">Description copied from interface: <code><a href="../BlockCache.html#getFreeSize()">BlockCache</a></code></span></div>
<div class="block">Returns the free size of the block cache, in bytes.</div>
<dl class="notes">
@@ -2498,7 +2498,7 @@ implements <a href="../BlockCache.html" title="interface in org.apache.hadoop.hb
<li>
<section class="detail" id="getBlockCount()">
<h3>getBlockCount</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">long</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1898">getBlockCount</a></span>()</div>
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">long</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1912">getBlockCount</a></span>()</div>
<div class="block"><span class="descfrm-type-label">Description copied from interface: <code><a href="../BlockCache.html#getBlockCount()">BlockCache</a></code></span></div>
<div class="block">Returns the number of blocks currently cached in the block cache.</div>
<dl class="notes">
@@ -2512,7 +2512,7 @@ implements <a href="../BlockCache.html" title="interface in org.apache.hadoop.hb
<li>
<section class="detail" id="getDataBlockCount()">
<h3>getDataBlockCount</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">long</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1903">getDataBlockCount</a></span>()</div>
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">long</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1917">getDataBlockCount</a></span>()</div>
<div class="block"><span class="descfrm-type-label">Description copied from interface: <code><a href="../BlockCache.html#getDataBlockCount()">BlockCache</a></code></span></div>
<div class="block">Returns the number of data blocks currently cached in the block cache.</div>
<dl class="notes">
@@ -2526,7 +2526,7 @@ implements <a href="../BlockCache.html" title="interface in org.apache.hadoop.hb
<li>
<section class="detail" id="getCurrentSize()">
<h3>getCurrentSize</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">long</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1908">getCurrentSize</a></span>()</div>
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">long</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1922">getCurrentSize</a></span>()</div>
<div class="block"><span class="descfrm-type-label">Description copied from interface: <code><a href="../BlockCache.html#getCurrentSize()">BlockCache</a></code></span></div>
<div class="block">Returns the occupied size of the block cache, in bytes.</div>
<dl class="notes">
@@ -2540,13 +2540,13 @@ implements <a href="../BlockCache.html" title="interface in org.apache.hadoop.hb
<li>
<section class="detail" id="getAlgorithm()">
<h3>getAlgorithm</h3>
-<div class="member-signature"><span class="modifiers">protected</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a></span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1916">getAlgorithm</a></span>()</div>
+<div class="member-signature"><span class="modifiers">protected</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a></span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1930">getAlgorithm</a></span>()</div>
</section>
</li>
<li>
<section class="detail" id="evictBlocksByHfileName(java.lang.String)">
<h3>evictBlocksByHfileName</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">int</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1926">evictBlocksByHfileName</a></span><wbr><span class="parameters">(<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a> hfileNam [...]
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">int</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1940">evictBlocksByHfileName</a></span><wbr><span class="parameters">(<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a> hfileNam [...]
<div class="block">Evicts all blocks for a specific HFile.
<p>
This is used for evict-on-close to remove all blocks of a specific HFile.</div>
@@ -2561,7 +2561,7 @@ implements <a href="../BlockCache.html" title="interface in org.apache.hadoop.hb
<li>
<section class="detail" id="evictBlocksRangeByHfileName(java.lang.String,long,long)">
<h3>evictBlocksRangeByHfileName</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">int</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1931">evictBlocksRangeByHfileName</a></span><wbr><span class="parameters">(<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a> hfileName,
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">int</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-1945">evictBlocksRangeByHfileName</a></span><wbr><span class="parameters">(<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a> hfileName,
long initOffset,
long endOffset)</span></div>
<div class="block"><span class="descfrm-type-label">Description copied from interface: <code><a href="../BlockCache.html#evictBlocksRangeByHfileName(java.lang.String,long,long)">BlockCache</a></code></span></div>
@@ -2581,7 +2581,7 @@ implements <a href="../BlockCache.html" title="interface in org.apache.hadoop.hb
<li>
<section class="detail" id="getAllCacheKeysForFile(java.lang.String,long,long)">
<h3>getAllCacheKeysForFile</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Set.html" title="class or interface in java.util" class="external-link">Set</a><<a href="../BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a>></span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketC [...]
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Set.html" title="class or interface in java.util" class="external-link">Set</a><<a href="../BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a>></span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketC [...]
long init,
long end)</span></div>
</section>
@@ -2589,7 +2589,7 @@ implements <a href="../BlockCache.html" title="interface in org.apache.hadoop.hb
<li>
<section class="detail" id="stopWriterThreads()">
<h3>stopWriterThreads</h3>
-<div class="member-signature"><span class="return-type">void</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-2113">stopWriterThreads</a></span>()
+<div class="member-signature"><span class="return-type">void</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-2127">stopWriterThreads</a></span>()
throws <span class="exceptions"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/InterruptedException.html" title="class or interface in java.lang" class="external-link">InterruptedException</a></span></div>
<div class="block">Only used in test</div>
<dl class="notes">
@@ -2601,7 +2601,7 @@ implements <a href="../BlockCache.html" title="interface in org.apache.hadoop.hb
<li>
<section class="detail" id="iterator()">
<h3>iterator</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Iterator.html" title="class or interface in java.util" class="external-link">Iterator</a><<a href="../CachedBlock.html" title="interface in org.apache.hadoop.hbase.io.hfile">CachedBlock</a>></span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucke [...]
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Iterator.html" title="class or interface in java.util" class="external-link">Iterator</a><<a href="../CachedBlock.html" title="interface in org.apache.hadoop.hbase.io.hfile">CachedBlock</a>></span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucke [...]
<div class="block"><span class="descfrm-type-label">Description copied from interface: <code><a href="../BlockCache.html#iterator()">BlockCache</a></code></span></div>
<div class="block">Returns Iterator over the blocks in the cache.</div>
<dl class="notes">
@@ -2615,7 +2615,7 @@ implements <a href="../BlockCache.html" title="interface in org.apache.hadoop.hb
<li>
<section class="detail" id="getBlockCaches()">
<h3>getBlockCaches</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type"><a href="../BlockCache.html" title="interface in org.apache.hadoop.hbase.io.hfile">BlockCache</a>[]</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-2211">getBlockCaches</a></span>()</div>
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type"><a href="../BlockCache.html" title="interface in org.apache.hadoop.hbase.io.hfile">BlockCache</a>[]</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-2225">getBlockCaches</a></span>()</div>
<div class="block"><span class="descfrm-type-label">Description copied from interface: <code><a href="../BlockCache.html#getBlockCaches()">BlockCache</a></code></span></div>
<div class="block">Returns The list of sub blockcaches that make up this one; returns null if no sub caches.</div>
<dl class="notes">
@@ -2627,85 +2627,85 @@ implements <a href="../BlockCache.html" title="interface in org.apache.hadoop.hb
<li>
<section class="detail" id="getRpcRefCount(org.apache.hadoop.hbase.io.hfile.BlockCacheKey)">
<h3>getRpcRefCount</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">int</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-2216">getRpcRefCount</a></span><wbr><span class="parameters">(<a href="../BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a> cacheKey)</span></div>
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">int</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-2230">getRpcRefCount</a></span><wbr><span class="parameters">(<a href="../BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a> cacheKey)</span></div>
</section>
</li>
<li>
<section class="detail" id="getAcceptableFactor()">
<h3>getAcceptableFactor</h3>
-<div class="member-signature"><span class="return-type">float</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-2224">getAcceptableFactor</a></span>()</div>
+<div class="member-signature"><span class="return-type">float</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-2238">getAcceptableFactor</a></span>()</div>
</section>
</li>
<li>
<section class="detail" id="getMinFactor()">
<h3>getMinFactor</h3>
-<div class="member-signature"><span class="return-type">float</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-2228">getMinFactor</a></span>()</div>
+<div class="member-signature"><span class="return-type">float</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-2242">getMinFactor</a></span>()</div>
</section>
</li>
<li>
<section class="detail" id="getExtraFreeFactor()">
<h3>getExtraFreeFactor</h3>
-<div class="member-signature"><span class="return-type">float</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-2232">getExtraFreeFactor</a></span>()</div>
+<div class="member-signature"><span class="return-type">float</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-2246">getExtraFreeFactor</a></span>()</div>
</section>
</li>
<li>
<section class="detail" id="getSingleFactor()">
<h3>getSingleFactor</h3>
-<div class="member-signature"><span class="return-type">float</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-2236">getSingleFactor</a></span>()</div>
+<div class="member-signature"><span class="return-type">float</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-2250">getSingleFactor</a></span>()</div>
</section>
</li>
<li>
<section class="detail" id="getMultiFactor()">
<h3>getMultiFactor</h3>
-<div class="member-signature"><span class="return-type">float</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-2240">getMultiFactor</a></span>()</div>
+<div class="member-signature"><span class="return-type">float</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-2254">getMultiFactor</a></span>()</div>
</section>
</li>
<li>
<section class="detail" id="getMemoryFactor()">
<h3>getMemoryFactor</h3>
-<div class="member-signature"><span class="return-type">float</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-2244">getMemoryFactor</a></span>()</div>
+<div class="member-signature"><span class="return-type">float</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-2258">getMemoryFactor</a></span>()</div>
</section>
</li>
<li>
<section class="detail" id="getQueueAdditionWaitTime()">
<h3>getQueueAdditionWaitTime</h3>
-<div class="member-signature"><span class="return-type">long</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-2248">getQueueAdditionWaitTime</a></span>()</div>
+<div class="member-signature"><span class="return-type">long</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-2262">getQueueAdditionWaitTime</a></span>()</div>
</section>
</li>
<li>
<section class="detail" id="getPersistenceChunkSize()">
<h3>getPersistenceChunkSize</h3>
-<div class="member-signature"><span class="return-type">long</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-2252">getPersistenceChunkSize</a></span>()</div>
+<div class="member-signature"><span class="return-type">long</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-2266">getPersistenceChunkSize</a></span>()</div>
</section>
</li>
<li>
<section class="detail" id="getBucketcachePersistInterval()">
<h3>getBucketcachePersistInterval</h3>
-<div class="member-signature"><span class="return-type">long</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-2256">getBucketcachePersistInterval</a></span>()</div>
+<div class="member-signature"><span class="return-type">long</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-2270">getBucketcachePersistInterval</a></span>()</div>
</section>
</li>
<li>
<section class="detail" id="getPersistencePath()">
<h3>getPersistencePath</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a></span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-2260">getPersistencePath</a></span>()</div>
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a></span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-2274">getPersistencePath</a></span>()</div>
</section>
</li>
<li>
<section class="detail" id="getBackingMap()">
<h3>getBackingMap</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Map.html" title="class or interface in java.util" class="external-link">Map</a><<a href="../BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a>,<wbr><a href="BucketEntry.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketEntry</a>></span> <span cla [...]
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Map.html" title="class or interface in java.util" class="external-link">Map</a><<a href="../BlockCacheKey.html" title="class in org.apache.hadoop.hbase.io.hfile">BlockCacheKey</a>,<wbr><a href="BucketEntry.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketEntry</a>></span> <span cla [...]
</section>
</li>
<li>
<section class="detail" id="getBackingMapValidated()">
<h3>getBackingMapValidated</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/atomic/AtomicBoolean.html" title="class or interface in java.util.concurrent.atomic" class="external-link">AtomicBoolean</a></span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-2351">getBackingMapValidated</a></spa [...]
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/atomic/AtomicBoolean.html" title="class or interface in java.util.concurrent.atomic" class="external-link">AtomicBoolean</a></span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-2365">getBackingMapValidated</a></spa [...]
</section>
</li>
<li>
<section class="detail" id="getFullyCachedFiles()">
<h3>getFullyCachedFiles</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Optional.html" title="class or interface in java.util" class="external-link">Optional</a><<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Map.html" title="class or interface in java.util" class="external-link">Map</a><<a href="https://docs.oracle.com/en/java/javase/17/docs/a [...]
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Optional.html" title="class or interface in java.util" class="external-link">Optional</a><<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Map.html" title="class or interface in java.util" class="external-link">Map</a><<a href="https://docs.oracle.com/en/java/javase/17/docs/a [...]
<div class="block"><span class="descfrm-type-label">Description copied from interface: <code><a href="../BlockCache.html#getFullyCachedFiles()">BlockCache</a></code></span></div>
<div class="block">Returns an Optional containing the map of files that have been fully cached (all its blocks are
present in the cache. This method may not be overridden by all implementing classes. In such
@@ -2722,13 +2722,13 @@ implements <a href="../BlockCache.html" title="interface in org.apache.hadoop.hb
<li>
<section class="detail" id="getBucketCacheFromCacheConfig(org.apache.hadoop.hbase.io.hfile.CacheConfig)">
<h3>getBucketCacheFromCacheConfig</h3>
-<div class="member-signature"><span class="modifiers">public static</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Optional.html" title="class or interface in java.util" class="external-link">Optional</a><<a href="BucketCache.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketCache</a>></span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfil [...]
+<div class="member-signature"><span class="modifiers">public static</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Optional.html" title="class or interface in java.util" class="external-link">Optional</a><<a href="BucketCache.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketCache</a>></span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfil [...]
</section>
</li>
<li>
<section class="detail" id="notifyFileCachingCompleted(org.apache.hadoop.fs.Path,int,int,long)">
<h3>notifyFileCachingCompleted</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-2375">notifyFileCachingCompleted</a></span><wbr><span class="parameters">(org.apache.hadoop.fs.Path fileName,
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-2389">notifyFileCachingCompleted</a></span><wbr><span class="parameters">(org.apache.hadoop.fs.Path fileName,
int totalBlockCount,
int dataBlockCount,
long size)</span></div>
@@ -2749,7 +2749,7 @@ implements <a href="../BlockCache.html" title="interface in org.apache.hadoop.hb
<li>
<section class="detail" id="blockFitsIntoTheCache(org.apache.hadoop.hbase.io.hfile.HFileBlock)">
<h3>blockFitsIntoTheCache</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Optional.html" title="class or interface in java.util" class="external-link">Optional</a><<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Boolean.html" title="class or interface in java.lang" class="external-link">Boolean</a>></span> <span class="element-name"><a href=" [...]
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Optional.html" title="class or interface in java.util" class="external-link">Optional</a><<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Boolean.html" title="class or interface in java.lang" class="external-link">Boolean</a>></span> <span class="element-name"><a href=" [...]
<div class="block"><span class="descfrm-type-label">Description copied from interface: <code><a href="../BlockCache.html#blockFitsIntoTheCache(org.apache.hadoop.hbase.io.hfile.HFileBlock)">BlockCache</a></code></span></div>
<div class="block">Checks whether there's enough space left in the cache to accommodate the passed block. This
method may not be overridden by all implementing classes. In such cases, the returned Optional
@@ -2769,7 +2769,7 @@ implements <a href="../BlockCache.html" title="interface in org.apache.hadoop.hb
<li>
<section class="detail" id="shouldCacheFile(org.apache.hadoop.hbase.io.hfile.HFileInfo,org.apache.hadoop.conf.Configuration)">
<h3>shouldCacheFile</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Optional.html" title="class or interface in java.util" class="external-link">Optional</a><<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Boolean.html" title="class or interface in java.lang" class="external-link">Boolean</a>></span> <span class="element-name"><a href=" [...]
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Optional.html" title="class or interface in java.util" class="external-link">Optional</a><<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Boolean.html" title="class or interface in java.lang" class="external-link">Boolean</a>></span> <span class="element-name"><a href=" [...]
org.apache.hadoop.conf.Configuration conf)</span></div>
<div class="block"><span class="descfrm-type-label">Description copied from interface: <code><a href="../BlockCache.html#shouldCacheFile(org.apache.hadoop.hbase.io.hfile.HFileInfo,org.apache.hadoop.conf.Configuration)">BlockCache</a></code></span></div>
<div class="block">Checks whether blocks for the passed file should be cached or not. This method may not be
@@ -2791,7 +2791,7 @@ implements <a href="../BlockCache.html" title="interface in org.apache.hadoop.hb
<li>
<section class="detail" id="shouldCacheBlock(org.apache.hadoop.hbase.io.hfile.BlockCacheKey,long,org.apache.hadoop.conf.Configuration)">
<h3>shouldCacheBlock</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Optional.html" title="class or interface in java.util" class="external-link">Optional</a><<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Boolean.html" title="class or interface in java.lang" class="external-link">Boolean</a>></span> <span class="element-name"><a href=" [...]
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Optional.html" title="class or interface in java.util" class="external-link">Optional</a><<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Boolean.html" title="class or interface in java.lang" class="external-link">Boolean</a>></span> <span class="element-name"><a href=" [...]
long maxTimestamp,
org.apache.hadoop.conf.Configuration conf)</span></div>
<div class="block"><span class="descfrm-type-label">Description copied from interface: <code><a href="../BlockCache.html#shouldCacheBlock(org.apache.hadoop.hbase.io.hfile.BlockCacheKey,long,org.apache.hadoop.conf.Configuration)">BlockCache</a></code></span></div>
@@ -2815,7 +2815,7 @@ implements <a href="../BlockCache.html" title="interface in org.apache.hadoop.hb
<li>
<section class="detail" id="isAlreadyCached(org.apache.hadoop.hbase.io.hfile.BlockCacheKey)">
<h3>isAlreadyCached</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Optional.html" title="class or interface in java.util" class="external-link">Optional</a><<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Boolean.html" title="class or interface in java.lang" class="external-link">Boolean</a>></span> <span class="element-name"><a href=" [...]
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Optional.html" title="class or interface in java.util" class="external-link">Optional</a><<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Boolean.html" title="class or interface in java.lang" class="external-link">Boolean</a>></span> <span class="element-name"><a href=" [...]
<div class="block"><span class="descfrm-type-label">Description copied from interface: <code><a href="../BlockCache.html#isAlreadyCached(org.apache.hadoop.hbase.io.hfile.BlockCacheKey)">BlockCache</a></code></span></div>
<div class="block">Checks whether the block for the passed key is already cached. This method may not be
overridden by all implementing classes. In such cases, the returned Optional will be empty. For
@@ -2835,7 +2835,7 @@ implements <a href="../BlockCache.html" title="interface in org.apache.hadoop.hb
<li>
<section class="detail" id="getBlockSize(org.apache.hadoop.hbase.io.hfile.BlockCacheKey)">
<h3>getBlockSize</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Optional.html" title="class or interface in java.util" class="external-link">Optional</a><<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Integer.html" title="class or interface in java.lang" class="external-link">Integer</a>></span> <span class="element-name"><a href=" [...]
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Optional.html" title="class or interface in java.util" class="external-link">Optional</a><<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Integer.html" title="class or interface in java.lang" class="external-link">Integer</a>></span> <span class="element-name"><a href=" [...]
<div class="block"><span class="descfrm-type-label">Description copied from interface: <code><a href="../BlockCache.html#getBlockSize(org.apache.hadoop.hbase.io.hfile.BlockCacheKey)">BlockCache</a></code></span></div>
<div class="block">Returns an Optional containing the size of the block related to the passed key. If the block is
not in the cache, returned optional will be empty. Also, this method may not be overridden by
@@ -2854,13 +2854,13 @@ implements <a href="../BlockCache.html" title="interface in org.apache.hadoop.hb
<li>
<section class="detail" id="isCacheInitialized(java.lang.String)">
<h3>isCacheInitialized</h3>
-<div class="member-signature"><span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-2497">isCacheInitialized</a></span><wbr><span class="parameters">(<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a> api)</span></div>
+<div class="member-signature"><span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-2511">isCacheInitialized</a></span><wbr><span class="parameters">(<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a> api)</span></div>
</section>
</li>
<li>
<section class="detail" id="waitForCacheInitialization(long)">
<h3>waitForCacheInitialization</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-2505">waitForCacheInitialization</a></span><wbr><span class="parameters">(long timeout)</span></div>
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../../../src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.html#line-2519">waitForCacheInitialization</a></span><wbr><span class="parameters">(long timeout)</span></div>
<div class="block"><span class="descfrm-type-label">Description copied from interface: <code><a href="../BlockCache.html#waitForCacheInitialization(long)">BlockCache</a></code></span></div>
<div class="block">Wait for the block cache implementation to be completely enabled. Some block cache
implementations may take longer to initialise, and this initialisation may be asynchronous.</div>
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntryGroup.html b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntryGroup.html
index a8c94de95c9..4ac8ffd5120 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntryGroup.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.BucketEntryGroup.html
@@ -1624,915 +1624,929 @@
<span class="source-line-no">1611</span><span id="line-1611"> int pblen = ProtobufMagic.lengthOfPBMagic();</span>
<span class="source-line-no">1612</span><span id="line-1612"> byte[] pbuf = new byte[pblen];</span>
<span class="source-line-no">1613</span><span id="line-1613"> IOUtils.readFully(in, pbuf, 0, pblen);</span>
-<span class="source-line-no">1614</span><span id="line-1614"> if (ProtobufMagic.isPBMagicPrefix(pbuf)) {</span>
-<span class="source-line-no">1615</span><span id="line-1615"> LOG.info("Reading old format of persistence.");</span>
-<span class="source-line-no">1616</span><span id="line-1616"> // The old non-chunked version of backing map persistence.</span>
-<span class="source-line-no">1617</span><span id="line-1617"> parsePB(BucketCacheProtos.BucketCacheEntry.parseDelimitedFrom(in));</span>
-<span class="source-line-no">1618</span><span id="line-1618"> } else if (Arrays.equals(pbuf, BucketProtoUtils.PB_MAGIC_V2)) {</span>
-<span class="source-line-no">1619</span><span id="line-1619"> // The new persistence format of chunked persistence.</span>
-<span class="source-line-no">1620</span><span id="line-1620"> LOG.info("Reading new chunked format of persistence.");</span>
-<span class="source-line-no">1621</span><span id="line-1621"> retrieveChunkedBackingMap(in);</span>
-<span class="source-line-no">1622</span><span id="line-1622"> } else {</span>
-<span class="source-line-no">1623</span><span id="line-1623"> // In 3.0 we have enough flexibility to dump the old cache data.</span>
-<span class="source-line-no">1624</span><span id="line-1624"> // TODO: In 2.x line, this might need to be filled in to support reading the old format</span>
-<span class="source-line-no">1625</span><span id="line-1625"> throw new IOException(</span>
-<span class="source-line-no">1626</span><span id="line-1626"> "Persistence file does not start with protobuf magic number. " + persistencePath);</span>
-<span class="source-line-no">1627</span><span id="line-1627"> }</span>
-<span class="source-line-no">1628</span><span id="line-1628"> bucketAllocator = new BucketAllocator(cacheCapacity, bucketSizes, backingMap, realCacheSize);</span>
-<span class="source-line-no">1629</span><span id="line-1629"> blockNumber.add(backingMap.size());</span>
-<span class="source-line-no">1630</span><span id="line-1630"> LOG.info("Bucket cache retrieved from file successfully with size: {}", backingMap.size());</span>
-<span class="source-line-no">1631</span><span id="line-1631"> }</span>
-<span class="source-line-no">1632</span><span id="line-1632"> }</span>
-<span class="source-line-no">1633</span><span id="line-1633"></span>
-<span class="source-line-no">1634</span><span id="line-1634"> private void updateRegionSizeMapWhileRetrievingFromFile() {</span>
-<span class="source-line-no">1635</span><span id="line-1635"> // Update the regionCachedSize with the region size while restarting the region server</span>
-<span class="source-line-no">1636</span><span id="line-1636"> if (LOG.isDebugEnabled()) {</span>
-<span class="source-line-no">1637</span><span id="line-1637"> LOG.debug("Updating region size map after retrieving cached file list");</span>
-<span class="source-line-no">1638</span><span id="line-1638"> dumpPrefetchList();</span>
-<span class="source-line-no">1639</span><span id="line-1639"> }</span>
-<span class="source-line-no">1640</span><span id="line-1640"> regionCachedSize.clear();</span>
-<span class="source-line-no">1641</span><span id="line-1641"> fullyCachedFiles.forEach((hFileName, hFileSize) -> {</span>
-<span class="source-line-no">1642</span><span id="line-1642"> // Get the region name for each file</span>
-<span class="source-line-no">1643</span><span id="line-1643"> String regionEncodedName = hFileSize.getFirst();</span>
-<span class="source-line-no">1644</span><span id="line-1644"> long cachedFileSize = hFileSize.getSecond();</span>
-<span class="source-line-no">1645</span><span id="line-1645"> regionCachedSize.merge(regionEncodedName, cachedFileSize,</span>
-<span class="source-line-no">1646</span><span id="line-1646"> (oldpf, fileSize) -> oldpf + fileSize);</span>
-<span class="source-line-no">1647</span><span id="line-1647"> });</span>
-<span class="source-line-no">1648</span><span id="line-1648"> }</span>
-<span class="source-line-no">1649</span><span id="line-1649"></span>
-<span class="source-line-no">1650</span><span id="line-1650"> private void dumpPrefetchList() {</span>
-<span class="source-line-no">1651</span><span id="line-1651"> for (Map.Entry<String, Pair<String, Long>> outerEntry : fullyCachedFiles.entrySet()) {</span>
-<span class="source-line-no">1652</span><span id="line-1652"> LOG.debug("Cached File Entry:<{},<{},{}>>", outerEntry.getKey(),</span>
-<span class="source-line-no">1653</span><span id="line-1653"> outerEntry.getValue().getFirst(), outerEntry.getValue().getSecond());</span>
-<span class="source-line-no">1654</span><span id="line-1654"> }</span>
+<span class="source-line-no">1614</span><span id="line-1614"></span>
+<span class="source-line-no">1615</span><span id="line-1615"> if (ProtobufMagic.isPBMagicPrefix(pbuf)) {</span>
+<span class="source-line-no">1616</span><span id="line-1616"> LOG.info("Reading old format of persistence.");</span>
+<span class="source-line-no">1617</span><span id="line-1617"> // The old non-chunked version of backing map persistence.</span>
+<span class="source-line-no">1618</span><span id="line-1618"> BucketCacheProtos.BucketCacheEntry cacheEntry =</span>
+<span class="source-line-no">1619</span><span id="line-1619"> BucketCacheProtos.BucketCacheEntry.parseDelimitedFrom(in);</span>
+<span class="source-line-no">1620</span><span id="line-1620"> if (cacheEntry == null) {</span>
+<span class="source-line-no">1621</span><span id="line-1621"> throw new IOException(</span>
+<span class="source-line-no">1622</span><span id="line-1622"> "Failed to parse cache entry from persistence file: " + persistencePath);</span>
+<span class="source-line-no">1623</span><span id="line-1623"> }</span>
+<span class="source-line-no">1624</span><span id="line-1624"> parsePB(cacheEntry);</span>
+<span class="source-line-no">1625</span><span id="line-1625"> } else if (Arrays.equals(pbuf, BucketProtoUtils.PB_MAGIC_V2)) {</span>
+<span class="source-line-no">1626</span><span id="line-1626"> // The new persistence format of chunked persistence.</span>
+<span class="source-line-no">1627</span><span id="line-1627"> LOG.info("Reading new chunked format of persistence.");</span>
+<span class="source-line-no">1628</span><span id="line-1628"> retrieveChunkedBackingMap(in);</span>
+<span class="source-line-no">1629</span><span id="line-1629"> } else {</span>
+<span class="source-line-no">1630</span><span id="line-1630"> // In 3.0 we have enough flexibility to dump the old cache data.</span>
+<span class="source-line-no">1631</span><span id="line-1631"> // TODO: In 2.x line, this might need to be filled in to support reading the old format</span>
+<span class="source-line-no">1632</span><span id="line-1632"> throw new IOException(</span>
+<span class="source-line-no">1633</span><span id="line-1633"> "Persistence file does not start with protobuf magic number. " + persistencePath);</span>
+<span class="source-line-no">1634</span><span id="line-1634"> }</span>
+<span class="source-line-no">1635</span><span id="line-1635"> bucketAllocator = new BucketAllocator(cacheCapacity, bucketSizes, backingMap, realCacheSize);</span>
+<span class="source-line-no">1636</span><span id="line-1636"> blockNumber.add(backingMap.size());</span>
+<span class="source-line-no">1637</span><span id="line-1637"> LOG.info("Bucket cache retrieved from file successfully with size: {}", backingMap.size());</span>
+<span class="source-line-no">1638</span><span id="line-1638"> }</span>
+<span class="source-line-no">1639</span><span id="line-1639"> }</span>
+<span class="source-line-no">1640</span><span id="line-1640"></span>
+<span class="source-line-no">1641</span><span id="line-1641"> private void updateRegionSizeMapWhileRetrievingFromFile() {</span>
+<span class="source-line-no">1642</span><span id="line-1642"> // Update the regionCachedSize with the region size while restarting the region server</span>
+<span class="source-line-no">1643</span><span id="line-1643"> if (LOG.isDebugEnabled()) {</span>
+<span class="source-line-no">1644</span><span id="line-1644"> LOG.debug("Updating region size map after retrieving cached file list");</span>
+<span class="source-line-no">1645</span><span id="line-1645"> dumpPrefetchList();</span>
+<span class="source-line-no">1646</span><span id="line-1646"> }</span>
+<span class="source-line-no">1647</span><span id="line-1647"> regionCachedSize.clear();</span>
+<span class="source-line-no">1648</span><span id="line-1648"> fullyCachedFiles.forEach((hFileName, hFileSize) -> {</span>
+<span class="source-line-no">1649</span><span id="line-1649"> // Get the region name for each file</span>
+<span class="source-line-no">1650</span><span id="line-1650"> String regionEncodedName = hFileSize.getFirst();</span>
+<span class="source-line-no">1651</span><span id="line-1651"> long cachedFileSize = hFileSize.getSecond();</span>
+<span class="source-line-no">1652</span><span id="line-1652"> regionCachedSize.merge(regionEncodedName, cachedFileSize,</span>
+<span class="source-line-no">1653</span><span id="line-1653"> (oldpf, fileSize) -> oldpf + fileSize);</span>
+<span class="source-line-no">1654</span><span id="line-1654"> });</span>
<span class="source-line-no">1655</span><span id="line-1655"> }</span>
<span class="source-line-no">1656</span><span id="line-1656"></span>
-<span class="source-line-no">1657</span><span id="line-1657"> private void verifyCapacityAndClasses(long capacitySize, String ioclass, String mapclass)</span>
-<span class="source-line-no">1658</span><span id="line-1658"> throws IOException {</span>
-<span class="source-line-no">1659</span><span id="line-1659"> if (capacitySize != cacheCapacity) {</span>
-<span class="source-line-no">1660</span><span id="line-1660"> throw new IOException("Mismatched cache capacity:" + StringUtils.byteDesc(capacitySize)</span>
-<span class="source-line-no">1661</span><span id="line-1661"> + ", expected: " + StringUtils.byteDesc(cacheCapacity));</span>
-<span class="source-line-no">1662</span><span id="line-1662"> }</span>
-<span class="source-line-no">1663</span><span id="line-1663"> if (!ioEngine.getClass().getName().equals(ioclass)) {</span>
-<span class="source-line-no">1664</span><span id="line-1664"> throw new IOException("Class name for IO engine mismatch: " + ioclass + ", expected:"</span>
-<span class="source-line-no">1665</span><span id="line-1665"> + ioEngine.getClass().getName());</span>
-<span class="source-line-no">1666</span><span id="line-1666"> }</span>
-<span class="source-line-no">1667</span><span id="line-1667"> if (!backingMap.getClass().getName().equals(mapclass)) {</span>
-<span class="source-line-no">1668</span><span id="line-1668"> throw new IOException("Class name for cache map mismatch: " + mapclass + ", expected:"</span>
-<span class="source-line-no">1669</span><span id="line-1669"> + backingMap.getClass().getName());</span>
-<span class="source-line-no">1670</span><span id="line-1670"> }</span>
-<span class="source-line-no">1671</span><span id="line-1671"> }</span>
-<span class="source-line-no">1672</span><span id="line-1672"></span>
-<span class="source-line-no">1673</span><span id="line-1673"> private void verifyFileIntegrity(BucketCacheProtos.BucketCacheEntry proto) {</span>
-<span class="source-line-no">1674</span><span id="line-1674"> try {</span>
-<span class="source-line-no">1675</span><span id="line-1675"> if (proto.hasChecksum()) {</span>
-<span class="source-line-no">1676</span><span id="line-1676"> ((PersistentIOEngine) ioEngine).verifyFileIntegrity(proto.getChecksum().toByteArray(),</span>
-<span class="source-line-no">1677</span><span id="line-1677"> algorithm);</span>
-<span class="source-line-no">1678</span><span id="line-1678"> }</span>
-<span class="source-line-no">1679</span><span id="line-1679"> backingMapValidated.set(true);</span>
-<span class="source-line-no">1680</span><span id="line-1680"> } catch (IOException e) {</span>
-<span class="source-line-no">1681</span><span id="line-1681"> LOG.warn("Checksum for cache file failed. "</span>
-<span class="source-line-no">1682</span><span id="line-1682"> + "We need to validate each cache key in the backing map. "</span>
-<span class="source-line-no">1683</span><span id="line-1683"> + "This may take some time, so we'll do it in a background thread,");</span>
-<span class="source-line-no">1684</span><span id="line-1684"></span>
-<span class="source-line-no">1685</span><span id="line-1685"> Runnable cacheValidator = () -> {</span>
-<span class="source-line-no">1686</span><span id="line-1686"> while (bucketAllocator == null) {</span>
-<span class="source-line-no">1687</span><span id="line-1687"> try {</span>
-<span class="source-line-no">1688</span><span id="line-1688"> Thread.sleep(50);</span>
-<span class="source-line-no">1689</span><span id="line-1689"> } catch (InterruptedException ex) {</span>
-<span class="source-line-no">1690</span><span id="line-1690"> throw new RuntimeException(ex);</span>
-<span class="source-line-no">1691</span><span id="line-1691"> }</span>
-<span class="source-line-no">1692</span><span id="line-1692"> }</span>
-<span class="source-line-no">1693</span><span id="line-1693"> long startTime = EnvironmentEdgeManager.currentTime();</span>
-<span class="source-line-no">1694</span><span id="line-1694"> int totalKeysOriginally = backingMap.size();</span>
-<span class="source-line-no">1695</span><span id="line-1695"> for (Map.Entry<BlockCacheKey, BucketEntry> keyEntry : backingMap.entrySet()) {</span>
-<span class="source-line-no">1696</span><span id="line-1696"> try {</span>
-<span class="source-line-no">1697</span><span id="line-1697"> ((FileIOEngine) ioEngine).checkCacheTime(keyEntry.getValue());</span>
-<span class="source-line-no">1698</span><span id="line-1698"> } catch (IOException e1) {</span>
-<span class="source-line-no">1699</span><span id="line-1699"> LOG.debug("Check for key {} failed. Evicting.", keyEntry.getKey());</span>
-<span class="source-line-no">1700</span><span id="line-1700"> evictBlock(keyEntry.getKey());</span>
-<span class="source-line-no">1701</span><span id="line-1701"> fileNotFullyCached(keyEntry.getKey(), keyEntry.getValue());</span>
-<span class="source-line-no">1702</span><span id="line-1702"> }</span>
-<span class="source-line-no">1703</span><span id="line-1703"> }</span>
-<span class="source-line-no">1704</span><span id="line-1704"> backingMapValidated.set(true);</span>
-<span class="source-line-no">1705</span><span id="line-1705"> LOG.info("Finished validating {} keys in the backing map. Recovered: {}. This took {}ms.",</span>
-<span class="source-line-no">1706</span><span id="line-1706"> totalKeysOriginally, backingMap.size(),</span>
-<span class="source-line-no">1707</span><span id="line-1707"> (EnvironmentEdgeManager.currentTime() - startTime));</span>
-<span class="source-line-no">1708</span><span id="line-1708"> };</span>
-<span class="source-line-no">1709</span><span id="line-1709"> Thread t = new Thread(cacheValidator);</span>
-<span class="source-line-no">1710</span><span id="line-1710"> t.setDaemon(true);</span>
-<span class="source-line-no">1711</span><span id="line-1711"> t.start();</span>
-<span class="source-line-no">1712</span><span id="line-1712"> }</span>
-<span class="source-line-no">1713</span><span id="line-1713"> }</span>
-<span class="source-line-no">1714</span><span id="line-1714"></span>
-<span class="source-line-no">1715</span><span id="line-1715"> private void updateCacheIndex(BucketCacheProtos.BackingMap chunk,</span>
-<span class="source-line-no">1716</span><span id="line-1716"> java.util.Map<java.lang.Integer, java.lang.String> deserializer) throws IOException {</span>
-<span class="source-line-no">1717</span><span id="line-1717"> Pair<ConcurrentHashMap<BlockCacheKey, BucketEntry>, NavigableSet<BlockCacheKey>> pair2 =</span>
-<span class="source-line-no">1718</span><span id="line-1718"> BucketProtoUtils.fromPB(deserializer, chunk, this::createRecycler);</span>
-<span class="source-line-no">1719</span><span id="line-1719"> backingMap.putAll(pair2.getFirst());</span>
-<span class="source-line-no">1720</span><span id="line-1720"> blocksByHFile.addAll(pair2.getSecond());</span>
-<span class="source-line-no">1721</span><span id="line-1721"> }</span>
-<span class="source-line-no">1722</span><span id="line-1722"></span>
-<span class="source-line-no">1723</span><span id="line-1723"> private void parsePB(BucketCacheProtos.BucketCacheEntry proto) throws IOException {</span>
-<span class="source-line-no">1724</span><span id="line-1724"> Pair<ConcurrentHashMap<BlockCacheKey, BucketEntry>, NavigableSet<BlockCacheKey>> pair =</span>
-<span class="source-line-no">1725</span><span id="line-1725"> BucketProtoUtils.fromPB(proto.getDeserializersMap(), proto.getBackingMap(),</span>
-<span class="source-line-no">1726</span><span id="line-1726"> this::createRecycler);</span>
-<span class="source-line-no">1727</span><span id="line-1727"> backingMap = pair.getFirst();</span>
-<span class="source-line-no">1728</span><span id="line-1728"> blocksByHFile = pair.getSecond();</span>
-<span class="source-line-no">1729</span><span id="line-1729"> fullyCachedFiles.clear();</span>
-<span class="source-line-no">1730</span><span id="line-1730"> fullyCachedFiles.putAll(BucketProtoUtils.fromPB(proto.getCachedFilesMap()));</span>
-<span class="source-line-no">1731</span><span id="line-1731"></span>
-<span class="source-line-no">1732</span><span id="line-1732"> LOG.info("After retrieval Backing map size: {}, fullyCachedFiles size: {}", backingMap.size(),</span>
-<span class="source-line-no">1733</span><span id="line-1733"> fullyCachedFiles.size());</span>
-<span class="source-line-no">1734</span><span id="line-1734"></span>
-<span class="source-line-no">1735</span><span id="line-1735"> verifyFileIntegrity(proto);</span>
-<span class="source-line-no">1736</span><span id="line-1736"> updateRegionSizeMapWhileRetrievingFromFile();</span>
-<span class="source-line-no">1737</span><span id="line-1737"> verifyCapacityAndClasses(proto.getCacheCapacity(), proto.getIoClass(), proto.getMapClass());</span>
-<span class="source-line-no">1738</span><span id="line-1738"> }</span>
-<span class="source-line-no">1739</span><span id="line-1739"></span>
-<span class="source-line-no">1740</span><span id="line-1740"> private void persistChunkedBackingMap(FileOutputStream fos) throws IOException {</span>
-<span class="source-line-no">1741</span><span id="line-1741"> LOG.debug(</span>
-<span class="source-line-no">1742</span><span id="line-1742"> "persistToFile: before persisting backing map size: {}, "</span>
-<span class="source-line-no">1743</span><span id="line-1743"> + "fullycachedFiles size: {}, chunkSize: {}",</span>
-<span class="source-line-no">1744</span><span id="line-1744"> backingMap.size(), fullyCachedFiles.size(), persistenceChunkSize);</span>
-<span class="source-line-no">1745</span><span id="line-1745"></span>
-<span class="source-line-no">1746</span><span id="line-1746"> BucketProtoUtils.serializeAsPB(this, fos, persistenceChunkSize);</span>
-<span class="source-line-no">1747</span><span id="line-1747"></span>
+<span class="source-line-no">1657</span><span id="line-1657"> private void dumpPrefetchList() {</span>
+<span class="source-line-no">1658</span><span id="line-1658"> for (Map.Entry<String, Pair<String, Long>> outerEntry : fullyCachedFiles.entrySet()) {</span>
+<span class="source-line-no">1659</span><span id="line-1659"> LOG.debug("Cached File Entry:<{},<{},{}>>", outerEntry.getKey(),</span>
+<span class="source-line-no">1660</span><span id="line-1660"> outerEntry.getValue().getFirst(), outerEntry.getValue().getSecond());</span>
+<span class="source-line-no">1661</span><span id="line-1661"> }</span>
+<span class="source-line-no">1662</span><span id="line-1662"> }</span>
+<span class="source-line-no">1663</span><span id="line-1663"></span>
+<span class="source-line-no">1664</span><span id="line-1664"> private void verifyCapacityAndClasses(long capacitySize, String ioclass, String mapclass)</span>
+<span class="source-line-no">1665</span><span id="line-1665"> throws IOException {</span>
+<span class="source-line-no">1666</span><span id="line-1666"> if (capacitySize != cacheCapacity) {</span>
+<span class="source-line-no">1667</span><span id="line-1667"> throw new IOException("Mismatched cache capacity:" + StringUtils.byteDesc(capacitySize)</span>
+<span class="source-line-no">1668</span><span id="line-1668"> + ", expected: " + StringUtils.byteDesc(cacheCapacity));</span>
+<span class="source-line-no">1669</span><span id="line-1669"> }</span>
+<span class="source-line-no">1670</span><span id="line-1670"> if (!ioEngine.getClass().getName().equals(ioclass)) {</span>
+<span class="source-line-no">1671</span><span id="line-1671"> throw new IOException("Class name for IO engine mismatch: " + ioclass + ", expected:"</span>
+<span class="source-line-no">1672</span><span id="line-1672"> + ioEngine.getClass().getName());</span>
+<span class="source-line-no">1673</span><span id="line-1673"> }</span>
+<span class="source-line-no">1674</span><span id="line-1674"> if (!backingMap.getClass().getName().equals(mapclass)) {</span>
+<span class="source-line-no">1675</span><span id="line-1675"> throw new IOException("Class name for cache map mismatch: " + mapclass + ", expected:"</span>
+<span class="source-line-no">1676</span><span id="line-1676"> + backingMap.getClass().getName());</span>
+<span class="source-line-no">1677</span><span id="line-1677"> }</span>
+<span class="source-line-no">1678</span><span id="line-1678"> }</span>
+<span class="source-line-no">1679</span><span id="line-1679"></span>
+<span class="source-line-no">1680</span><span id="line-1680"> private void verifyFileIntegrity(BucketCacheProtos.BucketCacheEntry proto) {</span>
+<span class="source-line-no">1681</span><span id="line-1681"> try {</span>
+<span class="source-line-no">1682</span><span id="line-1682"> if (proto.hasChecksum()) {</span>
+<span class="source-line-no">1683</span><span id="line-1683"> ((PersistentIOEngine) ioEngine).verifyFileIntegrity(proto.getChecksum().toByteArray(),</span>
+<span class="source-line-no">1684</span><span id="line-1684"> algorithm);</span>
+<span class="source-line-no">1685</span><span id="line-1685"> }</span>
+<span class="source-line-no">1686</span><span id="line-1686"> backingMapValidated.set(true);</span>
+<span class="source-line-no">1687</span><span id="line-1687"> } catch (IOException e) {</span>
+<span class="source-line-no">1688</span><span id="line-1688"> LOG.warn("Checksum for cache file failed. "</span>
+<span class="source-line-no">1689</span><span id="line-1689"> + "We need to validate each cache key in the backing map. "</span>
+<span class="source-line-no">1690</span><span id="line-1690"> + "This may take some time, so we'll do it in a background thread,");</span>
+<span class="source-line-no">1691</span><span id="line-1691"></span>
+<span class="source-line-no">1692</span><span id="line-1692"> Runnable cacheValidator = () -> {</span>
+<span class="source-line-no">1693</span><span id="line-1693"> while (bucketAllocator == null) {</span>
+<span class="source-line-no">1694</span><span id="line-1694"> try {</span>
+<span class="source-line-no">1695</span><span id="line-1695"> Thread.sleep(50);</span>
+<span class="source-line-no">1696</span><span id="line-1696"> } catch (InterruptedException ex) {</span>
+<span class="source-line-no">1697</span><span id="line-1697"> throw new RuntimeException(ex);</span>
+<span class="source-line-no">1698</span><span id="line-1698"> }</span>
+<span class="source-line-no">1699</span><span id="line-1699"> }</span>
+<span class="source-line-no">1700</span><span id="line-1700"> long startTime = EnvironmentEdgeManager.currentTime();</span>
+<span class="source-line-no">1701</span><span id="line-1701"> int totalKeysOriginally = backingMap.size();</span>
+<span class="source-line-no">1702</span><span id="line-1702"> for (Map.Entry<BlockCacheKey, BucketEntry> keyEntry : backingMap.entrySet()) {</span>
+<span class="source-line-no">1703</span><span id="line-1703"> try {</span>
+<span class="source-line-no">1704</span><span id="line-1704"> ((FileIOEngine) ioEngine).checkCacheTime(keyEntry.getValue());</span>
+<span class="source-line-no">1705</span><span id="line-1705"> } catch (IOException e1) {</span>
+<span class="source-line-no">1706</span><span id="line-1706"> LOG.debug("Check for key {} failed. Evicting.", keyEntry.getKey());</span>
+<span class="source-line-no">1707</span><span id="line-1707"> evictBlock(keyEntry.getKey());</span>
+<span class="source-line-no">1708</span><span id="line-1708"> fileNotFullyCached(keyEntry.getKey(), keyEntry.getValue());</span>
+<span class="source-line-no">1709</span><span id="line-1709"> }</span>
+<span class="source-line-no">1710</span><span id="line-1710"> }</span>
+<span class="source-line-no">1711</span><span id="line-1711"> backingMapValidated.set(true);</span>
+<span class="source-line-no">1712</span><span id="line-1712"> LOG.info("Finished validating {} keys in the backing map. Recovered: {}. This took {}ms.",</span>
+<span class="source-line-no">1713</span><span id="line-1713"> totalKeysOriginally, backingMap.size(),</span>
+<span class="source-line-no">1714</span><span id="line-1714"> (EnvironmentEdgeManager.currentTime() - startTime));</span>
+<span class="source-line-no">1715</span><span id="line-1715"> };</span>
+<span class="source-line-no">1716</span><span id="line-1716"> Thread t = new Thread(cacheValidator);</span>
+<span class="source-line-no">1717</span><span id="line-1717"> t.setDaemon(true);</span>
+<span class="source-line-no">1718</span><span id="line-1718"> t.start();</span>
+<span class="source-line-no">1719</span><span id="line-1719"> }</span>
+<span class="source-line-no">1720</span><span id="line-1720"> }</span>
+<span class="source-line-no">1721</span><span id="line-1721"></span>
+<span class="source-line-no">1722</span><span id="line-1722"> private void updateCacheIndex(BucketCacheProtos.BackingMap chunk,</span>
+<span class="source-line-no">1723</span><span id="line-1723"> java.util.Map<java.lang.Integer, java.lang.String> deserializer) throws IOException {</span>
+<span class="source-line-no">1724</span><span id="line-1724"> Pair<ConcurrentHashMap<BlockCacheKey, BucketEntry>, NavigableSet<BlockCacheKey>> pair2 =</span>
+<span class="source-line-no">1725</span><span id="line-1725"> BucketProtoUtils.fromPB(deserializer, chunk, this::createRecycler);</span>
+<span class="source-line-no">1726</span><span id="line-1726"> backingMap.putAll(pair2.getFirst());</span>
+<span class="source-line-no">1727</span><span id="line-1727"> blocksByHFile.addAll(pair2.getSecond());</span>
+<span class="source-line-no">1728</span><span id="line-1728"> }</span>
+<span class="source-line-no">1729</span><span id="line-1729"></span>
+<span class="source-line-no">1730</span><span id="line-1730"> private void parsePB(BucketCacheProtos.BucketCacheEntry proto) throws IOException {</span>
+<span class="source-line-no">1731</span><span id="line-1731"> Pair<ConcurrentHashMap<BlockCacheKey, BucketEntry>, NavigableSet<BlockCacheKey>> pair =</span>
+<span class="source-line-no">1732</span><span id="line-1732"> BucketProtoUtils.fromPB(proto.getDeserializersMap(), proto.getBackingMap(),</span>
+<span class="source-line-no">1733</span><span id="line-1733"> this::createRecycler);</span>
+<span class="source-line-no">1734</span><span id="line-1734"> backingMap = pair.getFirst();</span>
+<span class="source-line-no">1735</span><span id="line-1735"> blocksByHFile = pair.getSecond();</span>
+<span class="source-line-no">1736</span><span id="line-1736"> fullyCachedFiles.clear();</span>
+<span class="source-line-no">1737</span><span id="line-1737"> fullyCachedFiles.putAll(BucketProtoUtils.fromPB(proto.getCachedFilesMap()));</span>
+<span class="source-line-no">1738</span><span id="line-1738"></span>
+<span class="source-line-no">1739</span><span id="line-1739"> LOG.info("After retrieval Backing map size: {}, fullyCachedFiles size: {}", backingMap.size(),</span>
+<span class="source-line-no">1740</span><span id="line-1740"> fullyCachedFiles.size());</span>
+<span class="source-line-no">1741</span><span id="line-1741"></span>
+<span class="source-line-no">1742</span><span id="line-1742"> verifyFileIntegrity(proto);</span>
+<span class="source-line-no">1743</span><span id="line-1743"> updateRegionSizeMapWhileRetrievingFromFile();</span>
+<span class="source-line-no">1744</span><span id="line-1744"> verifyCapacityAndClasses(proto.getCacheCapacity(), proto.getIoClass(), proto.getMapClass());</span>
+<span class="source-line-no">1745</span><span id="line-1745"> }</span>
+<span class="source-line-no">1746</span><span id="line-1746"></span>
+<span class="source-line-no">1747</span><span id="line-1747"> private void persistChunkedBackingMap(FileOutputStream fos) throws IOException {</span>
<span class="source-line-no">1748</span><span id="line-1748"> LOG.debug(</span>
-<span class="source-line-no">1749</span><span id="line-1749"> "persistToFile: after persisting backing map size: {}, " + "fullycachedFiles size: {}",</span>
-<span class="source-line-no">1750</span><span id="line-1750"> backingMap.size(), fullyCachedFiles.size());</span>
-<span class="source-line-no">1751</span><span id="line-1751"> }</span>
+<span class="source-line-no">1749</span><span id="line-1749"> "persistToFile: before persisting backing map size: {}, "</span>
+<span class="source-line-no">1750</span><span id="line-1750"> + "fullycachedFiles size: {}, chunkSize: {}",</span>
+<span class="source-line-no">1751</span><span id="line-1751"> backingMap.size(), fullyCachedFiles.size(), persistenceChunkSize);</span>
<span class="source-line-no">1752</span><span id="line-1752"></span>
-<span class="source-line-no">1753</span><span id="line-1753"> private void retrieveChunkedBackingMap(FileInputStream in) throws IOException {</span>
-<span class="source-line-no">1754</span><span id="line-1754"> // Read the first chunk that has all the details.</span>
-<span class="source-line-no">1755</span><span id="line-1755"> BucketCacheProtos.BucketCacheEntry cacheEntry =</span>
-<span class="source-line-no">1756</span><span id="line-1756"> BucketCacheProtos.BucketCacheEntry.parseDelimitedFrom(in);</span>
-<span class="source-line-no">1757</span><span id="line-1757"></span>
-<span class="source-line-no">1758</span><span id="line-1758"> fullyCachedFiles.clear();</span>
-<span class="source-line-no">1759</span><span id="line-1759"> fullyCachedFiles.putAll(BucketProtoUtils.fromPB(cacheEntry.getCachedFilesMap()));</span>
-<span class="source-line-no">1760</span><span id="line-1760"></span>
-<span class="source-line-no">1761</span><span id="line-1761"> backingMap.clear();</span>
-<span class="source-line-no">1762</span><span id="line-1762"> blocksByHFile.clear();</span>
-<span class="source-line-no">1763</span><span id="line-1763"></span>
-<span class="source-line-no">1764</span><span id="line-1764"> // Read the backing map entries in batches.</span>
-<span class="source-line-no">1765</span><span id="line-1765"> int numChunks = 0;</span>
-<span class="source-line-no">1766</span><span id="line-1766"> while (in.available() > 0) {</span>
-<span class="source-line-no">1767</span><span id="line-1767"> updateCacheIndex(BucketCacheProtos.BackingMap.parseDelimitedFrom(in),</span>
-<span class="source-line-no">1768</span><span id="line-1768"> cacheEntry.getDeserializersMap());</span>
-<span class="source-line-no">1769</span><span id="line-1769"> numChunks++;</span>
+<span class="source-line-no">1753</span><span id="line-1753"> BucketProtoUtils.serializeAsPB(this, fos, persistenceChunkSize);</span>
+<span class="source-line-no">1754</span><span id="line-1754"></span>
+<span class="source-line-no">1755</span><span id="line-1755"> LOG.debug(</span>
+<span class="source-line-no">1756</span><span id="line-1756"> "persistToFile: after persisting backing map size: {}, " + "fullycachedFiles size: {}",</span>
+<span class="source-line-no">1757</span><span id="line-1757"> backingMap.size(), fullyCachedFiles.size());</span>
+<span class="source-line-no">1758</span><span id="line-1758"> }</span>
+<span class="source-line-no">1759</span><span id="line-1759"></span>
+<span class="source-line-no">1760</span><span id="line-1760"> private void retrieveChunkedBackingMap(FileInputStream in) throws IOException {</span>
+<span class="source-line-no">1761</span><span id="line-1761"> // Read the first chunk that has all the details.</span>
+<span class="source-line-no">1762</span><span id="line-1762"> BucketCacheProtos.BucketCacheEntry cacheEntry =</span>
+<span class="source-line-no">1763</span><span id="line-1763"> BucketCacheProtos.BucketCacheEntry.parseDelimitedFrom(in);</span>
+<span class="source-line-no">1764</span><span id="line-1764"></span>
+<span class="source-line-no">1765</span><span id="line-1765"> // HBASE-29857: Handle case where persistence file is empty.</span>
+<span class="source-line-no">1766</span><span id="line-1766"> // parseDelimitedFrom() returns null when there's no data to read.</span>
+<span class="source-line-no">1767</span><span id="line-1767"> // Note: Corrupted files would throw InvalidProtocolBufferException (subclass of IOException).</span>
+<span class="source-line-no">1768</span><span id="line-1768"> if (cacheEntry == null) {</span>
+<span class="source-line-no">1769</span><span id="line-1769"> throw new IOException("Failed to read cache entry from persistence file (file is empty)");</span>
<span class="source-line-no">1770</span><span id="line-1770"> }</span>
<span class="source-line-no">1771</span><span id="line-1771"></span>
-<span class="source-line-no">1772</span><span id="line-1772"> LOG.info("Retrieved {} of chunks with blockCount = {}.", numChunks, backingMap.size());</span>
-<span class="source-line-no">1773</span><span id="line-1773"> verifyFileIntegrity(cacheEntry);</span>
-<span class="source-line-no">1774</span><span id="line-1774"> verifyCapacityAndClasses(cacheEntry.getCacheCapacity(), cacheEntry.getIoClass(),</span>
-<span class="source-line-no">1775</span><span id="line-1775"> cacheEntry.getMapClass());</span>
-<span class="source-line-no">1776</span><span id="line-1776"> updateRegionSizeMapWhileRetrievingFromFile();</span>
-<span class="source-line-no">1777</span><span id="line-1777"> }</span>
-<span class="source-line-no">1778</span><span id="line-1778"></span>
-<span class="source-line-no">1779</span><span id="line-1779"> /**</span>
-<span class="source-line-no">1780</span><span id="line-1780"> * Check whether we tolerate IO error this time. If the duration of IOEngine throwing errors</span>
-<span class="source-line-no">1781</span><span id="line-1781"> * exceeds ioErrorsDurationTimeTolerated, we will disable the cache</span>
-<span class="source-line-no">1782</span><span id="line-1782"> */</span>
-<span class="source-line-no">1783</span><span id="line-1783"> private void checkIOErrorIsTolerated() {</span>
-<span class="source-line-no">1784</span><span id="line-1784"> long now = EnvironmentEdgeManager.currentTime();</span>
-<span class="source-line-no">1785</span><span id="line-1785"> // Do a single read to a local variable to avoid timing issue - HBASE-24454</span>
-<span class="source-line-no">1786</span><span id="line-1786"> long ioErrorStartTimeTmp = this.ioErrorStartTime;</span>
-<span class="source-line-no">1787</span><span id="line-1787"> if (ioErrorStartTimeTmp > 0) {</span>
-<span class="source-line-no">1788</span><span id="line-1788"> if (isCacheEnabled() && (now - ioErrorStartTimeTmp) > this.ioErrorsTolerationDuration) {</span>
-<span class="source-line-no">1789</span><span id="line-1789"> LOG.error("IO errors duration time has exceeded " + ioErrorsTolerationDuration</span>
-<span class="source-line-no">1790</span><span id="line-1790"> + "ms, disabling cache, please check your IOEngine");</span>
-<span class="source-line-no">1791</span><span id="line-1791"> disableCache();</span>
-<span class="source-line-no">1792</span><span id="line-1792"> }</span>
-<span class="source-line-no">1793</span><span id="line-1793"> } else {</span>
-<span class="source-line-no">1794</span><span id="line-1794"> this.ioErrorStartTime = now;</span>
-<span class="source-line-no">1795</span><span id="line-1795"> }</span>
-<span class="source-line-no">1796</span><span id="line-1796"> }</span>
-<span class="source-line-no">1797</span><span id="line-1797"></span>
-<span class="source-line-no">1798</span><span id="line-1798"> /**</span>
-<span class="source-line-no">1799</span><span id="line-1799"> * Used to shut down the cache -or- turn it off in the case of something broken.</span>
-<span class="source-line-no">1800</span><span id="line-1800"> */</span>
-<span class="source-line-no">1801</span><span id="line-1801"> private void disableCache() {</span>
-<span class="source-line-no">1802</span><span id="line-1802"> if (!isCacheEnabled()) {</span>
-<span class="source-line-no">1803</span><span id="line-1803"> return;</span>
-<span class="source-line-no">1804</span><span id="line-1804"> }</span>
-<span class="source-line-no">1805</span><span id="line-1805"> LOG.info("Disabling cache");</span>
-<span class="source-line-no">1806</span><span id="line-1806"> cacheState = CacheState.DISABLED;</span>
-<span class="source-line-no">1807</span><span id="line-1807"> ioEngine.shutdown();</span>
-<span class="source-line-no">1808</span><span id="line-1808"> this.scheduleThreadPool.shutdown();</span>
-<span class="source-line-no">1809</span><span id="line-1809"> for (int i = 0; i < writerThreads.length; ++i)</span>
-<span class="source-line-no">1810</span><span id="line-1810"> writerThreads[i].interrupt();</span>
-<span class="source-line-no">1811</span><span id="line-1811"> this.ramCache.clear();</span>
-<span class="source-line-no">1812</span><span id="line-1812"> if (!ioEngine.isPersistent() || persistencePath == null) {</span>
-<span class="source-line-no">1813</span><span id="line-1813"> // If persistent ioengine and a path, we will serialize out the backingMap.</span>
-<span class="source-line-no">1814</span><span id="line-1814"> this.backingMap.clear();</span>
-<span class="source-line-no">1815</span><span id="line-1815"> this.blocksByHFile.clear();</span>
-<span class="source-line-no">1816</span><span id="line-1816"> this.fullyCachedFiles.clear();</span>
-<span class="source-line-no">1817</span><span id="line-1817"> this.regionCachedSize.clear();</span>
+<span class="source-line-no">1772</span><span id="line-1772"> fullyCachedFiles.clear();</span>
+<span class="source-line-no">1773</span><span id="line-1773"> fullyCachedFiles.putAll(BucketProtoUtils.fromPB(cacheEntry.getCachedFilesMap()));</span>
+<span class="source-line-no">1774</span><span id="line-1774"></span>
+<span class="source-line-no">1775</span><span id="line-1775"> backingMap.clear();</span>
+<span class="source-line-no">1776</span><span id="line-1776"> blocksByHFile.clear();</span>
+<span class="source-line-no">1777</span><span id="line-1777"></span>
+<span class="source-line-no">1778</span><span id="line-1778"> // Read the backing map entries in batches.</span>
+<span class="source-line-no">1779</span><span id="line-1779"> int numChunks = 0;</span>
+<span class="source-line-no">1780</span><span id="line-1780"> while (in.available() > 0) {</span>
+<span class="source-line-no">1781</span><span id="line-1781"> updateCacheIndex(BucketCacheProtos.BackingMap.parseDelimitedFrom(in),</span>
+<span class="source-line-no">1782</span><span id="line-1782"> cacheEntry.getDeserializersMap());</span>
+<span class="source-line-no">1783</span><span id="line-1783"> numChunks++;</span>
+<span class="source-line-no">1784</span><span id="line-1784"> }</span>
+<span class="source-line-no">1785</span><span id="line-1785"></span>
+<span class="source-line-no">1786</span><span id="line-1786"> LOG.info("Retrieved {} of chunks with blockCount = {}.", numChunks, backingMap.size());</span>
+<span class="source-line-no">1787</span><span id="line-1787"> verifyFileIntegrity(cacheEntry);</span>
+<span class="source-line-no">1788</span><span id="line-1788"> verifyCapacityAndClasses(cacheEntry.getCacheCapacity(), cacheEntry.getIoClass(),</span>
+<span class="source-line-no">1789</span><span id="line-1789"> cacheEntry.getMapClass());</span>
+<span class="source-line-no">1790</span><span id="line-1790"> updateRegionSizeMapWhileRetrievingFromFile();</span>
+<span class="source-line-no">1791</span><span id="line-1791"> }</span>
+<span class="source-line-no">1792</span><span id="line-1792"></span>
+<span class="source-line-no">1793</span><span id="line-1793"> /**</span>
+<span class="source-line-no">1794</span><span id="line-1794"> * Check whether we tolerate IO error this time. If the duration of IOEngine throwing errors</span>
+<span class="source-line-no">1795</span><span id="line-1795"> * exceeds ioErrorsDurationTimeTolerated, we will disable the cache</span>
+<span class="source-line-no">1796</span><span id="line-1796"> */</span>
+<span class="source-line-no">1797</span><span id="line-1797"> private void checkIOErrorIsTolerated() {</span>
+<span class="source-line-no">1798</span><span id="line-1798"> long now = EnvironmentEdgeManager.currentTime();</span>
+<span class="source-line-no">1799</span><span id="line-1799"> // Do a single read to a local variable to avoid timing issue - HBASE-24454</span>
+<span class="source-line-no">1800</span><span id="line-1800"> long ioErrorStartTimeTmp = this.ioErrorStartTime;</span>
+<span class="source-line-no">1801</span><span id="line-1801"> if (ioErrorStartTimeTmp > 0) {</span>
+<span class="source-line-no">1802</span><span id="line-1802"> if (isCacheEnabled() && (now - ioErrorStartTimeTmp) > this.ioErrorsTolerationDuration) {</span>
+<span class="source-line-no">1803</span><span id="line-1803"> LOG.error("IO errors duration time has exceeded " + ioErrorsTolerationDuration</span>
+<span class="source-line-no">1804</span><span id="line-1804"> + "ms, disabling cache, please check your IOEngine");</span>
+<span class="source-line-no">1805</span><span id="line-1805"> disableCache();</span>
+<span class="source-line-no">1806</span><span id="line-1806"> }</span>
+<span class="source-line-no">1807</span><span id="line-1807"> } else {</span>
+<span class="source-line-no">1808</span><span id="line-1808"> this.ioErrorStartTime = now;</span>
+<span class="source-line-no">1809</span><span id="line-1809"> }</span>
+<span class="source-line-no">1810</span><span id="line-1810"> }</span>
+<span class="source-line-no">1811</span><span id="line-1811"></span>
+<span class="source-line-no">1812</span><span id="line-1812"> /**</span>
+<span class="source-line-no">1813</span><span id="line-1813"> * Used to shut down the cache -or- turn it off in the case of something broken.</span>
+<span class="source-line-no">1814</span><span id="line-1814"> */</span>
+<span class="source-line-no">1815</span><span id="line-1815"> private void disableCache() {</span>
+<span class="source-line-no">1816</span><span id="line-1816"> if (!isCacheEnabled()) {</span>
+<span class="source-line-no">1817</span><span id="line-1817"> return;</span>
<span class="source-line-no">1818</span><span id="line-1818"> }</span>
-<span class="source-line-no">1819</span><span id="line-1819"> if (cacheStats.getMetricsRollerScheduler() != null) {</span>
-<span class="source-line-no">1820</span><span id="line-1820"> cacheStats.getMetricsRollerScheduler().shutdownNow();</span>
-<span class="source-line-no">1821</span><span id="line-1821"> }</span>
-<span class="source-line-no">1822</span><span id="line-1822"> }</span>
-<span class="source-line-no">1823</span><span id="line-1823"></span>
-<span class="source-line-no">1824</span><span id="line-1824"> private void join() throws InterruptedException {</span>
-<span class="source-line-no">1825</span><span id="line-1825"> for (int i = 0; i < writerThreads.length; ++i)</span>
-<span class="source-line-no">1826</span><span id="line-1826"> writerThreads[i].join();</span>
-<span class="source-line-no">1827</span><span id="line-1827"> }</span>
-<span class="source-line-no">1828</span><span id="line-1828"></span>
-<span class="source-line-no">1829</span><span id="line-1829"> @Override</span>
-<span class="source-line-no">1830</span><span id="line-1830"> public void shutdown() {</span>
-<span class="source-line-no">1831</span><span id="line-1831"> if (isCacheEnabled()) {</span>
-<span class="source-line-no">1832</span><span id="line-1832"> disableCache();</span>
-<span class="source-line-no">1833</span><span id="line-1833"> LOG.info("Shutdown bucket cache: IO persistent=" + ioEngine.isPersistent()</span>
-<span class="source-line-no">1834</span><span id="line-1834"> + "; path to write=" + persistencePath);</span>
-<span class="source-line-no">1835</span><span id="line-1835"> if (ioEngine.isPersistent() && persistencePath != null) {</span>
-<span class="source-line-no">1836</span><span id="line-1836"> try {</span>
-<span class="source-line-no">1837</span><span id="line-1837"> join();</span>
-<span class="source-line-no">1838</span><span id="line-1838"> if (cachePersister != null) {</span>
-<span class="source-line-no">1839</span><span id="line-1839"> LOG.info("Shutting down cache persister thread.");</span>
-<span class="source-line-no">1840</span><span id="line-1840"> cachePersister.shutdown();</span>
-<span class="source-line-no">1841</span><span id="line-1841"> while (cachePersister.isAlive()) {</span>
-<span class="source-line-no">1842</span><span id="line-1842"> Thread.sleep(10);</span>
-<span class="source-line-no">1843</span><span id="line-1843"> }</span>
-<span class="source-line-no">1844</span><span id="line-1844"> }</span>
-<span class="source-line-no">1845</span><span id="line-1845"> persistToFile();</span>
-<span class="source-line-no">1846</span><span id="line-1846"> } catch (IOException ex) {</span>
-<span class="source-line-no">1847</span><span id="line-1847"> LOG.error("Unable to persist data on exit: " + ex.toString(), ex);</span>
-<span class="source-line-no">1848</span><span id="line-1848"> } catch (InterruptedException e) {</span>
-<span class="source-line-no">1849</span><span id="line-1849"> LOG.warn("Failed to persist data on exit", e);</span>
-<span class="source-line-no">1850</span><span id="line-1850"> }</span>
-<span class="source-line-no">1851</span><span id="line-1851"> }</span>
-<span class="source-line-no">1852</span><span id="line-1852"> }</span>
-<span class="source-line-no">1853</span><span id="line-1853"> }</span>
-<span class="source-line-no">1854</span><span id="line-1854"></span>
-<span class="source-line-no">1855</span><span id="line-1855"> /**</span>
-<span class="source-line-no">1856</span><span id="line-1856"> * Needed mostly for UTs that might run in the same VM and create different BucketCache instances</span>
-<span class="source-line-no">1857</span><span id="line-1857"> * on different UT methods.</span>
-<span class="source-line-no">1858</span><span id="line-1858"> */</span>
-<span class="source-line-no">1859</span><span id="line-1859"> @Override</span>
-<span class="source-line-no">1860</span><span id="line-1860"> protected void finalize() {</span>
-<span class="source-line-no">1861</span><span id="line-1861"> if (cachePersister != null && !cachePersister.isInterrupted()) {</span>
-<span class="source-line-no">1862</span><span id="line-1862"> cachePersister.interrupt();</span>
-<span class="source-line-no">1863</span><span id="line-1863"> }</span>
-<span class="source-line-no">1864</span><span id="line-1864"> }</span>
-<span class="source-line-no">1865</span><span id="line-1865"></span>
-<span class="source-line-no">1866</span><span id="line-1866"> @Override</span>
-<span class="source-line-no">1867</span><span id="line-1867"> public CacheStats getStats() {</span>
-<span class="source-line-no">1868</span><span id="line-1868"> return cacheStats;</span>
-<span class="source-line-no">1869</span><span id="line-1869"> }</span>
-<span class="source-line-no">1870</span><span id="line-1870"></span>
-<span class="source-line-no">1871</span><span id="line-1871"> public BucketAllocator getAllocator() {</span>
-<span class="source-line-no">1872</span><span id="line-1872"> return this.bucketAllocator;</span>
-<span class="source-line-no">1873</span><span id="line-1873"> }</span>
-<span class="source-line-no">1874</span><span id="line-1874"></span>
-<span class="source-line-no">1875</span><span id="line-1875"> @Override</span>
-<span class="source-line-no">1876</span><span id="line-1876"> public long heapSize() {</span>
-<span class="source-line-no">1877</span><span id="line-1877"> return this.heapSize.sum();</span>
+<span class="source-line-no">1819</span><span id="line-1819"> LOG.info("Disabling cache");</span>
+<span class="source-line-no">1820</span><span id="line-1820"> cacheState = CacheState.DISABLED;</span>
+<span class="source-line-no">1821</span><span id="line-1821"> ioEngine.shutdown();</span>
+<span class="source-line-no">1822</span><span id="line-1822"> this.scheduleThreadPool.shutdown();</span>
+<span class="source-line-no">1823</span><span id="line-1823"> for (int i = 0; i < writerThreads.length; ++i)</span>
+<span class="source-line-no">1824</span><span id="line-1824"> writerThreads[i].interrupt();</span>
+<span class="source-line-no">1825</span><span id="line-1825"> this.ramCache.clear();</span>
+<span class="source-line-no">1826</span><span id="line-1826"> if (!ioEngine.isPersistent() || persistencePath == null) {</span>
+<span class="source-line-no">1827</span><span id="line-1827"> // If persistent ioengine and a path, we will serialize out the backingMap.</span>
+<span class="source-line-no">1828</span><span id="line-1828"> this.backingMap.clear();</span>
+<span class="source-line-no">1829</span><span id="line-1829"> this.blocksByHFile.clear();</span>
+<span class="source-line-no">1830</span><span id="line-1830"> this.fullyCachedFiles.clear();</span>
+<span class="source-line-no">1831</span><span id="line-1831"> this.regionCachedSize.clear();</span>
+<span class="source-line-no">1832</span><span id="line-1832"> }</span>
+<span class="source-line-no">1833</span><span id="line-1833"> if (cacheStats.getMetricsRollerScheduler() != null) {</span>
+<span class="source-line-no">1834</span><span id="line-1834"> cacheStats.getMetricsRollerScheduler().shutdownNow();</span>
+<span class="source-line-no">1835</span><span id="line-1835"> }</span>
+<span class="source-line-no">1836</span><span id="line-1836"> }</span>
+<span class="source-line-no">1837</span><span id="line-1837"></span>
+<span class="source-line-no">1838</span><span id="line-1838"> private void join() throws InterruptedException {</span>
+<span class="source-line-no">1839</span><span id="line-1839"> for (int i = 0; i < writerThreads.length; ++i)</span>
+<span class="source-line-no">1840</span><span id="line-1840"> writerThreads[i].join();</span>
+<span class="source-line-no">1841</span><span id="line-1841"> }</span>
+<span class="source-line-no">1842</span><span id="line-1842"></span>
+<span class="source-line-no">1843</span><span id="line-1843"> @Override</span>
+<span class="source-line-no">1844</span><span id="line-1844"> public void shutdown() {</span>
+<span class="source-line-no">1845</span><span id="line-1845"> if (isCacheEnabled()) {</span>
+<span class="source-line-no">1846</span><span id="line-1846"> disableCache();</span>
+<span class="source-line-no">1847</span><span id="line-1847"> LOG.info("Shutdown bucket cache: IO persistent=" + ioEngine.isPersistent()</span>
+<span class="source-line-no">1848</span><span id="line-1848"> + "; path to write=" + persistencePath);</span>
+<span class="source-line-no">1849</span><span id="line-1849"> if (ioEngine.isPersistent() && persistencePath != null) {</span>
+<span class="source-line-no">1850</span><span id="line-1850"> try {</span>
+<span class="source-line-no">1851</span><span id="line-1851"> join();</span>
+<span class="source-line-no">1852</span><span id="line-1852"> if (cachePersister != null) {</span>
+<span class="source-line-no">1853</span><span id="line-1853"> LOG.info("Shutting down cache persister thread.");</span>
+<span class="source-line-no">1854</span><span id="line-1854"> cachePersister.shutdown();</span>
+<span class="source-line-no">1855</span><span id="line-1855"> while (cachePersister.isAlive()) {</span>
+<span class="source-line-no">1856</span><span id="line-1856"> Thread.sleep(10);</span>
+<span class="source-line-no">1857</span><span id="line-1857"> }</span>
+<span class="source-line-no">1858</span><span id="line-1858"> }</span>
+<span class="source-line-no">1859</span><span id="line-1859"> persistToFile();</span>
+<span class="source-line-no">1860</span><span id="line-1860"> } catch (IOException ex) {</span>
+<span class="source-line-no">1861</span><span id="line-1861"> LOG.error("Unable to persist data on exit: " + ex.toString(), ex);</span>
+<span class="source-line-no">1862</span><span id="line-1862"> } catch (InterruptedException e) {</span>
+<span class="source-line-no">1863</span><span id="line-1863"> LOG.warn("Failed to persist data on exit", e);</span>
+<span class="source-line-no">1864</span><span id="line-1864"> }</span>
+<span class="source-line-no">1865</span><span id="line-1865"> }</span>
+<span class="source-line-no">1866</span><span id="line-1866"> }</span>
+<span class="source-line-no">1867</span><span id="line-1867"> }</span>
+<span class="source-line-no">1868</span><span id="line-1868"></span>
+<span class="source-line-no">1869</span><span id="line-1869"> /**</span>
+<span class="source-line-no">1870</span><span id="line-1870"> * Needed mostly for UTs that might run in the same VM and create different BucketCache instances</span>
+<span class="source-line-no">1871</span><span id="line-1871"> * on different UT methods.</span>
+<span class="source-line-no">1872</span><span id="line-1872"> */</span>
+<span class="source-line-no">1873</span><span id="line-1873"> @Override</span>
+<span class="source-line-no">1874</span><span id="line-1874"> protected void finalize() {</span>
+<span class="source-line-no">1875</span><span id="line-1875"> if (cachePersister != null && !cachePersister.isInterrupted()) {</span>
+<span class="source-line-no">1876</span><span id="line-1876"> cachePersister.interrupt();</span>
+<span class="source-line-no">1877</span><span id="line-1877"> }</span>
<span class="source-line-no">1878</span><span id="line-1878"> }</span>
<span class="source-line-no">1879</span><span id="line-1879"></span>
<span class="source-line-no">1880</span><span id="line-1880"> @Override</span>
-<span class="source-line-no">1881</span><span id="line-1881"> public long size() {</span>
-<span class="source-line-no">1882</span><span id="line-1882"> return this.realCacheSize.sum();</span>
+<span class="source-line-no">1881</span><span id="line-1881"> public CacheStats getStats() {</span>
+<span class="source-line-no">1882</span><span id="line-1882"> return cacheStats;</span>
<span class="source-line-no">1883</span><span id="line-1883"> }</span>
<span class="source-line-no">1884</span><span id="line-1884"></span>
-<span class="source-line-no">1885</span><span id="line-1885"> @Override</span>
-<span class="source-line-no">1886</span><span id="line-1886"> public long getCurrentDataSize() {</span>
-<span class="source-line-no">1887</span><span id="line-1887"> return size();</span>
-<span class="source-line-no">1888</span><span id="line-1888"> }</span>
-<span class="source-line-no">1889</span><span id="line-1889"></span>
-<span class="source-line-no">1890</span><span id="line-1890"> @Override</span>
-<span class="source-line-no">1891</span><span id="line-1891"> public long getFreeSize() {</span>
-<span class="source-line-no">1892</span><span id="line-1892"> if (!isCacheInitialized("BucketCache:getFreeSize")) {</span>
-<span class="source-line-no">1893</span><span id="line-1893"> return 0;</span>
-<span class="source-line-no">1894</span><span id="line-1894"> }</span>
-<span class="source-line-no">1895</span><span id="line-1895"> return this.bucketAllocator.getFreeSize();</span>
-<span class="source-line-no">1896</span><span id="line-1896"> }</span>
-<span class="source-line-no">1897</span><span id="line-1897"></span>
-<span class="source-line-no">1898</span><span id="line-1898"> @Override</span>
-<span class="source-line-no">1899</span><span id="line-1899"> public long getBlockCount() {</span>
-<span class="source-line-no">1900</span><span id="line-1900"> return this.blockNumber.sum();</span>
-<span class="source-line-no">1901</span><span id="line-1901"> }</span>
-<span class="source-line-no">1902</span><span id="line-1902"></span>
-<span class="source-line-no">1903</span><span id="line-1903"> @Override</span>
-<span class="source-line-no">1904</span><span id="line-1904"> public long getDataBlockCount() {</span>
-<span class="source-line-no">1905</span><span id="line-1905"> return getBlockCount();</span>
-<span class="source-line-no">1906</span><span id="line-1906"> }</span>
-<span class="source-line-no">1907</span><span id="line-1907"></span>
-<span class="source-line-no">1908</span><span id="line-1908"> @Override</span>
-<span class="source-line-no">1909</span><span id="line-1909"> public long getCurrentSize() {</span>
-<span class="source-line-no">1910</span><span id="line-1910"> if (!isCacheInitialized("BucketCache::getCurrentSize")) {</span>
-<span class="source-line-no">1911</span><span id="line-1911"> return 0;</span>
-<span class="source-line-no">1912</span><span id="line-1912"> }</span>
-<span class="source-line-no">1913</span><span id="line-1913"> return this.bucketAllocator.getUsedSize();</span>
-<span class="source-line-no">1914</span><span id="line-1914"> }</span>
-<span class="source-line-no">1915</span><span id="line-1915"></span>
-<span class="source-line-no">1916</span><span id="line-1916"> protected String getAlgorithm() {</span>
-<span class="source-line-no">1917</span><span id="line-1917"> return algorithm;</span>
-<span class="source-line-no">1918</span><span id="line-1918"> }</span>
-<span class="source-line-no">1919</span><span id="line-1919"></span>
-<span class="source-line-no">1920</span><span id="line-1920"> /**</span>
-<span class="source-line-no">1921</span><span id="line-1921"> * Evicts all blocks for a specific HFile.</span>
-<span class="source-line-no">1922</span><span id="line-1922"> * <p></span>
-<span class="source-line-no">1923</span><span id="line-1923"> * This is used for evict-on-close to remove all blocks of a specific HFile.</span>
-<span class="source-line-no">1924</span><span id="line-1924"> * @return the number of blocks evicted</span>
-<span class="source-line-no">1925</span><span id="line-1925"> */</span>
-<span class="source-line-no">1926</span><span id="line-1926"> @Override</span>
-<span class="source-line-no">1927</span><span id="line-1927"> public int evictBlocksByHfileName(String hfileName) {</span>
-<span class="source-line-no">1928</span><span id="line-1928"> return evictBlocksRangeByHfileName(hfileName, 0, Long.MAX_VALUE);</span>
-<span class="source-line-no">1929</span><span id="line-1929"> }</span>
-<span class="source-line-no">1930</span><span id="line-1930"></span>
-<span class="source-line-no">1931</span><span id="line-1931"> @Override</span>
-<span class="source-line-no">1932</span><span id="line-1932"> public int evictBlocksRangeByHfileName(String hfileName, long initOffset, long endOffset) {</span>
-<span class="source-line-no">1933</span><span id="line-1933"> Set<BlockCacheKey> keySet = getAllCacheKeysForFile(hfileName, initOffset, endOffset);</span>
-<span class="source-line-no">1934</span><span id="line-1934"> // We need to make sure whether we are evicting all blocks for this given file. In case of</span>
-<span class="source-line-no">1935</span><span id="line-1935"> // split references, we might be evicting just half of the blocks</span>
-<span class="source-line-no">1936</span><span id="line-1936"> LOG.debug("found {} blocks for file {}, starting offset: {}, end offset: {}", keySet.size(),</span>
-<span class="source-line-no">1937</span><span id="line-1937"> hfileName, initOffset, endOffset);</span>
-<span class="source-line-no">1938</span><span id="line-1938"> int numEvicted = 0;</span>
-<span class="source-line-no">1939</span><span id="line-1939"> for (BlockCacheKey key : keySet) {</span>
-<span class="source-line-no">1940</span><span id="line-1940"> if (evictBlock(key)) {</span>
-<span class="source-line-no">1941</span><span id="line-1941"> ++numEvicted;</span>
-<span class="source-line-no">1942</span><span id="line-1942"> }</span>
-<span class="source-line-no">1943</span><span id="line-1943"> }</span>
-<span class="source-line-no">1944</span><span id="line-1944"> return numEvicted;</span>
-<span class="source-line-no">1945</span><span id="line-1945"> }</span>
-<span class="source-line-no">1946</span><span id="line-1946"></span>
-<span class="source-line-no">1947</span><span id="line-1947"> private Set<BlockCacheKey> getAllCacheKeysForFile(String hfileName, long init, long end) {</span>
-<span class="source-line-no">1948</span><span id="line-1948"> // These keys are just for comparison and are short lived, so we need only file name and offset</span>
-<span class="source-line-no">1949</span><span id="line-1949"> return blocksByHFile.subSet(new BlockCacheKey(hfileName, init), true,</span>
-<span class="source-line-no">1950</span><span id="line-1950"> new BlockCacheKey(hfileName, end), true);</span>
-<span class="source-line-no">1951</span><span id="line-1951"> }</span>
-<span class="source-line-no">1952</span><span id="line-1952"></span>
-<span class="source-line-no">1953</span><span id="line-1953"> /**</span>
-<span class="source-line-no">1954</span><span id="line-1954"> * Used to group bucket entries into priority buckets. There will be a BucketEntryGroup for each</span>
-<span class="source-line-no">1955</span><span id="line-1955"> * priority (single, multi, memory). Once bucketed, the eviction algorithm takes the appropriate</span>
-<span class="source-line-no">1956</span><span id="line-1956"> * number of elements out of each according to configuration parameters and their relative sizes.</span>
-<span class="source-line-no">1957</span><span id="line-1957"> */</span>
-<span class="source-line-no">1958</span><span id="line-1958"> private class BucketEntryGroup {</span>
-<span class="source-line-no">1959</span><span id="line-1959"></span>
-<span class="source-line-no">1960</span><span id="line-1960"> private CachedEntryQueue queue;</span>
-<span class="source-line-no">1961</span><span id="line-1961"> private long totalSize = 0;</span>
-<span class="source-line-no">1962</span><span id="line-1962"> private long bucketSize;</span>
-<span class="source-line-no">1963</span><span id="line-1963"></span>
-<span class="source-line-no">1964</span><span id="line-1964"> public BucketEntryGroup(long bytesToFree, long blockSize, long bucketSize) {</span>
-<span class="source-line-no">1965</span><span id="line-1965"> this.bucketSize = bucketSize;</span>
-<span class="source-line-no">1966</span><span id="line-1966"> queue = new CachedEntryQueue(bytesToFree, blockSize);</span>
-<span class="source-line-no">1967</span><span id="line-1967"> totalSize = 0;</span>
-<span class="source-line-no">1968</span><span id="line-1968"> }</span>
-<span class="source-line-no">1969</span><span id="line-1969"></span>
-<span class="source-line-no">1970</span><span id="line-1970"> public void add(Map.Entry<BlockCacheKey, BucketEntry> block) {</span>
-<span class="source-line-no">1971</span><span id="line-1971"> totalSize += block.getValue().getLength();</span>
-<span class="source-line-no">1972</span><span id="line-1972"> queue.add(block);</span>
-<span class="source-line-no">1973</span><span id="line-1973"> }</span>
-<span class="source-line-no">1974</span><span id="line-1974"></span>
-<span class="source-line-no">1975</span><span id="line-1975"> public long free(long toFree) {</span>
-<span class="source-line-no">1976</span><span id="line-1976"> Map.Entry<BlockCacheKey, BucketEntry> entry;</span>
-<span class="source-line-no">1977</span><span id="line-1977"> long freedBytes = 0;</span>
-<span class="source-line-no">1978</span><span id="line-1978"> // TODO avoid a cycling siutation. We find no block which is not in use and so no way to free</span>
-<span class="source-line-no">1979</span><span id="line-1979"> // What to do then? Caching attempt fail? Need some changes in cacheBlock API?</span>
-<span class="source-line-no">1980</span><span id="line-1980"> while ((entry = queue.pollLast()) != null) {</span>
-<span class="source-line-no">1981</span><span id="line-1981"> BlockCacheKey blockCacheKey = entry.getKey();</span>
-<span class="source-line-no">1982</span><span id="line-1982"> BucketEntry be = entry.getValue();</span>
-<span class="source-line-no">1983</span><span id="line-1983"> if (evictBucketEntryIfNoRpcReferenced(blockCacheKey, be)) {</span>
-<span class="source-line-no">1984</span><span id="line-1984"> freedBytes += be.getLength();</span>
-<span class="source-line-no">1985</span><span id="line-1985"> }</span>
-<span class="source-line-no">1986</span><span id="line-1986"> if (freedBytes >= toFree) {</span>
-<span class="source-line-no">1987</span><span id="line-1987"> return freedBytes;</span>
-<span class="source-line-no">1988</span><span id="line-1988"> }</span>
-<span class="source-line-no">1989</span><span id="line-1989"> }</span>
-<span class="source-line-no">1990</span><span id="line-1990"> return freedBytes;</span>
-<span class="source-line-no">1991</span><span id="line-1991"> }</span>
-<span class="source-line-no">1992</span><span id="line-1992"></span>
-<span class="source-line-no">1993</span><span id="line-1993"> public long overflow() {</span>
-<span class="source-line-no">1994</span><span id="line-1994"> return totalSize - bucketSize;</span>
-<span class="source-line-no">1995</span><span id="line-1995"> }</span>
-<span class="source-line-no">1996</span><span id="line-1996"></span>
-<span class="source-line-no">1997</span><span id="line-1997"> public long totalSize() {</span>
-<span class="source-line-no">1998</span><span id="line-1998"> return totalSize;</span>
-<span class="source-line-no">1999</span><span id="line-1999"> }</span>
-<span class="source-line-no">2000</span><span id="line-2000"> }</span>
-<span class="source-line-no">2001</span><span id="line-2001"></span>
-<span class="source-line-no">2002</span><span id="line-2002"> /**</span>
-<span class="source-line-no">2003</span><span id="line-2003"> * Block Entry stored in the memory with key,data and so on</span>
-<span class="source-line-no">2004</span><span id="line-2004"> */</span>
-<span class="source-line-no">2005</span><span id="line-2005"> static class RAMQueueEntry {</span>
-<span class="source-line-no">2006</span><span id="line-2006"> private final BlockCacheKey key;</span>
-<span class="source-line-no">2007</span><span id="line-2007"> private final Cacheable data;</span>
-<span class="source-line-no">2008</span><span id="line-2008"> private long accessCounter;</span>
-<span class="source-line-no">2009</span><span id="line-2009"> private boolean inMemory;</span>
-<span class="source-line-no">2010</span><span id="line-2010"> private boolean isCachePersistent;</span>
-<span class="source-line-no">2011</span><span id="line-2011"></span>
-<span class="source-line-no">2012</span><span id="line-2012"> private boolean isPrefetch;</span>
-<span class="source-line-no">2013</span><span id="line-2013"></span>
-<span class="source-line-no">2014</span><span id="line-2014"> RAMQueueEntry(BlockCacheKey bck, Cacheable data, long accessCounter, boolean inMemory,</span>
-<span class="source-line-no">2015</span><span id="line-2015"> boolean isCachePersistent, boolean isPrefetch) {</span>
-<span class="source-line-no">2016</span><span id="line-2016"> this.key = bck;</span>
-<span class="source-line-no">2017</span><span id="line-2017"> this.data = data;</span>
-<span class="source-line-no">2018</span><span id="line-2018"> this.accessCounter = accessCounter;</span>
-<span class="source-line-no">2019</span><span id="line-2019"> this.inMemory = inMemory;</span>
-<span class="source-line-no">2020</span><span id="line-2020"> this.isCachePersistent = isCachePersistent;</span>
-<span class="source-line-no">2021</span><span id="line-2021"> this.isPrefetch = isPrefetch;</span>
-<span class="source-line-no">2022</span><span id="line-2022"> }</span>
-<span class="source-line-no">2023</span><span id="line-2023"></span>
-<span class="source-line-no">2024</span><span id="line-2024"> public Cacheable getData() {</span>
-<span class="source-line-no">2025</span><span id="line-2025"> return data;</span>
-<span class="source-line-no">2026</span><span id="line-2026"> }</span>
+<span class="source-line-no">1885</span><span id="line-1885"> public BucketAllocator getAllocator() {</span>
+<span class="source-line-no">1886</span><span id="line-1886"> return this.bucketAllocator;</span>
+<span class="source-line-no">1887</span><span id="line-1887"> }</span>
+<span class="source-line-no">1888</span><span id="line-1888"></span>
+<span class="source-line-no">1889</span><span id="line-1889"> @Override</span>
+<span class="source-line-no">1890</span><span id="line-1890"> public long heapSize() {</span>
+<span class="source-line-no">1891</span><span id="line-1891"> return this.heapSize.sum();</span>
+<span class="source-line-no">1892</span><span id="line-1892"> }</span>
+<span class="source-line-no">1893</span><span id="line-1893"></span>
+<span class="source-line-no">1894</span><span id="line-1894"> @Override</span>
+<span class="source-line-no">1895</span><span id="line-1895"> public long size() {</span>
+<span class="source-line-no">1896</span><span id="line-1896"> return this.realCacheSize.sum();</span>
+<span class="source-line-no">1897</span><span id="line-1897"> }</span>
+<span class="source-line-no">1898</span><span id="line-1898"></span>
+<span class="source-line-no">1899</span><span id="line-1899"> @Override</span>
+<span class="source-line-no">1900</span><span id="line-1900"> public long getCurrentDataSize() {</span>
+<span class="source-line-no">1901</span><span id="line-1901"> return size();</span>
+<span class="source-line-no">1902</span><span id="line-1902"> }</span>
+<span class="source-line-no">1903</span><span id="line-1903"></span>
+<span class="source-line-no">1904</span><span id="line-1904"> @Override</span>
+<span class="source-line-no">1905</span><span id="line-1905"> public long getFreeSize() {</span>
+<span class="source-line-no">1906</span><span id="line-1906"> if (!isCacheInitialized("BucketCache:getFreeSize")) {</span>
+<span class="source-line-no">1907</span><span id="line-1907"> return 0;</span>
+<span class="source-line-no">1908</span><span id="line-1908"> }</span>
+<span class="source-line-no">1909</span><span id="line-1909"> return this.bucketAllocator.getFreeSize();</span>
+<span class="source-line-no">1910</span><span id="line-1910"> }</span>
+<span class="source-line-no">1911</span><span id="line-1911"></span>
+<span class="source-line-no">1912</span><span id="line-1912"> @Override</span>
+<span class="source-line-no">1913</span><span id="line-1913"> public long getBlockCount() {</span>
+<span class="source-line-no">1914</span><span id="line-1914"> return this.blockNumber.sum();</span>
+<span class="source-line-no">1915</span><span id="line-1915"> }</span>
+<span class="source-line-no">1916</span><span id="line-1916"></span>
+<span class="source-line-no">1917</span><span id="line-1917"> @Override</span>
+<span class="source-line-no">1918</span><span id="line-1918"> public long getDataBlockCount() {</span>
+<span class="source-line-no">1919</span><span id="line-1919"> return getBlockCount();</span>
+<span class="source-line-no">1920</span><span id="line-1920"> }</span>
+<span class="source-line-no">1921</span><span id="line-1921"></span>
+<span class="source-line-no">1922</span><span id="line-1922"> @Override</span>
+<span class="source-line-no">1923</span><span id="line-1923"> public long getCurrentSize() {</span>
+<span class="source-line-no">1924</span><span id="line-1924"> if (!isCacheInitialized("BucketCache::getCurrentSize")) {</span>
+<span class="source-line-no">1925</span><span id="line-1925"> return 0;</span>
+<span class="source-line-no">1926</span><span id="line-1926"> }</span>
+<span class="source-line-no">1927</span><span id="line-1927"> return this.bucketAllocator.getUsedSize();</span>
+<span class="source-line-no">1928</span><span id="line-1928"> }</span>
+<span class="source-line-no">1929</span><span id="line-1929"></span>
+<span class="source-line-no">1930</span><span id="line-1930"> protected String getAlgorithm() {</span>
+<span class="source-line-no">1931</span><span id="line-1931"> return algorithm;</span>
+<span class="source-line-no">1932</span><span id="line-1932"> }</span>
+<span class="source-line-no">1933</span><span id="line-1933"></span>
+<span class="source-line-no">1934</span><span id="line-1934"> /**</span>
+<span class="source-line-no">1935</span><span id="line-1935"> * Evicts all blocks for a specific HFile.</span>
+<span class="source-line-no">1936</span><span id="line-1936"> * <p></span>
+<span class="source-line-no">1937</span><span id="line-1937"> * This is used for evict-on-close to remove all blocks of a specific HFile.</span>
+<span class="source-line-no">1938</span><span id="line-1938"> * @return the number of blocks evicted</span>
+<span class="source-line-no">1939</span><span id="line-1939"> */</span>
+<span class="source-line-no">1940</span><span id="line-1940"> @Override</span>
+<span class="source-line-no">1941</span><span id="line-1941"> public int evictBlocksByHfileName(String hfileName) {</span>
+<span class="source-line-no">1942</span><span id="line-1942"> return evictBlocksRangeByHfileName(hfileName, 0, Long.MAX_VALUE);</span>
+<span class="source-line-no">1943</span><span id="line-1943"> }</span>
+<span class="source-line-no">1944</span><span id="line-1944"></span>
+<span class="source-line-no">1945</span><span id="line-1945"> @Override</span>
+<span class="source-line-no">1946</span><span id="line-1946"> public int evictBlocksRangeByHfileName(String hfileName, long initOffset, long endOffset) {</span>
+<span class="source-line-no">1947</span><span id="line-1947"> Set<BlockCacheKey> keySet = getAllCacheKeysForFile(hfileName, initOffset, endOffset);</span>
+<span class="source-line-no">1948</span><span id="line-1948"> // We need to make sure whether we are evicting all blocks for this given file. In case of</span>
+<span class="source-line-no">1949</span><span id="line-1949"> // split references, we might be evicting just half of the blocks</span>
+<span class="source-line-no">1950</span><span id="line-1950"> LOG.debug("found {} blocks for file {}, starting offset: {}, end offset: {}", keySet.size(),</span>
+<span class="source-line-no">1951</span><span id="line-1951"> hfileName, initOffset, endOffset);</span>
+<span class="source-line-no">1952</span><span id="line-1952"> int numEvicted = 0;</span>
+<span class="source-line-no">1953</span><span id="line-1953"> for (BlockCacheKey key : keySet) {</span>
+<span class="source-line-no">1954</span><span id="line-1954"> if (evictBlock(key)) {</span>
+<span class="source-line-no">1955</span><span id="line-1955"> ++numEvicted;</span>
+<span class="source-line-no">1956</span><span id="line-1956"> }</span>
+<span class="source-line-no">1957</span><span id="line-1957"> }</span>
+<span class="source-line-no">1958</span><span id="line-1958"> return numEvicted;</span>
+<span class="source-line-no">1959</span><span id="line-1959"> }</span>
+<span class="source-line-no">1960</span><span id="line-1960"></span>
+<span class="source-line-no">1961</span><span id="line-1961"> private Set<BlockCacheKey> getAllCacheKeysForFile(String hfileName, long init, long end) {</span>
+<span class="source-line-no">1962</span><span id="line-1962"> // These keys are just for comparison and are short lived, so we need only file name and offset</span>
+<span class="source-line-no">1963</span><span id="line-1963"> return blocksByHFile.subSet(new BlockCacheKey(hfileName, init), true,</span>
+<span class="source-line-no">1964</span><span id="line-1964"> new BlockCacheKey(hfileName, end), true);</span>
+<span class="source-line-no">1965</span><span id="line-1965"> }</span>
+<span class="source-line-no">1966</span><span id="line-1966"></span>
+<span class="source-line-no">1967</span><span id="line-1967"> /**</span>
+<span class="source-line-no">1968</span><span id="line-1968"> * Used to group bucket entries into priority buckets. There will be a BucketEntryGroup for each</span>
+<span class="source-line-no">1969</span><span id="line-1969"> * priority (single, multi, memory). Once bucketed, the eviction algorithm takes the appropriate</span>
+<span class="source-line-no">1970</span><span id="line-1970"> * number of elements out of each according to configuration parameters and their relative sizes.</span>
+<span class="source-line-no">1971</span><span id="line-1971"> */</span>
+<span class="source-line-no">1972</span><span id="line-1972"> private class BucketEntryGroup {</span>
+<span class="source-line-no">1973</span><span id="line-1973"></span>
+<span class="source-line-no">1974</span><span id="line-1974"> private CachedEntryQueue queue;</span>
+<span class="source-line-no">1975</span><span id="line-1975"> private long totalSize = 0;</span>
+<span class="source-line-no">1976</span><span id="line-1976"> private long bucketSize;</span>
+<span class="source-line-no">1977</span><span id="line-1977"></span>
+<span class="source-line-no">1978</span><span id="line-1978"> public BucketEntryGroup(long bytesToFree, long blockSize, long bucketSize) {</span>
+<span class="source-line-no">1979</span><span id="line-1979"> this.bucketSize = bucketSize;</span>
+<span class="source-line-no">1980</span><span id="line-1980"> queue = new CachedEntryQueue(bytesToFree, blockSize);</span>
+<span class="source-line-no">1981</span><span id="line-1981"> totalSize = 0;</span>
+<span class="source-line-no">1982</span><span id="line-1982"> }</span>
+<span class="source-line-no">1983</span><span id="line-1983"></span>
+<span class="source-line-no">1984</span><span id="line-1984"> public void add(Map.Entry<BlockCacheKey, BucketEntry> block) {</span>
+<span class="source-line-no">1985</span><span id="line-1985"> totalSize += block.getValue().getLength();</span>
+<span class="source-line-no">1986</span><span id="line-1986"> queue.add(block);</span>
+<span class="source-line-no">1987</span><span id="line-1987"> }</span>
+<span class="source-line-no">1988</span><span id="line-1988"></span>
+<span class="source-line-no">1989</span><span id="line-1989"> public long free(long toFree) {</span>
+<span class="source-line-no">1990</span><span id="line-1990"> Map.Entry<BlockCacheKey, BucketEntry> entry;</span>
+<span class="source-line-no">1991</span><span id="line-1991"> long freedBytes = 0;</span>
+<span class="source-line-no">1992</span><span id="line-1992"> // TODO avoid a cycling siutation. We find no block which is not in use and so no way to free</span>
+<span class="source-line-no">1993</span><span id="line-1993"> // What to do then? Caching attempt fail? Need some changes in cacheBlock API?</span>
+<span class="source-line-no">1994</span><span id="line-1994"> while ((entry = queue.pollLast()) != null) {</span>
+<span class="source-line-no">1995</span><span id="line-1995"> BlockCacheKey blockCacheKey = entry.getKey();</span>
+<span class="source-line-no">1996</span><span id="line-1996"> BucketEntry be = entry.getValue();</span>
+<span class="source-line-no">1997</span><span id="line-1997"> if (evictBucketEntryIfNoRpcReferenced(blockCacheKey, be)) {</span>
+<span class="source-line-no">1998</span><span id="line-1998"> freedBytes += be.getLength();</span>
+<span class="source-line-no">1999</span><span id="line-1999"> }</span>
+<span class="source-line-no">2000</span><span id="line-2000"> if (freedBytes >= toFree) {</span>
+<span class="source-line-no">2001</span><span id="line-2001"> return freedBytes;</span>
+<span class="source-line-no">2002</span><span id="line-2002"> }</span>
+<span class="source-line-no">2003</span><span id="line-2003"> }</span>
+<span class="source-line-no">2004</span><span id="line-2004"> return freedBytes;</span>
+<span class="source-line-no">2005</span><span id="line-2005"> }</span>
+<span class="source-line-no">2006</span><span id="line-2006"></span>
+<span class="source-line-no">2007</span><span id="line-2007"> public long overflow() {</span>
+<span class="source-line-no">2008</span><span id="line-2008"> return totalSize - bucketSize;</span>
+<span class="source-line-no">2009</span><span id="line-2009"> }</span>
+<span class="source-line-no">2010</span><span id="line-2010"></span>
+<span class="source-line-no">2011</span><span id="line-2011"> public long totalSize() {</span>
+<span class="source-line-no">2012</span><span id="line-2012"> return totalSize;</span>
+<span class="source-line-no">2013</span><span id="line-2013"> }</span>
+<span class="source-line-no">2014</span><span id="line-2014"> }</span>
+<span class="source-line-no">2015</span><span id="line-2015"></span>
+<span class="source-line-no">2016</span><span id="line-2016"> /**</span>
+<span class="source-line-no">2017</span><span id="line-2017"> * Block Entry stored in the memory with key,data and so on</span>
+<span class="source-line-no">2018</span><span id="line-2018"> */</span>
+<span class="source-line-no">2019</span><span id="line-2019"> static class RAMQueueEntry {</span>
+<span class="source-line-no">2020</span><span id="line-2020"> private final BlockCacheKey key;</span>
+<span class="source-line-no">2021</span><span id="line-2021"> private final Cacheable data;</span>
+<span class="source-line-no">2022</span><span id="line-2022"> private long accessCounter;</span>
+<span class="source-line-no">2023</span><span id="line-2023"> private boolean inMemory;</span>
+<span class="source-line-no">2024</span><span id="line-2024"> private boolean isCachePersistent;</span>
+<span class="source-line-no">2025</span><span id="line-2025"></span>
+<span class="source-line-no">2026</span><span id="line-2026"> private boolean isPrefetch;</span>
<span class="source-line-no">2027</span><span id="line-2027"></span>
-<span class="source-line-no">2028</span><span id="line-2028"> public BlockCacheKey getKey() {</span>
-<span class="source-line-no">2029</span><span id="line-2029"> return key;</span>
-<span class="source-line-no">2030</span><span id="line-2030"> }</span>
-<span class="source-line-no">2031</span><span id="line-2031"></span>
-<span class="source-line-no">2032</span><span id="line-2032"> public boolean isPrefetch() {</span>
-<span class="source-line-no">2033</span><span id="line-2033"> return isPrefetch;</span>
-<span class="source-line-no">2034</span><span id="line-2034"> }</span>
-<span class="source-line-no">2035</span><span id="line-2035"></span>
-<span class="source-line-no">2036</span><span id="line-2036"> public void access(long accessCounter) {</span>
-<span class="source-line-no">2037</span><span id="line-2037"> this.accessCounter = accessCounter;</span>
-<span class="source-line-no">2038</span><span id="line-2038"> }</span>
-<span class="source-line-no">2039</span><span id="line-2039"></span>
-<span class="source-line-no">2040</span><span id="line-2040"> private ByteBuffAllocator getByteBuffAllocator() {</span>
-<span class="source-line-no">2041</span><span id="line-2041"> if (data instanceof HFileBlock) {</span>
-<span class="source-line-no">2042</span><span id="line-2042"> return ((HFileBlock) data).getByteBuffAllocator();</span>
-<span class="source-line-no">2043</span><span id="line-2043"> }</span>
-<span class="source-line-no">2044</span><span id="line-2044"> return ByteBuffAllocator.HEAP;</span>
-<span class="source-line-no">2045</span><span id="line-2045"> }</span>
-<span class="source-line-no">2046</span><span id="line-2046"></span>
-<span class="source-line-no">2047</span><span id="line-2047"> public BucketEntry writeToCache(final IOEngine ioEngine, final BucketAllocator alloc,</span>
-<span class="source-line-no">2048</span><span id="line-2048"> final LongAdder realCacheSize, Function<BucketEntry, Recycler> createRecycler,</span>
-<span class="source-line-no">2049</span><span id="line-2049"> ByteBuffer metaBuff, final Long acceptableSize) throws IOException {</span>
-<span class="source-line-no">2050</span><span id="line-2050"> int len = data.getSerializedLength();</span>
-<span class="source-line-no">2051</span><span id="line-2051"> // This cacheable thing can't be serialized</span>
-<span class="source-line-no">2052</span><span id="line-2052"> if (len == 0) {</span>
-<span class="source-line-no">2053</span><span id="line-2053"> return null;</span>
-<span class="source-line-no">2054</span><span id="line-2054"> }</span>
-<span class="source-line-no">2055</span><span id="line-2055"> if (isCachePersistent && data instanceof HFileBlock) {</span>
-<span class="source-line-no">2056</span><span id="line-2056"> len += Long.BYTES; // we need to record the cache time for consistency check in case of</span>
-<span class="source-line-no">2057</span><span id="line-2057"> // recovery</span>
-<span class="source-line-no">2058</span><span id="line-2058"> }</span>
-<span class="source-line-no">2059</span><span id="line-2059"> long offset = alloc.allocateBlock(len);</span>
-<span class="source-line-no">2060</span><span id="line-2060"> // In the case of prefetch, we want to avoid freeSpace runs when the cache is full.</span>
-<span class="source-line-no">2061</span><span id="line-2061"> // this makes the cache allocation more predictable, and is particularly important</span>
-<span class="source-line-no">2062</span><span id="line-2062"> // when persistent cache is enabled, as it won't trigger evictions of the recovered blocks,</span>
-<span class="source-line-no">2063</span><span id="line-2063"> // which are likely the most accessed and relevant blocks in the cache.</span>
-<span class="source-line-no">2064</span><span id="line-2064"> if (isPrefetch() && alloc.getUsedSize() > acceptableSize) {</span>
-<span class="source-line-no">2065</span><span id="line-2065"> alloc.freeBlock(offset, len);</span>
-<span class="source-line-no">2066</span><span id="line-2066"> return null;</span>
-<span class="source-line-no">2067</span><span id="line-2067"> }</span>
-<span class="source-line-no">2068</span><span id="line-2068"> boolean succ = false;</span>
-<span class="source-line-no">2069</span><span id="line-2069"> BucketEntry bucketEntry = null;</span>
-<span class="source-line-no">2070</span><span id="line-2070"> try {</span>
-<span class="source-line-no">2071</span><span id="line-2071"> int diskSizeWithHeader = (data instanceof HFileBlock)</span>
-<span class="source-line-no">2072</span><span id="line-2072"> ? ((HFileBlock) data).getOnDiskSizeWithHeader()</span>
-<span class="source-line-no">2073</span><span id="line-2073"> : data.getSerializedLength();</span>
-<span class="source-line-no">2074</span><span id="line-2074"> bucketEntry = new BucketEntry(offset, len, diskSizeWithHeader, accessCounter, inMemory,</span>
-<span class="source-line-no">2075</span><span id="line-2075"> createRecycler, getByteBuffAllocator());</span>
-<span class="source-line-no">2076</span><span id="line-2076"> bucketEntry.setDeserializerReference(data.getDeserializer());</span>
-<span class="source-line-no">2077</span><span id="line-2077"> if (data instanceof HFileBlock) {</span>
-<span class="source-line-no">2078</span><span id="line-2078"> // If an instance of HFileBlock, save on some allocations.</span>
-<span class="source-line-no">2079</span><span id="line-2079"> HFileBlock block = (HFileBlock) data;</span>
-<span class="source-line-no">2080</span><span id="line-2080"> ByteBuff sliceBuf = block.getBufferReadOnly();</span>
-<span class="source-line-no">2081</span><span id="line-2081"> block.getMetaData(metaBuff);</span>
-<span class="source-line-no">2082</span><span id="line-2082"> // adds the cache time prior to the block and metadata part</span>
-<span class="source-line-no">2083</span><span id="line-2083"> if (isCachePersistent) {</span>
-<span class="source-line-no">2084</span><span id="line-2084"> ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);</span>
-<span class="source-line-no">2085</span><span id="line-2085"> buffer.putLong(bucketEntry.getCachedTime());</span>
-<span class="source-line-no">2086</span><span id="line-2086"> buffer.rewind();</span>
-<span class="source-line-no">2087</span><span id="line-2087"> ioEngine.write(buffer, offset);</span>
-<span class="source-line-no">2088</span><span id="line-2088"> ioEngine.write(sliceBuf, (offset + Long.BYTES));</span>
-<span class="source-line-no">2089</span><span id="line-2089"> } else {</span>
-<span class="source-line-no">2090</span><span id="line-2090"> ioEngine.write(sliceBuf, offset);</span>
-<span class="source-line-no">2091</span><span id="line-2091"> }</span>
-<span class="source-line-no">2092</span><span id="line-2092"> ioEngine.write(metaBuff, offset + len - metaBuff.limit());</span>
-<span class="source-line-no">2093</span><span id="line-2093"> } else {</span>
-<span class="source-line-no">2094</span><span id="line-2094"> // Only used for testing.</span>
-<span class="source-line-no">2095</span><span id="line-2095"> ByteBuffer bb = ByteBuffer.allocate(len);</span>
-<span class="source-line-no">2096</span><span id="line-2096"> data.serialize(bb, true);</span>
-<span class="source-line-no">2097</span><span id="line-2097"> ioEngine.write(bb, offset);</span>
-<span class="source-line-no">2098</span><span id="line-2098"> }</span>
-<span class="source-line-no">2099</span><span id="line-2099"> succ = true;</span>
-<span class="source-line-no">2100</span><span id="line-2100"> } finally {</span>
-<span class="source-line-no">2101</span><span id="line-2101"> if (!succ) {</span>
-<span class="source-line-no">2102</span><span id="line-2102"> alloc.freeBlock(offset, len);</span>
-<span class="source-line-no">2103</span><span id="line-2103"> }</span>
-<span class="source-line-no">2104</span><span id="line-2104"> }</span>
-<span class="source-line-no">2105</span><span id="line-2105"> realCacheSize.add(len);</span>
-<span class="source-line-no">2106</span><span id="line-2106"> return bucketEntry;</span>
-<span class="source-line-no">2107</span><span id="line-2107"> }</span>
-<span class="source-line-no">2108</span><span id="line-2108"> }</span>
-<span class="source-line-no">2109</span><span id="line-2109"></span>
-<span class="source-line-no">2110</span><span id="line-2110"> /**</span>
-<span class="source-line-no">2111</span><span id="line-2111"> * Only used in test</span>
-<span class="source-line-no">2112</span><span id="line-2112"> */</span>
-<span class="source-line-no">2113</span><span id="line-2113"> void stopWriterThreads() throws InterruptedException {</span>
-<span class="source-line-no">2114</span><span id="line-2114"> for (WriterThread writerThread : writerThreads) {</span>
-<span class="source-line-no">2115</span><span id="line-2115"> writerThread.disableWriter();</span>
-<span class="source-line-no">2116</span><span id="line-2116"> writerThread.interrupt();</span>
-<span class="source-line-no">2117</span><span id="line-2117"> writerThread.join();</span>
-<span class="source-line-no">2118</span><span id="line-2118"> }</span>
-<span class="source-line-no">2119</span><span id="line-2119"> }</span>
-<span class="source-line-no">2120</span><span id="line-2120"></span>
-<span class="source-line-no">2121</span><span id="line-2121"> @Override</span>
-<span class="source-line-no">2122</span><span id="line-2122"> public Iterator<CachedBlock> iterator() {</span>
-<span class="source-line-no">2123</span><span id="line-2123"> // Don't bother with ramcache since stuff is in here only a little while.</span>
-<span class="source-line-no">2124</span><span id="line-2124"> final Iterator<Map.Entry<BlockCacheKey, BucketEntry>> i = this.backingMap.entrySet().iterator();</span>
-<span class="source-line-no">2125</span><span id="line-2125"> return new Iterator<CachedBlock>() {</span>
-<span class="source-line-no">2126</span><span id="line-2126"> private final long now = System.nanoTime();</span>
-<span class="source-line-no">2127</span><span id="line-2127"></span>
-<span class="source-line-no">2128</span><span id="line-2128"> @Override</span>
-<span class="source-line-no">2129</span><span id="line-2129"> public boolean hasNext() {</span>
-<span class="source-line-no">2130</span><span id="line-2130"> return i.hasNext();</span>
-<span class="source-line-no">2131</span><span id="line-2131"> }</span>
-<span class="source-line-no">2132</span><span id="line-2132"></span>
-<span class="source-line-no">2133</span><span id="line-2133"> @Override</span>
-<span class="source-line-no">2134</span><span id="line-2134"> public CachedBlock next() {</span>
-<span class="source-line-no">2135</span><span id="line-2135"> final Map.Entry<BlockCacheKey, BucketEntry> e = i.next();</span>
-<span class="source-line-no">2136</span><span id="line-2136"> return new CachedBlock() {</span>
-<span class="source-line-no">2137</span><span id="line-2137"> @Override</span>
-<span class="source-line-no">2138</span><span id="line-2138"> public String toString() {</span>
-<span class="source-line-no">2139</span><span id="line-2139"> return BlockCacheUtil.toString(this, now);</span>
-<span class="source-line-no">2140</span><span id="line-2140"> }</span>
+<span class="source-line-no">2028</span><span id="line-2028"> RAMQueueEntry(BlockCacheKey bck, Cacheable data, long accessCounter, boolean inMemory,</span>
+<span class="source-line-no">2029</span><span id="line-2029"> boolean isCachePersistent, boolean isPrefetch) {</span>
+<span class="source-line-no">2030</span><span id="line-2030"> this.key = bck;</span>
+<span class="source-line-no">2031</span><span id="line-2031"> this.data = data;</span>
+<span class="source-line-no">2032</span><span id="line-2032"> this.accessCounter = accessCounter;</span>
+<span class="source-line-no">2033</span><span id="line-2033"> this.inMemory = inMemory;</span>
+<span class="source-line-no">2034</span><span id="line-2034"> this.isCachePersistent = isCachePersistent;</span>
+<span class="source-line-no">2035</span><span id="line-2035"> this.isPrefetch = isPrefetch;</span>
+<span class="source-line-no">2036</span><span id="line-2036"> }</span>
+<span class="source-line-no">2037</span><span id="line-2037"></span>
+<span class="source-line-no">2038</span><span id="line-2038"> public Cacheable getData() {</span>
+<span class="source-line-no">2039</span><span id="line-2039"> return data;</span>
+<span class="source-line-no">2040</span><span id="line-2040"> }</span>
+<span class="source-line-no">2041</span><span id="line-2041"></span>
+<span class="source-line-no">2042</span><span id="line-2042"> public BlockCacheKey getKey() {</span>
+<span class="source-line-no">2043</span><span id="line-2043"> return key;</span>
+<span class="source-line-no">2044</span><span id="line-2044"> }</span>
+<span class="source-line-no">2045</span><span id="line-2045"></span>
+<span class="source-line-no">2046</span><span id="line-2046"> public boolean isPrefetch() {</span>
+<span class="source-line-no">2047</span><span id="line-2047"> return isPrefetch;</span>
+<span class="source-line-no">2048</span><span id="line-2048"> }</span>
+<span class="source-line-no">2049</span><span id="line-2049"></span>
+<span class="source-line-no">2050</span><span id="line-2050"> public void access(long accessCounter) {</span>
+<span class="source-line-no">2051</span><span id="line-2051"> this.accessCounter = accessCounter;</span>
+<span class="source-line-no">2052</span><span id="line-2052"> }</span>
+<span class="source-line-no">2053</span><span id="line-2053"></span>
+<span class="source-line-no">2054</span><span id="line-2054"> private ByteBuffAllocator getByteBuffAllocator() {</span>
+<span class="source-line-no">2055</span><span id="line-2055"> if (data instanceof HFileBlock) {</span>
+<span class="source-line-no">2056</span><span id="line-2056"> return ((HFileBlock) data).getByteBuffAllocator();</span>
+<span class="source-line-no">2057</span><span id="line-2057"> }</span>
+<span class="source-line-no">2058</span><span id="line-2058"> return ByteBuffAllocator.HEAP;</span>
+<span class="source-line-no">2059</span><span id="line-2059"> }</span>
+<span class="source-line-no">2060</span><span id="line-2060"></span>
+<span class="source-line-no">2061</span><span id="line-2061"> public BucketEntry writeToCache(final IOEngine ioEngine, final BucketAllocator alloc,</span>
+<span class="source-line-no">2062</span><span id="line-2062"> final LongAdder realCacheSize, Function<BucketEntry, Recycler> createRecycler,</span>
+<span class="source-line-no">2063</span><span id="line-2063"> ByteBuffer metaBuff, final Long acceptableSize) throws IOException {</span>
+<span class="source-line-no">2064</span><span id="line-2064"> int len = data.getSerializedLength();</span>
+<span class="source-line-no">2065</span><span id="line-2065"> // This cacheable thing can't be serialized</span>
+<span class="source-line-no">2066</span><span id="line-2066"> if (len == 0) {</span>
+<span class="source-line-no">2067</span><span id="line-2067"> return null;</span>
+<span class="source-line-no">2068</span><span id="line-2068"> }</span>
+<span class="source-line-no">2069</span><span id="line-2069"> if (isCachePersistent && data instanceof HFileBlock) {</span>
+<span class="source-line-no">2070</span><span id="line-2070"> len += Long.BYTES; // we need to record the cache time for consistency check in case of</span>
+<span class="source-line-no">2071</span><span id="line-2071"> // recovery</span>
+<span class="source-line-no">2072</span><span id="line-2072"> }</span>
+<span class="source-line-no">2073</span><span id="line-2073"> long offset = alloc.allocateBlock(len);</span>
+<span class="source-line-no">2074</span><span id="line-2074"> // In the case of prefetch, we want to avoid freeSpace runs when the cache is full.</span>
+<span class="source-line-no">2075</span><span id="line-2075"> // this makes the cache allocation more predictable, and is particularly important</span>
+<span class="source-line-no">2076</span><span id="line-2076"> // when persistent cache is enabled, as it won't trigger evictions of the recovered blocks,</span>
+<span class="source-line-no">2077</span><span id="line-2077"> // which are likely the most accessed and relevant blocks in the cache.</span>
+<span class="source-line-no">2078</span><span id="line-2078"> if (isPrefetch() && alloc.getUsedSize() > acceptableSize) {</span>
+<span class="source-line-no">2079</span><span id="line-2079"> alloc.freeBlock(offset, len);</span>
+<span class="source-line-no">2080</span><span id="line-2080"> return null;</span>
+<span class="source-line-no">2081</span><span id="line-2081"> }</span>
+<span class="source-line-no">2082</span><span id="line-2082"> boolean succ = false;</span>
+<span class="source-line-no">2083</span><span id="line-2083"> BucketEntry bucketEntry = null;</span>
+<span class="source-line-no">2084</span><span id="line-2084"> try {</span>
+<span class="source-line-no">2085</span><span id="line-2085"> int diskSizeWithHeader = (data instanceof HFileBlock)</span>
+<span class="source-line-no">2086</span><span id="line-2086"> ? ((HFileBlock) data).getOnDiskSizeWithHeader()</span>
+<span class="source-line-no">2087</span><span id="line-2087"> : data.getSerializedLength();</span>
+<span class="source-line-no">2088</span><span id="line-2088"> bucketEntry = new BucketEntry(offset, len, diskSizeWithHeader, accessCounter, inMemory,</span>
+<span class="source-line-no">2089</span><span id="line-2089"> createRecycler, getByteBuffAllocator());</span>
+<span class="source-line-no">2090</span><span id="line-2090"> bucketEntry.setDeserializerReference(data.getDeserializer());</span>
+<span class="source-line-no">2091</span><span id="line-2091"> if (data instanceof HFileBlock) {</span>
+<span class="source-line-no">2092</span><span id="line-2092"> // If an instance of HFileBlock, save on some allocations.</span>
+<span class="source-line-no">2093</span><span id="line-2093"> HFileBlock block = (HFileBlock) data;</span>
+<span class="source-line-no">2094</span><span id="line-2094"> ByteBuff sliceBuf = block.getBufferReadOnly();</span>
+<span class="source-line-no">2095</span><span id="line-2095"> block.getMetaData(metaBuff);</span>
+<span class="source-line-no">2096</span><span id="line-2096"> // adds the cache time prior to the block and metadata part</span>
+<span class="source-line-no">2097</span><span id="line-2097"> if (isCachePersistent) {</span>
+<span class="source-line-no">2098</span><span id="line-2098"> ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);</span>
+<span class="source-line-no">2099</span><span id="line-2099"> buffer.putLong(bucketEntry.getCachedTime());</span>
+<span class="source-line-no">2100</span><span id="line-2100"> buffer.rewind();</span>
+<span class="source-line-no">2101</span><span id="line-2101"> ioEngine.write(buffer, offset);</span>
+<span class="source-line-no">2102</span><span id="line-2102"> ioEngine.write(sliceBuf, (offset + Long.BYTES));</span>
+<span class="source-line-no">2103</span><span id="line-2103"> } else {</span>
+<span class="source-line-no">2104</span><span id="line-2104"> ioEngine.write(sliceBuf, offset);</span>
+<span class="source-line-no">2105</span><span id="line-2105"> }</span>
+<span class="source-line-no">2106</span><span id="line-2106"> ioEngine.write(metaBuff, offset + len - metaBuff.limit());</span>
+<span class="source-line-no">2107</span><span id="line-2107"> } else {</span>
+<span class="source-line-no">2108</span><span id="line-2108"> // Only used for testing.</span>
+<span class="source-line-no">2109</span><span id="line-2109"> ByteBuffer bb = ByteBuffer.allocate(len);</span>
+<span class="source-line-no">2110</span><span id="line-2110"> data.serialize(bb, true);</span>
+<span class="source-line-no">2111</span><span id="line-2111"> ioEngine.write(bb, offset);</span>
+<span class="source-line-no">2112</span><span id="line-2112"> }</span>
+<span class="source-line-no">2113</span><span id="line-2113"> succ = true;</span>
+<span class="source-line-no">2114</span><span id="line-2114"> } finally {</span>
+<span class="source-line-no">2115</span><span id="line-2115"> if (!succ) {</span>
+<span class="source-line-no">2116</span><span id="line-2116"> alloc.freeBlock(offset, len);</span>
+<span class="source-line-no">2117</span><span id="line-2117"> }</span>
+<span class="source-line-no">2118</span><span id="line-2118"> }</span>
+<span class="source-line-no">2119</span><span id="line-2119"> realCacheSize.add(len);</span>
+<span class="source-line-no">2120</span><span id="line-2120"> return bucketEntry;</span>
+<span class="source-line-no">2121</span><span id="line-2121"> }</span>
+<span class="source-line-no">2122</span><span id="line-2122"> }</span>
+<span class="source-line-no">2123</span><span id="line-2123"></span>
+<span class="source-line-no">2124</span><span id="line-2124"> /**</span>
+<span class="source-line-no">2125</span><span id="line-2125"> * Only used in test</span>
+<span class="source-line-no">2126</span><span id="line-2126"> */</span>
+<span class="source-line-no">2127</span><span id="line-2127"> void stopWriterThreads() throws InterruptedException {</span>
+<span class="source-line-no">2128</span><span id="line-2128"> for (WriterThread writerThread : writerThreads) {</span>
+<span class="source-line-no">2129</span><span id="line-2129"> writerThread.disableWriter();</span>
+<span class="source-line-no">2130</span><span id="line-2130"> writerThread.interrupt();</span>
+<span class="source-line-no">2131</span><span id="line-2131"> writerThread.join();</span>
+<span class="source-line-no">2132</span><span id="line-2132"> }</span>
+<span class="source-line-no">2133</span><span id="line-2133"> }</span>
+<span class="source-line-no">2134</span><span id="line-2134"></span>
+<span class="source-line-no">2135</span><span id="line-2135"> @Override</span>
+<span class="source-line-no">2136</span><span id="line-2136"> public Iterator<CachedBlock> iterator() {</span>
+<span class="source-line-no">2137</span><span id="line-2137"> // Don't bother with ramcache since stuff is in here only a little while.</span>
+<span class="source-line-no">2138</span><span id="line-2138"> final Iterator<Map.Entry<BlockCacheKey, BucketEntry>> i = this.backingMap.entrySet().iterator();</span>
+<span class="source-line-no">2139</span><span id="line-2139"> return new Iterator<CachedBlock>() {</span>
+<span class="source-line-no">2140</span><span id="line-2140"> private final long now = System.nanoTime();</span>
<span class="source-line-no">2141</span><span id="line-2141"></span>
-<span class="source-line-no">2142</span><span id="line-2142"> @Override</span>
-<span class="source-line-no">2143</span><span id="line-2143"> public BlockPriority getBlockPriority() {</span>
-<span class="source-line-no">2144</span><span id="line-2144"> return e.getValue().getPriority();</span>
-<span class="source-line-no">2145</span><span id="line-2145"> }</span>
+<span class="source-line-no">2142</span><span id="line-2142"> @Override</span>
+<span class="source-line-no">2143</span><span id="line-2143"> public boolean hasNext() {</span>
+<span class="source-line-no">2144</span><span id="line-2144"> return i.hasNext();</span>
+<span class="source-line-no">2145</span><span id="line-2145"> }</span>
<span class="source-line-no">2146</span><span id="line-2146"></span>
-<span class="source-line-no">2147</span><span id="line-2147"> @Override</span>
-<span class="source-line-no">2148</span><span id="line-2148"> public BlockType getBlockType() {</span>
-<span class="source-line-no">2149</span><span id="line-2149"> // Not held by BucketEntry. Could add it if wanted on BucketEntry creation.</span>
-<span class="source-line-no">2150</span><span id="line-2150"> return null;</span>
-<span class="source-line-no">2151</span><span id="line-2151"> }</span>
-<span class="source-line-no">2152</span><span id="line-2152"></span>
-<span class="source-line-no">2153</span><span id="line-2153"> @Override</span>
-<span class="source-line-no">2154</span><span id="line-2154"> public long getOffset() {</span>
-<span class="source-line-no">2155</span><span id="line-2155"> return e.getKey().getOffset();</span>
-<span class="source-line-no">2156</span><span id="line-2156"> }</span>
-<span class="source-line-no">2157</span><span id="line-2157"></span>
-<span class="source-line-no">2158</span><span id="line-2158"> @Override</span>
-<span class="source-line-no">2159</span><span id="line-2159"> public long getSize() {</span>
-<span class="source-line-no">2160</span><span id="line-2160"> return e.getValue().getLength();</span>
-<span class="source-line-no">2161</span><span id="line-2161"> }</span>
-<span class="source-line-no">2162</span><span id="line-2162"></span>
-<span class="source-line-no">2163</span><span id="line-2163"> @Override</span>
-<span class="source-line-no">2164</span><span id="line-2164"> public long getCachedTime() {</span>
-<span class="source-line-no">2165</span><span id="line-2165"> return e.getValue().getCachedTime();</span>
-<span class="source-line-no">2166</span><span id="line-2166"> }</span>
-<span class="source-line-no">2167</span><span id="line-2167"></span>
-<span class="source-line-no">2168</span><span id="line-2168"> @Override</span>
-<span class="source-line-no">2169</span><span id="line-2169"> public String getFilename() {</span>
-<span class="source-line-no">2170</span><span id="line-2170"> return e.getKey().getHfileName();</span>
-<span class="source-line-no">2171</span><span id="line-2171"> }</span>
-<span class="source-line-no">2172</span><span id="line-2172"></span>
-<span class="source-line-no">2173</span><span id="line-2173"> @Override</span>
-<span class="source-line-no">2174</span><span id="line-2174"> public int compareTo(CachedBlock other) {</span>
-<span class="source-line-no">2175</span><span id="line-2175"> int diff = this.getFilename().compareTo(other.getFilename());</span>
-<span class="source-line-no">2176</span><span id="line-2176"> if (diff != 0) return diff;</span>
-<span class="source-line-no">2177</span><span id="line-2177"></span>
-<span class="source-line-no">2178</span><span id="line-2178"> diff = Long.compare(this.getOffset(), other.getOffset());</span>
-<span class="source-line-no">2179</span><span id="line-2179"> if (diff != 0) return diff;</span>
-<span class="source-line-no">2180</span><span id="line-2180"> if (other.getCachedTime() < 0 || this.getCachedTime() < 0) {</span>
-<span class="source-line-no">2181</span><span id="line-2181"> throw new IllegalStateException(</span>
-<span class="source-line-no">2182</span><span id="line-2182"> "" + this.getCachedTime() + ", " + other.getCachedTime());</span>
-<span class="source-line-no">2183</span><span id="line-2183"> }</span>
-<span class="source-line-no">2184</span><span id="line-2184"> return Long.compare(other.getCachedTime(), this.getCachedTime());</span>
+<span class="source-line-no">2147</span><span id="line-2147"> @Override</span>
+<span class="source-line-no">2148</span><span id="line-2148"> public CachedBlock next() {</span>
+<span class="source-line-no">2149</span><span id="line-2149"> final Map.Entry<BlockCacheKey, BucketEntry> e = i.next();</span>
+<span class="source-line-no">2150</span><span id="line-2150"> return new CachedBlock() {</span>
+<span class="source-line-no">2151</span><span id="line-2151"> @Override</span>
+<span class="source-line-no">2152</span><span id="line-2152"> public String toString() {</span>
+<span class="source-line-no">2153</span><span id="line-2153"> return BlockCacheUtil.toString(this, now);</span>
+<span class="source-line-no">2154</span><span id="line-2154"> }</span>
+<span class="source-line-no">2155</span><span id="line-2155"></span>
+<span class="source-line-no">2156</span><span id="line-2156"> @Override</span>
+<span class="source-line-no">2157</span><span id="line-2157"> public BlockPriority getBlockPriority() {</span>
+<span class="source-line-no">2158</span><span id="line-2158"> return e.getValue().getPriority();</span>
+<span class="source-line-no">2159</span><span id="line-2159"> }</span>
+<span class="source-line-no">2160</span><span id="line-2160"></span>
+<span class="source-line-no">2161</span><span id="line-2161"> @Override</span>
+<span class="source-line-no">2162</span><span id="line-2162"> public BlockType getBlockType() {</span>
+<span class="source-line-no">2163</span><span id="line-2163"> // Not held by BucketEntry. Could add it if wanted on BucketEntry creation.</span>
+<span class="source-line-no">2164</span><span id="line-2164"> return null;</span>
+<span class="source-line-no">2165</span><span id="line-2165"> }</span>
+<span class="source-line-no">2166</span><span id="line-2166"></span>
+<span class="source-line-no">2167</span><span id="line-2167"> @Override</span>
+<span class="source-line-no">2168</span><span id="line-2168"> public long getOffset() {</span>
+<span class="source-line-no">2169</span><span id="line-2169"> return e.getKey().getOffset();</span>
+<span class="source-line-no">2170</span><span id="line-2170"> }</span>
+<span class="source-line-no">2171</span><span id="line-2171"></span>
+<span class="source-line-no">2172</span><span id="line-2172"> @Override</span>
+<span class="source-line-no">2173</span><span id="line-2173"> public long getSize() {</span>
+<span class="source-line-no">2174</span><span id="line-2174"> return e.getValue().getLength();</span>
+<span class="source-line-no">2175</span><span id="line-2175"> }</span>
+<span class="source-line-no">2176</span><span id="line-2176"></span>
+<span class="source-line-no">2177</span><span id="line-2177"> @Override</span>
+<span class="source-line-no">2178</span><span id="line-2178"> public long getCachedTime() {</span>
+<span class="source-line-no">2179</span><span id="line-2179"> return e.getValue().getCachedTime();</span>
+<span class="source-line-no">2180</span><span id="line-2180"> }</span>
+<span class="source-line-no">2181</span><span id="line-2181"></span>
+<span class="source-line-no">2182</span><span id="line-2182"> @Override</span>
+<span class="source-line-no">2183</span><span id="line-2183"> public String getFilename() {</span>
+<span class="source-line-no">2184</span><span id="line-2184"> return e.getKey().getHfileName();</span>
<span class="source-line-no">2185</span><span id="line-2185"> }</span>
<span class="source-line-no">2186</span><span id="line-2186"></span>
<span class="source-line-no">2187</span><span id="line-2187"> @Override</span>
-<span class="source-line-no">2188</span><span id="line-2188"> public int hashCode() {</span>
-<span class="source-line-no">2189</span><span id="line-2189"> return e.getKey().hashCode();</span>
-<span class="source-line-no">2190</span><span id="line-2190"> }</span>
+<span class="source-line-no">2188</span><span id="line-2188"> public int compareTo(CachedBlock other) {</span>
+<span class="source-line-no">2189</span><span id="line-2189"> int diff = this.getFilename().compareTo(other.getFilename());</span>
+<span class="source-line-no">2190</span><span id="line-2190"> if (diff != 0) return diff;</span>
<span class="source-line-no">2191</span><span id="line-2191"></span>
-<span class="source-line-no">2192</span><span id="line-2192"> @Override</span>
-<span class="source-line-no">2193</span><span id="line-2193"> public boolean equals(Object obj) {</span>
-<span class="source-line-no">2194</span><span id="line-2194"> if (obj instanceof CachedBlock) {</span>
-<span class="source-line-no">2195</span><span id="line-2195"> CachedBlock cb = (CachedBlock) obj;</span>
-<span class="source-line-no">2196</span><span id="line-2196"> return compareTo(cb) == 0;</span>
-<span class="source-line-no">2197</span><span id="line-2197"> } else {</span>
-<span class="source-line-no">2198</span><span id="line-2198"> return false;</span>
-<span class="source-line-no">2199</span><span id="line-2199"> }</span>
-<span class="source-line-no">2200</span><span id="line-2200"> }</span>
-<span class="source-line-no">2201</span><span id="line-2201"> };</span>
-<span class="source-line-no">2202</span><span id="line-2202"> }</span>
-<span class="source-line-no">2203</span><span id="line-2203"></span>
-<span class="source-line-no">2204</span><span id="line-2204"> @Override</span>
-<span class="source-line-no">2205</span><span id="line-2205"> public void remove() {</span>
-<span class="source-line-no">2206</span><span id="line-2206"> throw new UnsupportedOperationException();</span>
-<span class="source-line-no">2207</span><span id="line-2207"> }</span>
-<span class="source-line-no">2208</span><span id="line-2208"> };</span>
-<span class="source-line-no">2209</span><span id="line-2209"> }</span>
-<span class="source-line-no">2210</span><span id="line-2210"></span>
-<span class="source-line-no">2211</span><span id="line-2211"> @Override</span>
-<span class="source-line-no">2212</span><span id="line-2212"> public BlockCache[] getBlockCaches() {</span>
-<span class="source-line-no">2213</span><span id="line-2213"> return null;</span>
-<span class="source-line-no">2214</span><span id="line-2214"> }</span>
-<span class="source-line-no">2215</span><span id="line-2215"></span>
-<span class="source-line-no">2216</span><span id="line-2216"> public int getRpcRefCount(BlockCacheKey cacheKey) {</span>
-<span class="source-line-no">2217</span><span id="line-2217"> BucketEntry bucketEntry = backingMap.get(cacheKey);</span>
-<span class="source-line-no">2218</span><span id="line-2218"> if (bucketEntry != null) {</span>
-<span class="source-line-no">2219</span><span id="line-2219"> return bucketEntry.refCnt() - (bucketEntry.markedAsEvicted.get() ? 0 : 1);</span>
-<span class="source-line-no">2220</span><span id="line-2220"> }</span>
-<span class="source-line-no">2221</span><span id="line-2221"> return 0;</span>
-<span class="source-line-no">2222</span><span id="line-2222"> }</span>
-<span class="source-line-no">2223</span><span id="line-2223"></span>
-<span class="source-line-no">2224</span><span id="line-2224"> float getAcceptableFactor() {</span>
-<span class="source-line-no">2225</span><span id="line-2225"> return acceptableFactor;</span>
-<span class="source-line-no">2226</span><span id="line-2226"> }</span>
-<span class="source-line-no">2227</span><span id="line-2227"></span>
-<span class="source-line-no">2228</span><span id="line-2228"> float getMinFactor() {</span>
-<span class="source-line-no">2229</span><span id="line-2229"> return minFactor;</span>
-<span class="source-line-no">2230</span><span id="line-2230"> }</span>
-<span class="source-line-no">2231</span><span id="line-2231"></span>
-<span class="source-line-no">2232</span><span id="line-2232"> float getExtraFreeFactor() {</span>
-<span class="source-line-no">2233</span><span id="line-2233"> return extraFreeFactor;</span>
-<span class="source-line-no">2234</span><span id="line-2234"> }</span>
-<span class="source-line-no">2235</span><span id="line-2235"></span>
-<span class="source-line-no">2236</span><span id="line-2236"> float getSingleFactor() {</span>
-<span class="source-line-no">2237</span><span id="line-2237"> return singleFactor;</span>
-<span class="source-line-no">2238</span><span id="line-2238"> }</span>
-<span class="source-line-no">2239</span><span id="line-2239"></span>
-<span class="source-line-no">2240</span><span id="line-2240"> float getMultiFactor() {</span>
-<span class="source-line-no">2241</span><span id="line-2241"> return multiFactor;</span>
-<span class="source-line-no">2242</span><span id="line-2242"> }</span>
-<span class="source-line-no">2243</span><span id="line-2243"></span>
-<span class="source-line-no">2244</span><span id="line-2244"> float getMemoryFactor() {</span>
-<span class="source-line-no">2245</span><span id="line-2245"> return memoryFactor;</span>
-<span class="source-line-no">2246</span><span id="line-2246"> }</span>
-<span class="source-line-no">2247</span><span id="line-2247"></span>
-<span class="source-line-no">2248</span><span id="line-2248"> long getQueueAdditionWaitTime() {</span>
-<span class="source-line-no">2249</span><span id="line-2249"> return queueAdditionWaitTime;</span>
-<span class="source-line-no">2250</span><span id="line-2250"> }</span>
-<span class="source-line-no">2251</span><span id="line-2251"></span>
-<span class="source-line-no">2252</span><span id="line-2252"> long getPersistenceChunkSize() {</span>
-<span class="source-line-no">2253</span><span id="line-2253"> return persistenceChunkSize;</span>
-<span class="source-line-no">2254</span><span id="line-2254"> }</span>
-<span class="source-line-no">2255</span><span id="line-2255"></span>
-<span class="source-line-no">2256</span><span id="line-2256"> long getBucketcachePersistInterval() {</span>
-<span class="source-line-no">2257</span><span id="line-2257"> return bucketcachePersistInterval;</span>
-<span class="source-line-no">2258</span><span id="line-2258"> }</span>
-<span class="source-line-no">2259</span><span id="line-2259"></span>
-<span class="source-line-no">2260</span><span id="line-2260"> public String getPersistencePath() {</span>
-<span class="source-line-no">2261</span><span id="line-2261"> return persistencePath;</span>
-<span class="source-line-no">2262</span><span id="line-2262"> }</span>
-<span class="source-line-no">2263</span><span id="line-2263"></span>
-<span class="source-line-no">2264</span><span id="line-2264"> /**</span>
-<span class="source-line-no">2265</span><span id="line-2265"> * Wrapped the delegate ConcurrentMap with maintaining its block's reference count.</span>
-<span class="source-line-no">2266</span><span id="line-2266"> */</span>
-<span class="source-line-no">2267</span><span id="line-2267"> static class RAMCache {</span>
-<span class="source-line-no">2268</span><span id="line-2268"> /**</span>
-<span class="source-line-no">2269</span><span id="line-2269"> * Defined the map as {@link ConcurrentHashMap} explicitly here, because in</span>
-<span class="source-line-no">2270</span><span id="line-2270"> * {@link RAMCache#get(BlockCacheKey)} and</span>
-<span class="source-line-no">2271</span><span id="line-2271"> * {@link RAMCache#putIfAbsent(BlockCacheKey, BucketCache.RAMQueueEntry)} , we need to guarantee</span>
-<span class="source-line-no">2272</span><span id="line-2272"> * the atomicity of map#computeIfPresent(key, func) and map#putIfAbsent(key, func). Besides, the</span>
-<span class="source-line-no">2273</span><span id="line-2273"> * func method can execute exactly once only when the key is present(or absent) and under the</span>
-<span class="source-line-no">2274</span><span id="line-2274"> * lock context. Otherwise, the reference count of block will be messed up. Notice that the</span>
-<span class="source-line-no">2275</span><span id="line-2275"> * {@link java.util.concurrent.ConcurrentSkipListMap} can not guarantee that.</span>
-<span class="source-line-no">2276</span><span id="line-2276"> */</span>
-<span class="source-line-no">2277</span><span id="line-2277"> final ConcurrentHashMap<BlockCacheKey, RAMQueueEntry> delegate = new ConcurrentHashMap<>();</span>
-<span class="source-line-no">2278</span><span id="line-2278"></span>
-<span class="source-line-no">2279</span><span id="line-2279"> public boolean containsKey(BlockCacheKey key) {</span>
-<span class="source-line-no">2280</span><span id="line-2280"> return delegate.containsKey(key);</span>
-<span class="source-line-no">2281</span><span id="line-2281"> }</span>
-<span class="source-line-no">2282</span><span id="line-2282"></span>
-<span class="source-line-no">2283</span><span id="line-2283"> public RAMQueueEntry get(BlockCacheKey key) {</span>
-<span class="source-line-no">2284</span><span id="line-2284"> return delegate.computeIfPresent(key, (k, re) -> {</span>
-<span class="source-line-no">2285</span><span id="line-2285"> // It'll be referenced by RPC, so retain atomically here. if the get and retain is not</span>
-<span class="source-line-no">2286</span><span id="line-2286"> // atomic, another thread may remove and release the block, when retaining in this thread we</span>
-<span class="source-line-no">2287</span><span id="line-2287"> // may retain a block with refCnt=0 which is disallowed. (see HBASE-22422)</span>
-<span class="source-line-no">2288</span><span id="line-2288"> re.getData().retain();</span>
-<span class="source-line-no">2289</span><span id="line-2289"> return re;</span>
-<span class="source-line-no">2290</span><span id="line-2290"> });</span>
-<span class="source-line-no">2291</span><span id="line-2291"> }</span>
+<span class="source-line-no">2192</span><span id="line-2192"> diff = Long.compare(this.getOffset(), other.getOffset());</span>
+<span class="source-line-no">2193</span><span id="line-2193"> if (diff != 0) return diff;</span>
+<span class="source-line-no">2194</span><span id="line-2194"> if (other.getCachedTime() < 0 || this.getCachedTime() < 0) {</span>
+<span class="source-line-no">2195</span><span id="line-2195"> throw new IllegalStateException(</span>
+<span class="source-line-no">2196</span><span id="line-2196"> "" + this.getCachedTime() + ", " + other.getCachedTime());</span>
+<span class="source-line-no">2197</span><span id="line-2197"> }</span>
+<span class="source-line-no">2198</span><span id="line-2198"> return Long.compare(other.getCachedTime(), this.getCachedTime());</span>
+<span class="source-line-no">2199</span><span id="line-2199"> }</span>
+<span class="source-line-no">2200</span><span id="line-2200"></span>
+<span class="source-line-no">2201</span><span id="line-2201"> @Override</span>
+<span class="source-line-no">2202</span><span id="line-2202"> public int hashCode() {</span>
+<span class="source-line-no">2203</span><span id="line-2203"> return e.getKey().hashCode();</span>
+<span class="source-line-no">2204</span><span id="line-2204"> }</span>
+<span class="source-line-no">2205</span><span id="line-2205"></span>
+<span class="source-line-no">2206</span><span id="line-2206"> @Override</span>
+<span class="source-line-no">2207</span><span id="line-2207"> public boolean equals(Object obj) {</span>
+<span class="source-line-no">2208</span><span id="line-2208"> if (obj instanceof CachedBlock) {</span>
+<span class="source-line-no">2209</span><span id="line-2209"> CachedBlock cb = (CachedBlock) obj;</span>
+<span class="source-line-no">2210</span><span id="line-2210"> return compareTo(cb) == 0;</span>
+<span class="source-line-no">2211</span><span id="line-2211"> } else {</span>
+<span class="source-line-no">2212</span><span id="line-2212"> return false;</span>
+<span class="source-line-no">2213</span><span id="line-2213"> }</span>
+<span class="source-line-no">2214</span><span id="line-2214"> }</span>
+<span class="source-line-no">2215</span><span id="line-2215"> };</span>
+<span class="source-line-no">2216</span><span id="line-2216"> }</span>
+<span class="source-line-no">2217</span><span id="line-2217"></span>
+<span class="source-line-no">2218</span><span id="line-2218"> @Override</span>
+<span class="source-line-no">2219</span><span id="line-2219"> public void remove() {</span>
+<span class="source-line-no">2220</span><span id="line-2220"> throw new UnsupportedOperationException();</span>
+<span class="source-line-no">2221</span><span id="line-2221"> }</span>
+<span class="source-line-no">2222</span><span id="line-2222"> };</span>
+<span class="source-line-no">2223</span><span id="line-2223"> }</span>
+<span class="source-line-no">2224</span><span id="line-2224"></span>
+<span class="source-line-no">2225</span><span id="line-2225"> @Override</span>
+<span class="source-line-no">2226</span><span id="line-2226"> public BlockCache[] getBlockCaches() {</span>
+<span class="source-line-no">2227</span><span id="line-2227"> return null;</span>
+<span class="source-line-no">2228</span><span id="line-2228"> }</span>
+<span class="source-line-no">2229</span><span id="line-2229"></span>
+<span class="source-line-no">2230</span><span id="line-2230"> public int getRpcRefCount(BlockCacheKey cacheKey) {</span>
+<span class="source-line-no">2231</span><span id="line-2231"> BucketEntry bucketEntry = backingMap.get(cacheKey);</span>
+<span class="source-line-no">2232</span><span id="line-2232"> if (bucketEntry != null) {</span>
+<span class="source-line-no">2233</span><span id="line-2233"> return bucketEntry.refCnt() - (bucketEntry.markedAsEvicted.get() ? 0 : 1);</span>
+<span class="source-line-no">2234</span><span id="line-2234"> }</span>
+<span class="source-line-no">2235</span><span id="line-2235"> return 0;</span>
+<span class="source-line-no">2236</span><span id="line-2236"> }</span>
+<span class="source-line-no">2237</span><span id="line-2237"></span>
+<span class="source-line-no">2238</span><span id="line-2238"> float getAcceptableFactor() {</span>
+<span class="source-line-no">2239</span><span id="line-2239"> return acceptableFactor;</span>
+<span class="source-line-no">2240</span><span id="line-2240"> }</span>
+<span class="source-line-no">2241</span><span id="line-2241"></span>
+<span class="source-line-no">2242</span><span id="line-2242"> float getMinFactor() {</span>
+<span class="source-line-no">2243</span><span id="line-2243"> return minFactor;</span>
+<span class="source-line-no">2244</span><span id="line-2244"> }</span>
+<span class="source-line-no">2245</span><span id="line-2245"></span>
+<span class="source-line-no">2246</span><span id="line-2246"> float getExtraFreeFactor() {</span>
+<span class="source-line-no">2247</span><span id="line-2247"> return extraFreeFactor;</span>
+<span class="source-line-no">2248</span><span id="line-2248"> }</span>
+<span class="source-line-no">2249</span><span id="line-2249"></span>
+<span class="source-line-no">2250</span><span id="line-2250"> float getSingleFactor() {</span>
+<span class="source-line-no">2251</span><span id="line-2251"> return singleFactor;</span>
+<span class="source-line-no">2252</span><span id="line-2252"> }</span>
+<span class="source-line-no">2253</span><span id="line-2253"></span>
+<span class="source-line-no">2254</span><span id="line-2254"> float getMultiFactor() {</span>
+<span class="source-line-no">2255</span><span id="line-2255"> return multiFactor;</span>
+<span class="source-line-no">2256</span><span id="line-2256"> }</span>
+<span class="source-line-no">2257</span><span id="line-2257"></span>
+<span class="source-line-no">2258</span><span id="line-2258"> float getMemoryFactor() {</span>
+<span class="source-line-no">2259</span><span id="line-2259"> return memoryFactor;</span>
+<span class="source-line-no">2260</span><span id="line-2260"> }</span>
+<span class="source-line-no">2261</span><span id="line-2261"></span>
+<span class="source-line-no">2262</span><span id="line-2262"> long getQueueAdditionWaitTime() {</span>
+<span class="source-line-no">2263</span><span id="line-2263"> return queueAdditionWaitTime;</span>
+<span class="source-line-no">2264</span><span id="line-2264"> }</span>
+<span class="source-line-no">2265</span><span id="line-2265"></span>
+<span class="source-line-no">2266</span><span id="line-2266"> long getPersistenceChunkSize() {</span>
+<span class="source-line-no">2267</span><span id="line-2267"> return persistenceChunkSize;</span>
+<span class="source-line-no">2268</span><span id="line-2268"> }</span>
+<span class="source-line-no">2269</span><span id="line-2269"></span>
+<span class="source-line-no">2270</span><span id="line-2270"> long getBucketcachePersistInterval() {</span>
+<span class="source-line-no">2271</span><span id="line-2271"> return bucketcachePersistInterval;</span>
+<span class="source-line-no">2272</span><span id="line-2272"> }</span>
+<span class="source-line-no">2273</span><span id="line-2273"></span>
+<span class="source-line-no">2274</span><span id="line-2274"> public String getPersistencePath() {</span>
+<span class="source-line-no">2275</span><span id="line-2275"> return persistencePath;</span>
+<span class="source-line-no">2276</span><span id="line-2276"> }</span>
+<span class="source-line-no">2277</span><span id="line-2277"></span>
+<span class="source-line-no">2278</span><span id="line-2278"> /**</span>
+<span class="source-line-no">2279</span><span id="line-2279"> * Wrapped the delegate ConcurrentMap with maintaining its block's reference count.</span>
+<span class="source-line-no">2280</span><span id="line-2280"> */</span>
+<span class="source-line-no">2281</span><span id="line-2281"> static class RAMCache {</span>
+<span class="source-line-no">2282</span><span id="line-2282"> /**</span>
+<span class="source-line-no">2283</span><span id="line-2283"> * Defined the map as {@link ConcurrentHashMap} explicitly here, because in</span>
+<span class="source-line-no">2284</span><span id="line-2284"> * {@link RAMCache#get(BlockCacheKey)} and</span>
+<span class="source-line-no">2285</span><span id="line-2285"> * {@link RAMCache#putIfAbsent(BlockCacheKey, BucketCache.RAMQueueEntry)} , we need to guarantee</span>
+<span class="source-line-no">2286</span><span id="line-2286"> * the atomicity of map#computeIfPresent(key, func) and map#putIfAbsent(key, func). Besides, the</span>
+<span class="source-line-no">2287</span><span id="line-2287"> * func method can execute exactly once only when the key is present(or absent) and under the</span>
+<span class="source-line-no">2288</span><span id="line-2288"> * lock context. Otherwise, the reference count of block will be messed up. Notice that the</span>
+<span class="source-line-no">2289</span><span id="line-2289"> * {@link java.util.concurrent.ConcurrentSkipListMap} can not guarantee that.</span>
+<span class="source-line-no">2290</span><span id="line-2290"> */</span>
+<span class="source-line-no">2291</span><span id="line-2291"> final ConcurrentHashMap<BlockCacheKey, RAMQueueEntry> delegate = new ConcurrentHashMap<>();</span>
<span class="source-line-no">2292</span><span id="line-2292"></span>
-<span class="source-line-no">2293</span><span id="line-2293"> /**</span>
-<span class="source-line-no">2294</span><span id="line-2294"> * Return the previous associated value, or null if absent. It has the same meaning as</span>
-<span class="source-line-no">2295</span><span id="line-2295"> * {@link ConcurrentMap#putIfAbsent(Object, Object)}</span>
-<span class="source-line-no">2296</span><span id="line-2296"> */</span>
-<span class="source-line-no">2297</span><span id="line-2297"> public RAMQueueEntry putIfAbsent(BlockCacheKey key, RAMQueueEntry entry) {</span>
-<span class="source-line-no">2298</span><span id="line-2298"> AtomicBoolean absent = new AtomicBoolean(false);</span>
-<span class="source-line-no">2299</span><span id="line-2299"> RAMQueueEntry re = delegate.computeIfAbsent(key, k -> {</span>
-<span class="source-line-no">2300</span><span id="line-2300"> // The RAMCache reference to this entry, so reference count should be increment.</span>
-<span class="source-line-no">2301</span><span id="line-2301"> entry.getData().retain();</span>
-<span class="source-line-no">2302</span><span id="line-2302"> absent.set(true);</span>
-<span class="source-line-no">2303</span><span id="line-2303"> return entry;</span>
+<span class="source-line-no">2293</span><span id="line-2293"> public boolean containsKey(BlockCacheKey key) {</span>
+<span class="source-line-no">2294</span><span id="line-2294"> return delegate.containsKey(key);</span>
+<span class="source-line-no">2295</span><span id="line-2295"> }</span>
+<span class="source-line-no">2296</span><span id="line-2296"></span>
+<span class="source-line-no">2297</span><span id="line-2297"> public RAMQueueEntry get(BlockCacheKey key) {</span>
+<span class="source-line-no">2298</span><span id="line-2298"> return delegate.computeIfPresent(key, (k, re) -> {</span>
+<span class="source-line-no">2299</span><span id="line-2299"> // It'll be referenced by RPC, so retain atomically here. if the get and retain is not</span>
+<span class="source-line-no">2300</span><span id="line-2300"> // atomic, another thread may remove and release the block, when retaining in this thread we</span>
+<span class="source-line-no">2301</span><span id="line-2301"> // may retain a block with refCnt=0 which is disallowed. (see HBASE-22422)</span>
+<span class="source-line-no">2302</span><span id="line-2302"> re.getData().retain();</span>
+<span class="source-line-no">2303</span><span id="line-2303"> return re;</span>
<span class="source-line-no">2304</span><span id="line-2304"> });</span>
-<span class="source-line-no">2305</span><span id="line-2305"> return absent.get() ? null : re;</span>
-<span class="source-line-no">2306</span><span id="line-2306"> }</span>
-<span class="source-line-no">2307</span><span id="line-2307"></span>
-<span class="source-line-no">2308</span><span id="line-2308"> public boolean remove(BlockCacheKey key) {</span>
-<span class="source-line-no">2309</span><span id="line-2309"> return remove(key, re -> {</span>
-<span class="source-line-no">2310</span><span id="line-2310"> });</span>
-<span class="source-line-no">2311</span><span id="line-2311"> }</span>
-<span class="source-line-no">2312</span><span id="line-2312"></span>
-<span class="source-line-no">2313</span><span id="line-2313"> /**</span>
-<span class="source-line-no">2314</span><span id="line-2314"> * Defined an {@link Consumer} here, because once the removed entry release its reference count,</span>
-<span class="source-line-no">2315</span><span id="line-2315"> * then it's ByteBuffers may be recycled and accessing it outside this method will be thrown an</span>
-<span class="source-line-no">2316</span><span id="line-2316"> * exception. the consumer will access entry to remove before release its reference count.</span>
-<span class="source-line-no">2317</span><span id="line-2317"> * Notice, don't change its reference count in the {@link Consumer}</span>
-<span class="source-line-no">2318</span><span id="line-2318"> */</span>
-<span class="source-line-no">2319</span><span id="line-2319"> public boolean remove(BlockCacheKey key, Consumer<RAMQueueEntry> action) {</span>
-<span class="source-line-no">2320</span><span id="line-2320"> RAMQueueEntry previous = delegate.remove(key);</span>
-<span class="source-line-no">2321</span><span id="line-2321"> action.accept(previous);</span>
-<span class="source-line-no">2322</span><span id="line-2322"> if (previous != null) {</span>
-<span class="source-line-no">2323</span><span id="line-2323"> previous.getData().release();</span>
-<span class="source-line-no">2324</span><span id="line-2324"> }</span>
-<span class="source-line-no">2325</span><span id="line-2325"> return previous != null;</span>
-<span class="source-line-no">2326</span><span id="line-2326"> }</span>
-<span class="source-line-no">2327</span><span id="line-2327"></span>
-<span class="source-line-no">2328</span><span id="line-2328"> public boolean isEmpty() {</span>
-<span class="source-line-no">2329</span><span id="line-2329"> return delegate.isEmpty();</span>
-<span class="source-line-no">2330</span><span id="line-2330"> }</span>
-<span class="source-line-no">2331</span><span id="line-2331"></span>
-<span class="source-line-no">2332</span><span id="line-2332"> public void clear() {</span>
-<span class="source-line-no">2333</span><span id="line-2333"> Iterator<Map.Entry<BlockCacheKey, RAMQueueEntry>> it = delegate.entrySet().iterator();</span>
-<span class="source-line-no">2334</span><span id="line-2334"> while (it.hasNext()) {</span>
-<span class="source-line-no">2335</span><span id="line-2335"> RAMQueueEntry re = it.next().getValue();</span>
-<span class="source-line-no">2336</span><span id="line-2336"> it.remove();</span>
-<span class="source-line-no">2337</span><span id="line-2337"> re.getData().release();</span>
+<span class="source-line-no">2305</span><span id="line-2305"> }</span>
+<span class="source-line-no">2306</span><span id="line-2306"></span>
+<span class="source-line-no">2307</span><span id="line-2307"> /**</span>
+<span class="source-line-no">2308</span><span id="line-2308"> * Return the previous associated value, or null if absent. It has the same meaning as</span>
+<span class="source-line-no">2309</span><span id="line-2309"> * {@link ConcurrentMap#putIfAbsent(Object, Object)}</span>
+<span class="source-line-no">2310</span><span id="line-2310"> */</span>
+<span class="source-line-no">2311</span><span id="line-2311"> public RAMQueueEntry putIfAbsent(BlockCacheKey key, RAMQueueEntry entry) {</span>
+<span class="source-line-no">2312</span><span id="line-2312"> AtomicBoolean absent = new AtomicBoolean(false);</span>
+<span class="source-line-no">2313</span><span id="line-2313"> RAMQueueEntry re = delegate.computeIfAbsent(key, k -> {</span>
+<span class="source-line-no">2314</span><span id="line-2314"> // The RAMCache reference to this entry, so reference count should be increment.</span>
+<span class="source-line-no">2315</span><span id="line-2315"> entry.getData().retain();</span>
+<span class="source-line-no">2316</span><span id="line-2316"> absent.set(true);</span>
+<span class="source-line-no">2317</span><span id="line-2317"> return entry;</span>
+<span class="source-line-no">2318</span><span id="line-2318"> });</span>
+<span class="source-line-no">2319</span><span id="line-2319"> return absent.get() ? null : re;</span>
+<span class="source-line-no">2320</span><span id="line-2320"> }</span>
+<span class="source-line-no">2321</span><span id="line-2321"></span>
+<span class="source-line-no">2322</span><span id="line-2322"> public boolean remove(BlockCacheKey key) {</span>
+<span class="source-line-no">2323</span><span id="line-2323"> return remove(key, re -> {</span>
+<span class="source-line-no">2324</span><span id="line-2324"> });</span>
+<span class="source-line-no">2325</span><span id="line-2325"> }</span>
+<span class="source-line-no">2326</span><span id="line-2326"></span>
+<span class="source-line-no">2327</span><span id="line-2327"> /**</span>
+<span class="source-line-no">2328</span><span id="line-2328"> * Defined an {@link Consumer} here, because once the removed entry release its reference count,</span>
+<span class="source-line-no">2329</span><span id="line-2329"> * then it's ByteBuffers may be recycled and accessing it outside this method will be thrown an</span>
+<span class="source-line-no">2330</span><span id="line-2330"> * exception. the consumer will access entry to remove before release its reference count.</span>
+<span class="source-line-no">2331</span><span id="line-2331"> * Notice, don't change its reference count in the {@link Consumer}</span>
+<span class="source-line-no">2332</span><span id="line-2332"> */</span>
+<span class="source-line-no">2333</span><span id="line-2333"> public boolean remove(BlockCacheKey key, Consumer<RAMQueueEntry> action) {</span>
+<span class="source-line-no">2334</span><span id="line-2334"> RAMQueueEntry previous = delegate.remove(key);</span>
+<span class="source-line-no">2335</span><span id="line-2335"> action.accept(previous);</span>
+<span class="source-line-no">2336</span><span id="line-2336"> if (previous != null) {</span>
+<span class="source-line-no">2337</span><span id="line-2337"> previous.getData().release();</span>
<span class="source-line-no">2338</span><span id="line-2338"> }</span>
-<span class="source-line-no">2339</span><span id="line-2339"> }</span>
-<span class="source-line-no">2340</span><span id="line-2340"></span>
-<span class="source-line-no">2341</span><span id="line-2341"> public boolean hasBlocksForFile(String fileName) {</span>
-<span class="source-line-no">2342</span><span id="line-2342"> return delegate.keySet().stream().filter(key -> key.getHfileName().equals(fileName))</span>
-<span class="source-line-no">2343</span><span id="line-2343"> .findFirst().isPresent();</span>
+<span class="source-line-no">2339</span><span id="line-2339"> return previous != null;</span>
+<span class="source-line-no">2340</span><span id="line-2340"> }</span>
+<span class="source-line-no">2341</span><span id="line-2341"></span>
+<span class="source-line-no">2342</span><span id="line-2342"> public boolean isEmpty() {</span>
+<span class="source-line-no">2343</span><span id="line-2343"> return delegate.isEmpty();</span>
<span class="source-line-no">2344</span><span id="line-2344"> }</span>
-<span class="source-line-no">2345</span><span id="line-2345"> }</span>
-<span class="source-line-no">2346</span><span id="line-2346"></span>
-<span class="source-line-no">2347</span><span id="line-2347"> public Map<BlockCacheKey, BucketEntry> getBackingMap() {</span>
-<span class="source-line-no">2348</span><span id="line-2348"> return backingMap;</span>
-<span class="source-line-no">2349</span><span id="line-2349"> }</span>
-<span class="source-line-no">2350</span><span id="line-2350"></span>
-<span class="source-line-no">2351</span><span id="line-2351"> public AtomicBoolean getBackingMapValidated() {</span>
-<span class="source-line-no">2352</span><span id="line-2352"> return backingMapValidated;</span>
-<span class="source-line-no">2353</span><span id="line-2353"> }</span>
+<span class="source-line-no">2345</span><span id="line-2345"></span>
+<span class="source-line-no">2346</span><span id="line-2346"> public void clear() {</span>
+<span class="source-line-no">2347</span><span id="line-2347"> Iterator<Map.Entry<BlockCacheKey, RAMQueueEntry>> it = delegate.entrySet().iterator();</span>
+<span class="source-line-no">2348</span><span id="line-2348"> while (it.hasNext()) {</span>
+<span class="source-line-no">2349</span><span id="line-2349"> RAMQueueEntry re = it.next().getValue();</span>
+<span class="source-line-no">2350</span><span id="line-2350"> it.remove();</span>
+<span class="source-line-no">2351</span><span id="line-2351"> re.getData().release();</span>
+<span class="source-line-no">2352</span><span id="line-2352"> }</span>
+<span class="source-line-no">2353</span><span id="line-2353"> }</span>
<span class="source-line-no">2354</span><span id="line-2354"></span>
-<span class="source-line-no">2355</span><span id="line-2355"> @Override</span>
-<span class="source-line-no">2356</span><span id="line-2356"> public Optional<Map<String, Pair<String, Long>>> getFullyCachedFiles() {</span>
-<span class="source-line-no">2357</span><span id="line-2357"> return Optional.of(fullyCachedFiles);</span>
-<span class="source-line-no">2358</span><span id="line-2358"> }</span>
-<span class="source-line-no">2359</span><span id="line-2359"></span>
-<span class="source-line-no">2360</span><span id="line-2360"> public static Optional<BucketCache> getBucketCacheFromCacheConfig(CacheConfig cacheConf) {</span>
-<span class="source-line-no">2361</span><span id="line-2361"> if (cacheConf.getBlockCache().isPresent()) {</span>
-<span class="source-line-no">2362</span><span id="line-2362"> BlockCache bc = cacheConf.getBlockCache().get();</span>
-<span class="source-line-no">2363</span><span id="line-2363"> if (bc instanceof CombinedBlockCache) {</span>
-<span class="source-line-no">2364</span><span id="line-2364"> BlockCache l2 = ((CombinedBlockCache) bc).getSecondLevelCache();</span>
-<span class="source-line-no">2365</span><span id="line-2365"> if (l2 instanceof BucketCache) {</span>
-<span class="source-line-no">2366</span><span id="line-2366"> return Optional.of((BucketCache) l2);</span>
-<span class="source-line-no">2367</span><span id="line-2367"> }</span>
-<span class="source-line-no">2368</span><span id="line-2368"> } else if (bc instanceof BucketCache) {</span>
-<span class="source-line-no">2369</span><span id="line-2369"> return Optional.of((BucketCache) bc);</span>
-<span class="source-line-no">2370</span><span id="line-2370"> }</span>
-<span class="source-line-no">2371</span><span id="line-2371"> }</span>
-<span class="source-line-no">2372</span><span id="line-2372"> return Optional.empty();</span>
-<span class="source-line-no">2373</span><span id="line-2373"> }</span>
-<span class="source-line-no">2374</span><span id="line-2374"></span>
-<span class="source-line-no">2375</span><span id="line-2375"> @Override</span>
-<span class="source-line-no">2376</span><span id="line-2376"> public void notifyFileCachingCompleted(Path fileName, int totalBlockCount, int dataBlockCount,</span>
-<span class="source-line-no">2377</span><span id="line-2377"> long size) {</span>
-<span class="source-line-no">2378</span><span id="line-2378"> // block eviction may be happening in the background as prefetch runs,</span>
-<span class="source-line-no">2379</span><span id="line-2379"> // so we need to count all blocks for this file in the backing map under</span>
-<span class="source-line-no">2380</span><span id="line-2380"> // a read lock for the block offset</span>
-<span class="source-line-no">2381</span><span id="line-2381"> final List<ReentrantReadWriteLock> locks = new ArrayList<>();</span>
-<span class="source-line-no">2382</span><span id="line-2382"> LOG.debug("Notifying caching completed for file {}, with total blocks {}, and data blocks {}",</span>
-<span class="source-line-no">2383</span><span id="line-2383"> fileName, totalBlockCount, dataBlockCount);</span>
-<span class="source-line-no">2384</span><span id="line-2384"> try {</span>
-<span class="source-line-no">2385</span><span id="line-2385"> int count = 0;</span>
-<span class="source-line-no">2386</span><span id="line-2386"> LOG.debug("iterating over {} entries in the backing map", backingMap.size());</span>
-<span class="source-line-no">2387</span><span id="line-2387"> Set<BlockCacheKey> result = getAllCacheKeysForFile(fileName.getName(), 0, Long.MAX_VALUE);</span>
-<span class="source-line-no">2388</span><span id="line-2388"> if (result.isEmpty() && StoreFileInfo.isReference(fileName)) {</span>
-<span class="source-line-no">2389</span><span id="line-2389"> result = getAllCacheKeysForFile(</span>
-<span class="source-line-no">2390</span><span id="line-2390"> StoreFileInfo.getReferredToRegionAndFile(fileName.getName()).getSecond(), 0,</span>
-<span class="source-line-no">2391</span><span id="line-2391"> Long.MAX_VALUE);</span>
-<span class="source-line-no">2392</span><span id="line-2392"> }</span>
-<span class="source-line-no">2393</span><span id="line-2393"> for (BlockCacheKey entry : result) {</span>
-<span class="source-line-no">2394</span><span id="line-2394"> LOG.debug("found block for file {} in the backing map. Acquiring read lock for offset {}",</span>
-<span class="source-line-no">2395</span><span id="line-2395"> fileName.getName(), entry.getOffset());</span>
-<span class="source-line-no">2396</span><span id="line-2396"> ReentrantReadWriteLock lock = offsetLock.getLock(entry.getOffset());</span>
-<span class="source-line-no">2397</span><span id="line-2397"> lock.readLock().lock();</span>
-<span class="source-line-no">2398</span><span id="line-2398"> locks.add(lock);</span>
-<span class="source-line-no">2399</span><span id="line-2399"> if (backingMap.containsKey(entry) && entry.getBlockType().isData()) {</span>
-<span class="source-line-no">2400</span><span id="line-2400"> count++;</span>
-<span class="source-line-no">2401</span><span id="line-2401"> }</span>
-<span class="source-line-no">2402</span><span id="line-2402"> }</span>
-<span class="source-line-no">2403</span><span id="line-2403"> // BucketCache would only have data blocks</span>
-<span class="source-line-no">2404</span><span id="line-2404"> if (dataBlockCount == count) {</span>
-<span class="source-line-no">2405</span><span id="line-2405"> LOG.debug("File {} has now been fully cached.", fileName);</span>
-<span class="source-line-no">2406</span><span id="line-2406"> fileCacheCompleted(fileName, size);</span>
-<span class="source-line-no">2407</span><span id="line-2407"> } else {</span>
-<span class="source-line-no">2408</span><span id="line-2408"> LOG.debug(</span>
-<span class="source-line-no">2409</span><span id="line-2409"> "Prefetch executor completed for {}, but only {} data blocks were cached. "</span>
-<span class="source-line-no">2410</span><span id="line-2410"> + "Total data blocks for file: {}. "</span>
-<span class="source-line-no">2411</span><span id="line-2411"> + "Checking for blocks pending cache in cache writer queue.",</span>
-<span class="source-line-no">2412</span><span id="line-2412"> fileName, count, dataBlockCount);</span>
-<span class="source-line-no">2413</span><span id="line-2413"> if (ramCache.hasBlocksForFile(fileName.getName())) {</span>
-<span class="source-line-no">2414</span><span id="line-2414"> for (ReentrantReadWriteLock lock : locks) {</span>
-<span class="source-line-no">2415</span><span id="line-2415"> lock.readLock().unlock();</span>
-<span class="source-line-no">2416</span><span id="line-2416"> }</span>
-<span class="source-line-no">2417</span><span id="line-2417"> locks.clear();</span>
-<span class="source-line-no">2418</span><span id="line-2418"> LOG.debug("There are still blocks pending caching for file {}. Will sleep 100ms "</span>
-<span class="source-line-no">2419</span><span id="line-2419"> + "and try the verification again.", fileName);</span>
-<span class="source-line-no">2420</span><span id="line-2420"> Thread.sleep(100);</span>
-<span class="source-line-no">2421</span><span id="line-2421"> notifyFileCachingCompleted(fileName, totalBlockCount, dataBlockCount, size);</span>
-<span class="source-line-no">2422</span><span id="line-2422"> } else {</span>
-<span class="source-line-no">2423</span><span id="line-2423"> LOG.info(</span>
-<span class="source-line-no">2424</span><span id="line-2424"> "The total block count was {}. We found only {} data blocks cached from "</span>
-<span class="source-line-no">2425</span><span id="line-2425"> + "a total of {} data blocks for file {}, "</span>
-<span class="source-line-no">2426</span><span id="line-2426"> + "but no blocks pending caching. Maybe cache is full or evictions "</span>
-<span class="source-line-no">2427</span><span id="line-2427"> + "happened concurrently to cache prefetch.",</span>
-<span class="source-line-no">2428</span><span id="line-2428"> totalBlockCount, count, dataBlockCount, fileName);</span>
-<span class="source-line-no">2429</span><span id="line-2429"> }</span>
-<span class="source-line-no">2430</span><span id="line-2430"> }</span>
-<span class="source-line-no">2431</span><span id="line-2431"> } catch (InterruptedException e) {</span>
-<span class="source-line-no">2432</span><span id="line-2432"> throw new RuntimeException(e);</span>
-<span class="source-line-no">2433</span><span id="line-2433"> } finally {</span>
-<span class="source-line-no">2434</span><span id="line-2434"> for (ReentrantReadWriteLock lock : locks) {</span>
-<span class="source-line-no">2435</span><span id="line-2435"> lock.readLock().unlock();</span>
-<span class="source-line-no">2436</span><span id="line-2436"> }</span>
-<span class="source-line-no">2437</span><span id="line-2437"> }</span>
-<span class="source-line-no">2438</span><span id="line-2438"> }</span>
-<span class="source-line-no">2439</span><span id="line-2439"></span>
-<span class="source-line-no">2440</span><span id="line-2440"> @Override</span>
-<span class="source-line-no">2441</span><span id="line-2441"> public Optional<Boolean> blockFitsIntoTheCache(HFileBlock block) {</span>
-<span class="source-line-no">2442</span><span id="line-2442"> if (!isCacheInitialized("blockFitsIntoTheCache")) {</span>
-<span class="source-line-no">2443</span><span id="line-2443"> return Optional.of(false);</span>
-<span class="source-line-no">2444</span><span id="line-2444"> }</span>
-<span class="source-line-no">2445</span><span id="line-2445"></span>
-<span class="source-line-no">2446</span><span id="line-2446"> long currentUsed = bucketAllocator.getUsedSize();</span>
-<span class="source-line-no">2447</span><span id="line-2447"> boolean result = (currentUsed + block.getOnDiskSizeWithHeader()) < acceptableSize();</span>
-<span class="source-line-no">2448</span><span id="line-2448"> return Optional.of(result);</span>
-<span class="source-line-no">2449</span><span id="line-2449"> }</span>
-<span class="source-line-no">2450</span><span id="line-2450"></span>
-<span class="source-line-no">2451</span><span id="line-2451"> @Override</span>
-<span class="source-line-no">2452</span><span id="line-2452"> public Optional<Boolean> shouldCacheFile(HFileInfo hFileInfo, Configuration conf) {</span>
-<span class="source-line-no">2453</span><span id="line-2453"> String fileName = hFileInfo.getHFileContext().getHFileName();</span>
-<span class="source-line-no">2454</span><span id="line-2454"> DataTieringManager dataTieringManager = DataTieringManager.getInstance();</span>
-<span class="source-line-no">2455</span><span id="line-2455"> if (dataTieringManager != null && !dataTieringManager.isHotData(hFileInfo, conf)) {</span>
-<span class="source-line-no">2456</span><span id="line-2456"> LOG.debug("Data tiering is enabled for file: '{}' and it is not hot data", fileName);</span>
+<span class="source-line-no">2355</span><span id="line-2355"> public boolean hasBlocksForFile(String fileName) {</span>
+<span class="source-line-no">2356</span><span id="line-2356"> return delegate.keySet().stream().filter(key -> key.getHfileName().equals(fileName))</span>
+<span class="source-line-no">2357</span><span id="line-2357"> .findFirst().isPresent();</span>
+<span class="source-line-no">2358</span><span id="line-2358"> }</span>
+<span class="source-line-no">2359</span><span id="line-2359"> }</span>
+<span class="source-line-no">2360</span><span id="line-2360"></span>
+<span class="source-line-no">2361</span><span id="line-2361"> public Map<BlockCacheKey, BucketEntry> getBackingMap() {</span>
+<span class="source-line-no">2362</span><span id="line-2362"> return backingMap;</span>
+<span class="source-line-no">2363</span><span id="line-2363"> }</span>
+<span class="source-line-no">2364</span><span id="line-2364"></span>
+<span class="source-line-no">2365</span><span id="line-2365"> public AtomicBoolean getBackingMapValidated() {</span>
+<span class="source-line-no">2366</span><span id="line-2366"> return backingMapValidated;</span>
+<span class="source-line-no">2367</span><span id="line-2367"> }</span>
+<span class="source-line-no">2368</span><span id="line-2368"></span>
+<span class="source-line-no">2369</span><span id="line-2369"> @Override</span>
+<span class="source-line-no">2370</span><span id="line-2370"> public Optional<Map<String, Pair<String, Long>>> getFullyCachedFiles() {</span>
+<span class="source-line-no">2371</span><span id="line-2371"> return Optional.of(fullyCachedFiles);</span>
+<span class="source-line-no">2372</span><span id="line-2372"> }</span>
+<span class="source-line-no">2373</span><span id="line-2373"></span>
+<span class="source-line-no">2374</span><span id="line-2374"> public static Optional<BucketCache> getBucketCacheFromCacheConfig(CacheConfig cacheConf) {</span>
+<span class="source-line-no">2375</span><span id="line-2375"> if (cacheConf.getBlockCache().isPresent()) {</span>
+<span class="source-line-no">2376</span><span id="line-2376"> BlockCache bc = cacheConf.getBlockCache().get();</span>
+<span class="source-line-no">2377</span><span id="line-2377"> if (bc instanceof CombinedBlockCache) {</span>
+<span class="source-line-no">2378</span><span id="line-2378"> BlockCache l2 = ((CombinedBlockCache) bc).getSecondLevelCache();</span>
+<span class="source-line-no">2379</span><span id="line-2379"> if (l2 instanceof BucketCache) {</span>
+<span class="source-line-no">2380</span><span id="line-2380"> return Optional.of((BucketCache) l2);</span>
+<span class="source-line-no">2381</span><span id="line-2381"> }</span>
+<span class="source-line-no">2382</span><span id="line-2382"> } else if (bc instanceof BucketCache) {</span>
+<span class="source-line-no">2383</span><span id="line-2383"> return Optional.of((BucketCache) bc);</span>
+<span class="source-line-no">2384</span><span id="line-2384"> }</span>
+<span class="source-line-no">2385</span><span id="line-2385"> }</span>
+<span class="source-line-no">2386</span><span id="line-2386"> return Optional.empty();</span>
+<span class="source-line-no">2387</span><span id="line-2387"> }</span>
+<span class="source-line-no">2388</span><span id="line-2388"></span>
+<span class="source-line-no">2389</span><span id="line-2389"> @Override</span>
+<span class="source-line-no">2390</span><span id="line-2390"> public void notifyFileCachingCompleted(Path fileName, int totalBlockCount, int dataBlockCount,</span>
+<span class="source-line-no">2391</span><span id="line-2391"> long size) {</span>
+<span class="source-line-no">2392</span><span id="line-2392"> // block eviction may be happening in the background as prefetch runs,</span>
+<span class="source-line-no">2393</span><span id="line-2393"> // so we need to count all blocks for this file in the backing map under</span>
+<span class="source-line-no">2394</span><span id="line-2394"> // a read lock for the block offset</span>
+<span class="source-line-no">2395</span><span id="line-2395"> final List<ReentrantReadWriteLock> locks = new ArrayList<>();</span>
+<span class="source-line-no">2396</span><span id="line-2396"> LOG.debug("Notifying caching completed for file {}, with total blocks {}, and data blocks {}",</span>
+<span class="source-line-no">2397</span><span id="line-2397"> fileName, totalBlockCount, dataBlockCount);</span>
+<span class="source-line-no">2398</span><span id="line-2398"> try {</span>
+<span class="source-line-no">2399</span><span id="line-2399"> int count = 0;</span>
+<span class="source-line-no">2400</span><span id="line-2400"> LOG.debug("iterating over {} entries in the backing map", backingMap.size());</span>
+<span class="source-line-no">2401</span><span id="line-2401"> Set<BlockCacheKey> result = getAllCacheKeysForFile(fileName.getName(), 0, Long.MAX_VALUE);</span>
+<span class="source-line-no">2402</span><span id="line-2402"> if (result.isEmpty() && StoreFileInfo.isReference(fileName)) {</span>
+<span class="source-line-no">2403</span><span id="line-2403"> result = getAllCacheKeysForFile(</span>
+<span class="source-line-no">2404</span><span id="line-2404"> StoreFileInfo.getReferredToRegionAndFile(fileName.getName()).getSecond(), 0,</span>
+<span class="source-line-no">2405</span><span id="line-2405"> Long.MAX_VALUE);</span>
+<span class="source-line-no">2406</span><span id="line-2406"> }</span>
+<span class="source-line-no">2407</span><span id="line-2407"> for (BlockCacheKey entry : result) {</span>
+<span class="source-line-no">2408</span><span id="line-2408"> LOG.debug("found block for file {} in the backing map. Acquiring read lock for offset {}",</span>
+<span class="source-line-no">2409</span><span id="line-2409"> fileName.getName(), entry.getOffset());</span>
+<span class="source-line-no">2410</span><span id="line-2410"> ReentrantReadWriteLock lock = offsetLock.getLock(entry.getOffset());</span>
+<span class="source-line-no">2411</span><span id="line-2411"> lock.readLock().lock();</span>
+<span class="source-line-no">2412</span><span id="line-2412"> locks.add(lock);</span>
+<span class="source-line-no">2413</span><span id="line-2413"> if (backingMap.containsKey(entry) && entry.getBlockType().isData()) {</span>
+<span class="source-line-no">2414</span><span id="line-2414"> count++;</span>
+<span class="source-line-no">2415</span><span id="line-2415"> }</span>
+<span class="source-line-no">2416</span><span id="line-2416"> }</span>
+<span class="source-line-no">2417</span><span id="line-2417"> // BucketCache would only have data blocks</span>
+<span class="source-line-no">2418</span><span id="line-2418"> if (dataBlockCount == count) {</span>
+<span class="source-line-no">2419</span><span id="line-2419"> LOG.debug("File {} has now been fully cached.", fileName);</span>
+<span class="source-line-no">2420</span><span id="line-2420"> fileCacheCompleted(fileName, size);</span>
+<span class="source-line-no">2421</span><span id="line-2421"> } else {</span>
+<span class="source-line-no">2422</span><span id="line-2422"> LOG.debug(</span>
+<span class="source-line-no">2423</span><span id="line-2423"> "Prefetch executor completed for {}, but only {} data blocks were cached. "</span>
+<span class="source-line-no">2424</span><span id="line-2424"> + "Total data blocks for file: {}. "</span>
+<span class="source-line-no">2425</span><span id="line-2425"> + "Checking for blocks pending cache in cache writer queue.",</span>
+<span class="source-line-no">2426</span><span id="line-2426"> fileName, count, dataBlockCount);</span>
+<span class="source-line-no">2427</span><span id="line-2427"> if (ramCache.hasBlocksForFile(fileName.getName())) {</span>
+<span class="source-line-no">2428</span><span id="line-2428"> for (ReentrantReadWriteLock lock : locks) {</span>
+<span class="source-line-no">2429</span><span id="line-2429"> lock.readLock().unlock();</span>
+<span class="source-line-no">2430</span><span id="line-2430"> }</span>
+<span class="source-line-no">2431</span><span id="line-2431"> locks.clear();</span>
+<span class="source-line-no">2432</span><span id="line-2432"> LOG.debug("There are still blocks pending caching for file {}. Will sleep 100ms "</span>
+<span class="source-line-no">2433</span><span id="line-2433"> + "and try the verification again.", fileName);</span>
+<span class="source-line-no">2434</span><span id="line-2434"> Thread.sleep(100);</span>
+<span class="source-line-no">2435</span><span id="line-2435"> notifyFileCachingCompleted(fileName, totalBlockCount, dataBlockCount, size);</span>
+<span class="source-line-no">2436</span><span id="line-2436"> } else {</span>
+<span class="source-line-no">2437</span><span id="line-2437"> LOG.info(</span>
+<span class="source-line-no">2438</span><span id="line-2438"> "The total block count was {}. We found only {} data blocks cached from "</span>
+<span class="source-line-no">2439</span><span id="line-2439"> + "a total of {} data blocks for file {}, "</span>
+<span class="source-line-no">2440</span><span id="line-2440"> + "but no blocks pending caching. Maybe cache is full or evictions "</span>
+<span class="source-line-no">2441</span><span id="line-2441"> + "happened concurrently to cache prefetch.",</span>
+<span class="source-line-no">2442</span><span id="line-2442"> totalBlockCount, count, dataBlockCount, fileName);</span>
+<span class="source-line-no">2443</span><span id="line-2443"> }</span>
+<span class="source-line-no">2444</span><span id="line-2444"> }</span>
+<span class="source-line-no">2445</span><span id="line-2445"> } catch (InterruptedException e) {</span>
+<span class="source-line-no">2446</span><span id="line-2446"> throw new RuntimeException(e);</span>
+<span class="source-line-no">2447</span><span id="line-2447"> } finally {</span>
+<span class="source-line-no">2448</span><span id="line-2448"> for (ReentrantReadWriteLock lock : locks) {</span>
+<span class="source-line-no">2449</span><span id="line-2449"> lock.readLock().unlock();</span>
+<span class="source-line-no">2450</span><span id="line-2450"> }</span>
+<span class="source-line-no">2451</span><span id="line-2451"> }</span>
+<span class="source-line-no">2452</span><span id="line-2452"> }</span>
+<span class="source-line-no">2453</span><span id="line-2453"></span>
+<span class="source-line-no">2454</span><span id="line-2454"> @Override</span>
+<span class="source-line-no">2455</span><span id="line-2455"> public Optional<Boolean> blockFitsIntoTheCache(HFileBlock block) {</span>
+<span class="source-line-no">2456</span><span id="line-2456"> if (!isCacheInitialized("blockFitsIntoTheCache")) {</span>
<span class="source-line-no">2457</span><span id="line-2457"> return Optional.of(false);</span>
<span class="source-line-no">2458</span><span id="line-2458"> }</span>
-<span class="source-line-no">2459</span><span id="line-2459"> // if we don't have the file in fullyCachedFiles, we should cache it</span>
-<span class="source-line-no">2460</span><span id="line-2460"> return Optional.of(!fullyCachedFiles.containsKey(fileName));</span>
-<span class="source-line-no">2461</span><span id="line-2461"> }</span>
-<span class="source-line-no">2462</span><span id="line-2462"></span>
-<span class="source-line-no">2463</span><span id="line-2463"> @Override</span>
-<span class="source-line-no">2464</span><span id="line-2464"> public Optional<Boolean> shouldCacheBlock(BlockCacheKey key, long maxTimestamp,</span>
-<span class="source-line-no">2465</span><span id="line-2465"> Configuration conf) {</span>
-<span class="source-line-no">2466</span><span id="line-2466"> DataTieringManager dataTieringManager = DataTieringManager.getInstance();</span>
-<span class="source-line-no">2467</span><span id="line-2467"> if (dataTieringManager != null && !dataTieringManager.isHotData(maxTimestamp, conf)) {</span>
-<span class="source-line-no">2468</span><span id="line-2468"> LOG.debug("Data tiering is enabled for file: '{}' and it is not hot data",</span>
-<span class="source-line-no">2469</span><span id="line-2469"> key.getHfileName());</span>
-<span class="source-line-no">2470</span><span id="line-2470"> return Optional.of(false);</span>
-<span class="source-line-no">2471</span><span id="line-2471"> }</span>
-<span class="source-line-no">2472</span><span id="line-2472"> return Optional.of(true);</span>
-<span class="source-line-no">2473</span><span id="line-2473"> }</span>
-<span class="source-line-no">2474</span><span id="line-2474"></span>
-<span class="source-line-no">2475</span><span id="line-2475"> @Override</span>
-<span class="source-line-no">2476</span><span id="line-2476"> public Optional<Boolean> isAlreadyCached(BlockCacheKey key) {</span>
-<span class="source-line-no">2477</span><span id="line-2477"> boolean foundKey = backingMap.containsKey(key);</span>
-<span class="source-line-no">2478</span><span id="line-2478"> // if there's no entry for the key itself, we need to check if this key is for a reference,</span>
-<span class="source-line-no">2479</span><span id="line-2479"> // and if so, look for a block from the referenced file using this getBlockForReference method.</span>
-<span class="source-line-no">2480</span><span id="line-2480"> return Optional.of(foundKey ? true : getBlockForReference(key) != null);</span>
-<span class="source-line-no">2481</span><span id="line-2481"> }</span>
-<span class="source-line-no">2482</span><span id="line-2482"></span>
-<span class="source-line-no">2483</span><span id="line-2483"> @Override</span>
-<span class="source-line-no">2484</span><span id="line-2484"> public Optional<Integer> getBlockSize(BlockCacheKey key) {</span>
-<span class="source-line-no">2485</span><span id="line-2485"> BucketEntry entry = backingMap.get(key);</span>
-<span class="source-line-no">2486</span><span id="line-2486"> if (entry == null) {</span>
-<span class="source-line-no">2487</span><span id="line-2487"> // the key might be for a reference tha we had found the block from the referenced file in</span>
-<span class="source-line-no">2488</span><span id="line-2488"> // the cache when we first tried to cache it.</span>
-<span class="source-line-no">2489</span><span id="line-2489"> entry = getBlockForReference(key);</span>
-<span class="source-line-no">2490</span><span id="line-2490"> return entry == null ? Optional.empty() : Optional.of(entry.getOnDiskSizeWithHeader());</span>
-<span class="source-line-no">2491</span><span id="line-2491"> } else {</span>
-<span class="source-line-no">2492</span><span id="line-2492"> return Optional.of(entry.getOnDiskSizeWithHeader());</span>
-<span class="source-line-no">2493</span><span id="line-2493"> }</span>
-<span class="source-line-no">2494</span><span id="line-2494"></span>
+<span class="source-line-no">2459</span><span id="line-2459"></span>
+<span class="source-line-no">2460</span><span id="line-2460"> long currentUsed = bucketAllocator.getUsedSize();</span>
+<span class="source-line-no">2461</span><span id="line-2461"> boolean result = (currentUsed + block.getOnDiskSizeWithHeader()) < acceptableSize();</span>
+<span class="source-line-no">2462</span><span id="line-2462"> return Optional.of(result);</span>
+<span class="source-line-no">2463</span><span id="line-2463"> }</span>
+<span class="source-line-no">2464</span><span id="line-2464"></span>
+<span class="source-line-no">2465</span><span id="line-2465"> @Override</span>
+<span class="source-line-no">2466</span><span id="line-2466"> public Optional<Boolean> shouldCacheFile(HFileInfo hFileInfo, Configuration conf) {</span>
+<span class="source-line-no">2467</span><span id="line-2467"> String fileName = hFileInfo.getHFileContext().getHFileName();</span>
+<span class="source-line-no">2468</span><span id="line-2468"> DataTieringManager dataTieringManager = DataTieringManager.getInstance();</span>
+<span class="source-line-no">2469</span><span id="line-2469"> if (dataTieringManager != null && !dataTieringManager.isHotData(hFileInfo, conf)) {</span>
+<span class="source-line-no">2470</span><span id="line-2470"> LOG.debug("Data tiering is enabled for file: '{}' and it is not hot data", fileName);</span>
+<span class="source-line-no">2471</span><span id="line-2471"> return Optional.of(false);</span>
+<span class="source-line-no">2472</span><span id="line-2472"> }</span>
+<span class="source-line-no">2473</span><span id="line-2473"> // if we don't have the file in fullyCachedFiles, we should cache it</span>
+<span class="source-line-no">2474</span><span id="line-2474"> return Optional.of(!fullyCachedFiles.containsKey(fileName));</span>
+<span class="source-line-no">2475</span><span id="line-2475"> }</span>
+<span class="source-line-no">2476</span><span id="line-2476"></span>
+<span class="source-line-no">2477</span><span id="line-2477"> @Override</span>
+<span class="source-line-no">2478</span><span id="line-2478"> public Optional<Boolean> shouldCacheBlock(BlockCacheKey key, long maxTimestamp,</span>
+<span class="source-line-no">2479</span><span id="line-2479"> Configuration conf) {</span>
+<span class="source-line-no">2480</span><span id="line-2480"> DataTieringManager dataTieringManager = DataTieringManager.getInstance();</span>
+<span class="source-line-no">2481</span><span id="line-2481"> if (dataTieringManager != null && !dataTieringManager.isHotData(maxTimestamp, conf)) {</span>
+<span class="source-line-no">2482</span><span id="line-2482"> LOG.debug("Data tiering is enabled for file: '{}' and it is not hot data",</span>
+<span class="source-line-no">2483</span><span id="line-2483"> key.getHfileName());</span>
+<span class="source-line-no">2484</span><span id="line-2484"> return Optional.of(false);</span>
+<span class="source-line-no">2485</span><span id="line-2485"> }</span>
+<span class="source-line-no">2486</span><span id="line-2486"> return Optional.of(true);</span>
+<span class="source-line-no">2487</span><span id="line-2487"> }</span>
+<span class="source-line-no">2488</span><span id="line-2488"></span>
+<span class="source-line-no">2489</span><span id="line-2489"> @Override</span>
+<span class="source-line-no">2490</span><span id="line-2490"> public Optional<Boolean> isAlreadyCached(BlockCacheKey key) {</span>
+<span class="source-line-no">2491</span><span id="line-2491"> boolean foundKey = backingMap.containsKey(key);</span>
+<span class="source-line-no">2492</span><span id="line-2492"> // if there's no entry for the key itself, we need to check if this key is for a reference,</span>
+<span class="source-line-no">2493</span><span id="line-2493"> // and if so, look for a block from the referenced file using this getBlockForReference method.</span>
+<span class="source-line-no">2494</span><span id="line-2494"> return Optional.of(foundKey ? true : getBlockForReference(key) != null);</span>
<span class="source-line-no">2495</span><span id="line-2495"> }</span>
<span class="source-line-no">2496</span><span id="line-2496"></span>
-<span class="source-line-no">2497</span><span id="line-2497"> boolean isCacheInitialized(String api) {</span>
-<span class="source-line-no">2498</span><span id="line-2498"> if (cacheState == CacheState.INITIALIZING) {</span>
-<span class="source-line-no">2499</span><span id="line-2499"> LOG.warn("Bucket initialisation pending at {}", api);</span>
-<span class="source-line-no">2500</span><span id="line-2500"> return false;</span>
-<span class="source-line-no">2501</span><span id="line-2501"> }</span>
-<span class="source-line-no">2502</span><span id="line-2502"> return true;</span>
-<span class="source-line-no">2503</span><span id="line-2503"> }</span>
-<span class="source-line-no">2504</span><span id="line-2504"></span>
-<span class="source-line-no">2505</span><span id="line-2505"> @Override</span>
-<span class="source-line-no">2506</span><span id="line-2506"> public boolean waitForCacheInitialization(long timeout) {</span>
-<span class="source-line-no">2507</span><span id="line-2507"> while (cacheState == CacheState.INITIALIZING) {</span>
-<span class="source-line-no">2508</span><span id="line-2508"> if (timeout <= 0) {</span>
-<span class="source-line-no">2509</span><span id="line-2509"> break;</span>
-<span class="source-line-no">2510</span><span id="line-2510"> }</span>
-<span class="source-line-no">2511</span><span id="line-2511"> try {</span>
-<span class="source-line-no">2512</span><span id="line-2512"> Thread.sleep(100);</span>
-<span class="source-line-no">2513</span><span id="line-2513"> } catch (InterruptedException e) {</span>
-<span class="source-line-no">2514</span><span id="line-2514"> LOG.warn("Interrupted while waiting for cache initialization", e);</span>
-<span class="source-line-no">2515</span><span id="line-2515"> Thread.currentThread().interrupt();</span>
-<span class="source-line-no">2516</span><span id="line-2516"> break;</span>
-<span class="source-line-no">2517</span><span id="line-2517"> }</span>
-<span class="source-line-no">2518</span><span id="line-2518"> timeout -= 100;</span>
-<span class="source-line-no">2519</span><span id="line-2519"> }</span>
-<span class="source-line-no">2520</span><span id="line-2520"> return isCacheEnabled();</span>
-<span class="source-line-no">2521</span><span id="line-2521"> }</span>
-<span class="source-line-no">2522</span><span id="line-2522">}</span>
+<span class="source-line-no">2497</span><span id="line-2497"> @Override</span>
+<span class="source-line-no">2498</span><span id="line-2498"> public Optional<Integer> getBlockSize(BlockCacheKey key) {</span>
+<span class="source-line-no">2499</span><span id="line-2499"> BucketEntry entry = backingMap.get(key);</span>
+<span class="source-line-no">2500</span><span id="line-2500"> if (entry == null) {</span>
+<span class="source-line-no">2501</span><span id="line-2501"> // the key might be for a reference tha we had found the block from the referenced file in</span>
+<span class="source-line-no">2502</span><span id="line-2502"> // the cache when we first tried to cache it.</span>
+<span class="source-line-no">2503</span><span id="line-2503"> entry = getBlockForReference(key);</span>
+<span class="source-line-no">2504</span><span id="line-2504"> return entry == null ? Optional.empty() : Optional.of(entry.getOnDiskSizeWithHeader());</span>
+<span class="source-line-no">2505</span><span id="line-2505"> } else {</span>
+<span class="source-line-no">2506</span><span id="line-2506"> return Optional.of(entry.getOnDiskSizeWithHeader());</span>
+<span class="source-line-no">2507</span><span id="line-2507"> }</span>
+<span class="source-line-no">2508</span><span id="line-2508"></span>
+<span class="source-line-no">2509</span><span id="line-2509"> }</span>
+<span class="source-line-no">2510</span><span id="line-2510"></span>
+<span class="source-line-no">2511</span><span id="line-2511"> boolean isCacheInitialized(String api) {</span>
+<span class="source-line-no">2512</span><span id="line-2512"> if (cacheState == CacheState.INITIALIZING) {</span>
+<span class="source-line-no">2513</span><span id="line-2513"> LOG.warn("Bucket initialisation pending at {}", api);</span>
+<span class="source-line-no">2514</span><span id="line-2514"> return false;</span>
+<span class="source-line-no">2515</span><span id="line-2515"> }</span>
+<span class="source-line-no">2516</span><span id="line-2516"> return true;</span>
+<span class="source-line-no">2517</span><span id="line-2517"> }</span>
+<span class="source-line-no">2518</span><span id="line-2518"></span>
+<span class="source-line-no">2519</span><span id="line-2519"> @Override</span>
+<span class="source-line-no">2520</span><span id="line-2520"> public boolean waitForCacheInitialization(long timeout) {</span>
+<span class="source-line-no">2521</span><span id="line-2521"> while (cacheState == CacheState.INITIALIZING) {</span>
+<span class="source-line-no">2522</span><span id="line-2522"> if (timeout <= 0) {</span>
+<span class="source-line-no">2523</span><span id="line-2523"> break;</span>
+<span class="source-line-no">2524</span><span id="line-2524"> }</span>
+<span class="source-line-no">2525</span><span id="line-2525"> try {</span>
+<span class="source-line-no">2526</span><span id="line-2526"> Thread.sleep(100);</span>
+<span class="source-line-no">2527</span><span id="line-2527"> } catch (InterruptedException e) {</span>
+<span class="source-line-no">2528</span><span id="line-2528"> LOG.warn("Interrupted while waiting for cache initialization", e);</span>
+<span class="source-line-no">2529</span><span id="line-2529"> Thread.currentThread().interrupt();</span>
+<span class="source-line-no">2530</span><span id="line-2530"> break;</span>
+<span class="source-line-no">2531</span><span id="line-2531"> }</span>
+<span class="source-line-no">2532</span><span id="line-2532"> timeout -= 100;</span>
+<span class="source-line-no">2533</span><span id="line-2533"> }</span>
+<span class="source-line-no">2534</span><span id="line-2534"> return isCacheEnabled();</span>
+<span class="source-line-no">2535</span><span id="line-2535"> }</span>
+<span class="source-line-no">2536</span><span id="line-2536">}</span>
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.CacheState.html b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.CacheState.html
index 6d6b02a4476..7d3730ec01f 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.CacheState.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.CacheState.html
@@ -1624,915 +1624,929 @@
<span class="source-line-no">1611</span><span id="line-1611"> int pblen = ProtobufMagic.lengthOfPBMagic();</span>
<span class="source-line-no">1612</span><span id="line-1612"> byte[] pbuf = new byte[pblen];</span>
<span class="source-line-no">1613</span><span id="line-1613"> IOUtils.readFully(in, pbuf, 0, pblen);</span>
-<span class="source-line-no">1614</span><span id="line-1614"> if (ProtobufMagic.isPBMagicPrefix(pbuf)) {</span>
-<span class="source-line-no">1615</span><span id="line-1615"> LOG.info("Reading old format of persistence.");</span>
-<span class="source-line-no">1616</span><span id="line-1616"> // The old non-chunked version of backing map persistence.</span>
-<span class="source-line-no">1617</span><span id="line-1617"> parsePB(BucketCacheProtos.BucketCacheEntry.parseDelimitedFrom(in));</span>
-<span class="source-line-no">1618</span><span id="line-1618"> } else if (Arrays.equals(pbuf, BucketProtoUtils.PB_MAGIC_V2)) {</span>
-<span class="source-line-no">1619</span><span id="line-1619"> // The new persistence format of chunked persistence.</span>
-<span class="source-line-no">1620</span><span id="line-1620"> LOG.info("Reading new chunked format of persistence.");</span>
-<span class="source-line-no">1621</span><span id="line-1621"> retrieveChunkedBackingMap(in);</span>
-<span class="source-line-no">1622</span><span id="line-1622"> } else {</span>
-<span class="source-line-no">1623</span><span id="line-1623"> // In 3.0 we have enough flexibility to dump the old cache data.</span>
-<span class="source-line-no">1624</span><span id="line-1624"> // TODO: In 2.x line, this might need to be filled in to support reading the old format</span>
-<span class="source-line-no">1625</span><span id="line-1625"> throw new IOException(</span>
-<span class="source-line-no">1626</span><span id="line-1626"> "Persistence file does not start with protobuf magic number. " + persistencePath);</span>
-<span class="source-line-no">1627</span><span id="line-1627"> }</span>
-<span class="source-line-no">1628</span><span id="line-1628"> bucketAllocator = new BucketAllocator(cacheCapacity, bucketSizes, backingMap, realCacheSize);</span>
-<span class="source-line-no">1629</span><span id="line-1629"> blockNumber.add(backingMap.size());</span>
-<span class="source-line-no">1630</span><span id="line-1630"> LOG.info("Bucket cache retrieved from file successfully with size: {}", backingMap.size());</span>
-<span class="source-line-no">1631</span><span id="line-1631"> }</span>
-<span class="source-line-no">1632</span><span id="line-1632"> }</span>
-<span class="source-line-no">1633</span><span id="line-1633"></span>
-<span class="source-line-no">1634</span><span id="line-1634"> private void updateRegionSizeMapWhileRetrievingFromFile() {</span>
-<span class="source-line-no">1635</span><span id="line-1635"> // Update the regionCachedSize with the region size while restarting the region server</span>
-<span class="source-line-no">1636</span><span id="line-1636"> if (LOG.isDebugEnabled()) {</span>
-<span class="source-line-no">1637</span><span id="line-1637"> LOG.debug("Updating region size map after retrieving cached file list");</span>
-<span class="source-line-no">1638</span><span id="line-1638"> dumpPrefetchList();</span>
-<span class="source-line-no">1639</span><span id="line-1639"> }</span>
-<span class="source-line-no">1640</span><span id="line-1640"> regionCachedSize.clear();</span>
-<span class="source-line-no">1641</span><span id="line-1641"> fullyCachedFiles.forEach((hFileName, hFileSize) -> {</span>
-<span class="source-line-no">1642</span><span id="line-1642"> // Get the region name for each file</span>
-<span class="source-line-no">1643</span><span id="line-1643"> String regionEncodedName = hFileSize.getFirst();</span>
-<span class="source-line-no">1644</span><span id="line-1644"> long cachedFileSize = hFileSize.getSecond();</span>
-<span class="source-line-no">1645</span><span id="line-1645"> regionCachedSize.merge(regionEncodedName, cachedFileSize,</span>
-<span class="source-line-no">1646</span><span id="line-1646"> (oldpf, fileSize) -> oldpf + fileSize);</span>
-<span class="source-line-no">1647</span><span id="line-1647"> });</span>
-<span class="source-line-no">1648</span><span id="line-1648"> }</span>
-<span class="source-line-no">1649</span><span id="line-1649"></span>
-<span class="source-line-no">1650</span><span id="line-1650"> private void dumpPrefetchList() {</span>
-<span class="source-line-no">1651</span><span id="line-1651"> for (Map.Entry<String, Pair<String, Long>> outerEntry : fullyCachedFiles.entrySet()) {</span>
-<span class="source-line-no">1652</span><span id="line-1652"> LOG.debug("Cached File Entry:<{},<{},{}>>", outerEntry.getKey(),</span>
-<span class="source-line-no">1653</span><span id="line-1653"> outerEntry.getValue().getFirst(), outerEntry.getValue().getSecond());</span>
-<span class="source-line-no">1654</span><span id="line-1654"> }</span>
+<span class="source-line-no">1614</span><span id="line-1614"></span>
+<span class="source-line-no">1615</span><span id="line-1615"> if (ProtobufMagic.isPBMagicPrefix(pbuf)) {</span>
+<span class="source-line-no">1616</span><span id="line-1616"> LOG.info("Reading old format of persistence.");</span>
+<span class="source-line-no">1617</span><span id="line-1617"> // The old non-chunked version of backing map persistence.</span>
+<span class="source-line-no">1618</span><span id="line-1618"> BucketCacheProtos.BucketCacheEntry cacheEntry =</span>
+<span class="source-line-no">1619</span><span id="line-1619"> BucketCacheProtos.BucketCacheEntry.parseDelimitedFrom(in);</span>
+<span class="source-line-no">1620</span><span id="line-1620"> if (cacheEntry == null) {</span>
+<span class="source-line-no">1621</span><span id="line-1621"> throw new IOException(</span>
+<span class="source-line-no">1622</span><span id="line-1622"> "Failed to parse cache entry from persistence file: " + persistencePath);</span>
+<span class="source-line-no">1623</span><span id="line-1623"> }</span>
+<span class="source-line-no">1624</span><span id="line-1624"> parsePB(cacheEntry);</span>
+<span class="source-line-no">1625</span><span id="line-1625"> } else if (Arrays.equals(pbuf, BucketProtoUtils.PB_MAGIC_V2)) {</span>
+<span class="source-line-no">1626</span><span id="line-1626"> // The new persistence format of chunked persistence.</span>
+<span class="source-line-no">1627</span><span id="line-1627"> LOG.info("Reading new chunked format of persistence.");</span>
+<span class="source-line-no">1628</span><span id="line-1628"> retrieveChunkedBackingMap(in);</span>
+<span class="source-line-no">1629</span><span id="line-1629"> } else {</span>
+<span class="source-line-no">1630</span><span id="line-1630"> // In 3.0 we have enough flexibility to dump the old cache data.</span>
+<span class="source-line-no">1631</span><span id="line-1631"> // TODO: In 2.x line, this might need to be filled in to support reading the old format</span>
+<span class="source-line-no">1632</span><span id="line-1632"> throw new IOException(</span>
+<span class="source-line-no">1633</span><span id="line-1633"> "Persistence file does not start with protobuf magic number. " + persistencePath);</span>
+<span class="source-line-no">1634</span><span id="line-1634"> }</span>
+<span class="source-line-no">1635</span><span id="line-1635"> bucketAllocator = new BucketAllocator(cacheCapacity, bucketSizes, backingMap, realCacheSize);</span>
+<span class="source-line-no">1636</span><span id="line-1636"> blockNumber.add(backingMap.size());</span>
+<span class="source-line-no">1637</span><span id="line-1637"> LOG.info("Bucket cache retrieved from file successfully with size: {}", backingMap.size());</span>
+<span class="source-line-no">1638</span><span id="line-1638"> }</span>
+<span class="source-line-no">1639</span><span id="line-1639"> }</span>
+<span class="source-line-no">1640</span><span id="line-1640"></span>
+<span class="source-line-no">1641</span><span id="line-1641"> private void updateRegionSizeMapWhileRetrievingFromFile() {</span>
+<span class="source-line-no">1642</span><span id="line-1642"> // Update the regionCachedSize with the region size while restarting the region server</span>
+<span class="source-line-no">1643</span><span id="line-1643"> if (LOG.isDebugEnabled()) {</span>
+<span class="source-line-no">1644</span><span id="line-1644"> LOG.debug("Updating region size map after retrieving cached file list");</span>
+<span class="source-line-no">1645</span><span id="line-1645"> dumpPrefetchList();</span>
+<span class="source-line-no">1646</span><span id="line-1646"> }</span>
+<span class="source-line-no">1647</span><span id="line-1647"> regionCachedSize.clear();</span>
+<span class="source-line-no">1648</span><span id="line-1648"> fullyCachedFiles.forEach((hFileName, hFileSize) -> {</span>
+<span class="source-line-no">1649</span><span id="line-1649"> // Get the region name for each file</span>
+<span class="source-line-no">1650</span><span id="line-1650"> String regionEncodedName = hFileSize.getFirst();</span>
+<span class="source-line-no">1651</span><span id="line-1651"> long cachedFileSize = hFileSize.getSecond();</span>
+<span class="source-line-no">1652</span><span id="line-1652"> regionCachedSize.merge(regionEncodedName, cachedFileSize,</span>
+<span class="source-line-no">1653</span><span id="line-1653"> (oldpf, fileSize) -> oldpf + fileSize);</span>
+<span class="source-line-no">1654</span><span id="line-1654"> });</span>
<span class="source-line-no">1655</span><span id="line-1655"> }</span>
<span class="source-line-no">1656</span><span id="line-1656"></span>
-<span class="source-line-no">1657</span><span id="line-1657"> private void verifyCapacityAndClasses(long capacitySize, String ioclass, String mapclass)</span>
-<span class="source-line-no">1658</span><span id="line-1658"> throws IOException {</span>
-<span class="source-line-no">1659</span><span id="line-1659"> if (capacitySize != cacheCapacity) {</span>
-<span class="source-line-no">1660</span><span id="line-1660"> throw new IOException("Mismatched cache capacity:" + StringUtils.byteDesc(capacitySize)</span>
-<span class="source-line-no">1661</span><span id="line-1661"> + ", expected: " + StringUtils.byteDesc(cacheCapacity));</span>
-<span class="source-line-no">1662</span><span id="line-1662"> }</span>
-<span class="source-line-no">1663</span><span id="line-1663"> if (!ioEngine.getClass().getName().equals(ioclass)) {</span>
-<span class="source-line-no">1664</span><span id="line-1664"> throw new IOException("Class name for IO engine mismatch: " + ioclass + ", expected:"</span>
-<span class="source-line-no">1665</span><span id="line-1665"> + ioEngine.getClass().getName());</span>
-<span class="source-line-no">1666</span><span id="line-1666"> }</span>
-<span class="source-line-no">1667</span><span id="line-1667"> if (!backingMap.getClass().getName().equals(mapclass)) {</span>
-<span class="source-line-no">1668</span><span id="line-1668"> throw new IOException("Class name for cache map mismatch: " + mapclass + ", expected:"</span>
-<span class="source-line-no">1669</span><span id="line-1669"> + backingMap.getClass().getName());</span>
-<span class="source-line-no">1670</span><span id="line-1670"> }</span>
-<span class="source-line-no">1671</span><span id="line-1671"> }</span>
-<span class="source-line-no">1672</span><span id="line-1672"></span>
-<span class="source-line-no">1673</span><span id="line-1673"> private void verifyFileIntegrity(BucketCacheProtos.BucketCacheEntry proto) {</span>
-<span class="source-line-no">1674</span><span id="line-1674"> try {</span>
-<span class="source-line-no">1675</span><span id="line-1675"> if (proto.hasChecksum()) {</span>
-<span class="source-line-no">1676</span><span id="line-1676"> ((PersistentIOEngine) ioEngine).verifyFileIntegrity(proto.getChecksum().toByteArray(),</span>
-<span class="source-line-no">1677</span><span id="line-1677"> algorithm);</span>
-<span class="source-line-no">1678</span><span id="line-1678"> }</span>
-<span class="source-line-no">1679</span><span id="line-1679"> backingMapValidated.set(true);</span>
-<span class="source-line-no">1680</span><span id="line-1680"> } catch (IOException e) {</span>
-<span class="source-line-no">1681</span><span id="line-1681"> LOG.warn("Checksum for cache file failed. "</span>
-<span class="source-line-no">1682</span><span id="line-1682"> + "We need to validate each cache key in the backing map. "</span>
-<span class="source-line-no">1683</span><span id="line-1683"> + "This may take some time, so we'll do it in a background thread,");</span>
-<span class="source-line-no">1684</span><span id="line-1684"></span>
-<span class="source-line-no">1685</span><span id="line-1685"> Runnable cacheValidator = () -> {</span>
-<span class="source-line-no">1686</span><span id="line-1686"> while (bucketAllocator == null) {</span>
-<span class="source-line-no">1687</span><span id="line-1687"> try {</span>
-<span class="source-line-no">1688</span><span id="line-1688"> Thread.sleep(50);</span>
-<span class="source-line-no">1689</span><span id="line-1689"> } catch (InterruptedException ex) {</span>
-<span class="source-line-no">1690</span><span id="line-1690"> throw new RuntimeException(ex);</span>
-<span class="source-line-no">1691</span><span id="line-1691"> }</span>
-<span class="source-line-no">1692</span><span id="line-1692"> }</span>
-<span class="source-line-no">1693</span><span id="line-1693"> long startTime = EnvironmentEdgeManager.currentTime();</span>
-<span class="source-line-no">1694</span><span id="line-1694"> int totalKeysOriginally = backingMap.size();</span>
-<span class="source-line-no">1695</span><span id="line-1695"> for (Map.Entry<BlockCacheKey, BucketEntry> keyEntry : backingMap.entrySet()) {</span>
-<span class="source-line-no">1696</span><span id="line-1696"> try {</span>
-<span class="source-line-no">1697</span><span id="line-1697"> ((FileIOEngine) ioEngine).checkCacheTime(keyEntry.getValue());</span>
-<span class="source-line-no">1698</span><span id="line-1698"> } catch (IOException e1) {</span>
-<span class="source-line-no">1699</span><span id="line-1699"> LOG.debug("Check for key {} failed. Evicting.", keyEntry.getKey());</span>
-<span class="source-line-no">1700</span><span id="line-1700"> evictBlock(keyEntry.getKey());</span>
-<span class="source-line-no">1701</span><span id="line-1701"> fileNotFullyCached(keyEntry.getKey(), keyEntry.getValue());</span>
-<span class="source-line-no">1702</span><span id="line-1702"> }</span>
-<span class="source-line-no">1703</span><span id="line-1703"> }</span>
-<span class="source-line-no">1704</span><span id="line-1704"> backingMapValidated.set(true);</span>
-<span class="source-line-no">1705</span><span id="line-1705"> LOG.info("Finished validating {} keys in the backing map. Recovered: {}. This took {}ms.",</span>
-<span class="source-line-no">1706</span><span id="line-1706"> totalKeysOriginally, backingMap.size(),</span>
-<span class="source-line-no">1707</span><span id="line-1707"> (EnvironmentEdgeManager.currentTime() - startTime));</span>
-<span class="source-line-no">1708</span><span id="line-1708"> };</span>
-<span class="source-line-no">1709</span><span id="line-1709"> Thread t = new Thread(cacheValidator);</span>
-<span class="source-line-no">1710</span><span id="line-1710"> t.setDaemon(true);</span>
-<span class="source-line-no">1711</span><span id="line-1711"> t.start();</span>
-<span class="source-line-no">1712</span><span id="line-1712"> }</span>
-<span class="source-line-no">1713</span><span id="line-1713"> }</span>
-<span class="source-line-no">1714</span><span id="line-1714"></span>
-<span class="source-line-no">1715</span><span id="line-1715"> private void updateCacheIndex(BucketCacheProtos.BackingMap chunk,</span>
-<span class="source-line-no">1716</span><span id="line-1716"> java.util.Map<java.lang.Integer, java.lang.String> deserializer) throws IOException {</span>
-<span class="source-line-no">1717</span><span id="line-1717"> Pair<ConcurrentHashMap<BlockCacheKey, BucketEntry>, NavigableSet<BlockCacheKey>> pair2 =</span>
-<span class="source-line-no">1718</span><span id="line-1718"> BucketProtoUtils.fromPB(deserializer, chunk, this::createRecycler);</span>
-<span class="source-line-no">1719</span><span id="line-1719"> backingMap.putAll(pair2.getFirst());</span>
-<span class="source-line-no">1720</span><span id="line-1720"> blocksByHFile.addAll(pair2.getSecond());</span>
-<span class="source-line-no">1721</span><span id="line-1721"> }</span>
-<span class="source-line-no">1722</span><span id="line-1722"></span>
-<span class="source-line-no">1723</span><span id="line-1723"> private void parsePB(BucketCacheProtos.BucketCacheEntry proto) throws IOException {</span>
-<span class="source-line-no">1724</span><span id="line-1724"> Pair<ConcurrentHashMap<BlockCacheKey, BucketEntry>, NavigableSet<BlockCacheKey>> pair =</span>
-<span class="source-line-no">1725</span><span id="line-1725"> BucketProtoUtils.fromPB(proto.getDeserializersMap(), proto.getBackingMap(),</span>
-<span class="source-line-no">1726</span><span id="line-1726"> this::createRecycler);</span>
-<span class="source-line-no">1727</span><span id="line-1727"> backingMap = pair.getFirst();</span>
-<span class="source-line-no">1728</span><span id="line-1728"> blocksByHFile = pair.getSecond();</span>
-<span class="source-line-no">1729</span><span id="line-1729"> fullyCachedFiles.clear();</span>
-<span class="source-line-no">1730</span><span id="line-1730"> fullyCachedFiles.putAll(BucketProtoUtils.fromPB(proto.getCachedFilesMap()));</span>
-<span class="source-line-no">1731</span><span id="line-1731"></span>
-<span class="source-line-no">1732</span><span id="line-1732"> LOG.info("After retrieval Backing map size: {}, fullyCachedFiles size: {}", backingMap.size(),</span>
-<span class="source-line-no">1733</span><span id="line-1733"> fullyCachedFiles.size());</span>
-<span class="source-line-no">1734</span><span id="line-1734"></span>
-<span class="source-line-no">1735</span><span id="line-1735"> verifyFileIntegrity(proto);</span>
-<span class="source-line-no">1736</span><span id="line-1736"> updateRegionSizeMapWhileRetrievingFromFile();</span>
-<span class="source-line-no">1737</span><span id="line-1737"> verifyCapacityAndClasses(proto.getCacheCapacity(), proto.getIoClass(), proto.getMapClass());</span>
-<span class="source-line-no">1738</span><span id="line-1738"> }</span>
-<span class="source-line-no">1739</span><span id="line-1739"></span>
-<span class="source-line-no">1740</span><span id="line-1740"> private void persistChunkedBackingMap(FileOutputStream fos) throws IOException {</span>
-<span class="source-line-no">1741</span><span id="line-1741"> LOG.debug(</span>
-<span class="source-line-no">1742</span><span id="line-1742"> "persistToFile: before persisting backing map size: {}, "</span>
-<span class="source-line-no">1743</span><span id="line-1743"> + "fullycachedFiles size: {}, chunkSize: {}",</span>
-<span class="source-line-no">1744</span><span id="line-1744"> backingMap.size(), fullyCachedFiles.size(), persistenceChunkSize);</span>
-<span class="source-line-no">1745</span><span id="line-1745"></span>
-<span class="source-line-no">1746</span><span id="line-1746"> BucketProtoUtils.serializeAsPB(this, fos, persistenceChunkSize);</span>
-<span class="source-line-no">1747</span><span id="line-1747"></span>
+<span class="source-line-no">1657</span><span id="line-1657"> private void dumpPrefetchList() {</span>
+<span class="source-line-no">1658</span><span id="line-1658"> for (Map.Entry<String, Pair<String, Long>> outerEntry : fullyCachedFiles.entrySet()) {</span>
+<span class="source-line-no">1659</span><span id="line-1659"> LOG.debug("Cached File Entry:<{},<{},{}>>", outerEntry.getKey(),</span>
+<span class="source-line-no">1660</span><span id="line-1660"> outerEntry.getValue().getFirst(), outerEntry.getValue().getSecond());</span>
+<span class="source-line-no">1661</span><span id="line-1661"> }</span>
+<span class="source-line-no">1662</span><span id="line-1662"> }</span>
+<span class="source-line-no">1663</span><span id="line-1663"></span>
+<span class="source-line-no">1664</span><span id="line-1664"> private void verifyCapacityAndClasses(long capacitySize, String ioclass, String mapclass)</span>
+<span class="source-line-no">1665</span><span id="line-1665"> throws IOException {</span>
+<span class="source-line-no">1666</span><span id="line-1666"> if (capacitySize != cacheCapacity) {</span>
+<span class="source-line-no">1667</span><span id="line-1667"> throw new IOException("Mismatched cache capacity:" + StringUtils.byteDesc(capacitySize)</span>
+<span class="source-line-no">1668</span><span id="line-1668"> + ", expected: " + StringUtils.byteDesc(cacheCapacity));</span>
+<span class="source-line-no">1669</span><span id="line-1669"> }</span>
+<span class="source-line-no">1670</span><span id="line-1670"> if (!ioEngine.getClass().getName().equals(ioclass)) {</span>
+<span class="source-line-no">1671</span><span id="line-1671"> throw new IOException("Class name for IO engine mismatch: " + ioclass + ", expected:"</span>
+<span class="source-line-no">1672</span><span id="line-1672"> + ioEngine.getClass().getName());</span>
+<span class="source-line-no">1673</span><span id="line-1673"> }</span>
+<span class="source-line-no">1674</span><span id="line-1674"> if (!backingMap.getClass().getName().equals(mapclass)) {</span>
+<span class="source-line-no">1675</span><span id="line-1675"> throw new IOException("Class name for cache map mismatch: " + mapclass + ", expected:"</span>
+<span class="source-line-no">1676</span><span id="line-1676"> + backingMap.getClass().getName());</span>
+<span class="source-line-no">1677</span><span id="line-1677"> }</span>
+<span class="source-line-no">1678</span><span id="line-1678"> }</span>
+<span class="source-line-no">1679</span><span id="line-1679"></span>
+<span class="source-line-no">1680</span><span id="line-1680"> private void verifyFileIntegrity(BucketCacheProtos.BucketCacheEntry proto) {</span>
+<span class="source-line-no">1681</span><span id="line-1681"> try {</span>
+<span class="source-line-no">1682</span><span id="line-1682"> if (proto.hasChecksum()) {</span>
+<span class="source-line-no">1683</span><span id="line-1683"> ((PersistentIOEngine) ioEngine).verifyFileIntegrity(proto.getChecksum().toByteArray(),</span>
+<span class="source-line-no">1684</span><span id="line-1684"> algorithm);</span>
+<span class="source-line-no">1685</span><span id="line-1685"> }</span>
+<span class="source-line-no">1686</span><span id="line-1686"> backingMapValidated.set(true);</span>
+<span class="source-line-no">1687</span><span id="line-1687"> } catch (IOException e) {</span>
+<span class="source-line-no">1688</span><span id="line-1688"> LOG.warn("Checksum for cache file failed. "</span>
+<span class="source-line-no">1689</span><span id="line-1689"> + "We need to validate each cache key in the backing map. "</span>
+<span class="source-line-no">1690</span><span id="line-1690"> + "This may take some time, so we'll do it in a background thread,");</span>
+<span class="source-line-no">1691</span><span id="line-1691"></span>
+<span class="source-line-no">1692</span><span id="line-1692"> Runnable cacheValidator = () -> {</span>
+<span class="source-line-no">1693</span><span id="line-1693"> while (bucketAllocator == null) {</span>
+<span class="source-line-no">1694</span><span id="line-1694"> try {</span>
+<span class="source-line-no">1695</span><span id="line-1695"> Thread.sleep(50);</span>
+<span class="source-line-no">1696</span><span id="line-1696"> } catch (InterruptedException ex) {</span>
+<span class="source-line-no">1697</span><span id="line-1697"> throw new RuntimeException(ex);</span>
+<span class="source-line-no">1698</span><span id="line-1698"> }</span>
+<span class="source-line-no">1699</span><span id="line-1699"> }</span>
+<span class="source-line-no">1700</span><span id="line-1700"> long startTime = EnvironmentEdgeManager.currentTime();</span>
+<span class="source-line-no">1701</span><span id="line-1701"> int totalKeysOriginally = backingMap.size();</span>
+<span class="source-line-no">1702</span><span id="line-1702"> for (Map.Entry<BlockCacheKey, BucketEntry> keyEntry : backingMap.entrySet()) {</span>
+<span class="source-line-no">1703</span><span id="line-1703"> try {</span>
+<span class="source-line-no">1704</span><span id="line-1704"> ((FileIOEngine) ioEngine).checkCacheTime(keyEntry.getValue());</span>
+<span class="source-line-no">1705</span><span id="line-1705"> } catch (IOException e1) {</span>
+<span class="source-line-no">1706</span><span id="line-1706"> LOG.debug("Check for key {} failed. Evicting.", keyEntry.getKey());</span>
+<span class="source-line-no">1707</span><span id="line-1707"> evictBlock(keyEntry.getKey());</span>
+<span class="source-line-no">1708</span><span id="line-1708"> fileNotFullyCached(keyEntry.getKey(), keyEntry.getValue());</span>
+<span class="source-line-no">1709</span><span id="line-1709"> }</span>
+<span class="source-line-no">1710</span><span id="line-1710"> }</span>
+<span class="source-line-no">1711</span><span id="line-1711"> backingMapValidated.set(true);</span>
+<span class="source-line-no">1712</span><span id="line-1712"> LOG.info("Finished validating {} keys in the backing map. Recovered: {}. This took {}ms.",</span>
+<span class="source-line-no">1713</span><span id="line-1713"> totalKeysOriginally, backingMap.size(),</span>
+<span class="source-line-no">1714</span><span id="line-1714"> (EnvironmentEdgeManager.currentTime() - startTime));</span>
+<span class="source-line-no">1715</span><span id="line-1715"> };</span>
+<span class="source-line-no">1716</span><span id="line-1716"> Thread t = new Thread(cacheValidator);</span>
+<span class="source-line-no">1717</span><span id="line-1717"> t.setDaemon(true);</span>
+<span class="source-line-no">1718</span><span id="line-1718"> t.start();</span>
+<span class="source-line-no">1719</span><span id="line-1719"> }</span>
+<span class="source-line-no">1720</span><span id="line-1720"> }</span>
+<span class="source-line-no">1721</span><span id="line-1721"></span>
+<span class="source-line-no">1722</span><span id="line-1722"> private void updateCacheIndex(BucketCacheProtos.BackingMap chunk,</span>
+<span class="source-line-no">1723</span><span id="line-1723"> java.util.Map<java.lang.Integer, java.lang.String> deserializer) throws IOException {</span>
+<span class="source-line-no">1724</span><span id="line-1724"> Pair<ConcurrentHashMap<BlockCacheKey, BucketEntry>, NavigableSet<BlockCacheKey>> pair2 =</span>
+<span class="source-line-no">1725</span><span id="line-1725"> BucketProtoUtils.fromPB(deserializer, chunk, this::createRecycler);</span>
+<span class="source-line-no">1726</span><span id="line-1726"> backingMap.putAll(pair2.getFirst());</span>
+<span class="source-line-no">1727</span><span id="line-1727"> blocksByHFile.addAll(pair2.getSecond());</span>
+<span class="source-line-no">1728</span><span id="line-1728"> }</span>
+<span class="source-line-no">1729</span><span id="line-1729"></span>
+<span class="source-line-no">1730</span><span id="line-1730"> private void parsePB(BucketCacheProtos.BucketCacheEntry proto) throws IOException {</span>
+<span class="source-line-no">1731</span><span id="line-1731"> Pair<ConcurrentHashMap<BlockCacheKey, BucketEntry>, NavigableSet<BlockCacheKey>> pair =</span>
+<span class="source-line-no">1732</span><span id="line-1732"> BucketProtoUtils.fromPB(proto.getDeserializersMap(), proto.getBackingMap(),</span>
+<span class="source-line-no">1733</span><span id="line-1733"> this::createRecycler);</span>
+<span class="source-line-no">1734</span><span id="line-1734"> backingMap = pair.getFirst();</span>
+<span class="source-line-no">1735</span><span id="line-1735"> blocksByHFile = pair.getSecond();</span>
+<span class="source-line-no">1736</span><span id="line-1736"> fullyCachedFiles.clear();</span>
+<span class="source-line-no">1737</span><span id="line-1737"> fullyCachedFiles.putAll(BucketProtoUtils.fromPB(proto.getCachedFilesMap()));</span>
+<span class="source-line-no">1738</span><span id="line-1738"></span>
+<span class="source-line-no">1739</span><span id="line-1739"> LOG.info("After retrieval Backing map size: {}, fullyCachedFiles size: {}", backingMap.size(),</span>
+<span class="source-line-no">1740</span><span id="line-1740"> fullyCachedFiles.size());</span>
+<span class="source-line-no">1741</span><span id="line-1741"></span>
+<span class="source-line-no">1742</span><span id="line-1742"> verifyFileIntegrity(proto);</span>
+<span class="source-line-no">1743</span><span id="line-1743"> updateRegionSizeMapWhileRetrievingFromFile();</span>
+<span class="source-line-no">1744</span><span id="line-1744"> verifyCapacityAndClasses(proto.getCacheCapacity(), proto.getIoClass(), proto.getMapClass());</span>
+<span class="source-line-no">1745</span><span id="line-1745"> }</span>
+<span class="source-line-no">1746</span><span id="line-1746"></span>
+<span class="source-line-no">1747</span><span id="line-1747"> private void persistChunkedBackingMap(FileOutputStream fos) throws IOException {</span>
<span class="source-line-no">1748</span><span id="line-1748"> LOG.debug(</span>
-<span class="source-line-no">1749</span><span id="line-1749"> "persistToFile: after persisting backing map size: {}, " + "fullycachedFiles size: {}",</span>
-<span class="source-line-no">1750</span><span id="line-1750"> backingMap.size(), fullyCachedFiles.size());</span>
-<span class="source-line-no">1751</span><span id="line-1751"> }</span>
+<span class="source-line-no">1749</span><span id="line-1749"> "persistToFile: before persisting backing map size: {}, "</span>
+<span class="source-line-no">1750</span><span id="line-1750"> + "fullycachedFiles size: {}, chunkSize: {}",</span>
+<span class="source-line-no">1751</span><span id="line-1751"> backingMap.size(), fullyCachedFiles.size(), persistenceChunkSize);</span>
<span class="source-line-no">1752</span><span id="line-1752"></span>
-<span class="source-line-no">1753</span><span id="line-1753"> private void retrieveChunkedBackingMap(FileInputStream in) throws IOException {</span>
-<span class="source-line-no">1754</span><span id="line-1754"> // Read the first chunk that has all the details.</span>
-<span class="source-line-no">1755</span><span id="line-1755"> BucketCacheProtos.BucketCacheEntry cacheEntry =</span>
-<span class="source-line-no">1756</span><span id="line-1756"> BucketCacheProtos.BucketCacheEntry.parseDelimitedFrom(in);</span>
-<span class="source-line-no">1757</span><span id="line-1757"></span>
-<span class="source-line-no">1758</span><span id="line-1758"> fullyCachedFiles.clear();</span>
-<span class="source-line-no">1759</span><span id="line-1759"> fullyCachedFiles.putAll(BucketProtoUtils.fromPB(cacheEntry.getCachedFilesMap()));</span>
-<span class="source-line-no">1760</span><span id="line-1760"></span>
-<span class="source-line-no">1761</span><span id="line-1761"> backingMap.clear();</span>
-<span class="source-line-no">1762</span><span id="line-1762"> blocksByHFile.clear();</span>
-<span class="source-line-no">1763</span><span id="line-1763"></span>
-<span class="source-line-no">1764</span><span id="line-1764"> // Read the backing map entries in batches.</span>
-<span class="source-line-no">1765</span><span id="line-1765"> int numChunks = 0;</span>
-<span class="source-line-no">1766</span><span id="line-1766"> while (in.available() > 0) {</span>
-<span class="source-line-no">1767</span><span id="line-1767"> updateCacheIndex(BucketCacheProtos.BackingMap.parseDelimitedFrom(in),</span>
-<span class="source-line-no">1768</span><span id="line-1768"> cacheEntry.getDeserializersMap());</span>
-<span class="source-line-no">1769</span><span id="line-1769"> numChunks++;</span>
+<span class="source-line-no">1753</span><span id="line-1753"> BucketProtoUtils.serializeAsPB(this, fos, persistenceChunkSize);</span>
+<span class="source-line-no">1754</span><span id="line-1754"></span>
+<span class="source-line-no">1755</span><span id="line-1755"> LOG.debug(</span>
+<span class="source-line-no">1756</span><span id="line-1756"> "persistToFile: after persisting backing map size: {}, " + "fullycachedFiles size: {}",</span>
+<span class="source-line-no">1757</span><span id="line-1757"> backingMap.size(), fullyCachedFiles.size());</span>
+<span class="source-line-no">1758</span><span id="line-1758"> }</span>
+<span class="source-line-no">1759</span><span id="line-1759"></span>
+<span class="source-line-no">1760</span><span id="line-1760"> private void retrieveChunkedBackingMap(FileInputStream in) throws IOException {</span>
+<span class="source-line-no">1761</span><span id="line-1761"> // Read the first chunk that has all the details.</span>
+<span class="source-line-no">1762</span><span id="line-1762"> BucketCacheProtos.BucketCacheEntry cacheEntry =</span>
+<span class="source-line-no">1763</span><span id="line-1763"> BucketCacheProtos.BucketCacheEntry.parseDelimitedFrom(in);</span>
+<span class="source-line-no">1764</span><span id="line-1764"></span>
+<span class="source-line-no">1765</span><span id="line-1765"> // HBASE-29857: Handle case where persistence file is empty.</span>
+<span class="source-line-no">1766</span><span id="line-1766"> // parseDelimitedFrom() returns null when there's no data to read.</span>
+<span class="source-line-no">1767</span><span id="line-1767"> // Note: Corrupted files would throw InvalidProtocolBufferException (subclass of IOException).</span>
+<span class="source-line-no">1768</span><span id="line-1768"> if (cacheEntry == null) {</span>
+<span class="source-line-no">1769</span><span id="line-1769"> throw new IOException("Failed to read cache entry from persistence file (file is empty)");</span>
<span class="source-line-no">1770</span><span id="line-1770"> }</span>
<span class="source-line-no">1771</span><span id="line-1771"></span>
-<span class="source-line-no">1772</span><span id="line-1772"> LOG.info("Retrieved {} of chunks with blockCount = {}.", numChunks, backingMap.size());</span>
-<span class="source-line-no">1773</span><span id="line-1773"> verifyFileIntegrity(cacheEntry);</span>
-<span class="source-line-no">1774</span><span id="line-1774"> verifyCapacityAndClasses(cacheEntry.getCacheCapacity(), cacheEntry.getIoClass(),</span>
-<span class="source-line-no">1775</span><span id="line-1775"> cacheEntry.getMapClass());</span>
-<span class="source-line-no">1776</span><span id="line-1776"> updateRegionSizeMapWhileRetrievingFromFile();</span>
-<span class="source-line-no">1777</span><span id="line-1777"> }</span>
-<span class="source-line-no">1778</span><span id="line-1778"></span>
-<span class="source-line-no">1779</span><span id="line-1779"> /**</span>
-<span class="source-line-no">1780</span><span id="line-1780"> * Check whether we tolerate IO error this time. If the duration of IOEngine throwing errors</span>
-<span class="source-line-no">1781</span><span id="line-1781"> * exceeds ioErrorsDurationTimeTolerated, we will disable the cache</span>
-<span class="source-line-no">1782</span><span id="line-1782"> */</span>
-<span class="source-line-no">1783</span><span id="line-1783"> private void checkIOErrorIsTolerated() {</span>
-<span class="source-line-no">1784</span><span id="line-1784"> long now = EnvironmentEdgeManager.currentTime();</span>
-<span class="source-line-no">1785</span><span id="line-1785"> // Do a single read to a local variable to avoid timing issue - HBASE-24454</span>
-<span class="source-line-no">1786</span><span id="line-1786"> long ioErrorStartTimeTmp = this.ioErrorStartTime;</span>
-<span class="source-line-no">1787</span><span id="line-1787"> if (ioErrorStartTimeTmp > 0) {</span>
-<span class="source-line-no">1788</span><span id="line-1788"> if (isCacheEnabled() && (now - ioErrorStartTimeTmp) > this.ioErrorsTolerationDuration) {</span>
-<span class="source-line-no">1789</span><span id="line-1789"> LOG.error("IO errors duration time has exceeded " + ioErrorsTolerationDuration</span>
-<span class="source-line-no">1790</span><span id="line-1790"> + "ms, disabling cache, please check your IOEngine");</span>
-<span class="source-line-no">1791</span><span id="line-1791"> disableCache();</span>
-<span class="source-line-no">1792</span><span id="line-1792"> }</span>
-<span class="source-line-no">1793</span><span id="line-1793"> } else {</span>
-<span class="source-line-no">1794</span><span id="line-1794"> this.ioErrorStartTime = now;</span>
-<span class="source-line-no">1795</span><span id="line-1795"> }</span>
-<span class="source-line-no">1796</span><span id="line-1796"> }</span>
-<span class="source-line-no">1797</span><span id="line-1797"></span>
-<span class="source-line-no">1798</span><span id="line-1798"> /**</span>
-<span class="source-line-no">1799</span><span id="line-1799"> * Used to shut down the cache -or- turn it off in the case of something broken.</span>
-<span class="source-line-no">1800</span><span id="line-1800"> */</span>
-<span class="source-line-no">1801</span><span id="line-1801"> private void disableCache() {</span>
-<span class="source-line-no">1802</span><span id="line-1802"> if (!isCacheEnabled()) {</span>
-<span class="source-line-no">1803</span><span id="line-1803"> return;</span>
-<span class="source-line-no">1804</span><span id="line-1804"> }</span>
-<span class="source-line-no">1805</span><span id="line-1805"> LOG.info("Disabling cache");</span>
-<span class="source-line-no">1806</span><span id="line-1806"> cacheState = CacheState.DISABLED;</span>
-<span class="source-line-no">1807</span><span id="line-1807"> ioEngine.shutdown();</span>
-<span class="source-line-no">1808</span><span id="line-1808"> this.scheduleThreadPool.shutdown();</span>
-<span class="source-line-no">1809</span><span id="line-1809"> for (int i = 0; i < writerThreads.length; ++i)</span>
-<span class="source-line-no">1810</span><span id="line-1810"> writerThreads[i].interrupt();</span>
-<span class="source-line-no">1811</span><span id="line-1811"> this.ramCache.clear();</span>
-<span class="source-line-no">1812</span><span id="line-1812"> if (!ioEngine.isPersistent() || persistencePath == null) {</span>
-<span class="source-line-no">1813</span><span id="line-1813"> // If persistent ioengine and a path, we will serialize out the backingMap.</span>
-<span class="source-line-no">1814</span><span id="line-1814"> this.backingMap.clear();</span>
-<span class="source-line-no">1815</span><span id="line-1815"> this.blocksByHFile.clear();</span>
-<span class="source-line-no">1816</span><span id="line-1816"> this.fullyCachedFiles.clear();</span>
-<span class="source-line-no">1817</span><span id="line-1817"> this.regionCachedSize.clear();</span>
+<span class="source-line-no">1772</span><span id="line-1772"> fullyCachedFiles.clear();</span>
+<span class="source-line-no">1773</span><span id="line-1773"> fullyCachedFiles.putAll(BucketProtoUtils.fromPB(cacheEntry.getCachedFilesMap()));</span>
+<span class="source-line-no">1774</span><span id="line-1774"></span>
+<span class="source-line-no">1775</span><span id="line-1775"> backingMap.clear();</span>
+<span class="source-line-no">1776</span><span id="line-1776"> blocksByHFile.clear();</span>
+<span class="source-line-no">1777</span><span id="line-1777"></span>
+<span class="source-line-no">1778</span><span id="line-1778"> // Read the backing map entries in batches.</span>
+<span class="source-line-no">1779</span><span id="line-1779"> int numChunks = 0;</span>
+<span class="source-line-no">1780</span><span id="line-1780"> while (in.available() > 0) {</span>
+<span class="source-line-no">1781</span><span id="line-1781"> updateCacheIndex(BucketCacheProtos.BackingMap.parseDelimitedFrom(in),</span>
+<span class="source-line-no">1782</span><span id="line-1782"> cacheEntry.getDeserializersMap());</span>
+<span class="source-line-no">1783</span><span id="line-1783"> numChunks++;</span>
+<span class="source-line-no">1784</span><span id="line-1784"> }</span>
+<span class="source-line-no">1785</span><span id="line-1785"></span>
+<span class="source-line-no">1786</span><span id="line-1786"> LOG.info("Retrieved {} of chunks with blockCount = {}.", numChunks, backingMap.size());</span>
+<span class="source-line-no">1787</span><span id="line-1787"> verifyFileIntegrity(cacheEntry);</span>
+<span class="source-line-no">1788</span><span id="line-1788"> verifyCapacityAndClasses(cacheEntry.getCacheCapacity(), cacheEntry.getIoClass(),</span>
+<span class="source-line-no">1789</span><span id="line-1789"> cacheEntry.getMapClass());</span>
+<span class="source-line-no">1790</span><span id="line-1790"> updateRegionSizeMapWhileRetrievingFromFile();</span>
+<span class="source-line-no">1791</span><span id="line-1791"> }</span>
+<span class="source-line-no">1792</span><span id="line-1792"></span>
+<span class="source-line-no">1793</span><span id="line-1793"> /**</span>
+<span class="source-line-no">1794</span><span id="line-1794"> * Check whether we tolerate IO error this time. If the duration of IOEngine throwing errors</span>
+<span class="source-line-no">1795</span><span id="line-1795"> * exceeds ioErrorsDurationTimeTolerated, we will disable the cache</span>
+<span class="source-line-no">1796</span><span id="line-1796"> */</span>
+<span class="source-line-no">1797</span><span id="line-1797"> private void checkIOErrorIsTolerated() {</span>
+<span class="source-line-no">1798</span><span id="line-1798"> long now = EnvironmentEdgeManager.currentTime();</span>
+<span class="source-line-no">1799</span><span id="line-1799"> // Do a single read to a local variable to avoid timing issue - HBASE-24454</span>
+<span class="source-line-no">1800</span><span id="line-1800"> long ioErrorStartTimeTmp = this.ioErrorStartTime;</span>
+<span class="source-line-no">1801</span><span id="line-1801"> if (ioErrorStartTimeTmp > 0) {</span>
+<span class="source-line-no">1802</span><span id="line-1802"> if (isCacheEnabled() && (now - ioErrorStartTimeTmp) > this.ioErrorsTolerationDuration) {</span>
+<span class="source-line-no">1803</span><span id="line-1803"> LOG.error("IO errors duration time has exceeded " + ioErrorsTolerationDuration</span>
+<span class="source-line-no">1804</span><span id="line-1804"> + "ms, disabling cache, please check your IOEngine");</span>
+<span class="source-line-no">1805</span><span id="line-1805"> disableCache();</span>
+<span class="source-line-no">1806</span><span id="line-1806"> }</span>
+<span class="source-line-no">1807</span><span id="line-1807"> } else {</span>
+<span class="source-line-no">1808</span><span id="line-1808"> this.ioErrorStartTime = now;</span>
+<span class="source-line-no">1809</span><span id="line-1809"> }</span>
+<span class="source-line-no">1810</span><span id="line-1810"> }</span>
+<span class="source-line-no">1811</span><span id="line-1811"></span>
+<span class="source-line-no">1812</span><span id="line-1812"> /**</span>
+<span class="source-line-no">1813</span><span id="line-1813"> * Used to shut down the cache -or- turn it off in the case of something broken.</span>
+<span class="source-line-no">1814</span><span id="line-1814"> */</span>
+<span class="source-line-no">1815</span><span id="line-1815"> private void disableCache() {</span>
+<span class="source-line-no">1816</span><span id="line-1816"> if (!isCacheEnabled()) {</span>
+<span class="source-line-no">1817</span><span id="line-1817"> return;</span>
<span class="source-line-no">1818</span><span id="line-1818"> }</span>
-<span class="source-line-no">1819</span><span id="line-1819"> if (cacheStats.getMetricsRollerScheduler() != null) {</span>
-<span class="source-line-no">1820</span><span id="line-1820"> cacheStats.getMetricsRollerScheduler().shutdownNow();</span>
-<span class="source-line-no">1821</span><span id="line-1821"> }</span>
-<span class="source-line-no">1822</span><span id="line-1822"> }</span>
-<span class="source-line-no">1823</span><span id="line-1823"></span>
-<span class="source-line-no">1824</span><span id="line-1824"> private void join() throws InterruptedException {</span>
-<span class="source-line-no">1825</span><span id="line-1825"> for (int i = 0; i < writerThreads.length; ++i)</span>
-<span class="source-line-no">1826</span><span id="line-1826"> writerThreads[i].join();</span>
-<span class="source-line-no">1827</span><span id="line-1827"> }</span>
-<span class="source-line-no">1828</span><span id="line-1828"></span>
-<span class="source-line-no">1829</span><span id="line-1829"> @Override</span>
-<span class="source-line-no">1830</span><span id="line-1830"> public void shutdown() {</span>
-<span class="source-line-no">1831</span><span id="line-1831"> if (isCacheEnabled()) {</span>
-<span class="source-line-no">1832</span><span id="line-1832"> disableCache();</span>
-<span class="source-line-no">1833</span><span id="line-1833"> LOG.info("Shutdown bucket cache: IO persistent=" + ioEngine.isPersistent()</span>
-<span class="source-line-no">1834</span><span id="line-1834"> + "; path to write=" + persistencePath);</span>
-<span class="source-line-no">1835</span><span id="line-1835"> if (ioEngine.isPersistent() && persistencePath != null) {</span>
-<span class="source-line-no">1836</span><span id="line-1836"> try {</span>
-<span class="source-line-no">1837</span><span id="line-1837"> join();</span>
-<span class="source-line-no">1838</span><span id="line-1838"> if (cachePersister != null) {</span>
-<span class="source-line-no">1839</span><span id="line-1839"> LOG.info("Shutting down cache persister thread.");</span>
-<span class="source-line-no">1840</span><span id="line-1840"> cachePersister.shutdown();</span>
-<span class="source-line-no">1841</span><span id="line-1841"> while (cachePersister.isAlive()) {</span>
-<span class="source-line-no">1842</span><span id="line-1842"> Thread.sleep(10);</span>
-<span class="source-line-no">1843</span><span id="line-1843"> }</span>
-<span class="source-line-no">1844</span><span id="line-1844"> }</span>
-<span class="source-line-no">1845</span><span id="line-1845"> persistToFile();</span>
-<span class="source-line-no">1846</span><span id="line-1846"> } catch (IOException ex) {</span>
-<span class="source-line-no">1847</span><span id="line-1847"> LOG.error("Unable to persist data on exit: " + ex.toString(), ex);</span>
-<span class="source-line-no">1848</span><span id="line-1848"> } catch (InterruptedException e) {</span>
-<span class="source-line-no">1849</span><span id="line-1849"> LOG.warn("Failed to persist data on exit", e);</span>
-<span class="source-line-no">1850</span><span id="line-1850"> }</span>
-<span class="source-line-no">1851</span><span id="line-1851"> }</span>
-<span class="source-line-no">1852</span><span id="line-1852"> }</span>
-<span class="source-line-no">1853</span><span id="line-1853"> }</span>
-<span class="source-line-no">1854</span><span id="line-1854"></span>
-<span class="source-line-no">1855</span><span id="line-1855"> /**</span>
-<span class="source-line-no">1856</span><span id="line-1856"> * Needed mostly for UTs that might run in the same VM and create different BucketCache instances</span>
-<span class="source-line-no">1857</span><span id="line-1857"> * on different UT methods.</span>
-<span class="source-line-no">1858</span><span id="line-1858"> */</span>
-<span class="source-line-no">1859</span><span id="line-1859"> @Override</span>
-<span class="source-line-no">1860</span><span id="line-1860"> protected void finalize() {</span>
-<span class="source-line-no">1861</span><span id="line-1861"> if (cachePersister != null && !cachePersister.isInterrupted()) {</span>
-<span class="source-line-no">1862</span><span id="line-1862"> cachePersister.interrupt();</span>
-<span class="source-line-no">1863</span><span id="line-1863"> }</span>
-<span class="source-line-no">1864</span><span id="line-1864"> }</span>
-<span class="source-line-no">1865</span><span id="line-1865"></span>
-<span class="source-line-no">1866</span><span id="line-1866"> @Override</span>
-<span class="source-line-no">1867</span><span id="line-1867"> public CacheStats getStats() {</span>
-<span class="source-line-no">1868</span><span id="line-1868"> return cacheStats;</span>
-<span class="source-line-no">1869</span><span id="line-1869"> }</span>
-<span class="source-line-no">1870</span><span id="line-1870"></span>
-<span class="source-line-no">1871</span><span id="line-1871"> public BucketAllocator getAllocator() {</span>
-<span class="source-line-no">1872</span><span id="line-1872"> return this.bucketAllocator;</span>
-<span class="source-line-no">1873</span><span id="line-1873"> }</span>
-<span class="source-line-no">1874</span><span id="line-1874"></span>
-<span class="source-line-no">1875</span><span id="line-1875"> @Override</span>
-<span class="source-line-no">1876</span><span id="line-1876"> public long heapSize() {</span>
-<span class="source-line-no">1877</span><span id="line-1877"> return this.heapSize.sum();</span>
+<span class="source-line-no">1819</span><span id="line-1819"> LOG.info("Disabling cache");</span>
+<span class="source-line-no">1820</span><span id="line-1820"> cacheState = CacheState.DISABLED;</span>
+<span class="source-line-no">1821</span><span id="line-1821"> ioEngine.shutdown();</span>
+<span class="source-line-no">1822</span><span id="line-1822"> this.scheduleThreadPool.shutdown();</span>
+<span class="source-line-no">1823</span><span id="line-1823"> for (int i = 0; i < writerThreads.length; ++i)</span>
+<span class="source-line-no">1824</span><span id="line-1824"> writerThreads[i].interrupt();</span>
+<span class="source-line-no">1825</span><span id="line-1825"> this.ramCache.clear();</span>
+<span class="source-line-no">1826</span><span id="line-1826"> if (!ioEngine.isPersistent() || persistencePath == null) {</span>
+<span class="source-line-no">1827</span><span id="line-1827"> // If persistent ioengine and a path, we will serialize out the backingMap.</span>
+<span class="source-line-no">1828</span><span id="line-1828"> this.backingMap.clear();</span>
+<span class="source-line-no">1829</span><span id="line-1829"> this.blocksByHFile.clear();</span>
+<span class="source-line-no">1830</span><span id="line-1830"> this.fullyCachedFiles.clear();</span>
+<span class="source-line-no">1831</span><span id="line-1831"> this.regionCachedSize.clear();</span>
+<span class="source-line-no">1832</span><span id="line-1832"> }</span>
+<span class="source-line-no">1833</span><span id="line-1833"> if (cacheStats.getMetricsRollerScheduler() != null) {</span>
+<span class="source-line-no">1834</span><span id="line-1834"> cacheStats.getMetricsRollerScheduler().shutdownNow();</span>
+<span class="source-line-no">1835</span><span id="line-1835"> }</span>
+<span class="source-line-no">1836</span><span id="line-1836"> }</span>
+<span class="source-line-no">1837</span><span id="line-1837"></span>
+<span class="source-line-no">1838</span><span id="line-1838"> private void join() throws InterruptedException {</span>
+<span class="source-line-no">1839</span><span id="line-1839"> for (int i = 0; i < writerThreads.length; ++i)</span>
+<span class="source-line-no">1840</span><span id="line-1840"> writerThreads[i].join();</span>
+<span class="source-line-no">1841</span><span id="line-1841"> }</span>
+<span class="source-line-no">1842</span><span id="line-1842"></span>
+<span class="source-line-no">1843</span><span id="line-1843"> @Override</span>
+<span class="source-line-no">1844</span><span id="line-1844"> public void shutdown() {</span>
+<span class="source-line-no">1845</span><span id="line-1845"> if (isCacheEnabled()) {</span>
+<span class="source-line-no">1846</span><span id="line-1846"> disableCache();</span>
+<span class="source-line-no">1847</span><span id="line-1847"> LOG.info("Shutdown bucket cache: IO persistent=" + ioEngine.isPersistent()</span>
+<span class="source-line-no">1848</span><span id="line-1848"> + "; path to write=" + persistencePath);</span>
+<span class="source-line-no">1849</span><span id="line-1849"> if (ioEngine.isPersistent() && persistencePath != null) {</span>
+<span class="source-line-no">1850</span><span id="line-1850"> try {</span>
+<span class="source-line-no">1851</span><span id="line-1851"> join();</span>
+<span class="source-line-no">1852</span><span id="line-1852"> if (cachePersister != null) {</span>
+<span class="source-line-no">1853</span><span id="line-1853"> LOG.info("Shutting down cache persister thread.");</span>
+<span class="source-line-no">1854</span><span id="line-1854"> cachePersister.shutdown();</span>
+<span class="source-line-no">1855</span><span id="line-1855"> while (cachePersister.isAlive()) {</span>
+<span class="source-line-no">1856</span><span id="line-1856"> Thread.sleep(10);</span>
+<span class="source-line-no">1857</span><span id="line-1857"> }</span>
+<span class="source-line-no">1858</span><span id="line-1858"> }</span>
+<span class="source-line-no">1859</span><span id="line-1859"> persistToFile();</span>
+<span class="source-line-no">1860</span><span id="line-1860"> } catch (IOException ex) {</span>
+<span class="source-line-no">1861</span><span id="line-1861"> LOG.error("Unable to persist data on exit: " + ex.toString(), ex);</span>
+<span class="source-line-no">1862</span><span id="line-1862"> } catch (InterruptedException e) {</span>
+<span class="source-line-no">1863</span><span id="line-1863"> LOG.warn("Failed to persist data on exit", e);</span>
+<span class="source-line-no">1864</span><span id="line-1864"> }</span>
+<span class="source-line-no">1865</span><span id="line-1865"> }</span>
+<span class="source-line-no">1866</span><span id="line-1866"> }</span>
+<span class="source-line-no">1867</span><span id="line-1867"> }</span>
+<span class="source-line-no">1868</span><span id="line-1868"></span>
+<span class="source-line-no">1869</span><span id="line-1869"> /**</span>
+<span class="source-line-no">1870</span><span id="line-1870"> * Needed mostly for UTs that might run in the same VM and create different BucketCache instances</span>
+<span class="source-line-no">1871</span><span id="line-1871"> * on different UT methods.</span>
+<span class="source-line-no">1872</span><span id="line-1872"> */</span>
+<span class="source-line-no">1873</span><span id="line-1873"> @Override</span>
+<span class="source-line-no">1874</span><span id="line-1874"> protected void finalize() {</span>
+<span class="source-line-no">1875</span><span id="line-1875"> if (cachePersister != null && !cachePersister.isInterrupted()) {</span>
+<span class="source-line-no">1876</span><span id="line-1876"> cachePersister.interrupt();</span>
+<span class="source-line-no">1877</span><span id="line-1877"> }</span>
<span class="source-line-no">1878</span><span id="line-1878"> }</span>
<span class="source-line-no">1879</span><span id="line-1879"></span>
<span class="source-line-no">1880</span><span id="line-1880"> @Override</span>
-<span class="source-line-no">1881</span><span id="line-1881"> public long size() {</span>
-<span class="source-line-no">1882</span><span id="line-1882"> return this.realCacheSize.sum();</span>
+<span class="source-line-no">1881</span><span id="line-1881"> public CacheStats getStats() {</span>
+<span class="source-line-no">1882</span><span id="line-1882"> return cacheStats;</span>
<span class="source-line-no">1883</span><span id="line-1883"> }</span>
<span class="source-line-no">1884</span><span id="line-1884"></span>
-<span class="source-line-no">1885</span><span id="line-1885"> @Override</span>
-<span class="source-line-no">1886</span><span id="line-1886"> public long getCurrentDataSize() {</span>
-<span class="source-line-no">1887</span><span id="line-1887"> return size();</span>
-<span class="source-line-no">1888</span><span id="line-1888"> }</span>
-<span class="source-line-no">1889</span><span id="line-1889"></span>
-<span class="source-line-no">1890</span><span id="line-1890"> @Override</span>
-<span class="source-line-no">1891</span><span id="line-1891"> public long getFreeSize() {</span>
-<span class="source-line-no">1892</span><span id="line-1892"> if (!isCacheInitialized("BucketCache:getFreeSize")) {</span>
-<span class="source-line-no">1893</span><span id="line-1893"> return 0;</span>
-<span class="source-line-no">1894</span><span id="line-1894"> }</span>
-<span class="source-line-no">1895</span><span id="line-1895"> return this.bucketAllocator.getFreeSize();</span>
-<span class="source-line-no">1896</span><span id="line-1896"> }</span>
-<span class="source-line-no">1897</span><span id="line-1897"></span>
-<span class="source-line-no">1898</span><span id="line-1898"> @Override</span>
-<span class="source-line-no">1899</span><span id="line-1899"> public long getBlockCount() {</span>
-<span class="source-line-no">1900</span><span id="line-1900"> return this.blockNumber.sum();</span>
-<span class="source-line-no">1901</span><span id="line-1901"> }</span>
-<span class="source-line-no">1902</span><span id="line-1902"></span>
-<span class="source-line-no">1903</span><span id="line-1903"> @Override</span>
-<span class="source-line-no">1904</span><span id="line-1904"> public long getDataBlockCount() {</span>
-<span class="source-line-no">1905</span><span id="line-1905"> return getBlockCount();</span>
-<span class="source-line-no">1906</span><span id="line-1906"> }</span>
-<span class="source-line-no">1907</span><span id="line-1907"></span>
-<span class="source-line-no">1908</span><span id="line-1908"> @Override</span>
-<span class="source-line-no">1909</span><span id="line-1909"> public long getCurrentSize() {</span>
-<span class="source-line-no">1910</span><span id="line-1910"> if (!isCacheInitialized("BucketCache::getCurrentSize")) {</span>
-<span class="source-line-no">1911</span><span id="line-1911"> return 0;</span>
-<span class="source-line-no">1912</span><span id="line-1912"> }</span>
-<span class="source-line-no">1913</span><span id="line-1913"> return this.bucketAllocator.getUsedSize();</span>
-<span class="source-line-no">1914</span><span id="line-1914"> }</span>
-<span class="source-line-no">1915</span><span id="line-1915"></span>
-<span class="source-line-no">1916</span><span id="line-1916"> protected String getAlgorithm() {</span>
-<span class="source-line-no">1917</span><span id="line-1917"> return algorithm;</span>
-<span class="source-line-no">1918</span><span id="line-1918"> }</span>
-<span class="source-line-no">1919</span><span id="line-1919"></span>
-<span class="source-line-no">1920</span><span id="line-1920"> /**</span>
-<span class="source-line-no">1921</span><span id="line-1921"> * Evicts all blocks for a specific HFile.</span>
-<span class="source-line-no">1922</span><span id="line-1922"> * <p></span>
-<span class="source-line-no">1923</span><span id="line-1923"> * This is used for evict-on-close to remove all blocks of a specific HFile.</span>
-<span class="source-line-no">1924</span><span id="line-1924"> * @return the number of blocks evicted</span>
-<span class="source-line-no">1925</span><span id="line-1925"> */</span>
-<span class="source-line-no">1926</span><span id="line-1926"> @Override</span>
-<span class="source-line-no">1927</span><span id="line-1927"> public int evictBlocksByHfileName(String hfileName) {</span>
-<span class="source-line-no">1928</span><span id="line-1928"> return evictBlocksRangeByHfileName(hfileName, 0, Long.MAX_VALUE);</span>
-<span class="source-line-no">1929</span><span id="line-1929"> }</span>
-<span class="source-line-no">1930</span><span id="line-1930"></span>
-<span class="source-line-no">1931</span><span id="line-1931"> @Override</span>
-<span class="source-line-no">1932</span><span id="line-1932"> public int evictBlocksRangeByHfileName(String hfileName, long initOffset, long endOffset) {</span>
-<span class="source-line-no">1933</span><span id="line-1933"> Set<BlockCacheKey> keySet = getAllCacheKeysForFile(hfileName, initOffset, endOffset);</span>
-<span class="source-line-no">1934</span><span id="line-1934"> // We need to make sure whether we are evicting all blocks for this given file. In case of</span>
-<span class="source-line-no">1935</span><span id="line-1935"> // split references, we might be evicting just half of the blocks</span>
-<span class="source-line-no">1936</span><span id="line-1936"> LOG.debug("found {} blocks for file {}, starting offset: {}, end offset: {}", keySet.size(),</span>
-<span class="source-line-no">1937</span><span id="line-1937"> hfileName, initOffset, endOffset);</span>
-<span class="source-line-no">1938</span><span id="line-1938"> int numEvicted = 0;</span>
-<span class="source-line-no">1939</span><span id="line-1939"> for (BlockCacheKey key : keySet) {</span>
-<span class="source-line-no">1940</span><span id="line-1940"> if (evictBlock(key)) {</span>
-<span class="source-line-no">1941</span><span id="line-1941"> ++numEvicted;</span>
-<span class="source-line-no">1942</span><span id="line-1942"> }</span>
-<span class="source-line-no">1943</span><span id="line-1943"> }</span>
-<span class="source-line-no">1944</span><span id="line-1944"> return numEvicted;</span>
-<span class="source-line-no">1945</span><span id="line-1945"> }</span>
-<span class="source-line-no">1946</span><span id="line-1946"></span>
-<span class="source-line-no">1947</span><span id="line-1947"> private Set<BlockCacheKey> getAllCacheKeysForFile(String hfileName, long init, long end) {</span>
-<span class="source-line-no">1948</span><span id="line-1948"> // These keys are just for comparison and are short lived, so we need only file name and offset</span>
-<span class="source-line-no">1949</span><span id="line-1949"> return blocksByHFile.subSet(new BlockCacheKey(hfileName, init), true,</span>
-<span class="source-line-no">1950</span><span id="line-1950"> new BlockCacheKey(hfileName, end), true);</span>
-<span class="source-line-no">1951</span><span id="line-1951"> }</span>
-<span class="source-line-no">1952</span><span id="line-1952"></span>
-<span class="source-line-no">1953</span><span id="line-1953"> /**</span>
-<span class="source-line-no">1954</span><span id="line-1954"> * Used to group bucket entries into priority buckets. There will be a BucketEntryGroup for each</span>
-<span class="source-line-no">1955</span><span id="line-1955"> * priority (single, multi, memory). Once bucketed, the eviction algorithm takes the appropriate</span>
-<span class="source-line-no">1956</span><span id="line-1956"> * number of elements out of each according to configuration parameters and their relative sizes.</span>
-<span class="source-line-no">1957</span><span id="line-1957"> */</span>
-<span class="source-line-no">1958</span><span id="line-1958"> private class BucketEntryGroup {</span>
-<span class="source-line-no">1959</span><span id="line-1959"></span>
-<span class="source-line-no">1960</span><span id="line-1960"> private CachedEntryQueue queue;</span>
-<span class="source-line-no">1961</span><span id="line-1961"> private long totalSize = 0;</span>
-<span class="source-line-no">1962</span><span id="line-1962"> private long bucketSize;</span>
-<span class="source-line-no">1963</span><span id="line-1963"></span>
-<span class="source-line-no">1964</span><span id="line-1964"> public BucketEntryGroup(long bytesToFree, long blockSize, long bucketSize) {</span>
-<span class="source-line-no">1965</span><span id="line-1965"> this.bucketSize = bucketSize;</span>
-<span class="source-line-no">1966</span><span id="line-1966"> queue = new CachedEntryQueue(bytesToFree, blockSize);</span>
-<span class="source-line-no">1967</span><span id="line-1967"> totalSize = 0;</span>
-<span class="source-line-no">1968</span><span id="line-1968"> }</span>
-<span class="source-line-no">1969</span><span id="line-1969"></span>
-<span class="source-line-no">1970</span><span id="line-1970"> public void add(Map.Entry<BlockCacheKey, BucketEntry> block) {</span>
-<span class="source-line-no">1971</span><span id="line-1971"> totalSize += block.getValue().getLength();</span>
-<span class="source-line-no">1972</span><span id="line-1972"> queue.add(block);</span>
-<span class="source-line-no">1973</span><span id="line-1973"> }</span>
-<span class="source-line-no">1974</span><span id="line-1974"></span>
-<span class="source-line-no">1975</span><span id="line-1975"> public long free(long toFree) {</span>
-<span class="source-line-no">1976</span><span id="line-1976"> Map.Entry<BlockCacheKey, BucketEntry> entry;</span>
-<span class="source-line-no">1977</span><span id="line-1977"> long freedBytes = 0;</span>
-<span class="source-line-no">1978</span><span id="line-1978"> // TODO avoid a cycling siutation. We find no block which is not in use and so no way to free</span>
-<span class="source-line-no">1979</span><span id="line-1979"> // What to do then? Caching attempt fail? Need some changes in cacheBlock API?</span>
-<span class="source-line-no">1980</span><span id="line-1980"> while ((entry = queue.pollLast()) != null) {</span>
-<span class="source-line-no">1981</span><span id="line-1981"> BlockCacheKey blockCacheKey = entry.getKey();</span>
-<span class="source-line-no">1982</span><span id="line-1982"> BucketEntry be = entry.getValue();</span>
-<span class="source-line-no">1983</span><span id="line-1983"> if (evictBucketEntryIfNoRpcReferenced(blockCacheKey, be)) {</span>
-<span class="source-line-no">1984</span><span id="line-1984"> freedBytes += be.getLength();</span>
-<span class="source-line-no">1985</span><span id="line-1985"> }</span>
-<span class="source-line-no">1986</span><span id="line-1986"> if (freedBytes >= toFree) {</span>
-<span class="source-line-no">1987</span><span id="line-1987"> return freedBytes;</span>
-<span class="source-line-no">1988</span><span id="line-1988"> }</span>
-<span class="source-line-no">1989</span><span id="line-1989"> }</span>
-<span class="source-line-no">1990</span><span id="line-1990"> return freedBytes;</span>
-<span class="source-line-no">1991</span><span id="line-1991"> }</span>
-<span class="source-line-no">1992</span><span id="line-1992"></span>
-<span class="source-line-no">1993</span><span id="line-1993"> public long overflow() {</span>
-<span class="source-line-no">1994</span><span id="line-1994"> return totalSize - bucketSize;</span>
-<span class="source-line-no">1995</span><span id="line-1995"> }</span>
-<span class="source-line-no">1996</span><span id="line-1996"></span>
-<span class="source-line-no">1997</span><span id="line-1997"> public long totalSize() {</span>
-<span class="source-line-no">1998</span><span id="line-1998"> return totalSize;</span>
-<span class="source-line-no">1999</span><span id="line-1999"> }</span>
-<span class="source-line-no">2000</span><span id="line-2000"> }</span>
-<span class="source-line-no">2001</span><span id="line-2001"></span>
-<span class="source-line-no">2002</span><span id="line-2002"> /**</span>
-<span class="source-line-no">2003</span><span id="line-2003"> * Block Entry stored in the memory with key,data and so on</span>
-<span class="source-line-no">2004</span><span id="line-2004"> */</span>
-<span class="source-line-no">2005</span><span id="line-2005"> static class RAMQueueEntry {</span>
-<span class="source-line-no">2006</span><span id="line-2006"> private final BlockCacheKey key;</span>
-<span class="source-line-no">2007</span><span id="line-2007"> private final Cacheable data;</span>
-<span class="source-line-no">2008</span><span id="line-2008"> private long accessCounter;</span>
-<span class="source-line-no">2009</span><span id="line-2009"> private boolean inMemory;</span>
-<span class="source-line-no">2010</span><span id="line-2010"> private boolean isCachePersistent;</span>
-<span class="source-line-no">2011</span><span id="line-2011"></span>
-<span class="source-line-no">2012</span><span id="line-2012"> private boolean isPrefetch;</span>
-<span class="source-line-no">2013</span><span id="line-2013"></span>
-<span class="source-line-no">2014</span><span id="line-2014"> RAMQueueEntry(BlockCacheKey bck, Cacheable data, long accessCounter, boolean inMemory,</span>
-<span class="source-line-no">2015</span><span id="line-2015"> boolean isCachePersistent, boolean isPrefetch) {</span>
-<span class="source-line-no">2016</span><span id="line-2016"> this.key = bck;</span>
-<span class="source-line-no">2017</span><span id="line-2017"> this.data = data;</span>
-<span class="source-line-no">2018</span><span id="line-2018"> this.accessCounter = accessCounter;</span>
-<span class="source-line-no">2019</span><span id="line-2019"> this.inMemory = inMemory;</span>
-<span class="source-line-no">2020</span><span id="line-2020"> this.isCachePersistent = isCachePersistent;</span>
-<span class="source-line-no">2021</span><span id="line-2021"> this.isPrefetch = isPrefetch;</span>
-<span class="source-line-no">2022</span><span id="line-2022"> }</span>
-<span class="source-line-no">2023</span><span id="line-2023"></span>
-<span class="source-line-no">2024</span><span id="line-2024"> public Cacheable getData() {</span>
-<span class="source-line-no">2025</span><span id="line-2025"> return data;</span>
-<span class="source-line-no">2026</span><span id="line-2026"> }</span>
+<span class="source-line-no">1885</span><span id="line-1885"> public BucketAllocator getAllocator() {</span>
+<span class="source-line-no">1886</span><span id="line-1886"> return this.bucketAllocator;</span>
+<span class="source-line-no">1887</span><span id="line-1887"> }</span>
+<span class="source-line-no">1888</span><span id="line-1888"></span>
+<span class="source-line-no">1889</span><span id="line-1889"> @Override</span>
+<span class="source-line-no">1890</span><span id="line-1890"> public long heapSize() {</span>
+<span class="source-line-no">1891</span><span id="line-1891"> return this.heapSize.sum();</span>
+<span class="source-line-no">1892</span><span id="line-1892"> }</span>
+<span class="source-line-no">1893</span><span id="line-1893"></span>
+<span class="source-line-no">1894</span><span id="line-1894"> @Override</span>
+<span class="source-line-no">1895</span><span id="line-1895"> public long size() {</span>
+<span class="source-line-no">1896</span><span id="line-1896"> return this.realCacheSize.sum();</span>
+<span class="source-line-no">1897</span><span id="line-1897"> }</span>
+<span class="source-line-no">1898</span><span id="line-1898"></span>
+<span class="source-line-no">1899</span><span id="line-1899"> @Override</span>
+<span class="source-line-no">1900</span><span id="line-1900"> public long getCurrentDataSize() {</span>
+<span class="source-line-no">1901</span><span id="line-1901"> return size();</span>
+<span class="source-line-no">1902</span><span id="line-1902"> }</span>
+<span class="source-line-no">1903</span><span id="line-1903"></span>
+<span class="source-line-no">1904</span><span id="line-1904"> @Override</span>
+<span class="source-line-no">1905</span><span id="line-1905"> public long getFreeSize() {</span>
+<span class="source-line-no">1906</span><span id="line-1906"> if (!isCacheInitialized("BucketCache:getFreeSize")) {</span>
+<span class="source-line-no">1907</span><span id="line-1907"> return 0;</span>
+<span class="source-line-no">1908</span><span id="line-1908"> }</span>
+<span class="source-line-no">1909</span><span id="line-1909"> return this.bucketAllocator.getFreeSize();</span>
+<span class="source-line-no">1910</span><span id="line-1910"> }</span>
+<span class="source-line-no">1911</span><span id="line-1911"></span>
+<span class="source-line-no">1912</span><span id="line-1912"> @Override</span>
+<span class="source-line-no">1913</span><span id="line-1913"> public long getBlockCount() {</span>
+<span class="source-line-no">1914</span><span id="line-1914"> return this.blockNumber.sum();</span>
+<span class="source-line-no">1915</span><span id="line-1915"> }</span>
+<span class="source-line-no">1916</span><span id="line-1916"></span>
+<span class="source-line-no">1917</span><span id="line-1917"> @Override</span>
+<span class="source-line-no">1918</span><span id="line-1918"> public long getDataBlockCount() {</span>
+<span class="source-line-no">1919</span><span id="line-1919"> return getBlockCount();</span>
+<span class="source-line-no">1920</span><span id="line-1920"> }</span>
+<span class="source-line-no">1921</span><span id="line-1921"></span>
+<span class="source-line-no">1922</span><span id="line-1922"> @Override</span>
+<span class="source-line-no">1923</span><span id="line-1923"> public long getCurrentSize() {</span>
+<span class="source-line-no">1924</span><span id="line-1924"> if (!isCacheInitialized("BucketCache::getCurrentSize")) {</span>
+<span class="source-line-no">1925</span><span id="line-1925"> return 0;</span>
+<span class="source-line-no">1926</span><span id="line-1926"> }</span>
+<span class="source-line-no">1927</span><span id="line-1927"> return this.bucketAllocator.getUsedSize();</span>
+<span class="source-line-no">1928</span><span id="line-1928"> }</span>
+<span class="source-line-no">1929</span><span id="line-1929"></span>
+<span class="source-line-no">1930</span><span id="line-1930"> protected String getAlgorithm() {</span>
+<span class="source-line-no">1931</span><span id="line-1931"> return algorithm;</span>
+<span class="source-line-no">1932</span><span id="line-1932"> }</span>
+<span class="source-line-no">1933</span><span id="line-1933"></span>
+<span class="source-line-no">1934</span><span id="line-1934"> /**</span>
+<span class="source-line-no">1935</span><span id="line-1935"> * Evicts all blocks for a specific HFile.</span>
+<span class="source-line-no">1936</span><span id="line-1936"> * <p></span>
+<span class="source-line-no">1937</span><span id="line-1937"> * This is used for evict-on-close to remove all blocks of a specific HFile.</span>
+<span class="source-line-no">1938</span><span id="line-1938"> * @return the number of blocks evicted</span>
+<span class="source-line-no">1939</span><span id="line-1939"> */</span>
+<span class="source-line-no">1940</span><span id="line-1940"> @Override</span>
+<span class="source-line-no">1941</span><span id="line-1941"> public int evictBlocksByHfileName(String hfileName) {</span>
+<span class="source-line-no">1942</span><span id="line-1942"> return evictBlocksRangeByHfileName(hfileName, 0, Long.MAX_VALUE);</span>
+<span class="source-line-no">1943</span><span id="line-1943"> }</span>
+<span class="source-line-no">1944</span><span id="line-1944"></span>
+<span class="source-line-no">1945</span><span id="line-1945"> @Override</span>
+<span class="source-line-no">1946</span><span id="line-1946"> public int evictBlocksRangeByHfileName(String hfileName, long initOffset, long endOffset) {</span>
+<span class="source-line-no">1947</span><span id="line-1947"> Set<BlockCacheKey> keySet = getAllCacheKeysForFile(hfileName, initOffset, endOffset);</span>
+<span class="source-line-no">1948</span><span id="line-1948"> // We need to make sure whether we are evicting all blocks for this given file. In case of</span>
+<span class="source-line-no">1949</span><span id="line-1949"> // split references, we might be evicting just half of the blocks</span>
+<span class="source-line-no">1950</span><span id="line-1950"> LOG.debug("found {} blocks for file {}, starting offset: {}, end offset: {}", keySet.size(),</span>
+<span class="source-line-no">1951</span><span id="line-1951"> hfileName, initOffset, endOffset);</span>
+<span class="source-line-no">1952</span><span id="line-1952"> int numEvicted = 0;</span>
+<span class="source-line-no">1953</span><span id="line-1953"> for (BlockCacheKey key : keySet) {</span>
+<span class="source-line-no">1954</span><span id="line-1954"> if (evictBlock(key)) {</span>
+<span class="source-line-no">1955</span><span id="line-1955"> ++numEvicted;</span>
+<span class="source-line-no">1956</span><span id="line-1956"> }</span>
+<span class="source-line-no">1957</span><span id="line-1957"> }</span>
+<span class="source-line-no">1958</span><span id="line-1958"> return numEvicted;</span>
+<span class="source-line-no">1959</span><span id="line-1959"> }</span>
+<span class="source-line-no">1960</span><span id="line-1960"></span>
+<span class="source-line-no">1961</span><span id="line-1961"> private Set<BlockCacheKey> getAllCacheKeysForFile(String hfileName, long init, long end) {</span>
+<span class="source-line-no">1962</span><span id="line-1962"> // These keys are just for comparison and are short lived, so we need only file name and offset</span>
+<span class="source-line-no">1963</span><span id="line-1963"> return blocksByHFile.subSet(new BlockCacheKey(hfileName, init), true,</span>
+<span class="source-line-no">1964</span><span id="line-1964"> new BlockCacheKey(hfileName, end), true);</span>
+<span class="source-line-no">1965</span><span id="line-1965"> }</span>
+<span class="source-line-no">1966</span><span id="line-1966"></span>
+<span class="source-line-no">1967</span><span id="line-1967"> /**</span>
+<span class="source-line-no">1968</span><span id="line-1968"> * Used to group bucket entries into priority buckets. There will be a BucketEntryGroup for each</span>
+<span class="source-line-no">1969</span><span id="line-1969"> * priority (single, multi, memory). Once bucketed, the eviction algorithm takes the appropriate</span>
+<span class="source-line-no">1970</span><span id="line-1970"> * number of elements out of each according to configuration parameters and their relative sizes.</span>
+<span class="source-line-no">1971</span><span id="line-1971"> */</span>
+<span class="source-line-no">1972</span><span id="line-1972"> private class BucketEntryGroup {</span>
+<span class="source-line-no">1973</span><span id="line-1973"></span>
+<span class="source-line-no">1974</span><span id="line-1974"> private CachedEntryQueue queue;</span>
+<span class="source-line-no">1975</span><span id="line-1975"> private long totalSize = 0;</span>
+<span class="source-line-no">1976</span><span id="line-1976"> private long bucketSize;</span>
+<span class="source-line-no">1977</span><span id="line-1977"></span>
+<span class="source-line-no">1978</span><span id="line-1978"> public BucketEntryGroup(long bytesToFree, long blockSize, long bucketSize) {</span>
+<span class="source-line-no">1979</span><span id="line-1979"> this.bucketSize = bucketSize;</span>
+<span class="source-line-no">1980</span><span id="line-1980"> queue = new CachedEntryQueue(bytesToFree, blockSize);</span>
+<span class="source-line-no">1981</span><span id="line-1981"> totalSize = 0;</span>
+<span class="source-line-no">1982</span><span id="line-1982"> }</span>
+<span class="source-line-no">1983</span><span id="line-1983"></span>
+<span class="source-line-no">1984</span><span id="line-1984"> public void add(Map.Entry<BlockCacheKey, BucketEntry> block) {</span>
+<span class="source-line-no">1985</span><span id="line-1985"> totalSize += block.getValue().getLength();</span>
+<span class="source-line-no">1986</span><span id="line-1986"> queue.add(block);</span>
+<span class="source-line-no">1987</span><span id="line-1987"> }</span>
+<span class="source-line-no">1988</span><span id="line-1988"></span>
+<span class="source-line-no">1989</span><span id="line-1989"> public long free(long toFree) {</span>
+<span class="source-line-no">1990</span><span id="line-1990"> Map.Entry<BlockCacheKey, BucketEntry> entry;</span>
+<span class="source-line-no">1991</span><span id="line-1991"> long freedBytes = 0;</span>
+<span class="source-line-no">1992</span><span id="line-1992"> // TODO avoid a cycling siutation. We find no block which is not in use and so no way to free</span>
+<span class="source-line-no">1993</span><span id="line-1993"> // What to do then? Caching attempt fail? Need some changes in cacheBlock API?</span>
+<span class="source-line-no">1994</span><span id="line-1994"> while ((entry = queue.pollLast()) != null) {</span>
+<span class="source-line-no">1995</span><span id="line-1995"> BlockCacheKey blockCacheKey = entry.getKey();</span>
+<span class="source-line-no">1996</span><span id="line-1996"> BucketEntry be = entry.getValue();</span>
+<span class="source-line-no">1997</span><span id="line-1997"> if (evictBucketEntryIfNoRpcReferenced(blockCacheKey, be)) {</span>
+<span class="source-line-no">1998</span><span id="line-1998"> freedBytes += be.getLength();</span>
+<span class="source-line-no">1999</span><span id="line-1999"> }</span>
+<span class="source-line-no">2000</span><span id="line-2000"> if (freedBytes >= toFree) {</span>
+<span class="source-line-no">2001</span><span id="line-2001"> return freedBytes;</span>
+<span class="source-line-no">2002</span><span id="line-2002"> }</span>
+<span class="source-line-no">2003</span><span id="line-2003"> }</span>
+<span class="source-line-no">2004</span><span id="line-2004"> return freedBytes;</span>
+<span class="source-line-no">2005</span><span id="line-2005"> }</span>
+<span class="source-line-no">2006</span><span id="line-2006"></span>
+<span class="source-line-no">2007</span><span id="line-2007"> public long overflow() {</span>
+<span class="source-line-no">2008</span><span id="line-2008"> return totalSize - bucketSize;</span>
+<span class="source-line-no">2009</span><span id="line-2009"> }</span>
+<span class="source-line-no">2010</span><span id="line-2010"></span>
+<span class="source-line-no">2011</span><span id="line-2011"> public long totalSize() {</span>
+<span class="source-line-no">2012</span><span id="line-2012"> return totalSize;</span>
+<span class="source-line-no">2013</span><span id="line-2013"> }</span>
+<span class="source-line-no">2014</span><span id="line-2014"> }</span>
+<span class="source-line-no">2015</span><span id="line-2015"></span>
+<span class="source-line-no">2016</span><span id="line-2016"> /**</span>
+<span class="source-line-no">2017</span><span id="line-2017"> * Block Entry stored in the memory with key,data and so on</span>
+<span class="source-line-no">2018</span><span id="line-2018"> */</span>
+<span class="source-line-no">2019</span><span id="line-2019"> static class RAMQueueEntry {</span>
+<span class="source-line-no">2020</span><span id="line-2020"> private final BlockCacheKey key;</span>
+<span class="source-line-no">2021</span><span id="line-2021"> private final Cacheable data;</span>
+<span class="source-line-no">2022</span><span id="line-2022"> private long accessCounter;</span>
+<span class="source-line-no">2023</span><span id="line-2023"> private boolean inMemory;</span>
+<span class="source-line-no">2024</span><span id="line-2024"> private boolean isCachePersistent;</span>
+<span class="source-line-no">2025</span><span id="line-2025"></span>
+<span class="source-line-no">2026</span><span id="line-2026"> private boolean isPrefetch;</span>
<span class="source-line-no">2027</span><span id="line-2027"></span>
-<span class="source-line-no">2028</span><span id="line-2028"> public BlockCacheKey getKey() {</span>
-<span class="source-line-no">2029</span><span id="line-2029"> return key;</span>
-<span class="source-line-no">2030</span><span id="line-2030"> }</span>
-<span class="source-line-no">2031</span><span id="line-2031"></span>
-<span class="source-line-no">2032</span><span id="line-2032"> public boolean isPrefetch() {</span>
-<span class="source-line-no">2033</span><span id="line-2033"> return isPrefetch;</span>
-<span class="source-line-no">2034</span><span id="line-2034"> }</span>
-<span class="source-line-no">2035</span><span id="line-2035"></span>
-<span class="source-line-no">2036</span><span id="line-2036"> public void access(long accessCounter) {</span>
-<span class="source-line-no">2037</span><span id="line-2037"> this.accessCounter = accessCounter;</span>
-<span class="source-line-no">2038</span><span id="line-2038"> }</span>
-<span class="source-line-no">2039</span><span id="line-2039"></span>
-<span class="source-line-no">2040</span><span id="line-2040"> private ByteBuffAllocator getByteBuffAllocator() {</span>
-<span class="source-line-no">2041</span><span id="line-2041"> if (data instanceof HFileBlock) {</span>
-<span class="source-line-no">2042</span><span id="line-2042"> return ((HFileBlock) data).getByteBuffAllocator();</span>
-<span class="source-line-no">2043</span><span id="line-2043"> }</span>
-<span class="source-line-no">2044</span><span id="line-2044"> return ByteBuffAllocator.HEAP;</span>
-<span class="source-line-no">2045</span><span id="line-2045"> }</span>
-<span class="source-line-no">2046</span><span id="line-2046"></span>
-<span class="source-line-no">2047</span><span id="line-2047"> public BucketEntry writeToCache(final IOEngine ioEngine, final BucketAllocator alloc,</span>
-<span class="source-line-no">2048</span><span id="line-2048"> final LongAdder realCacheSize, Function<BucketEntry, Recycler> createRecycler,</span>
-<span class="source-line-no">2049</span><span id="line-2049"> ByteBuffer metaBuff, final Long acceptableSize) throws IOException {</span>
-<span class="source-line-no">2050</span><span id="line-2050"> int len = data.getSerializedLength();</span>
-<span class="source-line-no">2051</span><span id="line-2051"> // This cacheable thing can't be serialized</span>
-<span class="source-line-no">2052</span><span id="line-2052"> if (len == 0) {</span>
-<span class="source-line-no">2053</span><span id="line-2053"> return null;</span>
-<span class="source-line-no">2054</span><span id="line-2054"> }</span>
-<span class="source-line-no">2055</span><span id="line-2055"> if (isCachePersistent && data instanceof HFileBlock) {</span>
-<span class="source-line-no">2056</span><span id="line-2056"> len += Long.BYTES; // we need to record the cache time for consistency check in case of</span>
-<span class="source-line-no">2057</span><span id="line-2057"> // recovery</span>
-<span class="source-line-no">2058</span><span id="line-2058"> }</span>
-<span class="source-line-no">2059</span><span id="line-2059"> long offset = alloc.allocateBlock(len);</span>
-<span class="source-line-no">2060</span><span id="line-2060"> // In the case of prefetch, we want to avoid freeSpace runs when the cache is full.</span>
-<span class="source-line-no">2061</span><span id="line-2061"> // this makes the cache allocation more predictable, and is particularly important</span>
-<span class="source-line-no">2062</span><span id="line-2062"> // when persistent cache is enabled, as it won't trigger evictions of the recovered blocks,</span>
-<span class="source-line-no">2063</span><span id="line-2063"> // which are likely the most accessed and relevant blocks in the cache.</span>
-<span class="source-line-no">2064</span><span id="line-2064"> if (isPrefetch() && alloc.getUsedSize() > acceptableSize) {</span>
-<span class="source-line-no">2065</span><span id="line-2065"> alloc.freeBlock(offset, len);</span>
-<span class="source-line-no">2066</span><span id="line-2066"> return null;</span>
-<span class="source-line-no">2067</span><span id="line-2067"> }</span>
-<span class="source-line-no">2068</span><span id="line-2068"> boolean succ = false;</span>
-<span class="source-line-no">2069</span><span id="line-2069"> BucketEntry bucketEntry = null;</span>
-<span class="source-line-no">2070</span><span id="line-2070"> try {</span>
-<span class="source-line-no">2071</span><span id="line-2071"> int diskSizeWithHeader = (data instanceof HFileBlock)</span>
-<span class="source-line-no">2072</span><span id="line-2072"> ? ((HFileBlock) data).getOnDiskSizeWithHeader()</span>
-<span class="source-line-no">2073</span><span id="line-2073"> : data.getSerializedLength();</span>
-<span class="source-line-no">2074</span><span id="line-2074"> bucketEntry = new BucketEntry(offset, len, diskSizeWithHeader, accessCounter, inMemory,</span>
-<span class="source-line-no">2075</span><span id="line-2075"> createRecycler, getByteBuffAllocator());</span>
-<span class="source-line-no">2076</span><span id="line-2076"> bucketEntry.setDeserializerReference(data.getDeserializer());</span>
-<span class="source-line-no">2077</span><span id="line-2077"> if (data instanceof HFileBlock) {</span>
-<span class="source-line-no">2078</span><span id="line-2078"> // If an instance of HFileBlock, save on some allocations.</span>
-<span class="source-line-no">2079</span><span id="line-2079"> HFileBlock block = (HFileBlock) data;</span>
-<span class="source-line-no">2080</span><span id="line-2080"> ByteBuff sliceBuf = block.getBufferReadOnly();</span>
-<span class="source-line-no">2081</span><span id="line-2081"> block.getMetaData(metaBuff);</span>
-<span class="source-line-no">2082</span><span id="line-2082"> // adds the cache time prior to the block and metadata part</span>
-<span class="source-line-no">2083</span><span id="line-2083"> if (isCachePersistent) {</span>
-<span class="source-line-no">2084</span><span id="line-2084"> ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);</span>
-<span class="source-line-no">2085</span><span id="line-2085"> buffer.putLong(bucketEntry.getCachedTime());</span>
-<span class="source-line-no">2086</span><span id="line-2086"> buffer.rewind();</span>
-<span class="source-line-no">2087</span><span id="line-2087"> ioEngine.write(buffer, offset);</span>
-<span class="source-line-no">2088</span><span id="line-2088"> ioEngine.write(sliceBuf, (offset + Long.BYTES));</span>
-<span class="source-line-no">2089</span><span id="line-2089"> } else {</span>
-<span class="source-line-no">2090</span><span id="line-2090"> ioEngine.write(sliceBuf, offset);</span>
-<span class="source-line-no">2091</span><span id="line-2091"> }</span>
-<span class="source-line-no">2092</span><span id="line-2092"> ioEngine.write(metaBuff, offset + len - metaBuff.limit());</span>
-<span class="source-line-no">2093</span><span id="line-2093"> } else {</span>
-<span class="source-line-no">2094</span><span id="line-2094"> // Only used for testing.</span>
-<span class="source-line-no">2095</span><span id="line-2095"> ByteBuffer bb = ByteBuffer.allocate(len);</span>
-<span class="source-line-no">2096</span><span id="line-2096"> data.serialize(bb, true);</span>
-<span class="source-line-no">2097</span><span id="line-2097"> ioEngine.write(bb, offset);</span>
-<span class="source-line-no">2098</span><span id="line-2098"> }</span>
-<span class="source-line-no">2099</span><span id="line-2099"> succ = true;</span>
-<span class="source-line-no">2100</span><span id="line-2100"> } finally {</span>
-<span class="source-line-no">2101</span><span id="line-2101"> if (!succ) {</span>
-<span class="source-line-no">2102</span><span id="line-2102"> alloc.freeBlock(offset, len);</span>
-<span class="source-line-no">2103</span><span id="line-2103"> }</span>
-<span class="source-line-no">2104</span><span id="line-2104"> }</span>
-<span class="source-line-no">2105</span><span id="line-2105"> realCacheSize.add(len);</span>
-<span class="source-line-no">2106</span><span id="line-2106"> return bucketEntry;</span>
-<span class="source-line-no">2107</span><span id="line-2107"> }</span>
-<span class="source-line-no">2108</span><span id="line-2108"> }</span>
-<span class="source-line-no">2109</span><span id="line-2109"></span>
-<span class="source-line-no">2110</span><span id="line-2110"> /**</span>
-<span class="source-line-no">2111</span><span id="line-2111"> * Only used in test</span>
-<span class="source-line-no">2112</span><span id="line-2112"> */</span>
-<span class="source-line-no">2113</span><span id="line-2113"> void stopWriterThreads() throws InterruptedException {</span>
-<span class="source-line-no">2114</span><span id="line-2114"> for (WriterThread writerThread : writerThreads) {</span>
-<span class="source-line-no">2115</span><span id="line-2115"> writerThread.disableWriter();</span>
-<span class="source-line-no">2116</span><span id="line-2116"> writerThread.interrupt();</span>
-<span class="source-line-no">2117</span><span id="line-2117"> writerThread.join();</span>
-<span class="source-line-no">2118</span><span id="line-2118"> }</span>
-<span class="source-line-no">2119</span><span id="line-2119"> }</span>
-<span class="source-line-no">2120</span><span id="line-2120"></span>
-<span class="source-line-no">2121</span><span id="line-2121"> @Override</span>
-<span class="source-line-no">2122</span><span id="line-2122"> public Iterator<CachedBlock> iterator() {</span>
-<span class="source-line-no">2123</span><span id="line-2123"> // Don't bother with ramcache since stuff is in here only a little while.</span>
-<span class="source-line-no">2124</span><span id="line-2124"> final Iterator<Map.Entry<BlockCacheKey, BucketEntry>> i = this.backingMap.entrySet().iterator();</span>
-<span class="source-line-no">2125</span><span id="line-2125"> return new Iterator<CachedBlock>() {</span>
-<span class="source-line-no">2126</span><span id="line-2126"> private final long now = System.nanoTime();</span>
-<span class="source-line-no">2127</span><span id="line-2127"></span>
-<span class="source-line-no">2128</span><span id="line-2128"> @Override</span>
-<span class="source-line-no">2129</span><span id="line-2129"> public boolean hasNext() {</span>
-<span class="source-line-no">2130</span><span id="line-2130"> return i.hasNext();</span>
-<span class="source-line-no">2131</span><span id="line-2131"> }</span>
-<span class="source-line-no">2132</span><span id="line-2132"></span>
-<span class="source-line-no">2133</span><span id="line-2133"> @Override</span>
-<span class="source-line-no">2134</span><span id="line-2134"> public CachedBlock next() {</span>
-<span class="source-line-no">2135</span><span id="line-2135"> final Map.Entry<BlockCacheKey, BucketEntry> e = i.next();</span>
-<span class="source-line-no">2136</span><span id="line-2136"> return new CachedBlock() {</span>
-<span class="source-line-no">2137</span><span id="line-2137"> @Override</span>
-<span class="source-line-no">2138</span><span id="line-2138"> public String toString() {</span>
-<span class="source-line-no">2139</span><span id="line-2139"> return BlockCacheUtil.toString(this, now);</span>
-<span class="source-line-no">2140</span><span id="line-2140"> }</span>
+<span class="source-line-no">2028</span><span id="line-2028"> RAMQueueEntry(BlockCacheKey bck, Cacheable data, long accessCounter, boolean inMemory,</span>
+<span class="source-line-no">2029</span><span id="line-2029"> boolean isCachePersistent, boolean isPrefetch) {</span>
+<span class="source-line-no">2030</span><span id="line-2030"> this.key = bck;</span>
+<span class="source-line-no">2031</span><span id="line-2031"> this.data = data;</span>
+<span class="source-line-no">2032</span><span id="line-2032"> this.accessCounter = accessCounter;</span>
+<span class="source-line-no">2033</span><span id="line-2033"> this.inMemory = inMemory;</span>
+<span class="source-line-no">2034</span><span id="line-2034"> this.isCachePersistent = isCachePersistent;</span>
+<span class="source-line-no">2035</span><span id="line-2035"> this.isPrefetch = isPrefetch;</span>
+<span class="source-line-no">2036</span><span id="line-2036"> }</span>
+<span class="source-line-no">2037</span><span id="line-2037"></span>
+<span class="source-line-no">2038</span><span id="line-2038"> public Cacheable getData() {</span>
+<span class="source-line-no">2039</span><span id="line-2039"> return data;</span>
+<span class="source-line-no">2040</span><span id="line-2040"> }</span>
+<span class="source-line-no">2041</span><span id="line-2041"></span>
+<span class="source-line-no">2042</span><span id="line-2042"> public BlockCacheKey getKey() {</span>
+<span class="source-line-no">2043</span><span id="line-2043"> return key;</span>
+<span class="source-line-no">2044</span><span id="line-2044"> }</span>
+<span class="source-line-no">2045</span><span id="line-2045"></span>
+<span class="source-line-no">2046</span><span id="line-2046"> public boolean isPrefetch() {</span>
+<span class="source-line-no">2047</span><span id="line-2047"> return isPrefetch;</span>
+<span class="source-line-no">2048</span><span id="line-2048"> }</span>
+<span class="source-line-no">2049</span><span id="line-2049"></span>
+<span class="source-line-no">2050</span><span id="line-2050"> public void access(long accessCounter) {</span>
+<span class="source-line-no">2051</span><span id="line-2051"> this.accessCounter = accessCounter;</span>
+<span class="source-line-no">2052</span><span id="line-2052"> }</span>
+<span class="source-line-no">2053</span><span id="line-2053"></span>
+<span class="source-line-no">2054</span><span id="line-2054"> private ByteBuffAllocator getByteBuffAllocator() {</span>
+<span class="source-line-no">2055</span><span id="line-2055"> if (data instanceof HFileBlock) {</span>
+<span class="source-line-no">2056</span><span id="line-2056"> return ((HFileBlock) data).getByteBuffAllocator();</span>
+<span class="source-line-no">2057</span><span id="line-2057"> }</span>
+<span class="source-line-no">2058</span><span id="line-2058"> return ByteBuffAllocator.HEAP;</span>
+<span class="source-line-no">2059</span><span id="line-2059"> }</span>
+<span class="source-line-no">2060</span><span id="line-2060"></span>
+<span class="source-line-no">2061</span><span id="line-2061"> public BucketEntry writeToCache(final IOEngine ioEngine, final BucketAllocator alloc,</span>
+<span class="source-line-no">2062</span><span id="line-2062"> final LongAdder realCacheSize, Function<BucketEntry, Recycler> createRecycler,</span>
+<span class="source-line-no">2063</span><span id="line-2063"> ByteBuffer metaBuff, final Long acceptableSize) throws IOException {</span>
+<span class="source-line-no">2064</span><span id="line-2064"> int len = data.getSerializedLength();</span>
+<span class="source-line-no">2065</span><span id="line-2065"> // This cacheable thing can't be serialized</span>
+<span class="source-line-no">2066</span><span id="line-2066"> if (len == 0) {</span>
+<span class="source-line-no">2067</span><span id="line-2067"> return null;</span>
+<span class="source-line-no">2068</span><span id="line-2068"> }</span>
+<span class="source-line-no">2069</span><span id="line-2069"> if (isCachePersistent && data instanceof HFileBlock) {</span>
+<span class="source-line-no">2070</span><span id="line-2070"> len += Long.BYTES; // we need to record the cache time for consistency check in case of</span>
+<span class="source-line-no">2071</span><span id="line-2071"> // recovery</span>
+<span class="source-line-no">2072</span><span id="line-2072"> }</span>
+<span class="source-line-no">2073</span><span id="line-2073"> long offset = alloc.allocateBlock(len);</span>
+<span class="source-line-no">2074</span><span id="line-2074"> // In the case of prefetch, we want to avoid freeSpace runs when the cache is full.</span>
+<span class="source-line-no">2075</span><span id="line-2075"> // this makes the cache allocation more predictable, and is particularly important</span>
+<span class="source-line-no">2076</span><span id="line-2076"> // when persistent cache is enabled, as it won't trigger evictions of the recovered blocks,</span>
+<span class="source-line-no">2077</span><span id="line-2077"> // which are likely the most accessed and relevant blocks in the cache.</span>
+<span class="source-line-no">2078</span><span id="line-2078"> if (isPrefetch() && alloc.getUsedSize() > acceptableSize) {</span>
+<span class="source-line-no">2079</span><span id="line-2079"> alloc.freeBlock(offset, len);</span>
+<span class="source-line-no">2080</span><span id="line-2080"> return null;</span>
+<span class="source-line-no">2081</span><span id="line-2081"> }</span>
+<span class="source-line-no">2082</span><span id="line-2082"> boolean succ = false;</span>
+<span class="source-line-no">2083</span><span id="line-2083"> BucketEntry bucketEntry = null;</span>
+<span class="source-line-no">2084</span><span id="line-2084"> try {</span>
+<span class="source-line-no">2085</span><span id="line-2085"> int diskSizeWithHeader = (data instanceof HFileBlock)</span>
+<span class="source-line-no">2086</span><span id="line-2086"> ? ((HFileBlock) data).getOnDiskSizeWithHeader()</span>
+<span class="source-line-no">2087</span><span id="line-2087"> : data.getSerializedLength();</span>
+<span class="source-line-no">2088</span><span id="line-2088"> bucketEntry = new BucketEntry(offset, len, diskSizeWithHeader, accessCounter, inMemory,</span>
+<span class="source-line-no">2089</span><span id="line-2089"> createRecycler, getByteBuffAllocator());</span>
+<span class="source-line-no">2090</span><span id="line-2090"> bucketEntry.setDeserializerReference(data.getDeserializer());</span>
+<span class="source-line-no">2091</span><span id="line-2091"> if (data instanceof HFileBlock) {</span>
+<span class="source-line-no">2092</span><span id="line-2092"> // If an instance of HFileBlock, save on some allocations.</span>
+<span class="source-line-no">2093</span><span id="line-2093"> HFileBlock block = (HFileBlock) data;</span>
+<span class="source-line-no">2094</span><span id="line-2094"> ByteBuff sliceBuf = block.getBufferReadOnly();</span>
+<span class="source-line-no">2095</span><span id="line-2095"> block.getMetaData(metaBuff);</span>
+<span class="source-line-no">2096</span><span id="line-2096"> // adds the cache time prior to the block and metadata part</span>
+<span class="source-line-no">2097</span><span id="line-2097"> if (isCachePersistent) {</span>
+<span class="source-line-no">2098</span><span id="line-2098"> ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);</span>
+<span class="source-line-no">2099</span><span id="line-2099"> buffer.putLong(bucketEntry.getCachedTime());</span>
+<span class="source-line-no">2100</span><span id="line-2100"> buffer.rewind();</span>
+<span class="source-line-no">2101</span><span id="line-2101"> ioEngine.write(buffer, offset);</span>
+<span class="source-line-no">2102</span><span id="line-2102"> ioEngine.write(sliceBuf, (offset + Long.BYTES));</span>
+<span class="source-line-no">2103</span><span id="line-2103"> } else {</span>
+<span class="source-line-no">2104</span><span id="line-2104"> ioEngine.write(sliceBuf, offset);</span>
+<span class="source-line-no">2105</span><span id="line-2105"> }</span>
+<span class="source-line-no">2106</span><span id="line-2106"> ioEngine.write(metaBuff, offset + len - metaBuff.limit());</span>
+<span class="source-line-no">2107</span><span id="line-2107"> } else {</span>
+<span class="source-line-no">2108</span><span id="line-2108"> // Only used for testing.</span>
+<span class="source-line-no">2109</span><span id="line-2109"> ByteBuffer bb = ByteBuffer.allocate(len);</span>
+<span class="source-line-no">2110</span><span id="line-2110"> data.serialize(bb, true);</span>
+<span class="source-line-no">2111</span><span id="line-2111"> ioEngine.write(bb, offset);</span>
+<span class="source-line-no">2112</span><span id="line-2112"> }</span>
+<span class="source-line-no">2113</span><span id="line-2113"> succ = true;</span>
+<span class="source-line-no">2114</span><span id="line-2114"> } finally {</span>
+<span class="source-line-no">2115</span><span id="line-2115"> if (!succ) {</span>
+<span class="source-line-no">2116</span><span id="line-2116"> alloc.freeBlock(offset, len);</span>
+<span class="source-line-no">2117</span><span id="line-2117"> }</span>
+<span class="source-line-no">2118</span><span id="line-2118"> }</span>
+<span class="source-line-no">2119</span><span id="line-2119"> realCacheSize.add(len);</span>
+<span class="source-line-no">2120</span><span id="line-2120"> return bucketEntry;</span>
+<span class="source-line-no">2121</span><span id="line-2121"> }</span>
+<span class="source-line-no">2122</span><span id="line-2122"> }</span>
+<span class="source-line-no">2123</span><span id="line-2123"></span>
+<span class="source-line-no">2124</span><span id="line-2124"> /**</span>
+<span class="source-line-no">2125</span><span id="line-2125"> * Only used in test</span>
+<span class="source-line-no">2126</span><span id="line-2126"> */</span>
+<span class="source-line-no">2127</span><span id="line-2127"> void stopWriterThreads() throws InterruptedException {</span>
+<span class="source-line-no">2128</span><span id="line-2128"> for (WriterThread writerThread : writerThreads) {</span>
+<span class="source-line-no">2129</span><span id="line-2129"> writerThread.disableWriter();</span>
+<span class="source-line-no">2130</span><span id="line-2130"> writerThread.interrupt();</span>
+<span class="source-line-no">2131</span><span id="line-2131"> writerThread.join();</span>
+<span class="source-line-no">2132</span><span id="line-2132"> }</span>
+<span class="source-line-no">2133</span><span id="line-2133"> }</span>
+<span class="source-line-no">2134</span><span id="line-2134"></span>
+<span class="source-line-no">2135</span><span id="line-2135"> @Override</span>
+<span class="source-line-no">2136</span><span id="line-2136"> public Iterator<CachedBlock> iterator() {</span>
+<span class="source-line-no">2137</span><span id="line-2137"> // Don't bother with ramcache since stuff is in here only a little while.</span>
+<span class="source-line-no">2138</span><span id="line-2138"> final Iterator<Map.Entry<BlockCacheKey, BucketEntry>> i = this.backingMap.entrySet().iterator();</span>
+<span class="source-line-no">2139</span><span id="line-2139"> return new Iterator<CachedBlock>() {</span>
+<span class="source-line-no">2140</span><span id="line-2140"> private final long now = System.nanoTime();</span>
<span class="source-line-no">2141</span><span id="line-2141"></span>
-<span class="source-line-no">2142</span><span id="line-2142"> @Override</span>
-<span class="source-line-no">2143</span><span id="line-2143"> public BlockPriority getBlockPriority() {</span>
-<span class="source-line-no">2144</span><span id="line-2144"> return e.getValue().getPriority();</span>
-<span class="source-line-no">2145</span><span id="line-2145"> }</span>
+<span class="source-line-no">2142</span><span id="line-2142"> @Override</span>
+<span class="source-line-no">2143</span><span id="line-2143"> public boolean hasNext() {</span>
+<span class="source-line-no">2144</span><span id="line-2144"> return i.hasNext();</span>
+<span class="source-line-no">2145</span><span id="line-2145"> }</span>
<span class="source-line-no">2146</span><span id="line-2146"></span>
-<span class="source-line-no">2147</span><span id="line-2147"> @Override</span>
-<span class="source-line-no">2148</span><span id="line-2148"> public BlockType getBlockType() {</span>
-<span class="source-line-no">2149</span><span id="line-2149"> // Not held by BucketEntry. Could add it if wanted on BucketEntry creation.</span>
-<span class="source-line-no">2150</span><span id="line-2150"> return null;</span>
-<span class="source-line-no">2151</span><span id="line-2151"> }</span>
-<span class="source-line-no">2152</span><span id="line-2152"></span>
-<span class="source-line-no">2153</span><span id="line-2153"> @Override</span>
-<span class="source-line-no">2154</span><span id="line-2154"> public long getOffset() {</span>
-<span class="source-line-no">2155</span><span id="line-2155"> return e.getKey().getOffset();</span>
-<span class="source-line-no">2156</span><span id="line-2156"> }</span>
-<span class="source-line-no">2157</span><span id="line-2157"></span>
-<span class="source-line-no">2158</span><span id="line-2158"> @Override</span>
-<span class="source-line-no">2159</span><span id="line-2159"> public long getSize() {</span>
-<span class="source-line-no">2160</span><span id="line-2160"> return e.getValue().getLength();</span>
-<span class="source-line-no">2161</span><span id="line-2161"> }</span>
-<span class="source-line-no">2162</span><span id="line-2162"></span>
-<span class="source-line-no">2163</span><span id="line-2163"> @Override</span>
-<span class="source-line-no">2164</span><span id="line-2164"> public long getCachedTime() {</span>
-<span class="source-line-no">2165</span><span id="line-2165"> return e.getValue().getCachedTime();</span>
-<span class="source-line-no">2166</span><span id="line-2166"> }</span>
-<span class="source-line-no">2167</span><span id="line-2167"></span>
-<span class="source-line-no">2168</span><span id="line-2168"> @Override</span>
-<span class="source-line-no">2169</span><span id="line-2169"> public String getFilename() {</span>
-<span class="source-line-no">2170</span><span id="line-2170"> return e.getKey().getHfileName();</span>
-<span class="source-line-no">2171</span><span id="line-2171"> }</span>
-<span class="source-line-no">2172</span><span id="line-2172"></span>
-<span class="source-line-no">2173</span><span id="line-2173"> @Override</span>
-<span class="source-line-no">2174</span><span id="line-2174"> public int compareTo(CachedBlock other) {</span>
-<span class="source-line-no">2175</span><span id="line-2175"> int diff = this.getFilename().compareTo(other.getFilename());</span>
-<span class="source-line-no">2176</span><span id="line-2176"> if (diff != 0) return diff;</span>
-<span class="source-line-no">2177</span><span id="line-2177"></span>
-<span class="source-line-no">2178</span><span id="line-2178"> diff = Long.compare(this.getOffset(), other.getOffset());</span>
-<span class="source-line-no">2179</span><span id="line-2179"> if (diff != 0) return diff;</span>
-<span class="source-line-no">2180</span><span id="line-2180"> if (other.getCachedTime() < 0 || this.getCachedTime() < 0) {</span>
-<span class="source-line-no">2181</span><span id="line-2181"> throw new IllegalStateException(</span>
-<span class="source-line-no">2182</span><span id="line-2182"> "" + this.getCachedTime() + ", " + other.getCachedTime());</span>
-<span class="source-line-no">2183</span><span id="line-2183"> }</span>
-<span class="source-line-no">2184</span><span id="line-2184"> return Long.compare(other.getCachedTime(), this.getCachedTime());</span>
+<span class="source-line-no">2147</span><span id="line-2147"> @Override</span>
+<span class="source-line-no">2148</span><span id="line-2148"> public CachedBlock next() {</span>
+<span class="source-line-no">2149</span><span id="line-2149"> final Map.Entry<BlockCacheKey, BucketEntry> e = i.next();</span>
+<span class="source-line-no">2150</span><span id="line-2150"> return new CachedBlock() {</span>
+<span class="source-line-no">2151</span><span id="line-2151"> @Override</span>
+<span class="source-line-no">2152</span><span id="line-2152"> public String toString() {</span>
+<span class="source-line-no">2153</span><span id="line-2153"> return BlockCacheUtil.toString(this, now);</span>
+<span class="source-line-no">2154</span><span id="line-2154"> }</span>
+<span class="source-line-no">2155</span><span id="line-2155"></span>
+<span class="source-line-no">2156</span><span id="line-2156"> @Override</span>
+<span class="source-line-no">2157</span><span id="line-2157"> public BlockPriority getBlockPriority() {</span>
+<span class="source-line-no">2158</span><span id="line-2158"> return e.getValue().getPriority();</span>
+<span class="source-line-no">2159</span><span id="line-2159"> }</span>
+<span class="source-line-no">2160</span><span id="line-2160"></span>
+<span class="source-line-no">2161</span><span id="line-2161"> @Override</span>
+<span class="source-line-no">2162</span><span id="line-2162"> public BlockType getBlockType() {</span>
+<span class="source-line-no">2163</span><span id="line-2163"> // Not held by BucketEntry. Could add it if wanted on BucketEntry creation.</span>
+<span class="source-line-no">2164</span><span id="line-2164"> return null;</span>
+<span class="source-line-no">2165</span><span id="line-2165"> }</span>
+<span class="source-line-no">2166</span><span id="line-2166"></span>
+<span class="source-line-no">2167</span><span id="line-2167"> @Override</span>
+<span class="source-line-no">2168</span><span id="line-2168"> public long getOffset() {</span>
+<span class="source-line-no">2169</span><span id="line-2169"> return e.getKey().getOffset();</span>
+<span class="source-line-no">2170</span><span id="line-2170"> }</span>
+<span class="source-line-no">2171</span><span id="line-2171"></span>
+<span class="source-line-no">2172</span><span id="line-2172"> @Override</span>
+<span class="source-line-no">2173</span><span id="line-2173"> public long getSize() {</span>
+<span class="source-line-no">2174</span><span id="line-2174"> return e.getValue().getLength();</span>
+<span class="source-line-no">2175</span><span id="line-2175"> }</span>
+<span class="source-line-no">2176</span><span id="line-2176"></span>
+<span class="source-line-no">2177</span><span id="line-2177"> @Override</span>
+<span class="source-line-no">2178</span><span id="line-2178"> public long getCachedTime() {</span>
+<span class="source-line-no">2179</span><span id="line-2179"> return e.getValue().getCachedTime();</span>
+<span class="source-line-no">2180</span><span id="line-2180"> }</span>
+<span class="source-line-no">2181</span><span id="line-2181"></span>
+<span class="source-line-no">2182</span><span id="line-2182"> @Override</span>
+<span class="source-line-no">2183</span><span id="line-2183"> public String getFilename() {</span>
+<span class="source-line-no">2184</span><span id="line-2184"> return e.getKey().getHfileName();</span>
<span class="source-line-no">2185</span><span id="line-2185"> }</span>
<span class="source-line-no">2186</span><span id="line-2186"></span>
<span class="source-line-no">2187</span><span id="line-2187"> @Override</span>
-<span class="source-line-no">2188</span><span id="line-2188"> public int hashCode() {</span>
-<span class="source-line-no">2189</span><span id="line-2189"> return e.getKey().hashCode();</span>
-<span class="source-line-no">2190</span><span id="line-2190"> }</span>
+<span class="source-line-no">2188</span><span id="line-2188"> public int compareTo(CachedBlock other) {</span>
+<span class="source-line-no">2189</span><span id="line-2189"> int diff = this.getFilename().compareTo(other.getFilename());</span>
+<span class="source-line-no">2190</span><span id="line-2190"> if (diff != 0) return diff;</span>
<span class="source-line-no">2191</span><span id="line-2191"></span>
-<span class="source-line-no">2192</span><span id="line-2192"> @Override</span>
-<span class="source-line-no">2193</span><span id="line-2193"> public boolean equals(Object obj) {</span>
-<span class="source-line-no">2194</span><span id="line-2194"> if (obj instanceof CachedBlock) {</span>
-<span class="source-line-no">2195</span><span id="line-2195"> CachedBlock cb = (CachedBlock) obj;</span>
-<span class="source-line-no">2196</span><span id="line-2196"> return compareTo(cb) == 0;</span>
-<span class="source-line-no">2197</span><span id="line-2197"> } else {</span>
-<span class="source-line-no">2198</span><span id="line-2198"> return false;</span>
-<span class="source-line-no">2199</span><span id="line-2199"> }</span>
-<span class="source-line-no">2200</span><span id="line-2200"> }</span>
-<span class="source-line-no">2201</span><span id="line-2201"> };</span>
-<span class="source-line-no">2202</span><span id="line-2202"> }</span>
-<span class="source-line-no">2203</span><span id="line-2203"></span>
-<span class="source-line-no">2204</span><span id="line-2204"> @Override</span>
-<span class="source-line-no">2205</span><span id="line-2205"> public void remove() {</span>
-<span class="source-line-no">2206</span><span id="line-2206"> throw new UnsupportedOperationException();</span>
-<span class="source-line-no">2207</span><span id="line-2207"> }</span>
-<span class="source-line-no">2208</span><span id="line-2208"> };</span>
-<span class="source-line-no">2209</span><span id="line-2209"> }</span>
-<span class="source-line-no">2210</span><span id="line-2210"></span>
-<span class="source-line-no">2211</span><span id="line-2211"> @Override</span>
-<span class="source-line-no">2212</span><span id="line-2212"> public BlockCache[] getBlockCaches() {</span>
-<span class="source-line-no">2213</span><span id="line-2213"> return null;</span>
-<span class="source-line-no">2214</span><span id="line-2214"> }</span>
-<span class="source-line-no">2215</span><span id="line-2215"></span>
-<span class="source-line-no">2216</span><span id="line-2216"> public int getRpcRefCount(BlockCacheKey cacheKey) {</span>
-<span class="source-line-no">2217</span><span id="line-2217"> BucketEntry bucketEntry = backingMap.get(cacheKey);</span>
-<span class="source-line-no">2218</span><span id="line-2218"> if (bucketEntry != null) {</span>
-<span class="source-line-no">2219</span><span id="line-2219"> return bucketEntry.refCnt() - (bucketEntry.markedAsEvicted.get() ? 0 : 1);</span>
-<span class="source-line-no">2220</span><span id="line-2220"> }</span>
-<span class="source-line-no">2221</span><span id="line-2221"> return 0;</span>
-<span class="source-line-no">2222</span><span id="line-2222"> }</span>
-<span class="source-line-no">2223</span><span id="line-2223"></span>
-<span class="source-line-no">2224</span><span id="line-2224"> float getAcceptableFactor() {</span>
-<span class="source-line-no">2225</span><span id="line-2225"> return acceptableFactor;</span>
-<span class="source-line-no">2226</span><span id="line-2226"> }</span>
-<span class="source-line-no">2227</span><span id="line-2227"></span>
-<span class="source-line-no">2228</span><span id="line-2228"> float getMinFactor() {</span>
-<span class="source-line-no">2229</span><span id="line-2229"> return minFactor;</span>
-<span class="source-line-no">2230</span><span id="line-2230"> }</span>
-<span class="source-line-no">2231</span><span id="line-2231"></span>
-<span class="source-line-no">2232</span><span id="line-2232"> float getExtraFreeFactor() {</span>
-<span class="source-line-no">2233</span><span id="line-2233"> return extraFreeFactor;</span>
-<span class="source-line-no">2234</span><span id="line-2234"> }</span>
-<span class="source-line-no">2235</span><span id="line-2235"></span>
-<span class="source-line-no">2236</span><span id="line-2236"> float getSingleFactor() {</span>
-<span class="source-line-no">2237</span><span id="line-2237"> return singleFactor;</span>
-<span class="source-line-no">2238</span><span id="line-2238"> }</span>
-<span class="source-line-no">2239</span><span id="line-2239"></span>
-<span class="source-line-no">2240</span><span id="line-2240"> float getMultiFactor() {</span>
-<span class="source-line-no">2241</span><span id="line-2241"> return multiFactor;</span>
-<span class="source-line-no">2242</span><span id="line-2242"> }</span>
-<span class="source-line-no">2243</span><span id="line-2243"></span>
-<span class="source-line-no">2244</span><span id="line-2244"> float getMemoryFactor() {</span>
-<span class="source-line-no">2245</span><span id="line-2245"> return memoryFactor;</span>
-<span class="source-line-no">2246</span><span id="line-2246"> }</span>
-<span class="source-line-no">2247</span><span id="line-2247"></span>
-<span class="source-line-no">2248</span><span id="line-2248"> long getQueueAdditionWaitTime() {</span>
-<span class="source-line-no">2249</span><span id="line-2249"> return queueAdditionWaitTime;</span>
-<span class="source-line-no">2250</span><span id="line-2250"> }</span>
-<span class="source-line-no">2251</span><span id="line-2251"></span>
-<span class="source-line-no">2252</span><span id="line-2252"> long getPersistenceChunkSize() {</span>
-<span class="source-line-no">2253</span><span id="line-2253"> return persistenceChunkSize;</span>
-<span class="source-line-no">2254</span><span id="line-2254"> }</span>
-<span class="source-line-no">2255</span><span id="line-2255"></span>
-<span class="source-line-no">2256</span><span id="line-2256"> long getBucketcachePersistInterval() {</span>
-<span class="source-line-no">2257</span><span id="line-2257"> return bucketcachePersistInterval;</span>
-<span class="source-line-no">2258</span><span id="line-2258"> }</span>
-<span class="source-line-no">2259</span><span id="line-2259"></span>
-<span class="source-line-no">2260</span><span id="line-2260"> public String getPersistencePath() {</span>
-<span class="source-line-no">2261</span><span id="line-2261"> return persistencePath;</span>
-<span class="source-line-no">2262</span><span id="line-2262"> }</span>
-<span class="source-line-no">2263</span><span id="line-2263"></span>
-<span class="source-line-no">2264</span><span id="line-2264"> /**</span>
-<span class="source-line-no">2265</span><span id="line-2265"> * Wrapped the delegate ConcurrentMap with maintaining its block's reference count.</span>
-<span class="source-line-no">2266</span><span id="line-2266"> */</span>
-<span class="source-line-no">2267</span><span id="line-2267"> static class RAMCache {</span>
-<span class="source-line-no">2268</span><span id="line-2268"> /**</span>
-<span class="source-line-no">2269</span><span id="line-2269"> * Defined the map as {@link ConcurrentHashMap} explicitly here, because in</span>
-<span class="source-line-no">2270</span><span id="line-2270"> * {@link RAMCache#get(BlockCacheKey)} and</span>
-<span class="source-line-no">2271</span><span id="line-2271"> * {@link RAMCache#putIfAbsent(BlockCacheKey, BucketCache.RAMQueueEntry)} , we need to guarantee</span>
-<span class="source-line-no">2272</span><span id="line-2272"> * the atomicity of map#computeIfPresent(key, func) and map#putIfAbsent(key, func). Besides, the</span>
-<span class="source-line-no">2273</span><span id="line-2273"> * func method can execute exactly once only when the key is present(or absent) and under the</span>
-<span class="source-line-no">2274</span><span id="line-2274"> * lock context. Otherwise, the reference count of block will be messed up. Notice that the</span>
-<span class="source-line-no">2275</span><span id="line-2275"> * {@link java.util.concurrent.ConcurrentSkipListMap} can not guarantee that.</span>
-<span class="source-line-no">2276</span><span id="line-2276"> */</span>
-<span class="source-line-no">2277</span><span id="line-2277"> final ConcurrentHashMap<BlockCacheKey, RAMQueueEntry> delegate = new ConcurrentHashMap<>();</span>
-<span class="source-line-no">2278</span><span id="line-2278"></span>
-<span class="source-line-no">2279</span><span id="line-2279"> public boolean containsKey(BlockCacheKey key) {</span>
-<span class="source-line-no">2280</span><span id="line-2280"> return delegate.containsKey(key);</span>
-<span class="source-line-no">2281</span><span id="line-2281"> }</span>
-<span class="source-line-no">2282</span><span id="line-2282"></span>
-<span class="source-line-no">2283</span><span id="line-2283"> public RAMQueueEntry get(BlockCacheKey key) {</span>
-<span class="source-line-no">2284</span><span id="line-2284"> return delegate.computeIfPresent(key, (k, re) -> {</span>
-<span class="source-line-no">2285</span><span id="line-2285"> // It'll be referenced by RPC, so retain atomically here. if the get and retain is not</span>
-<span class="source-line-no">2286</span><span id="line-2286"> // atomic, another thread may remove and release the block, when retaining in this thread we</span>
-<span class="source-line-no">2287</span><span id="line-2287"> // may retain a block with refCnt=0 which is disallowed. (see HBASE-22422)</span>
-<span class="source-line-no">2288</span><span id="line-2288"> re.getData().retain();</span>
-<span class="source-line-no">2289</span><span id="line-2289"> return re;</span>
-<span class="source-line-no">2290</span><span id="line-2290"> });</span>
-<span class="source-line-no">2291</span><span id="line-2291"> }</span>
+<span class="source-line-no">2192</span><span id="line-2192"> diff = Long.compare(this.getOffset(), other.getOffset());</span>
+<span class="source-line-no">2193</span><span id="line-2193"> if (diff != 0) return diff;</span>
+<span class="source-line-no">2194</span><span id="line-2194"> if (other.getCachedTime() < 0 || this.getCachedTime() < 0) {</span>
+<span class="source-line-no">2195</span><span id="line-2195"> throw new IllegalStateException(</span>
+<span class="source-line-no">2196</span><span id="line-2196"> "" + this.getCachedTime() + ", " + other.getCachedTime());</span>
+<span class="source-line-no">2197</span><span id="line-2197"> }</span>
+<span class="source-line-no">2198</span><span id="line-2198"> return Long.compare(other.getCachedTime(), this.getCachedTime());</span>
+<span class="source-line-no">2199</span><span id="line-2199"> }</span>
+<span class="source-line-no">2200</span><span id="line-2200"></span>
+<span class="source-line-no">2201</span><span id="line-2201"> @Override</span>
+<span class="source-line-no">2202</span><span id="line-2202"> public int hashCode() {</span>
+<span class="source-line-no">2203</span><span id="line-2203"> return e.getKey().hashCode();</span>
+<span class="source-line-no">2204</span><span id="line-2204"> }</span>
+<span class="source-line-no">2205</span><span id="line-2205"></span>
+<span class="source-line-no">2206</span><span id="line-2206"> @Override</span>
+<span class="source-line-no">2207</span><span id="line-2207"> public boolean equals(Object obj) {</span>
+<span class="source-line-no">2208</span><span id="line-2208"> if (obj instanceof CachedBlock) {</span>
+<span class="source-line-no">2209</span><span id="line-2209"> CachedBlock cb = (CachedBlock) obj;</span>
+<span class="source-line-no">2210</span><span id="line-2210"> return compareTo(cb) == 0;</span>
+<span class="source-line-no">2211</span><span id="line-2211"> } else {</span>
+<span class="source-line-no">2212</span><span id="line-2212"> return false;</span>
+<span class="source-line-no">2213</span><span id="line-2213"> }</span>
+<span class="source-line-no">2214</span><span id="line-2214"> }</span>
+<span class="source-line-no">2215</span><span id="line-2215"> };</span>
+<span class="source-line-no">2216</span><span id="line-2216"> }</span>
+<span class="source-line-no">2217</span><span id="line-2217"></span>
+<span class="source-line-no">2218</span><span id="line-2218"> @Override</span>
+<span class="source-line-no">2219</span><span id="line-2219"> public void remove() {</span>
+<span class="source-line-no">2220</span><span id="line-2220"> throw new UnsupportedOperationException();</span>
+<span class="source-line-no">2221</span><span id="line-2221"> }</span>
+<span class="source-line-no">2222</span><span id="line-2222"> };</span>
+<span class="source-line-no">2223</span><span id="line-2223"> }</span>
+<span class="source-line-no">2224</span><span id="line-2224"></span>
+<span class="source-line-no">2225</span><span id="line-2225"> @Override</span>
+<span class="source-line-no">2226</span><span id="line-2226"> public BlockCache[] getBlockCaches() {</span>
+<span class="source-line-no">2227</span><span id="line-2227"> return null;</span>
+<span class="source-line-no">2228</span><span id="line-2228"> }</span>
+<span class="source-line-no">2229</span><span id="line-2229"></span>
+<span class="source-line-no">2230</span><span id="line-2230"> public int getRpcRefCount(BlockCacheKey cacheKey) {</span>
+<span class="source-line-no">2231</span><span id="line-2231"> BucketEntry bucketEntry = backingMap.get(cacheKey);</span>
+<span class="source-line-no">2232</span><span id="line-2232"> if (bucketEntry != null) {</span>
+<span class="source-line-no">2233</span><span id="line-2233"> return bucketEntry.refCnt() - (bucketEntry.markedAsEvicted.get() ? 0 : 1);</span>
+<span class="source-line-no">2234</span><span id="line-2234"> }</span>
+<span class="source-line-no">2235</span><span id="line-2235"> return 0;</span>
+<span class="source-line-no">2236</span><span id="line-2236"> }</span>
+<span class="source-line-no">2237</span><span id="line-2237"></span>
+<span class="source-line-no">2238</span><span id="line-2238"> float getAcceptableFactor() {</span>
+<span class="source-line-no">2239</span><span id="line-2239"> return acceptableFactor;</span>
+<span class="source-line-no">2240</span><span id="line-2240"> }</span>
+<span class="source-line-no">2241</span><span id="line-2241"></span>
+<span class="source-line-no">2242</span><span id="line-2242"> float getMinFactor() {</span>
+<span class="source-line-no">2243</span><span id="line-2243"> return minFactor;</span>
+<span class="source-line-no">2244</span><span id="line-2244"> }</span>
+<span class="source-line-no">2245</span><span id="line-2245"></span>
+<span class="source-line-no">2246</span><span id="line-2246"> float getExtraFreeFactor() {</span>
+<span class="source-line-no">2247</span><span id="line-2247"> return extraFreeFactor;</span>
+<span class="source-line-no">2248</span><span id="line-2248"> }</span>
+<span class="source-line-no">2249</span><span id="line-2249"></span>
+<span class="source-line-no">2250</span><span id="line-2250"> float getSingleFactor() {</span>
+<span class="source-line-no">2251</span><span id="line-2251"> return singleFactor;</span>
+<span class="source-line-no">2252</span><span id="line-2252"> }</span>
+<span class="source-line-no">2253</span><span id="line-2253"></span>
+<span class="source-line-no">2254</span><span id="line-2254"> float getMultiFactor() {</span>
+<span class="source-line-no">2255</span><span id="line-2255"> return multiFactor;</span>
+<span class="source-line-no">2256</span><span id="line-2256"> }</span>
+<span class="source-line-no">2257</span><span id="line-2257"></span>
+<span class="source-line-no">2258</span><span id="line-2258"> float getMemoryFactor() {</span>
+<span class="source-line-no">2259</span><span id="line-2259"> return memoryFactor;</span>
+<span class="source-line-no">2260</span><span id="line-2260"> }</span>
+<span class="source-line-no">2261</span><span id="line-2261"></span>
+<span class="source-line-no">2262</span><span id="line-2262"> long getQueueAdditionWaitTime() {</span>
+<span class="source-line-no">2263</span><span id="line-2263"> return queueAdditionWaitTime;</span>
+<span class="source-line-no">2264</span><span id="line-2264"> }</span>
+<span class="source-line-no">2265</span><span id="line-2265"></span>
+<span class="source-line-no">2266</span><span id="line-2266"> long getPersistenceChunkSize() {</span>
+<span class="source-line-no">2267</span><span id="line-2267"> return persistenceChunkSize;</span>
+<span class="source-line-no">2268</span><span id="line-2268"> }</span>
+<span class="source-line-no">2269</span><span id="line-2269"></span>
+<span class="source-line-no">2270</span><span id="line-2270"> long getBucketcachePersistInterval() {</span>
+<span class="source-line-no">2271</span><span id="line-2271"> return bucketcachePersistInterval;</span>
+<span class="source-line-no">2272</span><span id="line-2272"> }</span>
+<span class="source-line-no">2273</span><span id="line-2273"></span>
+<span class="source-line-no">2274</span><span id="line-2274"> public String getPersistencePath() {</span>
+<span class="source-line-no">2275</span><span id="line-2275"> return persistencePath;</span>
+<span class="source-line-no">2276</span><span id="line-2276"> }</span>
+<span class="source-line-no">2277</span><span id="line-2277"></span>
+<span class="source-line-no">2278</span><span id="line-2278"> /**</span>
+<span class="source-line-no">2279</span><span id="line-2279"> * Wrapped the delegate ConcurrentMap with maintaining its block's reference count.</span>
+<span class="source-line-no">2280</span><span id="line-2280"> */</span>
+<span class="source-line-no">2281</span><span id="line-2281"> static class RAMCache {</span>
+<span class="source-line-no">2282</span><span id="line-2282"> /**</span>
+<span class="source-line-no">2283</span><span id="line-2283"> * Defined the map as {@link ConcurrentHashMap} explicitly here, because in</span>
+<span class="source-line-no">2284</span><span id="line-2284"> * {@link RAMCache#get(BlockCacheKey)} and</span>
+<span class="source-line-no">2285</span><span id="line-2285"> * {@link RAMCache#putIfAbsent(BlockCacheKey, BucketCache.RAMQueueEntry)} , we need to guarantee</span>
+<span class="source-line-no">2286</span><span id="line-2286"> * the atomicity of map#computeIfPresent(key, func) and map#putIfAbsent(key, func). Besides, the</span>
+<span class="source-line-no">2287</span><span id="line-2287"> * func method can execute exactly once only when the key is present(or absent) and under the</span>
+<span class="source-line-no">2288</span><span id="line-2288"> * lock context. Otherwise, the reference count of block will be messed up. Notice that the</span>
+<span class="source-line-no">2289</span><span id="line-2289"> * {@link java.util.concurrent.ConcurrentSkipListMap} can not guarantee that.</span>
+<span class="source-line-no">2290</span><span id="line-2290"> */</span>
+<span class="source-line-no">2291</span><span id="line-2291"> final ConcurrentHashMap<BlockCacheKey, RAMQueueEntry> delegate = new ConcurrentHashMap<>();</span>
<span class="source-line-no">2292</span><span id="line-2292"></span>
-<span class="source-line-no">2293</span><span id="line-2293"> /**</span>
-<span class="source-line-no">2294</span><span id="line-2294"> * Return the previous associated value, or null if absent. It has the same meaning as</span>
-<span class="source-line-no">2295</span><span id="line-2295"> * {@link ConcurrentMap#putIfAbsent(Object, Object)}</span>
-<span class="source-line-no">2296</span><span id="line-2296"> */</span>
-<span class="source-line-no">2297</span><span id="line-2297"> public RAMQueueEntry putIfAbsent(BlockCacheKey key, RAMQueueEntry entry) {</span>
-<span class="source-line-no">2298</span><span id="line-2298"> AtomicBoolean absent = new AtomicBoolean(false);</span>
-<span class="source-line-no">2299</span><span id="line-2299"> RAMQueueEntry re = delegate.computeIfAbsent(key, k -> {</span>
-<span class="source-line-no">2300</span><span id="line-2300"> // The RAMCache reference to this entry, so reference count should be increment.</span>
-<span class="source-line-no">2301</span><span id="line-2301"> entry.getData().retain();</span>
-<span class="source-line-no">2302</span><span id="line-2302"> absent.set(true);</span>
-<span class="source-line-no">2303</span><span id="line-2303"> return entry;</span>
+<span class="source-line-no">2293</span><span id="line-2293"> public boolean containsKey(BlockCacheKey key) {</span>
+<span class="source-line-no">2294</span><span id="line-2294"> return delegate.containsKey(key);</span>
+<span class="source-line-no">2295</span><span id="line-2295"> }</span>
+<span class="source-line-no">2296</span><span id="line-2296"></span>
+<span class="source-line-no">2297</span><span id="line-2297"> public RAMQueueEntry get(BlockCacheKey key) {</span>
+<span class="source-line-no">2298</span><span id="line-2298"> return delegate.computeIfPresent(key, (k, re) -> {</span>
+<span class="source-line-no">2299</span><span id="line-2299"> // It'll be referenced by RPC, so retain atomically here. if the get and retain is not</span>
+<span class="source-line-no">2300</span><span id="line-2300"> // atomic, another thread may remove and release the block, when retaining in this thread we</span>
+<span class="source-line-no">2301</span><span id="line-2301"> // may retain a block with refCnt=0 which is disallowed. (see HBASE-22422)</span>
+<span class="source-line-no">2302</span><span id="line-2302"> re.getData().retain();</span>
+<span class="source-line-no">2303</span><span id="line-2303"> return re;</span>
<span class="source-line-no">2304</span><span id="line-2304"> });</span>
-<span class="source-line-no">2305</span><span id="line-2305"> return absent.get() ? null : re;</span>
-<span class="source-line-no">2306</span><span id="line-2306"> }</span>
-<span class="source-line-no">2307</span><span id="line-2307"></span>
-<span class="source-line-no">2308</span><span id="line-2308"> public boolean remove(BlockCacheKey key) {</span>
-<span class="source-line-no">2309</span><span id="line-2309"> return remove(key, re -> {</span>
-<span class="source-line-no">2310</span><span id="line-2310"> });</span>
-<span class="source-line-no">2311</span><span id="line-2311"> }</span>
-<span class="source-line-no">2312</span><span id="line-2312"></span>
-<span class="source-line-no">2313</span><span id="line-2313"> /**</span>
-<span class="source-line-no">2314</span><span id="line-2314"> * Defined an {@link Consumer} here, because once the removed entry release its reference count,</span>
-<span class="source-line-no">2315</span><span id="line-2315"> * then it's ByteBuffers may be recycled and accessing it outside this method will be thrown an</span>
-<span class="source-line-no">2316</span><span id="line-2316"> * exception. the consumer will access entry to remove before release its reference count.</span>
-<span class="source-line-no">2317</span><span id="line-2317"> * Notice, don't change its reference count in the {@link Consumer}</span>
-<span class="source-line-no">2318</span><span id="line-2318"> */</span>
-<span class="source-line-no">2319</span><span id="line-2319"> public boolean remove(BlockCacheKey key, Consumer<RAMQueueEntry> action) {</span>
-<span class="source-line-no">2320</span><span id="line-2320"> RAMQueueEntry previous = delegate.remove(key);</span>
-<span class="source-line-no">2321</span><span id="line-2321"> action.accept(previous);</span>
-<span class="source-line-no">2322</span><span id="line-2322"> if (previous != null) {</span>
-<span class="source-line-no">2323</span><span id="line-2323"> previous.getData().release();</span>
-<span class="source-line-no">2324</span><span id="line-2324"> }</span>
-<span class="source-line-no">2325</span><span id="line-2325"> return previous != null;</span>
-<span class="source-line-no">2326</span><span id="line-2326"> }</span>
-<span class="source-line-no">2327</span><span id="line-2327"></span>
-<span class="source-line-no">2328</span><span id="line-2328"> public boolean isEmpty() {</span>
-<span class="source-line-no">2329</span><span id="line-2329"> return delegate.isEmpty();</span>
-<span class="source-line-no">2330</span><span id="line-2330"> }</span>
-<span class="source-line-no">2331</span><span id="line-2331"></span>
-<span class="source-line-no">2332</span><span id="line-2332"> public void clear() {</span>
-<span class="source-line-no">2333</span><span id="line-2333"> Iterator<Map.Entry<BlockCacheKey, RAMQueueEntry>> it = delegate.entrySet().iterator();</span>
-<span class="source-line-no">2334</span><span id="line-2334"> while (it.hasNext()) {</span>
-<span class="source-line-no">2335</span><span id="line-2335"> RAMQueueEntry re = it.next().getValue();</span>
-<span class="source-line-no">2336</span><span id="line-2336"> it.remove();</span>
-<span class="source-line-no">2337</span><span id="line-2337"> re.getData().release();</span>
+<span class="source-line-no">2305</span><span id="line-2305"> }</span>
+<span class="source-line-no">2306</span><span id="line-2306"></span>
+<span class="source-line-no">2307</span><span id="line-2307"> /**</span>
+<span class="source-line-no">2308</span><span id="line-2308"> * Return the previous associated value, or null if absent. It has the same meaning as</span>
+<span class="source-line-no">2309</span><span id="line-2309"> * {@link ConcurrentMap#putIfAbsent(Object, Object)}</span>
+<span class="source-line-no">2310</span><span id="line-2310"> */</span>
+<span class="source-line-no">2311</span><span id="line-2311"> public RAMQueueEntry putIfAbsent(BlockCacheKey key, RAMQueueEntry entry) {</span>
+<span class="source-line-no">2312</span><span id="line-2312"> AtomicBoolean absent = new AtomicBoolean(false);</span>
+<span class="source-line-no">2313</span><span id="line-2313"> RAMQueueEntry re = delegate.computeIfAbsent(key, k -> {</span>
+<span class="source-line-no">2314</span><span id="line-2314"> // The RAMCache reference to this entry, so reference count should be increment.</span>
+<span class="source-line-no">2315</span><span id="line-2315"> entry.getData().retain();</span>
+<span class="source-line-no">2316</span><span id="line-2316"> absent.set(true);</span>
+<span class="source-line-no">2317</span><span id="line-2317"> return entry;</span>
+<span class="source-line-no">2318</span><span id="line-2318"> });</span>
+<span class="source-line-no">2319</span><span id="line-2319"> return absent.get() ? null : re;</span>
+<span class="source-line-no">2320</span><span id="line-2320"> }</span>
+<span class="source-line-no">2321</span><span id="line-2321"></span>
+<span class="source-line-no">2322</span><span id="line-2322"> public boolean remove(BlockCacheKey key) {</span>
+<span class="source-line-no">2323</span><span id="line-2323"> return remove(key, re -> {</span>
+<span class="source-line-no">2324</span><span id="line-2324"> });</span>
+<span class="source-line-no">2325</span><span id="line-2325"> }</span>
+<span class="source-line-no">2326</span><span id="line-2326"></span>
+<span class="source-line-no">2327</span><span id="line-2327"> /**</span>
+<span class="source-line-no">2328</span><span id="line-2328"> * Defined an {@link Consumer} here, because once the removed entry release its reference count,</span>
+<span class="source-line-no">2329</span><span id="line-2329"> * then it's ByteBuffers may be recycled and accessing it outside this method will be thrown an</span>
+<span class="source-line-no">2330</span><span id="line-2330"> * exception. the consumer will access entry to remove before release its reference count.</span>
+<span class="source-line-no">2331</span><span id="line-2331"> * Notice, don't change its reference count in the {@link Consumer}</span>
+<span class="source-line-no">2332</span><span id="line-2332"> */</span>
+<span class="source-line-no">2333</span><span id="line-2333"> public boolean remove(BlockCacheKey key, Consumer<RAMQueueEntry> action) {</span>
+<span class="source-line-no">2334</span><span id="line-2334"> RAMQueueEntry previous = delegate.remove(key);</span>
+<span class="source-line-no">2335</span><span id="line-2335"> action.accept(previous);</span>
+<span class="source-line-no">2336</span><span id="line-2336"> if (previous != null) {</span>
+<span class="source-line-no">2337</span><span id="line-2337"> previous.getData().release();</span>
<span class="source-line-no">2338</span><span id="line-2338"> }</span>
-<span class="source-line-no">2339</span><span id="line-2339"> }</span>
-<span class="source-line-no">2340</span><span id="line-2340"></span>
-<span class="source-line-no">2341</span><span id="line-2341"> public boolean hasBlocksForFile(String fileName) {</span>
-<span class="source-line-no">2342</span><span id="line-2342"> return delegate.keySet().stream().filter(key -> key.getHfileName().equals(fileName))</span>
-<span class="source-line-no">2343</span><span id="line-2343"> .findFirst().isPresent();</span>
+<span class="source-line-no">2339</span><span id="line-2339"> return previous != null;</span>
+<span class="source-line-no">2340</span><span id="line-2340"> }</span>
+<span class="source-line-no">2341</span><span id="line-2341"></span>
+<span class="source-line-no">2342</span><span id="line-2342"> public boolean isEmpty() {</span>
+<span class="source-line-no">2343</span><span id="line-2343"> return delegate.isEmpty();</span>
<span class="source-line-no">2344</span><span id="line-2344"> }</span>
-<span class="source-line-no">2345</span><span id="line-2345"> }</span>
-<span class="source-line-no">2346</span><span id="line-2346"></span>
-<span class="source-line-no">2347</span><span id="line-2347"> public Map<BlockCacheKey, BucketEntry> getBackingMap() {</span>
-<span class="source-line-no">2348</span><span id="line-2348"> return backingMap;</span>
-<span class="source-line-no">2349</span><span id="line-2349"> }</span>
-<span class="source-line-no">2350</span><span id="line-2350"></span>
-<span class="source-line-no">2351</span><span id="line-2351"> public AtomicBoolean getBackingMapValidated() {</span>
-<span class="source-line-no">2352</span><span id="line-2352"> return backingMapValidated;</span>
-<span class="source-line-no">2353</span><span id="line-2353"> }</span>
+<span class="source-line-no">2345</span><span id="line-2345"></span>
+<span class="source-line-no">2346</span><span id="line-2346"> public void clear() {</span>
+<span class="source-line-no">2347</span><span id="line-2347"> Iterator<Map.Entry<BlockCacheKey, RAMQueueEntry>> it = delegate.entrySet().iterator();</span>
+<span class="source-line-no">2348</span><span id="line-2348"> while (it.hasNext()) {</span>
+<span class="source-line-no">2349</span><span id="line-2349"> RAMQueueEntry re = it.next().getValue();</span>
+<span class="source-line-no">2350</span><span id="line-2350"> it.remove();</span>
+<span class="source-line-no">2351</span><span id="line-2351"> re.getData().release();</span>
+<span class="source-line-no">2352</span><span id="line-2352"> }</span>
+<span class="source-line-no">2353</span><span id="line-2353"> }</span>
<span class="source-line-no">2354</span><span id="line-2354"></span>
-<span class="source-line-no">2355</span><span id="line-2355"> @Override</span>
-<span class="source-line-no">2356</span><span id="line-2356"> public Optional<Map<String, Pair<String, Long>>> getFullyCachedFiles() {</span>
-<span class="source-line-no">2357</span><span id="line-2357"> return Optional.of(fullyCachedFiles);</span>
-<span class="source-line-no">2358</span><span id="line-2358"> }</span>
-<span class="source-line-no">2359</span><span id="line-2359"></span>
-<span class="source-line-no">2360</span><span id="line-2360"> public static Optional<BucketCache> getBucketCacheFromCacheConfig(CacheConfig cacheConf) {</span>
-<span class="source-line-no">2361</span><span id="line-2361"> if (cacheConf.getBlockCache().isPresent()) {</span>
-<span class="source-line-no">2362</span><span id="line-2362"> BlockCache bc = cacheConf.getBlockCache().get();</span>
-<span class="source-line-no">2363</span><span id="line-2363"> if (bc instanceof CombinedBlockCache) {</span>
-<span class="source-line-no">2364</span><span id="line-2364"> BlockCache l2 = ((CombinedBlockCache) bc).getSecondLevelCache();</span>
-<span class="source-line-no">2365</span><span id="line-2365"> if (l2 instanceof BucketCache) {</span>
-<span class="source-line-no">2366</span><span id="line-2366"> return Optional.of((BucketCache) l2);</span>
-<span class="source-line-no">2367</span><span id="line-2367"> }</span>
-<span class="source-line-no">2368</span><span id="line-2368"> } else if (bc instanceof BucketCache) {</span>
-<span class="source-line-no">2369</span><span id="line-2369"> return Optional.of((BucketCache) bc);</span>
-<span class="source-line-no">2370</span><span id="line-2370"> }</span>
-<span class="source-line-no">2371</span><span id="line-2371"> }</span>
-<span class="source-line-no">2372</span><span id="line-2372"> return Optional.empty();</span>
-<span class="source-line-no">2373</span><span id="line-2373"> }</span>
-<span class="source-line-no">2374</span><span id="line-2374"></span>
-<span class="source-line-no">2375</span><span id="line-2375"> @Override</span>
-<span class="source-line-no">2376</span><span id="line-2376"> public void notifyFileCachingCompleted(Path fileName, int totalBlockCount, int dataBlockCount,</span>
-<span class="source-line-no">2377</span><span id="line-2377"> long size) {</span>
-<span class="source-line-no">2378</span><span id="line-2378"> // block eviction may be happening in the background as prefetch runs,</span>
-<span class="source-line-no">2379</span><span id="line-2379"> // so we need to count all blocks for this file in the backing map under</span>
-<span class="source-line-no">2380</span><span id="line-2380"> // a read lock for the block offset</span>
-<span class="source-line-no">2381</span><span id="line-2381"> final List<ReentrantReadWriteLock> locks = new ArrayList<>();</span>
-<span class="source-line-no">2382</span><span id="line-2382"> LOG.debug("Notifying caching completed for file {}, with total blocks {}, and data blocks {}",</span>
-<span class="source-line-no">2383</span><span id="line-2383"> fileName, totalBlockCount, dataBlockCount);</span>
-<span class="source-line-no">2384</span><span id="line-2384"> try {</span>
-<span class="source-line-no">2385</span><span id="line-2385"> int count = 0;</span>
-<span class="source-line-no">2386</span><span id="line-2386"> LOG.debug("iterating over {} entries in the backing map", backingMap.size());</span>
-<span class="source-line-no">2387</span><span id="line-2387"> Set<BlockCacheKey> result = getAllCacheKeysForFile(fileName.getName(), 0, Long.MAX_VALUE);</span>
-<span class="source-line-no">2388</span><span id="line-2388"> if (result.isEmpty() && StoreFileInfo.isReference(fileName)) {</span>
-<span class="source-line-no">2389</span><span id="line-2389"> result = getAllCacheKeysForFile(</span>
-<span class="source-line-no">2390</span><span id="line-2390"> StoreFileInfo.getReferredToRegionAndFile(fileName.getName()).getSecond(), 0,</span>
-<span class="source-line-no">2391</span><span id="line-2391"> Long.MAX_VALUE);</span>
-<span class="source-line-no">2392</span><span id="line-2392"> }</span>
-<span class="source-line-no">2393</span><span id="line-2393"> for (BlockCacheKey entry : result) {</span>
-<span class="source-line-no">2394</span><span id="line-2394"> LOG.debug("found block for file {} in the backing map. Acquiring read lock for offset {}",</span>
-<span class="source-line-no">2395</span><span id="line-2395"> fileName.getName(), entry.getOffset());</span>
-<span class="source-line-no">2396</span><span id="line-2396"> ReentrantReadWriteLock lock = offsetLock.getLock(entry.getOffset());</span>
-<span class="source-line-no">2397</span><span id="line-2397"> lock.readLock().lock();</span>
-<span class="source-line-no">2398</span><span id="line-2398"> locks.add(lock);</span>
-<span class="source-line-no">2399</span><span id="line-2399"> if (backingMap.containsKey(entry) && entry.getBlockType().isData()) {</span>
-<span class="source-line-no">2400</span><span id="line-2400"> count++;</span>
-<span class="source-line-no">2401</span><span id="line-2401"> }</span>
-<span class="source-line-no">2402</span><span id="line-2402"> }</span>
-<span class="source-line-no">2403</span><span id="line-2403"> // BucketCache would only have data blocks</span>
-<span class="source-line-no">2404</span><span id="line-2404"> if (dataBlockCount == count) {</span>
-<span class="source-line-no">2405</span><span id="line-2405"> LOG.debug("File {} has now been fully cached.", fileName);</span>
-<span class="source-line-no">2406</span><span id="line-2406"> fileCacheCompleted(fileName, size);</span>
-<span class="source-line-no">2407</span><span id="line-2407"> } else {</span>
-<span class="source-line-no">2408</span><span id="line-2408"> LOG.debug(</span>
-<span class="source-line-no">2409</span><span id="line-2409"> "Prefetch executor completed for {}, but only {} data blocks were cached. "</span>
-<span class="source-line-no">2410</span><span id="line-2410"> + "Total data blocks for file: {}. "</span>
-<span class="source-line-no">2411</span><span id="line-2411"> + "Checking for blocks pending cache in cache writer queue.",</span>
-<span class="source-line-no">2412</span><span id="line-2412"> fileName, count, dataBlockCount);</span>
-<span class="source-line-no">2413</span><span id="line-2413"> if (ramCache.hasBlocksForFile(fileName.getName())) {</span>
-<span class="source-line-no">2414</span><span id="line-2414"> for (ReentrantReadWriteLock lock : locks) {</span>
-<span class="source-line-no">2415</span><span id="line-2415"> lock.readLock().unlock();</span>
-<span class="source-line-no">2416</span><span id="line-2416"> }</span>
-<span class="source-line-no">2417</span><span id="line-2417"> locks.clear();</span>
-<span class="source-line-no">2418</span><span id="line-2418"> LOG.debug("There are still blocks pending caching for file {}. Will sleep 100ms "</span>
-<span class="source-line-no">2419</span><span id="line-2419"> + "and try the verification again.", fileName);</span>
-<span class="source-line-no">2420</span><span id="line-2420"> Thread.sleep(100);</span>
-<span class="source-line-no">2421</span><span id="line-2421"> notifyFileCachingCompleted(fileName, totalBlockCount, dataBlockCount, size);</span>
-<span class="source-line-no">2422</span><span id="line-2422"> } else {</span>
-<span class="source-line-no">2423</span><span id="line-2423"> LOG.info(</span>
-<span class="source-line-no">2424</span><span id="line-2424"> "The total block count was {}. We found only {} data blocks cached from "</span>
-<span class="source-line-no">2425</span><span id="line-2425"> + "a total of {} data blocks for file {}, "</span>
-<span class="source-line-no">2426</span><span id="line-2426"> + "but no blocks pending caching. Maybe cache is full or evictions "</span>
-<span class="source-line-no">2427</span><span id="line-2427"> + "happened concurrently to cache prefetch.",</span>
-<span class="source-line-no">2428</span><span id="line-2428"> totalBlockCount, count, dataBlockCount, fileName);</span>
-<span class="source-line-no">2429</span><span id="line-2429"> }</span>
-<span class="source-line-no">2430</span><span id="line-2430"> }</span>
-<span class="source-line-no">2431</span><span id="line-2431"> } catch (InterruptedException e) {</span>
-<span class="source-line-no">2432</span><span id="line-2432"> throw new RuntimeException(e);</span>
-<span class="source-line-no">2433</span><span id="line-2433"> } finally {</span>
-<span class="source-line-no">2434</span><span id="line-2434"> for (ReentrantReadWriteLock lock : locks) {</span>
-<span class="source-line-no">2435</span><span id="line-2435"> lock.readLock().unlock();</span>
-<span class="source-line-no">2436</span><span id="line-2436"> }</span>
-<span class="source-line-no">2437</span><span id="line-2437"> }</span>
-<span class="source-line-no">2438</span><span id="line-2438"> }</span>
-<span class="source-line-no">2439</span><span id="line-2439"></span>
-<span class="source-line-no">2440</span><span id="line-2440"> @Override</span>
-<span class="source-line-no">2441</span><span id="line-2441"> public Optional<Boolean> blockFitsIntoTheCache(HFileBlock block) {</span>
-<span class="source-line-no">2442</span><span id="line-2442"> if (!isCacheInitialized("blockFitsIntoTheCache")) {</span>
-<span class="source-line-no">2443</span><span id="line-2443"> return Optional.of(false);</span>
-<span class="source-line-no">2444</span><span id="line-2444"> }</span>
-<span class="source-line-no">2445</span><span id="line-2445"></span>
-<span class="source-line-no">2446</span><span id="line-2446"> long currentUsed = bucketAllocator.getUsedSize();</span>
-<span class="source-line-no">2447</span><span id="line-2447"> boolean result = (currentUsed + block.getOnDiskSizeWithHeader()) < acceptableSize();</span>
-<span class="source-line-no">2448</span><span id="line-2448"> return Optional.of(result);</span>
-<span class="source-line-no">2449</span><span id="line-2449"> }</span>
-<span class="source-line-no">2450</span><span id="line-2450"></span>
-<span class="source-line-no">2451</span><span id="line-2451"> @Override</span>
-<span class="source-line-no">2452</span><span id="line-2452"> public Optional<Boolean> shouldCacheFile(HFileInfo hFileInfo, Configuration conf) {</span>
-<span class="source-line-no">2453</span><span id="line-2453"> String fileName = hFileInfo.getHFileContext().getHFileName();</span>
-<span class="source-line-no">2454</span><span id="line-2454"> DataTieringManager dataTieringManager = DataTieringManager.getInstance();</span>
-<span class="source-line-no">2455</span><span id="line-2455"> if (dataTieringManager != null && !dataTieringManager.isHotData(hFileInfo, conf)) {</span>
-<span class="source-line-no">2456</span><span id="line-2456"> LOG.debug("Data tiering is enabled for file: '{}' and it is not hot data", fileName);</span>
+<span class="source-line-no">2355</span><span id="line-2355"> public boolean hasBlocksForFile(String fileName) {</span>
+<span class="source-line-no">2356</span><span id="line-2356"> return delegate.keySet().stream().filter(key -> key.getHfileName().equals(fileName))</span>
+<span class="source-line-no">2357</span><span id="line-2357"> .findFirst().isPresent();</span>
+<span class="source-line-no">2358</span><span id="line-2358"> }</span>
+<span class="source-line-no">2359</span><span id="line-2359"> }</span>
+<span class="source-line-no">2360</span><span id="line-2360"></span>
+<span class="source-line-no">2361</span><span id="line-2361"> public Map<BlockCacheKey, BucketEntry> getBackingMap() {</span>
+<span class="source-line-no">2362</span><span id="line-2362"> return backingMap;</span>
+<span class="source-line-no">2363</span><span id="line-2363"> }</span>
+<span class="source-line-no">2364</span><span id="line-2364"></span>
+<span class="source-line-no">2365</span><span id="line-2365"> public AtomicBoolean getBackingMapValidated() {</span>
+<span class="source-line-no">2366</span><span id="line-2366"> return backingMapValidated;</span>
+<span class="source-line-no">2367</span><span id="line-2367"> }</span>
+<span class="source-line-no">2368</span><span id="line-2368"></span>
+<span class="source-line-no">2369</span><span id="line-2369"> @Override</span>
+<span class="source-line-no">2370</span><span id="line-2370"> public Optional<Map<String, Pair<String, Long>>> getFullyCachedFiles() {</span>
+<span class="source-line-no">2371</span><span id="line-2371"> return Optional.of(fullyCachedFiles);</span>
+<span class="source-line-no">2372</span><span id="line-2372"> }</span>
+<span class="source-line-no">2373</span><span id="line-2373"></span>
+<span class="source-line-no">2374</span><span id="line-2374"> public static Optional<BucketCache> getBucketCacheFromCacheConfig(CacheConfig cacheConf) {</span>
+<span class="source-line-no">2375</span><span id="line-2375"> if (cacheConf.getBlockCache().isPresent()) {</span>
+<span class="source-line-no">2376</span><span id="line-2376"> BlockCache bc = cacheConf.getBlockCache().get();</span>
+<span class="source-line-no">2377</span><span id="line-2377"> if (bc instanceof CombinedBlockCache) {</span>
+<span class="source-line-no">2378</span><span id="line-2378"> BlockCache l2 = ((CombinedBlockCache) bc).getSecondLevelCache();</span>
+<span class="source-line-no">2379</span><span id="line-2379"> if (l2 instanceof BucketCache) {</span>
+<span class="source-line-no">2380</span><span id="line-2380"> return Optional.of((BucketCache) l2);</span>
+<span class="source-line-no">2381</span><span id="line-2381"> }</span>
+<span class="source-line-no">2382</span><span id="line-2382"> } else if (bc instanceof BucketCache) {</span>
+<span class="source-line-no">2383</span><span id="line-2383"> return Optional.of((BucketCache) bc);</span>
+<span class="source-line-no">2384</span><span id="line-2384"> }</span>
+<span class="source-line-no">2385</span><span id="line-2385"> }</span>
+<span class="source-line-no">2386</span><span id="line-2386"> return Optional.empty();</span>
+<span class="source-line-no">2387</span><span id="line-2387"> }</span>
+<span class="source-line-no">2388</span><span id="line-2388"></span>
+<span class="source-line-no">2389</span><span id="line-2389"> @Override</span>
+<span class="source-line-no">2390</span><span id="line-2390"> public void notifyFileCachingCompleted(Path fileName, int totalBlockCount, int dataBlockCount,</span>
+<span class="source-line-no">2391</span><span id="line-2391"> long size) {</span>
+<span class="source-line-no">2392</span><span id="line-2392"> // block eviction may be happening in the background as prefetch runs,</span>
+<span class="source-line-no">2393</span><span id="line-2393"> // so we need to count all blocks for this file in the backing map under</span>
+<span class="source-line-no">2394</span><span id="line-2394"> // a read lock for the block offset</span>
+<span class="source-line-no">2395</span><span id="line-2395"> final List<ReentrantReadWriteLock> locks = new ArrayList<>();</span>
+<span class="source-line-no">2396</span><span id="line-2396"> LOG.debug("Notifying caching completed for file {}, with total blocks {}, and data blocks {}",</span>
+<span class="source-line-no">2397</span><span id="line-2397"> fileName, totalBlockCount, dataBlockCount);</span>
+<span class="source-line-no">2398</span><span id="line-2398"> try {</span>
+<span class="source-line-no">2399</span><span id="line-2399"> int count = 0;</span>
+<span class="source-line-no">2400</span><span id="line-2400"> LOG.debug("iterating over {} entries in the backing map", backingMap.size());</span>
+<span class="source-line-no">2401</span><span id="line-2401"> Set<BlockCacheKey> result = getAllCacheKeysForFile(fileName.getName(), 0, Long.MAX_VALUE);</span>
+<span class="source-line-no">2402</span><span id="line-2402"> if (result.isEmpty() && StoreFileInfo.isReference(fileName)) {</span>
+<span class="source-line-no">2403</span><span id="line-2403"> result = getAllCacheKeysForFile(</span>
+<span class="source-line-no">2404</span><span id="line-2404"> StoreFileInfo.getReferredToRegionAndFile(fileName.getName()).getSecond(), 0,</span>
+<span class="source-line-no">2405</span><span id="line-2405"> Long.MAX_VALUE);</span>
+<span class="source-line-no">2406</span><span id="line-2406"> }</span>
+<span class="source-line-no">2407</span><span id="line-2407"> for (BlockCacheKey entry : result) {</span>
+<span class="source-line-no">2408</span><span id="line-2408"> LOG.debug("found block for file {} in the backing map. Acquiring read lock for offset {}",</span>
+<span class="source-line-no">2409</span><span id="line-2409"> fileName.getName(), entry.getOffset());</span>
+<span class="source-line-no">2410</span><span id="line-2410"> ReentrantReadWriteLock lock = offsetLock.getLock(entry.getOffset());</span>
+<span class="source-line-no">2411</span><span id="line-2411"> lock.readLock().lock();</span>
+<span class="source-line-no">2412</span><span id="line-2412"> locks.add(lock);</span>
+<span class="source-line-no">2413</span><span id="line-2413"> if (backingMap.containsKey(entry) && entry.getBlockType().isData()) {</span>
+<span class="source-line-no">2414</span><span id="line-2414"> count++;</span>
+<span class="source-line-no">2415</span><span id="line-2415"> }</span>
+<span class="source-line-no">2416</span><span id="line-2416"> }</span>
+<span class="source-line-no">2417</span><span id="line-2417"> // BucketCache would only have data blocks</span>
+<span class="source-line-no">2418</span><span id="line-2418"> if (dataBlockCount == count) {</span>
+<span class="source-line-no">2419</span><span id="line-2419"> LOG.debug("File {} has now been fully cached.", fileName);</span>
+<span class="source-line-no">2420</span><span id="line-2420"> fileCacheCompleted(fileName, size);</span>
+<span class="source-line-no">2421</span><span id="line-2421"> } else {</span>
+<span class="source-line-no">2422</span><span id="line-2422"> LOG.debug(</span>
+<span class="source-line-no">2423</span><span id="line-2423"> "Prefetch executor completed for {}, but only {} data blocks were cached. "</span>
+<span class="source-line-no">2424</span><span id="line-2424"> + "Total data blocks for file: {}. "</span>
+<span class="source-line-no">2425</span><span id="line-2425"> + "Checking for blocks pending cache in cache writer queue.",</span>
+<span class="source-line-no">2426</span><span id="line-2426"> fileName, count, dataBlockCount);</span>
+<span class="source-line-no">2427</span><span id="line-2427"> if (ramCache.hasBlocksForFile(fileName.getName())) {</span>
+<span class="source-line-no">2428</span><span id="line-2428"> for (ReentrantReadWriteLock lock : locks) {</span>
+<span class="source-line-no">2429</span><span id="line-2429"> lock.readLock().unlock();</span>
+<span class="source-line-no">2430</span><span id="line-2430"> }</span>
+<span class="source-line-no">2431</span><span id="line-2431"> locks.clear();</span>
+<span class="source-line-no">2432</span><span id="line-2432"> LOG.debug("There are still blocks pending caching for file {}. Will sleep 100ms "</span>
+<span class="source-line-no">2433</span><span id="line-2433"> + "and try the verification again.", fileName);</span>
+<span class="source-line-no">2434</span><span id="line-2434"> Thread.sleep(100);</span>
+<span class="source-line-no">2435</span><span id="line-2435"> notifyFileCachingCompleted(fileName, totalBlockCount, dataBlockCount, size);</span>
+<span class="source-line-no">2436</span><span id="line-2436"> } else {</span>
+<span class="source-line-no">2437</span><span id="line-2437"> LOG.info(</span>
+<span class="source-line-no">2438</span><span id="line-2438"> "The total block count was {}. We found only {} data blocks cached from "</span>
+<span class="source-line-no">2439</span><span id="line-2439"> + "a total of {} data blocks for file {}, "</span>
+<span class="source-line-no">2440</span><span id="line-2440"> + "but no blocks pending caching. Maybe cache is full or evictions "</span>
+<span class="source-line-no">2441</span><span id="line-2441"> + "happened concurrently to cache prefetch.",</span>
+<span class="source-line-no">2442</span><span id="line-2442"> totalBlockCount, count, dataBlockCount, fileName);</span>
+<span class="source-line-no">2443</span><span id="line-2443"> }</span>
+<span class="source-line-no">2444</span><span id="line-2444"> }</span>
+<span class="source-line-no">2445</span><span id="line-2445"> } catch (InterruptedException e) {</span>
+<span class="source-line-no">2446</span><span id="line-2446"> throw new RuntimeException(e);</span>
+<span class="source-line-no">2447</span><span id="line-2447"> } finally {</span>
+<span class="source-line-no">2448</span><span id="line-2448"> for (ReentrantReadWriteLock lock : locks) {</span>
+<span class="source-line-no">2449</span><span id="line-2449"> lock.readLock().unlock();</span>
+<span class="source-line-no">2450</span><span id="line-2450"> }</span>
+<span class="source-line-no">2451</span><span id="line-2451"> }</span>
+<span class="source-line-no">2452</span><span id="line-2452"> }</span>
+<span class="source-line-no">2453</span><span id="line-2453"></span>
+<span class="source-line-no">2454</span><span id="line-2454"> @Override</span>
+<span class="source-line-no">2455</span><span id="line-2455"> public Optional<Boolean> blockFitsIntoTheCache(HFileBlock block) {</span>
+<span class="source-line-no">2456</span><span id="line-2456"> if (!isCacheInitialized("blockFitsIntoTheCache")) {</span>
<span class="source-line-no">2457</span><span id="line-2457"> return Optional.of(false);</span>
<span class="source-line-no">2458</span><span id="line-2458"> }</span>
-<span class="source-line-no">2459</span><span id="line-2459"> // if we don't have the file in fullyCachedFiles, we should cache it</span>
-<span class="source-line-no">2460</span><span id="line-2460"> return Optional.of(!fullyCachedFiles.containsKey(fileName));</span>
-<span class="source-line-no">2461</span><span id="line-2461"> }</span>
-<span class="source-line-no">2462</span><span id="line-2462"></span>
-<span class="source-line-no">2463</span><span id="line-2463"> @Override</span>
-<span class="source-line-no">2464</span><span id="line-2464"> public Optional<Boolean> shouldCacheBlock(BlockCacheKey key, long maxTimestamp,</span>
-<span class="source-line-no">2465</span><span id="line-2465"> Configuration conf) {</span>
-<span class="source-line-no">2466</span><span id="line-2466"> DataTieringManager dataTieringManager = DataTieringManager.getInstance();</span>
-<span class="source-line-no">2467</span><span id="line-2467"> if (dataTieringManager != null && !dataTieringManager.isHotData(maxTimestamp, conf)) {</span>
-<span class="source-line-no">2468</span><span id="line-2468"> LOG.debug("Data tiering is enabled for file: '{}' and it is not hot data",</span>
-<span class="source-line-no">2469</span><span id="line-2469"> key.getHfileName());</span>
-<span class="source-line-no">2470</span><span id="line-2470"> return Optional.of(false);</span>
-<span class="source-line-no">2471</span><span id="line-2471"> }</span>
-<span class="source-line-no">2472</span><span id="line-2472"> return Optional.of(true);</span>
-<span class="source-line-no">2473</span><span id="line-2473"> }</span>
-<span class="source-line-no">2474</span><span id="line-2474"></span>
-<span class="source-line-no">2475</span><span id="line-2475"> @Override</span>
-<span class="source-line-no">2476</span><span id="line-2476"> public Optional<Boolean> isAlreadyCached(BlockCacheKey key) {</span>
-<span class="source-line-no">2477</span><span id="line-2477"> boolean foundKey = backingMap.containsKey(key);</span>
-<span class="source-line-no">2478</span><span id="line-2478"> // if there's no entry for the key itself, we need to check if this key is for a reference,</span>
-<span class="source-line-no">2479</span><span id="line-2479"> // and if so, look for a block from the referenced file using this getBlockForReference method.</span>
-<span class="source-line-no">2480</span><span id="line-2480"> return Optional.of(foundKey ? true : getBlockForReference(key) != null);</span>
-<span class="source-line-no">2481</span><span id="line-2481"> }</span>
-<span class="source-line-no">2482</span><span id="line-2482"></span>
-<span class="source-line-no">2483</span><span id="line-2483"> @Override</span>
-<span class="source-line-no">2484</span><span id="line-2484"> public Optional<Integer> getBlockSize(BlockCacheKey key) {</span>
-<span class="source-line-no">2485</span><span id="line-2485"> BucketEntry entry = backingMap.get(key);</span>
-<span class="source-line-no">2486</span><span id="line-2486"> if (entry == null) {</span>
-<span class="source-line-no">2487</span><span id="line-2487"> // the key might be for a reference tha we had found the block from the referenced file in</span>
-<span class="source-line-no">2488</span><span id="line-2488"> // the cache when we first tried to cache it.</span>
-<span class="source-line-no">2489</span><span id="line-2489"> entry = getBlockForReference(key);</span>
-<span class="source-line-no">2490</span><span id="line-2490"> return entry == null ? Optional.empty() : Optional.of(entry.getOnDiskSizeWithHeader());</span>
-<span class="source-line-no">2491</span><span id="line-2491"> } else {</span>
-<span class="source-line-no">2492</span><span id="line-2492"> return Optional.of(entry.getOnDiskSizeWithHeader());</span>
-<span class="source-line-no">2493</span><span id="line-2493"> }</span>
-<span class="source-line-no">2494</span><span id="line-2494"></span>
+<span class="source-line-no">2459</span><span id="line-2459"></span>
+<span class="source-line-no">2460</span><span id="line-2460"> long currentUsed = bucketAllocator.getUsedSize();</span>
+<span class="source-line-no">2461</span><span id="line-2461"> boolean result = (currentUsed + block.getOnDiskSizeWithHeader()) < acceptableSize();</span>
+<span class="source-line-no">2462</span><span id="line-2462"> return Optional.of(result);</span>
+<span class="source-line-no">2463</span><span id="line-2463"> }</span>
+<span class="source-line-no">2464</span><span id="line-2464"></span>
+<span class="source-line-no">2465</span><span id="line-2465"> @Override</span>
+<span class="source-line-no">2466</span><span id="line-2466"> public Optional<Boolean> shouldCacheFile(HFileInfo hFileInfo, Configuration conf) {</span>
+<span class="source-line-no">2467</span><span id="line-2467"> String fileName = hFileInfo.getHFileContext().getHFileName();</span>
+<span class="source-line-no">2468</span><span id="line-2468"> DataTieringManager dataTieringManager = DataTieringManager.getInstance();</span>
+<span class="source-line-no">2469</span><span id="line-2469"> if (dataTieringManager != null && !dataTieringManager.isHotData(hFileInfo, conf)) {</span>
+<span class="source-line-no">2470</span><span id="line-2470"> LOG.debug("Data tiering is enabled for file: '{}' and it is not hot data", fileName);</span>
+<span class="source-line-no">2471</span><span id="line-2471"> return Optional.of(false);</span>
+<span class="source-line-no">2472</span><span id="line-2472"> }</span>
+<span class="source-line-no">2473</span><span id="line-2473"> // if we don't have the file in fullyCachedFiles, we should cache it</span>
+<span class="source-line-no">2474</span><span id="line-2474"> return Optional.of(!fullyCachedFiles.containsKey(fileName));</span>
+<span class="source-line-no">2475</span><span id="line-2475"> }</span>
+<span class="source-line-no">2476</span><span id="line-2476"></span>
+<span class="source-line-no">2477</span><span id="line-2477"> @Override</span>
+<span class="source-line-no">2478</span><span id="line-2478"> public Optional<Boolean> shouldCacheBlock(BlockCacheKey key, long maxTimestamp,</span>
+<span class="source-line-no">2479</span><span id="line-2479"> Configuration conf) {</span>
+<span class="source-line-no">2480</span><span id="line-2480"> DataTieringManager dataTieringManager = DataTieringManager.getInstance();</span>
+<span class="source-line-no">2481</span><span id="line-2481"> if (dataTieringManager != null && !dataTieringManager.isHotData(maxTimestamp, conf)) {</span>
+<span class="source-line-no">2482</span><span id="line-2482"> LOG.debug("Data tiering is enabled for file: '{}' and it is not hot data",</span>
+<span class="source-line-no">2483</span><span id="line-2483"> key.getHfileName());</span>
+<span class="source-line-no">2484</span><span id="line-2484"> return Optional.of(false);</span>
+<span class="source-line-no">2485</span><span id="line-2485"> }</span>
+<span class="source-line-no">2486</span><span id="line-2486"> return Optional.of(true);</span>
+<span class="source-line-no">2487</span><span id="line-2487"> }</span>
+<span class="source-line-no">2488</span><span id="line-2488"></span>
+<span class="source-line-no">2489</span><span id="line-2489"> @Override</span>
+<span class="source-line-no">2490</span><span id="line-2490"> public Optional<Boolean> isAlreadyCached(BlockCacheKey key) {</span>
+<span class="source-line-no">2491</span><span id="line-2491"> boolean foundKey = backingMap.containsKey(key);</span>
+<span class="source-line-no">2492</span><span id="line-2492"> // if there's no entry for the key itself, we need to check if this key is for a reference,</span>
+<span class="source-line-no">2493</span><span id="line-2493"> // and if so, look for a block from the referenced file using this getBlockForReference method.</span>
+<span class="source-line-no">2494</span><span id="line-2494"> return Optional.of(foundKey ? true : getBlockForReference(key) != null);</span>
<span class="source-line-no">2495</span><span id="line-2495"> }</span>
<span class="source-line-no">2496</span><span id="line-2496"></span>
-<span class="source-line-no">2497</span><span id="line-2497"> boolean isCacheInitialized(String api) {</span>
-<span class="source-line-no">2498</span><span id="line-2498"> if (cacheState == CacheState.INITIALIZING) {</span>
-<span class="source-line-no">2499</span><span id="line-2499"> LOG.warn("Bucket initialisation pending at {}", api);</span>
-<span class="source-line-no">2500</span><span id="line-2500"> return false;</span>
-<span class="source-line-no">2501</span><span id="line-2501"> }</span>
-<span class="source-line-no">2502</span><span id="line-2502"> return true;</span>
-<span class="source-line-no">2503</span><span id="line-2503"> }</span>
-<span class="source-line-no">2504</span><span id="line-2504"></span>
-<span class="source-line-no">2505</span><span id="line-2505"> @Override</span>
-<span class="source-line-no">2506</span><span id="line-2506"> public boolean waitForCacheInitialization(long timeout) {</span>
-<span class="source-line-no">2507</span><span id="line-2507"> while (cacheState == CacheState.INITIALIZING) {</span>
-<span class="source-line-no">2508</span><span id="line-2508"> if (timeout <= 0) {</span>
-<span class="source-line-no">2509</span><span id="line-2509"> break;</span>
-<span class="source-line-no">2510</span><span id="line-2510"> }</span>
-<span class="source-line-no">2511</span><span id="line-2511"> try {</span>
-<span class="source-line-no">2512</span><span id="line-2512"> Thread.sleep(100);</span>
-<span class="source-line-no">2513</span><span id="line-2513"> } catch (InterruptedException e) {</span>
-<span class="source-line-no">2514</span><span id="line-2514"> LOG.warn("Interrupted while waiting for cache initialization", e);</span>
-<span class="source-line-no">2515</span><span id="line-2515"> Thread.currentThread().interrupt();</span>
-<span class="source-line-no">2516</span><span id="line-2516"> break;</span>
-<span class="source-line-no">2517</span><span id="line-2517"> }</span>
-<span class="source-line-no">2518</span><span id="line-2518"> timeout -= 100;</span>
-<span class="source-line-no">2519</span><span id="line-2519"> }</span>
-<span class="source-line-no">2520</span><span id="line-2520"> return isCacheEnabled();</span>
-<span class="source-line-no">2521</span><span id="line-2521"> }</span>
-<span class="source-line-no">2522</span><span id="line-2522">}</span>
+<span class="source-line-no">2497</span><span id="line-2497"> @Override</span>
+<span class="source-line-no">2498</span><span id="line-2498"> public Optional<Integer> getBlockSize(BlockCacheKey key) {</span>
+<span class="source-line-no">2499</span><span id="line-2499"> BucketEntry entry = backingMap.get(key);</span>
+<span class="source-line-no">2500</span><span id="line-2500"> if (entry == null) {</span>
+<span class="source-line-no">2501</span><span id="line-2501"> // the key might be for a reference tha we had found the block from the referenced file in</span>
+<span class="source-line-no">2502</span><span id="line-2502"> // the cache when we first tried to cache it.</span>
+<span class="source-line-no">2503</span><span id="line-2503"> entry = getBlockForReference(key);</span>
+<span class="source-line-no">2504</span><span id="line-2504"> return entry == null ? Optional.empty() : Optional.of(entry.getOnDiskSizeWithHeader());</span>
+<span class="source-line-no">2505</span><span id="line-2505"> } else {</span>
+<span class="source-line-no">2506</span><span id="line-2506"> return Optional.of(entry.getOnDiskSizeWithHeader());</span>
+<span class="source-line-no">2507</span><span id="line-2507"> }</span>
+<span class="source-line-no">2508</span><span id="line-2508"></span>
+<span class="source-line-no">2509</span><span id="line-2509"> }</span>
+<span class="source-line-no">2510</span><span id="line-2510"></span>
+<span class="source-line-no">2511</span><span id="line-2511"> boolean isCacheInitialized(String api) {</span>
+<span class="source-line-no">2512</span><span id="line-2512"> if (cacheState == CacheState.INITIALIZING) {</span>
+<span class="source-line-no">2513</span><span id="line-2513"> LOG.warn("Bucket initialisation pending at {}", api);</span>
+<span class="source-line-no">2514</span><span id="line-2514"> return false;</span>
+<span class="source-line-no">2515</span><span id="line-2515"> }</span>
+<span class="source-line-no">2516</span><span id="line-2516"> return true;</span>
+<span class="source-line-no">2517</span><span id="line-2517"> }</span>
+<span class="source-line-no">2518</span><span id="line-2518"></span>
+<span class="source-line-no">2519</span><span id="line-2519"> @Override</span>
+<span class="source-line-no">2520</span><span id="line-2520"> public boolean waitForCacheInitialization(long timeout) {</span>
+<span class="source-line-no">2521</span><span id="line-2521"> while (cacheState == CacheState.INITIALIZING) {</span>
+<span class="source-line-no">2522</span><span id="line-2522"> if (timeout <= 0) {</span>
+<span class="source-line-no">2523</span><span id="line-2523"> break;</span>
+<span class="source-line-no">2524</span><span id="line-2524"> }</span>
+<span class="source-line-no">2525</span><span id="line-2525"> try {</span>
+<span class="source-line-no">2526</span><span id="line-2526"> Thread.sleep(100);</span>
+<span class="source-line-no">2527</span><span id="line-2527"> } catch (InterruptedException e) {</span>
+<span class="source-line-no">2528</span><span id="line-2528"> LOG.warn("Interrupted while waiting for cache initialization", e);</span>
+<span class="source-line-no">2529</span><span id="line-2529"> Thread.currentThread().interrupt();</span>
+<span class="source-line-no">2530</span><span id="line-2530"> break;</span>
+<span class="source-line-no">2531</span><span id="line-2531"> }</span>
+<span class="source-line-no">2532</span><span id="line-2532"> timeout -= 100;</span>
+<span class="source-line-no">2533</span><span id="line-2533"> }</span>
+<span class="source-line-no">2534</span><span id="line-2534"> return isCacheEnabled();</span>
+<span class="source-line-no">2535</span><span id="line-2535"> }</span>
+<span class="source-line-no">2536</span><span id="line-2536">}</span>
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMCache.html b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMCache.html
index 8e2b599833c..53619245844 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMCache.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMCache.html
@@ -1624,915 +1624,929 @@
<span class="source-line-no">1611</span><span id="line-1611"> int pblen = ProtobufMagic.lengthOfPBMagic();</span>
<span class="source-line-no">1612</span><span id="line-1612"> byte[] pbuf = new byte[pblen];</span>
<span class="source-line-no">1613</span><span id="line-1613"> IOUtils.readFully(in, pbuf, 0, pblen);</span>
-<span class="source-line-no">1614</span><span id="line-1614"> if (ProtobufMagic.isPBMagicPrefix(pbuf)) {</span>
-<span class="source-line-no">1615</span><span id="line-1615"> LOG.info("Reading old format of persistence.");</span>
-<span class="source-line-no">1616</span><span id="line-1616"> // The old non-chunked version of backing map persistence.</span>
-<span class="source-line-no">1617</span><span id="line-1617"> parsePB(BucketCacheProtos.BucketCacheEntry.parseDelimitedFrom(in));</span>
-<span class="source-line-no">1618</span><span id="line-1618"> } else if (Arrays.equals(pbuf, BucketProtoUtils.PB_MAGIC_V2)) {</span>
-<span class="source-line-no">1619</span><span id="line-1619"> // The new persistence format of chunked persistence.</span>
-<span class="source-line-no">1620</span><span id="line-1620"> LOG.info("Reading new chunked format of persistence.");</span>
-<span class="source-line-no">1621</span><span id="line-1621"> retrieveChunkedBackingMap(in);</span>
-<span class="source-line-no">1622</span><span id="line-1622"> } else {</span>
-<span class="source-line-no">1623</span><span id="line-1623"> // In 3.0 we have enough flexibility to dump the old cache data.</span>
-<span class="source-line-no">1624</span><span id="line-1624"> // TODO: In 2.x line, this might need to be filled in to support reading the old format</span>
-<span class="source-line-no">1625</span><span id="line-1625"> throw new IOException(</span>
-<span class="source-line-no">1626</span><span id="line-1626"> "Persistence file does not start with protobuf magic number. " + persistencePath);</span>
-<span class="source-line-no">1627</span><span id="line-1627"> }</span>
-<span class="source-line-no">1628</span><span id="line-1628"> bucketAllocator = new BucketAllocator(cacheCapacity, bucketSizes, backingMap, realCacheSize);</span>
-<span class="source-line-no">1629</span><span id="line-1629"> blockNumber.add(backingMap.size());</span>
-<span class="source-line-no">1630</span><span id="line-1630"> LOG.info("Bucket cache retrieved from file successfully with size: {}", backingMap.size());</span>
-<span class="source-line-no">1631</span><span id="line-1631"> }</span>
-<span class="source-line-no">1632</span><span id="line-1632"> }</span>
-<span class="source-line-no">1633</span><span id="line-1633"></span>
-<span class="source-line-no">1634</span><span id="line-1634"> private void updateRegionSizeMapWhileRetrievingFromFile() {</span>
-<span class="source-line-no">1635</span><span id="line-1635"> // Update the regionCachedSize with the region size while restarting the region server</span>
-<span class="source-line-no">1636</span><span id="line-1636"> if (LOG.isDebugEnabled()) {</span>
-<span class="source-line-no">1637</span><span id="line-1637"> LOG.debug("Updating region size map after retrieving cached file list");</span>
-<span class="source-line-no">1638</span><span id="line-1638"> dumpPrefetchList();</span>
-<span class="source-line-no">1639</span><span id="line-1639"> }</span>
-<span class="source-line-no">1640</span><span id="line-1640"> regionCachedSize.clear();</span>
-<span class="source-line-no">1641</span><span id="line-1641"> fullyCachedFiles.forEach((hFileName, hFileSize) -> {</span>
-<span class="source-line-no">1642</span><span id="line-1642"> // Get the region name for each file</span>
-<span class="source-line-no">1643</span><span id="line-1643"> String regionEncodedName = hFileSize.getFirst();</span>
-<span class="source-line-no">1644</span><span id="line-1644"> long cachedFileSize = hFileSize.getSecond();</span>
-<span class="source-line-no">1645</span><span id="line-1645"> regionCachedSize.merge(regionEncodedName, cachedFileSize,</span>
-<span class="source-line-no">1646</span><span id="line-1646"> (oldpf, fileSize) -> oldpf + fileSize);</span>
-<span class="source-line-no">1647</span><span id="line-1647"> });</span>
-<span class="source-line-no">1648</span><span id="line-1648"> }</span>
-<span class="source-line-no">1649</span><span id="line-1649"></span>
-<span class="source-line-no">1650</span><span id="line-1650"> private void dumpPrefetchList() {</span>
-<span class="source-line-no">1651</span><span id="line-1651"> for (Map.Entry<String, Pair<String, Long>> outerEntry : fullyCachedFiles.entrySet()) {</span>
-<span class="source-line-no">1652</span><span id="line-1652"> LOG.debug("Cached File Entry:<{},<{},{}>>", outerEntry.getKey(),</span>
-<span class="source-line-no">1653</span><span id="line-1653"> outerEntry.getValue().getFirst(), outerEntry.getValue().getSecond());</span>
-<span class="source-line-no">1654</span><span id="line-1654"> }</span>
+<span class="source-line-no">1614</span><span id="line-1614"></span>
+<span class="source-line-no">1615</span><span id="line-1615"> if (ProtobufMagic.isPBMagicPrefix(pbuf)) {</span>
+<span class="source-line-no">1616</span><span id="line-1616"> LOG.info("Reading old format of persistence.");</span>
+<span class="source-line-no">1617</span><span id="line-1617"> // The old non-chunked version of backing map persistence.</span>
+<span class="source-line-no">1618</span><span id="line-1618"> BucketCacheProtos.BucketCacheEntry cacheEntry =</span>
+<span class="source-line-no">1619</span><span id="line-1619"> BucketCacheProtos.BucketCacheEntry.parseDelimitedFrom(in);</span>
+<span class="source-line-no">1620</span><span id="line-1620"> if (cacheEntry == null) {</span>
+<span class="source-line-no">1621</span><span id="line-1621"> throw new IOException(</span>
+<span class="source-line-no">1622</span><span id="line-1622"> "Failed to parse cache entry from persistence file: " + persistencePath);</span>
+<span class="source-line-no">1623</span><span id="line-1623"> }</span>
+<span class="source-line-no">1624</span><span id="line-1624"> parsePB(cacheEntry);</span>
+<span class="source-line-no">1625</span><span id="line-1625"> } else if (Arrays.equals(pbuf, BucketProtoUtils.PB_MAGIC_V2)) {</span>
+<span class="source-line-no">1626</span><span id="line-1626"> // The new persistence format of chunked persistence.</span>
+<span class="source-line-no">1627</span><span id="line-1627"> LOG.info("Reading new chunked format of persistence.");</span>
+<span class="source-line-no">1628</span><span id="line-1628"> retrieveChunkedBackingMap(in);</span>
+<span class="source-line-no">1629</span><span id="line-1629"> } else {</span>
+<span class="source-line-no">1630</span><span id="line-1630"> // In 3.0 we have enough flexibility to dump the old cache data.</span>
+<span class="source-line-no">1631</span><span id="line-1631"> // TODO: In 2.x line, this might need to be filled in to support reading the old format</span>
+<span class="source-line-no">1632</span><span id="line-1632"> throw new IOException(</span>
+<span class="source-line-no">1633</span><span id="line-1633"> "Persistence file does not start with protobuf magic number. " + persistencePath);</span>
+<span class="source-line-no">1634</span><span id="line-1634"> }</span>
+<span class="source-line-no">1635</span><span id="line-1635"> bucketAllocator = new BucketAllocator(cacheCapacity, bucketSizes, backingMap, realCacheSize);</span>
+<span class="source-line-no">1636</span><span id="line-1636"> blockNumber.add(backingMap.size());</span>
+<span class="source-line-no">1637</span><span id="line-1637"> LOG.info("Bucket cache retrieved from file successfully with size: {}", backingMap.size());</span>
+<span class="source-line-no">1638</span><span id="line-1638"> }</span>
+<span class="source-line-no">1639</span><span id="line-1639"> }</span>
+<span class="source-line-no">1640</span><span id="line-1640"></span>
+<span class="source-line-no">1641</span><span id="line-1641"> private void updateRegionSizeMapWhileRetrievingFromFile() {</span>
+<span class="source-line-no">1642</span><span id="line-1642"> // Update the regionCachedSize with the region size while restarting the region server</span>
+<span class="source-line-no">1643</span><span id="line-1643"> if (LOG.isDebugEnabled()) {</span>
+<span class="source-line-no">1644</span><span id="line-1644"> LOG.debug("Updating region size map after retrieving cached file list");</span>
+<span class="source-line-no">1645</span><span id="line-1645"> dumpPrefetchList();</span>
+<span class="source-line-no">1646</span><span id="line-1646"> }</span>
+<span class="source-line-no">1647</span><span id="line-1647"> regionCachedSize.clear();</span>
+<span class="source-line-no">1648</span><span id="line-1648"> fullyCachedFiles.forEach((hFileName, hFileSize) -> {</span>
+<span class="source-line-no">1649</span><span id="line-1649"> // Get the region name for each file</span>
+<span class="source-line-no">1650</span><span id="line-1650"> String regionEncodedName = hFileSize.getFirst();</span>
+<span class="source-line-no">1651</span><span id="line-1651"> long cachedFileSize = hFileSize.getSecond();</span>
+<span class="source-line-no">1652</span><span id="line-1652"> regionCachedSize.merge(regionEncodedName, cachedFileSize,</span>
+<span class="source-line-no">1653</span><span id="line-1653"> (oldpf, fileSize) -> oldpf + fileSize);</span>
+<span class="source-line-no">1654</span><span id="line-1654"> });</span>
<span class="source-line-no">1655</span><span id="line-1655"> }</span>
<span class="source-line-no">1656</span><span id="line-1656"></span>
-<span class="source-line-no">1657</span><span id="line-1657"> private void verifyCapacityAndClasses(long capacitySize, String ioclass, String mapclass)</span>
-<span class="source-line-no">1658</span><span id="line-1658"> throws IOException {</span>
-<span class="source-line-no">1659</span><span id="line-1659"> if (capacitySize != cacheCapacity) {</span>
-<span class="source-line-no">1660</span><span id="line-1660"> throw new IOException("Mismatched cache capacity:" + StringUtils.byteDesc(capacitySize)</span>
-<span class="source-line-no">1661</span><span id="line-1661"> + ", expected: " + StringUtils.byteDesc(cacheCapacity));</span>
-<span class="source-line-no">1662</span><span id="line-1662"> }</span>
-<span class="source-line-no">1663</span><span id="line-1663"> if (!ioEngine.getClass().getName().equals(ioclass)) {</span>
-<span class="source-line-no">1664</span><span id="line-1664"> throw new IOException("Class name for IO engine mismatch: " + ioclass + ", expected:"</span>
-<span class="source-line-no">1665</span><span id="line-1665"> + ioEngine.getClass().getName());</span>
-<span class="source-line-no">1666</span><span id="line-1666"> }</span>
-<span class="source-line-no">1667</span><span id="line-1667"> if (!backingMap.getClass().getName().equals(mapclass)) {</span>
-<span class="source-line-no">1668</span><span id="line-1668"> throw new IOException("Class name for cache map mismatch: " + mapclass + ", expected:"</span>
-<span class="source-line-no">1669</span><span id="line-1669"> + backingMap.getClass().getName());</span>
-<span class="source-line-no">1670</span><span id="line-1670"> }</span>
-<span class="source-line-no">1671</span><span id="line-1671"> }</span>
-<span class="source-line-no">1672</span><span id="line-1672"></span>
-<span class="source-line-no">1673</span><span id="line-1673"> private void verifyFileIntegrity(BucketCacheProtos.BucketCacheEntry proto) {</span>
-<span class="source-line-no">1674</span><span id="line-1674"> try {</span>
-<span class="source-line-no">1675</span><span id="line-1675"> if (proto.hasChecksum()) {</span>
-<span class="source-line-no">1676</span><span id="line-1676"> ((PersistentIOEngine) ioEngine).verifyFileIntegrity(proto.getChecksum().toByteArray(),</span>
-<span class="source-line-no">1677</span><span id="line-1677"> algorithm);</span>
-<span class="source-line-no">1678</span><span id="line-1678"> }</span>
-<span class="source-line-no">1679</span><span id="line-1679"> backingMapValidated.set(true);</span>
-<span class="source-line-no">1680</span><span id="line-1680"> } catch (IOException e) {</span>
-<span class="source-line-no">1681</span><span id="line-1681"> LOG.warn("Checksum for cache file failed. "</span>
-<span class="source-line-no">1682</span><span id="line-1682"> + "We need to validate each cache key in the backing map. "</span>
-<span class="source-line-no">1683</span><span id="line-1683"> + "This may take some time, so we'll do it in a background thread,");</span>
-<span class="source-line-no">1684</span><span id="line-1684"></span>
-<span class="source-line-no">1685</span><span id="line-1685"> Runnable cacheValidator = () -> {</span>
-<span class="source-line-no">1686</span><span id="line-1686"> while (bucketAllocator == null) {</span>
-<span class="source-line-no">1687</span><span id="line-1687"> try {</span>
-<span class="source-line-no">1688</span><span id="line-1688"> Thread.sleep(50);</span>
-<span class="source-line-no">1689</span><span id="line-1689"> } catch (InterruptedException ex) {</span>
-<span class="source-line-no">1690</span><span id="line-1690"> throw new RuntimeException(ex);</span>
-<span class="source-line-no">1691</span><span id="line-1691"> }</span>
-<span class="source-line-no">1692</span><span id="line-1692"> }</span>
-<span class="source-line-no">1693</span><span id="line-1693"> long startTime = EnvironmentEdgeManager.currentTime();</span>
-<span class="source-line-no">1694</span><span id="line-1694"> int totalKeysOriginally = backingMap.size();</span>
-<span class="source-line-no">1695</span><span id="line-1695"> for (Map.Entry<BlockCacheKey, BucketEntry> keyEntry : backingMap.entrySet()) {</span>
-<span class="source-line-no">1696</span><span id="line-1696"> try {</span>
-<span class="source-line-no">1697</span><span id="line-1697"> ((FileIOEngine) ioEngine).checkCacheTime(keyEntry.getValue());</span>
-<span class="source-line-no">1698</span><span id="line-1698"> } catch (IOException e1) {</span>
-<span class="source-line-no">1699</span><span id="line-1699"> LOG.debug("Check for key {} failed. Evicting.", keyEntry.getKey());</span>
-<span class="source-line-no">1700</span><span id="line-1700"> evictBlock(keyEntry.getKey());</span>
-<span class="source-line-no">1701</span><span id="line-1701"> fileNotFullyCached(keyEntry.getKey(), keyEntry.getValue());</span>
-<span class="source-line-no">1702</span><span id="line-1702"> }</span>
-<span class="source-line-no">1703</span><span id="line-1703"> }</span>
-<span class="source-line-no">1704</span><span id="line-1704"> backingMapValidated.set(true);</span>
-<span class="source-line-no">1705</span><span id="line-1705"> LOG.info("Finished validating {} keys in the backing map. Recovered: {}. This took {}ms.",</span>
-<span class="source-line-no">1706</span><span id="line-1706"> totalKeysOriginally, backingMap.size(),</span>
-<span class="source-line-no">1707</span><span id="line-1707"> (EnvironmentEdgeManager.currentTime() - startTime));</span>
-<span class="source-line-no">1708</span><span id="line-1708"> };</span>
-<span class="source-line-no">1709</span><span id="line-1709"> Thread t = new Thread(cacheValidator);</span>
-<span class="source-line-no">1710</span><span id="line-1710"> t.setDaemon(true);</span>
-<span class="source-line-no">1711</span><span id="line-1711"> t.start();</span>
-<span class="source-line-no">1712</span><span id="line-1712"> }</span>
-<span class="source-line-no">1713</span><span id="line-1713"> }</span>
-<span class="source-line-no">1714</span><span id="line-1714"></span>
-<span class="source-line-no">1715</span><span id="line-1715"> private void updateCacheIndex(BucketCacheProtos.BackingMap chunk,</span>
-<span class="source-line-no">1716</span><span id="line-1716"> java.util.Map<java.lang.Integer, java.lang.String> deserializer) throws IOException {</span>
-<span class="source-line-no">1717</span><span id="line-1717"> Pair<ConcurrentHashMap<BlockCacheKey, BucketEntry>, NavigableSet<BlockCacheKey>> pair2 =</span>
-<span class="source-line-no">1718</span><span id="line-1718"> BucketProtoUtils.fromPB(deserializer, chunk, this::createRecycler);</span>
-<span class="source-line-no">1719</span><span id="line-1719"> backingMap.putAll(pair2.getFirst());</span>
-<span class="source-line-no">1720</span><span id="line-1720"> blocksByHFile.addAll(pair2.getSecond());</span>
-<span class="source-line-no">1721</span><span id="line-1721"> }</span>
-<span class="source-line-no">1722</span><span id="line-1722"></span>
-<span class="source-line-no">1723</span><span id="line-1723"> private void parsePB(BucketCacheProtos.BucketCacheEntry proto) throws IOException {</span>
-<span class="source-line-no">1724</span><span id="line-1724"> Pair<ConcurrentHashMap<BlockCacheKey, BucketEntry>, NavigableSet<BlockCacheKey>> pair =</span>
-<span class="source-line-no">1725</span><span id="line-1725"> BucketProtoUtils.fromPB(proto.getDeserializersMap(), proto.getBackingMap(),</span>
-<span class="source-line-no">1726</span><span id="line-1726"> this::createRecycler);</span>
-<span class="source-line-no">1727</span><span id="line-1727"> backingMap = pair.getFirst();</span>
-<span class="source-line-no">1728</span><span id="line-1728"> blocksByHFile = pair.getSecond();</span>
-<span class="source-line-no">1729</span><span id="line-1729"> fullyCachedFiles.clear();</span>
-<span class="source-line-no">1730</span><span id="line-1730"> fullyCachedFiles.putAll(BucketProtoUtils.fromPB(proto.getCachedFilesMap()));</span>
-<span class="source-line-no">1731</span><span id="line-1731"></span>
-<span class="source-line-no">1732</span><span id="line-1732"> LOG.info("After retrieval Backing map size: {}, fullyCachedFiles size: {}", backingMap.size(),</span>
-<span class="source-line-no">1733</span><span id="line-1733"> fullyCachedFiles.size());</span>
-<span class="source-line-no">1734</span><span id="line-1734"></span>
-<span class="source-line-no">1735</span><span id="line-1735"> verifyFileIntegrity(proto);</span>
-<span class="source-line-no">1736</span><span id="line-1736"> updateRegionSizeMapWhileRetrievingFromFile();</span>
-<span class="source-line-no">1737</span><span id="line-1737"> verifyCapacityAndClasses(proto.getCacheCapacity(), proto.getIoClass(), proto.getMapClass());</span>
-<span class="source-line-no">1738</span><span id="line-1738"> }</span>
-<span class="source-line-no">1739</span><span id="line-1739"></span>
-<span class="source-line-no">1740</span><span id="line-1740"> private void persistChunkedBackingMap(FileOutputStream fos) throws IOException {</span>
-<span class="source-line-no">1741</span><span id="line-1741"> LOG.debug(</span>
-<span class="source-line-no">1742</span><span id="line-1742"> "persistToFile: before persisting backing map size: {}, "</span>
-<span class="source-line-no">1743</span><span id="line-1743"> + "fullycachedFiles size: {}, chunkSize: {}",</span>
-<span class="source-line-no">1744</span><span id="line-1744"> backingMap.size(), fullyCachedFiles.size(), persistenceChunkSize);</span>
-<span class="source-line-no">1745</span><span id="line-1745"></span>
-<span class="source-line-no">1746</span><span id="line-1746"> BucketProtoUtils.serializeAsPB(this, fos, persistenceChunkSize);</span>
-<span class="source-line-no">1747</span><span id="line-1747"></span>
+<span class="source-line-no">1657</span><span id="line-1657"> private void dumpPrefetchList() {</span>
+<span class="source-line-no">1658</span><span id="line-1658"> for (Map.Entry<String, Pair<String, Long>> outerEntry : fullyCachedFiles.entrySet()) {</span>
+<span class="source-line-no">1659</span><span id="line-1659"> LOG.debug("Cached File Entry:<{},<{},{}>>", outerEntry.getKey(),</span>
+<span class="source-line-no">1660</span><span id="line-1660"> outerEntry.getValue().getFirst(), outerEntry.getValue().getSecond());</span>
+<span class="source-line-no">1661</span><span id="line-1661"> }</span>
+<span class="source-line-no">1662</span><span id="line-1662"> }</span>
+<span class="source-line-no">1663</span><span id="line-1663"></span>
+<span class="source-line-no">1664</span><span id="line-1664"> private void verifyCapacityAndClasses(long capacitySize, String ioclass, String mapclass)</span>
+<span class="source-line-no">1665</span><span id="line-1665"> throws IOException {</span>
+<span class="source-line-no">1666</span><span id="line-1666"> if (capacitySize != cacheCapacity) {</span>
+<span class="source-line-no">1667</span><span id="line-1667"> throw new IOException("Mismatched cache capacity:" + StringUtils.byteDesc(capacitySize)</span>
+<span class="source-line-no">1668</span><span id="line-1668"> + ", expected: " + StringUtils.byteDesc(cacheCapacity));</span>
+<span class="source-line-no">1669</span><span id="line-1669"> }</span>
+<span class="source-line-no">1670</span><span id="line-1670"> if (!ioEngine.getClass().getName().equals(ioclass)) {</span>
+<span class="source-line-no">1671</span><span id="line-1671"> throw new IOException("Class name for IO engine mismatch: " + ioclass + ", expected:"</span>
+<span class="source-line-no">1672</span><span id="line-1672"> + ioEngine.getClass().getName());</span>
+<span class="source-line-no">1673</span><span id="line-1673"> }</span>
+<span class="source-line-no">1674</span><span id="line-1674"> if (!backingMap.getClass().getName().equals(mapclass)) {</span>
+<span class="source-line-no">1675</span><span id="line-1675"> throw new IOException("Class name for cache map mismatch: " + mapclass + ", expected:"</span>
+<span class="source-line-no">1676</span><span id="line-1676"> + backingMap.getClass().getName());</span>
+<span class="source-line-no">1677</span><span id="line-1677"> }</span>
+<span class="source-line-no">1678</span><span id="line-1678"> }</span>
+<span class="source-line-no">1679</span><span id="line-1679"></span>
+<span class="source-line-no">1680</span><span id="line-1680"> private void verifyFileIntegrity(BucketCacheProtos.BucketCacheEntry proto) {</span>
+<span class="source-line-no">1681</span><span id="line-1681"> try {</span>
+<span class="source-line-no">1682</span><span id="line-1682"> if (proto.hasChecksum()) {</span>
+<span class="source-line-no">1683</span><span id="line-1683"> ((PersistentIOEngine) ioEngine).verifyFileIntegrity(proto.getChecksum().toByteArray(),</span>
+<span class="source-line-no">1684</span><span id="line-1684"> algorithm);</span>
+<span class="source-line-no">1685</span><span id="line-1685"> }</span>
+<span class="source-line-no">1686</span><span id="line-1686"> backingMapValidated.set(true);</span>
+<span class="source-line-no">1687</span><span id="line-1687"> } catch (IOException e) {</span>
+<span class="source-line-no">1688</span><span id="line-1688"> LOG.warn("Checksum for cache file failed. "</span>
+<span class="source-line-no">1689</span><span id="line-1689"> + "We need to validate each cache key in the backing map. "</span>
+<span class="source-line-no">1690</span><span id="line-1690"> + "This may take some time, so we'll do it in a background thread,");</span>
+<span class="source-line-no">1691</span><span id="line-1691"></span>
+<span class="source-line-no">1692</span><span id="line-1692"> Runnable cacheValidator = () -> {</span>
+<span class="source-line-no">1693</span><span id="line-1693"> while (bucketAllocator == null) {</span>
+<span class="source-line-no">1694</span><span id="line-1694"> try {</span>
+<span class="source-line-no">1695</span><span id="line-1695"> Thread.sleep(50);</span>
+<span class="source-line-no">1696</span><span id="line-1696"> } catch (InterruptedException ex) {</span>
+<span class="source-line-no">1697</span><span id="line-1697"> throw new RuntimeException(ex);</span>
+<span class="source-line-no">1698</span><span id="line-1698"> }</span>
+<span class="source-line-no">1699</span><span id="line-1699"> }</span>
+<span class="source-line-no">1700</span><span id="line-1700"> long startTime = EnvironmentEdgeManager.currentTime();</span>
+<span class="source-line-no">1701</span><span id="line-1701"> int totalKeysOriginally = backingMap.size();</span>
+<span class="source-line-no">1702</span><span id="line-1702"> for (Map.Entry<BlockCacheKey, BucketEntry> keyEntry : backingMap.entrySet()) {</span>
+<span class="source-line-no">1703</span><span id="line-1703"> try {</span>
+<span class="source-line-no">1704</span><span id="line-1704"> ((FileIOEngine) ioEngine).checkCacheTime(keyEntry.getValue());</span>
+<span class="source-line-no">1705</span><span id="line-1705"> } catch (IOException e1) {</span>
+<span class="source-line-no">1706</span><span id="line-1706"> LOG.debug("Check for key {} failed. Evicting.", keyEntry.getKey());</span>
+<span class="source-line-no">1707</span><span id="line-1707"> evictBlock(keyEntry.getKey());</span>
+<span class="source-line-no">1708</span><span id="line-1708"> fileNotFullyCached(keyEntry.getKey(), keyEntry.getValue());</span>
+<span class="source-line-no">1709</span><span id="line-1709"> }</span>
+<span class="source-line-no">1710</span><span id="line-1710"> }</span>
+<span class="source-line-no">1711</span><span id="line-1711"> backingMapValidated.set(true);</span>
+<span class="source-line-no">1712</span><span id="line-1712"> LOG.info("Finished validating {} keys in the backing map. Recovered: {}. This took {}ms.",</span>
+<span class="source-line-no">1713</span><span id="line-1713"> totalKeysOriginally, backingMap.size(),</span>
+<span class="source-line-no">1714</span><span id="line-1714"> (EnvironmentEdgeManager.currentTime() - startTime));</span>
+<span class="source-line-no">1715</span><span id="line-1715"> };</span>
+<span class="source-line-no">1716</span><span id="line-1716"> Thread t = new Thread(cacheValidator);</span>
+<span class="source-line-no">1717</span><span id="line-1717"> t.setDaemon(true);</span>
+<span class="source-line-no">1718</span><span id="line-1718"> t.start();</span>
+<span class="source-line-no">1719</span><span id="line-1719"> }</span>
+<span class="source-line-no">1720</span><span id="line-1720"> }</span>
+<span class="source-line-no">1721</span><span id="line-1721"></span>
+<span class="source-line-no">1722</span><span id="line-1722"> private void updateCacheIndex(BucketCacheProtos.BackingMap chunk,</span>
+<span class="source-line-no">1723</span><span id="line-1723"> java.util.Map<java.lang.Integer, java.lang.String> deserializer) throws IOException {</span>
+<span class="source-line-no">1724</span><span id="line-1724"> Pair<ConcurrentHashMap<BlockCacheKey, BucketEntry>, NavigableSet<BlockCacheKey>> pair2 =</span>
+<span class="source-line-no">1725</span><span id="line-1725"> BucketProtoUtils.fromPB(deserializer, chunk, this::createRecycler);</span>
+<span class="source-line-no">1726</span><span id="line-1726"> backingMap.putAll(pair2.getFirst());</span>
+<span class="source-line-no">1727</span><span id="line-1727"> blocksByHFile.addAll(pair2.getSecond());</span>
+<span class="source-line-no">1728</span><span id="line-1728"> }</span>
+<span class="source-line-no">1729</span><span id="line-1729"></span>
+<span class="source-line-no">1730</span><span id="line-1730"> private void parsePB(BucketCacheProtos.BucketCacheEntry proto) throws IOException {</span>
+<span class="source-line-no">1731</span><span id="line-1731"> Pair<ConcurrentHashMap<BlockCacheKey, BucketEntry>, NavigableSet<BlockCacheKey>> pair =</span>
+<span class="source-line-no">1732</span><span id="line-1732"> BucketProtoUtils.fromPB(proto.getDeserializersMap(), proto.getBackingMap(),</span>
+<span class="source-line-no">1733</span><span id="line-1733"> this::createRecycler);</span>
+<span class="source-line-no">1734</span><span id="line-1734"> backingMap = pair.getFirst();</span>
+<span class="source-line-no">1735</span><span id="line-1735"> blocksByHFile = pair.getSecond();</span>
+<span class="source-line-no">1736</span><span id="line-1736"> fullyCachedFiles.clear();</span>
+<span class="source-line-no">1737</span><span id="line-1737"> fullyCachedFiles.putAll(BucketProtoUtils.fromPB(proto.getCachedFilesMap()));</span>
+<span class="source-line-no">1738</span><span id="line-1738"></span>
+<span class="source-line-no">1739</span><span id="line-1739"> LOG.info("After retrieval Backing map size: {}, fullyCachedFiles size: {}", backingMap.size(),</span>
+<span class="source-line-no">1740</span><span id="line-1740"> fullyCachedFiles.size());</span>
+<span class="source-line-no">1741</span><span id="line-1741"></span>
+<span class="source-line-no">1742</span><span id="line-1742"> verifyFileIntegrity(proto);</span>
+<span class="source-line-no">1743</span><span id="line-1743"> updateRegionSizeMapWhileRetrievingFromFile();</span>
+<span class="source-line-no">1744</span><span id="line-1744"> verifyCapacityAndClasses(proto.getCacheCapacity(), proto.getIoClass(), proto.getMapClass());</span>
+<span class="source-line-no">1745</span><span id="line-1745"> }</span>
+<span class="source-line-no">1746</span><span id="line-1746"></span>
+<span class="source-line-no">1747</span><span id="line-1747"> private void persistChunkedBackingMap(FileOutputStream fos) throws IOException {</span>
<span class="source-line-no">1748</span><span id="line-1748"> LOG.debug(</span>
-<span class="source-line-no">1749</span><span id="line-1749"> "persistToFile: after persisting backing map size: {}, " + "fullycachedFiles size: {}",</span>
-<span class="source-line-no">1750</span><span id="line-1750"> backingMap.size(), fullyCachedFiles.size());</span>
-<span class="source-line-no">1751</span><span id="line-1751"> }</span>
+<span class="source-line-no">1749</span><span id="line-1749"> "persistToFile: before persisting backing map size: {}, "</span>
+<span class="source-line-no">1750</span><span id="line-1750"> + "fullycachedFiles size: {}, chunkSize: {}",</span>
+<span class="source-line-no">1751</span><span id="line-1751"> backingMap.size(), fullyCachedFiles.size(), persistenceChunkSize);</span>
<span class="source-line-no">1752</span><span id="line-1752"></span>
-<span class="source-line-no">1753</span><span id="line-1753"> private void retrieveChunkedBackingMap(FileInputStream in) throws IOException {</span>
-<span class="source-line-no">1754</span><span id="line-1754"> // Read the first chunk that has all the details.</span>
-<span class="source-line-no">1755</span><span id="line-1755"> BucketCacheProtos.BucketCacheEntry cacheEntry =</span>
-<span class="source-line-no">1756</span><span id="line-1756"> BucketCacheProtos.BucketCacheEntry.parseDelimitedFrom(in);</span>
-<span class="source-line-no">1757</span><span id="line-1757"></span>
-<span class="source-line-no">1758</span><span id="line-1758"> fullyCachedFiles.clear();</span>
-<span class="source-line-no">1759</span><span id="line-1759"> fullyCachedFiles.putAll(BucketProtoUtils.fromPB(cacheEntry.getCachedFilesMap()));</span>
-<span class="source-line-no">1760</span><span id="line-1760"></span>
-<span class="source-line-no">1761</span><span id="line-1761"> backingMap.clear();</span>
-<span class="source-line-no">1762</span><span id="line-1762"> blocksByHFile.clear();</span>
-<span class="source-line-no">1763</span><span id="line-1763"></span>
-<span class="source-line-no">1764</span><span id="line-1764"> // Read the backing map entries in batches.</span>
-<span class="source-line-no">1765</span><span id="line-1765"> int numChunks = 0;</span>
-<span class="source-line-no">1766</span><span id="line-1766"> while (in.available() > 0) {</span>
-<span class="source-line-no">1767</span><span id="line-1767"> updateCacheIndex(BucketCacheProtos.BackingMap.parseDelimitedFrom(in),</span>
-<span class="source-line-no">1768</span><span id="line-1768"> cacheEntry.getDeserializersMap());</span>
-<span class="source-line-no">1769</span><span id="line-1769"> numChunks++;</span>
+<span class="source-line-no">1753</span><span id="line-1753"> BucketProtoUtils.serializeAsPB(this, fos, persistenceChunkSize);</span>
+<span class="source-line-no">1754</span><span id="line-1754"></span>
+<span class="source-line-no">1755</span><span id="line-1755"> LOG.debug(</span>
+<span class="source-line-no">1756</span><span id="line-1756"> "persistToFile: after persisting backing map size: {}, " + "fullycachedFiles size: {}",</span>
+<span class="source-line-no">1757</span><span id="line-1757"> backingMap.size(), fullyCachedFiles.size());</span>
+<span class="source-line-no">1758</span><span id="line-1758"> }</span>
+<span class="source-line-no">1759</span><span id="line-1759"></span>
+<span class="source-line-no">1760</span><span id="line-1760"> private void retrieveChunkedBackingMap(FileInputStream in) throws IOException {</span>
+<span class="source-line-no">1761</span><span id="line-1761"> // Read the first chunk that has all the details.</span>
+<span class="source-line-no">1762</span><span id="line-1762"> BucketCacheProtos.BucketCacheEntry cacheEntry =</span>
+<span class="source-line-no">1763</span><span id="line-1763"> BucketCacheProtos.BucketCacheEntry.parseDelimitedFrom(in);</span>
+<span class="source-line-no">1764</span><span id="line-1764"></span>
+<span class="source-line-no">1765</span><span id="line-1765"> // HBASE-29857: Handle case where persistence file is empty.</span>
+<span class="source-line-no">1766</span><span id="line-1766"> // parseDelimitedFrom() returns null when there's no data to read.</span>
+<span class="source-line-no">1767</span><span id="line-1767"> // Note: Corrupted files would throw InvalidProtocolBufferException (subclass of IOException).</span>
+<span class="source-line-no">1768</span><span id="line-1768"> if (cacheEntry == null) {</span>
+<span class="source-line-no">1769</span><span id="line-1769"> throw new IOException("Failed to read cache entry from persistence file (file is empty)");</span>
<span class="source-line-no">1770</span><span id="line-1770"> }</span>
<span class="source-line-no">1771</span><span id="line-1771"></span>
-<span class="source-line-no">1772</span><span id="line-1772"> LOG.info("Retrieved {} of chunks with blockCount = {}.", numChunks, backingMap.size());</span>
-<span class="source-line-no">1773</span><span id="line-1773"> verifyFileIntegrity(cacheEntry);</span>
-<span class="source-line-no">1774</span><span id="line-1774"> verifyCapacityAndClasses(cacheEntry.getCacheCapacity(), cacheEntry.getIoClass(),</span>
-<span class="source-line-no">1775</span><span id="line-1775"> cacheEntry.getMapClass());</span>
-<span class="source-line-no">1776</span><span id="line-1776"> updateRegionSizeMapWhileRetrievingFromFile();</span>
-<span class="source-line-no">1777</span><span id="line-1777"> }</span>
-<span class="source-line-no">1778</span><span id="line-1778"></span>
-<span class="source-line-no">1779</span><span id="line-1779"> /**</span>
-<span class="source-line-no">1780</span><span id="line-1780"> * Check whether we tolerate IO error this time. If the duration of IOEngine throwing errors</span>
-<span class="source-line-no">1781</span><span id="line-1781"> * exceeds ioErrorsDurationTimeTolerated, we will disable the cache</span>
-<span class="source-line-no">1782</span><span id="line-1782"> */</span>
-<span class="source-line-no">1783</span><span id="line-1783"> private void checkIOErrorIsTolerated() {</span>
-<span class="source-line-no">1784</span><span id="line-1784"> long now = EnvironmentEdgeManager.currentTime();</span>
-<span class="source-line-no">1785</span><span id="line-1785"> // Do a single read to a local variable to avoid timing issue - HBASE-24454</span>
-<span class="source-line-no">1786</span><span id="line-1786"> long ioErrorStartTimeTmp = this.ioErrorStartTime;</span>
-<span class="source-line-no">1787</span><span id="line-1787"> if (ioErrorStartTimeTmp > 0) {</span>
-<span class="source-line-no">1788</span><span id="line-1788"> if (isCacheEnabled() && (now - ioErrorStartTimeTmp) > this.ioErrorsTolerationDuration) {</span>
-<span class="source-line-no">1789</span><span id="line-1789"> LOG.error("IO errors duration time has exceeded " + ioErrorsTolerationDuration</span>
-<span class="source-line-no">1790</span><span id="line-1790"> + "ms, disabling cache, please check your IOEngine");</span>
-<span class="source-line-no">1791</span><span id="line-1791"> disableCache();</span>
-<span class="source-line-no">1792</span><span id="line-1792"> }</span>
-<span class="source-line-no">1793</span><span id="line-1793"> } else {</span>
-<span class="source-line-no">1794</span><span id="line-1794"> this.ioErrorStartTime = now;</span>
-<span class="source-line-no">1795</span><span id="line-1795"> }</span>
-<span class="source-line-no">1796</span><span id="line-1796"> }</span>
-<span class="source-line-no">1797</span><span id="line-1797"></span>
-<span class="source-line-no">1798</span><span id="line-1798"> /**</span>
-<span class="source-line-no">1799</span><span id="line-1799"> * Used to shut down the cache -or- turn it off in the case of something broken.</span>
-<span class="source-line-no">1800</span><span id="line-1800"> */</span>
-<span class="source-line-no">1801</span><span id="line-1801"> private void disableCache() {</span>
-<span class="source-line-no">1802</span><span id="line-1802"> if (!isCacheEnabled()) {</span>
-<span class="source-line-no">1803</span><span id="line-1803"> return;</span>
-<span class="source-line-no">1804</span><span id="line-1804"> }</span>
-<span class="source-line-no">1805</span><span id="line-1805"> LOG.info("Disabling cache");</span>
-<span class="source-line-no">1806</span><span id="line-1806"> cacheState = CacheState.DISABLED;</span>
-<span class="source-line-no">1807</span><span id="line-1807"> ioEngine.shutdown();</span>
-<span class="source-line-no">1808</span><span id="line-1808"> this.scheduleThreadPool.shutdown();</span>
-<span class="source-line-no">1809</span><span id="line-1809"> for (int i = 0; i < writerThreads.length; ++i)</span>
-<span class="source-line-no">1810</span><span id="line-1810"> writerThreads[i].interrupt();</span>
-<span class="source-line-no">1811</span><span id="line-1811"> this.ramCache.clear();</span>
-<span class="source-line-no">1812</span><span id="line-1812"> if (!ioEngine.isPersistent() || persistencePath == null) {</span>
-<span class="source-line-no">1813</span><span id="line-1813"> // If persistent ioengine and a path, we will serialize out the backingMap.</span>
-<span class="source-line-no">1814</span><span id="line-1814"> this.backingMap.clear();</span>
-<span class="source-line-no">1815</span><span id="line-1815"> this.blocksByHFile.clear();</span>
-<span class="source-line-no">1816</span><span id="line-1816"> this.fullyCachedFiles.clear();</span>
-<span class="source-line-no">1817</span><span id="line-1817"> this.regionCachedSize.clear();</span>
+<span class="source-line-no">1772</span><span id="line-1772"> fullyCachedFiles.clear();</span>
+<span class="source-line-no">1773</span><span id="line-1773"> fullyCachedFiles.putAll(BucketProtoUtils.fromPB(cacheEntry.getCachedFilesMap()));</span>
+<span class="source-line-no">1774</span><span id="line-1774"></span>
+<span class="source-line-no">1775</span><span id="line-1775"> backingMap.clear();</span>
+<span class="source-line-no">1776</span><span id="line-1776"> blocksByHFile.clear();</span>
+<span class="source-line-no">1777</span><span id="line-1777"></span>
+<span class="source-line-no">1778</span><span id="line-1778"> // Read the backing map entries in batches.</span>
+<span class="source-line-no">1779</span><span id="line-1779"> int numChunks = 0;</span>
+<span class="source-line-no">1780</span><span id="line-1780"> while (in.available() > 0) {</span>
+<span class="source-line-no">1781</span><span id="line-1781"> updateCacheIndex(BucketCacheProtos.BackingMap.parseDelimitedFrom(in),</span>
+<span class="source-line-no">1782</span><span id="line-1782"> cacheEntry.getDeserializersMap());</span>
+<span class="source-line-no">1783</span><span id="line-1783"> numChunks++;</span>
+<span class="source-line-no">1784</span><span id="line-1784"> }</span>
+<span class="source-line-no">1785</span><span id="line-1785"></span>
+<span class="source-line-no">1786</span><span id="line-1786"> LOG.info("Retrieved {} of chunks with blockCount = {}.", numChunks, backingMap.size());</span>
+<span class="source-line-no">1787</span><span id="line-1787"> verifyFileIntegrity(cacheEntry);</span>
+<span class="source-line-no">1788</span><span id="line-1788"> verifyCapacityAndClasses(cacheEntry.getCacheCapacity(), cacheEntry.getIoClass(),</span>
+<span class="source-line-no">1789</span><span id="line-1789"> cacheEntry.getMapClass());</span>
+<span class="source-line-no">1790</span><span id="line-1790"> updateRegionSizeMapWhileRetrievingFromFile();</span>
+<span class="source-line-no">1791</span><span id="line-1791"> }</span>
+<span class="source-line-no">1792</span><span id="line-1792"></span>
+<span class="source-line-no">1793</span><span id="line-1793"> /**</span>
+<span class="source-line-no">1794</span><span id="line-1794"> * Check whether we tolerate IO error this time. If the duration of IOEngine throwing errors</span>
+<span class="source-line-no">1795</span><span id="line-1795"> * exceeds ioErrorsDurationTimeTolerated, we will disable the cache</span>
+<span class="source-line-no">1796</span><span id="line-1796"> */</span>
+<span class="source-line-no">1797</span><span id="line-1797"> private void checkIOErrorIsTolerated() {</span>
+<span class="source-line-no">1798</span><span id="line-1798"> long now = EnvironmentEdgeManager.currentTime();</span>
+<span class="source-line-no">1799</span><span id="line-1799"> // Do a single read to a local variable to avoid timing issue - HBASE-24454</span>
+<span class="source-line-no">1800</span><span id="line-1800"> long ioErrorStartTimeTmp = this.ioErrorStartTime;</span>
+<span class="source-line-no">1801</span><span id="line-1801"> if (ioErrorStartTimeTmp > 0) {</span>
+<span class="source-line-no">1802</span><span id="line-1802"> if (isCacheEnabled() && (now - ioErrorStartTimeTmp) > this.ioErrorsTolerationDuration) {</span>
+<span class="source-line-no">1803</span><span id="line-1803"> LOG.error("IO errors duration time has exceeded " + ioErrorsTolerationDuration</span>
+<span class="source-line-no">1804</span><span id="line-1804"> + "ms, disabling cache, please check your IOEngine");</span>
+<span class="source-line-no">1805</span><span id="line-1805"> disableCache();</span>
+<span class="source-line-no">1806</span><span id="line-1806"> }</span>
+<span class="source-line-no">1807</span><span id="line-1807"> } else {</span>
+<span class="source-line-no">1808</span><span id="line-1808"> this.ioErrorStartTime = now;</span>
+<span class="source-line-no">1809</span><span id="line-1809"> }</span>
+<span class="source-line-no">1810</span><span id="line-1810"> }</span>
+<span class="source-line-no">1811</span><span id="line-1811"></span>
+<span class="source-line-no">1812</span><span id="line-1812"> /**</span>
+<span class="source-line-no">1813</span><span id="line-1813"> * Used to shut down the cache -or- turn it off in the case of something broken.</span>
+<span class="source-line-no">1814</span><span id="line-1814"> */</span>
+<span class="source-line-no">1815</span><span id="line-1815"> private void disableCache() {</span>
+<span class="source-line-no">1816</span><span id="line-1816"> if (!isCacheEnabled()) {</span>
+<span class="source-line-no">1817</span><span id="line-1817"> return;</span>
<span class="source-line-no">1818</span><span id="line-1818"> }</span>
-<span class="source-line-no">1819</span><span id="line-1819"> if (cacheStats.getMetricsRollerScheduler() != null) {</span>
-<span class="source-line-no">1820</span><span id="line-1820"> cacheStats.getMetricsRollerScheduler().shutdownNow();</span>
-<span class="source-line-no">1821</span><span id="line-1821"> }</span>
-<span class="source-line-no">1822</span><span id="line-1822"> }</span>
-<span class="source-line-no">1823</span><span id="line-1823"></span>
-<span class="source-line-no">1824</span><span id="line-1824"> private void join() throws InterruptedException {</span>
-<span class="source-line-no">1825</span><span id="line-1825"> for (int i = 0; i < writerThreads.length; ++i)</span>
-<span class="source-line-no">1826</span><span id="line-1826"> writerThreads[i].join();</span>
-<span class="source-line-no">1827</span><span id="line-1827"> }</span>
-<span class="source-line-no">1828</span><span id="line-1828"></span>
-<span class="source-line-no">1829</span><span id="line-1829"> @Override</span>
-<span class="source-line-no">1830</span><span id="line-1830"> public void shutdown() {</span>
-<span class="source-line-no">1831</span><span id="line-1831"> if (isCacheEnabled()) {</span>
-<span class="source-line-no">1832</span><span id="line-1832"> disableCache();</span>
-<span class="source-line-no">1833</span><span id="line-1833"> LOG.info("Shutdown bucket cache: IO persistent=" + ioEngine.isPersistent()</span>
-<span class="source-line-no">1834</span><span id="line-1834"> + "; path to write=" + persistencePath);</span>
-<span class="source-line-no">1835</span><span id="line-1835"> if (ioEngine.isPersistent() && persistencePath != null) {</span>
-<span class="source-line-no">1836</span><span id="line-1836"> try {</span>
-<span class="source-line-no">1837</span><span id="line-1837"> join();</span>
-<span class="source-line-no">1838</span><span id="line-1838"> if (cachePersister != null) {</span>
-<span class="source-line-no">1839</span><span id="line-1839"> LOG.info("Shutting down cache persister thread.");</span>
-<span class="source-line-no">1840</span><span id="line-1840"> cachePersister.shutdown();</span>
-<span class="source-line-no">1841</span><span id="line-1841"> while (cachePersister.isAlive()) {</span>
-<span class="source-line-no">1842</span><span id="line-1842"> Thread.sleep(10);</span>
-<span class="source-line-no">1843</span><span id="line-1843"> }</span>
-<span class="source-line-no">1844</span><span id="line-1844"> }</span>
-<span class="source-line-no">1845</span><span id="line-1845"> persistToFile();</span>
-<span class="source-line-no">1846</span><span id="line-1846"> } catch (IOException ex) {</span>
-<span class="source-line-no">1847</span><span id="line-1847"> LOG.error("Unable to persist data on exit: " + ex.toString(), ex);</span>
-<span class="source-line-no">1848</span><span id="line-1848"> } catch (InterruptedException e) {</span>
-<span class="source-line-no">1849</span><span id="line-1849"> LOG.warn("Failed to persist data on exit", e);</span>
-<span class="source-line-no">1850</span><span id="line-1850"> }</span>
-<span class="source-line-no">1851</span><span id="line-1851"> }</span>
-<span class="source-line-no">1852</span><span id="line-1852"> }</span>
-<span class="source-line-no">1853</span><span id="line-1853"> }</span>
-<span class="source-line-no">1854</span><span id="line-1854"></span>
-<span class="source-line-no">1855</span><span id="line-1855"> /**</span>
-<span class="source-line-no">1856</span><span id="line-1856"> * Needed mostly for UTs that might run in the same VM and create different BucketCache instances</span>
-<span class="source-line-no">1857</span><span id="line-1857"> * on different UT methods.</span>
-<span class="source-line-no">1858</span><span id="line-1858"> */</span>
-<span class="source-line-no">1859</span><span id="line-1859"> @Override</span>
-<span class="source-line-no">1860</span><span id="line-1860"> protected void finalize() {</span>
-<span class="source-line-no">1861</span><span id="line-1861"> if (cachePersister != null && !cachePersister.isInterrupted()) {</span>
-<span class="source-line-no">1862</span><span id="line-1862"> cachePersister.interrupt();</span>
-<span class="source-line-no">1863</span><span id="line-1863"> }</span>
-<span class="source-line-no">1864</span><span id="line-1864"> }</span>
-<span class="source-line-no">1865</span><span id="line-1865"></span>
-<span class="source-line-no">1866</span><span id="line-1866"> @Override</span>
-<span class="source-line-no">1867</span><span id="line-1867"> public CacheStats getStats() {</span>
-<span class="source-line-no">1868</span><span id="line-1868"> return cacheStats;</span>
-<span class="source-line-no">1869</span><span id="line-1869"> }</span>
-<span class="source-line-no">1870</span><span id="line-1870"></span>
-<span class="source-line-no">1871</span><span id="line-1871"> public BucketAllocator getAllocator() {</span>
-<span class="source-line-no">1872</span><span id="line-1872"> return this.bucketAllocator;</span>
-<span class="source-line-no">1873</span><span id="line-1873"> }</span>
-<span class="source-line-no">1874</span><span id="line-1874"></span>
-<span class="source-line-no">1875</span><span id="line-1875"> @Override</span>
-<span class="source-line-no">1876</span><span id="line-1876"> public long heapSize() {</span>
-<span class="source-line-no">1877</span><span id="line-1877"> return this.heapSize.sum();</span>
+<span class="source-line-no">1819</span><span id="line-1819"> LOG.info("Disabling cache");</span>
+<span class="source-line-no">1820</span><span id="line-1820"> cacheState = CacheState.DISABLED;</span>
+<span class="source-line-no">1821</span><span id="line-1821"> ioEngine.shutdown();</span>
+<span class="source-line-no">1822</span><span id="line-1822"> this.scheduleThreadPool.shutdown();</span>
+<span class="source-line-no">1823</span><span id="line-1823"> for (int i = 0; i < writerThreads.length; ++i)</span>
+<span class="source-line-no">1824</span><span id="line-1824"> writerThreads[i].interrupt();</span>
+<span class="source-line-no">1825</span><span id="line-1825"> this.ramCache.clear();</span>
+<span class="source-line-no">1826</span><span id="line-1826"> if (!ioEngine.isPersistent() || persistencePath == null) {</span>
+<span class="source-line-no">1827</span><span id="line-1827"> // If persistent ioengine and a path, we will serialize out the backingMap.</span>
+<span class="source-line-no">1828</span><span id="line-1828"> this.backingMap.clear();</span>
+<span class="source-line-no">1829</span><span id="line-1829"> this.blocksByHFile.clear();</span>
+<span class="source-line-no">1830</span><span id="line-1830"> this.fullyCachedFiles.clear();</span>
+<span class="source-line-no">1831</span><span id="line-1831"> this.regionCachedSize.clear();</span>
+<span class="source-line-no">1832</span><span id="line-1832"> }</span>
+<span class="source-line-no">1833</span><span id="line-1833"> if (cacheStats.getMetricsRollerScheduler() != null) {</span>
+<span class="source-line-no">1834</span><span id="line-1834"> cacheStats.getMetricsRollerScheduler().shutdownNow();</span>
+<span class="source-line-no">1835</span><span id="line-1835"> }</span>
+<span class="source-line-no">1836</span><span id="line-1836"> }</span>
+<span class="source-line-no">1837</span><span id="line-1837"></span>
+<span class="source-line-no">1838</span><span id="line-1838"> private void join() throws InterruptedException {</span>
+<span class="source-line-no">1839</span><span id="line-1839"> for (int i = 0; i < writerThreads.length; ++i)</span>
+<span class="source-line-no">1840</span><span id="line-1840"> writerThreads[i].join();</span>
+<span class="source-line-no">1841</span><span id="line-1841"> }</span>
+<span class="source-line-no">1842</span><span id="line-1842"></span>
+<span class="source-line-no">1843</span><span id="line-1843"> @Override</span>
+<span class="source-line-no">1844</span><span id="line-1844"> public void shutdown() {</span>
+<span class="source-line-no">1845</span><span id="line-1845"> if (isCacheEnabled()) {</span>
+<span class="source-line-no">1846</span><span id="line-1846"> disableCache();</span>
+<span class="source-line-no">1847</span><span id="line-1847"> LOG.info("Shutdown bucket cache: IO persistent=" + ioEngine.isPersistent()</span>
+<span class="source-line-no">1848</span><span id="line-1848"> + "; path to write=" + persistencePath);</span>
+<span class="source-line-no">1849</span><span id="line-1849"> if (ioEngine.isPersistent() && persistencePath != null) {</span>
+<span class="source-line-no">1850</span><span id="line-1850"> try {</span>
+<span class="source-line-no">1851</span><span id="line-1851"> join();</span>
+<span class="source-line-no">1852</span><span id="line-1852"> if (cachePersister != null) {</span>
+<span class="source-line-no">1853</span><span id="line-1853"> LOG.info("Shutting down cache persister thread.");</span>
+<span class="source-line-no">1854</span><span id="line-1854"> cachePersister.shutdown();</span>
+<span class="source-line-no">1855</span><span id="line-1855"> while (cachePersister.isAlive()) {</span>
+<span class="source-line-no">1856</span><span id="line-1856"> Thread.sleep(10);</span>
+<span class="source-line-no">1857</span><span id="line-1857"> }</span>
+<span class="source-line-no">1858</span><span id="line-1858"> }</span>
+<span class="source-line-no">1859</span><span id="line-1859"> persistToFile();</span>
+<span class="source-line-no">1860</span><span id="line-1860"> } catch (IOException ex) {</span>
+<span class="source-line-no">1861</span><span id="line-1861"> LOG.error("Unable to persist data on exit: " + ex.toString(), ex);</span>
+<span class="source-line-no">1862</span><span id="line-1862"> } catch (InterruptedException e) {</span>
+<span class="source-line-no">1863</span><span id="line-1863"> LOG.warn("Failed to persist data on exit", e);</span>
+<span class="source-line-no">1864</span><span id="line-1864"> }</span>
+<span class="source-line-no">1865</span><span id="line-1865"> }</span>
+<span class="source-line-no">1866</span><span id="line-1866"> }</span>
+<span class="source-line-no">1867</span><span id="line-1867"> }</span>
+<span class="source-line-no">1868</span><span id="line-1868"></span>
+<span class="source-line-no">1869</span><span id="line-1869"> /**</span>
+<span class="source-line-no">1870</span><span id="line-1870"> * Needed mostly for UTs that might run in the same VM and create different BucketCache instances</span>
+<span class="source-line-no">1871</span><span id="line-1871"> * on different UT methods.</span>
+<span class="source-line-no">1872</span><span id="line-1872"> */</span>
+<span class="source-line-no">1873</span><span id="line-1873"> @Override</span>
+<span class="source-line-no">1874</span><span id="line-1874"> protected void finalize() {</span>
+<span class="source-line-no">1875</span><span id="line-1875"> if (cachePersister != null && !cachePersister.isInterrupted()) {</span>
+<span class="source-line-no">1876</span><span id="line-1876"> cachePersister.interrupt();</span>
+<span class="source-line-no">1877</span><span id="line-1877"> }</span>
<span class="source-line-no">1878</span><span id="line-1878"> }</span>
<span class="source-line-no">1879</span><span id="line-1879"></span>
<span class="source-line-no">1880</span><span id="line-1880"> @Override</span>
-<span class="source-line-no">1881</span><span id="line-1881"> public long size() {</span>
-<span class="source-line-no">1882</span><span id="line-1882"> return this.realCacheSize.sum();</span>
+<span class="source-line-no">1881</span><span id="line-1881"> public CacheStats getStats() {</span>
+<span class="source-line-no">1882</span><span id="line-1882"> return cacheStats;</span>
<span class="source-line-no">1883</span><span id="line-1883"> }</span>
<span class="source-line-no">1884</span><span id="line-1884"></span>
-<span class="source-line-no">1885</span><span id="line-1885"> @Override</span>
-<span class="source-line-no">1886</span><span id="line-1886"> public long getCurrentDataSize() {</span>
-<span class="source-line-no">1887</span><span id="line-1887"> return size();</span>
-<span class="source-line-no">1888</span><span id="line-1888"> }</span>
-<span class="source-line-no">1889</span><span id="line-1889"></span>
-<span class="source-line-no">1890</span><span id="line-1890"> @Override</span>
-<span class="source-line-no">1891</span><span id="line-1891"> public long getFreeSize() {</span>
-<span class="source-line-no">1892</span><span id="line-1892"> if (!isCacheInitialized("BucketCache:getFreeSize")) {</span>
-<span class="source-line-no">1893</span><span id="line-1893"> return 0;</span>
-<span class="source-line-no">1894</span><span id="line-1894"> }</span>
-<span class="source-line-no">1895</span><span id="line-1895"> return this.bucketAllocator.getFreeSize();</span>
-<span class="source-line-no">1896</span><span id="line-1896"> }</span>
-<span class="source-line-no">1897</span><span id="line-1897"></span>
-<span class="source-line-no">1898</span><span id="line-1898"> @Override</span>
-<span class="source-line-no">1899</span><span id="line-1899"> public long getBlockCount() {</span>
-<span class="source-line-no">1900</span><span id="line-1900"> return this.blockNumber.sum();</span>
-<span class="source-line-no">1901</span><span id="line-1901"> }</span>
-<span class="source-line-no">1902</span><span id="line-1902"></span>
-<span class="source-line-no">1903</span><span id="line-1903"> @Override</span>
-<span class="source-line-no">1904</span><span id="line-1904"> public long getDataBlockCount() {</span>
-<span class="source-line-no">1905</span><span id="line-1905"> return getBlockCount();</span>
-<span class="source-line-no">1906</span><span id="line-1906"> }</span>
-<span class="source-line-no">1907</span><span id="line-1907"></span>
-<span class="source-line-no">1908</span><span id="line-1908"> @Override</span>
-<span class="source-line-no">1909</span><span id="line-1909"> public long getCurrentSize() {</span>
-<span class="source-line-no">1910</span><span id="line-1910"> if (!isCacheInitialized("BucketCache::getCurrentSize")) {</span>
-<span class="source-line-no">1911</span><span id="line-1911"> return 0;</span>
-<span class="source-line-no">1912</span><span id="line-1912"> }</span>
-<span class="source-line-no">1913</span><span id="line-1913"> return this.bucketAllocator.getUsedSize();</span>
-<span class="source-line-no">1914</span><span id="line-1914"> }</span>
-<span class="source-line-no">1915</span><span id="line-1915"></span>
-<span class="source-line-no">1916</span><span id="line-1916"> protected String getAlgorithm() {</span>
-<span class="source-line-no">1917</span><span id="line-1917"> return algorithm;</span>
-<span class="source-line-no">1918</span><span id="line-1918"> }</span>
-<span class="source-line-no">1919</span><span id="line-1919"></span>
-<span class="source-line-no">1920</span><span id="line-1920"> /**</span>
-<span class="source-line-no">1921</span><span id="line-1921"> * Evicts all blocks for a specific HFile.</span>
-<span class="source-line-no">1922</span><span id="line-1922"> * <p></span>
-<span class="source-line-no">1923</span><span id="line-1923"> * This is used for evict-on-close to remove all blocks of a specific HFile.</span>
-<span class="source-line-no">1924</span><span id="line-1924"> * @return the number of blocks evicted</span>
-<span class="source-line-no">1925</span><span id="line-1925"> */</span>
-<span class="source-line-no">1926</span><span id="line-1926"> @Override</span>
-<span class="source-line-no">1927</span><span id="line-1927"> public int evictBlocksByHfileName(String hfileName) {</span>
-<span class="source-line-no">1928</span><span id="line-1928"> return evictBlocksRangeByHfileName(hfileName, 0, Long.MAX_VALUE);</span>
-<span class="source-line-no">1929</span><span id="line-1929"> }</span>
-<span class="source-line-no">1930</span><span id="line-1930"></span>
-<span class="source-line-no">1931</span><span id="line-1931"> @Override</span>
-<span class="source-line-no">1932</span><span id="line-1932"> public int evictBlocksRangeByHfileName(String hfileName, long initOffset, long endOffset) {</span>
-<span class="source-line-no">1933</span><span id="line-1933"> Set<BlockCacheKey> keySet = getAllCacheKeysForFile(hfileName, initOffset, endOffset);</span>
-<span class="source-line-no">1934</span><span id="line-1934"> // We need to make sure whether we are evicting all blocks for this given file. In case of</span>
-<span class="source-line-no">1935</span><span id="line-1935"> // split references, we might be evicting just half of the blocks</span>
-<span class="source-line-no">1936</span><span id="line-1936"> LOG.debug("found {} blocks for file {}, starting offset: {}, end offset: {}", keySet.size(),</span>
-<span class="source-line-no">1937</span><span id="line-1937"> hfileName, initOffset, endOffset);</span>
-<span class="source-line-no">1938</span><span id="line-1938"> int numEvicted = 0;</span>
-<span class="source-line-no">1939</span><span id="line-1939"> for (BlockCacheKey key : keySet) {</span>
-<span class="source-line-no">1940</span><span id="line-1940"> if (evictBlock(key)) {</span>
-<span class="source-line-no">1941</span><span id="line-1941"> ++numEvicted;</span>
-<span class="source-line-no">1942</span><span id="line-1942"> }</span>
-<span class="source-line-no">1943</span><span id="line-1943"> }</span>
-<span class="source-line-no">1944</span><span id="line-1944"> return numEvicted;</span>
-<span class="source-line-no">1945</span><span id="line-1945"> }</span>
-<span class="source-line-no">1946</span><span id="line-1946"></span>
-<span class="source-line-no">1947</span><span id="line-1947"> private Set<BlockCacheKey> getAllCacheKeysForFile(String hfileName, long init, long end) {</span>
-<span class="source-line-no">1948</span><span id="line-1948"> // These keys are just for comparison and are short lived, so we need only file name and offset</span>
-<span class="source-line-no">1949</span><span id="line-1949"> return blocksByHFile.subSet(new BlockCacheKey(hfileName, init), true,</span>
-<span class="source-line-no">1950</span><span id="line-1950"> new BlockCacheKey(hfileName, end), true);</span>
-<span class="source-line-no">1951</span><span id="line-1951"> }</span>
-<span class="source-line-no">1952</span><span id="line-1952"></span>
-<span class="source-line-no">1953</span><span id="line-1953"> /**</span>
-<span class="source-line-no">1954</span><span id="line-1954"> * Used to group bucket entries into priority buckets. There will be a BucketEntryGroup for each</span>
-<span class="source-line-no">1955</span><span id="line-1955"> * priority (single, multi, memory). Once bucketed, the eviction algorithm takes the appropriate</span>
-<span class="source-line-no">1956</span><span id="line-1956"> * number of elements out of each according to configuration parameters and their relative sizes.</span>
-<span class="source-line-no">1957</span><span id="line-1957"> */</span>
-<span class="source-line-no">1958</span><span id="line-1958"> private class BucketEntryGroup {</span>
-<span class="source-line-no">1959</span><span id="line-1959"></span>
-<span class="source-line-no">1960</span><span id="line-1960"> private CachedEntryQueue queue;</span>
-<span class="source-line-no">1961</span><span id="line-1961"> private long totalSize = 0;</span>
-<span class="source-line-no">1962</span><span id="line-1962"> private long bucketSize;</span>
-<span class="source-line-no">1963</span><span id="line-1963"></span>
-<span class="source-line-no">1964</span><span id="line-1964"> public BucketEntryGroup(long bytesToFree, long blockSize, long bucketSize) {</span>
-<span class="source-line-no">1965</span><span id="line-1965"> this.bucketSize = bucketSize;</span>
-<span class="source-line-no">1966</span><span id="line-1966"> queue = new CachedEntryQueue(bytesToFree, blockSize);</span>
-<span class="source-line-no">1967</span><span id="line-1967"> totalSize = 0;</span>
-<span class="source-line-no">1968</span><span id="line-1968"> }</span>
-<span class="source-line-no">1969</span><span id="line-1969"></span>
-<span class="source-line-no">1970</span><span id="line-1970"> public void add(Map.Entry<BlockCacheKey, BucketEntry> block) {</span>
-<span class="source-line-no">1971</span><span id="line-1971"> totalSize += block.getValue().getLength();</span>
-<span class="source-line-no">1972</span><span id="line-1972"> queue.add(block);</span>
-<span class="source-line-no">1973</span><span id="line-1973"> }</span>
-<span class="source-line-no">1974</span><span id="line-1974"></span>
-<span class="source-line-no">1975</span><span id="line-1975"> public long free(long toFree) {</span>
-<span class="source-line-no">1976</span><span id="line-1976"> Map.Entry<BlockCacheKey, BucketEntry> entry;</span>
-<span class="source-line-no">1977</span><span id="line-1977"> long freedBytes = 0;</span>
-<span class="source-line-no">1978</span><span id="line-1978"> // TODO avoid a cycling siutation. We find no block which is not in use and so no way to free</span>
-<span class="source-line-no">1979</span><span id="line-1979"> // What to do then? Caching attempt fail? Need some changes in cacheBlock API?</span>
-<span class="source-line-no">1980</span><span id="line-1980"> while ((entry = queue.pollLast()) != null) {</span>
-<span class="source-line-no">1981</span><span id="line-1981"> BlockCacheKey blockCacheKey = entry.getKey();</span>
-<span class="source-line-no">1982</span><span id="line-1982"> BucketEntry be = entry.getValue();</span>
-<span class="source-line-no">1983</span><span id="line-1983"> if (evictBucketEntryIfNoRpcReferenced(blockCacheKey, be)) {</span>
-<span class="source-line-no">1984</span><span id="line-1984"> freedBytes += be.getLength();</span>
-<span class="source-line-no">1985</span><span id="line-1985"> }</span>
-<span class="source-line-no">1986</span><span id="line-1986"> if (freedBytes >= toFree) {</span>
-<span class="source-line-no">1987</span><span id="line-1987"> return freedBytes;</span>
-<span class="source-line-no">1988</span><span id="line-1988"> }</span>
-<span class="source-line-no">1989</span><span id="line-1989"> }</span>
-<span class="source-line-no">1990</span><span id="line-1990"> return freedBytes;</span>
-<span class="source-line-no">1991</span><span id="line-1991"> }</span>
-<span class="source-line-no">1992</span><span id="line-1992"></span>
-<span class="source-line-no">1993</span><span id="line-1993"> public long overflow() {</span>
-<span class="source-line-no">1994</span><span id="line-1994"> return totalSize - bucketSize;</span>
-<span class="source-line-no">1995</span><span id="line-1995"> }</span>
-<span class="source-line-no">1996</span><span id="line-1996"></span>
-<span class="source-line-no">1997</span><span id="line-1997"> public long totalSize() {</span>
-<span class="source-line-no">1998</span><span id="line-1998"> return totalSize;</span>
-<span class="source-line-no">1999</span><span id="line-1999"> }</span>
-<span class="source-line-no">2000</span><span id="line-2000"> }</span>
-<span class="source-line-no">2001</span><span id="line-2001"></span>
-<span class="source-line-no">2002</span><span id="line-2002"> /**</span>
-<span class="source-line-no">2003</span><span id="line-2003"> * Block Entry stored in the memory with key,data and so on</span>
-<span class="source-line-no">2004</span><span id="line-2004"> */</span>
-<span class="source-line-no">2005</span><span id="line-2005"> static class RAMQueueEntry {</span>
-<span class="source-line-no">2006</span><span id="line-2006"> private final BlockCacheKey key;</span>
-<span class="source-line-no">2007</span><span id="line-2007"> private final Cacheable data;</span>
-<span class="source-line-no">2008</span><span id="line-2008"> private long accessCounter;</span>
-<span class="source-line-no">2009</span><span id="line-2009"> private boolean inMemory;</span>
-<span class="source-line-no">2010</span><span id="line-2010"> private boolean isCachePersistent;</span>
-<span class="source-line-no">2011</span><span id="line-2011"></span>
-<span class="source-line-no">2012</span><span id="line-2012"> private boolean isPrefetch;</span>
-<span class="source-line-no">2013</span><span id="line-2013"></span>
-<span class="source-line-no">2014</span><span id="line-2014"> RAMQueueEntry(BlockCacheKey bck, Cacheable data, long accessCounter, boolean inMemory,</span>
-<span class="source-line-no">2015</span><span id="line-2015"> boolean isCachePersistent, boolean isPrefetch) {</span>
-<span class="source-line-no">2016</span><span id="line-2016"> this.key = bck;</span>
-<span class="source-line-no">2017</span><span id="line-2017"> this.data = data;</span>
-<span class="source-line-no">2018</span><span id="line-2018"> this.accessCounter = accessCounter;</span>
-<span class="source-line-no">2019</span><span id="line-2019"> this.inMemory = inMemory;</span>
-<span class="source-line-no">2020</span><span id="line-2020"> this.isCachePersistent = isCachePersistent;</span>
-<span class="source-line-no">2021</span><span id="line-2021"> this.isPrefetch = isPrefetch;</span>
-<span class="source-line-no">2022</span><span id="line-2022"> }</span>
-<span class="source-line-no">2023</span><span id="line-2023"></span>
-<span class="source-line-no">2024</span><span id="line-2024"> public Cacheable getData() {</span>
-<span class="source-line-no">2025</span><span id="line-2025"> return data;</span>
-<span class="source-line-no">2026</span><span id="line-2026"> }</span>
+<span class="source-line-no">1885</span><span id="line-1885"> public BucketAllocator getAllocator() {</span>
+<span class="source-line-no">1886</span><span id="line-1886"> return this.bucketAllocator;</span>
+<span class="source-line-no">1887</span><span id="line-1887"> }</span>
+<span class="source-line-no">1888</span><span id="line-1888"></span>
+<span class="source-line-no">1889</span><span id="line-1889"> @Override</span>
+<span class="source-line-no">1890</span><span id="line-1890"> public long heapSize() {</span>
+<span class="source-line-no">1891</span><span id="line-1891"> return this.heapSize.sum();</span>
+<span class="source-line-no">1892</span><span id="line-1892"> }</span>
+<span class="source-line-no">1893</span><span id="line-1893"></span>
+<span class="source-line-no">1894</span><span id="line-1894"> @Override</span>
+<span class="source-line-no">1895</span><span id="line-1895"> public long size() {</span>
+<span class="source-line-no">1896</span><span id="line-1896"> return this.realCacheSize.sum();</span>
+<span class="source-line-no">1897</span><span id="line-1897"> }</span>
+<span class="source-line-no">1898</span><span id="line-1898"></span>
+<span class="source-line-no">1899</span><span id="line-1899"> @Override</span>
+<span class="source-line-no">1900</span><span id="line-1900"> public long getCurrentDataSize() {</span>
+<span class="source-line-no">1901</span><span id="line-1901"> return size();</span>
+<span class="source-line-no">1902</span><span id="line-1902"> }</span>
+<span class="source-line-no">1903</span><span id="line-1903"></span>
+<span class="source-line-no">1904</span><span id="line-1904"> @Override</span>
+<span class="source-line-no">1905</span><span id="line-1905"> public long getFreeSize() {</span>
+<span class="source-line-no">1906</span><span id="line-1906"> if (!isCacheInitialized("BucketCache:getFreeSize")) {</span>
+<span class="source-line-no">1907</span><span id="line-1907"> return 0;</span>
+<span class="source-line-no">1908</span><span id="line-1908"> }</span>
+<span class="source-line-no">1909</span><span id="line-1909"> return this.bucketAllocator.getFreeSize();</span>
+<span class="source-line-no">1910</span><span id="line-1910"> }</span>
+<span class="source-line-no">1911</span><span id="line-1911"></span>
+<span class="source-line-no">1912</span><span id="line-1912"> @Override</span>
+<span class="source-line-no">1913</span><span id="line-1913"> public long getBlockCount() {</span>
+<span class="source-line-no">1914</span><span id="line-1914"> return this.blockNumber.sum();</span>
+<span class="source-line-no">1915</span><span id="line-1915"> }</span>
+<span class="source-line-no">1916</span><span id="line-1916"></span>
+<span class="source-line-no">1917</span><span id="line-1917"> @Override</span>
+<span class="source-line-no">1918</span><span id="line-1918"> public long getDataBlockCount() {</span>
+<span class="source-line-no">1919</span><span id="line-1919"> return getBlockCount();</span>
+<span class="source-line-no">1920</span><span id="line-1920"> }</span>
+<span class="source-line-no">1921</span><span id="line-1921"></span>
+<span class="source-line-no">1922</span><span id="line-1922"> @Override</span>
+<span class="source-line-no">1923</span><span id="line-1923"> public long getCurrentSize() {</span>
+<span class="source-line-no">1924</span><span id="line-1924"> if (!isCacheInitialized("BucketCache::getCurrentSize")) {</span>
+<span class="source-line-no">1925</span><span id="line-1925"> return 0;</span>
+<span class="source-line-no">1926</span><span id="line-1926"> }</span>
+<span class="source-line-no">1927</span><span id="line-1927"> return this.bucketAllocator.getUsedSize();</span>
+<span class="source-line-no">1928</span><span id="line-1928"> }</span>
+<span class="source-line-no">1929</span><span id="line-1929"></span>
+<span class="source-line-no">1930</span><span id="line-1930"> protected String getAlgorithm() {</span>
+<span class="source-line-no">1931</span><span id="line-1931"> return algorithm;</span>
+<span class="source-line-no">1932</span><span id="line-1932"> }</span>
+<span class="source-line-no">1933</span><span id="line-1933"></span>
+<span class="source-line-no">1934</span><span id="line-1934"> /**</span>
+<span class="source-line-no">1935</span><span id="line-1935"> * Evicts all blocks for a specific HFile.</span>
+<span class="source-line-no">1936</span><span id="line-1936"> * <p></span>
+<span class="source-line-no">1937</span><span id="line-1937"> * This is used for evict-on-close to remove all blocks of a specific HFile.</span>
+<span class="source-line-no">1938</span><span id="line-1938"> * @return the number of blocks evicted</span>
+<span class="source-line-no">1939</span><span id="line-1939"> */</span>
+<span class="source-line-no">1940</span><span id="line-1940"> @Override</span>
+<span class="source-line-no">1941</span><span id="line-1941"> public int evictBlocksByHfileName(String hfileName) {</span>
+<span class="source-line-no">1942</span><span id="line-1942"> return evictBlocksRangeByHfileName(hfileName, 0, Long.MAX_VALUE);</span>
+<span class="source-line-no">1943</span><span id="line-1943"> }</span>
+<span class="source-line-no">1944</span><span id="line-1944"></span>
+<span class="source-line-no">1945</span><span id="line-1945"> @Override</span>
+<span class="source-line-no">1946</span><span id="line-1946"> public int evictBlocksRangeByHfileName(String hfileName, long initOffset, long endOffset) {</span>
+<span class="source-line-no">1947</span><span id="line-1947"> Set<BlockCacheKey> keySet = getAllCacheKeysForFile(hfileName, initOffset, endOffset);</span>
+<span class="source-line-no">1948</span><span id="line-1948"> // We need to make sure whether we are evicting all blocks for this given file. In case of</span>
+<span class="source-line-no">1949</span><span id="line-1949"> // split references, we might be evicting just half of the blocks</span>
+<span class="source-line-no">1950</span><span id="line-1950"> LOG.debug("found {} blocks for file {}, starting offset: {}, end offset: {}", keySet.size(),</span>
+<span class="source-line-no">1951</span><span id="line-1951"> hfileName, initOffset, endOffset);</span>
+<span class="source-line-no">1952</span><span id="line-1952"> int numEvicted = 0;</span>
+<span class="source-line-no">1953</span><span id="line-1953"> for (BlockCacheKey key : keySet) {</span>
+<span class="source-line-no">1954</span><span id="line-1954"> if (evictBlock(key)) {</span>
+<span class="source-line-no">1955</span><span id="line-1955"> ++numEvicted;</span>
+<span class="source-line-no">1956</span><span id="line-1956"> }</span>
+<span class="source-line-no">1957</span><span id="line-1957"> }</span>
+<span class="source-line-no">1958</span><span id="line-1958"> return numEvicted;</span>
+<span class="source-line-no">1959</span><span id="line-1959"> }</span>
+<span class="source-line-no">1960</span><span id="line-1960"></span>
+<span class="source-line-no">1961</span><span id="line-1961"> private Set<BlockCacheKey> getAllCacheKeysForFile(String hfileName, long init, long end) {</span>
+<span class="source-line-no">1962</span><span id="line-1962"> // These keys are just for comparison and are short lived, so we need only file name and offset</span>
+<span class="source-line-no">1963</span><span id="line-1963"> return blocksByHFile.subSet(new BlockCacheKey(hfileName, init), true,</span>
+<span class="source-line-no">1964</span><span id="line-1964"> new BlockCacheKey(hfileName, end), true);</span>
+<span class="source-line-no">1965</span><span id="line-1965"> }</span>
+<span class="source-line-no">1966</span><span id="line-1966"></span>
+<span class="source-line-no">1967</span><span id="line-1967"> /**</span>
+<span class="source-line-no">1968</span><span id="line-1968"> * Used to group bucket entries into priority buckets. There will be a BucketEntryGroup for each</span>
+<span class="source-line-no">1969</span><span id="line-1969"> * priority (single, multi, memory). Once bucketed, the eviction algorithm takes the appropriate</span>
+<span class="source-line-no">1970</span><span id="line-1970"> * number of elements out of each according to configuration parameters and their relative sizes.</span>
+<span class="source-line-no">1971</span><span id="line-1971"> */</span>
+<span class="source-line-no">1972</span><span id="line-1972"> private class BucketEntryGroup {</span>
+<span class="source-line-no">1973</span><span id="line-1973"></span>
+<span class="source-line-no">1974</span><span id="line-1974"> private CachedEntryQueue queue;</span>
+<span class="source-line-no">1975</span><span id="line-1975"> private long totalSize = 0;</span>
+<span class="source-line-no">1976</span><span id="line-1976"> private long bucketSize;</span>
+<span class="source-line-no">1977</span><span id="line-1977"></span>
+<span class="source-line-no">1978</span><span id="line-1978"> public BucketEntryGroup(long bytesToFree, long blockSize, long bucketSize) {</span>
+<span class="source-line-no">1979</span><span id="line-1979"> this.bucketSize = bucketSize;</span>
+<span class="source-line-no">1980</span><span id="line-1980"> queue = new CachedEntryQueue(bytesToFree, blockSize);</span>
+<span class="source-line-no">1981</span><span id="line-1981"> totalSize = 0;</span>
+<span class="source-line-no">1982</span><span id="line-1982"> }</span>
+<span class="source-line-no">1983</span><span id="line-1983"></span>
+<span class="source-line-no">1984</span><span id="line-1984"> public void add(Map.Entry<BlockCacheKey, BucketEntry> block) {</span>
+<span class="source-line-no">1985</span><span id="line-1985"> totalSize += block.getValue().getLength();</span>
+<span class="source-line-no">1986</span><span id="line-1986"> queue.add(block);</span>
+<span class="source-line-no">1987</span><span id="line-1987"> }</span>
+<span class="source-line-no">1988</span><span id="line-1988"></span>
+<span class="source-line-no">1989</span><span id="line-1989"> public long free(long toFree) {</span>
+<span class="source-line-no">1990</span><span id="line-1990"> Map.Entry<BlockCacheKey, BucketEntry> entry;</span>
+<span class="source-line-no">1991</span><span id="line-1991"> long freedBytes = 0;</span>
+<span class="source-line-no">1992</span><span id="line-1992"> // TODO avoid a cycling siutation. We find no block which is not in use and so no way to free</span>
+<span class="source-line-no">1993</span><span id="line-1993"> // What to do then? Caching attempt fail? Need some changes in cacheBlock API?</span>
+<span class="source-line-no">1994</span><span id="line-1994"> while ((entry = queue.pollLast()) != null) {</span>
+<span class="source-line-no">1995</span><span id="line-1995"> BlockCacheKey blockCacheKey = entry.getKey();</span>
+<span class="source-line-no">1996</span><span id="line-1996"> BucketEntry be = entry.getValue();</span>
+<span class="source-line-no">1997</span><span id="line-1997"> if (evictBucketEntryIfNoRpcReferenced(blockCacheKey, be)) {</span>
+<span class="source-line-no">1998</span><span id="line-1998"> freedBytes += be.getLength();</span>
+<span class="source-line-no">1999</span><span id="line-1999"> }</span>
+<span class="source-line-no">2000</span><span id="line-2000"> if (freedBytes >= toFree) {</span>
+<span class="source-line-no">2001</span><span id="line-2001"> return freedBytes;</span>
+<span class="source-line-no">2002</span><span id="line-2002"> }</span>
+<span class="source-line-no">2003</span><span id="line-2003"> }</span>
+<span class="source-line-no">2004</span><span id="line-2004"> return freedBytes;</span>
+<span class="source-line-no">2005</span><span id="line-2005"> }</span>
+<span class="source-line-no">2006</span><span id="line-2006"></span>
+<span class="source-line-no">2007</span><span id="line-2007"> public long overflow() {</span>
+<span class="source-line-no">2008</span><span id="line-2008"> return totalSize - bucketSize;</span>
+<span class="source-line-no">2009</span><span id="line-2009"> }</span>
+<span class="source-line-no">2010</span><span id="line-2010"></span>
+<span class="source-line-no">2011</span><span id="line-2011"> public long totalSize() {</span>
+<span class="source-line-no">2012</span><span id="line-2012"> return totalSize;</span>
+<span class="source-line-no">2013</span><span id="line-2013"> }</span>
+<span class="source-line-no">2014</span><span id="line-2014"> }</span>
+<span class="source-line-no">2015</span><span id="line-2015"></span>
+<span class="source-line-no">2016</span><span id="line-2016"> /**</span>
+<span class="source-line-no">2017</span><span id="line-2017"> * Block Entry stored in the memory with key,data and so on</span>
+<span class="source-line-no">2018</span><span id="line-2018"> */</span>
+<span class="source-line-no">2019</span><span id="line-2019"> static class RAMQueueEntry {</span>
+<span class="source-line-no">2020</span><span id="line-2020"> private final BlockCacheKey key;</span>
+<span class="source-line-no">2021</span><span id="line-2021"> private final Cacheable data;</span>
+<span class="source-line-no">2022</span><span id="line-2022"> private long accessCounter;</span>
+<span class="source-line-no">2023</span><span id="line-2023"> private boolean inMemory;</span>
+<span class="source-line-no">2024</span><span id="line-2024"> private boolean isCachePersistent;</span>
+<span class="source-line-no">2025</span><span id="line-2025"></span>
+<span class="source-line-no">2026</span><span id="line-2026"> private boolean isPrefetch;</span>
<span class="source-line-no">2027</span><span id="line-2027"></span>
-<span class="source-line-no">2028</span><span id="line-2028"> public BlockCacheKey getKey() {</span>
-<span class="source-line-no">2029</span><span id="line-2029"> return key;</span>
-<span class="source-line-no">2030</span><span id="line-2030"> }</span>
-<span class="source-line-no">2031</span><span id="line-2031"></span>
-<span class="source-line-no">2032</span><span id="line-2032"> public boolean isPrefetch() {</span>
-<span class="source-line-no">2033</span><span id="line-2033"> return isPrefetch;</span>
-<span class="source-line-no">2034</span><span id="line-2034"> }</span>
-<span class="source-line-no">2035</span><span id="line-2035"></span>
-<span class="source-line-no">2036</span><span id="line-2036"> public void access(long accessCounter) {</span>
-<span class="source-line-no">2037</span><span id="line-2037"> this.accessCounter = accessCounter;</span>
-<span class="source-line-no">2038</span><span id="line-2038"> }</span>
-<span class="source-line-no">2039</span><span id="line-2039"></span>
-<span class="source-line-no">2040</span><span id="line-2040"> private ByteBuffAllocator getByteBuffAllocator() {</span>
-<span class="source-line-no">2041</span><span id="line-2041"> if (data instanceof HFileBlock) {</span>
-<span class="source-line-no">2042</span><span id="line-2042"> return ((HFileBlock) data).getByteBuffAllocator();</span>
-<span class="source-line-no">2043</span><span id="line-2043"> }</span>
-<span class="source-line-no">2044</span><span id="line-2044"> return ByteBuffAllocator.HEAP;</span>
-<span class="source-line-no">2045</span><span id="line-2045"> }</span>
-<span class="source-line-no">2046</span><span id="line-2046"></span>
-<span class="source-line-no">2047</span><span id="line-2047"> public BucketEntry writeToCache(final IOEngine ioEngine, final BucketAllocator alloc,</span>
-<span class="source-line-no">2048</span><span id="line-2048"> final LongAdder realCacheSize, Function<BucketEntry, Recycler> createRecycler,</span>
-<span class="source-line-no">2049</span><span id="line-2049"> ByteBuffer metaBuff, final Long acceptableSize) throws IOException {</span>
-<span class="source-line-no">2050</span><span id="line-2050"> int len = data.getSerializedLength();</span>
-<span class="source-line-no">2051</span><span id="line-2051"> // This cacheable thing can't be serialized</span>
-<span class="source-line-no">2052</span><span id="line-2052"> if (len == 0) {</span>
-<span class="source-line-no">2053</span><span id="line-2053"> return null;</span>
-<span class="source-line-no">2054</span><span id="line-2054"> }</span>
-<span class="source-line-no">2055</span><span id="line-2055"> if (isCachePersistent && data instanceof HFileBlock) {</span>
-<span class="source-line-no">2056</span><span id="line-2056"> len += Long.BYTES; // we need to record the cache time for consistency check in case of</span>
-<span class="source-line-no">2057</span><span id="line-2057"> // recovery</span>
-<span class="source-line-no">2058</span><span id="line-2058"> }</span>
-<span class="source-line-no">2059</span><span id="line-2059"> long offset = alloc.allocateBlock(len);</span>
-<span class="source-line-no">2060</span><span id="line-2060"> // In the case of prefetch, we want to avoid freeSpace runs when the cache is full.</span>
-<span class="source-line-no">2061</span><span id="line-2061"> // this makes the cache allocation more predictable, and is particularly important</span>
-<span class="source-line-no">2062</span><span id="line-2062"> // when persistent cache is enabled, as it won't trigger evictions of the recovered blocks,</span>
-<span class="source-line-no">2063</span><span id="line-2063"> // which are likely the most accessed and relevant blocks in the cache.</span>
-<span class="source-line-no">2064</span><span id="line-2064"> if (isPrefetch() && alloc.getUsedSize() > acceptableSize) {</span>
-<span class="source-line-no">2065</span><span id="line-2065"> alloc.freeBlock(offset, len);</span>
-<span class="source-line-no">2066</span><span id="line-2066"> return null;</span>
-<span class="source-line-no">2067</span><span id="line-2067"> }</span>
-<span class="source-line-no">2068</span><span id="line-2068"> boolean succ = false;</span>
-<span class="source-line-no">2069</span><span id="line-2069"> BucketEntry bucketEntry = null;</span>
-<span class="source-line-no">2070</span><span id="line-2070"> try {</span>
-<span class="source-line-no">2071</span><span id="line-2071"> int diskSizeWithHeader = (data instanceof HFileBlock)</span>
-<span class="source-line-no">2072</span><span id="line-2072"> ? ((HFileBlock) data).getOnDiskSizeWithHeader()</span>
-<span class="source-line-no">2073</span><span id="line-2073"> : data.getSerializedLength();</span>
-<span class="source-line-no">2074</span><span id="line-2074"> bucketEntry = new BucketEntry(offset, len, diskSizeWithHeader, accessCounter, inMemory,</span>
-<span class="source-line-no">2075</span><span id="line-2075"> createRecycler, getByteBuffAllocator());</span>
-<span class="source-line-no">2076</span><span id="line-2076"> bucketEntry.setDeserializerReference(data.getDeserializer());</span>
-<span class="source-line-no">2077</span><span id="line-2077"> if (data instanceof HFileBlock) {</span>
-<span class="source-line-no">2078</span><span id="line-2078"> // If an instance of HFileBlock, save on some allocations.</span>
-<span class="source-line-no">2079</span><span id="line-2079"> HFileBlock block = (HFileBlock) data;</span>
-<span class="source-line-no">2080</span><span id="line-2080"> ByteBuff sliceBuf = block.getBufferReadOnly();</span>
-<span class="source-line-no">2081</span><span id="line-2081"> block.getMetaData(metaBuff);</span>
-<span class="source-line-no">2082</span><span id="line-2082"> // adds the cache time prior to the block and metadata part</span>
-<span class="source-line-no">2083</span><span id="line-2083"> if (isCachePersistent) {</span>
-<span class="source-line-no">2084</span><span id="line-2084"> ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);</span>
-<span class="source-line-no">2085</span><span id="line-2085"> buffer.putLong(bucketEntry.getCachedTime());</span>
-<span class="source-line-no">2086</span><span id="line-2086"> buffer.rewind();</span>
-<span class="source-line-no">2087</span><span id="line-2087"> ioEngine.write(buffer, offset);</span>
-<span class="source-line-no">2088</span><span id="line-2088"> ioEngine.write(sliceBuf, (offset + Long.BYTES));</span>
-<span class="source-line-no">2089</span><span id="line-2089"> } else {</span>
-<span class="source-line-no">2090</span><span id="line-2090"> ioEngine.write(sliceBuf, offset);</span>
-<span class="source-line-no">2091</span><span id="line-2091"> }</span>
-<span class="source-line-no">2092</span><span id="line-2092"> ioEngine.write(metaBuff, offset + len - metaBuff.limit());</span>
-<span class="source-line-no">2093</span><span id="line-2093"> } else {</span>
-<span class="source-line-no">2094</span><span id="line-2094"> // Only used for testing.</span>
-<span class="source-line-no">2095</span><span id="line-2095"> ByteBuffer bb = ByteBuffer.allocate(len);</span>
-<span class="source-line-no">2096</span><span id="line-2096"> data.serialize(bb, true);</span>
-<span class="source-line-no">2097</span><span id="line-2097"> ioEngine.write(bb, offset);</span>
-<span class="source-line-no">2098</span><span id="line-2098"> }</span>
-<span class="source-line-no">2099</span><span id="line-2099"> succ = true;</span>
-<span class="source-line-no">2100</span><span id="line-2100"> } finally {</span>
-<span class="source-line-no">2101</span><span id="line-2101"> if (!succ) {</span>
-<span class="source-line-no">2102</span><span id="line-2102"> alloc.freeBlock(offset, len);</span>
-<span class="source-line-no">2103</span><span id="line-2103"> }</span>
-<span class="source-line-no">2104</span><span id="line-2104"> }</span>
-<span class="source-line-no">2105</span><span id="line-2105"> realCacheSize.add(len);</span>
-<span class="source-line-no">2106</span><span id="line-2106"> return bucketEntry;</span>
-<span class="source-line-no">2107</span><span id="line-2107"> }</span>
-<span class="source-line-no">2108</span><span id="line-2108"> }</span>
-<span class="source-line-no">2109</span><span id="line-2109"></span>
-<span class="source-line-no">2110</span><span id="line-2110"> /**</span>
-<span class="source-line-no">2111</span><span id="line-2111"> * Only used in test</span>
-<span class="source-line-no">2112</span><span id="line-2112"> */</span>
-<span class="source-line-no">2113</span><span id="line-2113"> void stopWriterThreads() throws InterruptedException {</span>
-<span class="source-line-no">2114</span><span id="line-2114"> for (WriterThread writerThread : writerThreads) {</span>
-<span class="source-line-no">2115</span><span id="line-2115"> writerThread.disableWriter();</span>
-<span class="source-line-no">2116</span><span id="line-2116"> writerThread.interrupt();</span>
-<span class="source-line-no">2117</span><span id="line-2117"> writerThread.join();</span>
-<span class="source-line-no">2118</span><span id="line-2118"> }</span>
-<span class="source-line-no">2119</span><span id="line-2119"> }</span>
-<span class="source-line-no">2120</span><span id="line-2120"></span>
-<span class="source-line-no">2121</span><span id="line-2121"> @Override</span>
-<span class="source-line-no">2122</span><span id="line-2122"> public Iterator<CachedBlock> iterator() {</span>
-<span class="source-line-no">2123</span><span id="line-2123"> // Don't bother with ramcache since stuff is in here only a little while.</span>
-<span class="source-line-no">2124</span><span id="line-2124"> final Iterator<Map.Entry<BlockCacheKey, BucketEntry>> i = this.backingMap.entrySet().iterator();</span>
-<span class="source-line-no">2125</span><span id="line-2125"> return new Iterator<CachedBlock>() {</span>
-<span class="source-line-no">2126</span><span id="line-2126"> private final long now = System.nanoTime();</span>
-<span class="source-line-no">2127</span><span id="line-2127"></span>
-<span class="source-line-no">2128</span><span id="line-2128"> @Override</span>
-<span class="source-line-no">2129</span><span id="line-2129"> public boolean hasNext() {</span>
-<span class="source-line-no">2130</span><span id="line-2130"> return i.hasNext();</span>
-<span class="source-line-no">2131</span><span id="line-2131"> }</span>
-<span class="source-line-no">2132</span><span id="line-2132"></span>
-<span class="source-line-no">2133</span><span id="line-2133"> @Override</span>
-<span class="source-line-no">2134</span><span id="line-2134"> public CachedBlock next() {</span>
-<span class="source-line-no">2135</span><span id="line-2135"> final Map.Entry<BlockCacheKey, BucketEntry> e = i.next();</span>
-<span class="source-line-no">2136</span><span id="line-2136"> return new CachedBlock() {</span>
-<span class="source-line-no">2137</span><span id="line-2137"> @Override</span>
-<span class="source-line-no">2138</span><span id="line-2138"> public String toString() {</span>
-<span class="source-line-no">2139</span><span id="line-2139"> return BlockCacheUtil.toString(this, now);</span>
-<span class="source-line-no">2140</span><span id="line-2140"> }</span>
+<span class="source-line-no">2028</span><span id="line-2028"> RAMQueueEntry(BlockCacheKey bck, Cacheable data, long accessCounter, boolean inMemory,</span>
+<span class="source-line-no">2029</span><span id="line-2029"> boolean isCachePersistent, boolean isPrefetch) {</span>
+<span class="source-line-no">2030</span><span id="line-2030"> this.key = bck;</span>
+<span class="source-line-no">2031</span><span id="line-2031"> this.data = data;</span>
+<span class="source-line-no">2032</span><span id="line-2032"> this.accessCounter = accessCounter;</span>
+<span class="source-line-no">2033</span><span id="line-2033"> this.inMemory = inMemory;</span>
+<span class="source-line-no">2034</span><span id="line-2034"> this.isCachePersistent = isCachePersistent;</span>
+<span class="source-line-no">2035</span><span id="line-2035"> this.isPrefetch = isPrefetch;</span>
+<span class="source-line-no">2036</span><span id="line-2036"> }</span>
+<span class="source-line-no">2037</span><span id="line-2037"></span>
+<span class="source-line-no">2038</span><span id="line-2038"> public Cacheable getData() {</span>
+<span class="source-line-no">2039</span><span id="line-2039"> return data;</span>
+<span class="source-line-no">2040</span><span id="line-2040"> }</span>
+<span class="source-line-no">2041</span><span id="line-2041"></span>
+<span class="source-line-no">2042</span><span id="line-2042"> public BlockCacheKey getKey() {</span>
+<span class="source-line-no">2043</span><span id="line-2043"> return key;</span>
+<span class="source-line-no">2044</span><span id="line-2044"> }</span>
+<span class="source-line-no">2045</span><span id="line-2045"></span>
+<span class="source-line-no">2046</span><span id="line-2046"> public boolean isPrefetch() {</span>
+<span class="source-line-no">2047</span><span id="line-2047"> return isPrefetch;</span>
+<span class="source-line-no">2048</span><span id="line-2048"> }</span>
+<span class="source-line-no">2049</span><span id="line-2049"></span>
+<span class="source-line-no">2050</span><span id="line-2050"> public void access(long accessCounter) {</span>
+<span class="source-line-no">2051</span><span id="line-2051"> this.accessCounter = accessCounter;</span>
+<span class="source-line-no">2052</span><span id="line-2052"> }</span>
+<span class="source-line-no">2053</span><span id="line-2053"></span>
+<span class="source-line-no">2054</span><span id="line-2054"> private ByteBuffAllocator getByteBuffAllocator() {</span>
+<span class="source-line-no">2055</span><span id="line-2055"> if (data instanceof HFileBlock) {</span>
+<span class="source-line-no">2056</span><span id="line-2056"> return ((HFileBlock) data).getByteBuffAllocator();</span>
+<span class="source-line-no">2057</span><span id="line-2057"> }</span>
+<span class="source-line-no">2058</span><span id="line-2058"> return ByteBuffAllocator.HEAP;</span>
+<span class="source-line-no">2059</span><span id="line-2059"> }</span>
+<span class="source-line-no">2060</span><span id="line-2060"></span>
+<span class="source-line-no">2061</span><span id="line-2061"> public BucketEntry writeToCache(final IOEngine ioEngine, final BucketAllocator alloc,</span>
+<span class="source-line-no">2062</span><span id="line-2062"> final LongAdder realCacheSize, Function<BucketEntry, Recycler> createRecycler,</span>
+<span class="source-line-no">2063</span><span id="line-2063"> ByteBuffer metaBuff, final Long acceptableSize) throws IOException {</span>
+<span class="source-line-no">2064</span><span id="line-2064"> int len = data.getSerializedLength();</span>
+<span class="source-line-no">2065</span><span id="line-2065"> // This cacheable thing can't be serialized</span>
+<span class="source-line-no">2066</span><span id="line-2066"> if (len == 0) {</span>
+<span class="source-line-no">2067</span><span id="line-2067"> return null;</span>
+<span class="source-line-no">2068</span><span id="line-2068"> }</span>
+<span class="source-line-no">2069</span><span id="line-2069"> if (isCachePersistent && data instanceof HFileBlock) {</span>
+<span class="source-line-no">2070</span><span id="line-2070"> len += Long.BYTES; // we need to record the cache time for consistency check in case of</span>
+<span class="source-line-no">2071</span><span id="line-2071"> // recovery</span>
+<span class="source-line-no">2072</span><span id="line-2072"> }</span>
+<span class="source-line-no">2073</span><span id="line-2073"> long offset = alloc.allocateBlock(len);</span>
+<span class="source-line-no">2074</span><span id="line-2074"> // In the case of prefetch, we want to avoid freeSpace runs when the cache is full.</span>
+<span class="source-line-no">2075</span><span id="line-2075"> // this makes the cache allocation more predictable, and is particularly important</span>
+<span class="source-line-no">2076</span><span id="line-2076"> // when persistent cache is enabled, as it won't trigger evictions of the recovered blocks,</span>
+<span class="source-line-no">2077</span><span id="line-2077"> // which are likely the most accessed and relevant blocks in the cache.</span>
+<span class="source-line-no">2078</span><span id="line-2078"> if (isPrefetch() && alloc.getUsedSize() > acceptableSize) {</span>
+<span class="source-line-no">2079</span><span id="line-2079"> alloc.freeBlock(offset, len);</span>
+<span class="source-line-no">2080</span><span id="line-2080"> return null;</span>
+<span class="source-line-no">2081</span><span id="line-2081"> }</span>
+<span class="source-line-no">2082</span><span id="line-2082"> boolean succ = false;</span>
+<span class="source-line-no">2083</span><span id="line-2083"> BucketEntry bucketEntry = null;</span>
+<span class="source-line-no">2084</span><span id="line-2084"> try {</span>
+<span class="source-line-no">2085</span><span id="line-2085"> int diskSizeWithHeader = (data instanceof HFileBlock)</span>
+<span class="source-line-no">2086</span><span id="line-2086"> ? ((HFileBlock) data).getOnDiskSizeWithHeader()</span>
+<span class="source-line-no">2087</span><span id="line-2087"> : data.getSerializedLength();</span>
+<span class="source-line-no">2088</span><span id="line-2088"> bucketEntry = new BucketEntry(offset, len, diskSizeWithHeader, accessCounter, inMemory,</span>
+<span class="source-line-no">2089</span><span id="line-2089"> createRecycler, getByteBuffAllocator());</span>
+<span class="source-line-no">2090</span><span id="line-2090"> bucketEntry.setDeserializerReference(data.getDeserializer());</span>
+<span class="source-line-no">2091</span><span id="line-2091"> if (data instanceof HFileBlock) {</span>
+<span class="source-line-no">2092</span><span id="line-2092"> // If an instance of HFileBlock, save on some allocations.</span>
+<span class="source-line-no">2093</span><span id="line-2093"> HFileBlock block = (HFileBlock) data;</span>
+<span class="source-line-no">2094</span><span id="line-2094"> ByteBuff sliceBuf = block.getBufferReadOnly();</span>
+<span class="source-line-no">2095</span><span id="line-2095"> block.getMetaData(metaBuff);</span>
+<span class="source-line-no">2096</span><span id="line-2096"> // adds the cache time prior to the block and metadata part</span>
+<span class="source-line-no">2097</span><span id="line-2097"> if (isCachePersistent) {</span>
+<span class="source-line-no">2098</span><span id="line-2098"> ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);</span>
+<span class="source-line-no">2099</span><span id="line-2099"> buffer.putLong(bucketEntry.getCachedTime());</span>
+<span class="source-line-no">2100</span><span id="line-2100"> buffer.rewind();</span>
+<span class="source-line-no">2101</span><span id="line-2101"> ioEngine.write(buffer, offset);</span>
+<span class="source-line-no">2102</span><span id="line-2102"> ioEngine.write(sliceBuf, (offset + Long.BYTES));</span>
+<span class="source-line-no">2103</span><span id="line-2103"> } else {</span>
+<span class="source-line-no">2104</span><span id="line-2104"> ioEngine.write(sliceBuf, offset);</span>
+<span class="source-line-no">2105</span><span id="line-2105"> }</span>
+<span class="source-line-no">2106</span><span id="line-2106"> ioEngine.write(metaBuff, offset + len - metaBuff.limit());</span>
+<span class="source-line-no">2107</span><span id="line-2107"> } else {</span>
+<span class="source-line-no">2108</span><span id="line-2108"> // Only used for testing.</span>
+<span class="source-line-no">2109</span><span id="line-2109"> ByteBuffer bb = ByteBuffer.allocate(len);</span>
+<span class="source-line-no">2110</span><span id="line-2110"> data.serialize(bb, true);</span>
+<span class="source-line-no">2111</span><span id="line-2111"> ioEngine.write(bb, offset);</span>
+<span class="source-line-no">2112</span><span id="line-2112"> }</span>
+<span class="source-line-no">2113</span><span id="line-2113"> succ = true;</span>
+<span class="source-line-no">2114</span><span id="line-2114"> } finally {</span>
+<span class="source-line-no">2115</span><span id="line-2115"> if (!succ) {</span>
+<span class="source-line-no">2116</span><span id="line-2116"> alloc.freeBlock(offset, len);</span>
+<span class="source-line-no">2117</span><span id="line-2117"> }</span>
+<span class="source-line-no">2118</span><span id="line-2118"> }</span>
+<span class="source-line-no">2119</span><span id="line-2119"> realCacheSize.add(len);</span>
+<span class="source-line-no">2120</span><span id="line-2120"> return bucketEntry;</span>
+<span class="source-line-no">2121</span><span id="line-2121"> }</span>
+<span class="source-line-no">2122</span><span id="line-2122"> }</span>
+<span class="source-line-no">2123</span><span id="line-2123"></span>
+<span class="source-line-no">2124</span><span id="line-2124"> /**</span>
+<span class="source-line-no">2125</span><span id="line-2125"> * Only used in test</span>
+<span class="source-line-no">2126</span><span id="line-2126"> */</span>
+<span class="source-line-no">2127</span><span id="line-2127"> void stopWriterThreads() throws InterruptedException {</span>
+<span class="source-line-no">2128</span><span id="line-2128"> for (WriterThread writerThread : writerThreads) {</span>
+<span class="source-line-no">2129</span><span id="line-2129"> writerThread.disableWriter();</span>
+<span class="source-line-no">2130</span><span id="line-2130"> writerThread.interrupt();</span>
+<span class="source-line-no">2131</span><span id="line-2131"> writerThread.join();</span>
+<span class="source-line-no">2132</span><span id="line-2132"> }</span>
+<span class="source-line-no">2133</span><span id="line-2133"> }</span>
+<span class="source-line-no">2134</span><span id="line-2134"></span>
+<span class="source-line-no">2135</span><span id="line-2135"> @Override</span>
+<span class="source-line-no">2136</span><span id="line-2136"> public Iterator<CachedBlock> iterator() {</span>
+<span class="source-line-no">2137</span><span id="line-2137"> // Don't bother with ramcache since stuff is in here only a little while.</span>
+<span class="source-line-no">2138</span><span id="line-2138"> final Iterator<Map.Entry<BlockCacheKey, BucketEntry>> i = this.backingMap.entrySet().iterator();</span>
+<span class="source-line-no">2139</span><span id="line-2139"> return new Iterator<CachedBlock>() {</span>
+<span class="source-line-no">2140</span><span id="line-2140"> private final long now = System.nanoTime();</span>
<span class="source-line-no">2141</span><span id="line-2141"></span>
-<span class="source-line-no">2142</span><span id="line-2142"> @Override</span>
-<span class="source-line-no">2143</span><span id="line-2143"> public BlockPriority getBlockPriority() {</span>
-<span class="source-line-no">2144</span><span id="line-2144"> return e.getValue().getPriority();</span>
-<span class="source-line-no">2145</span><span id="line-2145"> }</span>
+<span class="source-line-no">2142</span><span id="line-2142"> @Override</span>
+<span class="source-line-no">2143</span><span id="line-2143"> public boolean hasNext() {</span>
+<span class="source-line-no">2144</span><span id="line-2144"> return i.hasNext();</span>
+<span class="source-line-no">2145</span><span id="line-2145"> }</span>
<span class="source-line-no">2146</span><span id="line-2146"></span>
-<span class="source-line-no">2147</span><span id="line-2147"> @Override</span>
-<span class="source-line-no">2148</span><span id="line-2148"> public BlockType getBlockType() {</span>
-<span class="source-line-no">2149</span><span id="line-2149"> // Not held by BucketEntry. Could add it if wanted on BucketEntry creation.</span>
-<span class="source-line-no">2150</span><span id="line-2150"> return null;</span>
-<span class="source-line-no">2151</span><span id="line-2151"> }</span>
-<span class="source-line-no">2152</span><span id="line-2152"></span>
-<span class="source-line-no">2153</span><span id="line-2153"> @Override</span>
-<span class="source-line-no">2154</span><span id="line-2154"> public long getOffset() {</span>
-<span class="source-line-no">2155</span><span id="line-2155"> return e.getKey().getOffset();</span>
-<span class="source-line-no">2156</span><span id="line-2156"> }</span>
-<span class="source-line-no">2157</span><span id="line-2157"></span>
-<span class="source-line-no">2158</span><span id="line-2158"> @Override</span>
-<span class="source-line-no">2159</span><span id="line-2159"> public long getSize() {</span>
-<span class="source-line-no">2160</span><span id="line-2160"> return e.getValue().getLength();</span>
-<span class="source-line-no">2161</span><span id="line-2161"> }</span>
-<span class="source-line-no">2162</span><span id="line-2162"></span>
-<span class="source-line-no">2163</span><span id="line-2163"> @Override</span>
-<span class="source-line-no">2164</span><span id="line-2164"> public long getCachedTime() {</span>
-<span class="source-line-no">2165</span><span id="line-2165"> return e.getValue().getCachedTime();</span>
-<span class="source-line-no">2166</span><span id="line-2166"> }</span>
-<span class="source-line-no">2167</span><span id="line-2167"></span>
-<span class="source-line-no">2168</span><span id="line-2168"> @Override</span>
-<span class="source-line-no">2169</span><span id="line-2169"> public String getFilename() {</span>
-<span class="source-line-no">2170</span><span id="line-2170"> return e.getKey().getHfileName();</span>
-<span class="source-line-no">2171</span><span id="line-2171"> }</span>
-<span class="source-line-no">2172</span><span id="line-2172"></span>
-<span class="source-line-no">2173</span><span id="line-2173"> @Override</span>
-<span class="source-line-no">2174</span><span id="line-2174"> public int compareTo(CachedBlock other) {</span>
-<span class="source-line-no">2175</span><span id="line-2175"> int diff = this.getFilename().compareTo(other.getFilename());</span>
-<span class="source-line-no">2176</span><span id="line-2176"> if (diff != 0) return diff;</span>
-<span class="source-line-no">2177</span><span id="line-2177"></span>
-<span class="source-line-no">2178</span><span id="line-2178"> diff = Long.compare(this.getOffset(), other.getOffset());</span>
-<span class="source-line-no">2179</span><span id="line-2179"> if (diff != 0) return diff;</span>
-<span class="source-line-no">2180</span><span id="line-2180"> if (other.getCachedTime() < 0 || this.getCachedTime() < 0) {</span>
-<span class="source-line-no">2181</span><span id="line-2181"> throw new IllegalStateException(</span>
-<span class="source-line-no">2182</span><span id="line-2182"> "" + this.getCachedTime() + ", " + other.getCachedTime());</span>
-<span class="source-line-no">2183</span><span id="line-2183"> }</span>
-<span class="source-line-no">2184</span><span id="line-2184"> return Long.compare(other.getCachedTime(), this.getCachedTime());</span>
+<span class="source-line-no">2147</span><span id="line-2147"> @Override</span>
+<span class="source-line-no">2148</span><span id="line-2148"> public CachedBlock next() {</span>
+<span class="source-line-no">2149</span><span id="line-2149"> final Map.Entry<BlockCacheKey, BucketEntry> e = i.next();</span>
+<span class="source-line-no">2150</span><span id="line-2150"> return new CachedBlock() {</span>
+<span class="source-line-no">2151</span><span id="line-2151"> @Override</span>
+<span class="source-line-no">2152</span><span id="line-2152"> public String toString() {</span>
+<span class="source-line-no">2153</span><span id="line-2153"> return BlockCacheUtil.toString(this, now);</span>
+<span class="source-line-no">2154</span><span id="line-2154"> }</span>
+<span class="source-line-no">2155</span><span id="line-2155"></span>
+<span class="source-line-no">2156</span><span id="line-2156"> @Override</span>
+<span class="source-line-no">2157</span><span id="line-2157"> public BlockPriority getBlockPriority() {</span>
+<span class="source-line-no">2158</span><span id="line-2158"> return e.getValue().getPriority();</span>
+<span class="source-line-no">2159</span><span id="line-2159"> }</span>
+<span class="source-line-no">2160</span><span id="line-2160"></span>
+<span class="source-line-no">2161</span><span id="line-2161"> @Override</span>
+<span class="source-line-no">2162</span><span id="line-2162"> public BlockType getBlockType() {</span>
+<span class="source-line-no">2163</span><span id="line-2163"> // Not held by BucketEntry. Could add it if wanted on BucketEntry creation.</span>
+<span class="source-line-no">2164</span><span id="line-2164"> return null;</span>
+<span class="source-line-no">2165</span><span id="line-2165"> }</span>
+<span class="source-line-no">2166</span><span id="line-2166"></span>
+<span class="source-line-no">2167</span><span id="line-2167"> @Override</span>
+<span class="source-line-no">2168</span><span id="line-2168"> public long getOffset() {</span>
+<span class="source-line-no">2169</span><span id="line-2169"> return e.getKey().getOffset();</span>
+<span class="source-line-no">2170</span><span id="line-2170"> }</span>
+<span class="source-line-no">2171</span><span id="line-2171"></span>
+<span class="source-line-no">2172</span><span id="line-2172"> @Override</span>
+<span class="source-line-no">2173</span><span id="line-2173"> public long getSize() {</span>
+<span class="source-line-no">2174</span><span id="line-2174"> return e.getValue().getLength();</span>
+<span class="source-line-no">2175</span><span id="line-2175"> }</span>
+<span class="source-line-no">2176</span><span id="line-2176"></span>
+<span class="source-line-no">2177</span><span id="line-2177"> @Override</span>
+<span class="source-line-no">2178</span><span id="line-2178"> public long getCachedTime() {</span>
+<span class="source-line-no">2179</span><span id="line-2179"> return e.getValue().getCachedTime();</span>
+<span class="source-line-no">2180</span><span id="line-2180"> }</span>
+<span class="source-line-no">2181</span><span id="line-2181"></span>
+<span class="source-line-no">2182</span><span id="line-2182"> @Override</span>
+<span class="source-line-no">2183</span><span id="line-2183"> public String getFilename() {</span>
+<span class="source-line-no">2184</span><span id="line-2184"> return e.getKey().getHfileName();</span>
<span class="source-line-no">2185</span><span id="line-2185"> }</span>
<span class="source-line-no">2186</span><span id="line-2186"></span>
<span class="source-line-no">2187</span><span id="line-2187"> @Override</span>
-<span class="source-line-no">2188</span><span id="line-2188"> public int hashCode() {</span>
-<span class="source-line-no">2189</span><span id="line-2189"> return e.getKey().hashCode();</span>
-<span class="source-line-no">2190</span><span id="line-2190"> }</span>
+<span class="source-line-no">2188</span><span id="line-2188"> public int compareTo(CachedBlock other) {</span>
+<span class="source-line-no">2189</span><span id="line-2189"> int diff = this.getFilename().compareTo(other.getFilename());</span>
+<span class="source-line-no">2190</span><span id="line-2190"> if (diff != 0) return diff;</span>
<span class="source-line-no">2191</span><span id="line-2191"></span>
-<span class="source-line-no">2192</span><span id="line-2192"> @Override</span>
-<span class="source-line-no">2193</span><span id="line-2193"> public boolean equals(Object obj) {</span>
-<span class="source-line-no">2194</span><span id="line-2194"> if (obj instanceof CachedBlock) {</span>
-<span class="source-line-no">2195</span><span id="line-2195"> CachedBlock cb = (CachedBlock) obj;</span>
-<span class="source-line-no">2196</span><span id="line-2196"> return compareTo(cb) == 0;</span>
-<span class="source-line-no">2197</span><span id="line-2197"> } else {</span>
-<span class="source-line-no">2198</span><span id="line-2198"> return false;</span>
-<span class="source-line-no">2199</span><span id="line-2199"> }</span>
-<span class="source-line-no">2200</span><span id="line-2200"> }</span>
-<span class="source-line-no">2201</span><span id="line-2201"> };</span>
-<span class="source-line-no">2202</span><span id="line-2202"> }</span>
-<span class="source-line-no">2203</span><span id="line-2203"></span>
-<span class="source-line-no">2204</span><span id="line-2204"> @Override</span>
-<span class="source-line-no">2205</span><span id="line-2205"> public void remove() {</span>
-<span class="source-line-no">2206</span><span id="line-2206"> throw new UnsupportedOperationException();</span>
-<span class="source-line-no">2207</span><span id="line-2207"> }</span>
-<span class="source-line-no">2208</span><span id="line-2208"> };</span>
-<span class="source-line-no">2209</span><span id="line-2209"> }</span>
-<span class="source-line-no">2210</span><span id="line-2210"></span>
-<span class="source-line-no">2211</span><span id="line-2211"> @Override</span>
-<span class="source-line-no">2212</span><span id="line-2212"> public BlockCache[] getBlockCaches() {</span>
-<span class="source-line-no">2213</span><span id="line-2213"> return null;</span>
-<span class="source-line-no">2214</span><span id="line-2214"> }</span>
-<span class="source-line-no">2215</span><span id="line-2215"></span>
-<span class="source-line-no">2216</span><span id="line-2216"> public int getRpcRefCount(BlockCacheKey cacheKey) {</span>
-<span class="source-line-no">2217</span><span id="line-2217"> BucketEntry bucketEntry = backingMap.get(cacheKey);</span>
-<span class="source-line-no">2218</span><span id="line-2218"> if (bucketEntry != null) {</span>
-<span class="source-line-no">2219</span><span id="line-2219"> return bucketEntry.refCnt() - (bucketEntry.markedAsEvicted.get() ? 0 : 1);</span>
-<span class="source-line-no">2220</span><span id="line-2220"> }</span>
-<span class="source-line-no">2221</span><span id="line-2221"> return 0;</span>
-<span class="source-line-no">2222</span><span id="line-2222"> }</span>
-<span class="source-line-no">2223</span><span id="line-2223"></span>
-<span class="source-line-no">2224</span><span id="line-2224"> float getAcceptableFactor() {</span>
-<span class="source-line-no">2225</span><span id="line-2225"> return acceptableFactor;</span>
-<span class="source-line-no">2226</span><span id="line-2226"> }</span>
-<span class="source-line-no">2227</span><span id="line-2227"></span>
-<span class="source-line-no">2228</span><span id="line-2228"> float getMinFactor() {</span>
-<span class="source-line-no">2229</span><span id="line-2229"> return minFactor;</span>
-<span class="source-line-no">2230</span><span id="line-2230"> }</span>
-<span class="source-line-no">2231</span><span id="line-2231"></span>
-<span class="source-line-no">2232</span><span id="line-2232"> float getExtraFreeFactor() {</span>
-<span class="source-line-no">2233</span><span id="line-2233"> return extraFreeFactor;</span>
-<span class="source-line-no">2234</span><span id="line-2234"> }</span>
-<span class="source-line-no">2235</span><span id="line-2235"></span>
-<span class="source-line-no">2236</span><span id="line-2236"> float getSingleFactor() {</span>
-<span class="source-line-no">2237</span><span id="line-2237"> return singleFactor;</span>
-<span class="source-line-no">2238</span><span id="line-2238"> }</span>
-<span class="source-line-no">2239</span><span id="line-2239"></span>
-<span class="source-line-no">2240</span><span id="line-2240"> float getMultiFactor() {</span>
-<span class="source-line-no">2241</span><span id="line-2241"> return multiFactor;</span>
-<span class="source-line-no">2242</span><span id="line-2242"> }</span>
-<span class="source-line-no">2243</span><span id="line-2243"></span>
-<span class="source-line-no">2244</span><span id="line-2244"> float getMemoryFactor() {</span>
-<span class="source-line-no">2245</span><span id="line-2245"> return memoryFactor;</span>
-<span class="source-line-no">2246</span><span id="line-2246"> }</span>
-<span class="source-line-no">2247</span><span id="line-2247"></span>
-<span class="source-line-no">2248</span><span id="line-2248"> long getQueueAdditionWaitTime() {</span>
-<span class="source-line-no">2249</span><span id="line-2249"> return queueAdditionWaitTime;</span>
-<span class="source-line-no">2250</span><span id="line-2250"> }</span>
-<span class="source-line-no">2251</span><span id="line-2251"></span>
-<span class="source-line-no">2252</span><span id="line-2252"> long getPersistenceChunkSize() {</span>
-<span class="source-line-no">2253</span><span id="line-2253"> return persistenceChunkSize;</span>
-<span class="source-line-no">2254</span><span id="line-2254"> }</span>
-<span class="source-line-no">2255</span><span id="line-2255"></span>
-<span class="source-line-no">2256</span><span id="line-2256"> long getBucketcachePersistInterval() {</span>
-<span class="source-line-no">2257</span><span id="line-2257"> return bucketcachePersistInterval;</span>
-<span class="source-line-no">2258</span><span id="line-2258"> }</span>
-<span class="source-line-no">2259</span><span id="line-2259"></span>
-<span class="source-line-no">2260</span><span id="line-2260"> public String getPersistencePath() {</span>
-<span class="source-line-no">2261</span><span id="line-2261"> return persistencePath;</span>
-<span class="source-line-no">2262</span><span id="line-2262"> }</span>
-<span class="source-line-no">2263</span><span id="line-2263"></span>
-<span class="source-line-no">2264</span><span id="line-2264"> /**</span>
-<span class="source-line-no">2265</span><span id="line-2265"> * Wrapped the delegate ConcurrentMap with maintaining its block's reference count.</span>
-<span class="source-line-no">2266</span><span id="line-2266"> */</span>
-<span class="source-line-no">2267</span><span id="line-2267"> static class RAMCache {</span>
-<span class="source-line-no">2268</span><span id="line-2268"> /**</span>
-<span class="source-line-no">2269</span><span id="line-2269"> * Defined the map as {@link ConcurrentHashMap} explicitly here, because in</span>
-<span class="source-line-no">2270</span><span id="line-2270"> * {@link RAMCache#get(BlockCacheKey)} and</span>
-<span class="source-line-no">2271</span><span id="line-2271"> * {@link RAMCache#putIfAbsent(BlockCacheKey, BucketCache.RAMQueueEntry)} , we need to guarantee</span>
-<span class="source-line-no">2272</span><span id="line-2272"> * the atomicity of map#computeIfPresent(key, func) and map#putIfAbsent(key, func). Besides, the</span>
-<span class="source-line-no">2273</span><span id="line-2273"> * func method can execute exactly once only when the key is present(or absent) and under the</span>
-<span class="source-line-no">2274</span><span id="line-2274"> * lock context. Otherwise, the reference count of block will be messed up. Notice that the</span>
-<span class="source-line-no">2275</span><span id="line-2275"> * {@link java.util.concurrent.ConcurrentSkipListMap} can not guarantee that.</span>
-<span class="source-line-no">2276</span><span id="line-2276"> */</span>
-<span class="source-line-no">2277</span><span id="line-2277"> final ConcurrentHashMap<BlockCacheKey, RAMQueueEntry> delegate = new ConcurrentHashMap<>();</span>
-<span class="source-line-no">2278</span><span id="line-2278"></span>
-<span class="source-line-no">2279</span><span id="line-2279"> public boolean containsKey(BlockCacheKey key) {</span>
-<span class="source-line-no">2280</span><span id="line-2280"> return delegate.containsKey(key);</span>
-<span class="source-line-no">2281</span><span id="line-2281"> }</span>
-<span class="source-line-no">2282</span><span id="line-2282"></span>
-<span class="source-line-no">2283</span><span id="line-2283"> public RAMQueueEntry get(BlockCacheKey key) {</span>
-<span class="source-line-no">2284</span><span id="line-2284"> return delegate.computeIfPresent(key, (k, re) -> {</span>
-<span class="source-line-no">2285</span><span id="line-2285"> // It'll be referenced by RPC, so retain atomically here. if the get and retain is not</span>
-<span class="source-line-no">2286</span><span id="line-2286"> // atomic, another thread may remove and release the block, when retaining in this thread we</span>
-<span class="source-line-no">2287</span><span id="line-2287"> // may retain a block with refCnt=0 which is disallowed. (see HBASE-22422)</span>
-<span class="source-line-no">2288</span><span id="line-2288"> re.getData().retain();</span>
-<span class="source-line-no">2289</span><span id="line-2289"> return re;</span>
-<span class="source-line-no">2290</span><span id="line-2290"> });</span>
-<span class="source-line-no">2291</span><span id="line-2291"> }</span>
+<span class="source-line-no">2192</span><span id="line-2192"> diff = Long.compare(this.getOffset(), other.getOffset());</span>
+<span class="source-line-no">2193</span><span id="line-2193"> if (diff != 0) return diff;</span>
+<span class="source-line-no">2194</span><span id="line-2194"> if (other.getCachedTime() < 0 || this.getCachedTime() < 0) {</span>
+<span class="source-line-no">2195</span><span id="line-2195"> throw new IllegalStateException(</span>
+<span class="source-line-no">2196</span><span id="line-2196"> "" + this.getCachedTime() + ", " + other.getCachedTime());</span>
+<span class="source-line-no">2197</span><span id="line-2197"> }</span>
+<span class="source-line-no">2198</span><span id="line-2198"> return Long.compare(other.getCachedTime(), this.getCachedTime());</span>
+<span class="source-line-no">2199</span><span id="line-2199"> }</span>
+<span class="source-line-no">2200</span><span id="line-2200"></span>
+<span class="source-line-no">2201</span><span id="line-2201"> @Override</span>
+<span class="source-line-no">2202</span><span id="line-2202"> public int hashCode() {</span>
+<span class="source-line-no">2203</span><span id="line-2203"> return e.getKey().hashCode();</span>
+<span class="source-line-no">2204</span><span id="line-2204"> }</span>
+<span class="source-line-no">2205</span><span id="line-2205"></span>
+<span class="source-line-no">2206</span><span id="line-2206"> @Override</span>
+<span class="source-line-no">2207</span><span id="line-2207"> public boolean equals(Object obj) {</span>
+<span class="source-line-no">2208</span><span id="line-2208"> if (obj instanceof CachedBlock) {</span>
+<span class="source-line-no">2209</span><span id="line-2209"> CachedBlock cb = (CachedBlock) obj;</span>
+<span class="source-line-no">2210</span><span id="line-2210"> return compareTo(cb) == 0;</span>
+<span class="source-line-no">2211</span><span id="line-2211"> } else {</span>
+<span class="source-line-no">2212</span><span id="line-2212"> return false;</span>
+<span class="source-line-no">2213</span><span id="line-2213"> }</span>
+<span class="source-line-no">2214</span><span id="line-2214"> }</span>
+<span class="source-line-no">2215</span><span id="line-2215"> };</span>
+<span class="source-line-no">2216</span><span id="line-2216"> }</span>
+<span class="source-line-no">2217</span><span id="line-2217"></span>
+<span class="source-line-no">2218</span><span id="line-2218"> @Override</span>
+<span class="source-line-no">2219</span><span id="line-2219"> public void remove() {</span>
+<span class="source-line-no">2220</span><span id="line-2220"> throw new UnsupportedOperationException();</span>
+<span class="source-line-no">2221</span><span id="line-2221"> }</span>
+<span class="source-line-no">2222</span><span id="line-2222"> };</span>
+<span class="source-line-no">2223</span><span id="line-2223"> }</span>
+<span class="source-line-no">2224</span><span id="line-2224"></span>
+<span class="source-line-no">2225</span><span id="line-2225"> @Override</span>
+<span class="source-line-no">2226</span><span id="line-2226"> public BlockCache[] getBlockCaches() {</span>
+<span class="source-line-no">2227</span><span id="line-2227"> return null;</span>
+<span class="source-line-no">2228</span><span id="line-2228"> }</span>
+<span class="source-line-no">2229</span><span id="line-2229"></span>
+<span class="source-line-no">2230</span><span id="line-2230"> public int getRpcRefCount(BlockCacheKey cacheKey) {</span>
+<span class="source-line-no">2231</span><span id="line-2231"> BucketEntry bucketEntry = backingMap.get(cacheKey);</span>
+<span class="source-line-no">2232</span><span id="line-2232"> if (bucketEntry != null) {</span>
+<span class="source-line-no">2233</span><span id="line-2233"> return bucketEntry.refCnt() - (bucketEntry.markedAsEvicted.get() ? 0 : 1);</span>
+<span class="source-line-no">2234</span><span id="line-2234"> }</span>
+<span class="source-line-no">2235</span><span id="line-2235"> return 0;</span>
+<span class="source-line-no">2236</span><span id="line-2236"> }</span>
+<span class="source-line-no">2237</span><span id="line-2237"></span>
+<span class="source-line-no">2238</span><span id="line-2238"> float getAcceptableFactor() {</span>
+<span class="source-line-no">2239</span><span id="line-2239"> return acceptableFactor;</span>
+<span class="source-line-no">2240</span><span id="line-2240"> }</span>
+<span class="source-line-no">2241</span><span id="line-2241"></span>
+<span class="source-line-no">2242</span><span id="line-2242"> float getMinFactor() {</span>
+<span class="source-line-no">2243</span><span id="line-2243"> return minFactor;</span>
+<span class="source-line-no">2244</span><span id="line-2244"> }</span>
+<span class="source-line-no">2245</span><span id="line-2245"></span>
+<span class="source-line-no">2246</span><span id="line-2246"> float getExtraFreeFactor() {</span>
+<span class="source-line-no">2247</span><span id="line-2247"> return extraFreeFactor;</span>
+<span class="source-line-no">2248</span><span id="line-2248"> }</span>
+<span class="source-line-no">2249</span><span id="line-2249"></span>
+<span class="source-line-no">2250</span><span id="line-2250"> float getSingleFactor() {</span>
+<span class="source-line-no">2251</span><span id="line-2251"> return singleFactor;</span>
+<span class="source-line-no">2252</span><span id="line-2252"> }</span>
+<span class="source-line-no">2253</span><span id="line-2253"></span>
+<span class="source-line-no">2254</span><span id="line-2254"> float getMultiFactor() {</span>
+<span class="source-line-no">2255</span><span id="line-2255"> return multiFactor;</span>
+<span class="source-line-no">2256</span><span id="line-2256"> }</span>
+<span class="source-line-no">2257</span><span id="line-2257"></span>
+<span class="source-line-no">2258</span><span id="line-2258"> float getMemoryFactor() {</span>
+<span class="source-line-no">2259</span><span id="line-2259"> return memoryFactor;</span>
+<span class="source-line-no">2260</span><span id="line-2260"> }</span>
+<span class="source-line-no">2261</span><span id="line-2261"></span>
+<span class="source-line-no">2262</span><span id="line-2262"> long getQueueAdditionWaitTime() {</span>
+<span class="source-line-no">2263</span><span id="line-2263"> return queueAdditionWaitTime;</span>
+<span class="source-line-no">2264</span><span id="line-2264"> }</span>
+<span class="source-line-no">2265</span><span id="line-2265"></span>
+<span class="source-line-no">2266</span><span id="line-2266"> long getPersistenceChunkSize() {</span>
+<span class="source-line-no">2267</span><span id="line-2267"> return persistenceChunkSize;</span>
+<span class="source-line-no">2268</span><span id="line-2268"> }</span>
+<span class="source-line-no">2269</span><span id="line-2269"></span>
+<span class="source-line-no">2270</span><span id="line-2270"> long getBucketcachePersistInterval() {</span>
+<span class="source-line-no">2271</span><span id="line-2271"> return bucketcachePersistInterval;</span>
+<span class="source-line-no">2272</span><span id="line-2272"> }</span>
+<span class="source-line-no">2273</span><span id="line-2273"></span>
+<span class="source-line-no">2274</span><span id="line-2274"> public String getPersistencePath() {</span>
+<span class="source-line-no">2275</span><span id="line-2275"> return persistencePath;</span>
+<span class="source-line-no">2276</span><span id="line-2276"> }</span>
+<span class="source-line-no">2277</span><span id="line-2277"></span>
+<span class="source-line-no">2278</span><span id="line-2278"> /**</span>
+<span class="source-line-no">2279</span><span id="line-2279"> * Wrapped the delegate ConcurrentMap with maintaining its block's reference count.</span>
+<span class="source-line-no">2280</span><span id="line-2280"> */</span>
+<span class="source-line-no">2281</span><span id="line-2281"> static class RAMCache {</span>
+<span class="source-line-no">2282</span><span id="line-2282"> /**</span>
+<span class="source-line-no">2283</span><span id="line-2283"> * Defined the map as {@link ConcurrentHashMap} explicitly here, because in</span>
+<span class="source-line-no">2284</span><span id="line-2284"> * {@link RAMCache#get(BlockCacheKey)} and</span>
+<span class="source-line-no">2285</span><span id="line-2285"> * {@link RAMCache#putIfAbsent(BlockCacheKey, BucketCache.RAMQueueEntry)} , we need to guarantee</span>
+<span class="source-line-no">2286</span><span id="line-2286"> * the atomicity of map#computeIfPresent(key, func) and map#putIfAbsent(key, func). Besides, the</span>
+<span class="source-line-no">2287</span><span id="line-2287"> * func method can execute exactly once only when the key is present(or absent) and under the</span>
+<span class="source-line-no">2288</span><span id="line-2288"> * lock context. Otherwise, the reference count of block will be messed up. Notice that the</span>
+<span class="source-line-no">2289</span><span id="line-2289"> * {@link java.util.concurrent.ConcurrentSkipListMap} can not guarantee that.</span>
+<span class="source-line-no">2290</span><span id="line-2290"> */</span>
+<span class="source-line-no">2291</span><span id="line-2291"> final ConcurrentHashMap<BlockCacheKey, RAMQueueEntry> delegate = new ConcurrentHashMap<>();</span>
<span class="source-line-no">2292</span><span id="line-2292"></span>
-<span class="source-line-no">2293</span><span id="line-2293"> /**</span>
-<span class="source-line-no">2294</span><span id="line-2294"> * Return the previous associated value, or null if absent. It has the same meaning as</span>
-<span class="source-line-no">2295</span><span id="line-2295"> * {@link ConcurrentMap#putIfAbsent(Object, Object)}</span>
-<span class="source-line-no">2296</span><span id="line-2296"> */</span>
-<span class="source-line-no">2297</span><span id="line-2297"> public RAMQueueEntry putIfAbsent(BlockCacheKey key, RAMQueueEntry entry) {</span>
-<span class="source-line-no">2298</span><span id="line-2298"> AtomicBoolean absent = new AtomicBoolean(false);</span>
-<span class="source-line-no">2299</span><span id="line-2299"> RAMQueueEntry re = delegate.computeIfAbsent(key, k -> {</span>
-<span class="source-line-no">2300</span><span id="line-2300"> // The RAMCache reference to this entry, so reference count should be increment.</span>
-<span class="source-line-no">2301</span><span id="line-2301"> entry.getData().retain();</span>
-<span class="source-line-no">2302</span><span id="line-2302"> absent.set(true);</span>
-<span class="source-line-no">2303</span><span id="line-2303"> return entry;</span>
+<span class="source-line-no">2293</span><span id="line-2293"> public boolean containsKey(BlockCacheKey key) {</span>
+<span class="source-line-no">2294</span><span id="line-2294"> return delegate.containsKey(key);</span>
+<span class="source-line-no">2295</span><span id="line-2295"> }</span>
+<span class="source-line-no">2296</span><span id="line-2296"></span>
+<span class="source-line-no">2297</span><span id="line-2297"> public RAMQueueEntry get(BlockCacheKey key) {</span>
+<span class="source-line-no">2298</span><span id="line-2298"> return delegate.computeIfPresent(key, (k, re) -> {</span>
+<span class="source-line-no">2299</span><span id="line-2299"> // It'll be referenced by RPC, so retain atomically here. if the get and retain is not</span>
+<span class="source-line-no">2300</span><span id="line-2300"> // atomic, another thread may remove and release the block, when retaining in this thread we</span>
+<span class="source-line-no">2301</span><span id="line-2301"> // may retain a block with refCnt=0 which is disallowed. (see HBASE-22422)</span>
+<span class="source-line-no">2302</span><span id="line-2302"> re.getData().retain();</span>
+<span class="source-line-no">2303</span><span id="line-2303"> return re;</span>
<span class="source-line-no">2304</span><span id="line-2304"> });</span>
-<span class="source-line-no">2305</span><span id="line-2305"> return absent.get() ? null : re;</span>
-<span class="source-line-no">2306</span><span id="line-2306"> }</span>
-<span class="source-line-no">2307</span><span id="line-2307"></span>
-<span class="source-line-no">2308</span><span id="line-2308"> public boolean remove(BlockCacheKey key) {</span>
-<span class="source-line-no">2309</span><span id="line-2309"> return remove(key, re -> {</span>
-<span class="source-line-no">2310</span><span id="line-2310"> });</span>
-<span class="source-line-no">2311</span><span id="line-2311"> }</span>
-<span class="source-line-no">2312</span><span id="line-2312"></span>
-<span class="source-line-no">2313</span><span id="line-2313"> /**</span>
-<span class="source-line-no">2314</span><span id="line-2314"> * Defined an {@link Consumer} here, because once the removed entry release its reference count,</span>
-<span class="source-line-no">2315</span><span id="line-2315"> * then it's ByteBuffers may be recycled and accessing it outside this method will be thrown an</span>
-<span class="source-line-no">2316</span><span id="line-2316"> * exception. the consumer will access entry to remove before release its reference count.</span>
-<span class="source-line-no">2317</span><span id="line-2317"> * Notice, don't change its reference count in the {@link Consumer}</span>
-<span class="source-line-no">2318</span><span id="line-2318"> */</span>
-<span class="source-line-no">2319</span><span id="line-2319"> public boolean remove(BlockCacheKey key, Consumer<RAMQueueEntry> action) {</span>
-<span class="source-line-no">2320</span><span id="line-2320"> RAMQueueEntry previous = delegate.remove(key);</span>
-<span class="source-line-no">2321</span><span id="line-2321"> action.accept(previous);</span>
-<span class="source-line-no">2322</span><span id="line-2322"> if (previous != null) {</span>
-<span class="source-line-no">2323</span><span id="line-2323"> previous.getData().release();</span>
-<span class="source-line-no">2324</span><span id="line-2324"> }</span>
-<span class="source-line-no">2325</span><span id="line-2325"> return previous != null;</span>
-<span class="source-line-no">2326</span><span id="line-2326"> }</span>
-<span class="source-line-no">2327</span><span id="line-2327"></span>
-<span class="source-line-no">2328</span><span id="line-2328"> public boolean isEmpty() {</span>
-<span class="source-line-no">2329</span><span id="line-2329"> return delegate.isEmpty();</span>
-<span class="source-line-no">2330</span><span id="line-2330"> }</span>
-<span class="source-line-no">2331</span><span id="line-2331"></span>
-<span class="source-line-no">2332</span><span id="line-2332"> public void clear() {</span>
-<span class="source-line-no">2333</span><span id="line-2333"> Iterator<Map.Entry<BlockCacheKey, RAMQueueEntry>> it = delegate.entrySet().iterator();</span>
-<span class="source-line-no">2334</span><span id="line-2334"> while (it.hasNext()) {</span>
-<span class="source-line-no">2335</span><span id="line-2335"> RAMQueueEntry re = it.next().getValue();</span>
-<span class="source-line-no">2336</span><span id="line-2336"> it.remove();</span>
-<span class="source-line-no">2337</span><span id="line-2337"> re.getData().release();</span>
+<span class="source-line-no">2305</span><span id="line-2305"> }</span>
+<span class="source-line-no">2306</span><span id="line-2306"></span>
+<span class="source-line-no">2307</span><span id="line-2307"> /**</span>
+<span class="source-line-no">2308</span><span id="line-2308"> * Return the previous associated value, or null if absent. It has the same meaning as</span>
+<span class="source-line-no">2309</span><span id="line-2309"> * {@link ConcurrentMap#putIfAbsent(Object, Object)}</span>
+<span class="source-line-no">2310</span><span id="line-2310"> */</span>
+<span class="source-line-no">2311</span><span id="line-2311"> public RAMQueueEntry putIfAbsent(BlockCacheKey key, RAMQueueEntry entry) {</span>
+<span class="source-line-no">2312</span><span id="line-2312"> AtomicBoolean absent = new AtomicBoolean(false);</span>
+<span class="source-line-no">2313</span><span id="line-2313"> RAMQueueEntry re = delegate.computeIfAbsent(key, k -> {</span>
+<span class="source-line-no">2314</span><span id="line-2314"> // The RAMCache reference to this entry, so reference count should be increment.</span>
+<span class="source-line-no">2315</span><span id="line-2315"> entry.getData().retain();</span>
+<span class="source-line-no">2316</span><span id="line-2316"> absent.set(true);</span>
+<span class="source-line-no">2317</span><span id="line-2317"> return entry;</span>
+<span class="source-line-no">2318</span><span id="line-2318"> });</span>
+<span class="source-line-no">2319</span><span id="line-2319"> return absent.get() ? null : re;</span>
+<span class="source-line-no">2320</span><span id="line-2320"> }</span>
+<span class="source-line-no">2321</span><span id="line-2321"></span>
+<span class="source-line-no">2322</span><span id="line-2322"> public boolean remove(BlockCacheKey key) {</span>
+<span class="source-line-no">2323</span><span id="line-2323"> return remove(key, re -> {</span>
+<span class="source-line-no">2324</span><span id="line-2324"> });</span>
+<span class="source-line-no">2325</span><span id="line-2325"> }</span>
+<span class="source-line-no">2326</span><span id="line-2326"></span>
+<span class="source-line-no">2327</span><span id="line-2327"> /**</span>
+<span class="source-line-no">2328</span><span id="line-2328"> * Defined an {@link Consumer} here, because once the removed entry release its reference count,</span>
+<span class="source-line-no">2329</span><span id="line-2329"> * then it's ByteBuffers may be recycled and accessing it outside this method will be thrown an</span>
+<span class="source-line-no">2330</span><span id="line-2330"> * exception. the consumer will access entry to remove before release its reference count.</span>
+<span class="source-line-no">2331</span><span id="line-2331"> * Notice, don't change its reference count in the {@link Consumer}</span>
+<span class="source-line-no">2332</span><span id="line-2332"> */</span>
+<span class="source-line-no">2333</span><span id="line-2333"> public boolean remove(BlockCacheKey key, Consumer<RAMQueueEntry> action) {</span>
+<span class="source-line-no">2334</span><span id="line-2334"> RAMQueueEntry previous = delegate.remove(key);</span>
+<span class="source-line-no">2335</span><span id="line-2335"> action.accept(previous);</span>
+<span class="source-line-no">2336</span><span id="line-2336"> if (previous != null) {</span>
+<span class="source-line-no">2337</span><span id="line-2337"> previous.getData().release();</span>
<span class="source-line-no">2338</span><span id="line-2338"> }</span>
-<span class="source-line-no">2339</span><span id="line-2339"> }</span>
-<span class="source-line-no">2340</span><span id="line-2340"></span>
-<span class="source-line-no">2341</span><span id="line-2341"> public boolean hasBlocksForFile(String fileName) {</span>
-<span class="source-line-no">2342</span><span id="line-2342"> return delegate.keySet().stream().filter(key -> key.getHfileName().equals(fileName))</span>
-<span class="source-line-no">2343</span><span id="line-2343"> .findFirst().isPresent();</span>
+<span class="source-line-no">2339</span><span id="line-2339"> return previous != null;</span>
+<span class="source-line-no">2340</span><span id="line-2340"> }</span>
+<span class="source-line-no">2341</span><span id="line-2341"></span>
+<span class="source-line-no">2342</span><span id="line-2342"> public boolean isEmpty() {</span>
+<span class="source-line-no">2343</span><span id="line-2343"> return delegate.isEmpty();</span>
<span class="source-line-no">2344</span><span id="line-2344"> }</span>
-<span class="source-line-no">2345</span><span id="line-2345"> }</span>
-<span class="source-line-no">2346</span><span id="line-2346"></span>
-<span class="source-line-no">2347</span><span id="line-2347"> public Map<BlockCacheKey, BucketEntry> getBackingMap() {</span>
-<span class="source-line-no">2348</span><span id="line-2348"> return backingMap;</span>
-<span class="source-line-no">2349</span><span id="line-2349"> }</span>
-<span class="source-line-no">2350</span><span id="line-2350"></span>
-<span class="source-line-no">2351</span><span id="line-2351"> public AtomicBoolean getBackingMapValidated() {</span>
-<span class="source-line-no">2352</span><span id="line-2352"> return backingMapValidated;</span>
-<span class="source-line-no">2353</span><span id="line-2353"> }</span>
+<span class="source-line-no">2345</span><span id="line-2345"></span>
+<span class="source-line-no">2346</span><span id="line-2346"> public void clear() {</span>
+<span class="source-line-no">2347</span><span id="line-2347"> Iterator<Map.Entry<BlockCacheKey, RAMQueueEntry>> it = delegate.entrySet().iterator();</span>
+<span class="source-line-no">2348</span><span id="line-2348"> while (it.hasNext()) {</span>
+<span class="source-line-no">2349</span><span id="line-2349"> RAMQueueEntry re = it.next().getValue();</span>
+<span class="source-line-no">2350</span><span id="line-2350"> it.remove();</span>
+<span class="source-line-no">2351</span><span id="line-2351"> re.getData().release();</span>
+<span class="source-line-no">2352</span><span id="line-2352"> }</span>
+<span class="source-line-no">2353</span><span id="line-2353"> }</span>
<span class="source-line-no">2354</span><span id="line-2354"></span>
-<span class="source-line-no">2355</span><span id="line-2355"> @Override</span>
-<span class="source-line-no">2356</span><span id="line-2356"> public Optional<Map<String, Pair<String, Long>>> getFullyCachedFiles() {</span>
-<span class="source-line-no">2357</span><span id="line-2357"> return Optional.of(fullyCachedFiles);</span>
-<span class="source-line-no">2358</span><span id="line-2358"> }</span>
-<span class="source-line-no">2359</span><span id="line-2359"></span>
-<span class="source-line-no">2360</span><span id="line-2360"> public static Optional<BucketCache> getBucketCacheFromCacheConfig(CacheConfig cacheConf) {</span>
-<span class="source-line-no">2361</span><span id="line-2361"> if (cacheConf.getBlockCache().isPresent()) {</span>
-<span class="source-line-no">2362</span><span id="line-2362"> BlockCache bc = cacheConf.getBlockCache().get();</span>
-<span class="source-line-no">2363</span><span id="line-2363"> if (bc instanceof CombinedBlockCache) {</span>
-<span class="source-line-no">2364</span><span id="line-2364"> BlockCache l2 = ((CombinedBlockCache) bc).getSecondLevelCache();</span>
-<span class="source-line-no">2365</span><span id="line-2365"> if (l2 instanceof BucketCache) {</span>
-<span class="source-line-no">2366</span><span id="line-2366"> return Optional.of((BucketCache) l2);</span>
-<span class="source-line-no">2367</span><span id="line-2367"> }</span>
-<span class="source-line-no">2368</span><span id="line-2368"> } else if (bc instanceof BucketCache) {</span>
-<span class="source-line-no">2369</span><span id="line-2369"> return Optional.of((BucketCache) bc);</span>
-<span class="source-line-no">2370</span><span id="line-2370"> }</span>
-<span class="source-line-no">2371</span><span id="line-2371"> }</span>
-<span class="source-line-no">2372</span><span id="line-2372"> return Optional.empty();</span>
-<span class="source-line-no">2373</span><span id="line-2373"> }</span>
-<span class="source-line-no">2374</span><span id="line-2374"></span>
-<span class="source-line-no">2375</span><span id="line-2375"> @Override</span>
-<span class="source-line-no">2376</span><span id="line-2376"> public void notifyFileCachingCompleted(Path fileName, int totalBlockCount, int dataBlockCount,</span>
-<span class="source-line-no">2377</span><span id="line-2377"> long size) {</span>
-<span class="source-line-no">2378</span><span id="line-2378"> // block eviction may be happening in the background as prefetch runs,</span>
-<span class="source-line-no">2379</span><span id="line-2379"> // so we need to count all blocks for this file in the backing map under</span>
-<span class="source-line-no">2380</span><span id="line-2380"> // a read lock for the block offset</span>
-<span class="source-line-no">2381</span><span id="line-2381"> final List<ReentrantReadWriteLock> locks = new ArrayList<>();</span>
-<span class="source-line-no">2382</span><span id="line-2382"> LOG.debug("Notifying caching completed for file {}, with total blocks {}, and data blocks {}",</span>
-<span class="source-line-no">2383</span><span id="line-2383"> fileName, totalBlockCount, dataBlockCount);</span>
-<span class="source-line-no">2384</span><span id="line-2384"> try {</span>
-<span class="source-line-no">2385</span><span id="line-2385"> int count = 0;</span>
-<span class="source-line-no">2386</span><span id="line-2386"> LOG.debug("iterating over {} entries in the backing map", backingMap.size());</span>
-<span class="source-line-no">2387</span><span id="line-2387"> Set<BlockCacheKey> result = getAllCacheKeysForFile(fileName.getName(), 0, Long.MAX_VALUE);</span>
-<span class="source-line-no">2388</span><span id="line-2388"> if (result.isEmpty() && StoreFileInfo.isReference(fileName)) {</span>
-<span class="source-line-no">2389</span><span id="line-2389"> result = getAllCacheKeysForFile(</span>
-<span class="source-line-no">2390</span><span id="line-2390"> StoreFileInfo.getReferredToRegionAndFile(fileName.getName()).getSecond(), 0,</span>
-<span class="source-line-no">2391</span><span id="line-2391"> Long.MAX_VALUE);</span>
-<span class="source-line-no">2392</span><span id="line-2392"> }</span>
-<span class="source-line-no">2393</span><span id="line-2393"> for (BlockCacheKey entry : result) {</span>
-<span class="source-line-no">2394</span><span id="line-2394"> LOG.debug("found block for file {} in the backing map. Acquiring read lock for offset {}",</span>
-<span class="source-line-no">2395</span><span id="line-2395"> fileName.getName(), entry.getOffset());</span>
-<span class="source-line-no">2396</span><span id="line-2396"> ReentrantReadWriteLock lock = offsetLock.getLock(entry.getOffset());</span>
-<span class="source-line-no">2397</span><span id="line-2397"> lock.readLock().lock();</span>
-<span class="source-line-no">2398</span><span id="line-2398"> locks.add(lock);</span>
-<span class="source-line-no">2399</span><span id="line-2399"> if (backingMap.containsKey(entry) && entry.getBlockType().isData()) {</span>
-<span class="source-line-no">2400</span><span id="line-2400"> count++;</span>
-<span class="source-line-no">2401</span><span id="line-2401"> }</span>
-<span class="source-line-no">2402</span><span id="line-2402"> }</span>
-<span class="source-line-no">2403</span><span id="line-2403"> // BucketCache would only have data blocks</span>
-<span class="source-line-no">2404</span><span id="line-2404"> if (dataBlockCount == count) {</span>
-<span class="source-line-no">2405</span><span id="line-2405"> LOG.debug("File {} has now been fully cached.", fileName);</span>
-<span class="source-line-no">2406</span><span id="line-2406"> fileCacheCompleted(fileName, size);</span>
-<span class="source-line-no">2407</span><span id="line-2407"> } else {</span>
-<span class="source-line-no">2408</span><span id="line-2408"> LOG.debug(</span>
-<span class="source-line-no">2409</span><span id="line-2409"> "Prefetch executor completed for {}, but only {} data blocks were cached. "</span>
-<span class="source-line-no">2410</span><span id="line-2410"> + "Total data blocks for file: {}. "</span>
-<span class="source-line-no">2411</span><span id="line-2411"> + "Checking for blocks pending cache in cache writer queue.",</span>
-<span class="source-line-no">2412</span><span id="line-2412"> fileName, count, dataBlockCount);</span>
-<span class="source-line-no">2413</span><span id="line-2413"> if (ramCache.hasBlocksForFile(fileName.getName())) {</span>
-<span class="source-line-no">2414</span><span id="line-2414"> for (ReentrantReadWriteLock lock : locks) {</span>
-<span class="source-line-no">2415</span><span id="line-2415"> lock.readLock().unlock();</span>
-<span class="source-line-no">2416</span><span id="line-2416"> }</span>
-<span class="source-line-no">2417</span><span id="line-2417"> locks.clear();</span>
-<span class="source-line-no">2418</span><span id="line-2418"> LOG.debug("There are still blocks pending caching for file {}. Will sleep 100ms "</span>
-<span class="source-line-no">2419</span><span id="line-2419"> + "and try the verification again.", fileName);</span>
-<span class="source-line-no">2420</span><span id="line-2420"> Thread.sleep(100);</span>
-<span class="source-line-no">2421</span><span id="line-2421"> notifyFileCachingCompleted(fileName, totalBlockCount, dataBlockCount, size);</span>
-<span class="source-line-no">2422</span><span id="line-2422"> } else {</span>
-<span class="source-line-no">2423</span><span id="line-2423"> LOG.info(</span>
-<span class="source-line-no">2424</span><span id="line-2424"> "The total block count was {}. We found only {} data blocks cached from "</span>
-<span class="source-line-no">2425</span><span id="line-2425"> + "a total of {} data blocks for file {}, "</span>
-<span class="source-line-no">2426</span><span id="line-2426"> + "but no blocks pending caching. Maybe cache is full or evictions "</span>
-<span class="source-line-no">2427</span><span id="line-2427"> + "happened concurrently to cache prefetch.",</span>
-<span class="source-line-no">2428</span><span id="line-2428"> totalBlockCount, count, dataBlockCount, fileName);</span>
-<span class="source-line-no">2429</span><span id="line-2429"> }</span>
-<span class="source-line-no">2430</span><span id="line-2430"> }</span>
-<span class="source-line-no">2431</span><span id="line-2431"> } catch (InterruptedException e) {</span>
-<span class="source-line-no">2432</span><span id="line-2432"> throw new RuntimeException(e);</span>
-<span class="source-line-no">2433</span><span id="line-2433"> } finally {</span>
-<span class="source-line-no">2434</span><span id="line-2434"> for (ReentrantReadWriteLock lock : locks) {</span>
-<span class="source-line-no">2435</span><span id="line-2435"> lock.readLock().unlock();</span>
-<span class="source-line-no">2436</span><span id="line-2436"> }</span>
-<span class="source-line-no">2437</span><span id="line-2437"> }</span>
-<span class="source-line-no">2438</span><span id="line-2438"> }</span>
-<span class="source-line-no">2439</span><span id="line-2439"></span>
-<span class="source-line-no">2440</span><span id="line-2440"> @Override</span>
-<span class="source-line-no">2441</span><span id="line-2441"> public Optional<Boolean> blockFitsIntoTheCache(HFileBlock block) {</span>
-<span class="source-line-no">2442</span><span id="line-2442"> if (!isCacheInitialized("blockFitsIntoTheCache")) {</span>
-<span class="source-line-no">2443</span><span id="line-2443"> return Optional.of(false);</span>
-<span class="source-line-no">2444</span><span id="line-2444"> }</span>
-<span class="source-line-no">2445</span><span id="line-2445"></span>
-<span class="source-line-no">2446</span><span id="line-2446"> long currentUsed = bucketAllocator.getUsedSize();</span>
-<span class="source-line-no">2447</span><span id="line-2447"> boolean result = (currentUsed + block.getOnDiskSizeWithHeader()) < acceptableSize();</span>
-<span class="source-line-no">2448</span><span id="line-2448"> return Optional.of(result);</span>
-<span class="source-line-no">2449</span><span id="line-2449"> }</span>
-<span class="source-line-no">2450</span><span id="line-2450"></span>
-<span class="source-line-no">2451</span><span id="line-2451"> @Override</span>
-<span class="source-line-no">2452</span><span id="line-2452"> public Optional<Boolean> shouldCacheFile(HFileInfo hFileInfo, Configuration conf) {</span>
-<span class="source-line-no">2453</span><span id="line-2453"> String fileName = hFileInfo.getHFileContext().getHFileName();</span>
-<span class="source-line-no">2454</span><span id="line-2454"> DataTieringManager dataTieringManager = DataTieringManager.getInstance();</span>
-<span class="source-line-no">2455</span><span id="line-2455"> if (dataTieringManager != null && !dataTieringManager.isHotData(hFileInfo, conf)) {</span>
-<span class="source-line-no">2456</span><span id="line-2456"> LOG.debug("Data tiering is enabled for file: '{}' and it is not hot data", fileName);</span>
+<span class="source-line-no">2355</span><span id="line-2355"> public boolean hasBlocksForFile(String fileName) {</span>
+<span class="source-line-no">2356</span><span id="line-2356"> return delegate.keySet().stream().filter(key -> key.getHfileName().equals(fileName))</span>
+<span class="source-line-no">2357</span><span id="line-2357"> .findFirst().isPresent();</span>
+<span class="source-line-no">2358</span><span id="line-2358"> }</span>
+<span class="source-line-no">2359</span><span id="line-2359"> }</span>
+<span class="source-line-no">2360</span><span id="line-2360"></span>
+<span class="source-line-no">2361</span><span id="line-2361"> public Map<BlockCacheKey, BucketEntry> getBackingMap() {</span>
+<span class="source-line-no">2362</span><span id="line-2362"> return backingMap;</span>
+<span class="source-line-no">2363</span><span id="line-2363"> }</span>
+<span class="source-line-no">2364</span><span id="line-2364"></span>
+<span class="source-line-no">2365</span><span id="line-2365"> public AtomicBoolean getBackingMapValidated() {</span>
+<span class="source-line-no">2366</span><span id="line-2366"> return backingMapValidated;</span>
+<span class="source-line-no">2367</span><span id="line-2367"> }</span>
+<span class="source-line-no">2368</span><span id="line-2368"></span>
+<span class="source-line-no">2369</span><span id="line-2369"> @Override</span>
+<span class="source-line-no">2370</span><span id="line-2370"> public Optional<Map<String, Pair<String, Long>>> getFullyCachedFiles() {</span>
+<span class="source-line-no">2371</span><span id="line-2371"> return Optional.of(fullyCachedFiles);</span>
+<span class="source-line-no">2372</span><span id="line-2372"> }</span>
+<span class="source-line-no">2373</span><span id="line-2373"></span>
+<span class="source-line-no">2374</span><span id="line-2374"> public static Optional<BucketCache> getBucketCacheFromCacheConfig(CacheConfig cacheConf) {</span>
+<span class="source-line-no">2375</span><span id="line-2375"> if (cacheConf.getBlockCache().isPresent()) {</span>
+<span class="source-line-no">2376</span><span id="line-2376"> BlockCache bc = cacheConf.getBlockCache().get();</span>
+<span class="source-line-no">2377</span><span id="line-2377"> if (bc instanceof CombinedBlockCache) {</span>
+<span class="source-line-no">2378</span><span id="line-2378"> BlockCache l2 = ((CombinedBlockCache) bc).getSecondLevelCache();</span>
+<span class="source-line-no">2379</span><span id="line-2379"> if (l2 instanceof BucketCache) {</span>
+<span class="source-line-no">2380</span><span id="line-2380"> return Optional.of((BucketCache) l2);</span>
+<span class="source-line-no">2381</span><span id="line-2381"> }</span>
+<span class="source-line-no">2382</span><span id="line-2382"> } else if (bc instanceof BucketCache) {</span>
+<span class="source-line-no">2383</span><span id="line-2383"> return Optional.of((BucketCache) bc);</span>
+<span class="source-line-no">2384</span><span id="line-2384"> }</span>
+<span class="source-line-no">2385</span><span id="line-2385"> }</span>
+<span class="source-line-no">2386</span><span id="line-2386"> return Optional.empty();</span>
+<span class="source-line-no">2387</span><span id="line-2387"> }</span>
+<span class="source-line-no">2388</span><span id="line-2388"></span>
+<span class="source-line-no">2389</span><span id="line-2389"> @Override</span>
+<span class="source-line-no">2390</span><span id="line-2390"> public void notifyFileCachingCompleted(Path fileName, int totalBlockCount, int dataBlockCount,</span>
+<span class="source-line-no">2391</span><span id="line-2391"> long size) {</span>
+<span class="source-line-no">2392</span><span id="line-2392"> // block eviction may be happening in the background as prefetch runs,</span>
+<span class="source-line-no">2393</span><span id="line-2393"> // so we need to count all blocks for this file in the backing map under</span>
+<span class="source-line-no">2394</span><span id="line-2394"> // a read lock for the block offset</span>
+<span class="source-line-no">2395</span><span id="line-2395"> final List<ReentrantReadWriteLock> locks = new ArrayList<>();</span>
+<span class="source-line-no">2396</span><span id="line-2396"> LOG.debug("Notifying caching completed for file {}, with total blocks {}, and data blocks {}",</span>
+<span class="source-line-no">2397</span><span id="line-2397"> fileName, totalBlockCount, dataBlockCount);</span>
+<span class="source-line-no">2398</span><span id="line-2398"> try {</span>
+<span class="source-line-no">2399</span><span id="line-2399"> int count = 0;</span>
+<span class="source-line-no">2400</span><span id="line-2400"> LOG.debug("iterating over {} entries in the backing map", backingMap.size());</span>
+<span class="source-line-no">2401</span><span id="line-2401"> Set<BlockCacheKey> result = getAllCacheKeysForFile(fileName.getName(), 0, Long.MAX_VALUE);</span>
+<span class="source-line-no">2402</span><span id="line-2402"> if (result.isEmpty() && StoreFileInfo.isReference(fileName)) {</span>
+<span class="source-line-no">2403</span><span id="line-2403"> result = getAllCacheKeysForFile(</span>
+<span class="source-line-no">2404</span><span id="line-2404"> StoreFileInfo.getReferredToRegionAndFile(fileName.getName()).getSecond(), 0,</span>
+<span class="source-line-no">2405</span><span id="line-2405"> Long.MAX_VALUE);</span>
+<span class="source-line-no">2406</span><span id="line-2406"> }</span>
+<span class="source-line-no">2407</span><span id="line-2407"> for (BlockCacheKey entry : result) {</span>
+<span class="source-line-no">2408</span><span id="line-2408"> LOG.debug("found block for file {} in the backing map. Acquiring read lock for offset {}",</span>
+<span class="source-line-no">2409</span><span id="line-2409"> fileName.getName(), entry.getOffset());</span>
+<span class="source-line-no">2410</span><span id="line-2410"> ReentrantReadWriteLock lock = offsetLock.getLock(entry.getOffset());</span>
+<span class="source-line-no">2411</span><span id="line-2411"> lock.readLock().lock();</span>
+<span class="source-line-no">2412</span><span id="line-2412"> locks.add(lock);</span>
+<span class="source-line-no">2413</span><span id="line-2413"> if (backingMap.containsKey(entry) && entry.getBlockType().isData()) {</span>
+<span class="source-line-no">2414</span><span id="line-2414"> count++;</span>
+<span class="source-line-no">2415</span><span id="line-2415"> }</span>
+<span class="source-line-no">2416</span><span id="line-2416"> }</span>
+<span class="source-line-no">2417</span><span id="line-2417"> // BucketCache would only have data blocks</span>
+<span class="source-line-no">2418</span><span id="line-2418"> if (dataBlockCount == count) {</span>
+<span class="source-line-no">2419</span><span id="line-2419"> LOG.debug("File {} has now been fully cached.", fileName);</span>
+<span class="source-line-no">2420</span><span id="line-2420"> fileCacheCompleted(fileName, size);</span>
+<span class="source-line-no">2421</span><span id="line-2421"> } else {</span>
+<span class="source-line-no">2422</span><span id="line-2422"> LOG.debug(</span>
+<span class="source-line-no">2423</span><span id="line-2423"> "Prefetch executor completed for {}, but only {} data blocks were cached. "</span>
+<span class="source-line-no">2424</span><span id="line-2424"> + "Total data blocks for file: {}. "</span>
+<span class="source-line-no">2425</span><span id="line-2425"> + "Checking for blocks pending cache in cache writer queue.",</span>
+<span class="source-line-no">2426</span><span id="line-2426"> fileName, count, dataBlockCount);</span>
+<span class="source-line-no">2427</span><span id="line-2427"> if (ramCache.hasBlocksForFile(fileName.getName())) {</span>
+<span class="source-line-no">2428</span><span id="line-2428"> for (ReentrantReadWriteLock lock : locks) {</span>
+<span class="source-line-no">2429</span><span id="line-2429"> lock.readLock().unlock();</span>
+<span class="source-line-no">2430</span><span id="line-2430"> }</span>
+<span class="source-line-no">2431</span><span id="line-2431"> locks.clear();</span>
+<span class="source-line-no">2432</span><span id="line-2432"> LOG.debug("There are still blocks pending caching for file {}. Will sleep 100ms "</span>
+<span class="source-line-no">2433</span><span id="line-2433"> + "and try the verification again.", fileName);</span>
+<span class="source-line-no">2434</span><span id="line-2434"> Thread.sleep(100);</span>
+<span class="source-line-no">2435</span><span id="line-2435"> notifyFileCachingCompleted(fileName, totalBlockCount, dataBlockCount, size);</span>
+<span class="source-line-no">2436</span><span id="line-2436"> } else {</span>
+<span class="source-line-no">2437</span><span id="line-2437"> LOG.info(</span>
+<span class="source-line-no">2438</span><span id="line-2438"> "The total block count was {}. We found only {} data blocks cached from "</span>
+<span class="source-line-no">2439</span><span id="line-2439"> + "a total of {} data blocks for file {}, "</span>
+<span class="source-line-no">2440</span><span id="line-2440"> + "but no blocks pending caching. Maybe cache is full or evictions "</span>
+<span class="source-line-no">2441</span><span id="line-2441"> + "happened concurrently to cache prefetch.",</span>
+<span class="source-line-no">2442</span><span id="line-2442"> totalBlockCount, count, dataBlockCount, fileName);</span>
+<span class="source-line-no">2443</span><span id="line-2443"> }</span>
+<span class="source-line-no">2444</span><span id="line-2444"> }</span>
+<span class="source-line-no">2445</span><span id="line-2445"> } catch (InterruptedException e) {</span>
+<span class="source-line-no">2446</span><span id="line-2446"> throw new RuntimeException(e);</span>
+<span class="source-line-no">2447</span><span id="line-2447"> } finally {</span>
+<span class="source-line-no">2448</span><span id="line-2448"> for (ReentrantReadWriteLock lock : locks) {</span>
+<span class="source-line-no">2449</span><span id="line-2449"> lock.readLock().unlock();</span>
+<span class="source-line-no">2450</span><span id="line-2450"> }</span>
+<span class="source-line-no">2451</span><span id="line-2451"> }</span>
+<span class="source-line-no">2452</span><span id="line-2452"> }</span>
+<span class="source-line-no">2453</span><span id="line-2453"></span>
+<span class="source-line-no">2454</span><span id="line-2454"> @Override</span>
+<span class="source-line-no">2455</span><span id="line-2455"> public Optional<Boolean> blockFitsIntoTheCache(HFileBlock block) {</span>
+<span class="source-line-no">2456</span><span id="line-2456"> if (!isCacheInitialized("blockFitsIntoTheCache")) {</span>
<span class="source-line-no">2457</span><span id="line-2457"> return Optional.of(false);</span>
<span class="source-line-no">2458</span><span id="line-2458"> }</span>
-<span class="source-line-no">2459</span><span id="line-2459"> // if we don't have the file in fullyCachedFiles, we should cache it</span>
-<span class="source-line-no">2460</span><span id="line-2460"> return Optional.of(!fullyCachedFiles.containsKey(fileName));</span>
-<span class="source-line-no">2461</span><span id="line-2461"> }</span>
-<span class="source-line-no">2462</span><span id="line-2462"></span>
-<span class="source-line-no">2463</span><span id="line-2463"> @Override</span>
-<span class="source-line-no">2464</span><span id="line-2464"> public Optional<Boolean> shouldCacheBlock(BlockCacheKey key, long maxTimestamp,</span>
-<span class="source-line-no">2465</span><span id="line-2465"> Configuration conf) {</span>
-<span class="source-line-no">2466</span><span id="line-2466"> DataTieringManager dataTieringManager = DataTieringManager.getInstance();</span>
-<span class="source-line-no">2467</span><span id="line-2467"> if (dataTieringManager != null && !dataTieringManager.isHotData(maxTimestamp, conf)) {</span>
-<span class="source-line-no">2468</span><span id="line-2468"> LOG.debug("Data tiering is enabled for file: '{}' and it is not hot data",</span>
-<span class="source-line-no">2469</span><span id="line-2469"> key.getHfileName());</span>
-<span class="source-line-no">2470</span><span id="line-2470"> return Optional.of(false);</span>
-<span class="source-line-no">2471</span><span id="line-2471"> }</span>
-<span class="source-line-no">2472</span><span id="line-2472"> return Optional.of(true);</span>
-<span class="source-line-no">2473</span><span id="line-2473"> }</span>
-<span class="source-line-no">2474</span><span id="line-2474"></span>
-<span class="source-line-no">2475</span><span id="line-2475"> @Override</span>
-<span class="source-line-no">2476</span><span id="line-2476"> public Optional<Boolean> isAlreadyCached(BlockCacheKey key) {</span>
-<span class="source-line-no">2477</span><span id="line-2477"> boolean foundKey = backingMap.containsKey(key);</span>
-<span class="source-line-no">2478</span><span id="line-2478"> // if there's no entry for the key itself, we need to check if this key is for a reference,</span>
-<span class="source-line-no">2479</span><span id="line-2479"> // and if so, look for a block from the referenced file using this getBlockForReference method.</span>
-<span class="source-line-no">2480</span><span id="line-2480"> return Optional.of(foundKey ? true : getBlockForReference(key) != null);</span>
-<span class="source-line-no">2481</span><span id="line-2481"> }</span>
-<span class="source-line-no">2482</span><span id="line-2482"></span>
-<span class="source-line-no">2483</span><span id="line-2483"> @Override</span>
-<span class="source-line-no">2484</span><span id="line-2484"> public Optional<Integer> getBlockSize(BlockCacheKey key) {</span>
-<span class="source-line-no">2485</span><span id="line-2485"> BucketEntry entry = backingMap.get(key);</span>
-<span class="source-line-no">2486</span><span id="line-2486"> if (entry == null) {</span>
-<span class="source-line-no">2487</span><span id="line-2487"> // the key might be for a reference tha we had found the block from the referenced file in</span>
-<span class="source-line-no">2488</span><span id="line-2488"> // the cache when we first tried to cache it.</span>
-<span class="source-line-no">2489</span><span id="line-2489"> entry = getBlockForReference(key);</span>
-<span class="source-line-no">2490</span><span id="line-2490"> return entry == null ? Optional.empty() : Optional.of(entry.getOnDiskSizeWithHeader());</span>
-<span class="source-line-no">2491</span><span id="line-2491"> } else {</span>
-<span class="source-line-no">2492</span><span id="line-2492"> return Optional.of(entry.getOnDiskSizeWithHeader());</span>
-<span class="source-line-no">2493</span><span id="line-2493"> }</span>
-<span class="source-line-no">2494</span><span id="line-2494"></span>
+<span class="source-line-no">2459</span><span id="line-2459"></span>
+<span class="source-line-no">2460</span><span id="line-2460"> long currentUsed = bucketAllocator.getUsedSize();</span>
+<span class="source-line-no">2461</span><span id="line-2461"> boolean result = (currentUsed + block.getOnDiskSizeWithHeader()) < acceptableSize();</span>
+<span class="source-line-no">2462</span><span id="line-2462"> return Optional.of(result);</span>
+<span class="source-line-no">2463</span><span id="line-2463"> }</span>
+<span class="source-line-no">2464</span><span id="line-2464"></span>
+<span class="source-line-no">2465</span><span id="line-2465"> @Override</span>
+<span class="source-line-no">2466</span><span id="line-2466"> public Optional<Boolean> shouldCacheFile(HFileInfo hFileInfo, Configuration conf) {</span>
+<span class="source-line-no">2467</span><span id="line-2467"> String fileName = hFileInfo.getHFileContext().getHFileName();</span>
+<span class="source-line-no">2468</span><span id="line-2468"> DataTieringManager dataTieringManager = DataTieringManager.getInstance();</span>
+<span class="source-line-no">2469</span><span id="line-2469"> if (dataTieringManager != null && !dataTieringManager.isHotData(hFileInfo, conf)) {</span>
+<span class="source-line-no">2470</span><span id="line-2470"> LOG.debug("Data tiering is enabled for file: '{}' and it is not hot data", fileName);</span>
+<span class="source-line-no">2471</span><span id="line-2471"> return Optional.of(false);</span>
+<span class="source-line-no">2472</span><span id="line-2472"> }</span>
+<span class="source-line-no">2473</span><span id="line-2473"> // if we don't have the file in fullyCachedFiles, we should cache it</span>
+<span class="source-line-no">2474</span><span id="line-2474"> return Optional.of(!fullyCachedFiles.containsKey(fileName));</span>
+<span class="source-line-no">2475</span><span id="line-2475"> }</span>
+<span class="source-line-no">2476</span><span id="line-2476"></span>
+<span class="source-line-no">2477</span><span id="line-2477"> @Override</span>
+<span class="source-line-no">2478</span><span id="line-2478"> public Optional<Boolean> shouldCacheBlock(BlockCacheKey key, long maxTimestamp,</span>
+<span class="source-line-no">2479</span><span id="line-2479"> Configuration conf) {</span>
+<span class="source-line-no">2480</span><span id="line-2480"> DataTieringManager dataTieringManager = DataTieringManager.getInstance();</span>
+<span class="source-line-no">2481</span><span id="line-2481"> if (dataTieringManager != null && !dataTieringManager.isHotData(maxTimestamp, conf)) {</span>
+<span class="source-line-no">2482</span><span id="line-2482"> LOG.debug("Data tiering is enabled for file: '{}' and it is not hot data",</span>
+<span class="source-line-no">2483</span><span id="line-2483"> key.getHfileName());</span>
+<span class="source-line-no">2484</span><span id="line-2484"> return Optional.of(false);</span>
+<span class="source-line-no">2485</span><span id="line-2485"> }</span>
+<span class="source-line-no">2486</span><span id="line-2486"> return Optional.of(true);</span>
+<span class="source-line-no">2487</span><span id="line-2487"> }</span>
+<span class="source-line-no">2488</span><span id="line-2488"></span>
+<span class="source-line-no">2489</span><span id="line-2489"> @Override</span>
+<span class="source-line-no">2490</span><span id="line-2490"> public Optional<Boolean> isAlreadyCached(BlockCacheKey key) {</span>
+<span class="source-line-no">2491</span><span id="line-2491"> boolean foundKey = backingMap.containsKey(key);</span>
+<span class="source-line-no">2492</span><span id="line-2492"> // if there's no entry for the key itself, we need to check if this key is for a reference,</span>
+<span class="source-line-no">2493</span><span id="line-2493"> // and if so, look for a block from the referenced file using this getBlockForReference method.</span>
+<span class="source-line-no">2494</span><span id="line-2494"> return Optional.of(foundKey ? true : getBlockForReference(key) != null);</span>
<span class="source-line-no">2495</span><span id="line-2495"> }</span>
<span class="source-line-no">2496</span><span id="line-2496"></span>
-<span class="source-line-no">2497</span><span id="line-2497"> boolean isCacheInitialized(String api) {</span>
-<span class="source-line-no">2498</span><span id="line-2498"> if (cacheState == CacheState.INITIALIZING) {</span>
-<span class="source-line-no">2499</span><span id="line-2499"> LOG.warn("Bucket initialisation pending at {}", api);</span>
-<span class="source-line-no">2500</span><span id="line-2500"> return false;</span>
-<span class="source-line-no">2501</span><span id="line-2501"> }</span>
-<span class="source-line-no">2502</span><span id="line-2502"> return true;</span>
-<span class="source-line-no">2503</span><span id="line-2503"> }</span>
-<span class="source-line-no">2504</span><span id="line-2504"></span>
-<span class="source-line-no">2505</span><span id="line-2505"> @Override</span>
-<span class="source-line-no">2506</span><span id="line-2506"> public boolean waitForCacheInitialization(long timeout) {</span>
-<span class="source-line-no">2507</span><span id="line-2507"> while (cacheState == CacheState.INITIALIZING) {</span>
-<span class="source-line-no">2508</span><span id="line-2508"> if (timeout <= 0) {</span>
-<span class="source-line-no">2509</span><span id="line-2509"> break;</span>
-<span class="source-line-no">2510</span><span id="line-2510"> }</span>
-<span class="source-line-no">2511</span><span id="line-2511"> try {</span>
-<span class="source-line-no">2512</span><span id="line-2512"> Thread.sleep(100);</span>
-<span class="source-line-no">2513</span><span id="line-2513"> } catch (InterruptedException e) {</span>
-<span class="source-line-no">2514</span><span id="line-2514"> LOG.warn("Interrupted while waiting for cache initialization", e);</span>
-<span class="source-line-no">2515</span><span id="line-2515"> Thread.currentThread().interrupt();</span>
-<span class="source-line-no">2516</span><span id="line-2516"> break;</span>
-<span class="source-line-no">2517</span><span id="line-2517"> }</span>
-<span class="source-line-no">2518</span><span id="line-2518"> timeout -= 100;</span>
-<span class="source-line-no">2519</span><span id="line-2519"> }</span>
-<span class="source-line-no">2520</span><span id="line-2520"> return isCacheEnabled();</span>
-<span class="source-line-no">2521</span><span id="line-2521"> }</span>
-<span class="source-line-no">2522</span><span id="line-2522">}</span>
+<span class="source-line-no">2497</span><span id="line-2497"> @Override</span>
+<span class="source-line-no">2498</span><span id="line-2498"> public Optional<Integer> getBlockSize(BlockCacheKey key) {</span>
+<span class="source-line-no">2499</span><span id="line-2499"> BucketEntry entry = backingMap.get(key);</span>
+<span class="source-line-no">2500</span><span id="line-2500"> if (entry == null) {</span>
+<span class="source-line-no">2501</span><span id="line-2501"> // the key might be for a reference tha we had found the block from the referenced file in</span>
+<span class="source-line-no">2502</span><span id="line-2502"> // the cache when we first tried to cache it.</span>
+<span class="source-line-no">2503</span><span id="line-2503"> entry = getBlockForReference(key);</span>
+<span class="source-line-no">2504</span><span id="line-2504"> return entry == null ? Optional.empty() : Optional.of(entry.getOnDiskSizeWithHeader());</span>
+<span class="source-line-no">2505</span><span id="line-2505"> } else {</span>
+<span class="source-line-no">2506</span><span id="line-2506"> return Optional.of(entry.getOnDiskSizeWithHeader());</span>
+<span class="source-line-no">2507</span><span id="line-2507"> }</span>
+<span class="source-line-no">2508</span><span id="line-2508"></span>
+<span class="source-line-no">2509</span><span id="line-2509"> }</span>
+<span class="source-line-no">2510</span><span id="line-2510"></span>
+<span class="source-line-no">2511</span><span id="line-2511"> boolean isCacheInitialized(String api) {</span>
+<span class="source-line-no">2512</span><span id="line-2512"> if (cacheState == CacheState.INITIALIZING) {</span>
+<span class="source-line-no">2513</span><span id="line-2513"> LOG.warn("Bucket initialisation pending at {}", api);</span>
+<span class="source-line-no">2514</span><span id="line-2514"> return false;</span>
+<span class="source-line-no">2515</span><span id="line-2515"> }</span>
+<span class="source-line-no">2516</span><span id="line-2516"> return true;</span>
+<span class="source-line-no">2517</span><span id="line-2517"> }</span>
+<span class="source-line-no">2518</span><span id="line-2518"></span>
+<span class="source-line-no">2519</span><span id="line-2519"> @Override</span>
+<span class="source-line-no">2520</span><span id="line-2520"> public boolean waitForCacheInitialization(long timeout) {</span>
+<span class="source-line-no">2521</span><span id="line-2521"> while (cacheState == CacheState.INITIALIZING) {</span>
+<span class="source-line-no">2522</span><span id="line-2522"> if (timeout <= 0) {</span>
+<span class="source-line-no">2523</span><span id="line-2523"> break;</span>
+<span class="source-line-no">2524</span><span id="line-2524"> }</span>
+<span class="source-line-no">2525</span><span id="line-2525"> try {</span>
+<span class="source-line-no">2526</span><span id="line-2526"> Thread.sleep(100);</span>
+<span class="source-line-no">2527</span><span id="line-2527"> } catch (InterruptedException e) {</span>
+<span class="source-line-no">2528</span><span id="line-2528"> LOG.warn("Interrupted while waiting for cache initialization", e);</span>
+<span class="source-line-no">2529</span><span id="line-2529"> Thread.currentThread().interrupt();</span>
+<span class="source-line-no">2530</span><span id="line-2530"> break;</span>
+<span class="source-line-no">2531</span><span id="line-2531"> }</span>
+<span class="source-line-no">2532</span><span id="line-2532"> timeout -= 100;</span>
+<span class="source-line-no">2533</span><span id="line-2533"> }</span>
+<span class="source-line-no">2534</span><span id="line-2534"> return isCacheEnabled();</span>
+<span class="source-line-no">2535</span><span id="line-2535"> }</span>
+<span class="source-line-no">2536</span><span id="line-2536">}</span>
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html
index cbb54929061..f9c31c0761a 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.RAMQueueEntry.html
@@ -1624,915 +1624,929 @@
<span class="source-line-no">1611</span><span id="line-1611"> int pblen = ProtobufMagic.lengthOfPBMagic();</span>
<span class="source-line-no">1612</span><span id="line-1612"> byte[] pbuf = new byte[pblen];</span>
<span class="source-line-no">1613</span><span id="line-1613"> IOUtils.readFully(in, pbuf, 0, pblen);</span>
-<span class="source-line-no">1614</span><span id="line-1614"> if (ProtobufMagic.isPBMagicPrefix(pbuf)) {</span>
-<span class="source-line-no">1615</span><span id="line-1615"> LOG.info("Reading old format of persistence.");</span>
-<span class="source-line-no">1616</span><span id="line-1616"> // The old non-chunked version of backing map persistence.</span>
-<span class="source-line-no">1617</span><span id="line-1617"> parsePB(BucketCacheProtos.BucketCacheEntry.parseDelimitedFrom(in));</span>
-<span class="source-line-no">1618</span><span id="line-1618"> } else if (Arrays.equals(pbuf, BucketProtoUtils.PB_MAGIC_V2)) {</span>
-<span class="source-line-no">1619</span><span id="line-1619"> // The new persistence format of chunked persistence.</span>
-<span class="source-line-no">1620</span><span id="line-1620"> LOG.info("Reading new chunked format of persistence.");</span>
-<span class="source-line-no">1621</span><span id="line-1621"> retrieveChunkedBackingMap(in);</span>
-<span class="source-line-no">1622</span><span id="line-1622"> } else {</span>
-<span class="source-line-no">1623</span><span id="line-1623"> // In 3.0 we have enough flexibility to dump the old cache data.</span>
-<span class="source-line-no">1624</span><span id="line-1624"> // TODO: In 2.x line, this might need to be filled in to support reading the old format</span>
-<span class="source-line-no">1625</span><span id="line-1625"> throw new IOException(</span>
-<span class="source-line-no">1626</span><span id="line-1626"> "Persistence file does not start with protobuf magic number. " + persistencePath);</span>
-<span class="source-line-no">1627</span><span id="line-1627"> }</span>
-<span class="source-line-no">1628</span><span id="line-1628"> bucketAllocator = new BucketAllocator(cacheCapacity, bucketSizes, backingMap, realCacheSize);</span>
-<span class="source-line-no">1629</span><span id="line-1629"> blockNumber.add(backingMap.size());</span>
-<span class="source-line-no">1630</span><span id="line-1630"> LOG.info("Bucket cache retrieved from file successfully with size: {}", backingMap.size());</span>
-<span class="source-line-no">1631</span><span id="line-1631"> }</span>
-<span class="source-line-no">1632</span><span id="line-1632"> }</span>
-<span class="source-line-no">1633</span><span id="line-1633"></span>
-<span class="source-line-no">1634</span><span id="line-1634"> private void updateRegionSizeMapWhileRetrievingFromFile() {</span>
-<span class="source-line-no">1635</span><span id="line-1635"> // Update the regionCachedSize with the region size while restarting the region server</span>
-<span class="source-line-no">1636</span><span id="line-1636"> if (LOG.isDebugEnabled()) {</span>
-<span class="source-line-no">1637</span><span id="line-1637"> LOG.debug("Updating region size map after retrieving cached file list");</span>
-<span class="source-line-no">1638</span><span id="line-1638"> dumpPrefetchList();</span>
-<span class="source-line-no">1639</span><span id="line-1639"> }</span>
-<span class="source-line-no">1640</span><span id="line-1640"> regionCachedSize.clear();</span>
-<span class="source-line-no">1641</span><span id="line-1641"> fullyCachedFiles.forEach((hFileName, hFileSize) -> {</span>
-<span class="source-line-no">1642</span><span id="line-1642"> // Get the region name for each file</span>
-<span class="source-line-no">1643</span><span id="line-1643"> String regionEncodedName = hFileSize.getFirst();</span>
-<span class="source-line-no">1644</span><span id="line-1644"> long cachedFileSize = hFileSize.getSecond();</span>
-<span class="source-line-no">1645</span><span id="line-1645"> regionCachedSize.merge(regionEncodedName, cachedFileSize,</span>
-<span class="source-line-no">1646</span><span id="line-1646"> (oldpf, fileSize) -> oldpf + fileSize);</span>
-<span class="source-line-no">1647</span><span id="line-1647"> });</span>
-<span class="source-line-no">1648</span><span id="line-1648"> }</span>
-<span class="source-line-no">1649</span><span id="line-1649"></span>
-<span class="source-line-no">1650</span><span id="line-1650"> private void dumpPrefetchList() {</span>
-<span class="source-line-no">1651</span><span id="line-1651"> for (Map.Entry<String, Pair<String, Long>> outerEntry : fullyCachedFiles.entrySet()) {</span>
-<span class="source-line-no">1652</span><span id="line-1652"> LOG.debug("Cached File Entry:<{},<{},{}>>", outerEntry.getKey(),</span>
-<span class="source-line-no">1653</span><span id="line-1653"> outerEntry.getValue().getFirst(), outerEntry.getValue().getSecond());</span>
-<span class="source-line-no">1654</span><span id="line-1654"> }</span>
+<span class="source-line-no">1614</span><span id="line-1614"></span>
+<span class="source-line-no">1615</span><span id="line-1615"> if (ProtobufMagic.isPBMagicPrefix(pbuf)) {</span>
+<span class="source-line-no">1616</span><span id="line-1616"> LOG.info("Reading old format of persistence.");</span>
+<span class="source-line-no">1617</span><span id="line-1617"> // The old non-chunked version of backing map persistence.</span>
+<span class="source-line-no">1618</span><span id="line-1618"> BucketCacheProtos.BucketCacheEntry cacheEntry =</span>
+<span class="source-line-no">1619</span><span id="line-1619"> BucketCacheProtos.BucketCacheEntry.parseDelimitedFrom(in);</span>
+<span class="source-line-no">1620</span><span id="line-1620"> if (cacheEntry == null) {</span>
+<span class="source-line-no">1621</span><span id="line-1621"> throw new IOException(</span>
+<span class="source-line-no">1622</span><span id="line-1622"> "Failed to parse cache entry from persistence file: " + persistencePath);</span>
+<span class="source-line-no">1623</span><span id="line-1623"> }</span>
+<span class="source-line-no">1624</span><span id="line-1624"> parsePB(cacheEntry);</span>
+<span class="source-line-no">1625</span><span id="line-1625"> } else if (Arrays.equals(pbuf, BucketProtoUtils.PB_MAGIC_V2)) {</span>
+<span class="source-line-no">1626</span><span id="line-1626"> // The new persistence format of chunked persistence.</span>
+<span class="source-line-no">1627</span><span id="line-1627"> LOG.info("Reading new chunked format of persistence.");</span>
+<span class="source-line-no">1628</span><span id="line-1628"> retrieveChunkedBackingMap(in);</span>
+<span class="source-line-no">1629</span><span id="line-1629"> } else {</span>
+<span class="source-line-no">1630</span><span id="line-1630"> // In 3.0 we have enough flexibility to dump the old cache data.</span>
+<span class="source-line-no">1631</span><span id="line-1631"> // TODO: In 2.x line, this might need to be filled in to support reading the old format</span>
+<span class="source-line-no">1632</span><span id="line-1632"> throw new IOException(</span>
+<span class="source-line-no">1633</span><span id="line-1633"> "Persistence file does not start with protobuf magic number. " + persistencePath);</span>
+<span class="source-line-no">1634</span><span id="line-1634"> }</span>
+<span class="source-line-no">1635</span><span id="line-1635"> bucketAllocator = new BucketAllocator(cacheCapacity, bucketSizes, backingMap, realCacheSize);</span>
+<span class="source-line-no">1636</span><span id="line-1636"> blockNumber.add(backingMap.size());</span>
+<span class="source-line-no">1637</span><span id="line-1637"> LOG.info("Bucket cache retrieved from file successfully with size: {}", backingMap.size());</span>
+<span class="source-line-no">1638</span><span id="line-1638"> }</span>
+<span class="source-line-no">1639</span><span id="line-1639"> }</span>
+<span class="source-line-no">1640</span><span id="line-1640"></span>
+<span class="source-line-no">1641</span><span id="line-1641"> private void updateRegionSizeMapWhileRetrievingFromFile() {</span>
+<span class="source-line-no">1642</span><span id="line-1642"> // Update the regionCachedSize with the region size while restarting the region server</span>
+<span class="source-line-no">1643</span><span id="line-1643"> if (LOG.isDebugEnabled()) {</span>
+<span class="source-line-no">1644</span><span id="line-1644"> LOG.debug("Updating region size map after retrieving cached file list");</span>
+<span class="source-line-no">1645</span><span id="line-1645"> dumpPrefetchList();</span>
+<span class="source-line-no">1646</span><span id="line-1646"> }</span>
+<span class="source-line-no">1647</span><span id="line-1647"> regionCachedSize.clear();</span>
+<span class="source-line-no">1648</span><span id="line-1648"> fullyCachedFiles.forEach((hFileName, hFileSize) -> {</span>
+<span class="source-line-no">1649</span><span id="line-1649"> // Get the region name for each file</span>
+<span class="source-line-no">1650</span><span id="line-1650"> String regionEncodedName = hFileSize.getFirst();</span>
+<span class="source-line-no">1651</span><span id="line-1651"> long cachedFileSize = hFileSize.getSecond();</span>
+<span class="source-line-no">1652</span><span id="line-1652"> regionCachedSize.merge(regionEncodedName, cachedFileSize,</span>
+<span class="source-line-no">1653</span><span id="line-1653"> (oldpf, fileSize) -> oldpf + fileSize);</span>
+<span class="source-line-no">1654</span><span id="line-1654"> });</span>
<span class="source-line-no">1655</span><span id="line-1655"> }</span>
<span class="source-line-no">1656</span><span id="line-1656"></span>
-<span class="source-line-no">1657</span><span id="line-1657"> private void verifyCapacityAndClasses(long capacitySize, String ioclass, String mapclass)</span>
-<span class="source-line-no">1658</span><span id="line-1658"> throws IOException {</span>
-<span class="source-line-no">1659</span><span id="line-1659"> if (capacitySize != cacheCapacity) {</span>
-<span class="source-line-no">1660</span><span id="line-1660"> throw new IOException("Mismatched cache capacity:" + StringUtils.byteDesc(capacitySize)</span>
-<span class="source-line-no">1661</span><span id="line-1661"> + ", expected: " + StringUtils.byteDesc(cacheCapacity));</span>
-<span class="source-line-no">1662</span><span id="line-1662"> }</span>
-<span class="source-line-no">1663</span><span id="line-1663"> if (!ioEngine.getClass().getName().equals(ioclass)) {</span>
-<span class="source-line-no">1664</span><span id="line-1664"> throw new IOException("Class name for IO engine mismatch: " + ioclass + ", expected:"</span>
-<span class="source-line-no">1665</span><span id="line-1665"> + ioEngine.getClass().getName());</span>
-<span class="source-line-no">1666</span><span id="line-1666"> }</span>
-<span class="source-line-no">1667</span><span id="line-1667"> if (!backingMap.getClass().getName().equals(mapclass)) {</span>
-<span class="source-line-no">1668</span><span id="line-1668"> throw new IOException("Class name for cache map mismatch: " + mapclass + ", expected:"</span>
-<span class="source-line-no">1669</span><span id="line-1669"> + backingMap.getClass().getName());</span>
-<span class="source-line-no">1670</span><span id="line-1670"> }</span>
-<span class="source-line-no">1671</span><span id="line-1671"> }</span>
-<span class="source-line-no">1672</span><span id="line-1672"></span>
-<span class="source-line-no">1673</span><span id="line-1673"> private void verifyFileIntegrity(BucketCacheProtos.BucketCacheEntry proto) {</span>
-<span class="source-line-no">1674</span><span id="line-1674"> try {</span>
-<span class="source-line-no">1675</span><span id="line-1675"> if (proto.hasChecksum()) {</span>
-<span class="source-line-no">1676</span><span id="line-1676"> ((PersistentIOEngine) ioEngine).verifyFileIntegrity(proto.getChecksum().toByteArray(),</span>
-<span class="source-line-no">1677</span><span id="line-1677"> algorithm);</span>
-<span class="source-line-no">1678</span><span id="line-1678"> }</span>
-<span class="source-line-no">1679</span><span id="line-1679"> backingMapValidated.set(true);</span>
-<span class="source-line-no">1680</span><span id="line-1680"> } catch (IOException e) {</span>
-<span class="source-line-no">1681</span><span id="line-1681"> LOG.warn("Checksum for cache file failed. "</span>
-<span class="source-line-no">1682</span><span id="line-1682"> + "We need to validate each cache key in the backing map. "</span>
-<span class="source-line-no">1683</span><span id="line-1683"> + "This may take some time, so we'll do it in a background thread,");</span>
-<span class="source-line-no">1684</span><span id="line-1684"></span>
-<span class="source-line-no">1685</span><span id="line-1685"> Runnable cacheValidator = () -> {</span>
-<span class="source-line-no">1686</span><span id="line-1686"> while (bucketAllocator == null) {</span>
-<span class="source-line-no">1687</span><span id="line-1687"> try {</span>
-<span class="source-line-no">1688</span><span id="line-1688"> Thread.sleep(50);</span>
-<span class="source-line-no">1689</span><span id="line-1689"> } catch (InterruptedException ex) {</span>
-<span class="source-line-no">1690</span><span id="line-1690"> throw new RuntimeException(ex);</span>
-<span class="source-line-no">1691</span><span id="line-1691"> }</span>
-<span class="source-line-no">1692</span><span id="line-1692"> }</span>
-<span class="source-line-no">1693</span><span id="line-1693"> long startTime = EnvironmentEdgeManager.currentTime();</span>
-<span class="source-line-no">1694</span><span id="line-1694"> int totalKeysOriginally = backingMap.size();</span>
-<span class="source-line-no">1695</span><span id="line-1695"> for (Map.Entry<BlockCacheKey, BucketEntry> keyEntry : backingMap.entrySet()) {</span>
-<span class="source-line-no">1696</span><span id="line-1696"> try {</span>
-<span class="source-line-no">1697</span><span id="line-1697"> ((FileIOEngine) ioEngine).checkCacheTime(keyEntry.getValue());</span>
-<span class="source-line-no">1698</span><span id="line-1698"> } catch (IOException e1) {</span>
-<span class="source-line-no">1699</span><span id="line-1699"> LOG.debug("Check for key {} failed. Evicting.", keyEntry.getKey());</span>
-<span class="source-line-no">1700</span><span id="line-1700"> evictBlock(keyEntry.getKey());</span>
-<span class="source-line-no">1701</span><span id="line-1701"> fileNotFullyCached(keyEntry.getKey(), keyEntry.getValue());</span>
-<span class="source-line-no">1702</span><span id="line-1702"> }</span>
-<span class="source-line-no">1703</span><span id="line-1703"> }</span>
-<span class="source-line-no">1704</span><span id="line-1704"> backingMapValidated.set(true);</span>
-<span class="source-line-no">1705</span><span id="line-1705"> LOG.info("Finished validating {} keys in the backing map. Recovered: {}. This took {}ms.",</span>
-<span class="source-line-no">1706</span><span id="line-1706"> totalKeysOriginally, backingMap.size(),</span>
-<span class="source-line-no">1707</span><span id="line-1707"> (EnvironmentEdgeManager.currentTime() - startTime));</span>
-<span class="source-line-no">1708</span><span id="line-1708"> };</span>
-<span class="source-line-no">1709</span><span id="line-1709"> Thread t = new Thread(cacheValidator);</span>
-<span class="source-line-no">1710</span><span id="line-1710"> t.setDaemon(true);</span>
-<span class="source-line-no">1711</span><span id="line-1711"> t.start();</span>
-<span class="source-line-no">1712</span><span id="line-1712"> }</span>
-<span class="source-line-no">1713</span><span id="line-1713"> }</span>
-<span class="source-line-no">1714</span><span id="line-1714"></span>
-<span class="source-line-no">1715</span><span id="line-1715"> private void updateCacheIndex(BucketCacheProtos.BackingMap chunk,</span>
-<span class="source-line-no">1716</span><span id="line-1716"> java.util.Map<java.lang.Integer, java.lang.String> deserializer) throws IOException {</span>
-<span class="source-line-no">1717</span><span id="line-1717"> Pair<ConcurrentHashMap<BlockCacheKey, BucketEntry>, NavigableSet<BlockCacheKey>> pair2 =</span>
-<span class="source-line-no">1718</span><span id="line-1718"> BucketProtoUtils.fromPB(deserializer, chunk, this::createRecycler);</span>
-<span class="source-line-no">1719</span><span id="line-1719"> backingMap.putAll(pair2.getFirst());</span>
-<span class="source-line-no">1720</span><span id="line-1720"> blocksByHFile.addAll(pair2.getSecond());</span>
-<span class="source-line-no">1721</span><span id="line-1721"> }</span>
-<span class="source-line-no">1722</span><span id="line-1722"></span>
-<span class="source-line-no">1723</span><span id="line-1723"> private void parsePB(BucketCacheProtos.BucketCacheEntry proto) throws IOException {</span>
-<span class="source-line-no">1724</span><span id="line-1724"> Pair<ConcurrentHashMap<BlockCacheKey, BucketEntry>, NavigableSet<BlockCacheKey>> pair =</span>
-<span class="source-line-no">1725</span><span id="line-1725"> BucketProtoUtils.fromPB(proto.getDeserializersMap(), proto.getBackingMap(),</span>
-<span class="source-line-no">1726</span><span id="line-1726"> this::createRecycler);</span>
-<span class="source-line-no">1727</span><span id="line-1727"> backingMap = pair.getFirst();</span>
-<span class="source-line-no">1728</span><span id="line-1728"> blocksByHFile = pair.getSecond();</span>
-<span class="source-line-no">1729</span><span id="line-1729"> fullyCachedFiles.clear();</span>
-<span class="source-line-no">1730</span><span id="line-1730"> fullyCachedFiles.putAll(BucketProtoUtils.fromPB(proto.getCachedFilesMap()));</span>
-<span class="source-line-no">1731</span><span id="line-1731"></span>
-<span class="source-line-no">1732</span><span id="line-1732"> LOG.info("After retrieval Backing map size: {}, fullyCachedFiles size: {}", backingMap.size(),</span>
-<span class="source-line-no">1733</span><span id="line-1733"> fullyCachedFiles.size());</span>
-<span class="source-line-no">1734</span><span id="line-1734"></span>
-<span class="source-line-no">1735</span><span id="line-1735"> verifyFileIntegrity(proto);</span>
-<span class="source-line-no">1736</span><span id="line-1736"> updateRegionSizeMapWhileRetrievingFromFile();</span>
-<span class="source-line-no">1737</span><span id="line-1737"> verifyCapacityAndClasses(proto.getCacheCapacity(), proto.getIoClass(), proto.getMapClass());</span>
-<span class="source-line-no">1738</span><span id="line-1738"> }</span>
-<span class="source-line-no">1739</span><span id="line-1739"></span>
-<span class="source-line-no">1740</span><span id="line-1740"> private void persistChunkedBackingMap(FileOutputStream fos) throws IOException {</span>
-<span class="source-line-no">1741</span><span id="line-1741"> LOG.debug(</span>
-<span class="source-line-no">1742</span><span id="line-1742"> "persistToFile: before persisting backing map size: {}, "</span>
-<span class="source-line-no">1743</span><span id="line-1743"> + "fullycachedFiles size: {}, chunkSize: {}",</span>
-<span class="source-line-no">1744</span><span id="line-1744"> backingMap.size(), fullyCachedFiles.size(), persistenceChunkSize);</span>
-<span class="source-line-no">1745</span><span id="line-1745"></span>
-<span class="source-line-no">1746</span><span id="line-1746"> BucketProtoUtils.serializeAsPB(this, fos, persistenceChunkSize);</span>
-<span class="source-line-no">1747</span><span id="line-1747"></span>
+<span class="source-line-no">1657</span><span id="line-1657"> private void dumpPrefetchList() {</span>
+<span class="source-line-no">1658</span><span id="line-1658"> for (Map.Entry<String, Pair<String, Long>> outerEntry : fullyCachedFiles.entrySet()) {</span>
+<span class="source-line-no">1659</span><span id="line-1659"> LOG.debug("Cached File Entry:<{},<{},{}>>", outerEntry.getKey(),</span>
+<span class="source-line-no">1660</span><span id="line-1660"> outerEntry.getValue().getFirst(), outerEntry.getValue().getSecond());</span>
+<span class="source-line-no">1661</span><span id="line-1661"> }</span>
+<span class="source-line-no">1662</span><span id="line-1662"> }</span>
+<span class="source-line-no">1663</span><span id="line-1663"></span>
+<span class="source-line-no">1664</span><span id="line-1664"> private void verifyCapacityAndClasses(long capacitySize, String ioclass, String mapclass)</span>
+<span class="source-line-no">1665</span><span id="line-1665"> throws IOException {</span>
+<span class="source-line-no">1666</span><span id="line-1666"> if (capacitySize != cacheCapacity) {</span>
+<span class="source-line-no">1667</span><span id="line-1667"> throw new IOException("Mismatched cache capacity:" + StringUtils.byteDesc(capacitySize)</span>
+<span class="source-line-no">1668</span><span id="line-1668"> + ", expected: " + StringUtils.byteDesc(cacheCapacity));</span>
+<span class="source-line-no">1669</span><span id="line-1669"> }</span>
+<span class="source-line-no">1670</span><span id="line-1670"> if (!ioEngine.getClass().getName().equals(ioclass)) {</span>
+<span class="source-line-no">1671</span><span id="line-1671"> throw new IOException("Class name for IO engine mismatch: " + ioclass + ", expected:"</span>
+<span class="source-line-no">1672</span><span id="line-1672"> + ioEngine.getClass().getName());</span>
+<span class="source-line-no">1673</span><span id="line-1673"> }</span>
+<span class="source-line-no">1674</span><span id="line-1674"> if (!backingMap.getClass().getName().equals(mapclass)) {</span>
+<span class="source-line-no">1675</span><span id="line-1675"> throw new IOException("Class name for cache map mismatch: " + mapclass + ", expected:"</span>
+<span class="source-line-no">1676</span><span id="line-1676"> + backingMap.getClass().getName());</span>
+<span class="source-line-no">1677</span><span id="line-1677"> }</span>
+<span class="source-line-no">1678</span><span id="line-1678"> }</span>
+<span class="source-line-no">1679</span><span id="line-1679"></span>
+<span class="source-line-no">1680</span><span id="line-1680"> private void verifyFileIntegrity(BucketCacheProtos.BucketCacheEntry proto) {</span>
+<span class="source-line-no">1681</span><span id="line-1681"> try {</span>
+<span class="source-line-no">1682</span><span id="line-1682"> if (proto.hasChecksum()) {</span>
+<span class="source-line-no">1683</span><span id="line-1683"> ((PersistentIOEngine) ioEngine).verifyFileIntegrity(proto.getChecksum().toByteArray(),</span>
+<span class="source-line-no">1684</span><span id="line-1684"> algorithm);</span>
+<span class="source-line-no">1685</span><span id="line-1685"> }</span>
+<span class="source-line-no">1686</span><span id="line-1686"> backingMapValidated.set(true);</span>
+<span class="source-line-no">1687</span><span id="line-1687"> } catch (IOException e) {</span>
+<span class="source-line-no">1688</span><span id="line-1688"> LOG.warn("Checksum for cache file failed. "</span>
+<span class="source-line-no">1689</span><span id="line-1689"> + "We need to validate each cache key in the backing map. "</span>
+<span class="source-line-no">1690</span><span id="line-1690"> + "This may take some time, so we'll do it in a background thread,");</span>
+<span class="source-line-no">1691</span><span id="line-1691"></span>
+<span class="source-line-no">1692</span><span id="line-1692"> Runnable cacheValidator = () -> {</span>
+<span class="source-line-no">1693</span><span id="line-1693"> while (bucketAllocator == null) {</span>
+<span class="source-line-no">1694</span><span id="line-1694"> try {</span>
+<span class="source-line-no">1695</span><span id="line-1695"> Thread.sleep(50);</span>
+<span class="source-line-no">1696</span><span id="line-1696"> } catch (InterruptedException ex) {</span>
+<span class="source-line-no">1697</span><span id="line-1697"> throw new RuntimeException(ex);</span>
+<span class="source-line-no">1698</span><span id="line-1698"> }</span>
+<span class="source-line-no">1699</span><span id="line-1699"> }</span>
+<span class="source-line-no">1700</span><span id="line-1700"> long startTime = EnvironmentEdgeManager.currentTime();</span>
+<span class="source-line-no">1701</span><span id="line-1701"> int totalKeysOriginally = backingMap.size();</span>
+<span class="source-line-no">1702</span><span id="line-1702"> for (Map.Entry<BlockCacheKey, BucketEntry> keyEntry : backingMap.entrySet()) {</span>
+<span class="source-line-no">1703</span><span id="line-1703"> try {</span>
+<span class="source-line-no">1704</span><span id="line-1704"> ((FileIOEngine) ioEngine).checkCacheTime(keyEntry.getValue());</span>
+<span class="source-line-no">1705</span><span id="line-1705"> } catch (IOException e1) {</span>
+<span class="source-line-no">1706</span><span id="line-1706"> LOG.debug("Check for key {} failed. Evicting.", keyEntry.getKey());</span>
+<span class="source-line-no">1707</span><span id="line-1707"> evictBlock(keyEntry.getKey());</span>
+<span class="source-line-no">1708</span><span id="line-1708"> fileNotFullyCached(keyEntry.getKey(), keyEntry.getValue());</span>
+<span class="source-line-no">1709</span><span id="line-1709"> }</span>
+<span class="source-line-no">1710</span><span id="line-1710"> }</span>
+<span class="source-line-no">1711</span><span id="line-1711"> backingMapValidated.set(true);</span>
+<span class="source-line-no">1712</span><span id="line-1712"> LOG.info("Finished validating {} keys in the backing map. Recovered: {}. This took {}ms.",</span>
+<span class="source-line-no">1713</span><span id="line-1713"> totalKeysOriginally, backingMap.size(),</span>
+<span class="source-line-no">1714</span><span id="line-1714"> (EnvironmentEdgeManager.currentTime() - startTime));</span>
+<span class="source-line-no">1715</span><span id="line-1715"> };</span>
+<span class="source-line-no">1716</span><span id="line-1716"> Thread t = new Thread(cacheValidator);</span>
+<span class="source-line-no">1717</span><span id="line-1717"> t.setDaemon(true);</span>
+<span class="source-line-no">1718</span><span id="line-1718"> t.start();</span>
+<span class="source-line-no">1719</span><span id="line-1719"> }</span>
+<span class="source-line-no">1720</span><span id="line-1720"> }</span>
+<span class="source-line-no">1721</span><span id="line-1721"></span>
+<span class="source-line-no">1722</span><span id="line-1722"> private void updateCacheIndex(BucketCacheProtos.BackingMap chunk,</span>
+<span class="source-line-no">1723</span><span id="line-1723"> java.util.Map<java.lang.Integer, java.lang.String> deserializer) throws IOException {</span>
+<span class="source-line-no">1724</span><span id="line-1724"> Pair<ConcurrentHashMap<BlockCacheKey, BucketEntry>, NavigableSet<BlockCacheKey>> pair2 =</span>
+<span class="source-line-no">1725</span><span id="line-1725"> BucketProtoUtils.fromPB(deserializer, chunk, this::createRecycler);</span>
+<span class="source-line-no">1726</span><span id="line-1726"> backingMap.putAll(pair2.getFirst());</span>
+<span class="source-line-no">1727</span><span id="line-1727"> blocksByHFile.addAll(pair2.getSecond());</span>
+<span class="source-line-no">1728</span><span id="line-1728"> }</span>
+<span class="source-line-no">1729</span><span id="line-1729"></span>
+<span class="source-line-no">1730</span><span id="line-1730"> private void parsePB(BucketCacheProtos.BucketCacheEntry proto) throws IOException {</span>
+<span class="source-line-no">1731</span><span id="line-1731"> Pair<ConcurrentHashMap<BlockCacheKey, BucketEntry>, NavigableSet<BlockCacheKey>> pair =</span>
+<span class="source-line-no">1732</span><span id="line-1732"> BucketProtoUtils.fromPB(proto.getDeserializersMap(), proto.getBackingMap(),</span>
+<span class="source-line-no">1733</span><span id="line-1733"> this::createRecycler);</span>
+<span class="source-line-no">1734</span><span id="line-1734"> backingMap = pair.getFirst();</span>
+<span class="source-line-no">1735</span><span id="line-1735"> blocksByHFile = pair.getSecond();</span>
+<span class="source-line-no">1736</span><span id="line-1736"> fullyCachedFiles.clear();</span>
+<span class="source-line-no">1737</span><span id="line-1737"> fullyCachedFiles.putAll(BucketProtoUtils.fromPB(proto.getCachedFilesMap()));</span>
+<span class="source-line-no">1738</span><span id="line-1738"></span>
+<span class="source-line-no">1739</span><span id="line-1739"> LOG.info("After retrieval Backing map size: {}, fullyCachedFiles size: {}", backingMap.size(),</span>
+<span class="source-line-no">1740</span><span id="line-1740"> fullyCachedFiles.size());</span>
+<span class="source-line-no">1741</span><span id="line-1741"></span>
+<span class="source-line-no">1742</span><span id="line-1742"> verifyFileIntegrity(proto);</span>
+<span class="source-line-no">1743</span><span id="line-1743"> updateRegionSizeMapWhileRetrievingFromFile();</span>
+<span class="source-line-no">1744</span><span id="line-1744"> verifyCapacityAndClasses(proto.getCacheCapacity(), proto.getIoClass(), proto.getMapClass());</span>
+<span class="source-line-no">1745</span><span id="line-1745"> }</span>
+<span class="source-line-no">1746</span><span id="line-1746"></span>
+<span class="source-line-no">1747</span><span id="line-1747"> private void persistChunkedBackingMap(FileOutputStream fos) throws IOException {</span>
<span class="source-line-no">1748</span><span id="line-1748"> LOG.debug(</span>
-<span class="source-line-no">1749</span><span id="line-1749"> "persistToFile: after persisting backing map size: {}, " + "fullycachedFiles size: {}",</span>
-<span class="source-line-no">1750</span><span id="line-1750"> backingMap.size(), fullyCachedFiles.size());</span>
-<span class="source-line-no">1751</span><span id="line-1751"> }</span>
+<span class="source-line-no">1749</span><span id="line-1749"> "persistToFile: before persisting backing map size: {}, "</span>
+<span class="source-line-no">1750</span><span id="line-1750"> + "fullycachedFiles size: {}, chunkSize: {}",</span>
+<span class="source-line-no">1751</span><span id="line-1751"> backingMap.size(), fullyCachedFiles.size(), persistenceChunkSize);</span>
<span class="source-line-no">1752</span><span id="line-1752"></span>
-<span class="source-line-no">1753</span><span id="line-1753"> private void retrieveChunkedBackingMap(FileInputStream in) throws IOException {</span>
-<span class="source-line-no">1754</span><span id="line-1754"> // Read the first chunk that has all the details.</span>
-<span class="source-line-no">1755</span><span id="line-1755"> BucketCacheProtos.BucketCacheEntry cacheEntry =</span>
-<span class="source-line-no">1756</span><span id="line-1756"> BucketCacheProtos.BucketCacheEntry.parseDelimitedFrom(in);</span>
-<span class="source-line-no">1757</span><span id="line-1757"></span>
-<span class="source-line-no">1758</span><span id="line-1758"> fullyCachedFiles.clear();</span>
-<span class="source-line-no">1759</span><span id="line-1759"> fullyCachedFiles.putAll(BucketProtoUtils.fromPB(cacheEntry.getCachedFilesMap()));</span>
-<span class="source-line-no">1760</span><span id="line-1760"></span>
-<span class="source-line-no">1761</span><span id="line-1761"> backingMap.clear();</span>
-<span class="source-line-no">1762</span><span id="line-1762"> blocksByHFile.clear();</span>
-<span class="source-line-no">1763</span><span id="line-1763"></span>
-<span class="source-line-no">1764</span><span id="line-1764"> // Read the backing map entries in batches.</span>
-<span class="source-line-no">1765</span><span id="line-1765"> int numChunks = 0;</span>
-<span class="source-line-no">1766</span><span id="line-1766"> while (in.available() > 0) {</span>
-<span class="source-line-no">1767</span><span id="line-1767"> updateCacheIndex(BucketCacheProtos.BackingMap.parseDelimitedFrom(in),</span>
-<span class="source-line-no">1768</span><span id="line-1768"> cacheEntry.getDeserializersMap());</span>
-<span class="source-line-no">1769</span><span id="line-1769"> numChunks++;</span>
+<span class="source-line-no">1753</span><span id="line-1753"> BucketProtoUtils.serializeAsPB(this, fos, persistenceChunkSize);</span>
+<span class="source-line-no">1754</span><span id="line-1754"></span>
+<span class="source-line-no">1755</span><span id="line-1755"> LOG.debug(</span>
+<span class="source-line-no">1756</span><span id="line-1756"> "persistToFile: after persisting backing map size: {}, " + "fullycachedFiles size: {}",</span>
+<span class="source-line-no">1757</span><span id="line-1757"> backingMap.size(), fullyCachedFiles.size());</span>
+<span class="source-line-no">1758</span><span id="line-1758"> }</span>
+<span class="source-line-no">1759</span><span id="line-1759"></span>
+<span class="source-line-no">1760</span><span id="line-1760"> private void retrieveChunkedBackingMap(FileInputStream in) throws IOException {</span>
+<span class="source-line-no">1761</span><span id="line-1761"> // Read the first chunk that has all the details.</span>
+<span class="source-line-no">1762</span><span id="line-1762"> BucketCacheProtos.BucketCacheEntry cacheEntry =</span>
+<span class="source-line-no">1763</span><span id="line-1763"> BucketCacheProtos.BucketCacheEntry.parseDelimitedFrom(in);</span>
+<span class="source-line-no">1764</span><span id="line-1764"></span>
+<span class="source-line-no">1765</span><span id="line-1765"> // HBASE-29857: Handle case where persistence file is empty.</span>
+<span class="source-line-no">1766</span><span id="line-1766"> // parseDelimitedFrom() returns null when there's no data to read.</span>
+<span class="source-line-no">1767</span><span id="line-1767"> // Note: Corrupted files would throw InvalidProtocolBufferException (subclass of IOException).</span>
+<span class="source-line-no">1768</span><span id="line-1768"> if (cacheEntry == null) {</span>
+<span class="source-line-no">1769</span><span id="line-1769"> throw new IOException("Failed to read cache entry from persistence file (file is empty)");</span>
<span class="source-line-no">1770</span><span id="line-1770"> }</span>
<span class="source-line-no">1771</span><span id="line-1771"></span>
-<span class="source-line-no">1772</span><span id="line-1772"> LOG.info("Retrieved {} of chunks with blockCount = {}.", numChunks, backingMap.size());</span>
-<span class="source-line-no">1773</span><span id="line-1773"> verifyFileIntegrity(cacheEntry);</span>
-<span class="source-line-no">1774</span><span id="line-1774"> verifyCapacityAndClasses(cacheEntry.getCacheCapacity(), cacheEntry.getIoClass(),</span>
-<span class="source-line-no">1775</span><span id="line-1775"> cacheEntry.getMapClass());</span>
-<span class="source-line-no">1776</span><span id="line-1776"> updateRegionSizeMapWhileRetrievingFromFile();</span>
-<span class="source-line-no">1777</span><span id="line-1777"> }</span>
-<span class="source-line-no">1778</span><span id="line-1778"></span>
-<span class="source-line-no">1779</span><span id="line-1779"> /**</span>
-<span class="source-line-no">1780</span><span id="line-1780"> * Check whether we tolerate IO error this time. If the duration of IOEngine throwing errors</span>
-<span class="source-line-no">1781</span><span id="line-1781"> * exceeds ioErrorsDurationTimeTolerated, we will disable the cache</span>
-<span class="source-line-no">1782</span><span id="line-1782"> */</span>
-<span class="source-line-no">1783</span><span id="line-1783"> private void checkIOErrorIsTolerated() {</span>
-<span class="source-line-no">1784</span><span id="line-1784"> long now = EnvironmentEdgeManager.currentTime();</span>
-<span class="source-line-no">1785</span><span id="line-1785"> // Do a single read to a local variable to avoid timing issue - HBASE-24454</span>
-<span class="source-line-no">1786</span><span id="line-1786"> long ioErrorStartTimeTmp = this.ioErrorStartTime;</span>
-<span class="source-line-no">1787</span><span id="line-1787"> if (ioErrorStartTimeTmp > 0) {</span>
-<span class="source-line-no">1788</span><span id="line-1788"> if (isCacheEnabled() && (now - ioErrorStartTimeTmp) > this.ioErrorsTolerationDuration) {</span>
-<span class="source-line-no">1789</span><span id="line-1789"> LOG.error("IO errors duration time has exceeded " + ioErrorsTolerationDuration</span>
-<span class="source-line-no">1790</span><span id="line-1790"> + "ms, disabling cache, please check your IOEngine");</span>
-<span class="source-line-no">1791</span><span id="line-1791"> disableCache();</span>
-<span class="source-line-no">1792</span><span id="line-1792"> }</span>
-<span class="source-line-no">1793</span><span id="line-1793"> } else {</span>
-<span class="source-line-no">1794</span><span id="line-1794"> this.ioErrorStartTime = now;</span>
-<span class="source-line-no">1795</span><span id="line-1795"> }</span>
-<span class="source-line-no">1796</span><span id="line-1796"> }</span>
-<span class="source-line-no">1797</span><span id="line-1797"></span>
-<span class="source-line-no">1798</span><span id="line-1798"> /**</span>
-<span class="source-line-no">1799</span><span id="line-1799"> * Used to shut down the cache -or- turn it off in the case of something broken.</span>
-<span class="source-line-no">1800</span><span id="line-1800"> */</span>
-<span class="source-line-no">1801</span><span id="line-1801"> private void disableCache() {</span>
-<span class="source-line-no">1802</span><span id="line-1802"> if (!isCacheEnabled()) {</span>
-<span class="source-line-no">1803</span><span id="line-1803"> return;</span>
-<span class="source-line-no">1804</span><span id="line-1804"> }</span>
-<span class="source-line-no">1805</span><span id="line-1805"> LOG.info("Disabling cache");</span>
-<span class="source-line-no">1806</span><span id="line-1806"> cacheState = CacheState.DISABLED;</span>
-<span class="source-line-no">1807</span><span id="line-1807"> ioEngine.shutdown();</span>
-<span class="source-line-no">1808</span><span id="line-1808"> this.scheduleThreadPool.shutdown();</span>
-<span class="source-line-no">1809</span><span id="line-1809"> for (int i = 0; i < writerThreads.length; ++i)</span>
-<span class="source-line-no">1810</span><span id="line-1810"> writerThreads[i].interrupt();</span>
-<span class="source-line-no">1811</span><span id="line-1811"> this.ramCache.clear();</span>
-<span class="source-line-no">1812</span><span id="line-1812"> if (!ioEngine.isPersistent() || persistencePath == null) {</span>
-<span class="source-line-no">1813</span><span id="line-1813"> // If persistent ioengine and a path, we will serialize out the backingMap.</span>
-<span class="source-line-no">1814</span><span id="line-1814"> this.backingMap.clear();</span>
-<span class="source-line-no">1815</span><span id="line-1815"> this.blocksByHFile.clear();</span>
-<span class="source-line-no">1816</span><span id="line-1816"> this.fullyCachedFiles.clear();</span>
-<span class="source-line-no">1817</span><span id="line-1817"> this.regionCachedSize.clear();</span>
+<span class="source-line-no">1772</span><span id="line-1772"> fullyCachedFiles.clear();</span>
+<span class="source-line-no">1773</span><span id="line-1773"> fullyCachedFiles.putAll(BucketProtoUtils.fromPB(cacheEntry.getCachedFilesMap()));</span>
+<span class="source-line-no">1774</span><span id="line-1774"></span>
+<span class="source-line-no">1775</span><span id="line-1775"> backingMap.clear();</span>
+<span class="source-line-no">1776</span><span id="line-1776"> blocksByHFile.clear();</span>
+<span class="source-line-no">1777</span><span id="line-1777"></span>
+<span class="source-line-no">1778</span><span id="line-1778"> // Read the backing map entries in batches.</span>
+<span class="source-line-no">1779</span><span id="line-1779"> int numChunks = 0;</span>
+<span class="source-line-no">1780</span><span id="line-1780"> while (in.available() > 0) {</span>
+<span class="source-line-no">1781</span><span id="line-1781"> updateCacheIndex(BucketCacheProtos.BackingMap.parseDelimitedFrom(in),</span>
+<span class="source-line-no">1782</span><span id="line-1782"> cacheEntry.getDeserializersMap());</span>
+<span class="source-line-no">1783</span><span id="line-1783"> numChunks++;</span>
+<span class="source-line-no">1784</span><span id="line-1784"> }</span>
+<span class="source-line-no">1785</span><span id="line-1785"></span>
+<span class="source-line-no">1786</span><span id="line-1786"> LOG.info("Retrieved {} of chunks with blockCount = {}.", numChunks, backingMap.size());</span>
+<span class="source-line-no">1787</span><span id="line-1787"> verifyFileIntegrity(cacheEntry);</span>
+<span class="source-line-no">1788</span><span id="line-1788"> verifyCapacityAndClasses(cacheEntry.getCacheCapacity(), cacheEntry.getIoClass(),</span>
+<span class="source-line-no">1789</span><span id="line-1789"> cacheEntry.getMapClass());</span>
+<span class="source-line-no">1790</span><span id="line-1790"> updateRegionSizeMapWhileRetrievingFromFile();</span>
+<span class="source-line-no">1791</span><span id="line-1791"> }</span>
+<span class="source-line-no">1792</span><span id="line-1792"></span>
+<span class="source-line-no">1793</span><span id="line-1793"> /**</span>
+<span class="source-line-no">1794</span><span id="line-1794"> * Check whether we tolerate IO error this time. If the duration of IOEngine throwing errors</span>
+<span class="source-line-no">1795</span><span id="line-1795"> * exceeds ioErrorsDurationTimeTolerated, we will disable the cache</span>
+<span class="source-line-no">1796</span><span id="line-1796"> */</span>
+<span class="source-line-no">1797</span><span id="line-1797"> private void checkIOErrorIsTolerated() {</span>
+<span class="source-line-no">1798</span><span id="line-1798"> long now = EnvironmentEdgeManager.currentTime();</span>
+<span class="source-line-no">1799</span><span id="line-1799"> // Do a single read to a local variable to avoid timing issue - HBASE-24454</span>
+<span class="source-line-no">1800</span><span id="line-1800"> long ioErrorStartTimeTmp = this.ioErrorStartTime;</span>
+<span class="source-line-no">1801</span><span id="line-1801"> if (ioErrorStartTimeTmp > 0) {</span>
+<span class="source-line-no">1802</span><span id="line-1802"> if (isCacheEnabled() && (now - ioErrorStartTimeTmp) > this.ioErrorsTolerationDuration) {</span>
+<span class="source-line-no">1803</span><span id="line-1803"> LOG.error("IO errors duration time has exceeded " + ioErrorsTolerationDuration</span>
+<span class="source-line-no">1804</span><span id="line-1804"> + "ms, disabling cache, please check your IOEngine");</span>
+<span class="source-line-no">1805</span><span id="line-1805"> disableCache();</span>
+<span class="source-line-no">1806</span><span id="line-1806"> }</span>
+<span class="source-line-no">1807</span><span id="line-1807"> } else {</span>
+<span class="source-line-no">1808</span><span id="line-1808"> this.ioErrorStartTime = now;</span>
+<span class="source-line-no">1809</span><span id="line-1809"> }</span>
+<span class="source-line-no">1810</span><span id="line-1810"> }</span>
+<span class="source-line-no">1811</span><span id="line-1811"></span>
+<span class="source-line-no">1812</span><span id="line-1812"> /**</span>
+<span class="source-line-no">1813</span><span id="line-1813"> * Used to shut down the cache -or- turn it off in the case of something broken.</span>
+<span class="source-line-no">1814</span><span id="line-1814"> */</span>
+<span class="source-line-no">1815</span><span id="line-1815"> private void disableCache() {</span>
+<span class="source-line-no">1816</span><span id="line-1816"> if (!isCacheEnabled()) {</span>
+<span class="source-line-no">1817</span><span id="line-1817"> return;</span>
<span class="source-line-no">1818</span><span id="line-1818"> }</span>
-<span class="source-line-no">1819</span><span id="line-1819"> if (cacheStats.getMetricsRollerScheduler() != null) {</span>
-<span class="source-line-no">1820</span><span id="line-1820"> cacheStats.getMetricsRollerScheduler().shutdownNow();</span>
-<span class="source-line-no">1821</span><span id="line-1821"> }</span>
-<span class="source-line-no">1822</span><span id="line-1822"> }</span>
-<span class="source-line-no">1823</span><span id="line-1823"></span>
-<span class="source-line-no">1824</span><span id="line-1824"> private void join() throws InterruptedException {</span>
-<span class="source-line-no">1825</span><span id="line-1825"> for (int i = 0; i < writerThreads.length; ++i)</span>
-<span class="source-line-no">1826</span><span id="line-1826"> writerThreads[i].join();</span>
-<span class="source-line-no">1827</span><span id="line-1827"> }</span>
-<span class="source-line-no">1828</span><span id="line-1828"></span>
-<span class="source-line-no">1829</span><span id="line-1829"> @Override</span>
-<span class="source-line-no">1830</span><span id="line-1830"> public void shutdown() {</span>
-<span class="source-line-no">1831</span><span id="line-1831"> if (isCacheEnabled()) {</span>
-<span class="source-line-no">1832</span><span id="line-1832"> disableCache();</span>
-<span class="source-line-no">1833</span><span id="line-1833"> LOG.info("Shutdown bucket cache: IO persistent=" + ioEngine.isPersistent()</span>
-<span class="source-line-no">1834</span><span id="line-1834"> + "; path to write=" + persistencePath);</span>
-<span class="source-line-no">1835</span><span id="line-1835"> if (ioEngine.isPersistent() && persistencePath != null) {</span>
-<span class="source-line-no">1836</span><span id="line-1836"> try {</span>
-<span class="source-line-no">1837</span><span id="line-1837"> join();</span>
-<span class="source-line-no">1838</span><span id="line-1838"> if (cachePersister != null) {</span>
-<span class="source-line-no">1839</span><span id="line-1839"> LOG.info("Shutting down cache persister thread.");</span>
-<span class="source-line-no">1840</span><span id="line-1840"> cachePersister.shutdown();</span>
-<span class="source-line-no">1841</span><span id="line-1841"> while (cachePersister.isAlive()) {</span>
-<span class="source-line-no">1842</span><span id="line-1842"> Thread.sleep(10);</span>
-<span class="source-line-no">1843</span><span id="line-1843"> }</span>
-<span class="source-line-no">1844</span><span id="line-1844"> }</span>
-<span class="source-line-no">1845</span><span id="line-1845"> persistToFile();</span>
-<span class="source-line-no">1846</span><span id="line-1846"> } catch (IOException ex) {</span>
-<span class="source-line-no">1847</span><span id="line-1847"> LOG.error("Unable to persist data on exit: " + ex.toString(), ex);</span>
-<span class="source-line-no">1848</span><span id="line-1848"> } catch (InterruptedException e) {</span>
-<span class="source-line-no">1849</span><span id="line-1849"> LOG.warn("Failed to persist data on exit", e);</span>
-<span class="source-line-no">1850</span><span id="line-1850"> }</span>
-<span class="source-line-no">1851</span><span id="line-1851"> }</span>
-<span class="source-line-no">1852</span><span id="line-1852"> }</span>
-<span class="source-line-no">1853</span><span id="line-1853"> }</span>
-<span class="source-line-no">1854</span><span id="line-1854"></span>
-<span class="source-line-no">1855</span><span id="line-1855"> /**</span>
-<span class="source-line-no">1856</span><span id="line-1856"> * Needed mostly for UTs that might run in the same VM and create different BucketCache instances</span>
-<span class="source-line-no">1857</span><span id="line-1857"> * on different UT methods.</span>
-<span class="source-line-no">1858</span><span id="line-1858"> */</span>
-<span class="source-line-no">1859</span><span id="line-1859"> @Override</span>
-<span class="source-line-no">1860</span><span id="line-1860"> protected void finalize() {</span>
-<span class="source-line-no">1861</span><span id="line-1861"> if (cachePersister != null && !cachePersister.isInterrupted()) {</span>
-<span class="source-line-no">1862</span><span id="line-1862"> cachePersister.interrupt();</span>
-<span class="source-line-no">1863</span><span id="line-1863"> }</span>
-<span class="source-line-no">1864</span><span id="line-1864"> }</span>
-<span class="source-line-no">1865</span><span id="line-1865"></span>
-<span class="source-line-no">1866</span><span id="line-1866"> @Override</span>
-<span class="source-line-no">1867</span><span id="line-1867"> public CacheStats getStats() {</span>
-<span class="source-line-no">1868</span><span id="line-1868"> return cacheStats;</span>
-<span class="source-line-no">1869</span><span id="line-1869"> }</span>
-<span class="source-line-no">1870</span><span id="line-1870"></span>
-<span class="source-line-no">1871</span><span id="line-1871"> public BucketAllocator getAllocator() {</span>
-<span class="source-line-no">1872</span><span id="line-1872"> return this.bucketAllocator;</span>
-<span class="source-line-no">1873</span><span id="line-1873"> }</span>
-<span class="source-line-no">1874</span><span id="line-1874"></span>
-<span class="source-line-no">1875</span><span id="line-1875"> @Override</span>
-<span class="source-line-no">1876</span><span id="line-1876"> public long heapSize() {</span>
-<span class="source-line-no">1877</span><span id="line-1877"> return this.heapSize.sum();</span>
+<span class="source-line-no">1819</span><span id="line-1819"> LOG.info("Disabling cache");</span>
+<span class="source-line-no">1820</span><span id="line-1820"> cacheState = CacheState.DISABLED;</span>
+<span class="source-line-no">1821</span><span id="line-1821"> ioEngine.shutdown();</span>
+<span class="source-line-no">1822</span><span id="line-1822"> this.scheduleThreadPool.shutdown();</span>
+<span class="source-line-no">1823</span><span id="line-1823"> for (int i = 0; i < writerThreads.length; ++i)</span>
+<span class="source-line-no">1824</span><span id="line-1824"> writerThreads[i].interrupt();</span>
+<span class="source-line-no">1825</span><span id="line-1825"> this.ramCache.clear();</span>
+<span class="source-line-no">1826</span><span id="line-1826"> if (!ioEngine.isPersistent() || persistencePath == null) {</span>
+<span class="source-line-no">1827</span><span id="line-1827"> // If persistent ioengine and a path, we will serialize out the backingMap.</span>
+<span class="source-line-no">1828</span><span id="line-1828"> this.backingMap.clear();</span>
+<span class="source-line-no">1829</span><span id="line-1829"> this.blocksByHFile.clear();</span>
+<span class="source-line-no">1830</span><span id="line-1830"> this.fullyCachedFiles.clear();</span>
+<span class="source-line-no">1831</span><span id="line-1831"> this.regionCachedSize.clear();</span>
+<span class="source-line-no">1832</span><span id="line-1832"> }</span>
+<span class="source-line-no">1833</span><span id="line-1833"> if (cacheStats.getMetricsRollerScheduler() != null) {</span>
+<span class="source-line-no">1834</span><span id="line-1834"> cacheStats.getMetricsRollerScheduler().shutdownNow();</span>
+<span class="source-line-no">1835</span><span id="line-1835"> }</span>
+<span class="source-line-no">1836</span><span id="line-1836"> }</span>
+<span class="source-line-no">1837</span><span id="line-1837"></span>
+<span class="source-line-no">1838</span><span id="line-1838"> private void join() throws InterruptedException {</span>
+<span class="source-line-no">1839</span><span id="line-1839"> for (int i = 0; i < writerThreads.length; ++i)</span>
+<span class="source-line-no">1840</span><span id="line-1840"> writerThreads[i].join();</span>
+<span class="source-line-no">1841</span><span id="line-1841"> }</span>
+<span class="source-line-no">1842</span><span id="line-1842"></span>
+<span class="source-line-no">1843</span><span id="line-1843"> @Override</span>
+<span class="source-line-no">1844</span><span id="line-1844"> public void shutdown() {</span>
+<span class="source-line-no">1845</span><span id="line-1845"> if (isCacheEnabled()) {</span>
+<span class="source-line-no">1846</span><span id="line-1846"> disableCache();</span>
+<span class="source-line-no">1847</span><span id="line-1847"> LOG.info("Shutdown bucket cache: IO persistent=" + ioEngine.isPersistent()</span>
+<span class="source-line-no">1848</span><span id="line-1848"> + "; path to write=" + persistencePath);</span>
+<span class="source-line-no">1849</span><span id="line-1849"> if (ioEngine.isPersistent() && persistencePath != null) {</span>
+<span class="source-line-no">1850</span><span id="line-1850"> try {</span>
+<span class="source-line-no">1851</span><span id="line-1851"> join();</span>
+<span class="source-line-no">1852</span><span id="line-1852"> if (cachePersister != null) {</span>
+<span class="source-line-no">1853</span><span id="line-1853"> LOG.info("Shutting down cache persister thread.");</span>
+<span class="source-line-no">1854</span><span id="line-1854"> cachePersister.shutdown();</span>
+<span class="source-line-no">1855</span><span id="line-1855"> while (cachePersister.isAlive()) {</span>
+<span class="source-line-no">1856</span><span id="line-1856"> Thread.sleep(10);</span>
+<span class="source-line-no">1857</span><span id="line-1857"> }</span>
+<span class="source-line-no">1858</span><span id="line-1858"> }</span>
+<span class="source-line-no">1859</span><span id="line-1859"> persistToFile();</span>
+<span class="source-line-no">1860</span><span id="line-1860"> } catch (IOException ex) {</span>
+<span class="source-line-no">1861</span><span id="line-1861"> LOG.error("Unable to persist data on exit: " + ex.toString(), ex);</span>
+<span class="source-line-no">1862</span><span id="line-1862"> } catch (InterruptedException e) {</span>
+<span class="source-line-no">1863</span><span id="line-1863"> LOG.warn("Failed to persist data on exit", e);</span>
+<span class="source-line-no">1864</span><span id="line-1864"> }</span>
+<span class="source-line-no">1865</span><span id="line-1865"> }</span>
+<span class="source-line-no">1866</span><span id="line-1866"> }</span>
+<span class="source-line-no">1867</span><span id="line-1867"> }</span>
+<span class="source-line-no">1868</span><span id="line-1868"></span>
+<span class="source-line-no">1869</span><span id="line-1869"> /**</span>
+<span class="source-line-no">1870</span><span id="line-1870"> * Needed mostly for UTs that might run in the same VM and create different BucketCache instances</span>
+<span class="source-line-no">1871</span><span id="line-1871"> * on different UT methods.</span>
+<span class="source-line-no">1872</span><span id="line-1872"> */</span>
+<span class="source-line-no">1873</span><span id="line-1873"> @Override</span>
+<span class="source-line-no">1874</span><span id="line-1874"> protected void finalize() {</span>
+<span class="source-line-no">1875</span><span id="line-1875"> if (cachePersister != null && !cachePersister.isInterrupted()) {</span>
+<span class="source-line-no">1876</span><span id="line-1876"> cachePersister.interrupt();</span>
+<span class="source-line-no">1877</span><span id="line-1877"> }</span>
<span class="source-line-no">1878</span><span id="line-1878"> }</span>
<span class="source-line-no">1879</span><span id="line-1879"></span>
<span class="source-line-no">1880</span><span id="line-1880"> @Override</span>
-<span class="source-line-no">1881</span><span id="line-1881"> public long size() {</span>
-<span class="source-line-no">1882</span><span id="line-1882"> return this.realCacheSize.sum();</span>
+<span class="source-line-no">1881</span><span id="line-1881"> public CacheStats getStats() {</span>
+<span class="source-line-no">1882</span><span id="line-1882"> return cacheStats;</span>
<span class="source-line-no">1883</span><span id="line-1883"> }</span>
<span class="source-line-no">1884</span><span id="line-1884"></span>
-<span class="source-line-no">1885</span><span id="line-1885"> @Override</span>
-<span class="source-line-no">1886</span><span id="line-1886"> public long getCurrentDataSize() {</span>
-<span class="source-line-no">1887</span><span id="line-1887"> return size();</span>
-<span class="source-line-no">1888</span><span id="line-1888"> }</span>
-<span class="source-line-no">1889</span><span id="line-1889"></span>
-<span class="source-line-no">1890</span><span id="line-1890"> @Override</span>
-<span class="source-line-no">1891</span><span id="line-1891"> public long getFreeSize() {</span>
-<span class="source-line-no">1892</span><span id="line-1892"> if (!isCacheInitialized("BucketCache:getFreeSize")) {</span>
-<span class="source-line-no">1893</span><span id="line-1893"> return 0;</span>
-<span class="source-line-no">1894</span><span id="line-1894"> }</span>
-<span class="source-line-no">1895</span><span id="line-1895"> return this.bucketAllocator.getFreeSize();</span>
-<span class="source-line-no">1896</span><span id="line-1896"> }</span>
-<span class="source-line-no">1897</span><span id="line-1897"></span>
-<span class="source-line-no">1898</span><span id="line-1898"> @Override</span>
-<span class="source-line-no">1899</span><span id="line-1899"> public long getBlockCount() {</span>
-<span class="source-line-no">1900</span><span id="line-1900"> return this.blockNumber.sum();</span>
-<span class="source-line-no">1901</span><span id="line-1901"> }</span>
-<span class="source-line-no">1902</span><span id="line-1902"></span>
-<span class="source-line-no">1903</span><span id="line-1903"> @Override</span>
-<span class="source-line-no">1904</span><span id="line-1904"> public long getDataBlockCount() {</span>
-<span class="source-line-no">1905</span><span id="line-1905"> return getBlockCount();</span>
-<span class="source-line-no">1906</span><span id="line-1906"> }</span>
-<span class="source-line-no">1907</span><span id="line-1907"></span>
-<span class="source-line-no">1908</span><span id="line-1908"> @Override</span>
-<span class="source-line-no">1909</span><span id="line-1909"> public long getCurrentSize() {</span>
-<span class="source-line-no">1910</span><span id="line-1910"> if (!isCacheInitialized("BucketCache::getCurrentSize")) {</span>
-<span class="source-line-no">1911</span><span id="line-1911"> return 0;</span>
-<span class="source-line-no">1912</span><span id="line-1912"> }</span>
-<span class="source-line-no">1913</span><span id="line-1913"> return this.bucketAllocator.getUsedSize();</span>
-<span class="source-line-no">1914</span><span id="line-1914"> }</span>
-<span class="source-line-no">1915</span><span id="line-1915"></span>
-<span class="source-line-no">1916</span><span id="line-1916"> protected String getAlgorithm() {</span>
-<span class="source-line-no">1917</span><span id="line-1917"> return algorithm;</span>
-<span class="source-line-no">1918</span><span id="line-1918"> }</span>
-<span class="source-line-no">1919</span><span id="line-1919"></span>
-<span class="source-line-no">1920</span><span id="line-1920"> /**</span>
-<span class="source-line-no">1921</span><span id="line-1921"> * Evicts all blocks for a specific HFile.</span>
-<span class="source-line-no">1922</span><span id="line-1922"> * <p></span>
-<span class="source-line-no">1923</span><span id="line-1923"> * This is used for evict-on-close to remove all blocks of a specific HFile.</span>
-<span class="source-line-no">1924</span><span id="line-1924"> * @return the number of blocks evicted</span>
-<span class="source-line-no">1925</span><span id="line-1925"> */</span>
-<span class="source-line-no">1926</span><span id="line-1926"> @Override</span>
-<span class="source-line-no">1927</span><span id="line-1927"> public int evictBlocksByHfileName(String hfileName) {</span>
-<span class="source-line-no">1928</span><span id="line-1928"> return evictBlocksRangeByHfileName(hfileName, 0, Long.MAX_VALUE);</span>
-<span class="source-line-no">1929</span><span id="line-1929"> }</span>
-<span class="source-line-no">1930</span><span id="line-1930"></span>
-<span class="source-line-no">1931</span><span id="line-1931"> @Override</span>
-<span class="source-line-no">1932</span><span id="line-1932"> public int evictBlocksRangeByHfileName(String hfileName, long initOffset, long endOffset) {</span>
-<span class="source-line-no">1933</span><span id="line-1933"> Set<BlockCacheKey> keySet = getAllCacheKeysForFile(hfileName, initOffset, endOffset);</span>
-<span class="source-line-no">1934</span><span id="line-1934"> // We need to make sure whether we are evicting all blocks for this given file. In case of</span>
-<span class="source-line-no">1935</span><span id="line-1935"> // split references, we might be evicting just half of the blocks</span>
-<span class="source-line-no">1936</span><span id="line-1936"> LOG.debug("found {} blocks for file {}, starting offset: {}, end offset: {}", keySet.size(),</span>
-<span class="source-line-no">1937</span><span id="line-1937"> hfileName, initOffset, endOffset);</span>
-<span class="source-line-no">1938</span><span id="line-1938"> int numEvicted = 0;</span>
-<span class="source-line-no">1939</span><span id="line-1939"> for (BlockCacheKey key : keySet) {</span>
-<span class="source-line-no">1940</span><span id="line-1940"> if (evictBlock(key)) {</span>
-<span class="source-line-no">1941</span><span id="line-1941"> ++numEvicted;</span>
-<span class="source-line-no">1942</span><span id="line-1942"> }</span>
-<span class="source-line-no">1943</span><span id="line-1943"> }</span>
-<span class="source-line-no">1944</span><span id="line-1944"> return numEvicted;</span>
-<span class="source-line-no">1945</span><span id="line-1945"> }</span>
-<span class="source-line-no">1946</span><span id="line-1946"></span>
-<span class="source-line-no">1947</span><span id="line-1947"> private Set<BlockCacheKey> getAllCacheKeysForFile(String hfileName, long init, long end) {</span>
-<span class="source-line-no">1948</span><span id="line-1948"> // These keys are just for comparison and are short lived, so we need only file name and offset</span>
-<span class="source-line-no">1949</span><span id="line-1949"> return blocksByHFile.subSet(new BlockCacheKey(hfileName, init), true,</span>
-<span class="source-line-no">1950</span><span id="line-1950"> new BlockCacheKey(hfileName, end), true);</span>
-<span class="source-line-no">1951</span><span id="line-1951"> }</span>
-<span class="source-line-no">1952</span><span id="line-1952"></span>
-<span class="source-line-no">1953</span><span id="line-1953"> /**</span>
-<span class="source-line-no">1954</span><span id="line-1954"> * Used to group bucket entries into priority buckets. There will be a BucketEntryGroup for each</span>
-<span class="source-line-no">1955</span><span id="line-1955"> * priority (single, multi, memory). Once bucketed, the eviction algorithm takes the appropriate</span>
-<span class="source-line-no">1956</span><span id="line-1956"> * number of elements out of each according to configuration parameters and their relative sizes.</span>
-<span class="source-line-no">1957</span><span id="line-1957"> */</span>
-<span class="source-line-no">1958</span><span id="line-1958"> private class BucketEntryGroup {</span>
-<span class="source-line-no">1959</span><span id="line-1959"></span>
-<span class="source-line-no">1960</span><span id="line-1960"> private CachedEntryQueue queue;</span>
-<span class="source-line-no">1961</span><span id="line-1961"> private long totalSize = 0;</span>
-<span class="source-line-no">1962</span><span id="line-1962"> private long bucketSize;</span>
-<span class="source-line-no">1963</span><span id="line-1963"></span>
-<span class="source-line-no">1964</span><span id="line-1964"> public BucketEntryGroup(long bytesToFree, long blockSize, long bucketSize) {</span>
-<span class="source-line-no">1965</span><span id="line-1965"> this.bucketSize = bucketSize;</span>
-<span class="source-line-no">1966</span><span id="line-1966"> queue = new CachedEntryQueue(bytesToFree, blockSize);</span>
-<span class="source-line-no">1967</span><span id="line-1967"> totalSize = 0;</span>
-<span class="source-line-no">1968</span><span id="line-1968"> }</span>
-<span class="source-line-no">1969</span><span id="line-1969"></span>
-<span class="source-line-no">1970</span><span id="line-1970"> public void add(Map.Entry<BlockCacheKey, BucketEntry> block) {</span>
-<span class="source-line-no">1971</span><span id="line-1971"> totalSize += block.getValue().getLength();</span>
-<span class="source-line-no">1972</span><span id="line-1972"> queue.add(block);</span>
-<span class="source-line-no">1973</span><span id="line-1973"> }</span>
-<span class="source-line-no">1974</span><span id="line-1974"></span>
-<span class="source-line-no">1975</span><span id="line-1975"> public long free(long toFree) {</span>
-<span class="source-line-no">1976</span><span id="line-1976"> Map.Entry<BlockCacheKey, BucketEntry> entry;</span>
-<span class="source-line-no">1977</span><span id="line-1977"> long freedBytes = 0;</span>
-<span class="source-line-no">1978</span><span id="line-1978"> // TODO avoid a cycling siutation. We find no block which is not in use and so no way to free</span>
-<span class="source-line-no">1979</span><span id="line-1979"> // What to do then? Caching attempt fail? Need some changes in cacheBlock API?</span>
-<span class="source-line-no">1980</span><span id="line-1980"> while ((entry = queue.pollLast()) != null) {</span>
-<span class="source-line-no">1981</span><span id="line-1981"> BlockCacheKey blockCacheKey = entry.getKey();</span>
-<span class="source-line-no">1982</span><span id="line-1982"> BucketEntry be = entry.getValue();</span>
-<span class="source-line-no">1983</span><span id="line-1983"> if (evictBucketEntryIfNoRpcReferenced(blockCacheKey, be)) {</span>
-<span class="source-line-no">1984</span><span id="line-1984"> freedBytes += be.getLength();</span>
-<span class="source-line-no">1985</span><span id="line-1985"> }</span>
-<span class="source-line-no">1986</span><span id="line-1986"> if (freedBytes >= toFree) {</span>
-<span class="source-line-no">1987</span><span id="line-1987"> return freedBytes;</span>
-<span class="source-line-no">1988</span><span id="line-1988"> }</span>
-<span class="source-line-no">1989</span><span id="line-1989"> }</span>
-<span class="source-line-no">1990</span><span id="line-1990"> return freedBytes;</span>
-<span class="source-line-no">1991</span><span id="line-1991"> }</span>
-<span class="source-line-no">1992</span><span id="line-1992"></span>
-<span class="source-line-no">1993</span><span id="line-1993"> public long overflow() {</span>
-<span class="source-line-no">1994</span><span id="line-1994"> return totalSize - bucketSize;</span>
-<span class="source-line-no">1995</span><span id="line-1995"> }</span>
-<span class="source-line-no">1996</span><span id="line-1996"></span>
-<span class="source-line-no">1997</span><span id="line-1997"> public long totalSize() {</span>
-<span class="source-line-no">1998</span><span id="line-1998"> return totalSize;</span>
-<span class="source-line-no">1999</span><span id="line-1999"> }</span>
-<span class="source-line-no">2000</span><span id="line-2000"> }</span>
-<span class="source-line-no">2001</span><span id="line-2001"></span>
-<span class="source-line-no">2002</span><span id="line-2002"> /**</span>
-<span class="source-line-no">2003</span><span id="line-2003"> * Block Entry stored in the memory with key,data and so on</span>
-<span class="source-line-no">2004</span><span id="line-2004"> */</span>
-<span class="source-line-no">2005</span><span id="line-2005"> static class RAMQueueEntry {</span>
-<span class="source-line-no">2006</span><span id="line-2006"> private final BlockCacheKey key;</span>
-<span class="source-line-no">2007</span><span id="line-2007"> private final Cacheable data;</span>
-<span class="source-line-no">2008</span><span id="line-2008"> private long accessCounter;</span>
-<span class="source-line-no">2009</span><span id="line-2009"> private boolean inMemory;</span>
-<span class="source-line-no">2010</span><span id="line-2010"> private boolean isCachePersistent;</span>
-<span class="source-line-no">2011</span><span id="line-2011"></span>
-<span class="source-line-no">2012</span><span id="line-2012"> private boolean isPrefetch;</span>
-<span class="source-line-no">2013</span><span id="line-2013"></span>
-<span class="source-line-no">2014</span><span id="line-2014"> RAMQueueEntry(BlockCacheKey bck, Cacheable data, long accessCounter, boolean inMemory,</span>
-<span class="source-line-no">2015</span><span id="line-2015"> boolean isCachePersistent, boolean isPrefetch) {</span>
-<span class="source-line-no">2016</span><span id="line-2016"> this.key = bck;</span>
-<span class="source-line-no">2017</span><span id="line-2017"> this.data = data;</span>
-<span class="source-line-no">2018</span><span id="line-2018"> this.accessCounter = accessCounter;</span>
-<span class="source-line-no">2019</span><span id="line-2019"> this.inMemory = inMemory;</span>
-<span class="source-line-no">2020</span><span id="line-2020"> this.isCachePersistent = isCachePersistent;</span>
-<span class="source-line-no">2021</span><span id="line-2021"> this.isPrefetch = isPrefetch;</span>
-<span class="source-line-no">2022</span><span id="line-2022"> }</span>
-<span class="source-line-no">2023</span><span id="line-2023"></span>
-<span class="source-line-no">2024</span><span id="line-2024"> public Cacheable getData() {</span>
-<span class="source-line-no">2025</span><span id="line-2025"> return data;</span>
-<span class="source-line-no">2026</span><span id="line-2026"> }</span>
+<span class="source-line-no">1885</span><span id="line-1885"> public BucketAllocator getAllocator() {</span>
+<span class="source-line-no">1886</span><span id="line-1886"> return this.bucketAllocator;</span>
+<span class="source-line-no">1887</span><span id="line-1887"> }</span>
+<span class="source-line-no">1888</span><span id="line-1888"></span>
+<span class="source-line-no">1889</span><span id="line-1889"> @Override</span>
+<span class="source-line-no">1890</span><span id="line-1890"> public long heapSize() {</span>
+<span class="source-line-no">1891</span><span id="line-1891"> return this.heapSize.sum();</span>
+<span class="source-line-no">1892</span><span id="line-1892"> }</span>
+<span class="source-line-no">1893</span><span id="line-1893"></span>
+<span class="source-line-no">1894</span><span id="line-1894"> @Override</span>
+<span class="source-line-no">1895</span><span id="line-1895"> public long size() {</span>
+<span class="source-line-no">1896</span><span id="line-1896"> return this.realCacheSize.sum();</span>
+<span class="source-line-no">1897</span><span id="line-1897"> }</span>
+<span class="source-line-no">1898</span><span id="line-1898"></span>
+<span class="source-line-no">1899</span><span id="line-1899"> @Override</span>
+<span class="source-line-no">1900</span><span id="line-1900"> public long getCurrentDataSize() {</span>
+<span class="source-line-no">1901</span><span id="line-1901"> return size();</span>
+<span class="source-line-no">1902</span><span id="line-1902"> }</span>
+<span class="source-line-no">1903</span><span id="line-1903"></span>
+<span class="source-line-no">1904</span><span id="line-1904"> @Override</span>
+<span class="source-line-no">1905</span><span id="line-1905"> public long getFreeSize() {</span>
+<span class="source-line-no">1906</span><span id="line-1906"> if (!isCacheInitialized("BucketCache:getFreeSize")) {</span>
+<span class="source-line-no">1907</span><span id="line-1907"> return 0;</span>
+<span class="source-line-no">1908</span><span id="line-1908"> }</span>
+<span class="source-line-no">1909</span><span id="line-1909"> return this.bucketAllocator.getFreeSize();</span>
+<span class="source-line-no">1910</span><span id="line-1910"> }</span>
+<span class="source-line-no">1911</span><span id="line-1911"></span>
+<span class="source-line-no">1912</span><span id="line-1912"> @Override</span>
+<span class="source-line-no">1913</span><span id="line-1913"> public long getBlockCount() {</span>
+<span class="source-line-no">1914</span><span id="line-1914"> return this.blockNumber.sum();</span>
+<span class="source-line-no">1915</span><span id="line-1915"> }</span>
+<span class="source-line-no">1916</span><span id="line-1916"></span>
+<span class="source-line-no">1917</span><span id="line-1917"> @Override</span>
+<span class="source-line-no">1918</span><span id="line-1918"> public long getDataBlockCount() {</span>
+<span class="source-line-no">1919</span><span id="line-1919"> return getBlockCount();</span>
+<span class="source-line-no">1920</span><span id="line-1920"> }</span>
+<span class="source-line-no">1921</span><span id="line-1921"></span>
+<span class="source-line-no">1922</span><span id="line-1922"> @Override</span>
+<span class="source-line-no">1923</span><span id="line-1923"> public long getCurrentSize() {</span>
+<span class="source-line-no">1924</span><span id="line-1924"> if (!isCacheInitialized("BucketCache::getCurrentSize")) {</span>
+<span class="source-line-no">1925</span><span id="line-1925"> return 0;</span>
+<span class="source-line-no">1926</span><span id="line-1926"> }</span>
+<span class="source-line-no">1927</span><span id="line-1927"> return this.bucketAllocator.getUsedSize();</span>
+<span class="source-line-no">1928</span><span id="line-1928"> }</span>
+<span class="source-line-no">1929</span><span id="line-1929"></span>
+<span class="source-line-no">1930</span><span id="line-1930"> protected String getAlgorithm() {</span>
+<span class="source-line-no">1931</span><span id="line-1931"> return algorithm;</span>
+<span class="source-line-no">1932</span><span id="line-1932"> }</span>
+<span class="source-line-no">1933</span><span id="line-1933"></span>
+<span class="source-line-no">1934</span><span id="line-1934"> /**</span>
+<span class="source-line-no">1935</span><span id="line-1935"> * Evicts all blocks for a specific HFile.</span>
+<span class="source-line-no">1936</span><span id="line-1936"> * <p></span>
+<span class="source-line-no">1937</span><span id="line-1937"> * This is used for evict-on-close to remove all blocks of a specific HFile.</span>
+<span class="source-line-no">1938</span><span id="line-1938"> * @return the number of blocks evicted</span>
+<span class="source-line-no">1939</span><span id="line-1939"> */</span>
+<span class="source-line-no">1940</span><span id="line-1940"> @Override</span>
+<span class="source-line-no">1941</span><span id="line-1941"> public int evictBlocksByHfileName(String hfileName) {</span>
+<span class="source-line-no">1942</span><span id="line-1942"> return evictBlocksRangeByHfileName(hfileName, 0, Long.MAX_VALUE);</span>
+<span class="source-line-no">1943</span><span id="line-1943"> }</span>
+<span class="source-line-no">1944</span><span id="line-1944"></span>
+<span class="source-line-no">1945</span><span id="line-1945"> @Override</span>
+<span class="source-line-no">1946</span><span id="line-1946"> public int evictBlocksRangeByHfileName(String hfileName, long initOffset, long endOffset) {</span>
+<span class="source-line-no">1947</span><span id="line-1947"> Set<BlockCacheKey> keySet = getAllCacheKeysForFile(hfileName, initOffset, endOffset);</span>
+<span class="source-line-no">1948</span><span id="line-1948"> // We need to make sure whether we are evicting all blocks for this given file. In case of</span>
+<span class="source-line-no">1949</span><span id="line-1949"> // split references, we might be evicting just half of the blocks</span>
+<span class="source-line-no">1950</span><span id="line-1950"> LOG.debug("found {} blocks for file {}, starting offset: {}, end offset: {}", keySet.size(),</span>
+<span class="source-line-no">1951</span><span id="line-1951"> hfileName, initOffset, endOffset);</span>
+<span class="source-line-no">1952</span><span id="line-1952"> int numEvicted = 0;</span>
+<span class="source-line-no">1953</span><span id="line-1953"> for (BlockCacheKey key : keySet) {</span>
+<span class="source-line-no">1954</span><span id="line-1954"> if (evictBlock(key)) {</span>
+<span class="source-line-no">1955</span><span id="line-1955"> ++numEvicted;</span>
+<span class="source-line-no">1956</span><span id="line-1956"> }</span>
+<span class="source-line-no">1957</span><span id="line-1957"> }</span>
+<span class="source-line-no">1958</span><span id="line-1958"> return numEvicted;</span>
+<span class="source-line-no">1959</span><span id="line-1959"> }</span>
+<span class="source-line-no">1960</span><span id="line-1960"></span>
+<span class="source-line-no">1961</span><span id="line-1961"> private Set<BlockCacheKey> getAllCacheKeysForFile(String hfileName, long init, long end) {</span>
+<span class="source-line-no">1962</span><span id="line-1962"> // These keys are just for comparison and are short lived, so we need only file name and offset</span>
+<span class="source-line-no">1963</span><span id="line-1963"> return blocksByHFile.subSet(new BlockCacheKey(hfileName, init), true,</span>
+<span class="source-line-no">1964</span><span id="line-1964"> new BlockCacheKey(hfileName, end), true);</span>
+<span class="source-line-no">1965</span><span id="line-1965"> }</span>
+<span class="source-line-no">1966</span><span id="line-1966"></span>
+<span class="source-line-no">1967</span><span id="line-1967"> /**</span>
+<span class="source-line-no">1968</span><span id="line-1968"> * Used to group bucket entries into priority buckets. There will be a BucketEntryGroup for each</span>
+<span class="source-line-no">1969</span><span id="line-1969"> * priority (single, multi, memory). Once bucketed, the eviction algorithm takes the appropriate</span>
+<span class="source-line-no">1970</span><span id="line-1970"> * number of elements out of each according to configuration parameters and their relative sizes.</span>
+<span class="source-line-no">1971</span><span id="line-1971"> */</span>
+<span class="source-line-no">1972</span><span id="line-1972"> private class BucketEntryGroup {</span>
+<span class="source-line-no">1973</span><span id="line-1973"></span>
+<span class="source-line-no">1974</span><span id="line-1974"> private CachedEntryQueue queue;</span>
+<span class="source-line-no">1975</span><span id="line-1975"> private long totalSize = 0;</span>
+<span class="source-line-no">1976</span><span id="line-1976"> private long bucketSize;</span>
+<span class="source-line-no">1977</span><span id="line-1977"></span>
+<span class="source-line-no">1978</span><span id="line-1978"> public BucketEntryGroup(long bytesToFree, long blockSize, long bucketSize) {</span>
+<span class="source-line-no">1979</span><span id="line-1979"> this.bucketSize = bucketSize;</span>
+<span class="source-line-no">1980</span><span id="line-1980"> queue = new CachedEntryQueue(bytesToFree, blockSize);</span>
+<span class="source-line-no">1981</span><span id="line-1981"> totalSize = 0;</span>
+<span class="source-line-no">1982</span><span id="line-1982"> }</span>
+<span class="source-line-no">1983</span><span id="line-1983"></span>
+<span class="source-line-no">1984</span><span id="line-1984"> public void add(Map.Entry<BlockCacheKey, BucketEntry> block) {</span>
+<span class="source-line-no">1985</span><span id="line-1985"> totalSize += block.getValue().getLength();</span>
+<span class="source-line-no">1986</span><span id="line-1986"> queue.add(block);</span>
+<span class="source-line-no">1987</span><span id="line-1987"> }</span>
+<span class="source-line-no">1988</span><span id="line-1988"></span>
+<span class="source-line-no">1989</span><span id="line-1989"> public long free(long toFree) {</span>
+<span class="source-line-no">1990</span><span id="line-1990"> Map.Entry<BlockCacheKey, BucketEntry> entry;</span>
+<span class="source-line-no">1991</span><span id="line-1991"> long freedBytes = 0;</span>
+<span class="source-line-no">1992</span><span id="line-1992"> // TODO avoid a cycling siutation. We find no block which is not in use and so no way to free</span>
+<span class="source-line-no">1993</span><span id="line-1993"> // What to do then? Caching attempt fail? Need some changes in cacheBlock API?</span>
+<span class="source-line-no">1994</span><span id="line-1994"> while ((entry = queue.pollLast()) != null) {</span>
+<span class="source-line-no">1995</span><span id="line-1995"> BlockCacheKey blockCacheKey = entry.getKey();</span>
+<span class="source-line-no">1996</span><span id="line-1996"> BucketEntry be = entry.getValue();</span>
+<span class="source-line-no">1997</span><span id="line-1997"> if (evictBucketEntryIfNoRpcReferenced(blockCacheKey, be)) {</span>
+<span class="source-line-no">1998</span><span id="line-1998"> freedBytes += be.getLength();</span>
+<span class="source-line-no">1999</span><span id="line-1999"> }</span>
+<span class="source-line-no">2000</span><span id="line-2000"> if (freedBytes >= toFree) {</span>
+<span class="source-line-no">2001</span><span id="line-2001"> return freedBytes;</span>
+<span class="source-line-no">2002</span><span id="line-2002"> }</span>
+<span class="source-line-no">2003</span><span id="line-2003"> }</span>
+<span class="source-line-no">2004</span><span id="line-2004"> return freedBytes;</span>
+<span class="source-line-no">2005</span><span id="line-2005"> }</span>
+<span class="source-line-no">2006</span><span id="line-2006"></span>
+<span class="source-line-no">2007</span><span id="line-2007"> public long overflow() {</span>
+<span class="source-line-no">2008</span><span id="line-2008"> return totalSize - bucketSize;</span>
+<span class="source-line-no">2009</span><span id="line-2009"> }</span>
+<span class="source-line-no">2010</span><span id="line-2010"></span>
+<span class="source-line-no">2011</span><span id="line-2011"> public long totalSize() {</span>
+<span class="source-line-no">2012</span><span id="line-2012"> return totalSize;</span>
+<span class="source-line-no">2013</span><span id="line-2013"> }</span>
+<span class="source-line-no">2014</span><span id="line-2014"> }</span>
+<span class="source-line-no">2015</span><span id="line-2015"></span>
+<span class="source-line-no">2016</span><span id="line-2016"> /**</span>
+<span class="source-line-no">2017</span><span id="line-2017"> * Block Entry stored in the memory with key,data and so on</span>
+<span class="source-line-no">2018</span><span id="line-2018"> */</span>
+<span class="source-line-no">2019</span><span id="line-2019"> static class RAMQueueEntry {</span>
+<span class="source-line-no">2020</span><span id="line-2020"> private final BlockCacheKey key;</span>
+<span class="source-line-no">2021</span><span id="line-2021"> private final Cacheable data;</span>
+<span class="source-line-no">2022</span><span id="line-2022"> private long accessCounter;</span>
+<span class="source-line-no">2023</span><span id="line-2023"> private boolean inMemory;</span>
+<span class="source-line-no">2024</span><span id="line-2024"> private boolean isCachePersistent;</span>
+<span class="source-line-no">2025</span><span id="line-2025"></span>
+<span class="source-line-no">2026</span><span id="line-2026"> private boolean isPrefetch;</span>
<span class="source-line-no">2027</span><span id="line-2027"></span>
-<span class="source-line-no">2028</span><span id="line-2028"> public BlockCacheKey getKey() {</span>
-<span class="source-line-no">2029</span><span id="line-2029"> return key;</span>
-<span class="source-line-no">2030</span><span id="line-2030"> }</span>
-<span class="source-line-no">2031</span><span id="line-2031"></span>
-<span class="source-line-no">2032</span><span id="line-2032"> public boolean isPrefetch() {</span>
-<span class="source-line-no">2033</span><span id="line-2033"> return isPrefetch;</span>
-<span class="source-line-no">2034</span><span id="line-2034"> }</span>
-<span class="source-line-no">2035</span><span id="line-2035"></span>
-<span class="source-line-no">2036</span><span id="line-2036"> public void access(long accessCounter) {</span>
-<span class="source-line-no">2037</span><span id="line-2037"> this.accessCounter = accessCounter;</span>
-<span class="source-line-no">2038</span><span id="line-2038"> }</span>
-<span class="source-line-no">2039</span><span id="line-2039"></span>
-<span class="source-line-no">2040</span><span id="line-2040"> private ByteBuffAllocator getByteBuffAllocator() {</span>
-<span class="source-line-no">2041</span><span id="line-2041"> if (data instanceof HFileBlock) {</span>
-<span class="source-line-no">2042</span><span id="line-2042"> return ((HFileBlock) data).getByteBuffAllocator();</span>
-<span class="source-line-no">2043</span><span id="line-2043"> }</span>
-<span class="source-line-no">2044</span><span id="line-2044"> return ByteBuffAllocator.HEAP;</span>
-<span class="source-line-no">2045</span><span id="line-2045"> }</span>
-<span class="source-line-no">2046</span><span id="line-2046"></span>
-<span class="source-line-no">2047</span><span id="line-2047"> public BucketEntry writeToCache(final IOEngine ioEngine, final BucketAllocator alloc,</span>
-<span class="source-line-no">2048</span><span id="line-2048"> final LongAdder realCacheSize, Function<BucketEntry, Recycler> createRecycler,</span>
-<span class="source-line-no">2049</span><span id="line-2049"> ByteBuffer metaBuff, final Long acceptableSize) throws IOException {</span>
-<span class="source-line-no">2050</span><span id="line-2050"> int len = data.getSerializedLength();</span>
-<span class="source-line-no">2051</span><span id="line-2051"> // This cacheable thing can't be serialized</span>
-<span class="source-line-no">2052</span><span id="line-2052"> if (len == 0) {</span>
-<span class="source-line-no">2053</span><span id="line-2053"> return null;</span>
-<span class="source-line-no">2054</span><span id="line-2054"> }</span>
-<span class="source-line-no">2055</span><span id="line-2055"> if (isCachePersistent && data instanceof HFileBlock) {</span>
-<span class="source-line-no">2056</span><span id="line-2056"> len += Long.BYTES; // we need to record the cache time for consistency check in case of</span>
-<span class="source-line-no">2057</span><span id="line-2057"> // recovery</span>
-<span class="source-line-no">2058</span><span id="line-2058"> }</span>
-<span class="source-line-no">2059</span><span id="line-2059"> long offset = alloc.allocateBlock(len);</span>
-<span class="source-line-no">2060</span><span id="line-2060"> // In the case of prefetch, we want to avoid freeSpace runs when the cache is full.</span>
-<span class="source-line-no">2061</span><span id="line-2061"> // this makes the cache allocation more predictable, and is particularly important</span>
-<span class="source-line-no">2062</span><span id="line-2062"> // when persistent cache is enabled, as it won't trigger evictions of the recovered blocks,</span>
-<span class="source-line-no">2063</span><span id="line-2063"> // which are likely the most accessed and relevant blocks in the cache.</span>
-<span class="source-line-no">2064</span><span id="line-2064"> if (isPrefetch() && alloc.getUsedSize() > acceptableSize) {</span>
-<span class="source-line-no">2065</span><span id="line-2065"> alloc.freeBlock(offset, len);</span>
-<span class="source-line-no">2066</span><span id="line-2066"> return null;</span>
-<span class="source-line-no">2067</span><span id="line-2067"> }</span>
-<span class="source-line-no">2068</span><span id="line-2068"> boolean succ = false;</span>
-<span class="source-line-no">2069</span><span id="line-2069"> BucketEntry bucketEntry = null;</span>
-<span class="source-line-no">2070</span><span id="line-2070"> try {</span>
-<span class="source-line-no">2071</span><span id="line-2071"> int diskSizeWithHeader = (data instanceof HFileBlock)</span>
-<span class="source-line-no">2072</span><span id="line-2072"> ? ((HFileBlock) data).getOnDiskSizeWithHeader()</span>
-<span class="source-line-no">2073</span><span id="line-2073"> : data.getSerializedLength();</span>
-<span class="source-line-no">2074</span><span id="line-2074"> bucketEntry = new BucketEntry(offset, len, diskSizeWithHeader, accessCounter, inMemory,</span>
-<span class="source-line-no">2075</span><span id="line-2075"> createRecycler, getByteBuffAllocator());</span>
-<span class="source-line-no">2076</span><span id="line-2076"> bucketEntry.setDeserializerReference(data.getDeserializer());</span>
-<span class="source-line-no">2077</span><span id="line-2077"> if (data instanceof HFileBlock) {</span>
-<span class="source-line-no">2078</span><span id="line-2078"> // If an instance of HFileBlock, save on some allocations.</span>
-<span class="source-line-no">2079</span><span id="line-2079"> HFileBlock block = (HFileBlock) data;</span>
-<span class="source-line-no">2080</span><span id="line-2080"> ByteBuff sliceBuf = block.getBufferReadOnly();</span>
-<span class="source-line-no">2081</span><span id="line-2081"> block.getMetaData(metaBuff);</span>
-<span class="source-line-no">2082</span><span id="line-2082"> // adds the cache time prior to the block and metadata part</span>
-<span class="source-line-no">2083</span><span id="line-2083"> if (isCachePersistent) {</span>
-<span class="source-line-no">2084</span><span id="line-2084"> ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);</span>
-<span class="source-line-no">2085</span><span id="line-2085"> buffer.putLong(bucketEntry.getCachedTime());</span>
-<span class="source-line-no">2086</span><span id="line-2086"> buffer.rewind();</span>
-<span class="source-line-no">2087</span><span id="line-2087"> ioEngine.write(buffer, offset);</span>
-<span class="source-line-no">2088</span><span id="line-2088"> ioEngine.write(sliceBuf, (offset + Long.BYTES));</span>
-<span class="source-line-no">2089</span><span id="line-2089"> } else {</span>
-<span class="source-line-no">2090</span><span id="line-2090"> ioEngine.write(sliceBuf, offset);</span>
-<span class="source-line-no">2091</span><span id="line-2091"> }</span>
-<span class="source-line-no">2092</span><span id="line-2092"> ioEngine.write(metaBuff, offset + len - metaBuff.limit());</span>
-<span class="source-line-no">2093</span><span id="line-2093"> } else {</span>
-<span class="source-line-no">2094</span><span id="line-2094"> // Only used for testing.</span>
-<span class="source-line-no">2095</span><span id="line-2095"> ByteBuffer bb = ByteBuffer.allocate(len);</span>
-<span class="source-line-no">2096</span><span id="line-2096"> data.serialize(bb, true);</span>
-<span class="source-line-no">2097</span><span id="line-2097"> ioEngine.write(bb, offset);</span>
-<span class="source-line-no">2098</span><span id="line-2098"> }</span>
-<span class="source-line-no">2099</span><span id="line-2099"> succ = true;</span>
-<span class="source-line-no">2100</span><span id="line-2100"> } finally {</span>
-<span class="source-line-no">2101</span><span id="line-2101"> if (!succ) {</span>
-<span class="source-line-no">2102</span><span id="line-2102"> alloc.freeBlock(offset, len);</span>
-<span class="source-line-no">2103</span><span id="line-2103"> }</span>
-<span class="source-line-no">2104</span><span id="line-2104"> }</span>
-<span class="source-line-no">2105</span><span id="line-2105"> realCacheSize.add(len);</span>
-<span class="source-line-no">2106</span><span id="line-2106"> return bucketEntry;</span>
-<span class="source-line-no">2107</span><span id="line-2107"> }</span>
-<span class="source-line-no">2108</span><span id="line-2108"> }</span>
-<span class="source-line-no">2109</span><span id="line-2109"></span>
-<span class="source-line-no">2110</span><span id="line-2110"> /**</span>
-<span class="source-line-no">2111</span><span id="line-2111"> * Only used in test</span>
-<span class="source-line-no">2112</span><span id="line-2112"> */</span>
-<span class="source-line-no">2113</span><span id="line-2113"> void stopWriterThreads() throws InterruptedException {</span>
-<span class="source-line-no">2114</span><span id="line-2114"> for (WriterThread writerThread : writerThreads) {</span>
-<span class="source-line-no">2115</span><span id="line-2115"> writerThread.disableWriter();</span>
-<span class="source-line-no">2116</span><span id="line-2116"> writerThread.interrupt();</span>
-<span class="source-line-no">2117</span><span id="line-2117"> writerThread.join();</span>
-<span class="source-line-no">2118</span><span id="line-2118"> }</span>
-<span class="source-line-no">2119</span><span id="line-2119"> }</span>
-<span class="source-line-no">2120</span><span id="line-2120"></span>
-<span class="source-line-no">2121</span><span id="line-2121"> @Override</span>
-<span class="source-line-no">2122</span><span id="line-2122"> public Iterator<CachedBlock> iterator() {</span>
-<span class="source-line-no">2123</span><span id="line-2123"> // Don't bother with ramcache since stuff is in here only a little while.</span>
-<span class="source-line-no">2124</span><span id="line-2124"> final Iterator<Map.Entry<BlockCacheKey, BucketEntry>> i = this.backingMap.entrySet().iterator();</span>
-<span class="source-line-no">2125</span><span id="line-2125"> return new Iterator<CachedBlock>() {</span>
-<span class="source-line-no">2126</span><span id="line-2126"> private final long now = System.nanoTime();</span>
-<span class="source-line-no">2127</span><span id="line-2127"></span>
-<span class="source-line-no">2128</span><span id="line-2128"> @Override</span>
-<span class="source-line-no">2129</span><span id="line-2129"> public boolean hasNext() {</span>
-<span class="source-line-no">2130</span><span id="line-2130"> return i.hasNext();</span>
-<span class="source-line-no">2131</span><span id="line-2131"> }</span>
-<span class="source-line-no">2132</span><span id="line-2132"></span>
-<span class="source-line-no">2133</span><span id="line-2133"> @Override</span>
-<span class="source-line-no">2134</span><span id="line-2134"> public CachedBlock next() {</span>
-<span class="source-line-no">2135</span><span id="line-2135"> final Map.Entry<BlockCacheKey, BucketEntry> e = i.next();</span>
-<span class="source-line-no">2136</span><span id="line-2136"> return new CachedBlock() {</span>
-<span class="source-line-no">2137</span><span id="line-2137"> @Override</span>
-<span class="source-line-no">2138</span><span id="line-2138"> public String toString() {</span>
-<span class="source-line-no">2139</span><span id="line-2139"> return BlockCacheUtil.toString(this, now);</span>
-<span class="source-line-no">2140</span><span id="line-2140"> }</span>
+<span class="source-line-no">2028</span><span id="line-2028"> RAMQueueEntry(BlockCacheKey bck, Cacheable data, long accessCounter, boolean inMemory,</span>
+<span class="source-line-no">2029</span><span id="line-2029"> boolean isCachePersistent, boolean isPrefetch) {</span>
+<span class="source-line-no">2030</span><span id="line-2030"> this.key = bck;</span>
+<span class="source-line-no">2031</span><span id="line-2031"> this.data = data;</span>
+<span class="source-line-no">2032</span><span id="line-2032"> this.accessCounter = accessCounter;</span>
+<span class="source-line-no">2033</span><span id="line-2033"> this.inMemory = inMemory;</span>
+<span class="source-line-no">2034</span><span id="line-2034"> this.isCachePersistent = isCachePersistent;</span>
+<span class="source-line-no">2035</span><span id="line-2035"> this.isPrefetch = isPrefetch;</span>
+<span class="source-line-no">2036</span><span id="line-2036"> }</span>
+<span class="source-line-no">2037</span><span id="line-2037"></span>
+<span class="source-line-no">2038</span><span id="line-2038"> public Cacheable getData() {</span>
+<span class="source-line-no">2039</span><span id="line-2039"> return data;</span>
+<span class="source-line-no">2040</span><span id="line-2040"> }</span>
+<span class="source-line-no">2041</span><span id="line-2041"></span>
+<span class="source-line-no">2042</span><span id="line-2042"> public BlockCacheKey getKey() {</span>
+<span class="source-line-no">2043</span><span id="line-2043"> return key;</span>
+<span class="source-line-no">2044</span><span id="line-2044"> }</span>
+<span class="source-line-no">2045</span><span id="line-2045"></span>
+<span class="source-line-no">2046</span><span id="line-2046"> public boolean isPrefetch() {</span>
+<span class="source-line-no">2047</span><span id="line-2047"> return isPrefetch;</span>
+<span class="source-line-no">2048</span><span id="line-2048"> }</span>
+<span class="source-line-no">2049</span><span id="line-2049"></span>
+<span class="source-line-no">2050</span><span id="line-2050"> public void access(long accessCounter) {</span>
+<span class="source-line-no">2051</span><span id="line-2051"> this.accessCounter = accessCounter;</span>
+<span class="source-line-no">2052</span><span id="line-2052"> }</span>
+<span class="source-line-no">2053</span><span id="line-2053"></span>
+<span class="source-line-no">2054</span><span id="line-2054"> private ByteBuffAllocator getByteBuffAllocator() {</span>
+<span class="source-line-no">2055</span><span id="line-2055"> if (data instanceof HFileBlock) {</span>
+<span class="source-line-no">2056</span><span id="line-2056"> return ((HFileBlock) data).getByteBuffAllocator();</span>
+<span class="source-line-no">2057</span><span id="line-2057"> }</span>
+<span class="source-line-no">2058</span><span id="line-2058"> return ByteBuffAllocator.HEAP;</span>
+<span class="source-line-no">2059</span><span id="line-2059"> }</span>
+<span class="source-line-no">2060</span><span id="line-2060"></span>
+<span class="source-line-no">2061</span><span id="line-2061"> public BucketEntry writeToCache(final IOEngine ioEngine, final BucketAllocator alloc,</span>
+<span class="source-line-no">2062</span><span id="line-2062"> final LongAdder realCacheSize, Function<BucketEntry, Recycler> createRecycler,</span>
+<span class="source-line-no">2063</span><span id="line-2063"> ByteBuffer metaBuff, final Long acceptableSize) throws IOException {</span>
+<span class="source-line-no">2064</span><span id="line-2064"> int len = data.getSerializedLength();</span>
+<span class="source-line-no">2065</span><span id="line-2065"> // This cacheable thing can't be serialized</span>
+<span class="source-line-no">2066</span><span id="line-2066"> if (len == 0) {</span>
+<span class="source-line-no">2067</span><span id="line-2067"> return null;</span>
+<span class="source-line-no">2068</span><span id="line-2068"> }</span>
+<span class="source-line-no">2069</span><span id="line-2069"> if (isCachePersistent && data instanceof HFileBlock) {</span>
+<span class="source-line-no">2070</span><span id="line-2070"> len += Long.BYTES; // we need to record the cache time for consistency check in case of</span>
+<span class="source-line-no">2071</span><span id="line-2071"> // recovery</span>
+<span class="source-line-no">2072</span><span id="line-2072"> }</span>
+<span class="source-line-no">2073</span><span id="line-2073"> long offset = alloc.allocateBlock(len);</span>
+<span class="source-line-no">2074</span><span id="line-2074"> // In the case of prefetch, we want to avoid freeSpace runs when the cache is full.</span>
+<span class="source-line-no">2075</span><span id="line-2075"> // this makes the cache allocation more predictable, and is particularly important</span>
+<span class="source-line-no">2076</span><span id="line-2076"> // when persistent cache is enabled, as it won't trigger evictions of the recovered blocks,</span>
+<span class="source-line-no">2077</span><span id="line-2077"> // which are likely the most accessed and relevant blocks in the cache.</span>
+<span class="source-line-no">2078</span><span id="line-2078"> if (isPrefetch() && alloc.getUsedSize() > acceptableSize) {</span>
+<span class="source-line-no">2079</span><span id="line-2079"> alloc.freeBlock(offset, len);</span>
+<span class="source-line-no">2080</span><span id="line-2080"> return null;</span>
+<span class="source-line-no">2081</span><span id="line-2081"> }</span>
+<span class="source-line-no">2082</span><span id="line-2082"> boolean succ = false;</span>
+<span class="source-line-no">2083</span><span id="line-2083"> BucketEntry bucketEntry = null;</span>
+<span class="source-line-no">2084</span><span id="line-2084"> try {</span>
+<span class="source-line-no">2085</span><span id="line-2085"> int diskSizeWithHeader = (data instanceof HFileBlock)</span>
+<span class="source-line-no">2086</span><span id="line-2086"> ? ((HFileBlock) data).getOnDiskSizeWithHeader()</span>
+<span class="source-line-no">2087</span><span id="line-2087"> : data.getSerializedLength();</span>
+<span class="source-line-no">2088</span><span id="line-2088"> bucketEntry = new BucketEntry(offset, len, diskSizeWithHeader, accessCounter, inMemory,</span>
+<span class="source-line-no">2089</span><span id="line-2089"> createRecycler, getByteBuffAllocator());</span>
+<span class="source-line-no">2090</span><span id="line-2090"> bucketEntry.setDeserializerReference(data.getDeserializer());</span>
+<span class="source-line-no">2091</span><span id="line-2091"> if (data instanceof HFileBlock) {</span>
+<span class="source-line-no">2092</span><span id="line-2092"> // If an instance of HFileBlock, save on some allocations.</span>
+<span class="source-line-no">2093</span><span id="line-2093"> HFileBlock block = (HFileBlock) data;</span>
+<span class="source-line-no">2094</span><span id="line-2094"> ByteBuff sliceBuf = block.getBufferReadOnly();</span>
+<span class="source-line-no">2095</span><span id="line-2095"> block.getMetaData(metaBuff);</span>
+<span class="source-line-no">2096</span><span id="line-2096"> // adds the cache time prior to the block and metadata part</span>
+<span class="source-line-no">2097</span><span id="line-2097"> if (isCachePersistent) {</span>
+<span class="source-line-no">2098</span><span id="line-2098"> ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);</span>
+<span class="source-line-no">2099</span><span id="line-2099"> buffer.putLong(bucketEntry.getCachedTime());</span>
+<span class="source-line-no">2100</span><span id="line-2100"> buffer.rewind();</span>
+<span class="source-line-no">2101</span><span id="line-2101"> ioEngine.write(buffer, offset);</span>
+<span class="source-line-no">2102</span><span id="line-2102"> ioEngine.write(sliceBuf, (offset + Long.BYTES));</span>
+<span class="source-line-no">2103</span><span id="line-2103"> } else {</span>
+<span class="source-line-no">2104</span><span id="line-2104"> ioEngine.write(sliceBuf, offset);</span>
+<span class="source-line-no">2105</span><span id="line-2105"> }</span>
+<span class="source-line-no">2106</span><span id="line-2106"> ioEngine.write(metaBuff, offset + len - metaBuff.limit());</span>
+<span class="source-line-no">2107</span><span id="line-2107"> } else {</span>
+<span class="source-line-no">2108</span><span id="line-2108"> // Only used for testing.</span>
+<span class="source-line-no">2109</span><span id="line-2109"> ByteBuffer bb = ByteBuffer.allocate(len);</span>
+<span class="source-line-no">2110</span><span id="line-2110"> data.serialize(bb, true);</span>
+<span class="source-line-no">2111</span><span id="line-2111"> ioEngine.write(bb, offset);</span>
+<span class="source-line-no">2112</span><span id="line-2112"> }</span>
+<span class="source-line-no">2113</span><span id="line-2113"> succ = true;</span>
+<span class="source-line-no">2114</span><span id="line-2114"> } finally {</span>
+<span class="source-line-no">2115</span><span id="line-2115"> if (!succ) {</span>
+<span class="source-line-no">2116</span><span id="line-2116"> alloc.freeBlock(offset, len);</span>
+<span class="source-line-no">2117</span><span id="line-2117"> }</span>
+<span class="source-line-no">2118</span><span id="line-2118"> }</span>
+<span class="source-line-no">2119</span><span id="line-2119"> realCacheSize.add(len);</span>
+<span class="source-line-no">2120</span><span id="line-2120"> return bucketEntry;</span>
+<span class="source-line-no">2121</span><span id="line-2121"> }</span>
+<span class="source-line-no">2122</span><span id="line-2122"> }</span>
+<span class="source-line-no">2123</span><span id="line-2123"></span>
+<span class="source-line-no">2124</span><span id="line-2124"> /**</span>
+<span class="source-line-no">2125</span><span id="line-2125"> * Only used in test</span>
+<span class="source-line-no">2126</span><span id="line-2126"> */</span>
+<span class="source-line-no">2127</span><span id="line-2127"> void stopWriterThreads() throws InterruptedException {</span>
+<span class="source-line-no">2128</span><span id="line-2128"> for (WriterThread writerThread : writerThreads) {</span>
+<span class="source-line-no">2129</span><span id="line-2129"> writerThread.disableWriter();</span>
+<span class="source-line-no">2130</span><span id="line-2130"> writerThread.interrupt();</span>
+<span class="source-line-no">2131</span><span id="line-2131"> writerThread.join();</span>
+<span class="source-line-no">2132</span><span id="line-2132"> }</span>
+<span class="source-line-no">2133</span><span id="line-2133"> }</span>
+<span class="source-line-no">2134</span><span id="line-2134"></span>
+<span class="source-line-no">2135</span><span id="line-2135"> @Override</span>
+<span class="source-line-no">2136</span><span id="line-2136"> public Iterator<CachedBlock> iterator() {</span>
+<span class="source-line-no">2137</span><span id="line-2137"> // Don't bother with ramcache since stuff is in here only a little while.</span>
+<span class="source-line-no">2138</span><span id="line-2138"> final Iterator<Map.Entry<BlockCacheKey, BucketEntry>> i = this.backingMap.entrySet().iterator();</span>
+<span class="source-line-no">2139</span><span id="line-2139"> return new Iterator<CachedBlock>() {</span>
+<span class="source-line-no">2140</span><span id="line-2140"> private final long now = System.nanoTime();</span>
<span class="source-line-no">2141</span><span id="line-2141"></span>
-<span class="source-line-no">2142</span><span id="line-2142"> @Override</span>
-<span class="source-line-no">2143</span><span id="line-2143"> public BlockPriority getBlockPriority() {</span>
-<span class="source-line-no">2144</span><span id="line-2144"> return e.getValue().getPriority();</span>
-<span class="source-line-no">2145</span><span id="line-2145"> }</span>
+<span class="source-line-no">2142</span><span id="line-2142"> @Override</span>
+<span class="source-line-no">2143</span><span id="line-2143"> public boolean hasNext() {</span>
+<span class="source-line-no">2144</span><span id="line-2144"> return i.hasNext();</span>
+<span class="source-line-no">2145</span><span id="line-2145"> }</span>
<span class="source-line-no">2146</span><span id="line-2146"></span>
-<span class="source-line-no">2147</span><span id="line-2147"> @Override</span>
-<span class="source-line-no">2148</span><span id="line-2148"> public BlockType getBlockType() {</span>
-<span class="source-line-no">2149</span><span id="line-2149"> // Not held by BucketEntry. Could add it if wanted on BucketEntry creation.</span>
-<span class="source-line-no">2150</span><span id="line-2150"> return null;</span>
-<span class="source-line-no">2151</span><span id="line-2151"> }</span>
-<span class="source-line-no">2152</span><span id="line-2152"></span>
-<span class="source-line-no">2153</span><span id="line-2153"> @Override</span>
-<span class="source-line-no">2154</span><span id="line-2154"> public long getOffset() {</span>
-<span class="source-line-no">2155</span><span id="line-2155"> return e.getKey().getOffset();</span>
-<span class="source-line-no">2156</span><span id="line-2156"> }</span>
-<span class="source-line-no">2157</span><span id="line-2157"></span>
-<span class="source-line-no">2158</span><span id="line-2158"> @Override</span>
-<span class="source-line-no">2159</span><span id="line-2159"> public long getSize() {</span>
-<span class="source-line-no">2160</span><span id="line-2160"> return e.getValue().getLength();</span>
-<span class="source-line-no">2161</span><span id="line-2161"> }</span>
-<span class="source-line-no">2162</span><span id="line-2162"></span>
-<span class="source-line-no">2163</span><span id="line-2163"> @Override</span>
-<span class="source-line-no">2164</span><span id="line-2164"> public long getCachedTime() {</span>
-<span class="source-line-no">2165</span><span id="line-2165"> return e.getValue().getCachedTime();</span>
-<span class="source-line-no">2166</span><span id="line-2166"> }</span>
-<span class="source-line-no">2167</span><span id="line-2167"></span>
-<span class="source-line-no">2168</span><span id="line-2168"> @Override</span>
-<span class="source-line-no">2169</span><span id="line-2169"> public String getFilename() {</span>
-<span class="source-line-no">2170</span><span id="line-2170"> return e.getKey().getHfileName();</span>
-<span class="source-line-no">2171</span><span id="line-2171"> }</span>
-<span class="source-line-no">2172</span><span id="line-2172"></span>
-<span class="source-line-no">2173</span><span id="line-2173"> @Override</span>
-<span class="source-line-no">2174</span><span id="line-2174"> public int compareTo(CachedBlock other) {</span>
-<span class="source-line-no">2175</span><span id="line-2175"> int diff = this.getFilename().compareTo(other.getFilename());</span>
-<span class="source-line-no">2176</span><span id="line-2176"> if (diff != 0) return diff;</span>
-<span class="source-line-no">2177</span><span id="line-2177"></span>
-<span class="source-line-no">2178</span><span id="line-2178"> diff = Long.compare(this.getOffset(), other.getOffset());</span>
-<span class="source-line-no">2179</span><span id="line-2179"> if (diff != 0) return diff;</span>
-<span class="source-line-no">2180</span><span id="line-2180"> if (other.getCachedTime() < 0 || this.getCachedTime() < 0) {</span>
-<span class="source-line-no">2181</span><span id="line-2181"> throw new IllegalStateException(</span>
-<span class="source-line-no">2182</span><span id="line-2182"> "" + this.getCachedTime() + ", " + other.getCachedTime());</span>
-<span class="source-line-no">2183</span><span id="line-2183"> }</span>
-<span class="source-line-no">2184</span><span id="line-2184"> return Long.compare(other.getCachedTime(), this.getCachedTime());</span>
+<span class="source-line-no">2147</span><span id="line-2147"> @Override</span>
+<span class="source-line-no">2148</span><span id="line-2148"> public CachedBlock next() {</span>
+<span class="source-line-no">2149</span><span id="line-2149"> final Map.Entry<BlockCacheKey, BucketEntry> e = i.next();</span>
+<span class="source-line-no">2150</span><span id="line-2150"> return new CachedBlock() {</span>
+<span class="source-line-no">2151</span><span id="line-2151"> @Override</span>
+<span class="source-line-no">2152</span><span id="line-2152"> public String toString() {</span>
+<span class="source-line-no">2153</span><span id="line-2153"> return BlockCacheUtil.toString(this, now);</span>
+<span class="source-line-no">2154</span><span id="line-2154"> }</span>
+<span class="source-line-no">2155</span><span id="line-2155"></span>
+<span class="source-line-no">2156</span><span id="line-2156"> @Override</span>
+<span class="source-line-no">2157</span><span id="line-2157"> public BlockPriority getBlockPriority() {</span>
+<span class="source-line-no">2158</span><span id="line-2158"> return e.getValue().getPriority();</span>
+<span class="source-line-no">2159</span><span id="line-2159"> }</span>
+<span class="source-line-no">2160</span><span id="line-2160"></span>
+<span class="source-line-no">2161</span><span id="line-2161"> @Override</span>
+<span class="source-line-no">2162</span><span id="line-2162"> public BlockType getBlockType() {</span>
+<span class="source-line-no">2163</span><span id="line-2163"> // Not held by BucketEntry. Could add it if wanted on BucketEntry creation.</span>
+<span class="source-line-no">2164</span><span id="line-2164"> return null;</span>
+<span class="source-line-no">2165</span><span id="line-2165"> }</span>
+<span class="source-line-no">2166</span><span id="line-2166"></span>
+<span class="source-line-no">2167</span><span id="line-2167"> @Override</span>
+<span class="source-line-no">2168</span><span id="line-2168"> public long getOffset() {</span>
+<span class="source-line-no">2169</span><span id="line-2169"> return e.getKey().getOffset();</span>
+<span class="source-line-no">2170</span><span id="line-2170"> }</span>
+<span class="source-line-no">2171</span><span id="line-2171"></span>
+<span class="source-line-no">2172</span><span id="line-2172"> @Override</span>
+<span class="source-line-no">2173</span><span id="line-2173"> public long getSize() {</span>
+<span class="source-line-no">2174</span><span id="line-2174"> return e.getValue().getLength();</span>
+<span class="source-line-no">2175</span><span id="line-2175"> }</span>
+<span class="source-line-no">2176</span><span id="line-2176"></span>
+<span class="source-line-no">2177</span><span id="line-2177"> @Override</span>
+<span class="source-line-no">2178</span><span id="line-2178"> public long getCachedTime() {</span>
+<span class="source-line-no">2179</span><span id="line-2179"> return e.getValue().getCachedTime();</span>
+<span class="source-line-no">2180</span><span id="line-2180"> }</span>
+<span class="source-line-no">2181</span><span id="line-2181"></span>
+<span class="source-line-no">2182</span><span id="line-2182"> @Override</span>
+<span class="source-line-no">2183</span><span id="line-2183"> public String getFilename() {</span>
+<span class="source-line-no">2184</span><span id="line-2184"> return e.getKey().getHfileName();</span>
<span class="source-line-no">2185</span><span id="line-2185"> }</span>
<span class="source-line-no">2186</span><span id="line-2186"></span>
<span class="source-line-no">2187</span><span id="line-2187"> @Override</span>
-<span class="source-line-no">2188</span><span id="line-2188"> public int hashCode() {</span>
-<span class="source-line-no">2189</span><span id="line-2189"> return e.getKey().hashCode();</span>
-<span class="source-line-no">2190</span><span id="line-2190"> }</span>
+<span class="source-line-no">2188</span><span id="line-2188"> public int compareTo(CachedBlock other) {</span>
+<span class="source-line-no">2189</span><span id="line-2189"> int diff = this.getFilename().compareTo(other.getFilename());</span>
+<span class="source-line-no">2190</span><span id="line-2190"> if (diff != 0) return diff;</span>
<span class="source-line-no">2191</span><span id="line-2191"></span>
-<span class="source-line-no">2192</span><span id="line-2192"> @Override</span>
-<span class="source-line-no">2193</span><span id="line-2193"> public boolean equals(Object obj) {</span>
-<span class="source-line-no">2194</span><span id="line-2194"> if (obj instanceof CachedBlock) {</span>
-<span class="source-line-no">2195</span><span id="line-2195"> CachedBlock cb = (CachedBlock) obj;</span>
-<span class="source-line-no">2196</span><span id="line-2196"> return compareTo(cb) == 0;</span>
-<span class="source-line-no">2197</span><span id="line-2197"> } else {</span>
-<span class="source-line-no">2198</span><span id="line-2198"> return false;</span>
-<span class="source-line-no">2199</span><span id="line-2199"> }</span>
-<span class="source-line-no">2200</span><span id="line-2200"> }</span>
-<span class="source-line-no">2201</span><span id="line-2201"> };</span>
-<span class="source-line-no">2202</span><span id="line-2202"> }</span>
-<span class="source-line-no">2203</span><span id="line-2203"></span>
-<span class="source-line-no">2204</span><span id="line-2204"> @Override</span>
-<span class="source-line-no">2205</span><span id="line-2205"> public void remove() {</span>
-<span class="source-line-no">2206</span><span id="line-2206"> throw new UnsupportedOperationException();</span>
-<span class="source-line-no">2207</span><span id="line-2207"> }</span>
-<span class="source-line-no">2208</span><span id="line-2208"> };</span>
-<span class="source-line-no">2209</span><span id="line-2209"> }</span>
-<span class="source-line-no">2210</span><span id="line-2210"></span>
-<span class="source-line-no">2211</span><span id="line-2211"> @Override</span>
-<span class="source-line-no">2212</span><span id="line-2212"> public BlockCache[] getBlockCaches() {</span>
-<span class="source-line-no">2213</span><span id="line-2213"> return null;</span>
-<span class="source-line-no">2214</span><span id="line-2214"> }</span>
-<span class="source-line-no">2215</span><span id="line-2215"></span>
-<span class="source-line-no">2216</span><span id="line-2216"> public int getRpcRefCount(BlockCacheKey cacheKey) {</span>
-<span class="source-line-no">2217</span><span id="line-2217"> BucketEntry bucketEntry = backingMap.get(cacheKey);</span>
-<span class="source-line-no">2218</span><span id="line-2218"> if (bucketEntry != null) {</span>
-<span class="source-line-no">2219</span><span id="line-2219"> return bucketEntry.refCnt() - (bucketEntry.markedAsEvicted.get() ? 0 : 1);</span>
-<span class="source-line-no">2220</span><span id="line-2220"> }</span>
-<span class="source-line-no">2221</span><span id="line-2221"> return 0;</span>
-<span class="source-line-no">2222</span><span id="line-2222"> }</span>
-<span class="source-line-no">2223</span><span id="line-2223"></span>
-<span class="source-line-no">2224</span><span id="line-2224"> float getAcceptableFactor() {</span>
-<span class="source-line-no">2225</span><span id="line-2225"> return acceptableFactor;</span>
-<span class="source-line-no">2226</span><span id="line-2226"> }</span>
-<span class="source-line-no">2227</span><span id="line-2227"></span>
-<span class="source-line-no">2228</span><span id="line-2228"> float getMinFactor() {</span>
-<span class="source-line-no">2229</span><span id="line-2229"> return minFactor;</span>
-<span class="source-line-no">2230</span><span id="line-2230"> }</span>
-<span class="source-line-no">2231</span><span id="line-2231"></span>
-<span class="source-line-no">2232</span><span id="line-2232"> float getExtraFreeFactor() {</span>
-<span class="source-line-no">2233</span><span id="line-2233"> return extraFreeFactor;</span>
-<span class="source-line-no">2234</span><span id="line-2234"> }</span>
-<span class="source-line-no">2235</span><span id="line-2235"></span>
-<span class="source-line-no">2236</span><span id="line-2236"> float getSingleFactor() {</span>
-<span class="source-line-no">2237</span><span id="line-2237"> return singleFactor;</span>
-<span class="source-line-no">2238</span><span id="line-2238"> }</span>
-<span class="source-line-no">2239</span><span id="line-2239"></span>
-<span class="source-line-no">2240</span><span id="line-2240"> float getMultiFactor() {</span>
-<span class="source-line-no">2241</span><span id="line-2241"> return multiFactor;</span>
-<span class="source-line-no">2242</span><span id="line-2242"> }</span>
-<span class="source-line-no">2243</span><span id="line-2243"></span>
-<span class="source-line-no">2244</span><span id="line-2244"> float getMemoryFactor() {</span>
-<span class="source-line-no">2245</span><span id="line-2245"> return memoryFactor;</span>
-<span class="source-line-no">2246</span><span id="line-2246"> }</span>
-<span class="source-line-no">2247</span><span id="line-2247"></span>
-<span class="source-line-no">2248</span><span id="line-2248"> long getQueueAdditionWaitTime() {</span>
-<span class="source-line-no">2249</span><span id="line-2249"> return queueAdditionWaitTime;</span>
-<span class="source-line-no">2250</span><span id="line-2250"> }</span>
-<span class="source-line-no">2251</span><span id="line-2251"></span>
-<span class="source-line-no">2252</span><span id="line-2252"> long getPersistenceChunkSize() {</span>
-<span class="source-line-no">2253</span><span id="line-2253"> return persistenceChunkSize;</span>
-<span class="source-line-no">2254</span><span id="line-2254"> }</span>
-<span class="source-line-no">2255</span><span id="line-2255"></span>
-<span class="source-line-no">2256</span><span id="line-2256"> long getBucketcachePersistInterval() {</span>
-<span class="source-line-no">2257</span><span id="line-2257"> return bucketcachePersistInterval;</span>
-<span class="source-line-no">2258</span><span id="line-2258"> }</span>
-<span class="source-line-no">2259</span><span id="line-2259"></span>
-<span class="source-line-no">2260</span><span id="line-2260"> public String getPersistencePath() {</span>
-<span class="source-line-no">2261</span><span id="line-2261"> return persistencePath;</span>
-<span class="source-line-no">2262</span><span id="line-2262"> }</span>
-<span class="source-line-no">2263</span><span id="line-2263"></span>
-<span class="source-line-no">2264</span><span id="line-2264"> /**</span>
-<span class="source-line-no">2265</span><span id="line-2265"> * Wrapped the delegate ConcurrentMap with maintaining its block's reference count.</span>
-<span class="source-line-no">2266</span><span id="line-2266"> */</span>
-<span class="source-line-no">2267</span><span id="line-2267"> static class RAMCache {</span>
-<span class="source-line-no">2268</span><span id="line-2268"> /**</span>
-<span class="source-line-no">2269</span><span id="line-2269"> * Defined the map as {@link ConcurrentHashMap} explicitly here, because in</span>
-<span class="source-line-no">2270</span><span id="line-2270"> * {@link RAMCache#get(BlockCacheKey)} and</span>
-<span class="source-line-no">2271</span><span id="line-2271"> * {@link RAMCache#putIfAbsent(BlockCacheKey, BucketCache.RAMQueueEntry)} , we need to guarantee</span>
-<span class="source-line-no">2272</span><span id="line-2272"> * the atomicity of map#computeIfPresent(key, func) and map#putIfAbsent(key, func). Besides, the</span>
-<span class="source-line-no">2273</span><span id="line-2273"> * func method can execute exactly once only when the key is present(or absent) and under the</span>
-<span class="source-line-no">2274</span><span id="line-2274"> * lock context. Otherwise, the reference count of block will be messed up. Notice that the</span>
-<span class="source-line-no">2275</span><span id="line-2275"> * {@link java.util.concurrent.ConcurrentSkipListMap} can not guarantee that.</span>
-<span class="source-line-no">2276</span><span id="line-2276"> */</span>
-<span class="source-line-no">2277</span><span id="line-2277"> final ConcurrentHashMap<BlockCacheKey, RAMQueueEntry> delegate = new ConcurrentHashMap<>();</span>
-<span class="source-line-no">2278</span><span id="line-2278"></span>
-<span class="source-line-no">2279</span><span id="line-2279"> public boolean containsKey(BlockCacheKey key) {</span>
-<span class="source-line-no">2280</span><span id="line-2280"> return delegate.containsKey(key);</span>
-<span class="source-line-no">2281</span><span id="line-2281"> }</span>
-<span class="source-line-no">2282</span><span id="line-2282"></span>
-<span class="source-line-no">2283</span><span id="line-2283"> public RAMQueueEntry get(BlockCacheKey key) {</span>
-<span class="source-line-no">2284</span><span id="line-2284"> return delegate.computeIfPresent(key, (k, re) -> {</span>
-<span class="source-line-no">2285</span><span id="line-2285"> // It'll be referenced by RPC, so retain atomically here. if the get and retain is not</span>
-<span class="source-line-no">2286</span><span id="line-2286"> // atomic, another thread may remove and release the block, when retaining in this thread we</span>
-<span class="source-line-no">2287</span><span id="line-2287"> // may retain a block with refCnt=0 which is disallowed. (see HBASE-22422)</span>
-<span class="source-line-no">2288</span><span id="line-2288"> re.getData().retain();</span>
-<span class="source-line-no">2289</span><span id="line-2289"> return re;</span>
-<span class="source-line-no">2290</span><span id="line-2290"> });</span>
-<span class="source-line-no">2291</span><span id="line-2291"> }</span>
+<span class="source-line-no">2192</span><span id="line-2192"> diff = Long.compare(this.getOffset(), other.getOffset());</span>
+<span class="source-line-no">2193</span><span id="line-2193"> if (diff != 0) return diff;</span>
+<span class="source-line-no">2194</span><span id="line-2194"> if (other.getCachedTime() < 0 || this.getCachedTime() < 0) {</span>
+<span class="source-line-no">2195</span><span id="line-2195"> throw new IllegalStateException(</span>
+<span class="source-line-no">2196</span><span id="line-2196"> "" + this.getCachedTime() + ", " + other.getCachedTime());</span>
+<span class="source-line-no">2197</span><span id="line-2197"> }</span>
+<span class="source-line-no">2198</span><span id="line-2198"> return Long.compare(other.getCachedTime(), this.getCachedTime());</span>
+<span class="source-line-no">2199</span><span id="line-2199"> }</span>
+<span class="source-line-no">2200</span><span id="line-2200"></span>
+<span class="source-line-no">2201</span><span id="line-2201"> @Override</span>
+<span class="source-line-no">2202</span><span id="line-2202"> public int hashCode() {</span>
+<span class="source-line-no">2203</span><span id="line-2203"> return e.getKey().hashCode();</span>
+<span class="source-line-no">2204</span><span id="line-2204"> }</span>
+<span class="source-line-no">2205</span><span id="line-2205"></span>
+<span class="source-line-no">2206</span><span id="line-2206"> @Override</span>
+<span class="source-line-no">2207</span><span id="line-2207"> public boolean equals(Object obj) {</span>
+<span class="source-line-no">2208</span><span id="line-2208"> if (obj instanceof CachedBlock) {</span>
+<span class="source-line-no">2209</span><span id="line-2209"> CachedBlock cb = (CachedBlock) obj;</span>
+<span class="source-line-no">2210</span><span id="line-2210"> return compareTo(cb) == 0;</span>
+<span class="source-line-no">2211</span><span id="line-2211"> } else {</span>
+<span class="source-line-no">2212</span><span id="line-2212"> return false;</span>
+<span class="source-line-no">2213</span><span id="line-2213"> }</span>
+<span class="source-line-no">2214</span><span id="line-2214"> }</span>
+<span class="source-line-no">2215</span><span id="line-2215"> };</span>
+<span class="source-line-no">2216</span><span id="line-2216"> }</span>
+<span class="source-line-no">2217</span><span id="line-2217"></span>
+<span class="source-line-no">2218</span><span id="line-2218"> @Override</span>
+<span class="source-line-no">2219</span><span id="line-2219"> public void remove() {</span>
+<span class="source-line-no">2220</span><span id="line-2220"> throw new UnsupportedOperationException();</span>
+<span class="source-line-no">2221</span><span id="line-2221"> }</span>
+<span class="source-line-no">2222</span><span id="line-2222"> };</span>
+<span class="source-line-no">2223</span><span id="line-2223"> }</span>
+<span class="source-line-no">2224</span><span id="line-2224"></span>
+<span class="source-line-no">2225</span><span id="line-2225"> @Override</span>
+<span class="source-line-no">2226</span><span id="line-2226"> public BlockCache[] getBlockCaches() {</span>
+<span class="source-line-no">2227</span><span id="line-2227"> return null;</span>
+<span class="source-line-no">2228</span><span id="line-2228"> }</span>
+<span class="source-line-no">2229</span><span id="line-2229"></span>
+<span class="source-line-no">2230</span><span id="line-2230"> public int getRpcRefCount(BlockCacheKey cacheKey) {</span>
+<span class="source-line-no">2231</span><span id="line-2231"> BucketEntry bucketEntry = backingMap.get(cacheKey);</span>
+<span class="source-line-no">2232</span><span id="line-2232"> if (bucketEntry != null) {</span>
+<span class="source-line-no">2233</span><span id="line-2233"> return bucketEntry.refCnt() - (bucketEntry.markedAsEvicted.get() ? 0 : 1);</span>
+<span class="source-line-no">2234</span><span id="line-2234"> }</span>
+<span class="source-line-no">2235</span><span id="line-2235"> return 0;</span>
+<span class="source-line-no">2236</span><span id="line-2236"> }</span>
+<span class="source-line-no">2237</span><span id="line-2237"></span>
+<span class="source-line-no">2238</span><span id="line-2238"> float getAcceptableFactor() {</span>
+<span class="source-line-no">2239</span><span id="line-2239"> return acceptableFactor;</span>
+<span class="source-line-no">2240</span><span id="line-2240"> }</span>
+<span class="source-line-no">2241</span><span id="line-2241"></span>
+<span class="source-line-no">2242</span><span id="line-2242"> float getMinFactor() {</span>
+<span class="source-line-no">2243</span><span id="line-2243"> return minFactor;</span>
+<span class="source-line-no">2244</span><span id="line-2244"> }</span>
+<span class="source-line-no">2245</span><span id="line-2245"></span>
+<span class="source-line-no">2246</span><span id="line-2246"> float getExtraFreeFactor() {</span>
+<span class="source-line-no">2247</span><span id="line-2247"> return extraFreeFactor;</span>
+<span class="source-line-no">2248</span><span id="line-2248"> }</span>
+<span class="source-line-no">2249</span><span id="line-2249"></span>
+<span class="source-line-no">2250</span><span id="line-2250"> float getSingleFactor() {</span>
+<span class="source-line-no">2251</span><span id="line-2251"> return singleFactor;</span>
+<span class="source-line-no">2252</span><span id="line-2252"> }</span>
+<span class="source-line-no">2253</span><span id="line-2253"></span>
+<span class="source-line-no">2254</span><span id="line-2254"> float getMultiFactor() {</span>
+<span class="source-line-no">2255</span><span id="line-2255"> return multiFactor;</span>
+<span class="source-line-no">2256</span><span id="line-2256"> }</span>
+<span class="source-line-no">2257</span><span id="line-2257"></span>
+<span class="source-line-no">2258</span><span id="line-2258"> float getMemoryFactor() {</span>
+<span class="source-line-no">2259</span><span id="line-2259"> return memoryFactor;</span>
+<span class="source-line-no">2260</span><span id="line-2260"> }</span>
+<span class="source-line-no">2261</span><span id="line-2261"></span>
+<span class="source-line-no">2262</span><span id="line-2262"> long getQueueAdditionWaitTime() {</span>
+<span class="source-line-no">2263</span><span id="line-2263"> return queueAdditionWaitTime;</span>
+<span class="source-line-no">2264</span><span id="line-2264"> }</span>
+<span class="source-line-no">2265</span><span id="line-2265"></span>
+<span class="source-line-no">2266</span><span id="line-2266"> long getPersistenceChunkSize() {</span>
+<span class="source-line-no">2267</span><span id="line-2267"> return persistenceChunkSize;</span>
+<span class="source-line-no">2268</span><span id="line-2268"> }</span>
+<span class="source-line-no">2269</span><span id="line-2269"></span>
+<span class="source-line-no">2270</span><span id="line-2270"> long getBucketcachePersistInterval() {</span>
+<span class="source-line-no">2271</span><span id="line-2271"> return bucketcachePersistInterval;</span>
+<span class="source-line-no">2272</span><span id="line-2272"> }</span>
+<span class="source-line-no">2273</span><span id="line-2273"></span>
+<span class="source-line-no">2274</span><span id="line-2274"> public String getPersistencePath() {</span>
+<span class="source-line-no">2275</span><span id="line-2275"> return persistencePath;</span>
+<span class="source-line-no">2276</span><span id="line-2276"> }</span>
+<span class="source-line-no">2277</span><span id="line-2277"></span>
+<span class="source-line-no">2278</span><span id="line-2278"> /**</span>
+<span class="source-line-no">2279</span><span id="line-2279"> * Wrapped the delegate ConcurrentMap with maintaining its block's reference count.</span>
+<span class="source-line-no">2280</span><span id="line-2280"> */</span>
+<span class="source-line-no">2281</span><span id="line-2281"> static class RAMCache {</span>
+<span class="source-line-no">2282</span><span id="line-2282"> /**</span>
+<span class="source-line-no">2283</span><span id="line-2283"> * Defined the map as {@link ConcurrentHashMap} explicitly here, because in</span>
+<span class="source-line-no">2284</span><span id="line-2284"> * {@link RAMCache#get(BlockCacheKey)} and</span>
+<span class="source-line-no">2285</span><span id="line-2285"> * {@link RAMCache#putIfAbsent(BlockCacheKey, BucketCache.RAMQueueEntry)} , we need to guarantee</span>
+<span class="source-line-no">2286</span><span id="line-2286"> * the atomicity of map#computeIfPresent(key, func) and map#putIfAbsent(key, func). Besides, the</span>
+<span class="source-line-no">2287</span><span id="line-2287"> * func method can execute exactly once only when the key is present(or absent) and under the</span>
+<span class="source-line-no">2288</span><span id="line-2288"> * lock context. Otherwise, the reference count of block will be messed up. Notice that the</span>
+<span class="source-line-no">2289</span><span id="line-2289"> * {@link java.util.concurrent.ConcurrentSkipListMap} can not guarantee that.</span>
+<span class="source-line-no">2290</span><span id="line-2290"> */</span>
+<span class="source-line-no">2291</span><span id="line-2291"> final ConcurrentHashMap<BlockCacheKey, RAMQueueEntry> delegate = new ConcurrentHashMap<>();</span>
<span class="source-line-no">2292</span><span id="line-2292"></span>
-<span class="source-line-no">2293</span><span id="line-2293"> /**</span>
-<span class="source-line-no">2294</span><span id="line-2294"> * Return the previous associated value, or null if absent. It has the same meaning as</span>
-<span class="source-line-no">2295</span><span id="line-2295"> * {@link ConcurrentMap#putIfAbsent(Object, Object)}</span>
-<span class="source-line-no">2296</span><span id="line-2296"> */</span>
-<span class="source-line-no">2297</span><span id="line-2297"> public RAMQueueEntry putIfAbsent(BlockCacheKey key, RAMQueueEntry entry) {</span>
-<span class="source-line-no">2298</span><span id="line-2298"> AtomicBoolean absent = new AtomicBoolean(false);</span>
-<span class="source-line-no">2299</span><span id="line-2299"> RAMQueueEntry re = delegate.computeIfAbsent(key, k -> {</span>
-<span class="source-line-no">2300</span><span id="line-2300"> // The RAMCache reference to this entry, so reference count should be increment.</span>
-<span class="source-line-no">2301</span><span id="line-2301"> entry.getData().retain();</span>
-<span class="source-line-no">2302</span><span id="line-2302"> absent.set(true);</span>
-<span class="source-line-no">2303</span><span id="line-2303"> return entry;</span>
+<span class="source-line-no">2293</span><span id="line-2293"> public boolean containsKey(BlockCacheKey key) {</span>
+<span class="source-line-no">2294</span><span id="line-2294"> return delegate.containsKey(key);</span>
+<span class="source-line-no">2295</span><span id="line-2295"> }</span>
+<span class="source-line-no">2296</span><span id="line-2296"></span>
+<span class="source-line-no">2297</span><span id="line-2297"> public RAMQueueEntry get(BlockCacheKey key) {</span>
+<span class="source-line-no">2298</span><span id="line-2298"> return delegate.computeIfPresent(key, (k, re) -> {</span>
+<span class="source-line-no">2299</span><span id="line-2299"> // It'll be referenced by RPC, so retain atomically here. if the get and retain is not</span>
+<span class="source-line-no">2300</span><span id="line-2300"> // atomic, another thread may remove and release the block, when retaining in this thread we</span>
+<span class="source-line-no">2301</span><span id="line-2301"> // may retain a block with refCnt=0 which is disallowed. (see HBASE-22422)</span>
+<span class="source-line-no">2302</span><span id="line-2302"> re.getData().retain();</span>
+<span class="source-line-no">2303</span><span id="line-2303"> return re;</span>
<span class="source-line-no">2304</span><span id="line-2304"> });</span>
-<span class="source-line-no">2305</span><span id="line-2305"> return absent.get() ? null : re;</span>
-<span class="source-line-no">2306</span><span id="line-2306"> }</span>
-<span class="source-line-no">2307</span><span id="line-2307"></span>
-<span class="source-line-no">2308</span><span id="line-2308"> public boolean remove(BlockCacheKey key) {</span>
-<span class="source-line-no">2309</span><span id="line-2309"> return remove(key, re -> {</span>
-<span class="source-line-no">2310</span><span id="line-2310"> });</span>
-<span class="source-line-no">2311</span><span id="line-2311"> }</span>
-<span class="source-line-no">2312</span><span id="line-2312"></span>
-<span class="source-line-no">2313</span><span id="line-2313"> /**</span>
-<span class="source-line-no">2314</span><span id="line-2314"> * Defined an {@link Consumer} here, because once the removed entry release its reference count,</span>
-<span class="source-line-no">2315</span><span id="line-2315"> * then it's ByteBuffers may be recycled and accessing it outside this method will be thrown an</span>
-<span class="source-line-no">2316</span><span id="line-2316"> * exception. the consumer will access entry to remove before release its reference count.</span>
-<span class="source-line-no">2317</span><span id="line-2317"> * Notice, don't change its reference count in the {@link Consumer}</span>
-<span class="source-line-no">2318</span><span id="line-2318"> */</span>
-<span class="source-line-no">2319</span><span id="line-2319"> public boolean remove(BlockCacheKey key, Consumer<RAMQueueEntry> action) {</span>
-<span class="source-line-no">2320</span><span id="line-2320"> RAMQueueEntry previous = delegate.remove(key);</span>
-<span class="source-line-no">2321</span><span id="line-2321"> action.accept(previous);</span>
-<span class="source-line-no">2322</span><span id="line-2322"> if (previous != null) {</span>
-<span class="source-line-no">2323</span><span id="line-2323"> previous.getData().release();</span>
-<span class="source-line-no">2324</span><span id="line-2324"> }</span>
-<span class="source-line-no">2325</span><span id="line-2325"> return previous != null;</span>
-<span class="source-line-no">2326</span><span id="line-2326"> }</span>
-<span class="source-line-no">2327</span><span id="line-2327"></span>
-<span class="source-line-no">2328</span><span id="line-2328"> public boolean isEmpty() {</span>
-<span class="source-line-no">2329</span><span id="line-2329"> return delegate.isEmpty();</span>
-<span class="source-line-no">2330</span><span id="line-2330"> }</span>
-<span class="source-line-no">2331</span><span id="line-2331"></span>
-<span class="source-line-no">2332</span><span id="line-2332"> public void clear() {</span>
-<span class="source-line-no">2333</span><span id="line-2333"> Iterator<Map.Entry<BlockCacheKey, RAMQueueEntry>> it = delegate.entrySet().iterator();</span>
-<span class="source-line-no">2334</span><span id="line-2334"> while (it.hasNext()) {</span>
-<span class="source-line-no">2335</span><span id="line-2335"> RAMQueueEntry re = it.next().getValue();</span>
-<span class="source-line-no">2336</span><span id="line-2336"> it.remove();</span>
-<span class="source-line-no">2337</span><span id="line-2337"> re.getData().release();</span>
+<span class="source-line-no">2305</span><span id="line-2305"> }</span>
+<span class="source-line-no">2306</span><span id="line-2306"></span>
+<span class="source-line-no">2307</span><span id="line-2307"> /**</span>
+<span class="source-line-no">2308</span><span id="line-2308"> * Return the previous associated value, or null if absent. It has the same meaning as</span>
+<span class="source-line-no">2309</span><span id="line-2309"> * {@link ConcurrentMap#putIfAbsent(Object, Object)}</span>
+<span class="source-line-no">2310</span><span id="line-2310"> */</span>
+<span class="source-line-no">2311</span><span id="line-2311"> public RAMQueueEntry putIfAbsent(BlockCacheKey key, RAMQueueEntry entry) {</span>
+<span class="source-line-no">2312</span><span id="line-2312"> AtomicBoolean absent = new AtomicBoolean(false);</span>
+<span class="source-line-no">2313</span><span id="line-2313"> RAMQueueEntry re = delegate.computeIfAbsent(key, k -> {</span>
+<span class="source-line-no">2314</span><span id="line-2314"> // The RAMCache reference to this entry, so reference count should be increment.</span>
+<span class="source-line-no">2315</span><span id="line-2315"> entry.getData().retain();</span>
+<span class="source-line-no">2316</span><span id="line-2316"> absent.set(true);</span>
+<span class="source-line-no">2317</span><span id="line-2317"> return entry;</span>
+<span class="source-line-no">2318</span><span id="line-2318"> });</span>
+<span class="source-line-no">2319</span><span id="line-2319"> return absent.get() ? null : re;</span>
+<span class="source-line-no">2320</span><span id="line-2320"> }</span>
+<span class="source-line-no">2321</span><span id="line-2321"></span>
+<span class="source-line-no">2322</span><span id="line-2322"> public boolean remove(BlockCacheKey key) {</span>
+<span class="source-line-no">2323</span><span id="line-2323"> return remove(key, re -> {</span>
+<span class="source-line-no">2324</span><span id="line-2324"> });</span>
+<span class="source-line-no">2325</span><span id="line-2325"> }</span>
+<span class="source-line-no">2326</span><span id="line-2326"></span>
+<span class="source-line-no">2327</span><span id="line-2327"> /**</span>
+<span class="source-line-no">2328</span><span id="line-2328"> * Defined an {@link Consumer} here, because once the removed entry release its reference count,</span>
+<span class="source-line-no">2329</span><span id="line-2329"> * then it's ByteBuffers may be recycled and accessing it outside this method will be thrown an</span>
+<span class="source-line-no">2330</span><span id="line-2330"> * exception. the consumer will access entry to remove before release its reference count.</span>
+<span class="source-line-no">2331</span><span id="line-2331"> * Notice, don't change its reference count in the {@link Consumer}</span>
+<span class="source-line-no">2332</span><span id="line-2332"> */</span>
+<span class="source-line-no">2333</span><span id="line-2333"> public boolean remove(BlockCacheKey key, Consumer<RAMQueueEntry> action) {</span>
+<span class="source-line-no">2334</span><span id="line-2334"> RAMQueueEntry previous = delegate.remove(key);</span>
+<span class="source-line-no">2335</span><span id="line-2335"> action.accept(previous);</span>
+<span class="source-line-no">2336</span><span id="line-2336"> if (previous != null) {</span>
+<span class="source-line-no">2337</span><span id="line-2337"> previous.getData().release();</span>
<span class="source-line-no">2338</span><span id="line-2338"> }</span>
-<span class="source-line-no">2339</span><span id="line-2339"> }</span>
-<span class="source-line-no">2340</span><span id="line-2340"></span>
-<span class="source-line-no">2341</span><span id="line-2341"> public boolean hasBlocksForFile(String fileName) {</span>
-<span class="source-line-no">2342</span><span id="line-2342"> return delegate.keySet().stream().filter(key -> key.getHfileName().equals(fileName))</span>
-<span class="source-line-no">2343</span><span id="line-2343"> .findFirst().isPresent();</span>
+<span class="source-line-no">2339</span><span id="line-2339"> return previous != null;</span>
+<span class="source-line-no">2340</span><span id="line-2340"> }</span>
+<span class="source-line-no">2341</span><span id="line-2341"></span>
+<span class="source-line-no">2342</span><span id="line-2342"> public boolean isEmpty() {</span>
+<span class="source-line-no">2343</span><span id="line-2343"> return delegate.isEmpty();</span>
<span class="source-line-no">2344</span><span id="line-2344"> }</span>
-<span class="source-line-no">2345</span><span id="line-2345"> }</span>
-<span class="source-line-no">2346</span><span id="line-2346"></span>
-<span class="source-line-no">2347</span><span id="line-2347"> public Map<BlockCacheKey, BucketEntry> getBackingMap() {</span>
-<span class="source-line-no">2348</span><span id="line-2348"> return backingMap;</span>
-<span class="source-line-no">2349</span><span id="line-2349"> }</span>
-<span class="source-line-no">2350</span><span id="line-2350"></span>
-<span class="source-line-no">2351</span><span id="line-2351"> public AtomicBoolean getBackingMapValidated() {</span>
-<span class="source-line-no">2352</span><span id="line-2352"> return backingMapValidated;</span>
-<span class="source-line-no">2353</span><span id="line-2353"> }</span>
+<span class="source-line-no">2345</span><span id="line-2345"></span>
+<span class="source-line-no">2346</span><span id="line-2346"> public void clear() {</span>
+<span class="source-line-no">2347</span><span id="line-2347"> Iterator<Map.Entry<BlockCacheKey, RAMQueueEntry>> it = delegate.entrySet().iterator();</span>
+<span class="source-line-no">2348</span><span id="line-2348"> while (it.hasNext()) {</span>
+<span class="source-line-no">2349</span><span id="line-2349"> RAMQueueEntry re = it.next().getValue();</span>
+<span class="source-line-no">2350</span><span id="line-2350"> it.remove();</span>
+<span class="source-line-no">2351</span><span id="line-2351"> re.getData().release();</span>
+<span class="source-line-no">2352</span><span id="line-2352"> }</span>
+<span class="source-line-no">2353</span><span id="line-2353"> }</span>
<span class="source-line-no">2354</span><span id="line-2354"></span>
-<span class="source-line-no">2355</span><span id="line-2355"> @Override</span>
-<span class="source-line-no">2356</span><span id="line-2356"> public Optional<Map<String, Pair<String, Long>>> getFullyCachedFiles() {</span>
-<span class="source-line-no">2357</span><span id="line-2357"> return Optional.of(fullyCachedFiles);</span>
-<span class="source-line-no">2358</span><span id="line-2358"> }</span>
-<span class="source-line-no">2359</span><span id="line-2359"></span>
-<span class="source-line-no">2360</span><span id="line-2360"> public static Optional<BucketCache> getBucketCacheFromCacheConfig(CacheConfig cacheConf) {</span>
-<span class="source-line-no">2361</span><span id="line-2361"> if (cacheConf.getBlockCache().isPresent()) {</span>
-<span class="source-line-no">2362</span><span id="line-2362"> BlockCache bc = cacheConf.getBlockCache().get();</span>
-<span class="source-line-no">2363</span><span id="line-2363"> if (bc instanceof CombinedBlockCache) {</span>
-<span class="source-line-no">2364</span><span id="line-2364"> BlockCache l2 = ((CombinedBlockCache) bc).getSecondLevelCache();</span>
-<span class="source-line-no">2365</span><span id="line-2365"> if (l2 instanceof BucketCache) {</span>
-<span class="source-line-no">2366</span><span id="line-2366"> return Optional.of((BucketCache) l2);</span>
-<span class="source-line-no">2367</span><span id="line-2367"> }</span>
-<span class="source-line-no">2368</span><span id="line-2368"> } else if (bc instanceof BucketCache) {</span>
-<span class="source-line-no">2369</span><span id="line-2369"> return Optional.of((BucketCache) bc);</span>
-<span class="source-line-no">2370</span><span id="line-2370"> }</span>
-<span class="source-line-no">2371</span><span id="line-2371"> }</span>
-<span class="source-line-no">2372</span><span id="line-2372"> return Optional.empty();</span>
-<span class="source-line-no">2373</span><span id="line-2373"> }</span>
-<span class="source-line-no">2374</span><span id="line-2374"></span>
-<span class="source-line-no">2375</span><span id="line-2375"> @Override</span>
-<span class="source-line-no">2376</span><span id="line-2376"> public void notifyFileCachingCompleted(Path fileName, int totalBlockCount, int dataBlockCount,</span>
-<span class="source-line-no">2377</span><span id="line-2377"> long size) {</span>
-<span class="source-line-no">2378</span><span id="line-2378"> // block eviction may be happening in the background as prefetch runs,</span>
-<span class="source-line-no">2379</span><span id="line-2379"> // so we need to count all blocks for this file in the backing map under</span>
-<span class="source-line-no">2380</span><span id="line-2380"> // a read lock for the block offset</span>
-<span class="source-line-no">2381</span><span id="line-2381"> final List<ReentrantReadWriteLock> locks = new ArrayList<>();</span>
-<span class="source-line-no">2382</span><span id="line-2382"> LOG.debug("Notifying caching completed for file {}, with total blocks {}, and data blocks {}",</span>
-<span class="source-line-no">2383</span><span id="line-2383"> fileName, totalBlockCount, dataBlockCount);</span>
-<span class="source-line-no">2384</span><span id="line-2384"> try {</span>
-<span class="source-line-no">2385</span><span id="line-2385"> int count = 0;</span>
-<span class="source-line-no">2386</span><span id="line-2386"> LOG.debug("iterating over {} entries in the backing map", backingMap.size());</span>
-<span class="source-line-no">2387</span><span id="line-2387"> Set<BlockCacheKey> result = getAllCacheKeysForFile(fileName.getName(), 0, Long.MAX_VALUE);</span>
-<span class="source-line-no">2388</span><span id="line-2388"> if (result.isEmpty() && StoreFileInfo.isReference(fileName)) {</span>
-<span class="source-line-no">2389</span><span id="line-2389"> result = getAllCacheKeysForFile(</span>
-<span class="source-line-no">2390</span><span id="line-2390"> StoreFileInfo.getReferredToRegionAndFile(fileName.getName()).getSecond(), 0,</span>
-<span class="source-line-no">2391</span><span id="line-2391"> Long.MAX_VALUE);</span>
-<span class="source-line-no">2392</span><span id="line-2392"> }</span>
-<span class="source-line-no">2393</span><span id="line-2393"> for (BlockCacheKey entry : result) {</span>
-<span class="source-line-no">2394</span><span id="line-2394"> LOG.debug("found block for file {} in the backing map. Acquiring read lock for offset {}",</span>
-<span class="source-line-no">2395</span><span id="line-2395"> fileName.getName(), entry.getOffset());</span>
-<span class="source-line-no">2396</span><span id="line-2396"> ReentrantReadWriteLock lock = offsetLock.getLock(entry.getOffset());</span>
-<span class="source-line-no">2397</span><span id="line-2397"> lock.readLock().lock();</span>
-<span class="source-line-no">2398</span><span id="line-2398"> locks.add(lock);</span>
-<span class="source-line-no">2399</span><span id="line-2399"> if (backingMap.containsKey(entry) && entry.getBlockType().isData()) {</span>
-<span class="source-line-no">2400</span><span id="line-2400"> count++;</span>
-<span class="source-line-no">2401</span><span id="line-2401"> }</span>
-<span class="source-line-no">2402</span><span id="line-2402"> }</span>
-<span class="source-line-no">2403</span><span id="line-2403"> // BucketCache would only have data blocks</span>
-<span class="source-line-no">2404</span><span id="line-2404"> if (dataBlockCount == count) {</span>
-<span class="source-line-no">2405</span><span id="line-2405"> LOG.debug("File {} has now been fully cached.", fileName);</span>
-<span class="source-line-no">2406</span><span id="line-2406"> fileCacheCompleted(fileName, size);</span>
-<span class="source-line-no">2407</span><span id="line-2407"> } else {</span>
-<span class="source-line-no">2408</span><span id="line-2408"> LOG.debug(</span>
-<span class="source-line-no">2409</span><span id="line-2409"> "Prefetch executor completed for {}, but only {} data blocks were cached. "</span>
-<span class="source-line-no">2410</span><span id="line-2410"> + "Total data blocks for file: {}. "</span>
-<span class="source-line-no">2411</span><span id="line-2411"> + "Checking for blocks pending cache in cache writer queue.",</span>
-<span class="source-line-no">2412</span><span id="line-2412"> fileName, count, dataBlockCount);</span>
-<span class="source-line-no">2413</span><span id="line-2413"> if (ramCache.hasBlocksForFile(fileName.getName())) {</span>
-<span class="source-line-no">2414</span><span id="line-2414"> for (ReentrantReadWriteLock lock : locks) {</span>
-<span class="source-line-no">2415</span><span id="line-2415"> lock.readLock().unlock();</span>
-<span class="source-line-no">2416</span><span id="line-2416"> }</span>
-<span class="source-line-no">2417</span><span id="line-2417"> locks.clear();</span>
-<span class="source-line-no">2418</span><span id="line-2418"> LOG.debug("There are still blocks pending caching for file {}. Will sleep 100ms "</span>
-<span class="source-line-no">2419</span><span id="line-2419"> + "and try the verification again.", fileName);</span>
-<span class="source-line-no">2420</span><span id="line-2420"> Thread.sleep(100);</span>
-<span class="source-line-no">2421</span><span id="line-2421"> notifyFileCachingCompleted(fileName, totalBlockCount, dataBlockCount, size);</span>
-<span class="source-line-no">2422</span><span id="line-2422"> } else {</span>
-<span class="source-line-no">2423</span><span id="line-2423"> LOG.info(</span>
-<span class="source-line-no">2424</span><span id="line-2424"> "The total block count was {}. We found only {} data blocks cached from "</span>
-<span class="source-line-no">2425</span><span id="line-2425"> + "a total of {} data blocks for file {}, "</span>
-<span class="source-line-no">2426</span><span id="line-2426"> + "but no blocks pending caching. Maybe cache is full or evictions "</span>
-<span class="source-line-no">2427</span><span id="line-2427"> + "happened concurrently to cache prefetch.",</span>
-<span class="source-line-no">2428</span><span id="line-2428"> totalBlockCount, count, dataBlockCount, fileName);</span>
-<span class="source-line-no">2429</span><span id="line-2429"> }</span>
-<span class="source-line-no">2430</span><span id="line-2430"> }</span>
-<span class="source-line-no">2431</span><span id="line-2431"> } catch (InterruptedException e) {</span>
-<span class="source-line-no">2432</span><span id="line-2432"> throw new RuntimeException(e);</span>
-<span class="source-line-no">2433</span><span id="line-2433"> } finally {</span>
-<span class="source-line-no">2434</span><span id="line-2434"> for (ReentrantReadWriteLock lock : locks) {</span>
-<span class="source-line-no">2435</span><span id="line-2435"> lock.readLock().unlock();</span>
-<span class="source-line-no">2436</span><span id="line-2436"> }</span>
-<span class="source-line-no">2437</span><span id="line-2437"> }</span>
-<span class="source-line-no">2438</span><span id="line-2438"> }</span>
-<span class="source-line-no">2439</span><span id="line-2439"></span>
-<span class="source-line-no">2440</span><span id="line-2440"> @Override</span>
-<span class="source-line-no">2441</span><span id="line-2441"> public Optional<Boolean> blockFitsIntoTheCache(HFileBlock block) {</span>
-<span class="source-line-no">2442</span><span id="line-2442"> if (!isCacheInitialized("blockFitsIntoTheCache")) {</span>
-<span class="source-line-no">2443</span><span id="line-2443"> return Optional.of(false);</span>
-<span class="source-line-no">2444</span><span id="line-2444"> }</span>
-<span class="source-line-no">2445</span><span id="line-2445"></span>
-<span class="source-line-no">2446</span><span id="line-2446"> long currentUsed = bucketAllocator.getUsedSize();</span>
-<span class="source-line-no">2447</span><span id="line-2447"> boolean result = (currentUsed + block.getOnDiskSizeWithHeader()) < acceptableSize();</span>
-<span class="source-line-no">2448</span><span id="line-2448"> return Optional.of(result);</span>
-<span class="source-line-no">2449</span><span id="line-2449"> }</span>
-<span class="source-line-no">2450</span><span id="line-2450"></span>
-<span class="source-line-no">2451</span><span id="line-2451"> @Override</span>
-<span class="source-line-no">2452</span><span id="line-2452"> public Optional<Boolean> shouldCacheFile(HFileInfo hFileInfo, Configuration conf) {</span>
-<span class="source-line-no">2453</span><span id="line-2453"> String fileName = hFileInfo.getHFileContext().getHFileName();</span>
-<span class="source-line-no">2454</span><span id="line-2454"> DataTieringManager dataTieringManager = DataTieringManager.getInstance();</span>
-<span class="source-line-no">2455</span><span id="line-2455"> if (dataTieringManager != null && !dataTieringManager.isHotData(hFileInfo, conf)) {</span>
-<span class="source-line-no">2456</span><span id="line-2456"> LOG.debug("Data tiering is enabled for file: '{}' and it is not hot data", fileName);</span>
+<span class="source-line-no">2355</span><span id="line-2355"> public boolean hasBlocksForFile(String fileName) {</span>
+<span class="source-line-no">2356</span><span id="line-2356"> return delegate.keySet().stream().filter(key -> key.getHfileName().equals(fileName))</span>
+<span class="source-line-no">2357</span><span id="line-2357"> .findFirst().isPresent();</span>
+<span class="source-line-no">2358</span><span id="line-2358"> }</span>
+<span class="source-line-no">2359</span><span id="line-2359"> }</span>
+<span class="source-line-no">2360</span><span id="line-2360"></span>
+<span class="source-line-no">2361</span><span id="line-2361"> public Map<BlockCacheKey, BucketEntry> getBackingMap() {</span>
+<span class="source-line-no">2362</span><span id="line-2362"> return backingMap;</span>
+<span class="source-line-no">2363</span><span id="line-2363"> }</span>
+<span class="source-line-no">2364</span><span id="line-2364"></span>
+<span class="source-line-no">2365</span><span id="line-2365"> public AtomicBoolean getBackingMapValidated() {</span>
+<span class="source-line-no">2366</span><span id="line-2366"> return backingMapValidated;</span>
+<span class="source-line-no">2367</span><span id="line-2367"> }</span>
+<span class="source-line-no">2368</span><span id="line-2368"></span>
+<span class="source-line-no">2369</span><span id="line-2369"> @Override</span>
+<span class="source-line-no">2370</span><span id="line-2370"> public Optional<Map<String, Pair<String, Long>>> getFullyCachedFiles() {</span>
+<span class="source-line-no">2371</span><span id="line-2371"> return Optional.of(fullyCachedFiles);</span>
+<span class="source-line-no">2372</span><span id="line-2372"> }</span>
+<span class="source-line-no">2373</span><span id="line-2373"></span>
+<span class="source-line-no">2374</span><span id="line-2374"> public static Optional<BucketCache> getBucketCacheFromCacheConfig(CacheConfig cacheConf) {</span>
+<span class="source-line-no">2375</span><span id="line-2375"> if (cacheConf.getBlockCache().isPresent()) {</span>
+<span class="source-line-no">2376</span><span id="line-2376"> BlockCache bc = cacheConf.getBlockCache().get();</span>
+<span class="source-line-no">2377</span><span id="line-2377"> if (bc instanceof CombinedBlockCache) {</span>
+<span class="source-line-no">2378</span><span id="line-2378"> BlockCache l2 = ((CombinedBlockCache) bc).getSecondLevelCache();</span>
+<span class="source-line-no">2379</span><span id="line-2379"> if (l2 instanceof BucketCache) {</span>
+<span class="source-line-no">2380</span><span id="line-2380"> return Optional.of((BucketCache) l2);</span>
+<span class="source-line-no">2381</span><span id="line-2381"> }</span>
+<span class="source-line-no">2382</span><span id="line-2382"> } else if (bc instanceof BucketCache) {</span>
+<span class="source-line-no">2383</span><span id="line-2383"> return Optional.of((BucketCache) bc);</span>
+<span class="source-line-no">2384</span><span id="line-2384"> }</span>
+<span class="source-line-no">2385</span><span id="line-2385"> }</span>
+<span class="source-line-no">2386</span><span id="line-2386"> return Optional.empty();</span>
+<span class="source-line-no">2387</span><span id="line-2387"> }</span>
+<span class="source-line-no">2388</span><span id="line-2388"></span>
+<span class="source-line-no">2389</span><span id="line-2389"> @Override</span>
+<span class="source-line-no">2390</span><span id="line-2390"> public void notifyFileCachingCompleted(Path fileName, int totalBlockCount, int dataBlockCount,</span>
+<span class="source-line-no">2391</span><span id="line-2391"> long size) {</span>
+<span class="source-line-no">2392</span><span id="line-2392"> // block eviction may be happening in the background as prefetch runs,</span>
+<span class="source-line-no">2393</span><span id="line-2393"> // so we need to count all blocks for this file in the backing map under</span>
+<span class="source-line-no">2394</span><span id="line-2394"> // a read lock for the block offset</span>
+<span class="source-line-no">2395</span><span id="line-2395"> final List<ReentrantReadWriteLock> locks = new ArrayList<>();</span>
+<span class="source-line-no">2396</span><span id="line-2396"> LOG.debug("Notifying caching completed for file {}, with total blocks {}, and data blocks {}",</span>
+<span class="source-line-no">2397</span><span id="line-2397"> fileName, totalBlockCount, dataBlockCount);</span>
+<span class="source-line-no">2398</span><span id="line-2398"> try {</span>
+<span class="source-line-no">2399</span><span id="line-2399"> int count = 0;</span>
+<span class="source-line-no">2400</span><span id="line-2400"> LOG.debug("iterating over {} entries in the backing map", backingMap.size());</span>
+<span class="source-line-no">2401</span><span id="line-2401"> Set<BlockCacheKey> result = getAllCacheKeysForFile(fileName.getName(), 0, Long.MAX_VALUE);</span>
+<span class="source-line-no">2402</span><span id="line-2402"> if (result.isEmpty() && StoreFileInfo.isReference(fileName)) {</span>
+<span class="source-line-no">2403</span><span id="line-2403"> result = getAllCacheKeysForFile(</span>
+<span class="source-line-no">2404</span><span id="line-2404"> StoreFileInfo.getReferredToRegionAndFile(fileName.getName()).getSecond(), 0,</span>
+<span class="source-line-no">2405</span><span id="line-2405"> Long.MAX_VALUE);</span>
+<span class="source-line-no">2406</span><span id="line-2406"> }</span>
+<span class="source-line-no">2407</span><span id="line-2407"> for (BlockCacheKey entry : result) {</span>
+<span class="source-line-no">2408</span><span id="line-2408"> LOG.debug("found block for file {} in the backing map. Acquiring read lock for offset {}",</span>
+<span class="source-line-no">2409</span><span id="line-2409"> fileName.getName(), entry.getOffset());</span>
+<span class="source-line-no">2410</span><span id="line-2410"> ReentrantReadWriteLock lock = offsetLock.getLock(entry.getOffset());</span>
+<span class="source-line-no">2411</span><span id="line-2411"> lock.readLock().lock();</span>
+<span class="source-line-no">2412</span><span id="line-2412"> locks.add(lock);</span>
+<span class="source-line-no">2413</span><span id="line-2413"> if (backingMap.containsKey(entry) && entry.getBlockType().isData()) {</span>
+<span class="source-line-no">2414</span><span id="line-2414"> count++;</span>
+<span class="source-line-no">2415</span><span id="line-2415"> }</span>
+<span class="source-line-no">2416</span><span id="line-2416"> }</span>
+<span class="source-line-no">2417</span><span id="line-2417"> // BucketCache would only have data blocks</span>
+<span class="source-line-no">2418</span><span id="line-2418"> if (dataBlockCount == count) {</span>
+<span class="source-line-no">2419</span><span id="line-2419"> LOG.debug("File {} has now been fully cached.", fileName);</span>
+<span class="source-line-no">2420</span><span id="line-2420"> fileCacheCompleted(fileName, size);</span>
+<span class="source-line-no">2421</span><span id="line-2421"> } else {</span>
+<span class="source-line-no">2422</span><span id="line-2422"> LOG.debug(</span>
+<span class="source-line-no">2423</span><span id="line-2423"> "Prefetch executor completed for {}, but only {} data blocks were cached. "</span>
+<span class="source-line-no">2424</span><span id="line-2424"> + "Total data blocks for file: {}. "</span>
+<span class="source-line-no">2425</span><span id="line-2425"> + "Checking for blocks pending cache in cache writer queue.",</span>
+<span class="source-line-no">2426</span><span id="line-2426"> fileName, count, dataBlockCount);</span>
+<span class="source-line-no">2427</span><span id="line-2427"> if (ramCache.hasBlocksForFile(fileName.getName())) {</span>
+<span class="source-line-no">2428</span><span id="line-2428"> for (ReentrantReadWriteLock lock : locks) {</span>
+<span class="source-line-no">2429</span><span id="line-2429"> lock.readLock().unlock();</span>
+<span class="source-line-no">2430</span><span id="line-2430"> }</span>
+<span class="source-line-no">2431</span><span id="line-2431"> locks.clear();</span>
+<span class="source-line-no">2432</span><span id="line-2432"> LOG.debug("There are still blocks pending caching for file {}. Will sleep 100ms "</span>
+<span class="source-line-no">2433</span><span id="line-2433"> + "and try the verification again.", fileName);</span>
+<span class="source-line-no">2434</span><span id="line-2434"> Thread.sleep(100);</span>
+<span class="source-line-no">2435</span><span id="line-2435"> notifyFileCachingCompleted(fileName, totalBlockCount, dataBlockCount, size);</span>
+<span class="source-line-no">2436</span><span id="line-2436"> } else {</span>
+<span class="source-line-no">2437</span><span id="line-2437"> LOG.info(</span>
+<span class="source-line-no">2438</span><span id="line-2438"> "The total block count was {}. We found only {} data blocks cached from "</span>
+<span class="source-line-no">2439</span><span id="line-2439"> + "a total of {} data blocks for file {}, "</span>
+<span class="source-line-no">2440</span><span id="line-2440"> + "but no blocks pending caching. Maybe cache is full or evictions "</span>
+<span class="source-line-no">2441</span><span id="line-2441"> + "happened concurrently to cache prefetch.",</span>
+<span class="source-line-no">2442</span><span id="line-2442"> totalBlockCount, count, dataBlockCount, fileName);</span>
+<span class="source-line-no">2443</span><span id="line-2443"> }</span>
+<span class="source-line-no">2444</span><span id="line-2444"> }</span>
+<span class="source-line-no">2445</span><span id="line-2445"> } catch (InterruptedException e) {</span>
+<span class="source-line-no">2446</span><span id="line-2446"> throw new RuntimeException(e);</span>
+<span class="source-line-no">2447</span><span id="line-2447"> } finally {</span>
+<span class="source-line-no">2448</span><span id="line-2448"> for (ReentrantReadWriteLock lock : locks) {</span>
+<span class="source-line-no">2449</span><span id="line-2449"> lock.readLock().unlock();</span>
+<span class="source-line-no">2450</span><span id="line-2450"> }</span>
+<span class="source-line-no">2451</span><span id="line-2451"> }</span>
+<span class="source-line-no">2452</span><span id="line-2452"> }</span>
+<span class="source-line-no">2453</span><span id="line-2453"></span>
+<span class="source-line-no">2454</span><span id="line-2454"> @Override</span>
+<span class="source-line-no">2455</span><span id="line-2455"> public Optional<Boolean> blockFitsIntoTheCache(HFileBlock block) {</span>
+<span class="source-line-no">2456</span><span id="line-2456"> if (!isCacheInitialized("blockFitsIntoTheCache")) {</span>
<span class="source-line-no">2457</span><span id="line-2457"> return Optional.of(false);</span>
<span class="source-line-no">2458</span><span id="line-2458"> }</span>
-<span class="source-line-no">2459</span><span id="line-2459"> // if we don't have the file in fullyCachedFiles, we should cache it</span>
-<span class="source-line-no">2460</span><span id="line-2460"> return Optional.of(!fullyCachedFiles.containsKey(fileName));</span>
-<span class="source-line-no">2461</span><span id="line-2461"> }</span>
-<span class="source-line-no">2462</span><span id="line-2462"></span>
-<span class="source-line-no">2463</span><span id="line-2463"> @Override</span>
-<span class="source-line-no">2464</span><span id="line-2464"> public Optional<Boolean> shouldCacheBlock(BlockCacheKey key, long maxTimestamp,</span>
-<span class="source-line-no">2465</span><span id="line-2465"> Configuration conf) {</span>
-<span class="source-line-no">2466</span><span id="line-2466"> DataTieringManager dataTieringManager = DataTieringManager.getInstance();</span>
-<span class="source-line-no">2467</span><span id="line-2467"> if (dataTieringManager != null && !dataTieringManager.isHotData(maxTimestamp, conf)) {</span>
-<span class="source-line-no">2468</span><span id="line-2468"> LOG.debug("Data tiering is enabled for file: '{}' and it is not hot data",</span>
-<span class="source-line-no">2469</span><span id="line-2469"> key.getHfileName());</span>
-<span class="source-line-no">2470</span><span id="line-2470"> return Optional.of(false);</span>
-<span class="source-line-no">2471</span><span id="line-2471"> }</span>
-<span class="source-line-no">2472</span><span id="line-2472"> return Optional.of(true);</span>
-<span class="source-line-no">2473</span><span id="line-2473"> }</span>
-<span class="source-line-no">2474</span><span id="line-2474"></span>
-<span class="source-line-no">2475</span><span id="line-2475"> @Override</span>
-<span class="source-line-no">2476</span><span id="line-2476"> public Optional<Boolean> isAlreadyCached(BlockCacheKey key) {</span>
-<span class="source-line-no">2477</span><span id="line-2477"> boolean foundKey = backingMap.containsKey(key);</span>
-<span class="source-line-no">2478</span><span id="line-2478"> // if there's no entry for the key itself, we need to check if this key is for a reference,</span>
-<span class="source-line-no">2479</span><span id="line-2479"> // and if so, look for a block from the referenced file using this getBlockForReference method.</span>
-<span class="source-line-no">2480</span><span id="line-2480"> return Optional.of(foundKey ? true : getBlockForReference(key) != null);</span>
-<span class="source-line-no">2481</span><span id="line-2481"> }</span>
-<span class="source-line-no">2482</span><span id="line-2482"></span>
-<span class="source-line-no">2483</span><span id="line-2483"> @Override</span>
-<span class="source-line-no">2484</span><span id="line-2484"> public Optional<Integer> getBlockSize(BlockCacheKey key) {</span>
-<span class="source-line-no">2485</span><span id="line-2485"> BucketEntry entry = backingMap.get(key);</span>
-<span class="source-line-no">2486</span><span id="line-2486"> if (entry == null) {</span>
-<span class="source-line-no">2487</span><span id="line-2487"> // the key might be for a reference tha we had found the block from the referenced file in</span>
-<span class="source-line-no">2488</span><span id="line-2488"> // the cache when we first tried to cache it.</span>
-<span class="source-line-no">2489</span><span id="line-2489"> entry = getBlockForReference(key);</span>
-<span class="source-line-no">2490</span><span id="line-2490"> return entry == null ? Optional.empty() : Optional.of(entry.getOnDiskSizeWithHeader());</span>
-<span class="source-line-no">2491</span><span id="line-2491"> } else {</span>
-<span class="source-line-no">2492</span><span id="line-2492"> return Optional.of(entry.getOnDiskSizeWithHeader());</span>
-<span class="source-line-no">2493</span><span id="line-2493"> }</span>
-<span class="source-line-no">2494</span><span id="line-2494"></span>
+<span class="source-line-no">2459</span><span id="line-2459"></span>
+<span class="source-line-no">2460</span><span id="line-2460"> long currentUsed = bucketAllocator.getUsedSize();</span>
+<span class="source-line-no">2461</span><span id="line-2461"> boolean result = (currentUsed + block.getOnDiskSizeWithHeader()) < acceptableSize();</span>
+<span class="source-line-no">2462</span><span id="line-2462"> return Optional.of(result);</span>
+<span class="source-line-no">2463</span><span id="line-2463"> }</span>
+<span class="source-line-no">2464</span><span id="line-2464"></span>
+<span class="source-line-no">2465</span><span id="line-2465"> @Override</span>
+<span class="source-line-no">2466</span><span id="line-2466"> public Optional<Boolean> shouldCacheFile(HFileInfo hFileInfo, Configuration conf) {</span>
+<span class="source-line-no">2467</span><span id="line-2467"> String fileName = hFileInfo.getHFileContext().getHFileName();</span>
+<span class="source-line-no">2468</span><span id="line-2468"> DataTieringManager dataTieringManager = DataTieringManager.getInstance();</span>
+<span class="source-line-no">2469</span><span id="line-2469"> if (dataTieringManager != null && !dataTieringManager.isHotData(hFileInfo, conf)) {</span>
+<span class="source-line-no">2470</span><span id="line-2470"> LOG.debug("Data tiering is enabled for file: '{}' and it is not hot data", fileName);</span>
+<span class="source-line-no">2471</span><span id="line-2471"> return Optional.of(false);</span>
+<span class="source-line-no">2472</span><span id="line-2472"> }</span>
+<span class="source-line-no">2473</span><span id="line-2473"> // if we don't have the file in fullyCachedFiles, we should cache it</span>
+<span class="source-line-no">2474</span><span id="line-2474"> return Optional.of(!fullyCachedFiles.containsKey(fileName));</span>
+<span class="source-line-no">2475</span><span id="line-2475"> }</span>
+<span class="source-line-no">2476</span><span id="line-2476"></span>
+<span class="source-line-no">2477</span><span id="line-2477"> @Override</span>
+<span class="source-line-no">2478</span><span id="line-2478"> public Optional<Boolean> shouldCacheBlock(BlockCacheKey key, long maxTimestamp,</span>
+<span class="source-line-no">2479</span><span id="line-2479"> Configuration conf) {</span>
+<span class="source-line-no">2480</span><span id="line-2480"> DataTieringManager dataTieringManager = DataTieringManager.getInstance();</span>
+<span class="source-line-no">2481</span><span id="line-2481"> if (dataTieringManager != null && !dataTieringManager.isHotData(maxTimestamp, conf)) {</span>
+<span class="source-line-no">2482</span><span id="line-2482"> LOG.debug("Data tiering is enabled for file: '{}' and it is not hot data",</span>
+<span class="source-line-no">2483</span><span id="line-2483"> key.getHfileName());</span>
+<span class="source-line-no">2484</span><span id="line-2484"> return Optional.of(false);</span>
+<span class="source-line-no">2485</span><span id="line-2485"> }</span>
+<span class="source-line-no">2486</span><span id="line-2486"> return Optional.of(true);</span>
+<span class="source-line-no">2487</span><span id="line-2487"> }</span>
+<span class="source-line-no">2488</span><span id="line-2488"></span>
+<span class="source-line-no">2489</span><span id="line-2489"> @Override</span>
+<span class="source-line-no">2490</span><span id="line-2490"> public Optional<Boolean> isAlreadyCached(BlockCacheKey key) {</span>
+<span class="source-line-no">2491</span><span id="line-2491"> boolean foundKey = backingMap.containsKey(key);</span>
+<span class="source-line-no">2492</span><span id="line-2492"> // if there's no entry for the key itself, we need to check if this key is for a reference,</span>
+<span class="source-line-no">2493</span><span id="line-2493"> // and if so, look for a block from the referenced file using this getBlockForReference method.</span>
+<span class="source-line-no">2494</span><span id="line-2494"> return Optional.of(foundKey ? true : getBlockForReference(key) != null);</span>
<span class="source-line-no">2495</span><span id="line-2495"> }</span>
<span class="source-line-no">2496</span><span id="line-2496"></span>
-<span class="source-line-no">2497</span><span id="line-2497"> boolean isCacheInitialized(String api) {</span>
-<span class="source-line-no">2498</span><span id="line-2498"> if (cacheState == CacheState.INITIALIZING) {</span>
-<span class="source-line-no">2499</span><span id="line-2499"> LOG.warn("Bucket initialisation pending at {}", api);</span>
-<span class="source-line-no">2500</span><span id="line-2500"> return false;</span>
-<span class="source-line-no">2501</span><span id="line-2501"> }</span>
-<span class="source-line-no">2502</span><span id="line-2502"> return true;</span>
-<span class="source-line-no">2503</span><span id="line-2503"> }</span>
-<span class="source-line-no">2504</span><span id="line-2504"></span>
-<span class="source-line-no">2505</span><span id="line-2505"> @Override</span>
-<span class="source-line-no">2506</span><span id="line-2506"> public boolean waitForCacheInitialization(long timeout) {</span>
-<span class="source-line-no">2507</span><span id="line-2507"> while (cacheState == CacheState.INITIALIZING) {</span>
-<span class="source-line-no">2508</span><span id="line-2508"> if (timeout <= 0) {</span>
-<span class="source-line-no">2509</span><span id="line-2509"> break;</span>
-<span class="source-line-no">2510</span><span id="line-2510"> }</span>
-<span class="source-line-no">2511</span><span id="line-2511"> try {</span>
-<span class="source-line-no">2512</span><span id="line-2512"> Thread.sleep(100);</span>
-<span class="source-line-no">2513</span><span id="line-2513"> } catch (InterruptedException e) {</span>
-<span class="source-line-no">2514</span><span id="line-2514"> LOG.warn("Interrupted while waiting for cache initialization", e);</span>
-<span class="source-line-no">2515</span><span id="line-2515"> Thread.currentThread().interrupt();</span>
-<span class="source-line-no">2516</span><span id="line-2516"> break;</span>
-<span class="source-line-no">2517</span><span id="line-2517"> }</span>
-<span class="source-line-no">2518</span><span id="line-2518"> timeout -= 100;</span>
-<span class="source-line-no">2519</span><span id="line-2519"> }</span>
-<span class="source-line-no">2520</span><span id="line-2520"> return isCacheEnabled();</span>
-<span class="source-line-no">2521</span><span id="line-2521"> }</span>
-<span class="source-line-no">2522</span><span id="line-2522">}</span>
+<span class="source-line-no">2497</span><span id="line-2497"> @Override</span>
+<span class="source-line-no">2498</span><span id="line-2498"> public Optional<Integer> getBlockSize(BlockCacheKey key) {</span>
+<span class="source-line-no">2499</span><span id="line-2499"> BucketEntry entry = backingMap.get(key);</span>
+<span class="source-line-no">2500</span><span id="line-2500"> if (entry == null) {</span>
+<span class="source-line-no">2501</span><span id="line-2501"> // the key might be for a reference tha we had found the block from the referenced file in</span>
+<span class="source-line-no">2502</span><span id="line-2502"> // the cache when we first tried to cache it.</span>
+<span class="source-line-no">2503</span><span id="line-2503"> entry = getBlockForReference(key);</span>
+<span class="source-line-no">2504</span><span id="line-2504"> return entry == null ? Optional.empty() : Optional.of(entry.getOnDiskSizeWithHeader());</span>
+<span class="source-line-no">2505</span><span id="line-2505"> } else {</span>
+<span class="source-line-no">2506</span><span id="line-2506"> return Optional.of(entry.getOnDiskSizeWithHeader());</span>
+<span class="source-line-no">2507</span><span id="line-2507"> }</span>
+<span class="source-line-no">2508</span><span id="line-2508"></span>
+<span class="source-line-no">2509</span><span id="line-2509"> }</span>
+<span class="source-line-no">2510</span><span id="line-2510"></span>
+<span class="source-line-no">2511</span><span id="line-2511"> boolean isCacheInitialized(String api) {</span>
+<span class="source-line-no">2512</span><span id="line-2512"> if (cacheState == CacheState.INITIALIZING) {</span>
+<span class="source-line-no">2513</span><span id="line-2513"> LOG.warn("Bucket initialisation pending at {}", api);</span>
+<span class="source-line-no">2514</span><span id="line-2514"> return false;</span>
+<span class="source-line-no">2515</span><span id="line-2515"> }</span>
+<span class="source-line-no">2516</span><span id="line-2516"> return true;</span>
+<span class="source-line-no">2517</span><span id="line-2517"> }</span>
+<span class="source-line-no">2518</span><span id="line-2518"></span>
+<span class="source-line-no">2519</span><span id="line-2519"> @Override</span>
+<span class="source-line-no">2520</span><span id="line-2520"> public boolean waitForCacheInitialization(long timeout) {</span>
+<span class="source-line-no">2521</span><span id="line-2521"> while (cacheState == CacheState.INITIALIZING) {</span>
+<span class="source-line-no">2522</span><span id="line-2522"> if (timeout <= 0) {</span>
+<span class="source-line-no">2523</span><span id="line-2523"> break;</span>
+<span class="source-line-no">2524</span><span id="line-2524"> }</span>
+<span class="source-line-no">2525</span><span id="line-2525"> try {</span>
+<span class="source-line-no">2526</span><span id="line-2526"> Thread.sleep(100);</span>
+<span class="source-line-no">2527</span><span id="line-2527"> } catch (InterruptedException e) {</span>
+<span class="source-line-no">2528</span><span id="line-2528"> LOG.warn("Interrupted while waiting for cache initialization", e);</span>
+<span class="source-line-no">2529</span><span id="line-2529"> Thread.currentThread().interrupt();</span>
+<span class="source-line-no">2530</span><span id="line-2530"> break;</span>
+<span class="source-line-no">2531</span><span id="line-2531"> }</span>
+<span class="source-line-no">2532</span><span id="line-2532"> timeout -= 100;</span>
+<span class="source-line-no">2533</span><span id="line-2533"> }</span>
+<span class="source-line-no">2534</span><span id="line-2534"> return isCacheEnabled();</span>
+<span class="source-line-no">2535</span><span id="line-2535"> }</span>
+<span class="source-line-no">2536</span><span id="line-2536">}</span>
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.StatisticsThread.html b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.StatisticsThread.html
index 668a412844f..d9bbc17910e 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.StatisticsThread.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.StatisticsThread.html
@@ -1624,915 +1624,929 @@
<span class="source-line-no">1611</span><span id="line-1611"> int pblen = ProtobufMagic.lengthOfPBMagic();</span>
<span class="source-line-no">1612</span><span id="line-1612"> byte[] pbuf = new byte[pblen];</span>
<span class="source-line-no">1613</span><span id="line-1613"> IOUtils.readFully(in, pbuf, 0, pblen);</span>
-<span class="source-line-no">1614</span><span id="line-1614"> if (ProtobufMagic.isPBMagicPrefix(pbuf)) {</span>
-<span class="source-line-no">1615</span><span id="line-1615"> LOG.info("Reading old format of persistence.");</span>
-<span class="source-line-no">1616</span><span id="line-1616"> // The old non-chunked version of backing map persistence.</span>
-<span class="source-line-no">1617</span><span id="line-1617"> parsePB(BucketCacheProtos.BucketCacheEntry.parseDelimitedFrom(in));</span>
-<span class="source-line-no">1618</span><span id="line-1618"> } else if (Arrays.equals(pbuf, BucketProtoUtils.PB_MAGIC_V2)) {</span>
-<span class="source-line-no">1619</span><span id="line-1619"> // The new persistence format of chunked persistence.</span>
-<span class="source-line-no">1620</span><span id="line-1620"> LOG.info("Reading new chunked format of persistence.");</span>
-<span class="source-line-no">1621</span><span id="line-1621"> retrieveChunkedBackingMap(in);</span>
-<span class="source-line-no">1622</span><span id="line-1622"> } else {</span>
-<span class="source-line-no">1623</span><span id="line-1623"> // In 3.0 we have enough flexibility to dump the old cache data.</span>
-<span class="source-line-no">1624</span><span id="line-1624"> // TODO: In 2.x line, this might need to be filled in to support reading the old format</span>
-<span class="source-line-no">1625</span><span id="line-1625"> throw new IOException(</span>
-<span class="source-line-no">1626</span><span id="line-1626"> "Persistence file does not start with protobuf magic number. " + persistencePath);</span>
-<span class="source-line-no">1627</span><span id="line-1627"> }</span>
-<span class="source-line-no">1628</span><span id="line-1628"> bucketAllocator = new BucketAllocator(cacheCapacity, bucketSizes, backingMap, realCacheSize);</span>
-<span class="source-line-no">1629</span><span id="line-1629"> blockNumber.add(backingMap.size());</span>
-<span class="source-line-no">1630</span><span id="line-1630"> LOG.info("Bucket cache retrieved from file successfully with size: {}", backingMap.size());</span>
-<span class="source-line-no">1631</span><span id="line-1631"> }</span>
-<span class="source-line-no">1632</span><span id="line-1632"> }</span>
-<span class="source-line-no">1633</span><span id="line-1633"></span>
-<span class="source-line-no">1634</span><span id="line-1634"> private void updateRegionSizeMapWhileRetrievingFromFile() {</span>
-<span class="source-line-no">1635</span><span id="line-1635"> // Update the regionCachedSize with the region size while restarting the region server</span>
-<span class="source-line-no">1636</span><span id="line-1636"> if (LOG.isDebugEnabled()) {</span>
-<span class="source-line-no">1637</span><span id="line-1637"> LOG.debug("Updating region size map after retrieving cached file list");</span>
-<span class="source-line-no">1638</span><span id="line-1638"> dumpPrefetchList();</span>
-<span class="source-line-no">1639</span><span id="line-1639"> }</span>
-<span class="source-line-no">1640</span><span id="line-1640"> regionCachedSize.clear();</span>
-<span class="source-line-no">1641</span><span id="line-1641"> fullyCachedFiles.forEach((hFileName, hFileSize) -> {</span>
-<span class="source-line-no">1642</span><span id="line-1642"> // Get the region name for each file</span>
-<span class="source-line-no">1643</span><span id="line-1643"> String regionEncodedName = hFileSize.getFirst();</span>
-<span class="source-line-no">1644</span><span id="line-1644"> long cachedFileSize = hFileSize.getSecond();</span>
-<span class="source-line-no">1645</span><span id="line-1645"> regionCachedSize.merge(regionEncodedName, cachedFileSize,</span>
-<span class="source-line-no">1646</span><span id="line-1646"> (oldpf, fileSize) -> oldpf + fileSize);</span>
-<span class="source-line-no">1647</span><span id="line-1647"> });</span>
-<span class="source-line-no">1648</span><span id="line-1648"> }</span>
-<span class="source-line-no">1649</span><span id="line-1649"></span>
-<span class="source-line-no">1650</span><span id="line-1650"> private void dumpPrefetchList() {</span>
-<span class="source-line-no">1651</span><span id="line-1651"> for (Map.Entry<String, Pair<String, Long>> outerEntry : fullyCachedFiles.entrySet()) {</span>
-<span class="source-line-no">1652</span><span id="line-1652"> LOG.debug("Cached File Entry:<{},<{},{}>>", outerEntry.getKey(),</span>
-<span class="source-line-no">1653</span><span id="line-1653"> outerEntry.getValue().getFirst(), outerEntry.getValue().getSecond());</span>
-<span class="source-line-no">1654</span><span id="line-1654"> }</span>
+<span class="source-line-no">1614</span><span id="line-1614"></span>
+<span class="source-line-no">1615</span><span id="line-1615"> if (ProtobufMagic.isPBMagicPrefix(pbuf)) {</span>
+<span class="source-line-no">1616</span><span id="line-1616"> LOG.info("Reading old format of persistence.");</span>
+<span class="source-line-no">1617</span><span id="line-1617"> // The old non-chunked version of backing map persistence.</span>
+<span class="source-line-no">1618</span><span id="line-1618"> BucketCacheProtos.BucketCacheEntry cacheEntry =</span>
+<span class="source-line-no">1619</span><span id="line-1619"> BucketCacheProtos.BucketCacheEntry.parseDelimitedFrom(in);</span>
+<span class="source-line-no">1620</span><span id="line-1620"> if (cacheEntry == null) {</span>
+<span class="source-line-no">1621</span><span id="line-1621"> throw new IOException(</span>
+<span class="source-line-no">1622</span><span id="line-1622"> "Failed to parse cache entry from persistence file: " + persistencePath);</span>
+<span class="source-line-no">1623</span><span id="line-1623"> }</span>
+<span class="source-line-no">1624</span><span id="line-1624"> parsePB(cacheEntry);</span>
+<span class="source-line-no">1625</span><span id="line-1625"> } else if (Arrays.equals(pbuf, BucketProtoUtils.PB_MAGIC_V2)) {</span>
+<span class="source-line-no">1626</span><span id="line-1626"> // The new persistence format of chunked persistence.</span>
+<span class="source-line-no">1627</span><span id="line-1627"> LOG.info("Reading new chunked format of persistence.");</span>
+<span class="source-line-no">1628</span><span id="line-1628"> retrieveChunkedBackingMap(in);</span>
+<span class="source-line-no">1629</span><span id="line-1629"> } else {</span>
+<span class="source-line-no">1630</span><span id="line-1630"> // In 3.0 we have enough flexibility to dump the old cache data.</span>
+<span class="source-line-no">1631</span><span id="line-1631"> // TODO: In 2.x line, this might need to be filled in to support reading the old format</span>
+<span class="source-line-no">1632</span><span id="line-1632"> throw new IOException(</span>
+<span class="source-line-no">1633</span><span id="line-1633"> "Persistence file does not start with protobuf magic number. " + persistencePath);</span>
+<span class="source-line-no">1634</span><span id="line-1634"> }</span>
+<span class="source-line-no">1635</span><span id="line-1635"> bucketAllocator = new BucketAllocator(cacheCapacity, bucketSizes, backingMap, realCacheSize);</span>
+<span class="source-line-no">1636</span><span id="line-1636"> blockNumber.add(backingMap.size());</span>
+<span class="source-line-no">1637</span><span id="line-1637"> LOG.info("Bucket cache retrieved from file successfully with size: {}", backingMap.size());</span>
+<span class="source-line-no">1638</span><span id="line-1638"> }</span>
+<span class="source-line-no">1639</span><span id="line-1639"> }</span>
+<span class="source-line-no">1640</span><span id="line-1640"></span>
+<span class="source-line-no">1641</span><span id="line-1641"> private void updateRegionSizeMapWhileRetrievingFromFile() {</span>
+<span class="source-line-no">1642</span><span id="line-1642"> // Update the regionCachedSize with the region size while restarting the region server</span>
+<span class="source-line-no">1643</span><span id="line-1643"> if (LOG.isDebugEnabled()) {</span>
+<span class="source-line-no">1644</span><span id="line-1644"> LOG.debug("Updating region size map after retrieving cached file list");</span>
+<span class="source-line-no">1645</span><span id="line-1645"> dumpPrefetchList();</span>
+<span class="source-line-no">1646</span><span id="line-1646"> }</span>
+<span class="source-line-no">1647</span><span id="line-1647"> regionCachedSize.clear();</span>
+<span class="source-line-no">1648</span><span id="line-1648"> fullyCachedFiles.forEach((hFileName, hFileSize) -> {</span>
+<span class="source-line-no">1649</span><span id="line-1649"> // Get the region name for each file</span>
+<span class="source-line-no">1650</span><span id="line-1650"> String regionEncodedName = hFileSize.getFirst();</span>
+<span class="source-line-no">1651</span><span id="line-1651"> long cachedFileSize = hFileSize.getSecond();</span>
+<span class="source-line-no">1652</span><span id="line-1652"> regionCachedSize.merge(regionEncodedName, cachedFileSize,</span>
+<span class="source-line-no">1653</span><span id="line-1653"> (oldpf, fileSize) -> oldpf + fileSize);</span>
+<span class="source-line-no">1654</span><span id="line-1654"> });</span>
<span class="source-line-no">1655</span><span id="line-1655"> }</span>
<span class="source-line-no">1656</span><span id="line-1656"></span>
-<span class="source-line-no">1657</span><span id="line-1657"> private void verifyCapacityAndClasses(long capacitySize, String ioclass, String mapclass)</span>
-<span class="source-line-no">1658</span><span id="line-1658"> throws IOException {</span>
-<span class="source-line-no">1659</span><span id="line-1659"> if (capacitySize != cacheCapacity) {</span>
-<span class="source-line-no">1660</span><span id="line-1660"> throw new IOException("Mismatched cache capacity:" + StringUtils.byteDesc(capacitySize)</span>
-<span class="source-line-no">1661</span><span id="line-1661"> + ", expected: " + StringUtils.byteDesc(cacheCapacity));</span>
-<span class="source-line-no">1662</span><span id="line-1662"> }</span>
-<span class="source-line-no">1663</span><span id="line-1663"> if (!ioEngine.getClass().getName().equals(ioclass)) {</span>
-<span class="source-line-no">1664</span><span id="line-1664"> throw new IOException("Class name for IO engine mismatch: " + ioclass + ", expected:"</span>
-<span class="source-line-no">1665</span><span id="line-1665"> + ioEngine.getClass().getName());</span>
-<span class="source-line-no">1666</span><span id="line-1666"> }</span>
-<span class="source-line-no">1667</span><span id="line-1667"> if (!backingMap.getClass().getName().equals(mapclass)) {</span>
-<span class="source-line-no">1668</span><span id="line-1668"> throw new IOException("Class name for cache map mismatch: " + mapclass + ", expected:"</span>
-<span class="source-line-no">1669</span><span id="line-1669"> + backingMap.getClass().getName());</span>
-<span class="source-line-no">1670</span><span id="line-1670"> }</span>
-<span class="source-line-no">1671</span><span id="line-1671"> }</span>
-<span class="source-line-no">1672</span><span id="line-1672"></span>
-<span class="source-line-no">1673</span><span id="line-1673"> private void verifyFileIntegrity(BucketCacheProtos.BucketCacheEntry proto) {</span>
-<span class="source-line-no">1674</span><span id="line-1674"> try {</span>
-<span class="source-line-no">1675</span><span id="line-1675"> if (proto.hasChecksum()) {</span>
-<span class="source-line-no">1676</span><span id="line-1676"> ((PersistentIOEngine) ioEngine).verifyFileIntegrity(proto.getChecksum().toByteArray(),</span>
-<span class="source-line-no">1677</span><span id="line-1677"> algorithm);</span>
-<span class="source-line-no">1678</span><span id="line-1678"> }</span>
-<span class="source-line-no">1679</span><span id="line-1679"> backingMapValidated.set(true);</span>
-<span class="source-line-no">1680</span><span id="line-1680"> } catch (IOException e) {</span>
-<span class="source-line-no">1681</span><span id="line-1681"> LOG.warn("Checksum for cache file failed. "</span>
-<span class="source-line-no">1682</span><span id="line-1682"> + "We need to validate each cache key in the backing map. "</span>
-<span class="source-line-no">1683</span><span id="line-1683"> + "This may take some time, so we'll do it in a background thread,");</span>
-<span class="source-line-no">1684</span><span id="line-1684"></span>
-<span class="source-line-no">1685</span><span id="line-1685"> Runnable cacheValidator = () -> {</span>
-<span class="source-line-no">1686</span><span id="line-1686"> while (bucketAllocator == null) {</span>
-<span class="source-line-no">1687</span><span id="line-1687"> try {</span>
-<span class="source-line-no">1688</span><span id="line-1688"> Thread.sleep(50);</span>
-<span class="source-line-no">1689</span><span id="line-1689"> } catch (InterruptedException ex) {</span>
-<span class="source-line-no">1690</span><span id="line-1690"> throw new RuntimeException(ex);</span>
-<span class="source-line-no">1691</span><span id="line-1691"> }</span>
-<span class="source-line-no">1692</span><span id="line-1692"> }</span>
-<span class="source-line-no">1693</span><span id="line-1693"> long startTime = EnvironmentEdgeManager.currentTime();</span>
-<span class="source-line-no">1694</span><span id="line-1694"> int totalKeysOriginally = backingMap.size();</span>
-<span class="source-line-no">1695</span><span id="line-1695"> for (Map.Entry<BlockCacheKey, BucketEntry> keyEntry : backingMap.entrySet()) {</span>
-<span class="source-line-no">1696</span><span id="line-1696"> try {</span>
-<span class="source-line-no">1697</span><span id="line-1697"> ((FileIOEngine) ioEngine).checkCacheTime(keyEntry.getValue());</span>
-<span class="source-line-no">1698</span><span id="line-1698"> } catch (IOException e1) {</span>
-<span class="source-line-no">1699</span><span id="line-1699"> LOG.debug("Check for key {} failed. Evicting.", keyEntry.getKey());</span>
-<span class="source-line-no">1700</span><span id="line-1700"> evictBlock(keyEntry.getKey());</span>
-<span class="source-line-no">1701</span><span id="line-1701"> fileNotFullyCached(keyEntry.getKey(), keyEntry.getValue());</span>
-<span class="source-line-no">1702</span><span id="line-1702"> }</span>
-<span class="source-line-no">1703</span><span id="line-1703"> }</span>
-<span class="source-line-no">1704</span><span id="line-1704"> backingMapValidated.set(true);</span>
-<span class="source-line-no">1705</span><span id="line-1705"> LOG.info("Finished validating {} keys in the backing map. Recovered: {}. This took {}ms.",</span>
-<span class="source-line-no">1706</span><span id="line-1706"> totalKeysOriginally, backingMap.size(),</span>
-<span class="source-line-no">1707</span><span id="line-1707"> (EnvironmentEdgeManager.currentTime() - startTime));</span>
-<span class="source-line-no">1708</span><span id="line-1708"> };</span>
-<span class="source-line-no">1709</span><span id="line-1709"> Thread t = new Thread(cacheValidator);</span>
-<span class="source-line-no">1710</span><span id="line-1710"> t.setDaemon(true);</span>
-<span class="source-line-no">1711</span><span id="line-1711"> t.start();</span>
-<span class="source-line-no">1712</span><span id="line-1712"> }</span>
-<span class="source-line-no">1713</span><span id="line-1713"> }</span>
-<span class="source-line-no">1714</span><span id="line-1714"></span>
-<span class="source-line-no">1715</span><span id="line-1715"> private void updateCacheIndex(BucketCacheProtos.BackingMap chunk,</span>
-<span class="source-line-no">1716</span><span id="line-1716"> java.util.Map<java.lang.Integer, java.lang.String> deserializer) throws IOException {</span>
-<span class="source-line-no">1717</span><span id="line-1717"> Pair<ConcurrentHashMap<BlockCacheKey, BucketEntry>, NavigableSet<BlockCacheKey>> pair2 =</span>
-<span class="source-line-no">1718</span><span id="line-1718"> BucketProtoUtils.fromPB(deserializer, chunk, this::createRecycler);</span>
-<span class="source-line-no">1719</span><span id="line-1719"> backingMap.putAll(pair2.getFirst());</span>
-<span class="source-line-no">1720</span><span id="line-1720"> blocksByHFile.addAll(pair2.getSecond());</span>
-<span class="source-line-no">1721</span><span id="line-1721"> }</span>
-<span class="source-line-no">1722</span><span id="line-1722"></span>
-<span class="source-line-no">1723</span><span id="line-1723"> private void parsePB(BucketCacheProtos.BucketCacheEntry proto) throws IOException {</span>
-<span class="source-line-no">1724</span><span id="line-1724"> Pair<ConcurrentHashMap<BlockCacheKey, BucketEntry>, NavigableSet<BlockCacheKey>> pair =</span>
-<span class="source-line-no">1725</span><span id="line-1725"> BucketProtoUtils.fromPB(proto.getDeserializersMap(), proto.getBackingMap(),</span>
-<span class="source-line-no">1726</span><span id="line-1726"> this::createRecycler);</span>
-<span class="source-line-no">1727</span><span id="line-1727"> backingMap = pair.getFirst();</span>
-<span class="source-line-no">1728</span><span id="line-1728"> blocksByHFile = pair.getSecond();</span>
-<span class="source-line-no">1729</span><span id="line-1729"> fullyCachedFiles.clear();</span>
-<span class="source-line-no">1730</span><span id="line-1730"> fullyCachedFiles.putAll(BucketProtoUtils.fromPB(proto.getCachedFilesMap()));</span>
-<span class="source-line-no">1731</span><span id="line-1731"></span>
-<span class="source-line-no">1732</span><span id="line-1732"> LOG.info("After retrieval Backing map size: {}, fullyCachedFiles size: {}", backingMap.size(),</span>
-<span class="source-line-no">1733</span><span id="line-1733"> fullyCachedFiles.size());</span>
-<span class="source-line-no">1734</span><span id="line-1734"></span>
-<span class="source-line-no">1735</span><span id="line-1735"> verifyFileIntegrity(proto);</span>
-<span class="source-line-no">1736</span><span id="line-1736"> updateRegionSizeMapWhileRetrievingFromFile();</span>
-<span class="source-line-no">1737</span><span id="line-1737"> verifyCapacityAndClasses(proto.getCacheCapacity(), proto.getIoClass(), proto.getMapClass());</span>
-<span class="source-line-no">1738</span><span id="line-1738"> }</span>
-<span class="source-line-no">1739</span><span id="line-1739"></span>
-<span class="source-line-no">1740</span><span id="line-1740"> private void persistChunkedBackingMap(FileOutputStream fos) throws IOException {</span>
-<span class="source-line-no">1741</span><span id="line-1741"> LOG.debug(</span>
-<span class="source-line-no">1742</span><span id="line-1742"> "persistToFile: before persisting backing map size: {}, "</span>
-<span class="source-line-no">1743</span><span id="line-1743"> + "fullycachedFiles size: {}, chunkSize: {}",</span>
-<span class="source-line-no">1744</span><span id="line-1744"> backingMap.size(), fullyCachedFiles.size(), persistenceChunkSize);</span>
-<span class="source-line-no">1745</span><span id="line-1745"></span>
-<span class="source-line-no">1746</span><span id="line-1746"> BucketProtoUtils.serializeAsPB(this, fos, persistenceChunkSize);</span>
-<span class="source-line-no">1747</span><span id="line-1747"></span>
+<span class="source-line-no">1657</span><span id="line-1657"> private void dumpPrefetchList() {</span>
+<span class="source-line-no">1658</span><span id="line-1658"> for (Map.Entry<String, Pair<String, Long>> outerEntry : fullyCachedFiles.entrySet()) {</span>
+<span class="source-line-no">1659</span><span id="line-1659"> LOG.debug("Cached File Entry:<{},<{},{}>>", outerEntry.getKey(),</span>
+<span class="source-line-no">1660</span><span id="line-1660"> outerEntry.getValue().getFirst(), outerEntry.getValue().getSecond());</span>
+<span class="source-line-no">1661</span><span id="line-1661"> }</span>
+<span class="source-line-no">1662</span><span id="line-1662"> }</span>
+<span class="source-line-no">1663</span><span id="line-1663"></span>
+<span class="source-line-no">1664</span><span id="line-1664"> private void verifyCapacityAndClasses(long capacitySize, String ioclass, String mapclass)</span>
+<span class="source-line-no">1665</span><span id="line-1665"> throws IOException {</span>
+<span class="source-line-no">1666</span><span id="line-1666"> if (capacitySize != cacheCapacity) {</span>
+<span class="source-line-no">1667</span><span id="line-1667"> throw new IOException("Mismatched cache capacity:" + StringUtils.byteDesc(capacitySize)</span>
+<span class="source-line-no">1668</span><span id="line-1668"> + ", expected: " + StringUtils.byteDesc(cacheCapacity));</span>
+<span class="source-line-no">1669</span><span id="line-1669"> }</span>
+<span class="source-line-no">1670</span><span id="line-1670"> if (!ioEngine.getClass().getName().equals(ioclass)) {</span>
+<span class="source-line-no">1671</span><span id="line-1671"> throw new IOException("Class name for IO engine mismatch: " + ioclass + ", expected:"</span>
+<span class="source-line-no">1672</span><span id="line-1672"> + ioEngine.getClass().getName());</span>
+<span class="source-line-no">1673</span><span id="line-1673"> }</span>
+<span class="source-line-no">1674</span><span id="line-1674"> if (!backingMap.getClass().getName().equals(mapclass)) {</span>
+<span class="source-line-no">1675</span><span id="line-1675"> throw new IOException("Class name for cache map mismatch: " + mapclass + ", expected:"</span>
+<span class="source-line-no">1676</span><span id="line-1676"> + backingMap.getClass().getName());</span>
+<span class="source-line-no">1677</span><span id="line-1677"> }</span>
+<span class="source-line-no">1678</span><span id="line-1678"> }</span>
+<span class="source-line-no">1679</span><span id="line-1679"></span>
+<span class="source-line-no">1680</span><span id="line-1680"> private void verifyFileIntegrity(BucketCacheProtos.BucketCacheEntry proto) {</span>
+<span class="source-line-no">1681</span><span id="line-1681"> try {</span>
+<span class="source-line-no">1682</span><span id="line-1682"> if (proto.hasChecksum()) {</span>
+<span class="source-line-no">1683</span><span id="line-1683"> ((PersistentIOEngine) ioEngine).verifyFileIntegrity(proto.getChecksum().toByteArray(),</span>
+<span class="source-line-no">1684</span><span id="line-1684"> algorithm);</span>
+<span class="source-line-no">1685</span><span id="line-1685"> }</span>
+<span class="source-line-no">1686</span><span id="line-1686"> backingMapValidated.set(true);</span>
+<span class="source-line-no">1687</span><span id="line-1687"> } catch (IOException e) {</span>
+<span class="source-line-no">1688</span><span id="line-1688"> LOG.warn("Checksum for cache file failed. "</span>
+<span class="source-line-no">1689</span><span id="line-1689"> + "We need to validate each cache key in the backing map. "</span>
+<span class="source-line-no">1690</span><span id="line-1690"> + "This may take some time, so we'll do it in a background thread,");</span>
+<span class="source-line-no">1691</span><span id="line-1691"></span>
+<span class="source-line-no">1692</span><span id="line-1692"> Runnable cacheValidator = () -> {</span>
+<span class="source-line-no">1693</span><span id="line-1693"> while (bucketAllocator == null) {</span>
+<span class="source-line-no">1694</span><span id="line-1694"> try {</span>
+<span class="source-line-no">1695</span><span id="line-1695"> Thread.sleep(50);</span>
+<span class="source-line-no">1696</span><span id="line-1696"> } catch (InterruptedException ex) {</span>
+<span class="source-line-no">1697</span><span id="line-1697"> throw new RuntimeException(ex);</span>
+<span class="source-line-no">1698</span><span id="line-1698"> }</span>
+<span class="source-line-no">1699</span><span id="line-1699"> }</span>
+<span class="source-line-no">1700</span><span id="line-1700"> long startTime = EnvironmentEdgeManager.currentTime();</span>
+<span class="source-line-no">1701</span><span id="line-1701"> int totalKeysOriginally = backingMap.size();</span>
+<span class="source-line-no">1702</span><span id="line-1702"> for (Map.Entry<BlockCacheKey, BucketEntry> keyEntry : backingMap.entrySet()) {</span>
+<span class="source-line-no">1703</span><span id="line-1703"> try {</span>
+<span class="source-line-no">1704</span><span id="line-1704"> ((FileIOEngine) ioEngine).checkCacheTime(keyEntry.getValue());</span>
+<span class="source-line-no">1705</span><span id="line-1705"> } catch (IOException e1) {</span>
+<span class="source-line-no">1706</span><span id="line-1706"> LOG.debug("Check for key {} failed. Evicting.", keyEntry.getKey());</span>
+<span class="source-line-no">1707</span><span id="line-1707"> evictBlock(keyEntry.getKey());</span>
+<span class="source-line-no">1708</span><span id="line-1708"> fileNotFullyCached(keyEntry.getKey(), keyEntry.getValue());</span>
+<span class="source-line-no">1709</span><span id="line-1709"> }</span>
+<span class="source-line-no">1710</span><span id="line-1710"> }</span>
+<span class="source-line-no">1711</span><span id="line-1711"> backingMapValidated.set(true);</span>
+<span class="source-line-no">1712</span><span id="line-1712"> LOG.info("Finished validating {} keys in the backing map. Recovered: {}. This took {}ms.",</span>
+<span class="source-line-no">1713</span><span id="line-1713"> totalKeysOriginally, backingMap.size(),</span>
+<span class="source-line-no">1714</span><span id="line-1714"> (EnvironmentEdgeManager.currentTime() - startTime));</span>
+<span class="source-line-no">1715</span><span id="line-1715"> };</span>
+<span class="source-line-no">1716</span><span id="line-1716"> Thread t = new Thread(cacheValidator);</span>
+<span class="source-line-no">1717</span><span id="line-1717"> t.setDaemon(true);</span>
+<span class="source-line-no">1718</span><span id="line-1718"> t.start();</span>
+<span class="source-line-no">1719</span><span id="line-1719"> }</span>
+<span class="source-line-no">1720</span><span id="line-1720"> }</span>
+<span class="source-line-no">1721</span><span id="line-1721"></span>
+<span class="source-line-no">1722</span><span id="line-1722"> private void updateCacheIndex(BucketCacheProtos.BackingMap chunk,</span>
+<span class="source-line-no">1723</span><span id="line-1723"> java.util.Map<java.lang.Integer, java.lang.String> deserializer) throws IOException {</span>
+<span class="source-line-no">1724</span><span id="line-1724"> Pair<ConcurrentHashMap<BlockCacheKey, BucketEntry>, NavigableSet<BlockCacheKey>> pair2 =</span>
+<span class="source-line-no">1725</span><span id="line-1725"> BucketProtoUtils.fromPB(deserializer, chunk, this::createRecycler);</span>
+<span class="source-line-no">1726</span><span id="line-1726"> backingMap.putAll(pair2.getFirst());</span>
+<span class="source-line-no">1727</span><span id="line-1727"> blocksByHFile.addAll(pair2.getSecond());</span>
+<span class="source-line-no">1728</span><span id="line-1728"> }</span>
+<span class="source-line-no">1729</span><span id="line-1729"></span>
+<span class="source-line-no">1730</span><span id="line-1730"> private void parsePB(BucketCacheProtos.BucketCacheEntry proto) throws IOException {</span>
+<span class="source-line-no">1731</span><span id="line-1731"> Pair<ConcurrentHashMap<BlockCacheKey, BucketEntry>, NavigableSet<BlockCacheKey>> pair =</span>
+<span class="source-line-no">1732</span><span id="line-1732"> BucketProtoUtils.fromPB(proto.getDeserializersMap(), proto.getBackingMap(),</span>
+<span class="source-line-no">1733</span><span id="line-1733"> this::createRecycler);</span>
+<span class="source-line-no">1734</span><span id="line-1734"> backingMap = pair.getFirst();</span>
+<span class="source-line-no">1735</span><span id="line-1735"> blocksByHFile = pair.getSecond();</span>
+<span class="source-line-no">1736</span><span id="line-1736"> fullyCachedFiles.clear();</span>
+<span class="source-line-no">1737</span><span id="line-1737"> fullyCachedFiles.putAll(BucketProtoUtils.fromPB(proto.getCachedFilesMap()));</span>
+<span class="source-line-no">1738</span><span id="line-1738"></span>
+<span class="source-line-no">1739</span><span id="line-1739"> LOG.info("After retrieval Backing map size: {}, fullyCachedFiles size: {}", backingMap.size(),</span>
+<span class="source-line-no">1740</span><span id="line-1740"> fullyCachedFiles.size());</span>
+<span class="source-line-no">1741</span><span id="line-1741"></span>
+<span class="source-line-no">1742</span><span id="line-1742"> verifyFileIntegrity(proto);</span>
+<span class="source-line-no">1743</span><span id="line-1743"> updateRegionSizeMapWhileRetrievingFromFile();</span>
+<span class="source-line-no">1744</span><span id="line-1744"> verifyCapacityAndClasses(proto.getCacheCapacity(), proto.getIoClass(), proto.getMapClass());</span>
+<span class="source-line-no">1745</span><span id="line-1745"> }</span>
+<span class="source-line-no">1746</span><span id="line-1746"></span>
+<span class="source-line-no">1747</span><span id="line-1747"> private void persistChunkedBackingMap(FileOutputStream fos) throws IOException {</span>
<span class="source-line-no">1748</span><span id="line-1748"> LOG.debug(</span>
-<span class="source-line-no">1749</span><span id="line-1749"> "persistToFile: after persisting backing map size: {}, " + "fullycachedFiles size: {}",</span>
-<span class="source-line-no">1750</span><span id="line-1750"> backingMap.size(), fullyCachedFiles.size());</span>
-<span class="source-line-no">1751</span><span id="line-1751"> }</span>
+<span class="source-line-no">1749</span><span id="line-1749"> "persistToFile: before persisting backing map size: {}, "</span>
+<span class="source-line-no">1750</span><span id="line-1750"> + "fullycachedFiles size: {}, chunkSize: {}",</span>
+<span class="source-line-no">1751</span><span id="line-1751"> backingMap.size(), fullyCachedFiles.size(), persistenceChunkSize);</span>
<span class="source-line-no">1752</span><span id="line-1752"></span>
-<span class="source-line-no">1753</span><span id="line-1753"> private void retrieveChunkedBackingMap(FileInputStream in) throws IOException {</span>
-<span class="source-line-no">1754</span><span id="line-1754"> // Read the first chunk that has all the details.</span>
-<span class="source-line-no">1755</span><span id="line-1755"> BucketCacheProtos.BucketCacheEntry cacheEntry =</span>
-<span class="source-line-no">1756</span><span id="line-1756"> BucketCacheProtos.BucketCacheEntry.parseDelimitedFrom(in);</span>
-<span class="source-line-no">1757</span><span id="line-1757"></span>
-<span class="source-line-no">1758</span><span id="line-1758"> fullyCachedFiles.clear();</span>
-<span class="source-line-no">1759</span><span id="line-1759"> fullyCachedFiles.putAll(BucketProtoUtils.fromPB(cacheEntry.getCachedFilesMap()));</span>
-<span class="source-line-no">1760</span><span id="line-1760"></span>
-<span class="source-line-no">1761</span><span id="line-1761"> backingMap.clear();</span>
-<span class="source-line-no">1762</span><span id="line-1762"> blocksByHFile.clear();</span>
-<span class="source-line-no">1763</span><span id="line-1763"></span>
-<span class="source-line-no">1764</span><span id="line-1764"> // Read the backing map entries in batches.</span>
-<span class="source-line-no">1765</span><span id="line-1765"> int numChunks = 0;</span>
-<span class="source-line-no">1766</span><span id="line-1766"> while (in.available() > 0) {</span>
-<span class="source-line-no">1767</span><span id="line-1767"> updateCacheIndex(BucketCacheProtos.BackingMap.parseDelimitedFrom(in),</span>
-<span class="source-line-no">1768</span><span id="line-1768"> cacheEntry.getDeserializersMap());</span>
-<span class="source-line-no">1769</span><span id="line-1769"> numChunks++;</span>
+<span class="source-line-no">1753</span><span id="line-1753"> BucketProtoUtils.serializeAsPB(this, fos, persistenceChunkSize);</span>
+<span class="source-line-no">1754</span><span id="line-1754"></span>
+<span class="source-line-no">1755</span><span id="line-1755"> LOG.debug(</span>
+<span class="source-line-no">1756</span><span id="line-1756"> "persistToFile: after persisting backing map size: {}, " + "fullycachedFiles size: {}",</span>
+<span class="source-line-no">1757</span><span id="line-1757"> backingMap.size(), fullyCachedFiles.size());</span>
+<span class="source-line-no">1758</span><span id="line-1758"> }</span>
+<span class="source-line-no">1759</span><span id="line-1759"></span>
+<span class="source-line-no">1760</span><span id="line-1760"> private void retrieveChunkedBackingMap(FileInputStream in) throws IOException {</span>
+<span class="source-line-no">1761</span><span id="line-1761"> // Read the first chunk that has all the details.</span>
+<span class="source-line-no">1762</span><span id="line-1762"> BucketCacheProtos.BucketCacheEntry cacheEntry =</span>
+<span class="source-line-no">1763</span><span id="line-1763"> BucketCacheProtos.BucketCacheEntry.parseDelimitedFrom(in);</span>
+<span class="source-line-no">1764</span><span id="line-1764"></span>
+<span class="source-line-no">1765</span><span id="line-1765"> // HBASE-29857: Handle case where persistence file is empty.</span>
+<span class="source-line-no">1766</span><span id="line-1766"> // parseDelimitedFrom() returns null when there's no data to read.</span>
+<span class="source-line-no">1767</span><span id="line-1767"> // Note: Corrupted files would throw InvalidProtocolBufferException (subclass of IOException).</span>
+<span class="source-line-no">1768</span><span id="line-1768"> if (cacheEntry == null) {</span>
+<span class="source-line-no">1769</span><span id="line-1769"> throw new IOException("Failed to read cache entry from persistence file (file is empty)");</span>
<span class="source-line-no">1770</span><span id="line-1770"> }</span>
<span class="source-line-no">1771</span><span id="line-1771"></span>
-<span class="source-line-no">1772</span><span id="line-1772"> LOG.info("Retrieved {} of chunks with blockCount = {}.", numChunks, backingMap.size());</span>
-<span class="source-line-no">1773</span><span id="line-1773"> verifyFileIntegrity(cacheEntry);</span>
-<span class="source-line-no">1774</span><span id="line-1774"> verifyCapacityAndClasses(cacheEntry.getCacheCapacity(), cacheEntry.getIoClass(),</span>
-<span class="source-line-no">1775</span><span id="line-1775"> cacheEntry.getMapClass());</span>
-<span class="source-line-no">1776</span><span id="line-1776"> updateRegionSizeMapWhileRetrievingFromFile();</span>
-<span class="source-line-no">1777</span><span id="line-1777"> }</span>
-<span class="source-line-no">1778</span><span id="line-1778"></span>
-<span class="source-line-no">1779</span><span id="line-1779"> /**</span>
-<span class="source-line-no">1780</span><span id="line-1780"> * Check whether we tolerate IO error this time. If the duration of IOEngine throwing errors</span>
-<span class="source-line-no">1781</span><span id="line-1781"> * exceeds ioErrorsDurationTimeTolerated, we will disable the cache</span>
-<span class="source-line-no">1782</span><span id="line-1782"> */</span>
-<span class="source-line-no">1783</span><span id="line-1783"> private void checkIOErrorIsTolerated() {</span>
-<span class="source-line-no">1784</span><span id="line-1784"> long now = EnvironmentEdgeManager.currentTime();</span>
-<span class="source-line-no">1785</span><span id="line-1785"> // Do a single read to a local variable to avoid timing issue - HBASE-24454</span>
-<span class="source-line-no">1786</span><span id="line-1786"> long ioErrorStartTimeTmp = this.ioErrorStartTime;</span>
-<span class="source-line-no">1787</span><span id="line-1787"> if (ioErrorStartTimeTmp > 0) {</span>
-<span class="source-line-no">1788</span><span id="line-1788"> if (isCacheEnabled() && (now - ioErrorStartTimeTmp) > this.ioErrorsTolerationDuration) {</span>
-<span class="source-line-no">1789</span><span id="line-1789"> LOG.error("IO errors duration time has exceeded " + ioErrorsTolerationDuration</span>
-<span class="source-line-no">1790</span><span id="line-1790"> + "ms, disabling cache, please check your IOEngine");</span>
-<span class="source-line-no">1791</span><span id="line-1791"> disableCache();</span>
-<span class="source-line-no">1792</span><span id="line-1792"> }</span>
-<span class="source-line-no">1793</span><span id="line-1793"> } else {</span>
-<span class="source-line-no">1794</span><span id="line-1794"> this.ioErrorStartTime = now;</span>
-<span class="source-line-no">1795</span><span id="line-1795"> }</span>
-<span class="source-line-no">1796</span><span id="line-1796"> }</span>
-<span class="source-line-no">1797</span><span id="line-1797"></span>
-<span class="source-line-no">1798</span><span id="line-1798"> /**</span>
-<span class="source-line-no">1799</span><span id="line-1799"> * Used to shut down the cache -or- turn it off in the case of something broken.</span>
-<span class="source-line-no">1800</span><span id="line-1800"> */</span>
-<span class="source-line-no">1801</span><span id="line-1801"> private void disableCache() {</span>
-<span class="source-line-no">1802</span><span id="line-1802"> if (!isCacheEnabled()) {</span>
-<span class="source-line-no">1803</span><span id="line-1803"> return;</span>
-<span class="source-line-no">1804</span><span id="line-1804"> }</span>
-<span class="source-line-no">1805</span><span id="line-1805"> LOG.info("Disabling cache");</span>
-<span class="source-line-no">1806</span><span id="line-1806"> cacheState = CacheState.DISABLED;</span>
-<span class="source-line-no">1807</span><span id="line-1807"> ioEngine.shutdown();</span>
-<span class="source-line-no">1808</span><span id="line-1808"> this.scheduleThreadPool.shutdown();</span>
-<span class="source-line-no">1809</span><span id="line-1809"> for (int i = 0; i < writerThreads.length; ++i)</span>
-<span class="source-line-no">1810</span><span id="line-1810"> writerThreads[i].interrupt();</span>
-<span class="source-line-no">1811</span><span id="line-1811"> this.ramCache.clear();</span>
-<span class="source-line-no">1812</span><span id="line-1812"> if (!ioEngine.isPersistent() || persistencePath == null) {</span>
-<span class="source-line-no">1813</span><span id="line-1813"> // If persistent ioengine and a path, we will serialize out the backingMap.</span>
-<span class="source-line-no">1814</span><span id="line-1814"> this.backingMap.clear();</span>
-<span class="source-line-no">1815</span><span id="line-1815"> this.blocksByHFile.clear();</span>
-<span class="source-line-no">1816</span><span id="line-1816"> this.fullyCachedFiles.clear();</span>
-<span class="source-line-no">1817</span><span id="line-1817"> this.regionCachedSize.clear();</span>
+<span class="source-line-no">1772</span><span id="line-1772"> fullyCachedFiles.clear();</span>
+<span class="source-line-no">1773</span><span id="line-1773"> fullyCachedFiles.putAll(BucketProtoUtils.fromPB(cacheEntry.getCachedFilesMap()));</span>
+<span class="source-line-no">1774</span><span id="line-1774"></span>
+<span class="source-line-no">1775</span><span id="line-1775"> backingMap.clear();</span>
+<span class="source-line-no">1776</span><span id="line-1776"> blocksByHFile.clear();</span>
+<span class="source-line-no">1777</span><span id="line-1777"></span>
+<span class="source-line-no">1778</span><span id="line-1778"> // Read the backing map entries in batches.</span>
+<span class="source-line-no">1779</span><span id="line-1779"> int numChunks = 0;</span>
+<span class="source-line-no">1780</span><span id="line-1780"> while (in.available() > 0) {</span>
+<span class="source-line-no">1781</span><span id="line-1781"> updateCacheIndex(BucketCacheProtos.BackingMap.parseDelimitedFrom(in),</span>
+<span class="source-line-no">1782</span><span id="line-1782"> cacheEntry.getDeserializersMap());</span>
+<span class="source-line-no">1783</span><span id="line-1783"> numChunks++;</span>
+<span class="source-line-no">1784</span><span id="line-1784"> }</span>
+<span class="source-line-no">1785</span><span id="line-1785"></span>
+<span class="source-line-no">1786</span><span id="line-1786"> LOG.info("Retrieved {} of chunks with blockCount = {}.", numChunks, backingMap.size());</span>
+<span class="source-line-no">1787</span><span id="line-1787"> verifyFileIntegrity(cacheEntry);</span>
+<span class="source-line-no">1788</span><span id="line-1788"> verifyCapacityAndClasses(cacheEntry.getCacheCapacity(), cacheEntry.getIoClass(),</span>
+<span class="source-line-no">1789</span><span id="line-1789"> cacheEntry.getMapClass());</span>
+<span class="source-line-no">1790</span><span id="line-1790"> updateRegionSizeMapWhileRetrievingFromFile();</span>
+<span class="source-line-no">1791</span><span id="line-1791"> }</span>
+<span class="source-line-no">1792</span><span id="line-1792"></span>
+<span class="source-line-no">1793</span><span id="line-1793"> /**</span>
+<span class="source-line-no">1794</span><span id="line-1794"> * Check whether we tolerate IO error this time. If the duration of IOEngine throwing errors</span>
+<span class="source-line-no">1795</span><span id="line-1795"> * exceeds ioErrorsDurationTimeTolerated, we will disable the cache</span>
+<span class="source-line-no">1796</span><span id="line-1796"> */</span>
+<span class="source-line-no">1797</span><span id="line-1797"> private void checkIOErrorIsTolerated() {</span>
+<span class="source-line-no">1798</span><span id="line-1798"> long now = EnvironmentEdgeManager.currentTime();</span>
+<span class="source-line-no">1799</span><span id="line-1799"> // Do a single read to a local variable to avoid timing issue - HBASE-24454</span>
+<span class="source-line-no">1800</span><span id="line-1800"> long ioErrorStartTimeTmp = this.ioErrorStartTime;</span>
+<span class="source-line-no">1801</span><span id="line-1801"> if (ioErrorStartTimeTmp > 0) {</span>
+<span class="source-line-no">1802</span><span id="line-1802"> if (isCacheEnabled() && (now - ioErrorStartTimeTmp) > this.ioErrorsTolerationDuration) {</span>
+<span class="source-line-no">1803</span><span id="line-1803"> LOG.error("IO errors duration time has exceeded " + ioErrorsTolerationDuration</span>
+<span class="source-line-no">1804</span><span id="line-1804"> + "ms, disabling cache, please check your IOEngine");</span>
+<span class="source-line-no">1805</span><span id="line-1805"> disableCache();</span>
+<span class="source-line-no">1806</span><span id="line-1806"> }</span>
+<span class="source-line-no">1807</span><span id="line-1807"> } else {</span>
+<span class="source-line-no">1808</span><span id="line-1808"> this.ioErrorStartTime = now;</span>
+<span class="source-line-no">1809</span><span id="line-1809"> }</span>
+<span class="source-line-no">1810</span><span id="line-1810"> }</span>
+<span class="source-line-no">1811</span><span id="line-1811"></span>
+<span class="source-line-no">1812</span><span id="line-1812"> /**</span>
+<span class="source-line-no">1813</span><span id="line-1813"> * Used to shut down the cache -or- turn it off in the case of something broken.</span>
+<span class="source-line-no">1814</span><span id="line-1814"> */</span>
+<span class="source-line-no">1815</span><span id="line-1815"> private void disableCache() {</span>
+<span class="source-line-no">1816</span><span id="line-1816"> if (!isCacheEnabled()) {</span>
+<span class="source-line-no">1817</span><span id="line-1817"> return;</span>
<span class="source-line-no">1818</span><span id="line-1818"> }</span>
-<span class="source-line-no">1819</span><span id="line-1819"> if (cacheStats.getMetricsRollerScheduler() != null) {</span>
-<span class="source-line-no">1820</span><span id="line-1820"> cacheStats.getMetricsRollerScheduler().shutdownNow();</span>
-<span class="source-line-no">1821</span><span id="line-1821"> }</span>
-<span class="source-line-no">1822</span><span id="line-1822"> }</span>
-<span class="source-line-no">1823</span><span id="line-1823"></span>
-<span class="source-line-no">1824</span><span id="line-1824"> private void join() throws InterruptedException {</span>
-<span class="source-line-no">1825</span><span id="line-1825"> for (int i = 0; i < writerThreads.length; ++i)</span>
-<span class="source-line-no">1826</span><span id="line-1826"> writerThreads[i].join();</span>
-<span class="source-line-no">1827</span><span id="line-1827"> }</span>
-<span class="source-line-no">1828</span><span id="line-1828"></span>
-<span class="source-line-no">1829</span><span id="line-1829"> @Override</span>
-<span class="source-line-no">1830</span><span id="line-1830"> public void shutdown() {</span>
-<span class="source-line-no">1831</span><span id="line-1831"> if (isCacheEnabled()) {</span>
-<span class="source-line-no">1832</span><span id="line-1832"> disableCache();</span>
-<span class="source-line-no">1833</span><span id="line-1833"> LOG.info("Shutdown bucket cache: IO persistent=" + ioEngine.isPersistent()</span>
-<span class="source-line-no">1834</span><span id="line-1834"> + "; path to write=" + persistencePath);</span>
-<span class="source-line-no">1835</span><span id="line-1835"> if (ioEngine.isPersistent() && persistencePath != null) {</span>
-<span class="source-line-no">1836</span><span id="line-1836"> try {</span>
-<span class="source-line-no">1837</span><span id="line-1837"> join();</span>
-<span class="source-line-no">1838</span><span id="line-1838"> if (cachePersister != null) {</span>
-<span class="source-line-no">1839</span><span id="line-1839"> LOG.info("Shutting down cache persister thread.");</span>
-<span class="source-line-no">1840</span><span id="line-1840"> cachePersister.shutdown();</span>
-<span class="source-line-no">1841</span><span id="line-1841"> while (cachePersister.isAlive()) {</span>
-<span class="source-line-no">1842</span><span id="line-1842"> Thread.sleep(10);</span>
-<span class="source-line-no">1843</span><span id="line-1843"> }</span>
-<span class="source-line-no">1844</span><span id="line-1844"> }</span>
-<span class="source-line-no">1845</span><span id="line-1845"> persistToFile();</span>
-<span class="source-line-no">1846</span><span id="line-1846"> } catch (IOException ex) {</span>
-<span class="source-line-no">1847</span><span id="line-1847"> LOG.error("Unable to persist data on exit: " + ex.toString(), ex);</span>
-<span class="source-line-no">1848</span><span id="line-1848"> } catch (InterruptedException e) {</span>
-<span class="source-line-no">1849</span><span id="line-1849"> LOG.warn("Failed to persist data on exit", e);</span>
-<span class="source-line-no">1850</span><span id="line-1850"> }</span>
-<span class="source-line-no">1851</span><span id="line-1851"> }</span>
-<span class="source-line-no">1852</span><span id="line-1852"> }</span>
-<span class="source-line-no">1853</span><span id="line-1853"> }</span>
-<span class="source-line-no">1854</span><span id="line-1854"></span>
-<span class="source-line-no">1855</span><span id="line-1855"> /**</span>
-<span class="source-line-no">1856</span><span id="line-1856"> * Needed mostly for UTs that might run in the same VM and create different BucketCache instances</span>
-<span class="source-line-no">1857</span><span id="line-1857"> * on different UT methods.</span>
-<span class="source-line-no">1858</span><span id="line-1858"> */</span>
-<span class="source-line-no">1859</span><span id="line-1859"> @Override</span>
-<span class="source-line-no">1860</span><span id="line-1860"> protected void finalize() {</span>
-<span class="source-line-no">1861</span><span id="line-1861"> if (cachePersister != null && !cachePersister.isInterrupted()) {</span>
-<span class="source-line-no">1862</span><span id="line-1862"> cachePersister.interrupt();</span>
-<span class="source-line-no">1863</span><span id="line-1863"> }</span>
-<span class="source-line-no">1864</span><span id="line-1864"> }</span>
-<span class="source-line-no">1865</span><span id="line-1865"></span>
-<span class="source-line-no">1866</span><span id="line-1866"> @Override</span>
-<span class="source-line-no">1867</span><span id="line-1867"> public CacheStats getStats() {</span>
-<span class="source-line-no">1868</span><span id="line-1868"> return cacheStats;</span>
-<span class="source-line-no">1869</span><span id="line-1869"> }</span>
-<span class="source-line-no">1870</span><span id="line-1870"></span>
-<span class="source-line-no">1871</span><span id="line-1871"> public BucketAllocator getAllocator() {</span>
-<span class="source-line-no">1872</span><span id="line-1872"> return this.bucketAllocator;</span>
-<span class="source-line-no">1873</span><span id="line-1873"> }</span>
-<span class="source-line-no">1874</span><span id="line-1874"></span>
-<span class="source-line-no">1875</span><span id="line-1875"> @Override</span>
-<span class="source-line-no">1876</span><span id="line-1876"> public long heapSize() {</span>
-<span class="source-line-no">1877</span><span id="line-1877"> return this.heapSize.sum();</span>
+<span class="source-line-no">1819</span><span id="line-1819"> LOG.info("Disabling cache");</span>
+<span class="source-line-no">1820</span><span id="line-1820"> cacheState = CacheState.DISABLED;</span>
+<span class="source-line-no">1821</span><span id="line-1821"> ioEngine.shutdown();</span>
+<span class="source-line-no">1822</span><span id="line-1822"> this.scheduleThreadPool.shutdown();</span>
+<span class="source-line-no">1823</span><span id="line-1823"> for (int i = 0; i < writerThreads.length; ++i)</span>
+<span class="source-line-no">1824</span><span id="line-1824"> writerThreads[i].interrupt();</span>
+<span class="source-line-no">1825</span><span id="line-1825"> this.ramCache.clear();</span>
+<span class="source-line-no">1826</span><span id="line-1826"> if (!ioEngine.isPersistent() || persistencePath == null) {</span>
+<span class="source-line-no">1827</span><span id="line-1827"> // If persistent ioengine and a path, we will serialize out the backingMap.</span>
+<span class="source-line-no">1828</span><span id="line-1828"> this.backingMap.clear();</span>
+<span class="source-line-no">1829</span><span id="line-1829"> this.blocksByHFile.clear();</span>
+<span class="source-line-no">1830</span><span id="line-1830"> this.fullyCachedFiles.clear();</span>
+<span class="source-line-no">1831</span><span id="line-1831"> this.regionCachedSize.clear();</span>
+<span class="source-line-no">1832</span><span id="line-1832"> }</span>
+<span class="source-line-no">1833</span><span id="line-1833"> if (cacheStats.getMetricsRollerScheduler() != null) {</span>
+<span class="source-line-no">1834</span><span id="line-1834"> cacheStats.getMetricsRollerScheduler().shutdownNow();</span>
+<span class="source-line-no">1835</span><span id="line-1835"> }</span>
+<span class="source-line-no">1836</span><span id="line-1836"> }</span>
+<span class="source-line-no">1837</span><span id="line-1837"></span>
+<span class="source-line-no">1838</span><span id="line-1838"> private void join() throws InterruptedException {</span>
+<span class="source-line-no">1839</span><span id="line-1839"> for (int i = 0; i < writerThreads.length; ++i)</span>
+<span class="source-line-no">1840</span><span id="line-1840"> writerThreads[i].join();</span>
+<span class="source-line-no">1841</span><span id="line-1841"> }</span>
+<span class="source-line-no">1842</span><span id="line-1842"></span>
+<span class="source-line-no">1843</span><span id="line-1843"> @Override</span>
+<span class="source-line-no">1844</span><span id="line-1844"> public void shutdown() {</span>
+<span class="source-line-no">1845</span><span id="line-1845"> if (isCacheEnabled()) {</span>
+<span class="source-line-no">1846</span><span id="line-1846"> disableCache();</span>
+<span class="source-line-no">1847</span><span id="line-1847"> LOG.info("Shutdown bucket cache: IO persistent=" + ioEngine.isPersistent()</span>
+<span class="source-line-no">1848</span><span id="line-1848"> + "; path to write=" + persistencePath);</span>
+<span class="source-line-no">1849</span><span id="line-1849"> if (ioEngine.isPersistent() && persistencePath != null) {</span>
+<span class="source-line-no">1850</span><span id="line-1850"> try {</span>
+<span class="source-line-no">1851</span><span id="line-1851"> join();</span>
+<span class="source-line-no">1852</span><span id="line-1852"> if (cachePersister != null) {</span>
+<span class="source-line-no">1853</span><span id="line-1853"> LOG.info("Shutting down cache persister thread.");</span>
+<span class="source-line-no">1854</span><span id="line-1854"> cachePersister.shutdown();</span>
+<span class="source-line-no">1855</span><span id="line-1855"> while (cachePersister.isAlive()) {</span>
+<span class="source-line-no">1856</span><span id="line-1856"> Thread.sleep(10);</span>
+<span class="source-line-no">1857</span><span id="line-1857"> }</span>
+<span class="source-line-no">1858</span><span id="line-1858"> }</span>
+<span class="source-line-no">1859</span><span id="line-1859"> persistToFile();</span>
+<span class="source-line-no">1860</span><span id="line-1860"> } catch (IOException ex) {</span>
+<span class="source-line-no">1861</span><span id="line-1861"> LOG.error("Unable to persist data on exit: " + ex.toString(), ex);</span>
+<span class="source-line-no">1862</span><span id="line-1862"> } catch (InterruptedException e) {</span>
+<span class="source-line-no">1863</span><span id="line-1863"> LOG.warn("Failed to persist data on exit", e);</span>
+<span class="source-line-no">1864</span><span id="line-1864"> }</span>
+<span class="source-line-no">1865</span><span id="line-1865"> }</span>
+<span class="source-line-no">1866</span><span id="line-1866"> }</span>
+<span class="source-line-no">1867</span><span id="line-1867"> }</span>
+<span class="source-line-no">1868</span><span id="line-1868"></span>
+<span class="source-line-no">1869</span><span id="line-1869"> /**</span>
+<span class="source-line-no">1870</span><span id="line-1870"> * Needed mostly for UTs that might run in the same VM and create different BucketCache instances</span>
+<span class="source-line-no">1871</span><span id="line-1871"> * on different UT methods.</span>
+<span class="source-line-no">1872</span><span id="line-1872"> */</span>
+<span class="source-line-no">1873</span><span id="line-1873"> @Override</span>
+<span class="source-line-no">1874</span><span id="line-1874"> protected void finalize() {</span>
+<span class="source-line-no">1875</span><span id="line-1875"> if (cachePersister != null && !cachePersister.isInterrupted()) {</span>
+<span class="source-line-no">1876</span><span id="line-1876"> cachePersister.interrupt();</span>
+<span class="source-line-no">1877</span><span id="line-1877"> }</span>
<span class="source-line-no">1878</span><span id="line-1878"> }</span>
<span class="source-line-no">1879</span><span id="line-1879"></span>
<span class="source-line-no">1880</span><span id="line-1880"> @Override</span>
-<span class="source-line-no">1881</span><span id="line-1881"> public long size() {</span>
-<span class="source-line-no">1882</span><span id="line-1882"> return this.realCacheSize.sum();</span>
+<span class="source-line-no">1881</span><span id="line-1881"> public CacheStats getStats() {</span>
+<span class="source-line-no">1882</span><span id="line-1882"> return cacheStats;</span>
<span class="source-line-no">1883</span><span id="line-1883"> }</span>
<span class="source-line-no">1884</span><span id="line-1884"></span>
-<span class="source-line-no">1885</span><span id="line-1885"> @Override</span>
-<span class="source-line-no">1886</span><span id="line-1886"> public long getCurrentDataSize() {</span>
-<span class="source-line-no">1887</span><span id="line-1887"> return size();</span>
-<span class="source-line-no">1888</span><span id="line-1888"> }</span>
-<span class="source-line-no">1889</span><span id="line-1889"></span>
-<span class="source-line-no">1890</span><span id="line-1890"> @Override</span>
-<span class="source-line-no">1891</span><span id="line-1891"> public long getFreeSize() {</span>
-<span class="source-line-no">1892</span><span id="line-1892"> if (!isCacheInitialized("BucketCache:getFreeSize")) {</span>
-<span class="source-line-no">1893</span><span id="line-1893"> return 0;</span>
-<span class="source-line-no">1894</span><span id="line-1894"> }</span>
-<span class="source-line-no">1895</span><span id="line-1895"> return this.bucketAllocator.getFreeSize();</span>
-<span class="source-line-no">1896</span><span id="line-1896"> }</span>
-<span class="source-line-no">1897</span><span id="line-1897"></span>
-<span class="source-line-no">1898</span><span id="line-1898"> @Override</span>
-<span class="source-line-no">1899</span><span id="line-1899"> public long getBlockCount() {</span>
-<span class="source-line-no">1900</span><span id="line-1900"> return this.blockNumber.sum();</span>
-<span class="source-line-no">1901</span><span id="line-1901"> }</span>
-<span class="source-line-no">1902</span><span id="line-1902"></span>
-<span class="source-line-no">1903</span><span id="line-1903"> @Override</span>
-<span class="source-line-no">1904</span><span id="line-1904"> public long getDataBlockCount() {</span>
-<span class="source-line-no">1905</span><span id="line-1905"> return getBlockCount();</span>
-<span class="source-line-no">1906</span><span id="line-1906"> }</span>
-<span class="source-line-no">1907</span><span id="line-1907"></span>
-<span class="source-line-no">1908</span><span id="line-1908"> @Override</span>
-<span class="source-line-no">1909</span><span id="line-1909"> public long getCurrentSize() {</span>
-<span class="source-line-no">1910</span><span id="line-1910"> if (!isCacheInitialized("BucketCache::getCurrentSize")) {</span>
-<span class="source-line-no">1911</span><span id="line-1911"> return 0;</span>
-<span class="source-line-no">1912</span><span id="line-1912"> }</span>
-<span class="source-line-no">1913</span><span id="line-1913"> return this.bucketAllocator.getUsedSize();</span>
-<span class="source-line-no">1914</span><span id="line-1914"> }</span>
-<span class="source-line-no">1915</span><span id="line-1915"></span>
-<span class="source-line-no">1916</span><span id="line-1916"> protected String getAlgorithm() {</span>
-<span class="source-line-no">1917</span><span id="line-1917"> return algorithm;</span>
-<span class="source-line-no">1918</span><span id="line-1918"> }</span>
-<span class="source-line-no">1919</span><span id="line-1919"></span>
-<span class="source-line-no">1920</span><span id="line-1920"> /**</span>
-<span class="source-line-no">1921</span><span id="line-1921"> * Evicts all blocks for a specific HFile.</span>
-<span class="source-line-no">1922</span><span id="line-1922"> * <p></span>
-<span class="source-line-no">1923</span><span id="line-1923"> * This is used for evict-on-close to remove all blocks of a specific HFile.</span>
-<span class="source-line-no">1924</span><span id="line-1924"> * @return the number of blocks evicted</span>
-<span class="source-line-no">1925</span><span id="line-1925"> */</span>
-<span class="source-line-no">1926</span><span id="line-1926"> @Override</span>
-<span class="source-line-no">1927</span><span id="line-1927"> public int evictBlocksByHfileName(String hfileName) {</span>
-<span class="source-line-no">1928</span><span id="line-1928"> return evictBlocksRangeByHfileName(hfileName, 0, Long.MAX_VALUE);</span>
-<span class="source-line-no">1929</span><span id="line-1929"> }</span>
-<span class="source-line-no">1930</span><span id="line-1930"></span>
-<span class="source-line-no">1931</span><span id="line-1931"> @Override</span>
-<span class="source-line-no">1932</span><span id="line-1932"> public int evictBlocksRangeByHfileName(String hfileName, long initOffset, long endOffset) {</span>
-<span class="source-line-no">1933</span><span id="line-1933"> Set<BlockCacheKey> keySet = getAllCacheKeysForFile(hfileName, initOffset, endOffset);</span>
-<span class="source-line-no">1934</span><span id="line-1934"> // We need to make sure whether we are evicting all blocks for this given file. In case of</span>
-<span class="source-line-no">1935</span><span id="line-1935"> // split references, we might be evicting just half of the blocks</span>
-<span class="source-line-no">1936</span><span id="line-1936"> LOG.debug("found {} blocks for file {}, starting offset: {}, end offset: {}", keySet.size(),</span>
-<span class="source-line-no">1937</span><span id="line-1937"> hfileName, initOffset, endOffset);</span>
-<span class="source-line-no">1938</span><span id="line-1938"> int numEvicted = 0;</span>
-<span class="source-line-no">1939</span><span id="line-1939"> for (BlockCacheKey key : keySet) {</span>
-<span class="source-line-no">1940</span><span id="line-1940"> if (evictBlock(key)) {</span>
-<span class="source-line-no">1941</span><span id="line-1941"> ++numEvicted;</span>
-<span class="source-line-no">1942</span><span id="line-1942"> }</span>
-<span class="source-line-no">1943</span><span id="line-1943"> }</span>
-<span class="source-line-no">1944</span><span id="line-1944"> return numEvicted;</span>
-<span class="source-line-no">1945</span><span id="line-1945"> }</span>
-<span class="source-line-no">1946</span><span id="line-1946"></span>
-<span class="source-line-no">1947</span><span id="line-1947"> private Set<BlockCacheKey> getAllCacheKeysForFile(String hfileName, long init, long end) {</span>
-<span class="source-line-no">1948</span><span id="line-1948"> // These keys are just for comparison and are short lived, so we need only file name and offset</span>
-<span class="source-line-no">1949</span><span id="line-1949"> return blocksByHFile.subSet(new BlockCacheKey(hfileName, init), true,</span>
-<span class="source-line-no">1950</span><span id="line-1950"> new BlockCacheKey(hfileName, end), true);</span>
-<span class="source-line-no">1951</span><span id="line-1951"> }</span>
-<span class="source-line-no">1952</span><span id="line-1952"></span>
-<span class="source-line-no">1953</span><span id="line-1953"> /**</span>
-<span class="source-line-no">1954</span><span id="line-1954"> * Used to group bucket entries into priority buckets. There will be a BucketEntryGroup for each</span>
-<span class="source-line-no">1955</span><span id="line-1955"> * priority (single, multi, memory). Once bucketed, the eviction algorithm takes the appropriate</span>
-<span class="source-line-no">1956</span><span id="line-1956"> * number of elements out of each according to configuration parameters and their relative sizes.</span>
-<span class="source-line-no">1957</span><span id="line-1957"> */</span>
-<span class="source-line-no">1958</span><span id="line-1958"> private class BucketEntryGroup {</span>
-<span class="source-line-no">1959</span><span id="line-1959"></span>
-<span class="source-line-no">1960</span><span id="line-1960"> private CachedEntryQueue queue;</span>
-<span class="source-line-no">1961</span><span id="line-1961"> private long totalSize = 0;</span>
-<span class="source-line-no">1962</span><span id="line-1962"> private long bucketSize;</span>
-<span class="source-line-no">1963</span><span id="line-1963"></span>
-<span class="source-line-no">1964</span><span id="line-1964"> public BucketEntryGroup(long bytesToFree, long blockSize, long bucketSize) {</span>
-<span class="source-line-no">1965</span><span id="line-1965"> this.bucketSize = bucketSize;</span>
-<span class="source-line-no">1966</span><span id="line-1966"> queue = new CachedEntryQueue(bytesToFree, blockSize);</span>
-<span class="source-line-no">1967</span><span id="line-1967"> totalSize = 0;</span>
-<span class="source-line-no">1968</span><span id="line-1968"> }</span>
-<span class="source-line-no">1969</span><span id="line-1969"></span>
-<span class="source-line-no">1970</span><span id="line-1970"> public void add(Map.Entry<BlockCacheKey, BucketEntry> block) {</span>
-<span class="source-line-no">1971</span><span id="line-1971"> totalSize += block.getValue().getLength();</span>
-<span class="source-line-no">1972</span><span id="line-1972"> queue.add(block);</span>
-<span class="source-line-no">1973</span><span id="line-1973"> }</span>
-<span class="source-line-no">1974</span><span id="line-1974"></span>
-<span class="source-line-no">1975</span><span id="line-1975"> public long free(long toFree) {</span>
-<span class="source-line-no">1976</span><span id="line-1976"> Map.Entry<BlockCacheKey, BucketEntry> entry;</span>
-<span class="source-line-no">1977</span><span id="line-1977"> long freedBytes = 0;</span>
-<span class="source-line-no">1978</span><span id="line-1978"> // TODO avoid a cycling siutation. We find no block which is not in use and so no way to free</span>
-<span class="source-line-no">1979</span><span id="line-1979"> // What to do then? Caching attempt fail? Need some changes in cacheBlock API?</span>
-<span class="source-line-no">1980</span><span id="line-1980"> while ((entry = queue.pollLast()) != null) {</span>
-<span class="source-line-no">1981</span><span id="line-1981"> BlockCacheKey blockCacheKey = entry.getKey();</span>
-<span class="source-line-no">1982</span><span id="line-1982"> BucketEntry be = entry.getValue();</span>
-<span class="source-line-no">1983</span><span id="line-1983"> if (evictBucketEntryIfNoRpcReferenced(blockCacheKey, be)) {</span>
-<span class="source-line-no">1984</span><span id="line-1984"> freedBytes += be.getLength();</span>
-<span class="source-line-no">1985</span><span id="line-1985"> }</span>
-<span class="source-line-no">1986</span><span id="line-1986"> if (freedBytes >= toFree) {</span>
-<span class="source-line-no">1987</span><span id="line-1987"> return freedBytes;</span>
-<span class="source-line-no">1988</span><span id="line-1988"> }</span>
-<span class="source-line-no">1989</span><span id="line-1989"> }</span>
-<span class="source-line-no">1990</span><span id="line-1990"> return freedBytes;</span>
-<span class="source-line-no">1991</span><span id="line-1991"> }</span>
-<span class="source-line-no">1992</span><span id="line-1992"></span>
-<span class="source-line-no">1993</span><span id="line-1993"> public long overflow() {</span>
-<span class="source-line-no">1994</span><span id="line-1994"> return totalSize - bucketSize;</span>
-<span class="source-line-no">1995</span><span id="line-1995"> }</span>
-<span class="source-line-no">1996</span><span id="line-1996"></span>
-<span class="source-line-no">1997</span><span id="line-1997"> public long totalSize() {</span>
-<span class="source-line-no">1998</span><span id="line-1998"> return totalSize;</span>
-<span class="source-line-no">1999</span><span id="line-1999"> }</span>
-<span class="source-line-no">2000</span><span id="line-2000"> }</span>
-<span class="source-line-no">2001</span><span id="line-2001"></span>
-<span class="source-line-no">2002</span><span id="line-2002"> /**</span>
-<span class="source-line-no">2003</span><span id="line-2003"> * Block Entry stored in the memory with key,data and so on</span>
-<span class="source-line-no">2004</span><span id="line-2004"> */</span>
-<span class="source-line-no">2005</span><span id="line-2005"> static class RAMQueueEntry {</span>
-<span class="source-line-no">2006</span><span id="line-2006"> private final BlockCacheKey key;</span>
-<span class="source-line-no">2007</span><span id="line-2007"> private final Cacheable data;</span>
-<span class="source-line-no">2008</span><span id="line-2008"> private long accessCounter;</span>
-<span class="source-line-no">2009</span><span id="line-2009"> private boolean inMemory;</span>
-<span class="source-line-no">2010</span><span id="line-2010"> private boolean isCachePersistent;</span>
-<span class="source-line-no">2011</span><span id="line-2011"></span>
-<span class="source-line-no">2012</span><span id="line-2012"> private boolean isPrefetch;</span>
-<span class="source-line-no">2013</span><span id="line-2013"></span>
-<span class="source-line-no">2014</span><span id="line-2014"> RAMQueueEntry(BlockCacheKey bck, Cacheable data, long accessCounter, boolean inMemory,</span>
-<span class="source-line-no">2015</span><span id="line-2015"> boolean isCachePersistent, boolean isPrefetch) {</span>
-<span class="source-line-no">2016</span><span id="line-2016"> this.key = bck;</span>
-<span class="source-line-no">2017</span><span id="line-2017"> this.data = data;</span>
-<span class="source-line-no">2018</span><span id="line-2018"> this.accessCounter = accessCounter;</span>
-<span class="source-line-no">2019</span><span id="line-2019"> this.inMemory = inMemory;</span>
-<span class="source-line-no">2020</span><span id="line-2020"> this.isCachePersistent = isCachePersistent;</span>
-<span class="source-line-no">2021</span><span id="line-2021"> this.isPrefetch = isPrefetch;</span>
-<span class="source-line-no">2022</span><span id="line-2022"> }</span>
-<span class="source-line-no">2023</span><span id="line-2023"></span>
-<span class="source-line-no">2024</span><span id="line-2024"> public Cacheable getData() {</span>
-<span class="source-line-no">2025</span><span id="line-2025"> return data;</span>
-<span class="source-line-no">2026</span><span id="line-2026"> }</span>
+<span class="source-line-no">1885</span><span id="line-1885"> public BucketAllocator getAllocator() {</span>
+<span class="source-line-no">1886</span><span id="line-1886"> return this.bucketAllocator;</span>
+<span class="source-line-no">1887</span><span id="line-1887"> }</span>
+<span class="source-line-no">1888</span><span id="line-1888"></span>
+<span class="source-line-no">1889</span><span id="line-1889"> @Override</span>
+<span class="source-line-no">1890</span><span id="line-1890"> public long heapSize() {</span>
+<span class="source-line-no">1891</span><span id="line-1891"> return this.heapSize.sum();</span>
+<span class="source-line-no">1892</span><span id="line-1892"> }</span>
+<span class="source-line-no">1893</span><span id="line-1893"></span>
+<span class="source-line-no">1894</span><span id="line-1894"> @Override</span>
+<span class="source-line-no">1895</span><span id="line-1895"> public long size() {</span>
+<span class="source-line-no">1896</span><span id="line-1896"> return this.realCacheSize.sum();</span>
+<span class="source-line-no">1897</span><span id="line-1897"> }</span>
+<span class="source-line-no">1898</span><span id="line-1898"></span>
+<span class="source-line-no">1899</span><span id="line-1899"> @Override</span>
+<span class="source-line-no">1900</span><span id="line-1900"> public long getCurrentDataSize() {</span>
+<span class="source-line-no">1901</span><span id="line-1901"> return size();</span>
+<span class="source-line-no">1902</span><span id="line-1902"> }</span>
+<span class="source-line-no">1903</span><span id="line-1903"></span>
+<span class="source-line-no">1904</span><span id="line-1904"> @Override</span>
+<span class="source-line-no">1905</span><span id="line-1905"> public long getFreeSize() {</span>
+<span class="source-line-no">1906</span><span id="line-1906"> if (!isCacheInitialized("BucketCache:getFreeSize")) {</span>
+<span class="source-line-no">1907</span><span id="line-1907"> return 0;</span>
+<span class="source-line-no">1908</span><span id="line-1908"> }</span>
+<span class="source-line-no">1909</span><span id="line-1909"> return this.bucketAllocator.getFreeSize();</span>
+<span class="source-line-no">1910</span><span id="line-1910"> }</span>
+<span class="source-line-no">1911</span><span id="line-1911"></span>
+<span class="source-line-no">1912</span><span id="line-1912"> @Override</span>
+<span class="source-line-no">1913</span><span id="line-1913"> public long getBlockCount() {</span>
+<span class="source-line-no">1914</span><span id="line-1914"> return this.blockNumber.sum();</span>
+<span class="source-line-no">1915</span><span id="line-1915"> }</span>
+<span class="source-line-no">1916</span><span id="line-1916"></span>
+<span class="source-line-no">1917</span><span id="line-1917"> @Override</span>
+<span class="source-line-no">1918</span><span id="line-1918"> public long getDataBlockCount() {</span>
+<span class="source-line-no">1919</span><span id="line-1919"> return getBlockCount();</span>
+<span class="source-line-no">1920</span><span id="line-1920"> }</span>
+<span class="source-line-no">1921</span><span id="line-1921"></span>
+<span class="source-line-no">1922</span><span id="line-1922"> @Override</span>
+<span class="source-line-no">1923</span><span id="line-1923"> public long getCurrentSize() {</span>
+<span class="source-line-no">1924</span><span id="line-1924"> if (!isCacheInitialized("BucketCache::getCurrentSize")) {</span>
+<span class="source-line-no">1925</span><span id="line-1925"> return 0;</span>
+<span class="source-line-no">1926</span><span id="line-1926"> }</span>
+<span class="source-line-no">1927</span><span id="line-1927"> return this.bucketAllocator.getUsedSize();</span>
+<span class="source-line-no">1928</span><span id="line-1928"> }</span>
+<span class="source-line-no">1929</span><span id="line-1929"></span>
+<span class="source-line-no">1930</span><span id="line-1930"> protected String getAlgorithm() {</span>
+<span class="source-line-no">1931</span><span id="line-1931"> return algorithm;</span>
+<span class="source-line-no">1932</span><span id="line-1932"> }</span>
+<span class="source-line-no">1933</span><span id="line-1933"></span>
+<span class="source-line-no">1934</span><span id="line-1934"> /**</span>
+<span class="source-line-no">1935</span><span id="line-1935"> * Evicts all blocks for a specific HFile.</span>
+<span class="source-line-no">1936</span><span id="line-1936"> * <p></span>
+<span class="source-line-no">1937</span><span id="line-1937"> * This is used for evict-on-close to remove all blocks of a specific HFile.</span>
+<span class="source-line-no">1938</span><span id="line-1938"> * @return the number of blocks evicted</span>
+<span class="source-line-no">1939</span><span id="line-1939"> */</span>
+<span class="source-line-no">1940</span><span id="line-1940"> @Override</span>
+<span class="source-line-no">1941</span><span id="line-1941"> public int evictBlocksByHfileName(String hfileName) {</span>
+<span class="source-line-no">1942</span><span id="line-1942"> return evictBlocksRangeByHfileName(hfileName, 0, Long.MAX_VALUE);</span>
+<span class="source-line-no">1943</span><span id="line-1943"> }</span>
+<span class="source-line-no">1944</span><span id="line-1944"></span>
+<span class="source-line-no">1945</span><span id="line-1945"> @Override</span>
+<span class="source-line-no">1946</span><span id="line-1946"> public int evictBlocksRangeByHfileName(String hfileName, long initOffset, long endOffset) {</span>
+<span class="source-line-no">1947</span><span id="line-1947"> Set<BlockCacheKey> keySet = getAllCacheKeysForFile(hfileName, initOffset, endOffset);</span>
+<span class="source-line-no">1948</span><span id="line-1948"> // We need to make sure whether we are evicting all blocks for this given file. In case of</span>
+<span class="source-line-no">1949</span><span id="line-1949"> // split references, we might be evicting just half of the blocks</span>
+<span class="source-line-no">1950</span><span id="line-1950"> LOG.debug("found {} blocks for file {}, starting offset: {}, end offset: {}", keySet.size(),</span>
+<span class="source-line-no">1951</span><span id="line-1951"> hfileName, initOffset, endOffset);</span>
+<span class="source-line-no">1952</span><span id="line-1952"> int numEvicted = 0;</span>
+<span class="source-line-no">1953</span><span id="line-1953"> for (BlockCacheKey key : keySet) {</span>
+<span class="source-line-no">1954</span><span id="line-1954"> if (evictBlock(key)) {</span>
+<span class="source-line-no">1955</span><span id="line-1955"> ++numEvicted;</span>
+<span class="source-line-no">1956</span><span id="line-1956"> }</span>
+<span class="source-line-no">1957</span><span id="line-1957"> }</span>
+<span class="source-line-no">1958</span><span id="line-1958"> return numEvicted;</span>
+<span class="source-line-no">1959</span><span id="line-1959"> }</span>
+<span class="source-line-no">1960</span><span id="line-1960"></span>
+<span class="source-line-no">1961</span><span id="line-1961"> private Set<BlockCacheKey> getAllCacheKeysForFile(String hfileName, long init, long end) {</span>
+<span class="source-line-no">1962</span><span id="line-1962"> // These keys are just for comparison and are short lived, so we need only file name and offset</span>
+<span class="source-line-no">1963</span><span id="line-1963"> return blocksByHFile.subSet(new BlockCacheKey(hfileName, init), true,</span>
+<span class="source-line-no">1964</span><span id="line-1964"> new BlockCacheKey(hfileName, end), true);</span>
+<span class="source-line-no">1965</span><span id="line-1965"> }</span>
+<span class="source-line-no">1966</span><span id="line-1966"></span>
+<span class="source-line-no">1967</span><span id="line-1967"> /**</span>
+<span class="source-line-no">1968</span><span id="line-1968"> * Used to group bucket entries into priority buckets. There will be a BucketEntryGroup for each</span>
+<span class="source-line-no">1969</span><span id="line-1969"> * priority (single, multi, memory). Once bucketed, the eviction algorithm takes the appropriate</span>
+<span class="source-line-no">1970</span><span id="line-1970"> * number of elements out of each according to configuration parameters and their relative sizes.</span>
+<span class="source-line-no">1971</span><span id="line-1971"> */</span>
+<span class="source-line-no">1972</span><span id="line-1972"> private class BucketEntryGroup {</span>
+<span class="source-line-no">1973</span><span id="line-1973"></span>
+<span class="source-line-no">1974</span><span id="line-1974"> private CachedEntryQueue queue;</span>
+<span class="source-line-no">1975</span><span id="line-1975"> private long totalSize = 0;</span>
+<span class="source-line-no">1976</span><span id="line-1976"> private long bucketSize;</span>
+<span class="source-line-no">1977</span><span id="line-1977"></span>
+<span class="source-line-no">1978</span><span id="line-1978"> public BucketEntryGroup(long bytesToFree, long blockSize, long bucketSize) {</span>
+<span class="source-line-no">1979</span><span id="line-1979"> this.bucketSize = bucketSize;</span>
+<span class="source-line-no">1980</span><span id="line-1980"> queue = new CachedEntryQueue(bytesToFree, blockSize);</span>
+<span class="source-line-no">1981</span><span id="line-1981"> totalSize = 0;</span>
+<span class="source-line-no">1982</span><span id="line-1982"> }</span>
+<span class="source-line-no">1983</span><span id="line-1983"></span>
+<span class="source-line-no">1984</span><span id="line-1984"> public void add(Map.Entry<BlockCacheKey, BucketEntry> block) {</span>
+<span class="source-line-no">1985</span><span id="line-1985"> totalSize += block.getValue().getLength();</span>
+<span class="source-line-no">1986</span><span id="line-1986"> queue.add(block);</span>
+<span class="source-line-no">1987</span><span id="line-1987"> }</span>
+<span class="source-line-no">1988</span><span id="line-1988"></span>
+<span class="source-line-no">1989</span><span id="line-1989"> public long free(long toFree) {</span>
+<span class="source-line-no">1990</span><span id="line-1990"> Map.Entry<BlockCacheKey, BucketEntry> entry;</span>
+<span class="source-line-no">1991</span><span id="line-1991"> long freedBytes = 0;</span>
+<span class="source-line-no">1992</span><span id="line-1992"> // TODO avoid a cycling siutation. We find no block which is not in use and so no way to free</span>
+<span class="source-line-no">1993</span><span id="line-1993"> // What to do then? Caching attempt fail? Need some changes in cacheBlock API?</span>
+<span class="source-line-no">1994</span><span id="line-1994"> while ((entry = queue.pollLast()) != null) {</span>
+<span class="source-line-no">1995</span><span id="line-1995"> BlockCacheKey blockCacheKey = entry.getKey();</span>
+<span class="source-line-no">1996</span><span id="line-1996"> BucketEntry be = entry.getValue();</span>
+<span class="source-line-no">1997</span><span id="line-1997"> if (evictBucketEntryIfNoRpcReferenced(blockCacheKey, be)) {</span>
+<span class="source-line-no">1998</span><span id="line-1998"> freedBytes += be.getLength();</span>
+<span class="source-line-no">1999</span><span id="line-1999"> }</span>
+<span class="source-line-no">2000</span><span id="line-2000"> if (freedBytes >= toFree) {</span>
+<span class="source-line-no">2001</span><span id="line-2001"> return freedBytes;</span>
+<span class="source-line-no">2002</span><span id="line-2002"> }</span>
+<span class="source-line-no">2003</span><span id="line-2003"> }</span>
+<span class="source-line-no">2004</span><span id="line-2004"> return freedBytes;</span>
+<span class="source-line-no">2005</span><span id="line-2005"> }</span>
+<span class="source-line-no">2006</span><span id="line-2006"></span>
+<span class="source-line-no">2007</span><span id="line-2007"> public long overflow() {</span>
+<span class="source-line-no">2008</span><span id="line-2008"> return totalSize - bucketSize;</span>
+<span class="source-line-no">2009</span><span id="line-2009"> }</span>
+<span class="source-line-no">2010</span><span id="line-2010"></span>
+<span class="source-line-no">2011</span><span id="line-2011"> public long totalSize() {</span>
+<span class="source-line-no">2012</span><span id="line-2012"> return totalSize;</span>
+<span class="source-line-no">2013</span><span id="line-2013"> }</span>
+<span class="source-line-no">2014</span><span id="line-2014"> }</span>
+<span class="source-line-no">2015</span><span id="line-2015"></span>
+<span class="source-line-no">2016</span><span id="line-2016"> /**</span>
+<span class="source-line-no">2017</span><span id="line-2017"> * Block Entry stored in the memory with key,data and so on</span>
+<span class="source-line-no">2018</span><span id="line-2018"> */</span>
+<span class="source-line-no">2019</span><span id="line-2019"> static class RAMQueueEntry {</span>
+<span class="source-line-no">2020</span><span id="line-2020"> private final BlockCacheKey key;</span>
+<span class="source-line-no">2021</span><span id="line-2021"> private final Cacheable data;</span>
+<span class="source-line-no">2022</span><span id="line-2022"> private long accessCounter;</span>
+<span class="source-line-no">2023</span><span id="line-2023"> private boolean inMemory;</span>
+<span class="source-line-no">2024</span><span id="line-2024"> private boolean isCachePersistent;</span>
+<span class="source-line-no">2025</span><span id="line-2025"></span>
+<span class="source-line-no">2026</span><span id="line-2026"> private boolean isPrefetch;</span>
<span class="source-line-no">2027</span><span id="line-2027"></span>
-<span class="source-line-no">2028</span><span id="line-2028"> public BlockCacheKey getKey() {</span>
-<span class="source-line-no">2029</span><span id="line-2029"> return key;</span>
-<span class="source-line-no">2030</span><span id="line-2030"> }</span>
-<span class="source-line-no">2031</span><span id="line-2031"></span>
-<span class="source-line-no">2032</span><span id="line-2032"> public boolean isPrefetch() {</span>
-<span class="source-line-no">2033</span><span id="line-2033"> return isPrefetch;</span>
-<span class="source-line-no">2034</span><span id="line-2034"> }</span>
-<span class="source-line-no">2035</span><span id="line-2035"></span>
-<span class="source-line-no">2036</span><span id="line-2036"> public void access(long accessCounter) {</span>
-<span class="source-line-no">2037</span><span id="line-2037"> this.accessCounter = accessCounter;</span>
-<span class="source-line-no">2038</span><span id="line-2038"> }</span>
-<span class="source-line-no">2039</span><span id="line-2039"></span>
-<span class="source-line-no">2040</span><span id="line-2040"> private ByteBuffAllocator getByteBuffAllocator() {</span>
-<span class="source-line-no">2041</span><span id="line-2041"> if (data instanceof HFileBlock) {</span>
-<span class="source-line-no">2042</span><span id="line-2042"> return ((HFileBlock) data).getByteBuffAllocator();</span>
-<span class="source-line-no">2043</span><span id="line-2043"> }</span>
-<span class="source-line-no">2044</span><span id="line-2044"> return ByteBuffAllocator.HEAP;</span>
-<span class="source-line-no">2045</span><span id="line-2045"> }</span>
-<span class="source-line-no">2046</span><span id="line-2046"></span>
-<span class="source-line-no">2047</span><span id="line-2047"> public BucketEntry writeToCache(final IOEngine ioEngine, final BucketAllocator alloc,</span>
-<span class="source-line-no">2048</span><span id="line-2048"> final LongAdder realCacheSize, Function<BucketEntry, Recycler> createRecycler,</span>
-<span class="source-line-no">2049</span><span id="line-2049"> ByteBuffer metaBuff, final Long acceptableSize) throws IOException {</span>
-<span class="source-line-no">2050</span><span id="line-2050"> int len = data.getSerializedLength();</span>
-<span class="source-line-no">2051</span><span id="line-2051"> // This cacheable thing can't be serialized</span>
-<span class="source-line-no">2052</span><span id="line-2052"> if (len == 0) {</span>
-<span class="source-line-no">2053</span><span id="line-2053"> return null;</span>
-<span class="source-line-no">2054</span><span id="line-2054"> }</span>
-<span class="source-line-no">2055</span><span id="line-2055"> if (isCachePersistent && data instanceof HFileBlock) {</span>
-<span class="source-line-no">2056</span><span id="line-2056"> len += Long.BYTES; // we need to record the cache time for consistency check in case of</span>
-<span class="source-line-no">2057</span><span id="line-2057"> // recovery</span>
-<span class="source-line-no">2058</span><span id="line-2058"> }</span>
-<span class="source-line-no">2059</span><span id="line-2059"> long offset = alloc.allocateBlock(len);</span>
-<span class="source-line-no">2060</span><span id="line-2060"> // In the case of prefetch, we want to avoid freeSpace runs when the cache is full.</span>
-<span class="source-line-no">2061</span><span id="line-2061"> // this makes the cache allocation more predictable, and is particularly important</span>
-<span class="source-line-no">2062</span><span id="line-2062"> // when persistent cache is enabled, as it won't trigger evictions of the recovered blocks,</span>
-<span class="source-line-no">2063</span><span id="line-2063"> // which are likely the most accessed and relevant blocks in the cache.</span>
-<span class="source-line-no">2064</span><span id="line-2064"> if (isPrefetch() && alloc.getUsedSize() > acceptableSize) {</span>
-<span class="source-line-no">2065</span><span id="line-2065"> alloc.freeBlock(offset, len);</span>
-<span class="source-line-no">2066</span><span id="line-2066"> return null;</span>
-<span class="source-line-no">2067</span><span id="line-2067"> }</span>
-<span class="source-line-no">2068</span><span id="line-2068"> boolean succ = false;</span>
-<span class="source-line-no">2069</span><span id="line-2069"> BucketEntry bucketEntry = null;</span>
-<span class="source-line-no">2070</span><span id="line-2070"> try {</span>
-<span class="source-line-no">2071</span><span id="line-2071"> int diskSizeWithHeader = (data instanceof HFileBlock)</span>
-<span class="source-line-no">2072</span><span id="line-2072"> ? ((HFileBlock) data).getOnDiskSizeWithHeader()</span>
-<span class="source-line-no">2073</span><span id="line-2073"> : data.getSerializedLength();</span>
-<span class="source-line-no">2074</span><span id="line-2074"> bucketEntry = new BucketEntry(offset, len, diskSizeWithHeader, accessCounter, inMemory,</span>
-<span class="source-line-no">2075</span><span id="line-2075"> createRecycler, getByteBuffAllocator());</span>
-<span class="source-line-no">2076</span><span id="line-2076"> bucketEntry.setDeserializerReference(data.getDeserializer());</span>
-<span class="source-line-no">2077</span><span id="line-2077"> if (data instanceof HFileBlock) {</span>
-<span class="source-line-no">2078</span><span id="line-2078"> // If an instance of HFileBlock, save on some allocations.</span>
-<span class="source-line-no">2079</span><span id="line-2079"> HFileBlock block = (HFileBlock) data;</span>
-<span class="source-line-no">2080</span><span id="line-2080"> ByteBuff sliceBuf = block.getBufferReadOnly();</span>
-<span class="source-line-no">2081</span><span id="line-2081"> block.getMetaData(metaBuff);</span>
-<span class="source-line-no">2082</span><span id="line-2082"> // adds the cache time prior to the block and metadata part</span>
-<span class="source-line-no">2083</span><span id="line-2083"> if (isCachePersistent) {</span>
-<span class="source-line-no">2084</span><span id="line-2084"> ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);</span>
-<span class="source-line-no">2085</span><span id="line-2085"> buffer.putLong(bucketEntry.getCachedTime());</span>
-<span class="source-line-no">2086</span><span id="line-2086"> buffer.rewind();</span>
-<span class="source-line-no">2087</span><span id="line-2087"> ioEngine.write(buffer, offset);</span>
-<span class="source-line-no">2088</span><span id="line-2088"> ioEngine.write(sliceBuf, (offset + Long.BYTES));</span>
-<span class="source-line-no">2089</span><span id="line-2089"> } else {</span>
-<span class="source-line-no">2090</span><span id="line-2090"> ioEngine.write(sliceBuf, offset);</span>
-<span class="source-line-no">2091</span><span id="line-2091"> }</span>
-<span class="source-line-no">2092</span><span id="line-2092"> ioEngine.write(metaBuff, offset + len - metaBuff.limit());</span>
-<span class="source-line-no">2093</span><span id="line-2093"> } else {</span>
-<span class="source-line-no">2094</span><span id="line-2094"> // Only used for testing.</span>
-<span class="source-line-no">2095</span><span id="line-2095"> ByteBuffer bb = ByteBuffer.allocate(len);</span>
-<span class="source-line-no">2096</span><span id="line-2096"> data.serialize(bb, true);</span>
-<span class="source-line-no">2097</span><span id="line-2097"> ioEngine.write(bb, offset);</span>
-<span class="source-line-no">2098</span><span id="line-2098"> }</span>
-<span class="source-line-no">2099</span><span id="line-2099"> succ = true;</span>
-<span class="source-line-no">2100</span><span id="line-2100"> } finally {</span>
-<span class="source-line-no">2101</span><span id="line-2101"> if (!succ) {</span>
-<span class="source-line-no">2102</span><span id="line-2102"> alloc.freeBlock(offset, len);</span>
-<span class="source-line-no">2103</span><span id="line-2103"> }</span>
-<span class="source-line-no">2104</span><span id="line-2104"> }</span>
-<span class="source-line-no">2105</span><span id="line-2105"> realCacheSize.add(len);</span>
-<span class="source-line-no">2106</span><span id="line-2106"> return bucketEntry;</span>
-<span class="source-line-no">2107</span><span id="line-2107"> }</span>
-<span class="source-line-no">2108</span><span id="line-2108"> }</span>
-<span class="source-line-no">2109</span><span id="line-2109"></span>
-<span class="source-line-no">2110</span><span id="line-2110"> /**</span>
-<span class="source-line-no">2111</span><span id="line-2111"> * Only used in test</span>
-<span class="source-line-no">2112</span><span id="line-2112"> */</span>
-<span class="source-line-no">2113</span><span id="line-2113"> void stopWriterThreads() throws InterruptedException {</span>
-<span class="source-line-no">2114</span><span id="line-2114"> for (WriterThread writerThread : writerThreads) {</span>
-<span class="source-line-no">2115</span><span id="line-2115"> writerThread.disableWriter();</span>
-<span class="source-line-no">2116</span><span id="line-2116"> writerThread.interrupt();</span>
-<span class="source-line-no">2117</span><span id="line-2117"> writerThread.join();</span>
-<span class="source-line-no">2118</span><span id="line-2118"> }</span>
-<span class="source-line-no">2119</span><span id="line-2119"> }</span>
-<span class="source-line-no">2120</span><span id="line-2120"></span>
-<span class="source-line-no">2121</span><span id="line-2121"> @Override</span>
-<span class="source-line-no">2122</span><span id="line-2122"> public Iterator<CachedBlock> iterator() {</span>
-<span class="source-line-no">2123</span><span id="line-2123"> // Don't bother with ramcache since stuff is in here only a little while.</span>
-<span class="source-line-no">2124</span><span id="line-2124"> final Iterator<Map.Entry<BlockCacheKey, BucketEntry>> i = this.backingMap.entrySet().iterator();</span>
-<span class="source-line-no">2125</span><span id="line-2125"> return new Iterator<CachedBlock>() {</span>
-<span class="source-line-no">2126</span><span id="line-2126"> private final long now = System.nanoTime();</span>
-<span class="source-line-no">2127</span><span id="line-2127"></span>
-<span class="source-line-no">2128</span><span id="line-2128"> @Override</span>
-<span class="source-line-no">2129</span><span id="line-2129"> public boolean hasNext() {</span>
-<span class="source-line-no">2130</span><span id="line-2130"> return i.hasNext();</span>
-<span class="source-line-no">2131</span><span id="line-2131"> }</span>
-<span class="source-line-no">2132</span><span id="line-2132"></span>
-<span class="source-line-no">2133</span><span id="line-2133"> @Override</span>
-<span class="source-line-no">2134</span><span id="line-2134"> public CachedBlock next() {</span>
-<span class="source-line-no">2135</span><span id="line-2135"> final Map.Entry<BlockCacheKey, BucketEntry> e = i.next();</span>
-<span class="source-line-no">2136</span><span id="line-2136"> return new CachedBlock() {</span>
-<span class="source-line-no">2137</span><span id="line-2137"> @Override</span>
-<span class="source-line-no">2138</span><span id="line-2138"> public String toString() {</span>
-<span class="source-line-no">2139</span><span id="line-2139"> return BlockCacheUtil.toString(this, now);</span>
-<span class="source-line-no">2140</span><span id="line-2140"> }</span>
+<span class="source-line-no">2028</span><span id="line-2028"> RAMQueueEntry(BlockCacheKey bck, Cacheable data, long accessCounter, boolean inMemory,</span>
+<span class="source-line-no">2029</span><span id="line-2029"> boolean isCachePersistent, boolean isPrefetch) {</span>
+<span class="source-line-no">2030</span><span id="line-2030"> this.key = bck;</span>
+<span class="source-line-no">2031</span><span id="line-2031"> this.data = data;</span>
+<span class="source-line-no">2032</span><span id="line-2032"> this.accessCounter = accessCounter;</span>
+<span class="source-line-no">2033</span><span id="line-2033"> this.inMemory = inMemory;</span>
+<span class="source-line-no">2034</span><span id="line-2034"> this.isCachePersistent = isCachePersistent;</span>
+<span class="source-line-no">2035</span><span id="line-2035"> this.isPrefetch = isPrefetch;</span>
+<span class="source-line-no">2036</span><span id="line-2036"> }</span>
+<span class="source-line-no">2037</span><span id="line-2037"></span>
+<span class="source-line-no">2038</span><span id="line-2038"> public Cacheable getData() {</span>
+<span class="source-line-no">2039</span><span id="line-2039"> return data;</span>
+<span class="source-line-no">2040</span><span id="line-2040"> }</span>
+<span class="source-line-no">2041</span><span id="line-2041"></span>
+<span class="source-line-no">2042</span><span id="line-2042"> public BlockCacheKey getKey() {</span>
+<span class="source-line-no">2043</span><span id="line-2043"> return key;</span>
+<span class="source-line-no">2044</span><span id="line-2044"> }</span>
+<span class="source-line-no">2045</span><span id="line-2045"></span>
+<span class="source-line-no">2046</span><span id="line-2046"> public boolean isPrefetch() {</span>
+<span class="source-line-no">2047</span><span id="line-2047"> return isPrefetch;</span>
+<span class="source-line-no">2048</span><span id="line-2048"> }</span>
+<span class="source-line-no">2049</span><span id="line-2049"></span>
+<span class="source-line-no">2050</span><span id="line-2050"> public void access(long accessCounter) {</span>
+<span class="source-line-no">2051</span><span id="line-2051"> this.accessCounter = accessCounter;</span>
+<span class="source-line-no">2052</span><span id="line-2052"> }</span>
+<span class="source-line-no">2053</span><span id="line-2053"></span>
+<span class="source-line-no">2054</span><span id="line-2054"> private ByteBuffAllocator getByteBuffAllocator() {</span>
+<span class="source-line-no">2055</span><span id="line-2055"> if (data instanceof HFileBlock) {</span>
+<span class="source-line-no">2056</span><span id="line-2056"> return ((HFileBlock) data).getByteBuffAllocator();</span>
+<span class="source-line-no">2057</span><span id="line-2057"> }</span>
+<span class="source-line-no">2058</span><span id="line-2058"> return ByteBuffAllocator.HEAP;</span>
+<span class="source-line-no">2059</span><span id="line-2059"> }</span>
+<span class="source-line-no">2060</span><span id="line-2060"></span>
+<span class="source-line-no">2061</span><span id="line-2061"> public BucketEntry writeToCache(final IOEngine ioEngine, final BucketAllocator alloc,</span>
+<span class="source-line-no">2062</span><span id="line-2062"> final LongAdder realCacheSize, Function<BucketEntry, Recycler> createRecycler,</span>
+<span class="source-line-no">2063</span><span id="line-2063"> ByteBuffer metaBuff, final Long acceptableSize) throws IOException {</span>
+<span class="source-line-no">2064</span><span id="line-2064"> int len = data.getSerializedLength();</span>
+<span class="source-line-no">2065</span><span id="line-2065"> // This cacheable thing can't be serialized</span>
+<span class="source-line-no">2066</span><span id="line-2066"> if (len == 0) {</span>
+<span class="source-line-no">2067</span><span id="line-2067"> return null;</span>
+<span class="source-line-no">2068</span><span id="line-2068"> }</span>
+<span class="source-line-no">2069</span><span id="line-2069"> if (isCachePersistent && data instanceof HFileBlock) {</span>
+<span class="source-line-no">2070</span><span id="line-2070"> len += Long.BYTES; // we need to record the cache time for consistency check in case of</span>
+<span class="source-line-no">2071</span><span id="line-2071"> // recovery</span>
+<span class="source-line-no">2072</span><span id="line-2072"> }</span>
+<span class="source-line-no">2073</span><span id="line-2073"> long offset = alloc.allocateBlock(len);</span>
+<span class="source-line-no">2074</span><span id="line-2074"> // In the case of prefetch, we want to avoid freeSpace runs when the cache is full.</span>
+<span class="source-line-no">2075</span><span id="line-2075"> // this makes the cache allocation more predictable, and is particularly important</span>
+<span class="source-line-no">2076</span><span id="line-2076"> // when persistent cache is enabled, as it won't trigger evictions of the recovered blocks,</span>
+<span class="source-line-no">2077</span><span id="line-2077"> // which are likely the most accessed and relevant blocks in the cache.</span>
+<span class="source-line-no">2078</span><span id="line-2078"> if (isPrefetch() && alloc.getUsedSize() > acceptableSize) {</span>
+<span class="source-line-no">2079</span><span id="line-2079"> alloc.freeBlock(offset, len);</span>
+<span class="source-line-no">2080</span><span id="line-2080"> return null;</span>
+<span class="source-line-no">2081</span><span id="line-2081"> }</span>
+<span class="source-line-no">2082</span><span id="line-2082"> boolean succ = false;</span>
+<span class="source-line-no">2083</span><span id="line-2083"> BucketEntry bucketEntry = null;</span>
+<span class="source-line-no">2084</span><span id="line-2084"> try {</span>
+<span class="source-line-no">2085</span><span id="line-2085"> int diskSizeWithHeader = (data instanceof HFileBlock)</span>
+<span class="source-line-no">2086</span><span id="line-2086"> ? ((HFileBlock) data).getOnDiskSizeWithHeader()</span>
+<span class="source-line-no">2087</span><span id="line-2087"> : data.getSerializedLength();</span>
+<span class="source-line-no">2088</span><span id="line-2088"> bucketEntry = new BucketEntry(offset, len, diskSizeWithHeader, accessCounter, inMemory,</span>
+<span class="source-line-no">2089</span><span id="line-2089"> createRecycler, getByteBuffAllocator());</span>
+<span class="source-line-no">2090</span><span id="line-2090"> bucketEntry.setDeserializerReference(data.getDeserializer());</span>
+<span class="source-line-no">2091</span><span id="line-2091"> if (data instanceof HFileBlock) {</span>
+<span class="source-line-no">2092</span><span id="line-2092"> // If an instance of HFileBlock, save on some allocations.</span>
+<span class="source-line-no">2093</span><span id="line-2093"> HFileBlock block = (HFileBlock) data;</span>
+<span class="source-line-no">2094</span><span id="line-2094"> ByteBuff sliceBuf = block.getBufferReadOnly();</span>
+<span class="source-line-no">2095</span><span id="line-2095"> block.getMetaData(metaBuff);</span>
+<span class="source-line-no">2096</span><span id="line-2096"> // adds the cache time prior to the block and metadata part</span>
+<span class="source-line-no">2097</span><span id="line-2097"> if (isCachePersistent) {</span>
+<span class="source-line-no">2098</span><span id="line-2098"> ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);</span>
+<span class="source-line-no">2099</span><span id="line-2099"> buffer.putLong(bucketEntry.getCachedTime());</span>
+<span class="source-line-no">2100</span><span id="line-2100"> buffer.rewind();</span>
+<span class="source-line-no">2101</span><span id="line-2101"> ioEngine.write(buffer, offset);</span>
+<span class="source-line-no">2102</span><span id="line-2102"> ioEngine.write(sliceBuf, (offset + Long.BYTES));</span>
+<span class="source-line-no">2103</span><span id="line-2103"> } else {</span>
+<span class="source-line-no">2104</span><span id="line-2104"> ioEngine.write(sliceBuf, offset);</span>
+<span class="source-line-no">2105</span><span id="line-2105"> }</span>
+<span class="source-line-no">2106</span><span id="line-2106"> ioEngine.write(metaBuff, offset + len - metaBuff.limit());</span>
+<span class="source-line-no">2107</span><span id="line-2107"> } else {</span>
+<span class="source-line-no">2108</span><span id="line-2108"> // Only used for testing.</span>
+<span class="source-line-no">2109</span><span id="line-2109"> ByteBuffer bb = ByteBuffer.allocate(len);</span>
+<span class="source-line-no">2110</span><span id="line-2110"> data.serialize(bb, true);</span>
+<span class="source-line-no">2111</span><span id="line-2111"> ioEngine.write(bb, offset);</span>
+<span class="source-line-no">2112</span><span id="line-2112"> }</span>
+<span class="source-line-no">2113</span><span id="line-2113"> succ = true;</span>
+<span class="source-line-no">2114</span><span id="line-2114"> } finally {</span>
+<span class="source-line-no">2115</span><span id="line-2115"> if (!succ) {</span>
+<span class="source-line-no">2116</span><span id="line-2116"> alloc.freeBlock(offset, len);</span>
+<span class="source-line-no">2117</span><span id="line-2117"> }</span>
+<span class="source-line-no">2118</span><span id="line-2118"> }</span>
+<span class="source-line-no">2119</span><span id="line-2119"> realCacheSize.add(len);</span>
+<span class="source-line-no">2120</span><span id="line-2120"> return bucketEntry;</span>
+<span class="source-line-no">2121</span><span id="line-2121"> }</span>
+<span class="source-line-no">2122</span><span id="line-2122"> }</span>
+<span class="source-line-no">2123</span><span id="line-2123"></span>
+<span class="source-line-no">2124</span><span id="line-2124"> /**</span>
+<span class="source-line-no">2125</span><span id="line-2125"> * Only used in test</span>
+<span class="source-line-no">2126</span><span id="line-2126"> */</span>
+<span class="source-line-no">2127</span><span id="line-2127"> void stopWriterThreads() throws InterruptedException {</span>
+<span class="source-line-no">2128</span><span id="line-2128"> for (WriterThread writerThread : writerThreads) {</span>
+<span class="source-line-no">2129</span><span id="line-2129"> writerThread.disableWriter();</span>
+<span class="source-line-no">2130</span><span id="line-2130"> writerThread.interrupt();</span>
+<span class="source-line-no">2131</span><span id="line-2131"> writerThread.join();</span>
+<span class="source-line-no">2132</span><span id="line-2132"> }</span>
+<span class="source-line-no">2133</span><span id="line-2133"> }</span>
+<span class="source-line-no">2134</span><span id="line-2134"></span>
+<span class="source-line-no">2135</span><span id="line-2135"> @Override</span>
+<span class="source-line-no">2136</span><span id="line-2136"> public Iterator<CachedBlock> iterator() {</span>
+<span class="source-line-no">2137</span><span id="line-2137"> // Don't bother with ramcache since stuff is in here only a little while.</span>
+<span class="source-line-no">2138</span><span id="line-2138"> final Iterator<Map.Entry<BlockCacheKey, BucketEntry>> i = this.backingMap.entrySet().iterator();</span>
+<span class="source-line-no">2139</span><span id="line-2139"> return new Iterator<CachedBlock>() {</span>
+<span class="source-line-no">2140</span><span id="line-2140"> private final long now = System.nanoTime();</span>
<span class="source-line-no">2141</span><span id="line-2141"></span>
-<span class="source-line-no">2142</span><span id="line-2142"> @Override</span>
-<span class="source-line-no">2143</span><span id="line-2143"> public BlockPriority getBlockPriority() {</span>
-<span class="source-line-no">2144</span><span id="line-2144"> return e.getValue().getPriority();</span>
-<span class="source-line-no">2145</span><span id="line-2145"> }</span>
+<span class="source-line-no">2142</span><span id="line-2142"> @Override</span>
+<span class="source-line-no">2143</span><span id="line-2143"> public boolean hasNext() {</span>
+<span class="source-line-no">2144</span><span id="line-2144"> return i.hasNext();</span>
+<span class="source-line-no">2145</span><span id="line-2145"> }</span>
<span class="source-line-no">2146</span><span id="line-2146"></span>
-<span class="source-line-no">2147</span><span id="line-2147"> @Override</span>
-<span class="source-line-no">2148</span><span id="line-2148"> public BlockType getBlockType() {</span>
-<span class="source-line-no">2149</span><span id="line-2149"> // Not held by BucketEntry. Could add it if wanted on BucketEntry creation.</span>
-<span class="source-line-no">2150</span><span id="line-2150"> return null;</span>
-<span class="source-line-no">2151</span><span id="line-2151"> }</span>
-<span class="source-line-no">2152</span><span id="line-2152"></span>
-<span class="source-line-no">2153</span><span id="line-2153"> @Override</span>
-<span class="source-line-no">2154</span><span id="line-2154"> public long getOffset() {</span>
-<span class="source-line-no">2155</span><span id="line-2155"> return e.getKey().getOffset();</span>
-<span class="source-line-no">2156</span><span id="line-2156"> }</span>
-<span class="source-line-no">2157</span><span id="line-2157"></span>
-<span class="source-line-no">2158</span><span id="line-2158"> @Override</span>
-<span class="source-line-no">2159</span><span id="line-2159"> public long getSize() {</span>
-<span class="source-line-no">2160</span><span id="line-2160"> return e.getValue().getLength();</span>
-<span class="source-line-no">2161</span><span id="line-2161"> }</span>
-<span class="source-line-no">2162</span><span id="line-2162"></span>
-<span class="source-line-no">2163</span><span id="line-2163"> @Override</span>
-<span class="source-line-no">2164</span><span id="line-2164"> public long getCachedTime() {</span>
-<span class="source-line-no">2165</span><span id="line-2165"> return e.getValue().getCachedTime();</span>
-<span class="source-line-no">2166</span><span id="line-2166"> }</span>
-<span class="source-line-no">2167</span><span id="line-2167"></span>
-<span class="source-line-no">2168</span><span id="line-2168"> @Override</span>
-<span class="source-line-no">2169</span><span id="line-2169"> public String getFilename() {</span>
-<span class="source-line-no">2170</span><span id="line-2170"> return e.getKey().getHfileName();</span>
-<span class="source-line-no">2171</span><span id="line-2171"> }</span>
-<span class="source-line-no">2172</span><span id="line-2172"></span>
-<span class="source-line-no">2173</span><span id="line-2173"> @Override</span>
-<span class="source-line-no">2174</span><span id="line-2174"> public int compareTo(CachedBlock other) {</span>
-<span class="source-line-no">2175</span><span id="line-2175"> int diff = this.getFilename().compareTo(other.getFilename());</span>
-<span class="source-line-no">2176</span><span id="line-2176"> if (diff != 0) return diff;</span>
-<span class="source-line-no">2177</span><span id="line-2177"></span>
-<span class="source-line-no">2178</span><span id="line-2178"> diff = Long.compare(this.getOffset(), other.getOffset());</span>
-<span class="source-line-no">2179</span><span id="line-2179"> if (diff != 0) return diff;</span>
-<span class="source-line-no">2180</span><span id="line-2180"> if (other.getCachedTime() < 0 || this.getCachedTime() < 0) {</span>
-<span class="source-line-no">2181</span><span id="line-2181"> throw new IllegalStateException(</span>
-<span class="source-line-no">2182</span><span id="line-2182"> "" + this.getCachedTime() + ", " + other.getCachedTime());</span>
-<span class="source-line-no">2183</span><span id="line-2183"> }</span>
-<span class="source-line-no">2184</span><span id="line-2184"> return Long.compare(other.getCachedTime(), this.getCachedTime());</span>
+<span class="source-line-no">2147</span><span id="line-2147"> @Override</span>
+<span class="source-line-no">2148</span><span id="line-2148"> public CachedBlock next() {</span>
+<span class="source-line-no">2149</span><span id="line-2149"> final Map.Entry<BlockCacheKey, BucketEntry> e = i.next();</span>
+<span class="source-line-no">2150</span><span id="line-2150"> return new CachedBlock() {</span>
+<span class="source-line-no">2151</span><span id="line-2151"> @Override</span>
+<span class="source-line-no">2152</span><span id="line-2152"> public String toString() {</span>
+<span class="source-line-no">2153</span><span id="line-2153"> return BlockCacheUtil.toString(this, now);</span>
+<span class="source-line-no">2154</span><span id="line-2154"> }</span>
+<span class="source-line-no">2155</span><span id="line-2155"></span>
+<span class="source-line-no">2156</span><span id="line-2156"> @Override</span>
+<span class="source-line-no">2157</span><span id="line-2157"> public BlockPriority getBlockPriority() {</span>
+<span class="source-line-no">2158</span><span id="line-2158"> return e.getValue().getPriority();</span>
+<span class="source-line-no">2159</span><span id="line-2159"> }</span>
+<span class="source-line-no">2160</span><span id="line-2160"></span>
+<span class="source-line-no">2161</span><span id="line-2161"> @Override</span>
+<span class="source-line-no">2162</span><span id="line-2162"> public BlockType getBlockType() {</span>
+<span class="source-line-no">2163</span><span id="line-2163"> // Not held by BucketEntry. Could add it if wanted on BucketEntry creation.</span>
+<span class="source-line-no">2164</span><span id="line-2164"> return null;</span>
+<span class="source-line-no">2165</span><span id="line-2165"> }</span>
+<span class="source-line-no">2166</span><span id="line-2166"></span>
+<span class="source-line-no">2167</span><span id="line-2167"> @Override</span>
+<span class="source-line-no">2168</span><span id="line-2168"> public long getOffset() {</span>
+<span class="source-line-no">2169</span><span id="line-2169"> return e.getKey().getOffset();</span>
+<span class="source-line-no">2170</span><span id="line-2170"> }</span>
+<span class="source-line-no">2171</span><span id="line-2171"></span>
+<span class="source-line-no">2172</span><span id="line-2172"> @Override</span>
+<span class="source-line-no">2173</span><span id="line-2173"> public long getSize() {</span>
+<span class="source-line-no">2174</span><span id="line-2174"> return e.getValue().getLength();</span>
+<span class="source-line-no">2175</span><span id="line-2175"> }</span>
+<span class="source-line-no">2176</span><span id="line-2176"></span>
+<span class="source-line-no">2177</span><span id="line-2177"> @Override</span>
+<span class="source-line-no">2178</span><span id="line-2178"> public long getCachedTime() {</span>
+<span class="source-line-no">2179</span><span id="line-2179"> return e.getValue().getCachedTime();</span>
+<span class="source-line-no">2180</span><span id="line-2180"> }</span>
+<span class="source-line-no">2181</span><span id="line-2181"></span>
+<span class="source-line-no">2182</span><span id="line-2182"> @Override</span>
+<span class="source-line-no">2183</span><span id="line-2183"> public String getFilename() {</span>
+<span class="source-line-no">2184</span><span id="line-2184"> return e.getKey().getHfileName();</span>
<span class="source-line-no">2185</span><span id="line-2185"> }</span>
<span class="source-line-no">2186</span><span id="line-2186"></span>
<span class="source-line-no">2187</span><span id="line-2187"> @Override</span>
-<span class="source-line-no">2188</span><span id="line-2188"> public int hashCode() {</span>
-<span class="source-line-no">2189</span><span id="line-2189"> return e.getKey().hashCode();</span>
-<span class="source-line-no">2190</span><span id="line-2190"> }</span>
+<span class="source-line-no">2188</span><span id="line-2188"> public int compareTo(CachedBlock other) {</span>
+<span class="source-line-no">2189</span><span id="line-2189"> int diff = this.getFilename().compareTo(other.getFilename());</span>
+<span class="source-line-no">2190</span><span id="line-2190"> if (diff != 0) return diff;</span>
<span class="source-line-no">2191</span><span id="line-2191"></span>
-<span class="source-line-no">2192</span><span id="line-2192"> @Override</span>
-<span class="source-line-no">2193</span><span id="line-2193"> public boolean equals(Object obj) {</span>
-<span class="source-line-no">2194</span><span id="line-2194"> if (obj instanceof CachedBlock) {</span>
-<span class="source-line-no">2195</span><span id="line-2195"> CachedBlock cb = (CachedBlock) obj;</span>
-<span class="source-line-no">2196</span><span id="line-2196"> return compareTo(cb) == 0;</span>
-<span class="source-line-no">2197</span><span id="line-2197"> } else {</span>
-<span class="source-line-no">2198</span><span id="line-2198"> return false;</span>
-<span class="source-line-no">2199</span><span id="line-2199"> }</span>
-<span class="source-line-no">2200</span><span id="line-2200"> }</span>
-<span class="source-line-no">2201</span><span id="line-2201"> };</span>
-<span class="source-line-no">2202</span><span id="line-2202"> }</span>
-<span class="source-line-no">2203</span><span id="line-2203"></span>
-<span class="source-line-no">2204</span><span id="line-2204"> @Override</span>
-<span class="source-line-no">2205</span><span id="line-2205"> public void remove() {</span>
-<span class="source-line-no">2206</span><span id="line-2206"> throw new UnsupportedOperationException();</span>
-<span class="source-line-no">2207</span><span id="line-2207"> }</span>
-<span class="source-line-no">2208</span><span id="line-2208"> };</span>
-<span class="source-line-no">2209</span><span id="line-2209"> }</span>
-<span class="source-line-no">2210</span><span id="line-2210"></span>
-<span class="source-line-no">2211</span><span id="line-2211"> @Override</span>
-<span class="source-line-no">2212</span><span id="line-2212"> public BlockCache[] getBlockCaches() {</span>
-<span class="source-line-no">2213</span><span id="line-2213"> return null;</span>
-<span class="source-line-no">2214</span><span id="line-2214"> }</span>
-<span class="source-line-no">2215</span><span id="line-2215"></span>
-<span class="source-line-no">2216</span><span id="line-2216"> public int getRpcRefCount(BlockCacheKey cacheKey) {</span>
-<span class="source-line-no">2217</span><span id="line-2217"> BucketEntry bucketEntry = backingMap.get(cacheKey);</span>
-<span class="source-line-no">2218</span><span id="line-2218"> if (bucketEntry != null) {</span>
-<span class="source-line-no">2219</span><span id="line-2219"> return bucketEntry.refCnt() - (bucketEntry.markedAsEvicted.get() ? 0 : 1);</span>
-<span class="source-line-no">2220</span><span id="line-2220"> }</span>
-<span class="source-line-no">2221</span><span id="line-2221"> return 0;</span>
-<span class="source-line-no">2222</span><span id="line-2222"> }</span>
-<span class="source-line-no">2223</span><span id="line-2223"></span>
-<span class="source-line-no">2224</span><span id="line-2224"> float getAcceptableFactor() {</span>
-<span class="source-line-no">2225</span><span id="line-2225"> return acceptableFactor;</span>
-<span class="source-line-no">2226</span><span id="line-2226"> }</span>
-<span class="source-line-no">2227</span><span id="line-2227"></span>
-<span class="source-line-no">2228</span><span id="line-2228"> float getMinFactor() {</span>
-<span class="source-line-no">2229</span><span id="line-2229"> return minFactor;</span>
-<span class="source-line-no">2230</span><span id="line-2230"> }</span>
-<span class="source-line-no">2231</span><span id="line-2231"></span>
-<span class="source-line-no">2232</span><span id="line-2232"> float getExtraFreeFactor() {</span>
-<span class="source-line-no">2233</span><span id="line-2233"> return extraFreeFactor;</span>
-<span class="source-line-no">2234</span><span id="line-2234"> }</span>
-<span class="source-line-no">2235</span><span id="line-2235"></span>
-<span class="source-line-no">2236</span><span id="line-2236"> float getSingleFactor() {</span>
-<span class="source-line-no">2237</span><span id="line-2237"> return singleFactor;</span>
-<span class="source-line-no">2238</span><span id="line-2238"> }</span>
-<span class="source-line-no">2239</span><span id="line-2239"></span>
-<span class="source-line-no">2240</span><span id="line-2240"> float getMultiFactor() {</span>
-<span class="source-line-no">2241</span><span id="line-2241"> return multiFactor;</span>
-<span class="source-line-no">2242</span><span id="line-2242"> }</span>
-<span class="source-line-no">2243</span><span id="line-2243"></span>
-<span class="source-line-no">2244</span><span id="line-2244"> float getMemoryFactor() {</span>
-<span class="source-line-no">2245</span><span id="line-2245"> return memoryFactor;</span>
-<span class="source-line-no">2246</span><span id="line-2246"> }</span>
-<span class="source-line-no">2247</span><span id="line-2247"></span>
-<span class="source-line-no">2248</span><span id="line-2248"> long getQueueAdditionWaitTime() {</span>
-<span class="source-line-no">2249</span><span id="line-2249"> return queueAdditionWaitTime;</span>
-<span class="source-line-no">2250</span><span id="line-2250"> }</span>
-<span class="source-line-no">2251</span><span id="line-2251"></span>
-<span class="source-line-no">2252</span><span id="line-2252"> long getPersistenceChunkSize() {</span>
-<span class="source-line-no">2253</span><span id="line-2253"> return persistenceChunkSize;</span>
-<span class="source-line-no">2254</span><span id="line-2254"> }</span>
-<span class="source-line-no">2255</span><span id="line-2255"></span>
-<span class="source-line-no">2256</span><span id="line-2256"> long getBucketcachePersistInterval() {</span>
-<span class="source-line-no">2257</span><span id="line-2257"> return bucketcachePersistInterval;</span>
-<span class="source-line-no">2258</span><span id="line-2258"> }</span>
-<span class="source-line-no">2259</span><span id="line-2259"></span>
-<span class="source-line-no">2260</span><span id="line-2260"> public String getPersistencePath() {</span>
-<span class="source-line-no">2261</span><span id="line-2261"> return persistencePath;</span>
-<span class="source-line-no">2262</span><span id="line-2262"> }</span>
-<span class="source-line-no">2263</span><span id="line-2263"></span>
-<span class="source-line-no">2264</span><span id="line-2264"> /**</span>
-<span class="source-line-no">2265</span><span id="line-2265"> * Wrapped the delegate ConcurrentMap with maintaining its block's reference count.</span>
-<span class="source-line-no">2266</span><span id="line-2266"> */</span>
-<span class="source-line-no">2267</span><span id="line-2267"> static class RAMCache {</span>
-<span class="source-line-no">2268</span><span id="line-2268"> /**</span>
-<span class="source-line-no">2269</span><span id="line-2269"> * Defined the map as {@link ConcurrentHashMap} explicitly here, because in</span>
-<span class="source-line-no">2270</span><span id="line-2270"> * {@link RAMCache#get(BlockCacheKey)} and</span>
-<span class="source-line-no">2271</span><span id="line-2271"> * {@link RAMCache#putIfAbsent(BlockCacheKey, BucketCache.RAMQueueEntry)} , we need to guarantee</span>
-<span class="source-line-no">2272</span><span id="line-2272"> * the atomicity of map#computeIfPresent(key, func) and map#putIfAbsent(key, func). Besides, the</span>
-<span class="source-line-no">2273</span><span id="line-2273"> * func method can execute exactly once only when the key is present(or absent) and under the</span>
-<span class="source-line-no">2274</span><span id="line-2274"> * lock context. Otherwise, the reference count of block will be messed up. Notice that the</span>
-<span class="source-line-no">2275</span><span id="line-2275"> * {@link java.util.concurrent.ConcurrentSkipListMap} can not guarantee that.</span>
-<span class="source-line-no">2276</span><span id="line-2276"> */</span>
-<span class="source-line-no">2277</span><span id="line-2277"> final ConcurrentHashMap<BlockCacheKey, RAMQueueEntry> delegate = new ConcurrentHashMap<>();</span>
-<span class="source-line-no">2278</span><span id="line-2278"></span>
-<span class="source-line-no">2279</span><span id="line-2279"> public boolean containsKey(BlockCacheKey key) {</span>
-<span class="source-line-no">2280</span><span id="line-2280"> return delegate.containsKey(key);</span>
-<span class="source-line-no">2281</span><span id="line-2281"> }</span>
-<span class="source-line-no">2282</span><span id="line-2282"></span>
-<span class="source-line-no">2283</span><span id="line-2283"> public RAMQueueEntry get(BlockCacheKey key) {</span>
-<span class="source-line-no">2284</span><span id="line-2284"> return delegate.computeIfPresent(key, (k, re) -> {</span>
-<span class="source-line-no">2285</span><span id="line-2285"> // It'll be referenced by RPC, so retain atomically here. if the get and retain is not</span>
-<span class="source-line-no">2286</span><span id="line-2286"> // atomic, another thread may remove and release the block, when retaining in this thread we</span>
-<span class="source-line-no">2287</span><span id="line-2287"> // may retain a block with refCnt=0 which is disallowed. (see HBASE-22422)</span>
-<span class="source-line-no">2288</span><span id="line-2288"> re.getData().retain();</span>
-<span class="source-line-no">2289</span><span id="line-2289"> return re;</span>
-<span class="source-line-no">2290</span><span id="line-2290"> });</span>
-<span class="source-line-no">2291</span><span id="line-2291"> }</span>
+<span class="source-line-no">2192</span><span id="line-2192"> diff = Long.compare(this.getOffset(), other.getOffset());</span>
+<span class="source-line-no">2193</span><span id="line-2193"> if (diff != 0) return diff;</span>
+<span class="source-line-no">2194</span><span id="line-2194"> if (other.getCachedTime() < 0 || this.getCachedTime() < 0) {</span>
+<span class="source-line-no">2195</span><span id="line-2195"> throw new IllegalStateException(</span>
+<span class="source-line-no">2196</span><span id="line-2196"> "" + this.getCachedTime() + ", " + other.getCachedTime());</span>
+<span class="source-line-no">2197</span><span id="line-2197"> }</span>
+<span class="source-line-no">2198</span><span id="line-2198"> return Long.compare(other.getCachedTime(), this.getCachedTime());</span>
+<span class="source-line-no">2199</span><span id="line-2199"> }</span>
+<span class="source-line-no">2200</span><span id="line-2200"></span>
+<span class="source-line-no">2201</span><span id="line-2201"> @Override</span>
+<span class="source-line-no">2202</span><span id="line-2202"> public int hashCode() {</span>
+<span class="source-line-no">2203</span><span id="line-2203"> return e.getKey().hashCode();</span>
+<span class="source-line-no">2204</span><span id="line-2204"> }</span>
+<span class="source-line-no">2205</span><span id="line-2205"></span>
+<span class="source-line-no">2206</span><span id="line-2206"> @Override</span>
+<span class="source-line-no">2207</span><span id="line-2207"> public boolean equals(Object obj) {</span>
+<span class="source-line-no">2208</span><span id="line-2208"> if (obj instanceof CachedBlock) {</span>
+<span class="source-line-no">2209</span><span id="line-2209"> CachedBlock cb = (CachedBlock) obj;</span>
+<span class="source-line-no">2210</span><span id="line-2210"> return compareTo(cb) == 0;</span>
+<span class="source-line-no">2211</span><span id="line-2211"> } else {</span>
+<span class="source-line-no">2212</span><span id="line-2212"> return false;</span>
+<span class="source-line-no">2213</span><span id="line-2213"> }</span>
+<span class="source-line-no">2214</span><span id="line-2214"> }</span>
+<span class="source-line-no">2215</span><span id="line-2215"> };</span>
+<span class="source-line-no">2216</span><span id="line-2216"> }</span>
+<span class="source-line-no">2217</span><span id="line-2217"></span>
+<span class="source-line-no">2218</span><span id="line-2218"> @Override</span>
+<span class="source-line-no">2219</span><span id="line-2219"> public void remove() {</span>
+<span class="source-line-no">2220</span><span id="line-2220"> throw new UnsupportedOperationException();</span>
+<span class="source-line-no">2221</span><span id="line-2221"> }</span>
+<span class="source-line-no">2222</span><span id="line-2222"> };</span>
+<span class="source-line-no">2223</span><span id="line-2223"> }</span>
+<span class="source-line-no">2224</span><span id="line-2224"></span>
+<span class="source-line-no">2225</span><span id="line-2225"> @Override</span>
+<span class="source-line-no">2226</span><span id="line-2226"> public BlockCache[] getBlockCaches() {</span>
+<span class="source-line-no">2227</span><span id="line-2227"> return null;</span>
+<span class="source-line-no">2228</span><span id="line-2228"> }</span>
+<span class="source-line-no">2229</span><span id="line-2229"></span>
+<span class="source-line-no">2230</span><span id="line-2230"> public int getRpcRefCount(BlockCacheKey cacheKey) {</span>
+<span class="source-line-no">2231</span><span id="line-2231"> BucketEntry bucketEntry = backingMap.get(cacheKey);</span>
+<span class="source-line-no">2232</span><span id="line-2232"> if (bucketEntry != null) {</span>
+<span class="source-line-no">2233</span><span id="line-2233"> return bucketEntry.refCnt() - (bucketEntry.markedAsEvicted.get() ? 0 : 1);</span>
+<span class="source-line-no">2234</span><span id="line-2234"> }</span>
+<span class="source-line-no">2235</span><span id="line-2235"> return 0;</span>
+<span class="source-line-no">2236</span><span id="line-2236"> }</span>
+<span class="source-line-no">2237</span><span id="line-2237"></span>
+<span class="source-line-no">2238</span><span id="line-2238"> float getAcceptableFactor() {</span>
+<span class="source-line-no">2239</span><span id="line-2239"> return acceptableFactor;</span>
+<span class="source-line-no">2240</span><span id="line-2240"> }</span>
+<span class="source-line-no">2241</span><span id="line-2241"></span>
+<span class="source-line-no">2242</span><span id="line-2242"> float getMinFactor() {</span>
+<span class="source-line-no">2243</span><span id="line-2243"> return minFactor;</span>
+<span class="source-line-no">2244</span><span id="line-2244"> }</span>
+<span class="source-line-no">2245</span><span id="line-2245"></span>
+<span class="source-line-no">2246</span><span id="line-2246"> float getExtraFreeFactor() {</span>
+<span class="source-line-no">2247</span><span id="line-2247"> return extraFreeFactor;</span>
+<span class="source-line-no">2248</span><span id="line-2248"> }</span>
+<span class="source-line-no">2249</span><span id="line-2249"></span>
+<span class="source-line-no">2250</span><span id="line-2250"> float getSingleFactor() {</span>
+<span class="source-line-no">2251</span><span id="line-2251"> return singleFactor;</span>
+<span class="source-line-no">2252</span><span id="line-2252"> }</span>
+<span class="source-line-no">2253</span><span id="line-2253"></span>
+<span class="source-line-no">2254</span><span id="line-2254"> float getMultiFactor() {</span>
+<span class="source-line-no">2255</span><span id="line-2255"> return multiFactor;</span>
+<span class="source-line-no">2256</span><span id="line-2256"> }</span>
+<span class="source-line-no">2257</span><span id="line-2257"></span>
+<span class="source-line-no">2258</span><span id="line-2258"> float getMemoryFactor() {</span>
+<span class="source-line-no">2259</span><span id="line-2259"> return memoryFactor;</span>
+<span class="source-line-no">2260</span><span id="line-2260"> }</span>
+<span class="source-line-no">2261</span><span id="line-2261"></span>
+<span class="source-line-no">2262</span><span id="line-2262"> long getQueueAdditionWaitTime() {</span>
+<span class="source-line-no">2263</span><span id="line-2263"> return queueAdditionWaitTime;</span>
+<span class="source-line-no">2264</span><span id="line-2264"> }</span>
+<span class="source-line-no">2265</span><span id="line-2265"></span>
+<span class="source-line-no">2266</span><span id="line-2266"> long getPersistenceChunkSize() {</span>
+<span class="source-line-no">2267</span><span id="line-2267"> return persistenceChunkSize;</span>
+<span class="source-line-no">2268</span><span id="line-2268"> }</span>
+<span class="source-line-no">2269</span><span id="line-2269"></span>
+<span class="source-line-no">2270</span><span id="line-2270"> long getBucketcachePersistInterval() {</span>
+<span class="source-line-no">2271</span><span id="line-2271"> return bucketcachePersistInterval;</span>
+<span class="source-line-no">2272</span><span id="line-2272"> }</span>
+<span class="source-line-no">2273</span><span id="line-2273"></span>
+<span class="source-line-no">2274</span><span id="line-2274"> public String getPersistencePath() {</span>
+<span class="source-line-no">2275</span><span id="line-2275"> return persistencePath;</span>
+<span class="source-line-no">2276</span><span id="line-2276"> }</span>
+<span class="source-line-no">2277</span><span id="line-2277"></span>
+<span class="source-line-no">2278</span><span id="line-2278"> /**</span>
+<span class="source-line-no">2279</span><span id="line-2279"> * Wrapped the delegate ConcurrentMap with maintaining its block's reference count.</span>
+<span class="source-line-no">2280</span><span id="line-2280"> */</span>
+<span class="source-line-no">2281</span><span id="line-2281"> static class RAMCache {</span>
+<span class="source-line-no">2282</span><span id="line-2282"> /**</span>
+<span class="source-line-no">2283</span><span id="line-2283"> * Defined the map as {@link ConcurrentHashMap} explicitly here, because in</span>
+<span class="source-line-no">2284</span><span id="line-2284"> * {@link RAMCache#get(BlockCacheKey)} and</span>
+<span class="source-line-no">2285</span><span id="line-2285"> * {@link RAMCache#putIfAbsent(BlockCacheKey, BucketCache.RAMQueueEntry)} , we need to guarantee</span>
+<span class="source-line-no">2286</span><span id="line-2286"> * the atomicity of map#computeIfPresent(key, func) and map#putIfAbsent(key, func). Besides, the</span>
+<span class="source-line-no">2287</span><span id="line-2287"> * func method can execute exactly once only when the key is present(or absent) and under the</span>
+<span class="source-line-no">2288</span><span id="line-2288"> * lock context. Otherwise, the reference count of block will be messed up. Notice that the</span>
+<span class="source-line-no">2289</span><span id="line-2289"> * {@link java.util.concurrent.ConcurrentSkipListMap} can not guarantee that.</span>
+<span class="source-line-no">2290</span><span id="line-2290"> */</span>
+<span class="source-line-no">2291</span><span id="line-2291"> final ConcurrentHashMap<BlockCacheKey, RAMQueueEntry> delegate = new ConcurrentHashMap<>();</span>
<span class="source-line-no">2292</span><span id="line-2292"></span>
-<span class="source-line-no">2293</span><span id="line-2293"> /**</span>
-<span class="source-line-no">2294</span><span id="line-2294"> * Return the previous associated value, or null if absent. It has the same meaning as</span>
-<span class="source-line-no">2295</span><span id="line-2295"> * {@link ConcurrentMap#putIfAbsent(Object, Object)}</span>
-<span class="source-line-no">2296</span><span id="line-2296"> */</span>
-<span class="source-line-no">2297</span><span id="line-2297"> public RAMQueueEntry putIfAbsent(BlockCacheKey key, RAMQueueEntry entry) {</span>
-<span class="source-line-no">2298</span><span id="line-2298"> AtomicBoolean absent = new AtomicBoolean(false);</span>
-<span class="source-line-no">2299</span><span id="line-2299"> RAMQueueEntry re = delegate.computeIfAbsent(key, k -> {</span>
-<span class="source-line-no">2300</span><span id="line-2300"> // The RAMCache reference to this entry, so reference count should be increment.</span>
-<span class="source-line-no">2301</span><span id="line-2301"> entry.getData().retain();</span>
-<span class="source-line-no">2302</span><span id="line-2302"> absent.set(true);</span>
-<span class="source-line-no">2303</span><span id="line-2303"> return entry;</span>
+<span class="source-line-no">2293</span><span id="line-2293"> public boolean containsKey(BlockCacheKey key) {</span>
+<span class="source-line-no">2294</span><span id="line-2294"> return delegate.containsKey(key);</span>
+<span class="source-line-no">2295</span><span id="line-2295"> }</span>
+<span class="source-line-no">2296</span><span id="line-2296"></span>
+<span class="source-line-no">2297</span><span id="line-2297"> public RAMQueueEntry get(BlockCacheKey key) {</span>
+<span class="source-line-no">2298</span><span id="line-2298"> return delegate.computeIfPresent(key, (k, re) -> {</span>
+<span class="source-line-no">2299</span><span id="line-2299"> // It'll be referenced by RPC, so retain atomically here. if the get and retain is not</span>
+<span class="source-line-no">2300</span><span id="line-2300"> // atomic, another thread may remove and release the block, when retaining in this thread we</span>
+<span class="source-line-no">2301</span><span id="line-2301"> // may retain a block with refCnt=0 which is disallowed. (see HBASE-22422)</span>
+<span class="source-line-no">2302</span><span id="line-2302"> re.getData().retain();</span>
+<span class="source-line-no">2303</span><span id="line-2303"> return re;</span>
<span class="source-line-no">2304</span><span id="line-2304"> });</span>
-<span class="source-line-no">2305</span><span id="line-2305"> return absent.get() ? null : re;</span>
-<span class="source-line-no">2306</span><span id="line-2306"> }</span>
-<span class="source-line-no">2307</span><span id="line-2307"></span>
-<span class="source-line-no">2308</span><span id="line-2308"> public boolean remove(BlockCacheKey key) {</span>
-<span class="source-line-no">2309</span><span id="line-2309"> return remove(key, re -> {</span>
-<span class="source-line-no">2310</span><span id="line-2310"> });</span>
-<span class="source-line-no">2311</span><span id="line-2311"> }</span>
-<span class="source-line-no">2312</span><span id="line-2312"></span>
-<span class="source-line-no">2313</span><span id="line-2313"> /**</span>
-<span class="source-line-no">2314</span><span id="line-2314"> * Defined an {@link Consumer} here, because once the removed entry release its reference count,</span>
-<span class="source-line-no">2315</span><span id="line-2315"> * then it's ByteBuffers may be recycled and accessing it outside this method will be thrown an</span>
-<span class="source-line-no">2316</span><span id="line-2316"> * exception. the consumer will access entry to remove before release its reference count.</span>
-<span class="source-line-no">2317</span><span id="line-2317"> * Notice, don't change its reference count in the {@link Consumer}</span>
-<span class="source-line-no">2318</span><span id="line-2318"> */</span>
-<span class="source-line-no">2319</span><span id="line-2319"> public boolean remove(BlockCacheKey key, Consumer<RAMQueueEntry> action) {</span>
-<span class="source-line-no">2320</span><span id="line-2320"> RAMQueueEntry previous = delegate.remove(key);</span>
-<span class="source-line-no">2321</span><span id="line-2321"> action.accept(previous);</span>
-<span class="source-line-no">2322</span><span id="line-2322"> if (previous != null) {</span>
-<span class="source-line-no">2323</span><span id="line-2323"> previous.getData().release();</span>
-<span class="source-line-no">2324</span><span id="line-2324"> }</span>
-<span class="source-line-no">2325</span><span id="line-2325"> return previous != null;</span>
-<span class="source-line-no">2326</span><span id="line-2326"> }</span>
-<span class="source-line-no">2327</span><span id="line-2327"></span>
-<span class="source-line-no">2328</span><span id="line-2328"> public boolean isEmpty() {</span>
-<span class="source-line-no">2329</span><span id="line-2329"> return delegate.isEmpty();</span>
-<span class="source-line-no">2330</span><span id="line-2330"> }</span>
-<span class="source-line-no">2331</span><span id="line-2331"></span>
-<span class="source-line-no">2332</span><span id="line-2332"> public void clear() {</span>
-<span class="source-line-no">2333</span><span id="line-2333"> Iterator<Map.Entry<BlockCacheKey, RAMQueueEntry>> it = delegate.entrySet().iterator();</span>
-<span class="source-line-no">2334</span><span id="line-2334"> while (it.hasNext()) {</span>
-<span class="source-line-no">2335</span><span id="line-2335"> RAMQueueEntry re = it.next().getValue();</span>
-<span class="source-line-no">2336</span><span id="line-2336"> it.remove();</span>
-<span class="source-line-no">2337</span><span id="line-2337"> re.getData().release();</span>
+<span class="source-line-no">2305</span><span id="line-2305"> }</span>
+<span class="source-line-no">2306</span><span id="line-2306"></span>
+<span class="source-line-no">2307</span><span id="line-2307"> /**</span>
+<span class="source-line-no">2308</span><span id="line-2308"> * Return the previous associated value, or null if absent. It has the same meaning as</span>
+<span class="source-line-no">2309</span><span id="line-2309"> * {@link ConcurrentMap#putIfAbsent(Object, Object)}</span>
+<span class="source-line-no">2310</span><span id="line-2310"> */</span>
+<span class="source-line-no">2311</span><span id="line-2311"> public RAMQueueEntry putIfAbsent(BlockCacheKey key, RAMQueueEntry entry) {</span>
+<span class="source-line-no">2312</span><span id="line-2312"> AtomicBoolean absent = new AtomicBoolean(false);</span>
+<span class="source-line-no">2313</span><span id="line-2313"> RAMQueueEntry re = delegate.computeIfAbsent(key, k -> {</span>
+<span class="source-line-no">2314</span><span id="line-2314"> // The RAMCache reference to this entry, so reference count should be increment.</span>
+<span class="source-line-no">2315</span><span id="line-2315"> entry.getData().retain();</span>
+<span class="source-line-no">2316</span><span id="line-2316"> absent.set(true);</span>
+<span class="source-line-no">2317</span><span id="line-2317"> return entry;</span>
+<span class="source-line-no">2318</span><span id="line-2318"> });</span>
+<span class="source-line-no">2319</span><span id="line-2319"> return absent.get() ? null : re;</span>
+<span class="source-line-no">2320</span><span id="line-2320"> }</span>
+<span class="source-line-no">2321</span><span id="line-2321"></span>
+<span class="source-line-no">2322</span><span id="line-2322"> public boolean remove(BlockCacheKey key) {</span>
+<span class="source-line-no">2323</span><span id="line-2323"> return remove(key, re -> {</span>
+<span class="source-line-no">2324</span><span id="line-2324"> });</span>
+<span class="source-line-no">2325</span><span id="line-2325"> }</span>
+<span class="source-line-no">2326</span><span id="line-2326"></span>
+<span class="source-line-no">2327</span><span id="line-2327"> /**</span>
+<span class="source-line-no">2328</span><span id="line-2328"> * Defined an {@link Consumer} here, because once the removed entry release its reference count,</span>
+<span class="source-line-no">2329</span><span id="line-2329"> * then it's ByteBuffers may be recycled and accessing it outside this method will be thrown an</span>
+<span class="source-line-no">2330</span><span id="line-2330"> * exception. the consumer will access entry to remove before release its reference count.</span>
+<span class="source-line-no">2331</span><span id="line-2331"> * Notice, don't change its reference count in the {@link Consumer}</span>
+<span class="source-line-no">2332</span><span id="line-2332"> */</span>
+<span class="source-line-no">2333</span><span id="line-2333"> public boolean remove(BlockCacheKey key, Consumer<RAMQueueEntry> action) {</span>
+<span class="source-line-no">2334</span><span id="line-2334"> RAMQueueEntry previous = delegate.remove(key);</span>
+<span class="source-line-no">2335</span><span id="line-2335"> action.accept(previous);</span>
+<span class="source-line-no">2336</span><span id="line-2336"> if (previous != null) {</span>
+<span class="source-line-no">2337</span><span id="line-2337"> previous.getData().release();</span>
<span class="source-line-no">2338</span><span id="line-2338"> }</span>
-<span class="source-line-no">2339</span><span id="line-2339"> }</span>
-<span class="source-line-no">2340</span><span id="line-2340"></span>
-<span class="source-line-no">2341</span><span id="line-2341"> public boolean hasBlocksForFile(String fileName) {</span>
-<span class="source-line-no">2342</span><span id="line-2342"> return delegate.keySet().stream().filter(key -> key.getHfileName().equals(fileName))</span>
-<span class="source-line-no">2343</span><span id="line-2343"> .findFirst().isPresent();</span>
+<span class="source-line-no">2339</span><span id="line-2339"> return previous != null;</span>
+<span class="source-line-no">2340</span><span id="line-2340"> }</span>
+<span class="source-line-no">2341</span><span id="line-2341"></span>
+<span class="source-line-no">2342</span><span id="line-2342"> public boolean isEmpty() {</span>
+<span class="source-line-no">2343</span><span id="line-2343"> return delegate.isEmpty();</span>
<span class="source-line-no">2344</span><span id="line-2344"> }</span>
-<span class="source-line-no">2345</span><span id="line-2345"> }</span>
-<span class="source-line-no">2346</span><span id="line-2346"></span>
-<span class="source-line-no">2347</span><span id="line-2347"> public Map<BlockCacheKey, BucketEntry> getBackingMap() {</span>
-<span class="source-line-no">2348</span><span id="line-2348"> return backingMap;</span>
-<span class="source-line-no">2349</span><span id="line-2349"> }</span>
-<span class="source-line-no">2350</span><span id="line-2350"></span>
-<span class="source-line-no">2351</span><span id="line-2351"> public AtomicBoolean getBackingMapValidated() {</span>
-<span class="source-line-no">2352</span><span id="line-2352"> return backingMapValidated;</span>
-<span class="source-line-no">2353</span><span id="line-2353"> }</span>
+<span class="source-line-no">2345</span><span id="line-2345"></span>
+<span class="source-line-no">2346</span><span id="line-2346"> public void clear() {</span>
+<span class="source-line-no">2347</span><span id="line-2347"> Iterator<Map.Entry<BlockCacheKey, RAMQueueEntry>> it = delegate.entrySet().iterator();</span>
+<span class="source-line-no">2348</span><span id="line-2348"> while (it.hasNext()) {</span>
+<span class="source-line-no">2349</span><span id="line-2349"> RAMQueueEntry re = it.next().getValue();</span>
+<span class="source-line-no">2350</span><span id="line-2350"> it.remove();</span>
+<span class="source-line-no">2351</span><span id="line-2351"> re.getData().release();</span>
+<span class="source-line-no">2352</span><span id="line-2352"> }</span>
+<span class="source-line-no">2353</span><span id="line-2353"> }</span>
<span class="source-line-no">2354</span><span id="line-2354"></span>
-<span class="source-line-no">2355</span><span id="line-2355"> @Override</span>
-<span class="source-line-no">2356</span><span id="line-2356"> public Optional<Map<String, Pair<String, Long>>> getFullyCachedFiles() {</span>
-<span class="source-line-no">2357</span><span id="line-2357"> return Optional.of(fullyCachedFiles);</span>
-<span class="source-line-no">2358</span><span id="line-2358"> }</span>
-<span class="source-line-no">2359</span><span id="line-2359"></span>
-<span class="source-line-no">2360</span><span id="line-2360"> public static Optional<BucketCache> getBucketCacheFromCacheConfig(CacheConfig cacheConf) {</span>
-<span class="source-line-no">2361</span><span id="line-2361"> if (cacheConf.getBlockCache().isPresent()) {</span>
-<span class="source-line-no">2362</span><span id="line-2362"> BlockCache bc = cacheConf.getBlockCache().get();</span>
-<span class="source-line-no">2363</span><span id="line-2363"> if (bc instanceof CombinedBlockCache) {</span>
-<span class="source-line-no">2364</span><span id="line-2364"> BlockCache l2 = ((CombinedBlockCache) bc).getSecondLevelCache();</span>
-<span class="source-line-no">2365</span><span id="line-2365"> if (l2 instanceof BucketCache) {</span>
-<span class="source-line-no">2366</span><span id="line-2366"> return Optional.of((BucketCache) l2);</span>
-<span class="source-line-no">2367</span><span id="line-2367"> }</span>
-<span class="source-line-no">2368</span><span id="line-2368"> } else if (bc instanceof BucketCache) {</span>
-<span class="source-line-no">2369</span><span id="line-2369"> return Optional.of((BucketCache) bc);</span>
-<span class="source-line-no">2370</span><span id="line-2370"> }</span>
-<span class="source-line-no">2371</span><span id="line-2371"> }</span>
-<span class="source-line-no">2372</span><span id="line-2372"> return Optional.empty();</span>
-<span class="source-line-no">2373</span><span id="line-2373"> }</span>
-<span class="source-line-no">2374</span><span id="line-2374"></span>
-<span class="source-line-no">2375</span><span id="line-2375"> @Override</span>
-<span class="source-line-no">2376</span><span id="line-2376"> public void notifyFileCachingCompleted(Path fileName, int totalBlockCount, int dataBlockCount,</span>
-<span class="source-line-no">2377</span><span id="line-2377"> long size) {</span>
-<span class="source-line-no">2378</span><span id="line-2378"> // block eviction may be happening in the background as prefetch runs,</span>
-<span class="source-line-no">2379</span><span id="line-2379"> // so we need to count all blocks for this file in the backing map under</span>
-<span class="source-line-no">2380</span><span id="line-2380"> // a read lock for the block offset</span>
-<span class="source-line-no">2381</span><span id="line-2381"> final List<ReentrantReadWriteLock> locks = new ArrayList<>();</span>
-<span class="source-line-no">2382</span><span id="line-2382"> LOG.debug("Notifying caching completed for file {}, with total blocks {}, and data blocks {}",</span>
-<span class="source-line-no">2383</span><span id="line-2383"> fileName, totalBlockCount, dataBlockCount);</span>
-<span class="source-line-no">2384</span><span id="line-2384"> try {</span>
-<span class="source-line-no">2385</span><span id="line-2385"> int count = 0;</span>
-<span class="source-line-no">2386</span><span id="line-2386"> LOG.debug("iterating over {} entries in the backing map", backingMap.size());</span>
-<span class="source-line-no">2387</span><span id="line-2387"> Set<BlockCacheKey> result = getAllCacheKeysForFile(fileName.getName(), 0, Long.MAX_VALUE);</span>
-<span class="source-line-no">2388</span><span id="line-2388"> if (result.isEmpty() && StoreFileInfo.isReference(fileName)) {</span>
-<span class="source-line-no">2389</span><span id="line-2389"> result = getAllCacheKeysForFile(</span>
-<span class="source-line-no">2390</span><span id="line-2390"> StoreFileInfo.getReferredToRegionAndFile(fileName.getName()).getSecond(), 0,</span>
-<span class="source-line-no">2391</span><span id="line-2391"> Long.MAX_VALUE);</span>
-<span class="source-line-no">2392</span><span id="line-2392"> }</span>
-<span class="source-line-no">2393</span><span id="line-2393"> for (BlockCacheKey entry : result) {</span>
-<span class="source-line-no">2394</span><span id="line-2394"> LOG.debug("found block for file {} in the backing map. Acquiring read lock for offset {}",</span>
-<span class="source-line-no">2395</span><span id="line-2395"> fileName.getName(), entry.getOffset());</span>
-<span class="source-line-no">2396</span><span id="line-2396"> ReentrantReadWriteLock lock = offsetLock.getLock(entry.getOffset());</span>
-<span class="source-line-no">2397</span><span id="line-2397"> lock.readLock().lock();</span>
-<span class="source-line-no">2398</span><span id="line-2398"> locks.add(lock);</span>
-<span class="source-line-no">2399</span><span id="line-2399"> if (backingMap.containsKey(entry) && entry.getBlockType().isData()) {</span>
-<span class="source-line-no">2400</span><span id="line-2400"> count++;</span>
-<span class="source-line-no">2401</span><span id="line-2401"> }</span>
-<span class="source-line-no">2402</span><span id="line-2402"> }</span>
-<span class="source-line-no">2403</span><span id="line-2403"> // BucketCache would only have data blocks</span>
-<span class="source-line-no">2404</span><span id="line-2404"> if (dataBlockCount == count) {</span>
-<span class="source-line-no">2405</span><span id="line-2405"> LOG.debug("File {} has now been fully cached.", fileName);</span>
-<span class="source-line-no">2406</span><span id="line-2406"> fileCacheCompleted(fileName, size);</span>
-<span class="source-line-no">2407</span><span id="line-2407"> } else {</span>
-<span class="source-line-no">2408</span><span id="line-2408"> LOG.debug(</span>
-<span class="source-line-no">2409</span><span id="line-2409"> "Prefetch executor completed for {}, but only {} data blocks were cached. "</span>
-<span class="source-line-no">2410</span><span id="line-2410"> + "Total data blocks for file: {}. "</span>
-<span class="source-line-no">2411</span><span id="line-2411"> + "Checking for blocks pending cache in cache writer queue.",</span>
-<span class="source-line-no">2412</span><span id="line-2412"> fileName, count, dataBlockCount);</span>
-<span class="source-line-no">2413</span><span id="line-2413"> if (ramCache.hasBlocksForFile(fileName.getName())) {</span>
-<span class="source-line-no">2414</span><span id="line-2414"> for (ReentrantReadWriteLock lock : locks) {</span>
-<span class="source-line-no">2415</span><span id="line-2415"> lock.readLock().unlock();</span>
-<span class="source-line-no">2416</span><span id="line-2416"> }</span>
-<span class="source-line-no">2417</span><span id="line-2417"> locks.clear();</span>
-<span class="source-line-no">2418</span><span id="line-2418"> LOG.debug("There are still blocks pending caching for file {}. Will sleep 100ms "</span>
-<span class="source-line-no">2419</span><span id="line-2419"> + "and try the verification again.", fileName);</span>
-<span class="source-line-no">2420</span><span id="line-2420"> Thread.sleep(100);</span>
-<span class="source-line-no">2421</span><span id="line-2421"> notifyFileCachingCompleted(fileName, totalBlockCount, dataBlockCount, size);</span>
-<span class="source-line-no">2422</span><span id="line-2422"> } else {</span>
-<span class="source-line-no">2423</span><span id="line-2423"> LOG.info(</span>
-<span class="source-line-no">2424</span><span id="line-2424"> "The total block count was {}. We found only {} data blocks cached from "</span>
-<span class="source-line-no">2425</span><span id="line-2425"> + "a total of {} data blocks for file {}, "</span>
-<span class="source-line-no">2426</span><span id="line-2426"> + "but no blocks pending caching. Maybe cache is full or evictions "</span>
-<span class="source-line-no">2427</span><span id="line-2427"> + "happened concurrently to cache prefetch.",</span>
-<span class="source-line-no">2428</span><span id="line-2428"> totalBlockCount, count, dataBlockCount, fileName);</span>
-<span class="source-line-no">2429</span><span id="line-2429"> }</span>
-<span class="source-line-no">2430</span><span id="line-2430"> }</span>
-<span class="source-line-no">2431</span><span id="line-2431"> } catch (InterruptedException e) {</span>
-<span class="source-line-no">2432</span><span id="line-2432"> throw new RuntimeException(e);</span>
-<span class="source-line-no">2433</span><span id="line-2433"> } finally {</span>
-<span class="source-line-no">2434</span><span id="line-2434"> for (ReentrantReadWriteLock lock : locks) {</span>
-<span class="source-line-no">2435</span><span id="line-2435"> lock.readLock().unlock();</span>
-<span class="source-line-no">2436</span><span id="line-2436"> }</span>
-<span class="source-line-no">2437</span><span id="line-2437"> }</span>
-<span class="source-line-no">2438</span><span id="line-2438"> }</span>
-<span class="source-line-no">2439</span><span id="line-2439"></span>
-<span class="source-line-no">2440</span><span id="line-2440"> @Override</span>
-<span class="source-line-no">2441</span><span id="line-2441"> public Optional<Boolean> blockFitsIntoTheCache(HFileBlock block) {</span>
-<span class="source-line-no">2442</span><span id="line-2442"> if (!isCacheInitialized("blockFitsIntoTheCache")) {</span>
-<span class="source-line-no">2443</span><span id="line-2443"> return Optional.of(false);</span>
-<span class="source-line-no">2444</span><span id="line-2444"> }</span>
-<span class="source-line-no">2445</span><span id="line-2445"></span>
-<span class="source-line-no">2446</span><span id="line-2446"> long currentUsed = bucketAllocator.getUsedSize();</span>
-<span class="source-line-no">2447</span><span id="line-2447"> boolean result = (currentUsed + block.getOnDiskSizeWithHeader()) < acceptableSize();</span>
-<span class="source-line-no">2448</span><span id="line-2448"> return Optional.of(result);</span>
-<span class="source-line-no">2449</span><span id="line-2449"> }</span>
-<span class="source-line-no">2450</span><span id="line-2450"></span>
-<span class="source-line-no">2451</span><span id="line-2451"> @Override</span>
-<span class="source-line-no">2452</span><span id="line-2452"> public Optional<Boolean> shouldCacheFile(HFileInfo hFileInfo, Configuration conf) {</span>
-<span class="source-line-no">2453</span><span id="line-2453"> String fileName = hFileInfo.getHFileContext().getHFileName();</span>
-<span class="source-line-no">2454</span><span id="line-2454"> DataTieringManager dataTieringManager = DataTieringManager.getInstance();</span>
-<span class="source-line-no">2455</span><span id="line-2455"> if (dataTieringManager != null && !dataTieringManager.isHotData(hFileInfo, conf)) {</span>
-<span class="source-line-no">2456</span><span id="line-2456"> LOG.debug("Data tiering is enabled for file: '{}' and it is not hot data", fileName);</span>
+<span class="source-line-no">2355</span><span id="line-2355"> public boolean hasBlocksForFile(String fileName) {</span>
+<span class="source-line-no">2356</span><span id="line-2356"> return delegate.keySet().stream().filter(key -> key.getHfileName().equals(fileName))</span>
+<span class="source-line-no">2357</span><span id="line-2357"> .findFirst().isPresent();</span>
+<span class="source-line-no">2358</span><span id="line-2358"> }</span>
+<span class="source-line-no">2359</span><span id="line-2359"> }</span>
+<span class="source-line-no">2360</span><span id="line-2360"></span>
+<span class="source-line-no">2361</span><span id="line-2361"> public Map<BlockCacheKey, BucketEntry> getBackingMap() {</span>
+<span class="source-line-no">2362</span><span id="line-2362"> return backingMap;</span>
+<span class="source-line-no">2363</span><span id="line-2363"> }</span>
+<span class="source-line-no">2364</span><span id="line-2364"></span>
+<span class="source-line-no">2365</span><span id="line-2365"> public AtomicBoolean getBackingMapValidated() {</span>
+<span class="source-line-no">2366</span><span id="line-2366"> return backingMapValidated;</span>
+<span class="source-line-no">2367</span><span id="line-2367"> }</span>
+<span class="source-line-no">2368</span><span id="line-2368"></span>
+<span class="source-line-no">2369</span><span id="line-2369"> @Override</span>
+<span class="source-line-no">2370</span><span id="line-2370"> public Optional<Map<String, Pair<String, Long>>> getFullyCachedFiles() {</span>
+<span class="source-line-no">2371</span><span id="line-2371"> return Optional.of(fullyCachedFiles);</span>
+<span class="source-line-no">2372</span><span id="line-2372"> }</span>
+<span class="source-line-no">2373</span><span id="line-2373"></span>
+<span class="source-line-no">2374</span><span id="line-2374"> public static Optional<BucketCache> getBucketCacheFromCacheConfig(CacheConfig cacheConf) {</span>
+<span class="source-line-no">2375</span><span id="line-2375"> if (cacheConf.getBlockCache().isPresent()) {</span>
+<span class="source-line-no">2376</span><span id="line-2376"> BlockCache bc = cacheConf.getBlockCache().get();</span>
+<span class="source-line-no">2377</span><span id="line-2377"> if (bc instanceof CombinedBlockCache) {</span>
+<span class="source-line-no">2378</span><span id="line-2378"> BlockCache l2 = ((CombinedBlockCache) bc).getSecondLevelCache();</span>
+<span class="source-line-no">2379</span><span id="line-2379"> if (l2 instanceof BucketCache) {</span>
+<span class="source-line-no">2380</span><span id="line-2380"> return Optional.of((BucketCache) l2);</span>
+<span class="source-line-no">2381</span><span id="line-2381"> }</span>
+<span class="source-line-no">2382</span><span id="line-2382"> } else if (bc instanceof BucketCache) {</span>
+<span class="source-line-no">2383</span><span id="line-2383"> return Optional.of((BucketCache) bc);</span>
+<span class="source-line-no">2384</span><span id="line-2384"> }</span>
+<span class="source-line-no">2385</span><span id="line-2385"> }</span>
+<span class="source-line-no">2386</span><span id="line-2386"> return Optional.empty();</span>
+<span class="source-line-no">2387</span><span id="line-2387"> }</span>
+<span class="source-line-no">2388</span><span id="line-2388"></span>
+<span class="source-line-no">2389</span><span id="line-2389"> @Override</span>
+<span class="source-line-no">2390</span><span id="line-2390"> public void notifyFileCachingCompleted(Path fileName, int totalBlockCount, int dataBlockCount,</span>
+<span class="source-line-no">2391</span><span id="line-2391"> long size) {</span>
+<span class="source-line-no">2392</span><span id="line-2392"> // block eviction may be happening in the background as prefetch runs,</span>
+<span class="source-line-no">2393</span><span id="line-2393"> // so we need to count all blocks for this file in the backing map under</span>
+<span class="source-line-no">2394</span><span id="line-2394"> // a read lock for the block offset</span>
+<span class="source-line-no">2395</span><span id="line-2395"> final List<ReentrantReadWriteLock> locks = new ArrayList<>();</span>
+<span class="source-line-no">2396</span><span id="line-2396"> LOG.debug("Notifying caching completed for file {}, with total blocks {}, and data blocks {}",</span>
+<span class="source-line-no">2397</span><span id="line-2397"> fileName, totalBlockCount, dataBlockCount);</span>
+<span class="source-line-no">2398</span><span id="line-2398"> try {</span>
+<span class="source-line-no">2399</span><span id="line-2399"> int count = 0;</span>
+<span class="source-line-no">2400</span><span id="line-2400"> LOG.debug("iterating over {} entries in the backing map", backingMap.size());</span>
+<span class="source-line-no">2401</span><span id="line-2401"> Set<BlockCacheKey> result = getAllCacheKeysForFile(fileName.getName(), 0, Long.MAX_VALUE);</span>
+<span class="source-line-no">2402</span><span id="line-2402"> if (result.isEmpty() && StoreFileInfo.isReference(fileName)) {</span>
+<span class="source-line-no">2403</span><span id="line-2403"> result = getAllCacheKeysForFile(</span>
+<span class="source-line-no">2404</span><span id="line-2404"> StoreFileInfo.getReferredToRegionAndFile(fileName.getName()).getSecond(), 0,</span>
+<span class="source-line-no">2405</span><span id="line-2405"> Long.MAX_VALUE);</span>
+<span class="source-line-no">2406</span><span id="line-2406"> }</span>
+<span class="source-line-no">2407</span><span id="line-2407"> for (BlockCacheKey entry : result) {</span>
+<span class="source-line-no">2408</span><span id="line-2408"> LOG.debug("found block for file {} in the backing map. Acquiring read lock for offset {}",</span>
+<span class="source-line-no">2409</span><span id="line-2409"> fileName.getName(), entry.getOffset());</span>
+<span class="source-line-no">2410</span><span id="line-2410"> ReentrantReadWriteLock lock = offsetLock.getLock(entry.getOffset());</span>
+<span class="source-line-no">2411</span><span id="line-2411"> lock.readLock().lock();</span>
+<span class="source-line-no">2412</span><span id="line-2412"> locks.add(lock);</span>
+<span class="source-line-no">2413</span><span id="line-2413"> if (backingMap.containsKey(entry) && entry.getBlockType().isData()) {</span>
+<span class="source-line-no">2414</span><span id="line-2414"> count++;</span>
+<span class="source-line-no">2415</span><span id="line-2415"> }</span>
+<span class="source-line-no">2416</span><span id="line-2416"> }</span>
+<span class="source-line-no">2417</span><span id="line-2417"> // BucketCache would only have data blocks</span>
+<span class="source-line-no">2418</span><span id="line-2418"> if (dataBlockCount == count) {</span>
+<span class="source-line-no">2419</span><span id="line-2419"> LOG.debug("File {} has now been fully cached.", fileName);</span>
+<span class="source-line-no">2420</span><span id="line-2420"> fileCacheCompleted(fileName, size);</span>
+<span class="source-line-no">2421</span><span id="line-2421"> } else {</span>
+<span class="source-line-no">2422</span><span id="line-2422"> LOG.debug(</span>
+<span class="source-line-no">2423</span><span id="line-2423"> "Prefetch executor completed for {}, but only {} data blocks were cached. "</span>
+<span class="source-line-no">2424</span><span id="line-2424"> + "Total data blocks for file: {}. "</span>
+<span class="source-line-no">2425</span><span id="line-2425"> + "Checking for blocks pending cache in cache writer queue.",</span>
+<span class="source-line-no">2426</span><span id="line-2426"> fileName, count, dataBlockCount);</span>
+<span class="source-line-no">2427</span><span id="line-2427"> if (ramCache.hasBlocksForFile(fileName.getName())) {</span>
+<span class="source-line-no">2428</span><span id="line-2428"> for (ReentrantReadWriteLock lock : locks) {</span>
+<span class="source-line-no">2429</span><span id="line-2429"> lock.readLock().unlock();</span>
+<span class="source-line-no">2430</span><span id="line-2430"> }</span>
+<span class="source-line-no">2431</span><span id="line-2431"> locks.clear();</span>
+<span class="source-line-no">2432</span><span id="line-2432"> LOG.debug("There are still blocks pending caching for file {}. Will sleep 100ms "</span>
+<span class="source-line-no">2433</span><span id="line-2433"> + "and try the verification again.", fileName);</span>
+<span class="source-line-no">2434</span><span id="line-2434"> Thread.sleep(100);</span>
+<span class="source-line-no">2435</span><span id="line-2435"> notifyFileCachingCompleted(fileName, totalBlockCount, dataBlockCount, size);</span>
+<span class="source-line-no">2436</span><span id="line-2436"> } else {</span>
+<span class="source-line-no">2437</span><span id="line-2437"> LOG.info(</span>
+<span class="source-line-no">2438</span><span id="line-2438"> "The total block count was {}. We found only {} data blocks cached from "</span>
+<span class="source-line-no">2439</span><span id="line-2439"> + "a total of {} data blocks for file {}, "</span>
+<span class="source-line-no">2440</span><span id="line-2440"> + "but no blocks pending caching. Maybe cache is full or evictions "</span>
+<span class="source-line-no">2441</span><span id="line-2441"> + "happened concurrently to cache prefetch.",</span>
+<span class="source-line-no">2442</span><span id="line-2442"> totalBlockCount, count, dataBlockCount, fileName);</span>
+<span class="source-line-no">2443</span><span id="line-2443"> }</span>
+<span class="source-line-no">2444</span><span id="line-2444"> }</span>
+<span class="source-line-no">2445</span><span id="line-2445"> } catch (InterruptedException e) {</span>
+<span class="source-line-no">2446</span><span id="line-2446"> throw new RuntimeException(e);</span>
+<span class="source-line-no">2447</span><span id="line-2447"> } finally {</span>
+<span class="source-line-no">2448</span><span id="line-2448"> for (ReentrantReadWriteLock lock : locks) {</span>
+<span class="source-line-no">2449</span><span id="line-2449"> lock.readLock().unlock();</span>
+<span class="source-line-no">2450</span><span id="line-2450"> }</span>
+<span class="source-line-no">2451</span><span id="line-2451"> }</span>
+<span class="source-line-no">2452</span><span id="line-2452"> }</span>
+<span class="source-line-no">2453</span><span id="line-2453"></span>
+<span class="source-line-no">2454</span><span id="line-2454"> @Override</span>
+<span class="source-line-no">2455</span><span id="line-2455"> public Optional<Boolean> blockFitsIntoTheCache(HFileBlock block) {</span>
+<span class="source-line-no">2456</span><span id="line-2456"> if (!isCacheInitialized("blockFitsIntoTheCache")) {</span>
<span class="source-line-no">2457</span><span id="line-2457"> return Optional.of(false);</span>
<span class="source-line-no">2458</span><span id="line-2458"> }</span>
-<span class="source-line-no">2459</span><span id="line-2459"> // if we don't have the file in fullyCachedFiles, we should cache it</span>
-<span class="source-line-no">2460</span><span id="line-2460"> return Optional.of(!fullyCachedFiles.containsKey(fileName));</span>
-<span class="source-line-no">2461</span><span id="line-2461"> }</span>
-<span class="source-line-no">2462</span><span id="line-2462"></span>
-<span class="source-line-no">2463</span><span id="line-2463"> @Override</span>
-<span class="source-line-no">2464</span><span id="line-2464"> public Optional<Boolean> shouldCacheBlock(BlockCacheKey key, long maxTimestamp,</span>
-<span class="source-line-no">2465</span><span id="line-2465"> Configuration conf) {</span>
-<span class="source-line-no">2466</span><span id="line-2466"> DataTieringManager dataTieringManager = DataTieringManager.getInstance();</span>
-<span class="source-line-no">2467</span><span id="line-2467"> if (dataTieringManager != null && !dataTieringManager.isHotData(maxTimestamp, conf)) {</span>
-<span class="source-line-no">2468</span><span id="line-2468"> LOG.debug("Data tiering is enabled for file: '{}' and it is not hot data",</span>
-<span class="source-line-no">2469</span><span id="line-2469"> key.getHfileName());</span>
-<span class="source-line-no">2470</span><span id="line-2470"> return Optional.of(false);</span>
-<span class="source-line-no">2471</span><span id="line-2471"> }</span>
-<span class="source-line-no">2472</span><span id="line-2472"> return Optional.of(true);</span>
-<span class="source-line-no">2473</span><span id="line-2473"> }</span>
-<span class="source-line-no">2474</span><span id="line-2474"></span>
-<span class="source-line-no">2475</span><span id="line-2475"> @Override</span>
-<span class="source-line-no">2476</span><span id="line-2476"> public Optional<Boolean> isAlreadyCached(BlockCacheKey key) {</span>
... 65920 lines suppressed ...