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; 019 020import java.io.IOException; 021import java.util.List; 022import java.util.concurrent.Callable; 023import java.util.stream.Collectors; 024 025import org.apache.hadoop.conf.Configuration; 026import org.apache.hadoop.hbase.ipc.RpcControllerFactory; 027import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil; 028import org.apache.hadoop.hbase.shaded.protobuf.RequestConverter; 029import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos; 030import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos; 031import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetTableStateResponse; 032import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.HbckService.BlockingInterface; 033import org.apache.hbase.thirdparty.com.google.protobuf.ServiceException; 034import org.apache.yetus.audience.InterfaceAudience; 035import org.slf4j.Logger; 036import org.slf4j.LoggerFactory; 037 038 039/** 040 * Use {@link ClusterConnection#getHbck()} to obtain an instance of {@link Hbck} instead of 041 * constructing 042 * an HBaseHbck directly. This will be mostly used by hbck tool. 043 * 044 * <p>Connection should be an <i>unmanaged</i> connection obtained via 045 * {@link ConnectionFactory#createConnection(Configuration)}.</p> 046 * 047 * <p>An instance of this class is lightweight and not-thread safe. A new instance should be created 048 * by each thread. Pooling or caching of the instance is not recommended.</p> 049 * 050 * @see ConnectionFactory 051 * @see ClusterConnection 052 * @see Hbck 053 */ 054@InterfaceAudience.Private 055public class HBaseHbck implements Hbck { 056 private static final Logger LOG = LoggerFactory.getLogger(HBaseHbck.class); 057 058 private boolean aborted; 059 private final BlockingInterface hbck; 060 061 private RpcControllerFactory rpcControllerFactory; 062 063 HBaseHbck(ClusterConnection connection, BlockingInterface hbck) throws IOException { 064 this.hbck = hbck; 065 this.rpcControllerFactory = connection.getRpcControllerFactory(); 066 } 067 068 @Override 069 public void close() throws IOException { 070 // currently does nothing 071 } 072 073 @Override 074 public void abort(String why, Throwable e) { 075 this.aborted = true; 076 // Currently does nothing but throw the passed message and exception 077 throw new RuntimeException(why, e); 078 } 079 080 @Override 081 public boolean isAborted() { 082 return this.aborted; 083 } 084 085 /** 086 * NOTE: This is a dangerous action, as existing running procedures for the table or regions 087 * which belong to the table may get confused. 088 */ 089 @Override 090 public TableState setTableStateInMeta(TableState state) throws IOException { 091 try { 092 GetTableStateResponse response = hbck.setTableStateInMeta( 093 rpcControllerFactory.newController(), 094 RequestConverter.buildSetTableStateInMetaRequest(state)); 095 return TableState.convert(state.getTableName(), response.getTableState()); 096 } catch (ServiceException se) { 097 LOG.debug("table={}, state={}", state.getTableName(), state.getState(), se); 098 throw new IOException(se); 099 } 100 } 101 102 @Override 103 public List<Long> assigns(List<String> encodedRegionNames, boolean override) 104 throws IOException { 105 try { 106 MasterProtos.AssignsResponse response = 107 this.hbck.assigns(rpcControllerFactory.newController(), 108 RequestConverter.toAssignRegionsRequest(encodedRegionNames, override)); 109 return response.getPidList(); 110 } catch (ServiceException se) { 111 LOG.debug(toCommaDelimitedString(encodedRegionNames), se); 112 throw new IOException(se); 113 } 114 } 115 116 @Override 117 public List<Long> unassigns(List<String> encodedRegionNames, boolean override) 118 throws IOException { 119 try { 120 MasterProtos.UnassignsResponse response = 121 this.hbck.unassigns(rpcControllerFactory.newController(), 122 RequestConverter.toUnassignRegionsRequest(encodedRegionNames, override)); 123 return response.getPidList(); 124 } catch (ServiceException se) { 125 LOG.debug(toCommaDelimitedString(encodedRegionNames), se); 126 throw new IOException(se); 127 } 128 } 129 130 private static String toCommaDelimitedString(List<String> list) { 131 return list.stream().collect(Collectors.joining(", ")); 132 } 133 134 @Override 135 public List<Boolean> bypassProcedure(List<Long> pids, long waitTime, boolean override, 136 boolean recursive) 137 throws IOException { 138 MasterProtos.BypassProcedureResponse response = ProtobufUtil.call( 139 new Callable<MasterProtos.BypassProcedureResponse>() { 140 @Override 141 public MasterProtos.BypassProcedureResponse call() throws Exception { 142 try { 143 return hbck.bypassProcedure(rpcControllerFactory.newController(), 144 MasterProtos.BypassProcedureRequest.newBuilder().addAllProcId(pids). 145 setWaitTime(waitTime).setOverride(override).setRecursive(recursive).build()); 146 } catch (Throwable t) { 147 LOG.error(pids.stream().map(i -> i.toString()). 148 collect(Collectors.joining(", ")), t); 149 throw t; 150 } 151 } 152 }); 153 return response.getBypassedList(); 154 } 155 156 @Override 157 public List<Long> scheduleServerCrashProcedure(List<HBaseProtos.ServerName> serverNames) 158 throws IOException { 159 try { 160 MasterProtos.ScheduleServerCrashProcedureResponse response = 161 this.hbck.scheduleServerCrashProcedure(rpcControllerFactory.newController(), 162 RequestConverter.toScheduleServerCrashProcedureRequest(serverNames)); 163 return response.getPidList(); 164 } catch (ServiceException se) { 165 LOG.debug(toCommaDelimitedString( 166 serverNames.stream().map(serverName -> ProtobufUtil.toServerName(serverName).toString()) 167 .collect(Collectors.toList())), 168 se); 169 throw new IOException(se); 170 } 171 } 172}