HBASE-3573 Move shutdown messaging OFF hearbeat; prereq for fix of hbase-1502
git-svn-id: https://svn.apache.org/repos/asf/hbase/trunk@1076019 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
b0b96dd3db
commit
6b014bbf3b
|
@ -90,6 +90,8 @@ Release 0.91.0 - Unreleased
|
|||
|
||||
TASK
|
||||
HBASE-3559 Move report of split to master OFF the heartbeat channel
|
||||
HBASE-3573 Move shutdown messaging OFF hearbeat; prereq for fix of
|
||||
hbase-1502
|
||||
|
||||
|
||||
NEW FEATURES
|
||||
|
|
|
@ -38,15 +38,9 @@ import org.apache.hadoop.io.Writable;
|
|||
* design, these are to go via zk from here on out.
|
||||
*/
|
||||
public class HMsg implements Writable {
|
||||
public static final HMsg [] STOP_REGIONSERVER_ARRAY =
|
||||
new HMsg [] {new HMsg(Type.STOP_REGIONSERVER)};
|
||||
public static final HMsg [] EMPTY_HMSG_ARRAY = new HMsg[0];
|
||||
|
||||
public static enum Type {
|
||||
/** Master tells region server to stop.
|
||||
*/
|
||||
STOP_REGIONSERVER,
|
||||
|
||||
/**
|
||||
* When RegionServer receives this message, it goes into a sleep that only
|
||||
* an exit will cure. This message is sent by unit tests simulating
|
||||
|
|
|
@ -504,7 +504,9 @@ public class HRegionInfo extends VersionedWritable implements WritableComparable
|
|||
return this.tableDesc.isRootRegion();
|
||||
}
|
||||
|
||||
/** @return true if this is the meta table */
|
||||
/** @return true if this region is from a table that is a meta table,
|
||||
* either <code>.META.</code> or <code>-ROOT-</code>
|
||||
*/
|
||||
public boolean isMetaTable() {
|
||||
return this.tableDesc.isMetaTable();
|
||||
}
|
||||
|
|
|
@ -249,7 +249,9 @@ public class HTableDescriptor implements WritableComparable<HTableDescriptor> {
|
|||
values.put(IS_META_KEY, isMeta? TRUE: FALSE);
|
||||
}
|
||||
|
||||
/** @return true if table is the meta table */
|
||||
/** @return true if table is a meta table, either <code>.META.</code> or
|
||||
* <code>-ROOT-</code>
|
||||
*/
|
||||
public boolean isMetaTable() {
|
||||
return isMetaRegion() && !isRootRegion();
|
||||
}
|
||||
|
|
|
@ -1963,6 +1963,40 @@ public class AssignmentManager extends ZooKeeperListener {
|
|||
unassign(plan.getRegionInfo());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param hsi
|
||||
* @return True if this server is carrying a catalog region, a region from
|
||||
* -ROOT- or .META. table.
|
||||
*/
|
||||
boolean isMetaRegionServer(final HServerInfo hsi) {
|
||||
synchronized (this.regions) {
|
||||
List<HRegionInfo> regions = this.servers.get(hsi);
|
||||
if (regions == null || regions.isEmpty()) return false;
|
||||
for (HRegionInfo hri: regions) {
|
||||
if (hri.isMetaRegion()) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run through remaining regionservers and unassign all catalog regions.
|
||||
*/
|
||||
void unassignCatalogRegions() {
|
||||
this.servers.entrySet();
|
||||
synchronized (this.regions) {
|
||||
for (Map.Entry<HServerInfo, List<HRegionInfo>> e: this.servers.entrySet()) {
|
||||
List<HRegionInfo> regions = e.getValue();
|
||||
if (regions == null || regions.isEmpty()) continue;
|
||||
for (HRegionInfo hri: regions) {
|
||||
if (hri.isMetaRegion()) {
|
||||
unassign(hri);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* State of a Region while undergoing transitions.
|
||||
*/
|
||||
|
|
|
@ -269,11 +269,6 @@ public class ServerManager {
|
|||
"ready next on next report");
|
||||
}
|
||||
|
||||
// Check startcodes
|
||||
if (raceThatShouldNotHappenAnymore(storedInfo, info)) {
|
||||
return HMsg.STOP_REGIONSERVER_ARRAY;
|
||||
}
|
||||
|
||||
for (HMsg msg: msgs) {
|
||||
LOG.info("Received " + msg + " from " + serverInfo.getServerName());
|
||||
switch (msg.getType()) {
|
||||
|
@ -283,39 +278,33 @@ public class ServerManager {
|
|||
}
|
||||
|
||||
HMsg [] reply = null;
|
||||
int numservers = countOfRegionServers();
|
||||
if (this.clusterShutdown) {
|
||||
if (numservers <= 2) {
|
||||
if (isOnlyMetaRegionServersOnline()) {
|
||||
LOG.info("Only catalog regions remaining; running unassign");
|
||||
// The only remaining regions are catalog regions.
|
||||
// Shutdown needs to be staggered; the meta regions need to close last
|
||||
// in case they need to be updated during the close melee. If <= 2
|
||||
// servers left, then these are the two that were carrying root and meta
|
||||
// most likely (TODO: This presumes unsplittable meta -- FIX). Tell
|
||||
// these servers can shutdown now too.
|
||||
reply = HMsg.STOP_REGIONSERVER_ARRAY;
|
||||
// in case they need to be updated during the close melee. If only
|
||||
// catalog reigons remaining, tell them they can go down now too. On
|
||||
// close of region, the regionservers should then shut themselves down.
|
||||
this.services.getAssignmentManager().unassignCatalogRegions();
|
||||
}
|
||||
}
|
||||
return processRegionServerAllsWell(info, mostLoadedRegions, reply);
|
||||
}
|
||||
|
||||
private boolean raceThatShouldNotHappenAnymore(final HServerInfo storedInfo,
|
||||
final HServerInfo reportedInfo) {
|
||||
if (storedInfo.getStartCode() != reportedInfo.getStartCode()) {
|
||||
// TODO: I don't think this possible any more. We check startcodes when
|
||||
// server comes in on regionServerStartup -- St.Ack
|
||||
// This state is reachable if:
|
||||
// 1) RegionServer A started
|
||||
// 2) RegionServer B started on the same machine, then clobbered A in regionServerStartup.
|
||||
// 3) RegionServer A returns, expecting to work as usual.
|
||||
// The answer is to ask A to shut down for good.
|
||||
LOG.warn("Race condition detected: " + reportedInfo.getServerName());
|
||||
synchronized (this.onlineServers) {
|
||||
removeServerInfo(reportedInfo.getServerName());
|
||||
notifyOnlineServers();
|
||||
/**
|
||||
* @return True if all online servers are carrying one or more catalog
|
||||
* regions, there are no servers online carrying user regions only
|
||||
*/
|
||||
private boolean isOnlyMetaRegionServersOnline() {
|
||||
List<HServerInfo> onlineServers = getOnlineServersList();
|
||||
for (HServerInfo hsi: onlineServers) {
|
||||
if (!this.services.getAssignmentManager().isMetaRegionServer(hsi)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* RegionServer is checking in, no exceptional circumstances
|
||||
|
|
|
@ -741,16 +741,6 @@ public class HRegionServer implements HRegionInterface, HBaseRPCErrorHandler,
|
|||
}
|
||||
updateOutboundMsgs(outboundMessages);
|
||||
outboundMessages.clear();
|
||||
|
||||
for (int i = 0; !this.stopped && msgs != null && i < msgs.length; i++) {
|
||||
LOG.info(msgs[i].toString());
|
||||
// Intercept stop regionserver messages
|
||||
if (msgs[i].getType().equals(HMsg.Type.STOP_REGIONSERVER)) {
|
||||
stop("Received " + msgs[i]);
|
||||
continue;
|
||||
}
|
||||
LOG.warn("NOT PROCESSING " + msgs[i] + " -- WHY IS MASTER SENDING IT TO US?");
|
||||
}
|
||||
return outboundMessages;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,69 +0,0 @@
|
|||
/**
|
||||
* Copyright 2009 The Apache Software Foundation
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.hadoop.hbase;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.hadoop.hbase.util.Bytes;
|
||||
import org.apache.hadoop.hbase.util.Writables;
|
||||
|
||||
public class TestHMsg extends TestCase {
|
||||
public void testList() {
|
||||
List<HMsg> msgs = new ArrayList<HMsg>();
|
||||
HMsg hmsg = null;
|
||||
final int size = 10;
|
||||
for (int i = 0; i < size; i++) {
|
||||
byte [] b = Bytes.toBytes(i);
|
||||
hmsg = new HMsg(HMsg.Type.STOP_REGIONSERVER,
|
||||
new HRegionInfo(new HTableDescriptor(Bytes.toBytes("test")), b, b));
|
||||
msgs.add(hmsg);
|
||||
}
|
||||
assertEquals(size, msgs.size());
|
||||
int index = msgs.indexOf(hmsg);
|
||||
assertNotSame(-1, index);
|
||||
msgs.remove(index);
|
||||
assertEquals(size - 1, msgs.size());
|
||||
byte [] other = Bytes.toBytes("other");
|
||||
hmsg = new HMsg(HMsg.Type.STOP_REGIONSERVER,
|
||||
new HRegionInfo(new HTableDescriptor(Bytes.toBytes("test")), other, other));
|
||||
assertEquals(-1, msgs.indexOf(hmsg));
|
||||
// Assert that two HMsgs are same if same content.
|
||||
byte [] b = Bytes.toBytes(1);
|
||||
hmsg = new HMsg(HMsg.Type.STOP_REGIONSERVER,
|
||||
new HRegionInfo(new HTableDescriptor(Bytes.toBytes("test")), b, b));
|
||||
assertNotSame(-1, msgs.indexOf(hmsg));
|
||||
}
|
||||
|
||||
public void testSerialization() throws IOException {
|
||||
byte [] parentbytes = Bytes.toBytes("parent");
|
||||
HRegionInfo parent =
|
||||
new HRegionInfo(new HTableDescriptor(Bytes.toBytes("parent")),
|
||||
parentbytes, parentbytes);
|
||||
// Assert simple HMsg serializes
|
||||
HMsg hmsg = new HMsg(HMsg.Type.STOP_REGIONSERVER, parent);
|
||||
byte [] bytes = Writables.getBytes(hmsg);
|
||||
HMsg close = (HMsg)Writables.getWritable(bytes, new HMsg());
|
||||
assertTrue(close.equals(hmsg));
|
||||
}
|
||||
}
|
|
@ -84,21 +84,6 @@ public class TestSerialization {
|
|||
assertTrue(Bytes.equals("value".getBytes(), hmw.get("key".getBytes())));
|
||||
}
|
||||
|
||||
@Test public void testHMsg() throws Exception {
|
||||
final String name = "testHMsg";
|
||||
HMsg m = new HMsg(HMsg.Type.STOP_REGIONSERVER);
|
||||
byte [] mb = Writables.getBytes(m);
|
||||
HMsg deserializedHMsg = (HMsg)Writables.getWritable(mb, new HMsg());
|
||||
assertTrue(m.equals(deserializedHMsg));
|
||||
m = new HMsg(HMsg.Type.STOP_REGIONSERVER,
|
||||
new HRegionInfo(new HTableDescriptor(name),
|
||||
HConstants.EMPTY_BYTE_ARRAY, HConstants.EMPTY_BYTE_ARRAY),
|
||||
"Some message".getBytes());
|
||||
mb = Writables.getBytes(m);
|
||||
deserializedHMsg = (HMsg)Writables.getWritable(mb, new HMsg());
|
||||
assertTrue(m.equals(deserializedHMsg));
|
||||
}
|
||||
|
||||
@Test public void testTableDescriptor() throws Exception {
|
||||
final String name = "testTableDescriptor";
|
||||
HTableDescriptor htd = createTableDescriptor(name);
|
||||
|
|
Loading…
Reference in New Issue