001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.client.example; 019 020import java.io.Closeable; 021import java.io.IOException; 022import org.apache.hadoop.conf.Configuration; 023import org.apache.hadoop.conf.Configured; 024import org.apache.hadoop.hbase.HBaseConfiguration; 025import org.apache.hadoop.hbase.HConstants; 026import org.apache.hadoop.hbase.TableName; 027import org.apache.hadoop.hbase.client.Connection; 028import org.apache.hadoop.hbase.client.ConnectionFactory; 029import org.apache.hadoop.hbase.client.Table; 030import org.apache.hadoop.hbase.client.coprocessor.Batch; 031import org.apache.hadoop.hbase.ipc.CoprocessorRpcUtils.BlockingRpcCallback; 032import org.apache.hadoop.hbase.ipc.ServerRpcController; 033import org.apache.hadoop.hbase.protobuf.generated.RefreshHFilesProtos; 034import org.apache.hadoop.util.Tool; 035import org.apache.hadoop.util.ToolRunner; 036import org.apache.yetus.audience.InterfaceAudience; 037import org.slf4j.Logger; 038import org.slf4j.LoggerFactory; 039 040/** 041 * This client class is for invoking the refresh HFile function deployed on the Region Server side 042 * via the RefreshHFilesService. 043 */ 044@InterfaceAudience.Private 045public class RefreshHFilesClient extends Configured implements Tool, Closeable { 046 private static final Logger LOG = LoggerFactory.getLogger(RefreshHFilesClient.class); 047 private final Connection connection; 048 049 /** 050 * Constructor with Conf object 051 * @param cfg the {@link Configuration} object to use 052 */ 053 public RefreshHFilesClient(Configuration cfg) { 054 try { 055 this.connection = ConnectionFactory.createConnection(cfg); 056 } catch (IOException e) { 057 throw new RuntimeException(e); 058 } 059 } 060 061 @Override 062 public void close() throws IOException { 063 if (this.connection != null && !this.connection.isClosed()) { 064 this.connection.close(); 065 } 066 } 067 068 public void refreshHFiles(final TableName tableName) throws Throwable { 069 try (Table table = connection.getTable(tableName)) { 070 refreshHFiles(table); 071 } 072 } 073 074 public void refreshHFiles(final Table table) throws Throwable { 075 final RefreshHFilesProtos.RefreshHFilesRequest request = 076 RefreshHFilesProtos.RefreshHFilesRequest.getDefaultInstance(); 077 table.coprocessorService(RefreshHFilesProtos.RefreshHFilesService.class, 078 HConstants.EMPTY_START_ROW, HConstants.EMPTY_END_ROW, new Batch.Call< 079 RefreshHFilesProtos.RefreshHFilesService, RefreshHFilesProtos.RefreshHFilesResponse>() { 080 @Override 081 public RefreshHFilesProtos.RefreshHFilesResponse 082 call(RefreshHFilesProtos.RefreshHFilesService refreshHFilesService) throws IOException { 083 ServerRpcController controller = new ServerRpcController(); 084 BlockingRpcCallback<RefreshHFilesProtos.RefreshHFilesResponse> rpcCallback = 085 new BlockingRpcCallback<>(); 086 refreshHFilesService.refreshHFiles(controller, request, rpcCallback); 087 088 if (controller.failedOnException()) { 089 throw controller.getFailedOn(); 090 } 091 092 return rpcCallback.get(); 093 } 094 }); 095 LOG.debug("Done refreshing HFiles"); 096 } 097 098 @Override 099 public int run(String[] args) throws Exception { 100 if (args.length != 1) { 101 String message = "When there are multiple HBase clusters are sharing a common root dir, " 102 + "especially for read replica cluster (see detail in HBASE-18477), please consider to " 103 + "use this tool manually sync the flushed HFiles from the source cluster."; 104 message += "\nUsage: " + this.getClass().getName() + " tableName"; 105 System.out.println(message); 106 return -1; 107 } 108 final TableName tableName = TableName.valueOf(args[0]); 109 try { 110 refreshHFiles(tableName); 111 } catch (Throwable t) { 112 LOG.error("Refresh HFiles from table " + tableName.getNameAsString() + " failed: ", t); 113 return -1; 114 } 115 return 0; 116 } 117 118 public static void main(String[] args) throws Exception { 119 ToolRunner.run(new RefreshHFilesClient(HBaseConfiguration.create()), args); 120 } 121}