diff --git a/src/main/java/org/apache/hadoop/hbase/ipc/HBaseServer.java b/src/main/java/org/apache/hadoop/hbase/ipc/HBaseServer.java index e62f831..d4eae54 100644 --- a/src/main/java/org/apache/hadoop/hbase/ipc/HBaseServer.java +++ b/src/main/java/org/apache/hadoop/hbase/ipc/HBaseServer.java @@ -55,6 +55,7 @@ import java.util.concurrent.LinkedBlockingQueue; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.hbase.MasterNotRunningException; import org.apache.hadoop.hbase.io.WritableWithSize; import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.io.ObjectWritable; @@ -104,6 +105,7 @@ public abstract class HBaseServer { protected static final ThreadLocal SERVER = new ThreadLocal(); + private volatile boolean started = false; /** Returns the server instance called under or null. May be called under * {@link #call(Writable, long)} implementations, and under {@link Writable} @@ -1032,6 +1034,8 @@ public abstract class HBaseServer { UserGroupInformation previous = UserGroupInformation.getCurrentUGI(); UserGroupInformation.setCurrentUser(call.connection.ticket); try { + if (!started) + throw new ServerNotRunningException("Server is not running yet"); value = call(call.param, call.timestamp); // make the call } catch (Throwable e) { LOG.debug(getName()+", call "+call+": error: " + e, e); @@ -1189,7 +1193,23 @@ public abstract class HBaseServer { public void setSocketSendBufSize(int size) { this.socketSendBufferSize = size; } /** Starts the service. Must be called before any calls will be handled. */ - public synchronized void start() { + public void start() { + startThreads(); + openServer(); + } + + /** + * Open a previously started server. + */ + public void openServer() { + started = true; + } + + /** + * Starts the service threads but does not allow requests to be responded yet. + * Client will get {@link ServerNotRunningException} instead. + */ + public synchronized void startThreads() { responder.start(); listener.start(); handlers = new Handler[handlerCount]; diff --git a/src/main/java/org/apache/hadoop/hbase/ipc/ServerNotRunningException.java b/src/main/java/org/apache/hadoop/hbase/ipc/ServerNotRunningException.java new file mode 100644 index 0000000..2611286 --- /dev/null +++ b/src/main/java/org/apache/hadoop/hbase/ipc/ServerNotRunningException.java @@ -0,0 +1,29 @@ +/* + * Copyright 2010 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.ipc; + +import java.io.IOException; + +public class ServerNotRunningException extends IOException { + public ServerNotRunningException(String s) { + super(s); + } +} diff --git a/src/main/java/org/apache/hadoop/hbase/master/HMaster.java b/src/main/java/org/apache/hadoop/hbase/master/HMaster.java index 209c291..a8273f0 100644 --- a/src/main/java/org/apache/hadoop/hbase/master/HMaster.java +++ b/src/main/java/org/apache/hadoop/hbase/master/HMaster.java @@ -200,6 +200,8 @@ implements HMasterInterface, HMasterRegionInterface, MasterServices, Server { // set the thread name now we have an address setName(MASTER + "-" + this.address); + this.rpcServer.startThreads(); + // Hack! Maps DFSClient => Master for logs. HDFS made this // config param for task trackers, but we can piggyback off of it. if (this.conf.get("mapred.task.id") == null) { @@ -348,6 +350,9 @@ implements HMasterInterface, HMasterRegionInterface, MasterServices, Server { this.serverManager); this.regionServerTracker.start(); + // start up all service threads. + startServiceThreads(); + // Set the cluster as up. If new RSs, they'll be waiting on this before // going ahead with their startup. this.clusterStatusTracker = new ClusterStatusTracker(getZooKeeper(), this); @@ -360,9 +365,6 @@ implements HMasterInterface, HMasterRegionInterface, MasterServices, Server { Long.toHexString(this.zooKeeper.getZooKeeper().getSessionId()) + ", cluster-up flag was=" + wasUp); - // start up all service threads. - startServiceThreads(); - // Wait for region servers to report in. Returns count of regions. int regionCount = this.serverManager.waitForRegionServers(); @@ -522,10 +524,8 @@ implements HMasterInterface, HMasterRegionInterface, MasterServices, Server { this.infoServer.setAttribute(MASTER, this); this.infoServer.start(); } - - // Start the server last so everything else is running before we start - // receiving requests. - this.rpcServer.start(); + // Start allowing requests to happen. + this.rpcServer.openServer(); if (LOG.isDebugEnabled()) { LOG.debug("Started service threads"); }