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