HBASE-5935 Add Region-level PB-based calls to HMasterInterface

git-svn-id: https://svn.apache.org/repos/asf/hbase/trunk@1339488 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Michael Stack 2012-05-17 05:06:15 +00:00
parent 4fb583bafb
commit c18eebd8a6
8 changed files with 3270 additions and 115 deletions

View File

@ -37,6 +37,7 @@ import org.apache.hadoop.classification.InterfaceStability;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.Abortable;
import org.apache.hadoop.hbase.ClusterStatus;
import org.apache.hadoop.hbase.DeserializationException;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.HConstants;
@ -60,6 +61,7 @@ import org.apache.hadoop.hbase.ipc.HMasterInterface;
import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
import org.apache.hadoop.hbase.protobuf.RequestConverter;
import org.apache.hadoop.hbase.protobuf.ResponseConverter;
import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos;
import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.CloseRegionRequest;
import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.CloseRegionResponse;
import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.CompactRegionRequest;
@ -69,6 +71,11 @@ import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.RollWALWriterRespo
import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.StopServerRequest;
import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.ScanRequest;
import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.ScanResponse;
import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.RegionSpecifier;
import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.RegionSpecifier.RegionSpecifierType;
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.AssignRegionRequest;
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.MoveRegionRequest;
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.UnassignRegionRequest;
import org.apache.hadoop.hbase.regionserver.wal.FailedLogCloseException;
import org.apache.hadoop.hbase.util.Addressing;
import org.apache.hadoop.hbase.util.Bytes;
@ -1352,8 +1359,18 @@ public class HBaseAdmin implements Abortable, Closeable {
throws UnknownRegionException, MasterNotRunningException, ZooKeeperConnectionException {
MasterKeepAliveConnection master = connection.getKeepAliveMaster();
try {
master.move(encodedRegionName, destServerName);
} finally {
MoveRegionRequest request = RequestConverter.buildMoveRegionRequest(encodedRegionName, destServerName);
master.moveRegion(null,request);
} catch (ServiceException se) {
IOException ioe = ProtobufUtil.getRemoteException(se);
if (ioe instanceof UnknownRegionException) {
throw (UnknownRegionException)ioe;
}
LOG.error("Unexpected exception: " + se + " from calling HMaster.moveRegion");
} catch (DeserializationException de) {
LOG.error("Could not parse destination server name: " + de);
}
finally {
master.close();
}
}
@ -1369,8 +1386,9 @@ public class HBaseAdmin implements Abortable, Closeable {
ZooKeeperConnectionException, IOException {
execute(new MasterCallable<Void>() {
@Override
public Void call() throws IOException {
master.assign(regionName);
public Void call() throws ServiceException {
AssignRegionRequest request = RequestConverter.buildAssignRegionRequest(regionName);
master.assignRegion(null,request);
return null;
}
});
@ -1394,8 +1412,10 @@ public class HBaseAdmin implements Abortable, Closeable {
throws MasterNotRunningException, ZooKeeperConnectionException, IOException {
execute(new MasterCallable<Void>() {
@Override
public Void call() throws IOException {
master.unassign(regionName, force);
public Void call() throws ServiceException {
UnassignRegionRequest request =
RequestConverter.buildUnassignRegionRequest(regionName, force);
master.unassignRegion(null,request);
return null;
}
});
@ -1806,6 +1826,8 @@ public class HBaseAdmin implements Abortable, Closeable {
throw re.unwrapRemoteException();
} catch (IOException e) {
throw e;
} catch (ServiceException se) {
throw ProtobufUtil.getRemoteException(se);
} catch (Exception e) {
// This should not happen...
throw new IOException("Unexpected exception when calling master", e);

View File

@ -27,11 +27,19 @@ import org.apache.hadoop.classification.InterfaceStability;
import org.apache.hadoop.hbase.ClusterStatus;
import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.UnknownRegionException;
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.AssignRegionRequest;
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.AssignRegionResponse;
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.MoveRegionRequest;
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.MoveRegionResponse;
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.UnassignRegionRequest;
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.UnassignRegionResponse;
import org.apache.hadoop.hbase.security.TokenInfo;
import org.apache.hadoop.hbase.security.KerberosInfo;
import org.apache.hadoop.hbase.util.Pair;
import com.google.protobuf.RpcController;
import com.google.protobuf.ServiceException;
/**
* Clients interact with the HMasterInterface to gain access to meta-level
* HBase functionality, like finding an HRegionServer and creating/destroying
@ -56,7 +64,8 @@ public interface HMasterInterface extends VersionedProtocol {
// had changed. This has since been undone.
// 29: 4/3/2010 - changed ClusterStatus serialization
// 30: 3/20/2012 - HBASE-5589: Added offline method
public static final long VERSION = 30L;
// 31: 5/8/2012 - HBASE-5445: Converted to PB-based calls
public static final long VERSION = 31L;
/** @return true if master is available */
public boolean isMasterRunning();
@ -166,58 +175,6 @@ public interface HMasterInterface extends VersionedProtocol {
*/
public ClusterStatus getClusterStatus();
/**
* Move the region <code>r</code> to <code>dest</code>.
* @param encodedRegionName The encoded region name; i.e. the hash that makes
* up the region name suffix: e.g. if regionname is
* <code>TestTable,0094429456,1289497600452.527db22f95c8a9e0116f0cc13c680396.</code>,
* then the encoded region name is: <code>527db22f95c8a9e0116f0cc13c680396</code>.
* @param destServerName The servername of the destination regionserver. If
* passed the empty byte array we'll assign to a random server. A server name
* is made of host, port and startcode. Here is an example:
* <code> host187.example.com,60020,1289493121758</code>.
* @throws UnknownRegionException Thrown if we can't find a region named
* <code>encodedRegionName</code>
*/
public void move(final byte [] encodedRegionName, final byte [] destServerName)
throws UnknownRegionException;
/**
* Assign a region to a server chosen at random.
* @param regionName Region to assign. Will use existing RegionPlan if one
* found.
* @param force If true, will force the assignment.
* @throws IOException
* @deprecated The <code>force</code> is unused.Use {@link #assign(byte[])}
*/
public void assign(final byte [] regionName, final boolean force)
throws IOException;
/**
* Assign a region to a server chosen at random.
*
* @param regionName
* Region to assign. Will use existing RegionPlan if one found.
* @throws IOException
*/
public void assign(final byte[] regionName) throws IOException;
/**
* Unassign a region from current hosting regionserver. Region will then be
* assigned to a regionserver chosen at random. Region could be reassigned
* back to the same server. Use {@link #move(byte[], byte[])} if you want
* to control the region movement.
* @param regionName Region to unassign. Will clear any existing RegionPlan
* if one found.
* @param force If true, force unassign (Will remove region from
* regions-in-transition too if present as well as from assigned regions --
* radical!.If results in double assignment use hbck -fix to resolve.
* @throws IOException
*/
public void unassign(final byte [] regionName, final boolean force)
throws IOException;
/**
* Offline a region from the assignment manager's in-memory state. The
* region should be in a closed state and there will be no attempt to
@ -266,4 +223,49 @@ public interface HMasterInterface extends VersionedProtocol {
* @return array of HTableDescriptor
*/
public HTableDescriptor[] getHTableDescriptors(List<String> tableNames);
/**
* Assign a region to a server chosen at random.
* @param controller Unused (set to null).
* @param req contains the region to assign. Will use existing RegionPlan if one
* found.
* @throws ServiceException
*/
public AssignRegionResponse assignRegion(RpcController controller, AssignRegionRequest req)
throws ServiceException;
/**
* Unassign a region from current hosting regionserver. Region will then be
* assigned to a regionserver chosen at random. Region could be reassigned
* back to the same server. Use {@link #moveRegion(RpcController,MoveRegionRequest}
* if you want to control the region movement.
* @param controller Unused (set to null).
* @param req The request which contains:
* - region: Region to unassign. Will clear any existing RegionPlan
* if one found.
* - force: If true, force unassign (Will remove region from
* regions-in-transition too if present as well as from assigned regions --
* radical!.If results in double assignment use hbck -fix to resolve.
* @throws ServiceException
*/
public UnassignRegionResponse unassignRegion(RpcController controller, UnassignRegionRequest req)
throws ServiceException;
/**
* Move a region to a specified destination server.
* @param controller Unused (set to null).
* @param req The request which contains:
* - region: The encoded region name; i.e. the hash that makes
* up the region name suffix: e.g. if regionname is
* <code>TestTable,0094429456,1289497600452.527db22f95c8a9e0116f0cc13c680396.</code>,
* then the encoded region name is: <code>527db22f95c8a9e0116f0cc13c680396</code>.
* - destServerName: The servername of the destination regionserver. If
* passed the empty byte array we'll assign to a random server. A server name
* is made of host, port and startcode. Here is an example:
* <code> host187.example.com,60020,1289493121758</code>.
* @throws ServiceException that wraps a UnknownRegionException if we can't find a
* region named <code>encodedRegionName</code>
*/
public MoveRegionResponse moveRegion(RpcController controller, MoveRegionRequest req)
throws ServiceException;
}

View File

@ -117,8 +117,16 @@ import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.Watcher;
import org.apache.hadoop.hbase.ServerLoad;
import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.NameStringPair;
import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.RegionSpecifier.RegionSpecifierType;
import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos;
import com.google.protobuf.RpcController;
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.AssignRegionRequest;
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.AssignRegionResponse;
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.MoveRegionRequest;
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.MoveRegionResponse;
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.UnassignRegionRequest;
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.UnassignRegionResponse;
import org.apache.hadoop.hbase.protobuf.generated.RegionServerStatusProtos.RegionServerReportRequest;
import org.apache.hadoop.hbase.protobuf.generated.RegionServerStatusProtos.RegionServerReportResponse;
import org.apache.hadoop.hbase.protobuf.generated.RegionServerStatusProtos.ReportRSFatalErrorRequest;
@ -1200,12 +1208,24 @@ Server {
}
@Override
public void move(final byte[] encodedRegionName, final byte[] destServerName)
throws UnknownRegionException {
public MoveRegionResponse moveRegion(RpcController controller, MoveRegionRequest req)
throws ServiceException {
final byte [] encodedRegionName = req.getRegion().getValue().toByteArray();
RegionSpecifierType type = req.getRegion().getType();
final byte [] destServerName = (req.hasDestServerName())?
Bytes.toBytes(ProtobufUtil.toServerName(req.getDestServerName()).getServerName()):null;
MoveRegionResponse mrr = MoveRegionResponse.newBuilder().build();
if (type != RegionSpecifierType.ENCODED_REGION_NAME) {
LOG.warn("moveRegion specifier type: expected: " + RegionSpecifierType.ENCODED_REGION_NAME
+ " actual: " + RegionSpecifierType.REGION_NAME);
}
Pair<HRegionInfo, ServerName> p =
this.assignmentManager.getAssignment(encodedRegionName);
if (p == null)
throw new UnknownRegionException(Bytes.toStringBinary(encodedRegionName));
if (p == null) {
throw new ServiceException(
new UnknownRegionException(Bytes.toStringBinary(encodedRegionName)));
}
HRegionInfo hri = p.getFirst();
ServerName dest;
if (destServerName == null || destServerName.length == 0) {
@ -1219,7 +1239,7 @@ Server {
if (dest.equals(p.getSecond())) {
LOG.debug("Skipping move of region " + hri.getRegionNameAsString()
+ " because region already assigned to the same server " + dest + ".");
return;
return mrr;
}
}
@ -1229,7 +1249,7 @@ Server {
try {
if (this.cpHost != null) {
if (this.cpHost.preMove(hri, rp.getSource(), rp.getDestination())) {
return;
return mrr;
}
}
LOG.info("Added move plan " + rp + ", running balancer");
@ -1241,8 +1261,9 @@ Server {
UnknownRegionException ure = new UnknownRegionException(
Bytes.toStringBinary(encodedRegionName));
ure.initCause(ioe);
throw ure;
throw new ServiceException(ure);
}
return mrr;
}
public void createTable(HTableDescriptor hTableDescriptor,
@ -1783,46 +1804,62 @@ Server {
}
@Override
@Deprecated
public void assign(final byte[] regionName, final boolean force)
throws IOException {
assign(regionName);
}
public AssignRegionResponse assignRegion(RpcController controller, AssignRegionRequest req)
throws ServiceException {
try {
final byte [] regionName = req.getRegion().getValue().toByteArray();
RegionSpecifierType type = req.getRegion().getType();
AssignRegionResponse arr = AssignRegionResponse.newBuilder().build();
@Override
public void assign(final byte [] regionName)throws IOException {
checkInitialized();
if (type != RegionSpecifierType.REGION_NAME) {
LOG.warn("assignRegion specifier type: expected: " + RegionSpecifierType.REGION_NAME
+ " actual: " + RegionSpecifierType.ENCODED_REGION_NAME);
}
Pair<HRegionInfo, ServerName> pair =
MetaReader.getRegion(this.catalogTracker, regionName);
if (pair == null) throw new UnknownRegionException(Bytes.toString(regionName));
if (cpHost != null) {
if (cpHost.preAssign(pair.getFirst())) {
return;
return arr;
}
}
assignRegion(pair.getFirst());
if (cpHost != null) {
cpHost.postAssign(pair.getFirst());
}
return arr;
} catch (IOException ioe) {
throw new ServiceException(ioe);
}
}
public void assignRegion(HRegionInfo hri) {
assignmentManager.assign(hri, true);
}
@Override
public void unassign(final byte [] regionName, final boolean force)
throws IOException {
public UnassignRegionResponse unassignRegion(RpcController controller, UnassignRegionRequest req)
throws ServiceException {
try {
final byte [] regionName = req.getRegion().getValue().toByteArray();
RegionSpecifierType type = req.getRegion().getType();
final boolean force = req.getForce();
UnassignRegionResponse urr = UnassignRegionResponse.newBuilder().build();
checkInitialized();
if (type != RegionSpecifierType.REGION_NAME) {
LOG.warn("unassignRegion specifier type: expected: " + RegionSpecifierType.REGION_NAME
+ " actual: " + RegionSpecifierType.ENCODED_REGION_NAME);
}
Pair<HRegionInfo, ServerName> pair =
MetaReader.getRegion(this.catalogTracker, regionName);
if (pair == null) throw new UnknownRegionException(Bytes.toString(regionName));
HRegionInfo hri = pair.getFirst();
if (cpHost != null) {
if (cpHost.preUnassign(hri, force)) {
return;
return urr;
}
}
if (force) {
@ -1834,6 +1871,11 @@ Server {
if (cpHost != null) {
cpHost.postUnassign(hri, force);
}
return urr;
} catch (IOException ioe) {
throw new ServiceException(ioe);
}
}
/**

View File

@ -24,6 +24,7 @@ import java.util.NavigableMap;
import java.util.UUID;
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.hbase.DeserializationException;
import org.apache.hadoop.hbase.DoNotRetryIOException;
import org.apache.hadoop.hbase.HRegionInfo;
import org.apache.hadoop.hbase.KeyValue;
@ -77,6 +78,9 @@ import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.ScanRequest;
import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.UnlockRowRequest;
import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.RegionSpecifier;
import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.RegionSpecifier.RegionSpecifierType;
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.AssignRegionRequest;
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.MoveRegionRequest;
import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.UnassignRegionRequest;
import org.apache.hadoop.hbase.regionserver.wal.HLog;
import org.apache.hadoop.hbase.regionserver.wal.HLogKey;
import org.apache.hadoop.hbase.regionserver.wal.WALEdit;
@ -832,4 +836,52 @@ public final class RequestConverter {
builder.setCompareType(compareType);
return builder.build();
}
/**
* Create a protocol buffer MoveRegionRequest
*
* @param encodedRegionName
* @param destServerName
* @return A MoveRegionRequest
* @throws DeserializationException
*/
public static MoveRegionRequest buildMoveRegionRequest(
final byte [] encodedRegionName, final byte [] destServerName) throws DeserializationException {
MoveRegionRequest.Builder builder = MoveRegionRequest.newBuilder();
builder.setRegion(
buildRegionSpecifier(RegionSpecifierType.ENCODED_REGION_NAME,encodedRegionName));
if (destServerName != null) {
builder.setDestServerName(
ProtobufUtil.toServerName(new ServerName(Bytes.toString(destServerName))));
}
return builder.build();
}
/**
* Create a protocol buffer AssignRegionRequest
*
* @param regionName
* @return An AssignRegionRequest
*/
public static AssignRegionRequest buildAssignRegionRequest(final byte [] regionName) {
AssignRegionRequest.Builder builder = AssignRegionRequest.newBuilder();
builder.setRegion(buildRegionSpecifier(RegionSpecifierType.REGION_NAME,regionName));
return builder.build();
}
/**
* Creates a protocol buffer UnassignRegionRequest
*
* @param regionName
* @param force
* @return An UnassignRegionRequest
*/
public static UnassignRegionRequest buildUnassignRegionRequest(
final byte [] regionName, final boolean force) {
UnassignRegionRequest.Builder builder = UnassignRegionRequest.newBuilder();
RegionSpecifier.Builder rspec = RegionSpecifier.newBuilder();
builder.setRegion(buildRegionSpecifier(RegionSpecifierType.REGION_NAME,regionName));
builder.setForce(force);
return builder.build();
}
}

File diff suppressed because it is too large Load Diff

View File

@ -16,7 +16,7 @@
* limitations under the License.
*/
// This file contains protocol buffers that are used for MasterRegionProtocol.
// This file contains protocol buffers that are used for RegionServerStatusProtocol.
option java_package = "org.apache.hadoop.hbase.protobuf.generated";
option java_outer_classname = "RegionServerStatusProtos";

View File

@ -31,6 +31,7 @@ import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.hbase.client.HBaseAdmin;
import org.apache.hadoop.hbase.master.AssignmentManager;
import org.apache.hadoop.hbase.master.HMaster;
import org.apache.hadoop.hbase.protobuf.RequestConverter;
import org.apache.hadoop.hbase.master.ServerManager;
import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
import org.apache.hadoop.hbase.regionserver.HRegion;
@ -47,6 +48,8 @@ import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import com.google.protobuf.ServiceException;
/**
* Test the draining servers feature.
* @see <a href="https://issues.apache.org/jira/browse/HBASE-4298">HBASE-4298</a>
@ -138,7 +141,7 @@ public class TestDrainingServer {
*/
@Test // (timeout=30000)
public void testDrainingServerOffloading()
throws IOException, KeeperException {
throws IOException, KeeperException, ServiceException, DeserializationException {
// I need master in the below.
HMaster master = TEST_UTIL.getMiniHBaseCluster().getMaster();
HRegionInfo hriToMoveBack = null;
@ -153,7 +156,8 @@ public class TestDrainingServer {
for (HRegionInfo hri : hris) {
// Pass null and AssignmentManager will chose a random server BUT it
// should exclude draining servers.
master.move(hri.getEncodedNameAsBytes(), null);
master.moveRegion(null,
RequestConverter.buildMoveRegionRequest(hri.getEncodedNameAsBytes(), null));
// Save off region to move back.
hriToMoveBack = hri;
}
@ -165,8 +169,9 @@ public class TestDrainingServer {
}
// Now we've unset the draining server, we should be able to move a region
// to what was the draining server.
master.move(hriToMoveBack.getEncodedNameAsBytes(),
Bytes.toBytes(drainingServer.getServerName().toString()));
master.moveRegion(null,
RequestConverter.buildMoveRegionRequest(hriToMoveBack.getEncodedNameAsBytes(),
Bytes.toBytes(drainingServer.getServerName().toString())));
// Wait for regions to come back on line again.
waitForAllRegionsOnline();
Assert.assertEquals(1, drainingServer.getNumberOfOnlineRegions());

View File

@ -41,6 +41,7 @@ import org.apache.hadoop.hbase.client.HTable;
import org.apache.hadoop.hbase.master.AssignmentManager;
import org.apache.hadoop.hbase.master.HMaster;
import org.apache.hadoop.hbase.master.MasterCoprocessorHost;
import org.apache.hadoop.hbase.protobuf.RequestConverter;
import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
import org.apache.hadoop.hbase.regionserver.HRegionServer;
import org.apache.hadoop.hbase.util.Bytes;
@ -945,8 +946,8 @@ public class TestMasterObserver {
}
assertTrue("Found server", found);
LOG.info("Found " + destName);
master.move(firstGoodPair.getKey().getEncodedNameAsBytes(),
Bytes.toBytes(destName));
master.moveRegion(null,RequestConverter.buildMoveRegionRequest(
firstGoodPair.getKey().getEncodedNameAsBytes(),Bytes.toBytes(destName)));
assertTrue("Coprocessor should have been called on region move",
cp.wasMoveCalled());
@ -965,7 +966,8 @@ public class TestMasterObserver {
for (int i=0; i<moveCnt; i++) {
HRegionInfo info = openRegions.get(i);
if (!info.isMetaTable()) {
master.move(openRegions.get(i).getEncodedNameAsBytes(), destRS);
master.moveRegion(null,RequestConverter.buildMoveRegionRequest(
openRegions.get(i).getEncodedNameAsBytes(), destRS));
}
}