Index: bin/hbase-config.sh =================================================================== --- bin/hbase-config.sh (revision 983869) +++ bin/hbase-config.sh (working copy) @@ -73,6 +73,8 @@ HBASE_CONF_DIR="${HBASE_CONF_DIR:-$HBASE_HOME/conf}" # List of hbase regions servers. HBASE_REGIONSERVERS="${HBASE_REGIONSERVERS:-$HBASE_CONF_DIR/regionservers}" +# List of hbase secondary masters. +HBASE_BACKUP_MASTERS="${HBASE_BACKUP_MASTERS:-$HBASE_CONF_DIR/backup-masters}" # Source the hbase-env.sh. Will have JAVA_HOME defined. if [ -f "${HBASE_CONF_DIR}/hbase-env.sh" ]; then Index: bin/hbase-daemons.sh =================================================================== --- bin/hbase-daemons.sh (revision 983869) +++ bin/hbase-daemons.sh (working copy) @@ -45,6 +45,9 @@ (zookeeper) exec "$bin/zookeepers.sh" $args ;; + (master-backup) + exec "$bin/master-backup.sh" $args + ;; (*) exec "$bin/regionservers.sh" $args ;; Index: bin/local-master-backup.sh =================================================================== --- bin/local-master-backup.sh (revision 983869) +++ bin/local-master-backup.sh (working copy) @@ -21,6 +21,7 @@ DN=$2 export HBASE_IDENT_STRING="$USER-$DN" HBASE_MASTER_ARGS="\ + --backup \ -D hbase.master.port=`expr 60000 + $DN` \ -D hbase.master.info.port=`expr 60010 + $DN`" "$bin"/hbase-daemon.sh $1 master $HBASE_MASTER_ARGS Index: bin/master-backup.sh =================================================================== --- bin/master-backup.sh (revision 0) +++ bin/master-backup.sh (revision 0) @@ -0,0 +1,76 @@ +#!/usr/bin/env bash +# +#/** +# * 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. +# */ +# +# Run a shell command on all backup master hosts. +# +# Environment Variables +# +# HBASE_BACKUP_MASTERS File naming remote hosts. +# Default is ${HADOOP_CONF_DIR}/backup-masters +# HADOOP_CONF_DIR Alternate conf dir. Default is ${HADOOP_HOME}/conf. +# HBASE_CONF_DIR Alternate hbase conf dir. Default is ${HBASE_HOME}/conf. +# HADOOP_SLAVE_SLEEP Seconds to sleep between spawning remote commands. +# HADOOP_SSH_OPTS Options passed to ssh when running remote commands. +# +# Modelled after $HADOOP_HOME/bin/slaves.sh. + +usage="Usage: $0 [--config ] command..." + +# if no args specified, show usage +if [ $# -le 0 ]; then + echo $usage + exit 1 +fi + +bin=`dirname "${BASH_SOURCE-$0}"` +bin=`cd "$bin">/dev/null; pwd` + +. "$bin"/hbase-config.sh + +# If the master backup file is specified in the command line, +# then it takes precedence over the definition in +# hbase-env.sh. Save it here. +HOSTLIST=$HBASE_BACKUP_MASTERS + +if [ "$HOSTLIST" = "" ]; then + if [ "$HBASE_BACKUP_MASTERS" = "" ]; then + export HOSTLIST="${HBASE_CONF_DIR}/backup-masters" + else + export HOSTLIST="${HBASE_BACKUP_MASTERS}" + fi +fi + + +args=${@// /\\ } +args=${args/master-backup/master} + +if [ -f $HOSTLIST ]; then + for hmaster in `cat "$HOSTLIST"`; do + ssh $HBASE_SSH_OPTS $hmaster $"$args --backup" \ + 2>&1 | sed "s/^/$hmaster: /" & + if [ "$HBASE_SLAVE_SLEEP" != "" ]; then + sleep $HBASE_SLAVE_SLEEP + fi + done +fi + +wait Property changes on: bin/master-backup.sh ___________________________________________________________________ Added: svn:executable + * Index: bin/start-hbase.sh =================================================================== --- bin/start-hbase.sh (revision 983869) +++ bin/start-hbase.sh (working copy) @@ -49,4 +49,6 @@ "$bin"/hbase-daemon.sh --config "${HBASE_CONF_DIR}" start master "$bin"/hbase-daemons.sh --config "${HBASE_CONF_DIR}" \ --hosts "${HBASE_REGIONSERVERS}" start regionserver + "$bin"/hbase-daemons.sh --config "${HBASE_CONF_DIR}" \ + --hosts "${HBASE_BACKUP_MASTERS}" start master-backup fi Index: bin/stop-hbase.sh =================================================================== --- bin/stop-hbase.sh (revision 983869) +++ bin/stop-hbase.sh (working copy) @@ -60,5 +60,10 @@ distMode=`$bin/hbase org.apache.hadoop.hbase.HBaseConfTool hbase.cluster.distributed` if [ "$distMode" == 'true' ] then + # TODO: store backup masters in ZooKeeper and have the primary send them a shutdown message + # stop any backup masters + "$bin"/hbase-daemons.sh --config "${HBASE_CONF_DIR}" \ + --hosts "${HBASE_BACKUP_MASTERS}" stop master-backup + "$bin"/hbase-daemons.sh --config "${HBASE_CONF_DIR}" stop zookeeper fi Index: src/main/java/org/apache/hadoop/hbase/HConstants.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/HConstants.java (revision 983869) +++ src/main/java/org/apache/hadoop/hbase/HConstants.java (working copy) @@ -81,6 +81,12 @@ /** default port for master web api */ public static final int DEFAULT_MASTER_INFOPORT = 60010; + /** Parameter name for the master type being backup (waits for primary to go inactive). */ + public static final String MASTER_TYPE_BACKUP = "hbase.master.backup"; + + /** by default every master is a possible primary master unless the conf explicitly overrides it */ + public static final boolean DEFAULT_MASTER_TYPE_BACKUP = false; + /** Name of ZooKeeper quorum configuration parameter. */ public static final String ZOOKEEPER_QUORUM = "hbase.zookeeper.quorum"; Index: src/main/java/org/apache/hadoop/hbase/master/HMaster.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/master/HMaster.java (revision 983869) +++ src/main/java/org/apache/hadoop/hbase/master/HMaster.java (working copy) @@ -230,6 +230,22 @@ this.zkMasterAddressWatcher = new ZKMasterAddressWatcher(this.zooKeeperWrapper, this.shutdownRequested); zooKeeperWrapper.registerListener(zkMasterAddressWatcher); + + // if we're a backup master, stall until a primary to writes his address + if(conf.getBoolean(HConstants.MASTER_TYPE_BACKUP, HConstants.DEFAULT_MASTER_TYPE_BACKUP)) { + // this will only be a minute or so while the cluster starts up, + // so don't worry about setting watches on the parent znode + while (!zooKeeperWrapper.masterAddressExists()) { + try { + LOG.debug("Waiting for master address ZNode to be written " + + "(Also watching cluster state node)"); + Thread.sleep(conf.getInt("zookeeper.session.timeout", 60 * 1000)); + } catch (InterruptedException e) { + // interrupted = user wants to kill us. Don't continue + throw new IOException("Interrupted waiting for master address"); + } + } + } this.zkMasterAddressWatcher.writeAddressToZooKeeper(this.address, true); this.regionServerOperationQueue = new RegionServerOperationQueue(this.conf, this.closed); @@ -1265,6 +1281,7 @@ Options opt = new Options(); opt.addOption("minServers", true, "Minimum RegionServers needed to host user tables"); opt.addOption("D", true, "Override HBase Configuration Settings"); + opt.addOption("backup", false, "Do not try to become HMaster until the primary fails"); try { CommandLine cmd = new GnuParser().parse(opt, args); @@ -1286,6 +1303,11 @@ } } } + + // check if we are the backup master - override the conf if so + if (cmd.hasOption("backup")) { + conf.setBoolean(HConstants.MASTER_TYPE_BACKUP, true); + } if (cmd.getArgList().contains("start")) { try { Index: src/main/java/org/apache/hadoop/hbase/zookeeper/ZooKeeperWrapper.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/zookeeper/ZooKeeperWrapper.java (revision 983869) +++ src/main/java/org/apache/hadoop/hbase/zookeeper/ZooKeeperWrapper.java (working copy) @@ -464,6 +464,13 @@ LOG.debug("<" + instanceName + ">" + "Set watcher on master address ZNode " + masterElectionZNode); return true; } + + /** + * @return true if zookeeper has a master address. + */ + public boolean masterAddressExists() { + return checkExistenceOf(masterElectionZNode); + } private HServerAddress readAddress(String znode, Watcher watcher) { try {