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 org.apache.hadoop.conf.Configuration;
022import org.apache.hadoop.hbase.ipc.RpcControllerFactory;
023import org.apache.yetus.audience.InterfaceAudience;
024import org.slf4j.Logger;
025import org.slf4j.LoggerFactory;
026import org.apache.hbase.thirdparty.com.google.protobuf.ServiceException;
027import org.apache.hadoop.hbase.shaded.protobuf.RequestConverter;
028import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetTableStateResponse;
029import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.HbckService.BlockingInterface;
030
031
032/**
033 * Use {@link ClusterConnection#getHbck()} to obtain an instance of {@link Hbck} instead of
034 * constructing
035 * an HBaseHbck directly. This will be mostly used by hbck tool.
036 *
037 * <p>Connection should be an <i>unmanaged</i> connection obtained via
038 * {@link ConnectionFactory#createConnection(Configuration)}.</p>
039 *
040 * <p>An instance of this class is lightweight and not-thread safe. A new instance should be created
041 * by each thread. Pooling or caching of the instance is not recommended.</p>
042 *
043 * @see ConnectionFactory
044 * @see ClusterConnection
045 * @see Hbck
046 */
047@InterfaceAudience.Private
048public class HBaseHbck implements Hbck {
049  private static final Logger LOG = LoggerFactory.getLogger(HBaseHbck.class);
050
051  private boolean aborted;
052  private final BlockingInterface hbck;
053
054  private RpcControllerFactory rpcControllerFactory;
055
056  HBaseHbck(ClusterConnection connection, BlockingInterface hbck) throws IOException {
057    this.hbck = hbck;
058    this.rpcControllerFactory = connection.getRpcControllerFactory();
059  }
060
061  @Override
062  public void close() throws IOException {
063    // currently does nothing
064  }
065
066  @Override
067  public void abort(String why, Throwable e) {
068    this.aborted = true;
069    // Currently does nothing but throw the passed message and exception
070    throw new RuntimeException(why, e);
071  }
072
073  @Override
074  public boolean isAborted() {
075    return this.aborted;
076  }
077
078  /**
079   * NOTE: This is a dangerous action, as existing running procedures for the table or regions
080   * which belong to the table may get confused.
081   */
082  @Override
083  public TableState setTableStateInMeta(TableState state) throws IOException {
084    try {
085      GetTableStateResponse response = hbck.setTableStateInMeta(
086          rpcControllerFactory.newController(),
087          RequestConverter.buildSetTableStateInMetaRequest(state));
088      return TableState.convert(state.getTableName(), response.getTableState());
089    } catch (ServiceException se) {
090      LOG.debug("ServiceException while updating table state in meta. table={}, state={}",
091          state.getTableName(), state.getState());
092      throw new IOException(se);
093    }
094  }
095}