diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Admin.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Admin.java index 4d579c16af26..8a60bdab8d67 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Admin.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Admin.java @@ -2615,4 +2615,9 @@ List getLogEntries(Set serverNames, String logType, Server * Flush master local region */ void flushMasterStore() throws IOException; + + /** + * Get the list of prefetched files + */ + List getPrefetchedFilesList(ServerName serverName) throws IOException; } diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AdminOverAsyncAdmin.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AdminOverAsyncAdmin.java index 690b6406fd3a..c4ac601eb11a 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AdminOverAsyncAdmin.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AdminOverAsyncAdmin.java @@ -1115,4 +1115,9 @@ public List getLogEntries(Set serverNames, String logType, public void flushMasterStore() throws IOException { get(admin.flushMasterStore()); } + + @Override + public List getPrefetchedFilesList(ServerName serverName) throws IOException { + return get(admin.getPrefetchedFilesList(serverName)); + } } diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncAdmin.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncAdmin.java index 960982f5e3f1..436e4d835a94 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncAdmin.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncAdmin.java @@ -1837,4 +1837,9 @@ CompletableFuture> getLogEntries(Set serverNames, Str * Flush master local region */ CompletableFuture flushMasterStore(); + + /** + * Get the list of prefetched files + */ + CompletableFuture> getPrefetchedFilesList(ServerName serverName); } diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncHBaseAdmin.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncHBaseAdmin.java index 5ee8a6ab8269..5242ed5d4c3a 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncHBaseAdmin.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncHBaseAdmin.java @@ -990,4 +990,9 @@ public CompletableFuture> getLogEntries(Set serverNam public CompletableFuture flushMasterStore() { return wrap(rawAdmin.flushMasterStore()); } + + @Override + public CompletableFuture> getPrefetchedFilesList(ServerName serverName) { + return wrap(rawAdmin.getPrefetchedFilesList(serverName)); + } } diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RawAsyncHBaseAdmin.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RawAsyncHBaseAdmin.java index ee1dfac16bd3..50b1a53999f1 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RawAsyncHBaseAdmin.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RawAsyncHBaseAdmin.java @@ -134,6 +134,8 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.FlushRegionResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetOnlineRegionRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetOnlineRegionResponse; +import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetPrefetchedFilesListRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetPrefetchedFilesListResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetRegionInfoRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetRegionInfoResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetRegionLoadRequest; @@ -4453,4 +4455,15 @@ Void> call(controller, stub, request.build(), (s, c, req, done) -> s.flushMasterStore(c, req, done), resp -> null)) .call(); } + + @Override + public CompletableFuture> getPrefetchedFilesList(ServerName serverName) { + GetPrefetchedFilesListRequest.Builder request = GetPrefetchedFilesListRequest.newBuilder(); + return this.> newAdminCaller() + .action((controller, stub) -> this.> adminCall(controller, stub, request.build(), + (s, c, req, done) -> s.getPrefetchedFilesList(c, req, done), + resp -> resp.getPrefetchedFilesList())) + .serverName(serverName).call(); + } } diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/ProtobufUtil.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/ProtobufUtil.java index c14a0d042823..680ab7a8bc99 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/ProtobufUtil.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/ProtobufUtil.java @@ -155,6 +155,8 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.CloseRegionRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetOnlineRegionRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetOnlineRegionResponse; +import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetPrefetchedFilesListRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetPrefetchedFilesListResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetRegionInfoRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetRegionInfoResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetServerInfoRequest; @@ -1780,6 +1782,21 @@ public static List getOnlineRegions( return getRegionInfos(response); } + /** + * Get the list of prefetched files + */ + public static List getFullyPrefetchedFiles(final RpcController controller, + final AdminService.BlockingInterface admin) throws IOException { + GetPrefetchedFilesListRequest request = GetPrefetchedFilesListRequest.newBuilder().build(); + GetPrefetchedFilesListResponse response = null; + try { + response = admin.getPrefetchedFilesList(controller, request); + } catch (ServiceException se) { + throw getRemoteException(se); + } + return new ArrayList<>(response.getPrefetchedFilesList()); + } + /** * Get the list of region info from a GetOnlineRegionResponse * @param proto the GetOnlineRegionResponse diff --git a/hbase-protocol-shaded/src/main/protobuf/server/region/Admin.proto b/hbase-protocol-shaded/src/main/protobuf/server/region/Admin.proto index cd88a0ca7cdb..4113b1df4997 100644 --- a/hbase-protocol-shaded/src/main/protobuf/server/region/Admin.proto +++ b/hbase-protocol-shaded/src/main/protobuf/server/region/Admin.proto @@ -283,6 +283,13 @@ message ExecuteProceduresRequest { message ExecuteProceduresResponse { } +message GetPrefetchedFilesListRequest { +} + +message GetPrefetchedFilesListResponse { + repeated string prefetched_files = 1; +} + /** * Slow/Large log (LogRequest) use-case specific RPC request. This request payload will be * converted in bytes and sent to generic RPC API: GetLogEntries @@ -405,4 +412,7 @@ service AdminService { rpc GetLogEntries(LogRequest) returns(LogEntry); + rpc GetPrefetchedFilesList(GetPrefetchedFilesListRequest) + returns(GetPrefetchedFilesListResponse); + } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.java index bc5e7e7c9b9a..c208c58dc205 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.java @@ -1936,4 +1936,16 @@ public static Optional getBuckedCacheFromCacheConfig(CacheConfig ca return Optional.empty(); } + public List getPersistedCachedFiles() throws IOException { + List tmp = new ArrayList<>(); + File persistedFile = new File(persistencePath); + try (FileInputStream fis = new FileInputStream(persistedFile)) { + fis.skip(ProtobufMagic.lengthOfPBMagic()); + BucketCacheProtos.BucketCacheEntry proto = + BucketCacheProtos.BucketCacheEntry.parseDelimitedFrom(fis); + tmp.addAll(proto.getPrefetchedFilesMap().keySet()); + } + return tmp; + } + } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java index b6a17d8503b2..4a27c8e8f8f5 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java @@ -166,6 +166,8 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.FlushRegionResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetOnlineRegionRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetOnlineRegionResponse; +import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetPrefetchedFilesListRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetPrefetchedFilesListResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetRegionInfoRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetRegionInfoResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetRegionLoadRequest; @@ -3563,6 +3565,11 @@ public ExecuteProceduresResponse executeProcedures(RpcController controller, throw new ServiceException(new DoNotRetryIOException("Unsupported method on master")); } + public GetPrefetchedFilesListResponse getPrefetchedFilesList(RpcController controller, + GetPrefetchedFilesListRequest request) throws ServiceException { + throw new ServiceException(new DoNotRetryIOException("Unsupported method on master")); + } + @Override public GetLiveRegionServersResponse getLiveRegionServers(RpcController controller, GetLiveRegionServersRequest request) throws ServiceException { diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java index 85721a354977..16b2791861e0 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java @@ -108,7 +108,10 @@ import org.apache.hadoop.hbase.http.InfoServer; import org.apache.hadoop.hbase.io.hfile.BlockCache; import org.apache.hadoop.hbase.io.hfile.BlockCacheFactory; +import org.apache.hadoop.hbase.io.hfile.CacheConfig; +import org.apache.hadoop.hbase.io.hfile.CombinedBlockCache; import org.apache.hadoop.hbase.io.hfile.HFile; +import org.apache.hadoop.hbase.io.hfile.bucket.BucketCache; import org.apache.hadoop.hbase.io.util.MemorySizeUtil; import org.apache.hadoop.hbase.ipc.CoprocessorRpcUtils; import org.apache.hadoop.hbase.ipc.RpcClient; @@ -3324,6 +3327,21 @@ public Optional getBlockCache() { return Optional.ofNullable(this.blockCache); } + public Optional getBucketCacheIfPresent() { + if (getBlockCache().isPresent()) { + BlockCache bc = getBlockCache().get(); + if (bc instanceof CombinedBlockCache) { + BlockCache l2 = ((CombinedBlockCache) bc).getSecondLevelCache(); + if (l2 instanceof BucketCache) { + return Optional.of((BucketCache) l2); + } + } else if (bc instanceof BucketCache) { + return Optional.of((BucketCache) bc); + } + } + return Optional.empty(); + } + /** * May be null if this is a master which not carry table. * @return The cache for mob files used by the regionserver. diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RSRpcServices.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RSRpcServices.java index 57efe505c126..69cffd6d0da9 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RSRpcServices.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RSRpcServices.java @@ -87,6 +87,8 @@ import org.apache.hadoop.hbase.exceptions.UnknownProtocolException; import org.apache.hadoop.hbase.io.ByteBuffAllocator; import org.apache.hadoop.hbase.io.hfile.BlockCache; +import org.apache.hadoop.hbase.io.hfile.CombinedBlockCache; +import org.apache.hadoop.hbase.io.hfile.bucket.BucketCache; import org.apache.hadoop.hbase.ipc.HBaseRpcController; import org.apache.hadoop.hbase.ipc.PriorityFunction; import org.apache.hadoop.hbase.ipc.QosPriority; @@ -171,6 +173,8 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.FlushRegionResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetOnlineRegionRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetOnlineRegionResponse; +import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetPrefetchedFilesListRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetPrefetchedFilesListResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetRegionInfoRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetRegionInfoResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetRegionLoadRequest; @@ -3933,4 +3937,24 @@ public void onConfigurationChange(Configuration conf) { super.onConfigurationChange(conf); setReloadableGuardrails(conf); } + + @Override + public GetPrefetchedFilesListResponse getPrefetchedFilesList(RpcController controller, + GetPrefetchedFilesListRequest request) throws ServiceException { + GetPrefetchedFilesListResponse.Builder responseBuilder = + GetPrefetchedFilesListResponse.newBuilder(); + + List fullyCachedFiles = new ArrayList<>(); + server.getBucketCacheIfPresent().ifPresent(bucketCache -> { + if (bucketCache.isCachePersistenceEnabled()) { + LOG.info("Fetching fully cached files"); + try { + fullyCachedFiles.addAll(bucketCache.getPersistedCachedFiles()); + } catch (IOException e) { + LOG.info("Exception occurred reading the cache persistence file: {}", e.getMessage()); + } + } + }); + return responseBuilder.addAllPrefetchedFiles(fullyCachedFiles).build(); + } } diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/io/hfile/TestPrefetchRSClose.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/io/hfile/TestPrefetchRSClose.java index 64db9158333d..d78c5a0f0340 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/io/hfile/TestPrefetchRSClose.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/io/hfile/TestPrefetchRSClose.java @@ -23,6 +23,10 @@ import static org.junit.Assert.assertTrue; import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.Path; import org.apache.hadoop.hbase.HBaseClassTestRule; @@ -30,11 +34,15 @@ import org.apache.hadoop.hbase.SingleProcessHBaseCluster; import org.apache.hadoop.hbase.StartTestingClusterOption; import org.apache.hadoop.hbase.TableName; +import org.apache.hadoop.hbase.client.Admin; import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder; import org.apache.hadoop.hbase.client.Put; import org.apache.hadoop.hbase.client.Table; import org.apache.hadoop.hbase.client.TableDescriptor; import org.apache.hadoop.hbase.client.TableDescriptorBuilder; +import org.apache.hadoop.hbase.protobuf.ProtobufMagic; +import org.apache.hadoop.hbase.regionserver.HRegionServer; +import org.apache.hadoop.hbase.shaded.protobuf.generated.BucketCacheProtos; import org.apache.hadoop.hbase.testclassification.IOTests; import org.apache.hadoop.hbase.testclassification.LargeTests; import org.apache.hadoop.hbase.util.Bytes; @@ -112,7 +120,19 @@ public void testPrefetchPersistence() throws Exception { // Default interval for cache persistence is 1000ms. So after 1000ms, both the persistence files // should exist. - assertTrue(new File(testDir + "/bucket.persistence").exists()); + + HRegionServer regionServingRS = cluster.getRegionServer(1).getRegions(tableName).size() == 1 + ? cluster.getRegionServer(1) + : cluster.getRegionServer(0); + + Admin admin = TEST_UTIL.getAdmin(); + File persistenceFile = new File(testDir + "/bucket.persistence"); + assertTrue(persistenceFile.exists()); + FileInputStream fis = new FileInputStream(persistenceFile); + fis.skip(ProtobufMagic.lengthOfPBMagic()); + BucketCacheProtos.BucketCacheEntry proto = + BucketCacheProtos.BucketCacheEntry.parseDelimitedFrom(fis); + assertEquals(new ArrayList<>(proto.getPrefetchedFilesMap().keySet()), admin.getPrefetchedFilesList(regionServingRS.getServerName())); // Stop the RS cluster.stopRegionServer(0); diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/MockRegionServer.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/MockRegionServer.java index 9974c824f889..425b5a831202 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/MockRegionServer.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/MockRegionServer.java @@ -99,6 +99,8 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.FlushRegionResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetOnlineRegionRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetOnlineRegionResponse; +import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetPrefetchedFilesListRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetPrefetchedFilesListResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetRegionInfoRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetRegionInfoResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetRegionLoadRequest; @@ -452,6 +454,12 @@ public GetOnlineRegionResponse getOnlineRegion(RpcController controller, return null; } + @Override + public GetPrefetchedFilesListResponse getPrefetchedFilesList(RpcController controller, + GetPrefetchedFilesListRequest request) throws ServiceException { + return null; + } + @Override public List getRegions() { return null; diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/rsgroup/VerifyingRSGroupAdmin.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/rsgroup/VerifyingRSGroupAdmin.java index 9b1d8524d003..356404bac06e 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/rsgroup/VerifyingRSGroupAdmin.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/rsgroup/VerifyingRSGroupAdmin.java @@ -959,6 +959,11 @@ public void flushMasterStore() throws IOException { admin.flushMasterStore(); } + @Override + public List getPrefetchedFilesList(ServerName serverName) throws IOException { + return admin.getPrefetchedFilesList(serverName); + } + @Override public boolean replicationPeerModificationSwitch(boolean on, boolean drainProcedures) throws IOException { diff --git a/hbase-thrift/src/main/java/org/apache/hadoop/hbase/thrift2/client/ThriftAdmin.java b/hbase-thrift/src/main/java/org/apache/hadoop/hbase/thrift2/client/ThriftAdmin.java index 1b7b6938524a..b44e18acc521 100644 --- a/hbase-thrift/src/main/java/org/apache/hadoop/hbase/thrift2/client/ThriftAdmin.java +++ b/hbase-thrift/src/main/java/org/apache/hadoop/hbase/thrift2/client/ThriftAdmin.java @@ -1335,6 +1335,11 @@ public void flushMasterStore() throws IOException { throw new NotImplementedException("flushMasterStore not supported in ThriftAdmin"); } + @Override + public List getPrefetchedFilesList(ServerName serverName) throws IOException { + throw new NotImplementedException("getPrefetchedFilesList not supported in ThriftAdmin"); + } + @Override public boolean replicationPeerModificationSwitch(boolean on, boolean drainProcedures) throws IOException {