From 4dce2b26bfb8b47d7761dfe87bb79c79f7ebda87 Mon Sep 17 00:00:00 2001 From: Ryan Rawson Date: Tue, 9 Nov 2010 02:02:27 +0000 Subject: [PATCH] HBASE-3141 Master RPC server needs to be started before an RS can check in git-svn-id: https://svn.apache.org/repos/asf/hbase/trunk@1032812 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES.txt | 1 + .../apache/hadoop/hbase/ipc/HBaseServer.java | 21 ++++++- .../hbase/ipc/ServerNotRunningException.java | 29 +++++++++ .../apache/hadoop/hbase/master/HMaster.java | 8 +-- .../hbase/master/TestHMasterRPCException.java | 63 +++++++++++++++++++ 5 files changed, 117 insertions(+), 5 deletions(-) create mode 100644 src/main/java/org/apache/hadoop/hbase/ipc/ServerNotRunningException.java create mode 100644 src/test/java/org/apache/hadoop/hbase/master/TestHMasterRPCException.java diff --git a/CHANGES.txt b/CHANGES.txt index ceb164878cd..0942b3d3f38 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -660,6 +660,7 @@ Release 0.90.0 - Unreleased HBASE-3205 TableRecordReaderImpl.restart NPEs when first next is restarted HBASE-3208 HLog.findMemstoresWithEditsOlderThan needs to look for edits that are equal to too + HBASE-3141 Master RPC server needs to be started before an RS can check in IMPROVEMENTS 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 e4c356da6be..a65e436d610 100644 --- a/src/main/java/org/apache/hadoop/hbase/ipc/HBaseServer.java +++ b/src/main/java/org/apache/hadoop/hbase/ipc/HBaseServer.java @@ -94,6 +94,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} @@ -1022,6 +1023,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); @@ -1158,7 +1161,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 00000000000..26112866829 --- /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 209c29179e6..4f775dfcea1 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) { @@ -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"); } diff --git a/src/test/java/org/apache/hadoop/hbase/master/TestHMasterRPCException.java b/src/test/java/org/apache/hadoop/hbase/master/TestHMasterRPCException.java new file mode 100644 index 00000000000..f9c12c6cfe7 --- /dev/null +++ b/src/test/java/org/apache/hadoop/hbase/master/TestHMasterRPCException.java @@ -0,0 +1,63 @@ +/* + * 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.master; + +import org.apache.hadoop.hbase.HBaseTestingUtility; +import org.apache.hadoop.hbase.HConstants; +import org.apache.hadoop.hbase.HServerAddress; +import org.apache.hadoop.hbase.avro.generated.HBase; +import org.apache.hadoop.hbase.client.HBaseAdmin; +import org.apache.hadoop.hbase.ipc.HBaseRPC; +import org.apache.hadoop.hbase.ipc.HBaseRPCProtocolVersion; +import org.apache.hadoop.hbase.ipc.HMasterInterface; +import org.apache.hadoop.hbase.ipc.ServerNotRunningException; +import org.apache.hadoop.ipc.RemoteException; +import org.junit.Test; + +import java.lang.reflect.UndeclaredThrowableException; + +import static org.junit.Assert.*; + +public class TestHMasterRPCException { + + @Test + public void testRPCException() throws Exception { + HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility(); + TEST_UTIL.startMiniZKCluster(); + + HMaster hm = new HMaster(TEST_UTIL.getConfiguration()); + + HServerAddress hma = hm.getMasterAddress(); + try { + HMasterInterface inf = + (HMasterInterface) HBaseRPC.getProxy( + HMasterInterface.class, HBaseRPCProtocolVersion.versionID, + hma.getInetSocketAddress(), TEST_UTIL.getConfiguration(), + 100); + inf.isMasterRunning(); + fail(); + } catch (RemoteException ex) { + assertTrue(ex.getMessage().startsWith("org.apache.hadoop.hbase.ipc.ServerNotRunningException: Server is not running yet")); + } catch (Throwable t) { + fail("Unexpected throwable: " + t); + } + } +}