HADOOP-2338 Fix NullPointerException in master server.

git-svn-id: https://svn.apache.org/repos/asf/lucene/hadoop/trunk/src/contrib/hbase@602226 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Jim Kellerman 2007-12-07 21:23:54 +00:00
parent bccf1dc26f
commit 612f446dbd
6 changed files with 524 additions and 365 deletions

View File

@ -60,6 +60,7 @@ Trunk (unreleased changes)
(Bryan Duxbury via Stack) (Bryan Duxbury via Stack)
HADOOP-2365 Result of HashFunction.hash() contains all identical values HADOOP-2365 Result of HashFunction.hash() contains all identical values
HADOOP-2362 Leaking hdfs file handle on region split HADOOP-2362 Leaking hdfs file handle on region split
HADOOP-2338 Fix NullPointerException in master server.
IMPROVEMENTS IMPROVEMENTS
HADOOP-2401 Add convenience put method that takes writable HADOOP-2401 Add convenience put method that takes writable

File diff suppressed because it is too large Load Diff

View File

@ -49,6 +49,9 @@ public class HMsg implements Writable {
/** Stop serving the specified region and don't report back that it's closed */ /** Stop serving the specified region and don't report back that it's closed */
public static final byte MSG_REGION_CLOSE_WITHOUT_REPORT = 6; public static final byte MSG_REGION_CLOSE_WITHOUT_REPORT = 6;
/** Stop serving user regions */
public static final byte MSG_REGIONSERVER_QUIESCE = 7;
// Messages sent from the region server to the master // Messages sent from the region server to the master
/** region server is now serving the specified region */ /** region server is now serving the specified region */
@ -72,10 +75,13 @@ public class HMsg implements Writable {
* region server is shutting down * region server is shutting down
* *
* note that this message is followed by MSG_REPORT_CLOSE messages for each * note that this message is followed by MSG_REPORT_CLOSE messages for each
* region the region server was serving. * region the region server was serving, unless it was told to quiesce.
*/ */
public static final byte MSG_REPORT_EXITING = 104; public static final byte MSG_REPORT_EXITING = 104;
/** region server has closed all user regions but is still serving meta regions */
public static final byte MSG_REPORT_QUIESCED = 105;
byte msg; byte msg;
HRegionInfo info; HRegionInfo info;
@ -148,6 +154,10 @@ public class HMsg implements Writable {
message.append("MSG_REGION_CLOSE_WITHOUT_REPORT : "); message.append("MSG_REGION_CLOSE_WITHOUT_REPORT : ");
break; break;
case MSG_REGIONSERVER_QUIESCE:
message.append("MSG_REGIONSERVER_QUIESCE : ");
break;
case MSG_REPORT_PROCESS_OPEN: case MSG_REPORT_PROCESS_OPEN:
message.append("MSG_REPORT_PROCESS_OPEN : "); message.append("MSG_REPORT_PROCESS_OPEN : ");
break; break;
@ -168,6 +178,10 @@ public class HMsg implements Writable {
message.append("MSG_REPORT_EXITING : "); message.append("MSG_REPORT_EXITING : ");
break; break;
case MSG_REPORT_QUIESCED:
message.append("MSG_REPORT_QUIESCED : ");
break;
default: default:
message.append("unknown message code ("); message.append("unknown message code (");
message.append(msg); message.append(msg);

View File

@ -193,6 +193,21 @@ public class HRegionInfo implements WritableComparable {
return tableDesc; return tableDesc;
} }
/** @return true if this is the root region */
public boolean isRootRegion() {
return this.tableDesc.isRootRegion();
}
/** @return true if this is the meta table */
public boolean isMetaTable() {
return this.tableDesc.isMetaTable();
}
/** @return true if this region is a meta region */
public boolean isMetaRegion() {
return this.tableDesc.isMetaRegion();
}
/** /**
* @return True if has been split and has daughters. * @return True if has been split and has daughters.
*/ */

View File

@ -81,6 +81,8 @@ public class HRegionServer implements HConstants, HRegionInterface, Runnable {
// Chore threads need to know about the hosting class. // Chore threads need to know about the hosting class.
protected final AtomicBoolean stopRequested = new AtomicBoolean(false); protected final AtomicBoolean stopRequested = new AtomicBoolean(false);
protected final AtomicBoolean quiesced = new AtomicBoolean(false);
// Go down hard. Used if file system becomes unavailable and also in // Go down hard. Used if file system becomes unavailable and also in
// debugging and unit tests. // debugging and unit tests.
protected volatile boolean abortRequested; protected volatile boolean abortRequested;
@ -652,6 +654,7 @@ public class HRegionServer implements HConstants, HRegionInterface, Runnable {
* load/unload instructions. * load/unload instructions.
*/ */
public void run() { public void run() {
boolean quiesceRequested = false;
try { try {
init(reportForDuty()); init(reportForDuty());
long lastMsg = 0; long lastMsg = 0;
@ -682,6 +685,16 @@ public class HRegionServer implements HConstants, HRegionInterface, Runnable {
HMsg msgs[] = HMsg msgs[] =
this.hbaseMaster.regionServerReport(serverInfo, outboundArray); this.hbaseMaster.regionServerReport(serverInfo, outboundArray);
lastMsg = System.currentTimeMillis(); lastMsg = System.currentTimeMillis();
if (this.quiesced.get() && onlineRegions.size() == 0) {
// We've just told the master we're exiting because we aren't
// serving any regions. So set the stop bit and exit.
LOG.info("Server quiesced and not serving any regions. " +
"Starting shutdown");
stopRequested.set(true);
continue;
}
// Queue up the HMaster's instruction stream for processing // Queue up the HMaster's instruction stream for processing
boolean restart = false; boolean restart = false;
for(int i = 0; i < msgs.length && !stopRequested.get() && for(int i = 0; i < msgs.length && !stopRequested.get() &&
@ -689,9 +702,7 @@ public class HRegionServer implements HConstants, HRegionInterface, Runnable {
switch(msgs[i].getMsg()) { switch(msgs[i].getMsg()) {
case HMsg.MSG_CALL_SERVER_STARTUP: case HMsg.MSG_CALL_SERVER_STARTUP:
if (LOG.isDebugEnabled()) { LOG.info("Got call server startup message");
LOG.debug("Got call server startup message");
}
// We the MSG_CALL_SERVER_STARTUP on startup but we can also // We the MSG_CALL_SERVER_STARTUP on startup but we can also
// get it when the master is panicing because for instance // get it when the master is panicing because for instance
// the HDFS has been yanked out from under it. Be wary of // the HDFS has been yanked out from under it. Be wary of
@ -725,12 +736,23 @@ public class HRegionServer implements HConstants, HRegionInterface, Runnable {
break; break;
case HMsg.MSG_REGIONSERVER_STOP: case HMsg.MSG_REGIONSERVER_STOP:
if (LOG.isDebugEnabled()) { LOG.info("Got regionserver stop message");
LOG.debug("Got regionserver stop message");
}
stopRequested.set(true); stopRequested.set(true);
break; break;
case HMsg.MSG_REGIONSERVER_QUIESCE:
if (!quiesceRequested) {
LOG.info("Got quiesce server message");
try {
toDo.put(new ToDoEntry(msgs[i]));
} catch (InterruptedException e) {
throw new RuntimeException("Putting into msgQueue was " +
"interrupted.", e);
}
quiesceRequested = true;
}
break;
default: default:
if (fsOk) { if (fsOk) {
try { try {
@ -1102,6 +1124,10 @@ public class HRegionServer implements HConstants, HRegionInterface, Runnable {
LOG.info(e.msg.toString()); LOG.info(e.msg.toString());
switch(e.msg.getMsg()) { switch(e.msg.getMsg()) {
case HMsg.MSG_REGIONSERVER_QUIESCE:
closeUserRegions();
break;
case HMsg.MSG_REGION_OPEN: case HMsg.MSG_REGION_OPEN:
// Open a region // Open a region
openRegion(e.msg.getRegionInfo()); openRegion(e.msg.getRegionInfo());
@ -1149,12 +1175,19 @@ public class HRegionServer implements HConstants, HRegionInterface, Runnable {
} }
} }
void openRegion(final HRegionInfo regionInfo) throws IOException { void openRegion(final HRegionInfo regionInfo) {
HRegion region = onlineRegions.get(regionInfo.getRegionName()); HRegion region = onlineRegions.get(regionInfo.getRegionName());
if(region == null) { if(region == null) {
try {
region = new HRegion(new Path(this.conf.get(HConstants.HBASE_DIR)), region = new HRegion(new Path(this.conf.get(HConstants.HBASE_DIR)),
this.log, FileSystem.get(conf), conf, regionInfo, null, this.log, FileSystem.get(conf), conf, regionInfo, null,
this.cacheFlusher); this.cacheFlusher);
} catch (IOException e) {
LOG.error("error opening region " + regionInfo.getRegionName(), e);
reportClose(region);
return;
}
this.lock.writeLock().lock(); this.lock.writeLock().lock();
try { try {
this.log.setSequenceNumber(region.getMinSequenceId()); this.log.setSequenceNumber(region.getMinSequenceId());
@ -1208,6 +1241,45 @@ public class HRegionServer implements HConstants, HRegionInterface, Runnable {
return regionsToClose; return regionsToClose;
} }
/** Called as the first stage of cluster shutdown. */
void closeUserRegions() {
ArrayList<HRegion> regionsToClose = new ArrayList<HRegion>();
this.lock.writeLock().lock();
try {
synchronized (onlineRegions) {
for (Iterator<Map.Entry<Text, HRegion>> i =
onlineRegions.entrySet().iterator();
i.hasNext();) {
Map.Entry<Text, HRegion> e = i.next();
HRegion r = e.getValue();
if (!r.getRegionInfo().isMetaRegion()) {
regionsToClose.add(r);
i.remove();
}
}
}
} finally {
this.lock.writeLock().unlock();
}
for(HRegion region: regionsToClose) {
if (LOG.isDebugEnabled()) {
LOG.debug("closing region " + region.getRegionName());
}
try {
region.close(false);
} catch (IOException e) {
LOG.error("error closing region " + region.getRegionName(),
RemoteExceptionHandler.checkIOException(e));
}
}
this.quiesced.set(true);
if (onlineRegions.size() == 0) {
outboundMsgs.add(new HMsg(HMsg.MSG_REPORT_EXITING));
} else {
outboundMsgs.add(new HMsg(HMsg.MSG_REPORT_QUIESCED));
}
}
// //
// HRegionInterface // HRegionInterface
// //

View File

@ -52,7 +52,8 @@ public class HTableDescriptor implements WritableComparable {
HColumnDescriptor.CompressionType.NONE, false, Integer.MAX_VALUE, HColumnDescriptor.CompressionType.NONE, false, Integer.MAX_VALUE,
null)); null));
private boolean rootregion;
private boolean metaregion;
private Text name; private Text name;
// TODO: Does this need to be a treemap? Can it be a HashMap? // TODO: Does this need to be a treemap? Can it be a HashMap?
private final TreeMap<Text, HColumnDescriptor> families; private final TreeMap<Text, HColumnDescriptor> families;
@ -69,6 +70,8 @@ public class HTableDescriptor implements WritableComparable {
/** Used to construct the table descriptors for root and meta tables */ /** Used to construct the table descriptors for root and meta tables */
private HTableDescriptor(Text name, HColumnDescriptor family) { private HTableDescriptor(Text name, HColumnDescriptor family) {
rootregion = name.equals(HConstants.ROOT_TABLE_NAME);
this.metaregion = true;
this.name = new Text(name); this.name = new Text(name);
this.families = new TreeMap<Text, HColumnDescriptor>(); this.families = new TreeMap<Text, HColumnDescriptor>();
families.put(family.getName(), family); families.put(family.getName(), family);
@ -92,13 +95,30 @@ public class HTableDescriptor implements WritableComparable {
* <code>[a-zA-Z_0-9] * <code>[a-zA-Z_0-9]
*/ */
public HTableDescriptor(String name) { public HTableDescriptor(String name) {
this();
Matcher m = LEGAL_TABLE_NAME.matcher(name); Matcher m = LEGAL_TABLE_NAME.matcher(name);
if (m == null || !m.matches()) { if (m == null || !m.matches()) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Table names can only contain 'word characters': i.e. [a-zA-Z_0-9"); "Table names can only contain 'word characters': i.e. [a-zA-Z_0-9");
} }
this.name = new Text(name); this.name.set(name);
this.families = new TreeMap<Text, HColumnDescriptor>(); this.rootregion = false;
this.metaregion = false;
}
/** @return true if this is the root region */
public boolean isRootRegion() {
return rootregion;
}
/** @return true if table is the meta table */
public boolean isMetaTable() {
return metaregion && !rootregion;
}
/** @return true if this is a meta region (part of the root or meta tables) */
public boolean isMetaRegion() {
return metaregion;
} }
/** @return name of table */ /** @return name of table */
@ -165,6 +185,8 @@ public class HTableDescriptor implements WritableComparable {
/** {@inheritDoc} */ /** {@inheritDoc} */
public void write(DataOutput out) throws IOException { public void write(DataOutput out) throws IOException {
out.writeBoolean(rootregion);
out.writeBoolean(metaregion);
name.write(out); name.write(out);
out.writeInt(families.size()); out.writeInt(families.size());
for(Iterator<HColumnDescriptor> it = families.values().iterator(); for(Iterator<HColumnDescriptor> it = families.values().iterator();
@ -175,6 +197,8 @@ public class HTableDescriptor implements WritableComparable {
/** {@inheritDoc} */ /** {@inheritDoc} */
public void readFields(DataInput in) throws IOException { public void readFields(DataInput in) throws IOException {
this.rootregion = in.readBoolean();
this.metaregion = in.readBoolean();
this.name.readFields(in); this.name.readFields(in);
int numCols = in.readInt(); int numCols = in.readInt();
families.clear(); families.clear();