You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by mb...@apache.org on 2012/08/05 21:16:13 UTC
svn commit: r1369645 [1/3] - in /hbase/branches/0.89-fb: ./
src/main/java/org/apache/hadoop/hbase/
src/main/java/org/apache/hadoop/hbase/client/
src/main/java/org/apache/hadoop/hbase/executor/
src/main/java/org/apache/hadoop/hbase/master/ src/main/java...
Author: mbautin
Date: Sun Aug 5 19:16:11 2012
New Revision: 1369645
URL: http://svn.apache.org/viewvc?rev=1369645&view=rev
Log:
[master] [89-fb] Fix master failover
Summary:
To implement proper master failover, we need to:
- Do log splitting as the first thing on cluster startup, so that we can split logs for ROOT and META before we assign them.
- Start queuing all updates to the ZK unassigned directory for .META. and user regions
- Assign out the root region
- Scan the ZK unassigned directory for OPENED and CLOSED records for .META. regions and update -ROOT- accordingly
- Drain the queue of ZK unassigned directory updates for .META. regions, process events (modify -ROOT-), and switch to real-time processing for .META.
- Do initial root scan
- Wait until .META. is fully assigned (need to process region server events in a loop similarly to the master's main loop)
- Scan the ZK unassigned directory for user regions and update .META. accordingly
- Drain the queue of ZK unassigned directory updates for user regions, process events (modify .META.), and switch to real-time processing for -ROOT-.
Test Plan:
- Run all unit tests
- Deploy to cluster, kill a regionserver, then the active master. Look at the logs.
Reviewers: pkhemani, kranganathan, liyintang, kannan
Reviewed By: kranganathan
Differential Revision: https://reviews.facebook.net/D2085
Added:
hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/util/DrainableQueue.java
hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/util/ParamCallable.java
hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/zookeeper/LegacyRootZNodeUpdater.java
hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/zookeeper/ZNodePathAndData.java
hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/TestHServerInfo.java
hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/util/TestDrainableQueue.java
Modified:
hbase/branches/0.89-fb/pom.xml
hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/HRegionInfo.java
hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/HServerAddress.java
hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/HServerInfo.java
hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/KeyValue.java
hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java
hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/executor/HBaseEventHandler.java
hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/master/AssignmentManager.java
hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/master/BaseScanner.java
hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/master/HMaster.java
hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/master/MetaScanner.java
hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/master/ProcessRegionOpen.java
hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/master/ProcessRegionStatusChange.java
hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/master/RegionManager.java
hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/master/RegionServerOperation.java
hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/master/RootScanner.java
hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/master/ServerManager.java
hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/master/ZKClusterStateRecovery.java
hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/master/ZKUnassignedWatcher.java
hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/master/handler/MasterCloseRegionHandler.java
hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/master/handler/MasterOpenRegionHandler.java
hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java
hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/regionserver/wal/SequenceFileLogWriter.java
hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/util/JVMClusterUtil.java
hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/util/Threads.java
hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/zookeeper/RecoverableZooKeeper.java
hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/zookeeper/ZooKeeperWrapper.java
hbase/branches/0.89-fb/src/main/resources/hbase-default.xml
hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/HBaseTestingUtility.java
hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/io/encoding/TestUpgradeFromHFileV1ToEncoding.java
hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/mapreduce/TestTableMapReduce.java
hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/master/MultiMasterTest.java
hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/master/TestClusterStartupDetection.java
hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/master/TestLogSplitOnMasterFailover.java
hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/master/TestMasterFailover.java
hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/master/TestRSLivenessOnMasterFailover.java
hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/master/TestRegionStateOnMasterFailure.java
hbase/branches/0.89-fb/src/test/java/org/apache/hadoop/hbase/regionserver/TestHRegionInfo.java
Modified: hbase/branches/0.89-fb/pom.xml
URL: http://svn.apache.org/viewvc/hbase/branches/0.89-fb/pom.xml?rev=1369645&r1=1369644&r2=1369645&view=diff
==============================================================================
--- hbase/branches/0.89-fb/pom.xml (original)
+++ hbase/branches/0.89-fb/pom.xml Sun Aug 5 19:16:11 2012
@@ -229,7 +229,7 @@
<version>2.8</version>
<configuration>
<forkedProcessTimeoutInSeconds>900</forkedProcessTimeoutInSeconds>
- <argLine>-enableassertions -Xmx512m</argLine>
+ <argLine>-enableassertions -Xmx1024m</argLine>
<redirectTestOutputToFile>true</redirectTestOutputToFile>
</configuration>
</plugin>
Modified: hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/HRegionInfo.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/HRegionInfo.java?rev=1369645&r1=1369644&r2=1369645&view=diff
==============================================================================
--- hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/HRegionInfo.java (original)
+++ hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/HRegionInfo.java Sun Aug 5 19:16:11 2012
@@ -52,11 +52,11 @@ public class HRegionInfo extends Version
* where,
* <encodedName> is a hex version of the MD5 hash of
* <tablename>,<startkey>,<regionIdTimestamp>
- *
+ *
* The old region name format:
* <tablename>,<startkey>,<regionIdTimestamp>
* For region names in the old format, the encoded name is a 32-bit
- * JenkinsHash integer value (in its decimal notation, string form).
+ * JenkinsHash integer value (in its decimal notation, string form).
*<p>
* **NOTE**
*
@@ -66,8 +66,8 @@ public class HRegionInfo extends Version
*/
/** Separator used to demarcate the encodedName in a region name
- * in the new format. See description on new format above.
- */
+ * in the new format. See description on new format above.
+ */
private static final int ENC_SEPARATOR = '.';
public static final int MD5_HEX_LENGTH = 32;
@@ -82,11 +82,11 @@ public class HRegionInfo extends Version
if ((regionName.length >= 1)
&& (regionName[regionName.length - 1] == ENC_SEPARATOR)) {
// region name is new format. it contains the encoded name.
- return true;
+ return true;
}
return false;
}
-
+
/**
* @param regionName
* @return the encodedName
@@ -100,7 +100,7 @@ public class HRegionInfo extends Version
regionName.length - MD5_HEX_LENGTH - 1,
MD5_HEX_LENGTH);
} else {
- // old format region name. ROOT and first META region also
+ // old format region name. ROOT and first META region also
// use this format.EncodedName is the JenkinsHash value.
int hashVal = Math.abs(JenkinsHash.getInstance().hash(regionName,
regionName.length,
@@ -117,6 +117,10 @@ public class HRegionInfo extends Version
public static final HRegionInfo ROOT_REGIONINFO =
new HRegionInfo(0L, HTableDescriptor.ROOT_TABLEDESC);
+ /** Encoded name for the root region. This is always the same. */
+ public static final String ROOT_REGION_ENCODED_NAME_STR =
+ HRegionInfo.ROOT_REGIONINFO.getEncodedName();
+
/** HRegionInfo for first meta region */
public static final HRegionInfo FIRST_META_REGIONINFO =
new HRegionInfo(1L, HTableDescriptor.META_TABLEDESC);
@@ -153,8 +157,8 @@ public class HRegionInfo extends Version
super();
this.regionId = regionId;
this.tableDesc = tableDesc;
-
- // Note: Root & First Meta regions names are still in old format
+
+ // Note: Root & First Meta regions names are still in old format
this.regionName = createRegionName(tableDesc.getName(), null,
regionId, false);
this.regionNameStr = Bytes.toStringBinary(this.regionName);
@@ -303,7 +307,7 @@ public class HRegionInfo extends Version
if (md5HashBytes.length != MD5_HEX_LENGTH) {
LOG.error("MD5-hash length mismatch: Expected=" + MD5_HEX_LENGTH +
- "; Got=" + md5HashBytes.length);
+ "; Got=" + md5HashBytes.length);
}
// now append the bytes '.<encodedName>.' to the end
@@ -312,7 +316,7 @@ public class HRegionInfo extends Version
offset += MD5_HEX_LENGTH;
b[offset++] = ENC_SEPARATOR;
}
-
+
return b;
}
@@ -331,8 +335,8 @@ public class HRegionInfo extends Version
break;
}
}
- if(offset == -1) {
- throw new IOException("Invalid regionName format: " +
+ if(offset == -1) {
+ throw new IOException("Invalid regionName format: " +
Bytes.toStringBinary(regionName));
}
byte [] tableName = new byte[offset];
@@ -344,8 +348,8 @@ public class HRegionInfo extends Version
break;
}
}
- if(offset == -1) {
- throw new IOException("Invalid regionName format: " +
+ if(offset == -1) {
+ throw new IOException("Invalid regionName format: " +
Bytes.toStringBinary(regionName));
}
byte [] startKey = HConstants.EMPTY_BYTE_ARRAY;
@@ -404,7 +408,7 @@ public class HRegionInfo extends Version
public byte [] getStartKey(){
return startKey;
}
-
+
/** @return the endKey */
public byte [] getEndKey(){
return endKey;
@@ -430,7 +434,7 @@ public class HRegionInfo extends Version
Bytes.equals(endKey, HConstants.EMPTY_BYTE_ARRAY);
return firstKeyInRange && lastKeyInRange;
}
-
+
/**
* Return true if the given row falls in this region.
*/
@@ -485,7 +489,7 @@ public class HRegionInfo extends Version
* @return point to explicitly split the region on
*/
public byte[] getSplitPoint() {
- return (this.splitPoint != null && this.splitPoint.length > 0)
+ return (this.splitPoint != null && this.splitPoint.length > 0)
? this.splitPoint : null;
}
Modified: hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/HServerAddress.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/HServerAddress.java?rev=1369645&r1=1369644&r2=1369645&view=diff
==============================================================================
--- hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/HServerAddress.java (original)
+++ hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/HServerAddress.java Sun Aug 5 19:16:11 2012
@@ -27,6 +27,7 @@ import java.net.InetSocketAddress;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
+import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.io.WritableComparable;
@@ -34,6 +35,9 @@ import org.apache.hadoop.io.WritableComp
* HServerAddress is a "label" for a HBase server made of host and port number.
*/
public class HServerAddress implements WritableComparable<HServerAddress> {
+
+ private static final Log LOG = LogFactory.getLog(HServerAddress.class);
+
private InetSocketAddress address;
private String stringValue;
private String hostAddress;
@@ -108,7 +112,7 @@ public class HServerAddress implements W
stringValue = other.stringValue;
checkBindAddressCanBeResolved();
}
-
+
/**
* Get the normalized hostAddress:port as a string format
* @param address
@@ -134,13 +138,12 @@ public class HServerAddress implements W
public String getBindAddress() {
if (this.hostAddress != null)
return hostAddress;
-
+
final InetAddress addr = address.getAddress();
if (addr != null) {
return addr.getHostAddress();
} else {
- LogFactory.getLog(HServerAddress.class).error("Could not resolve the"
- + " DNS name of " + stringValue);
+ LOG.error("Could not resolve the DNS name of " + stringValue);
return null;
}
}
Modified: hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/HServerInfo.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/HServerInfo.java?rev=1369645&r1=1369644&r2=1369645&view=diff
==============================================================================
--- hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/HServerInfo.java (original)
+++ hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/HServerInfo.java Sun Aug 5 19:16:11 2012
@@ -24,6 +24,7 @@ import java.io.DataOutput;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.Set;
+import java.util.regex.Pattern;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -31,7 +32,6 @@ import org.apache.hadoop.hbase.regionser
import org.apache.hadoop.io.Writable;
import org.apache.hadoop.io.WritableComparable;
-
/**
* HServerInfo is meta info about an {@link HRegionServer}. It is the token
* by which a master distingushes a particular regionserver from the rest.
@@ -53,7 +53,12 @@ public class HServerInfo implements Writ
* its startcode. Servername is formatted as
* <code><hostname> '{@ink #SERVERNAME_SEPARATOR"}' <port> '{@ink #SERVERNAME_SEPARATOR"}' <startcode></code>.
*/
- private static final String SERVERNAME_SEPARATOR = ",";
+ static final String SERVERNAME_SEPARATOR = ",";
+
+ private static final Pattern SERVER_NAME_RE = Pattern.compile(
+ "^[^,]+" + SERVERNAME_SEPARATOR +
+ "[0-9]{1," + String.valueOf(0xffff).length() + "}" + SERVERNAME_SEPARATOR +
+ "-?[0-9]{1," + String.valueOf(Long.MAX_VALUE).length() + "}");
private HServerAddress serverAddress;
private long startCode;
@@ -79,6 +84,16 @@ public class HServerInfo implements Writ
this(serverAddress, System.currentTimeMillis(), hostname);
}
+ /** Initializes from server address and start code. Used in unit tests. */
+ HServerInfo(HServerAddress serverAddress, long startCode) {
+ this(serverAddress, startCode, serverAddress.getHostname());
+ }
+
+ /** Auto-generates a start code. */
+ public HServerInfo(final HServerAddress serverAddress) {
+ this(serverAddress, 0, serverAddress.getHostname());
+ }
+
public HServerInfo(HServerAddress serverAddress, long startCode, String hostname) {
this.serverAddress = serverAddress;
this.startCode = startCode;
@@ -288,4 +303,13 @@ public class HServerInfo implements Writ
return new HServerInfo(new HServerAddress(hostName, port), startCode, hostName);
}
+
+ public static boolean isValidServerName(String serverName) {
+ return SERVER_NAME_RE.matcher(serverName).matches();
+ }
+
+ public static HServerAddress getAddress(HServerInfo hsi) {
+ return hsi != null ? hsi.getServerAddress() : null;
+ }
+
}
Modified: hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/KeyValue.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/KeyValue.java?rev=1369645&r1=1369644&r2=1369645&view=diff
==============================================================================
--- hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/KeyValue.java (original)
+++ hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/KeyValue.java Sun Aug 5 19:16:11 2012
@@ -1295,7 +1295,7 @@ public class KeyValue implements Writabl
final int offset, final int length, final int delimiter) {
int index = getDelimiter(b, offset, length, delimiter);
if (index < 0) {
- throw new IllegalArgumentException("No " + (char)delimiter + " in <" +
+ throw new IllegalArgumentException("No '" + (char)delimiter + "' in <" +
Bytes.toString(b) + ">" + ", length=" + length + ", offset=" + offset);
}
return index;
@@ -1309,7 +1309,7 @@ public class KeyValue implements Writabl
final int offset, final int length, final int delimiter) {
int index = getDelimiterInReverse(b, offset, length, delimiter);
if (index < 0) {
- throw new IllegalArgumentException("No " + delimiter + " in <" +
+ throw new IllegalArgumentException("No '" + ((char) delimiter) + "' in <" +
Bytes.toString(b) + ">" + ", length=" + length + ", offset=" + offset);
}
return index;
Modified: hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java?rev=1369645&r1=1369644&r2=1369645&view=diff
==============================================================================
--- hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java (original)
+++ hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java Sun Aug 5 19:16:11 2012
@@ -60,10 +60,10 @@ import org.apache.hadoop.ipc.RemoteExcep
/**
- * Provides an interface to manage HBase database table metadata + general
- * administrative functions. Use HBaseAdmin to create, drop, list, enable and
- * disable tables. Use it also to add and drop table column families.
- *
+ * Provides an interface to manage HBase database table metadata + general
+ * administrative functions. Use HBaseAdmin to create, drop, list, enable and
+ * disable tables. Use it also to add and drop table column families.
+ *
* See {@link HTable} to add, update, and delete data from an individual table.
*/
public class HBaseAdmin {
@@ -284,14 +284,14 @@ public class HBaseAdmin {
MetaScanner.metaScan(conf, visitor, desc.getName());
if (actualRegCount.get() != numRegs) {
if (tries == numRetries - 1) {
- throw new RegionOfflineException("Only " + actualRegCount.get() +
+ throw new RegionOfflineException("Only " + actualRegCount.get() +
" of " + numRegs + " regions are online; retries exhausted.");
}
try { // Sleep
Thread.sleep(getPauseTime(tries));
} catch (InterruptedException e) {
throw new InterruptedIOException("Interrupted when opening" +
- " regions; " + actualRegCount.get() + " of " + numRegs +
+ " regions; " + actualRegCount.get() + " of " + numRegs +
" regions processed so far");
}
if (actualRegCount.get() > prevRegCount) { // Making progress
@@ -597,10 +597,10 @@ public class HBaseAdmin {
List<Pair<String, HColumnDescriptor>> columnModifications,
List<String> columnDeletions) throws IOException {
// convert all of the strings to bytes and pass to the bytes method
- List<Pair<byte [], HColumnDescriptor>> modificationsBytes =
+ List<Pair<byte [], HColumnDescriptor>> modificationsBytes =
new ArrayList<Pair<byte [], HColumnDescriptor>>(
columnModifications.size());
- List<byte []> deletionsBytes =
+ List<byte []> deletionsBytes =
new ArrayList<byte []>(columnDeletions.size());
for(Pair<String, HColumnDescriptor> c : columnModifications) {
@@ -618,7 +618,7 @@ public class HBaseAdmin {
/**
* Batch alter a table. Only takes regions offline once and performs a single
* update to .META.
- * Any of the three lists can be null, in which case those types of
+ * Any of the three lists can be null, in which case those types of
* alterations will be ignored.
* Asynchronous operation.
*
@@ -647,7 +647,7 @@ public class HBaseAdmin {
/**
* Get the status of alter command - indicates how many regions have received
* the updated schema Asynchronous operation.
- *
+ *
* @param tableName
* name of the table to get the status of
* @return List indicating the number of regions updated List.get(0) is the
@@ -687,7 +687,7 @@ public class HBaseAdmin {
* @param column column descriptor of column to be added
* @throws IOException if a remote or network exception occurs
*/
- public void addColumn(final byte [] tableName, HColumnDescriptor column)
+ public void addColumn(final byte [] tableName, HColumnDescriptor column)
throws IOException {
alterTable(tableName, Arrays.asList(column), null, null);
}
@@ -714,7 +714,7 @@ public class HBaseAdmin {
* @param columnName name of column to be deleted
* @throws IOException if a remote or network exception occurs
*/
- public void deleteColumn(final byte [] tableName,
+ public void deleteColumn(final byte [] tableName,
final byte [] columnName)
throws IOException {
alterTable(tableName, null, null, Arrays.asList(columnName));
@@ -732,7 +732,7 @@ public class HBaseAdmin {
HColumnDescriptor descriptor)
throws IOException {
alterTable(Bytes.toBytes(tableName), null, Arrays.asList(
- new Pair<byte [], HColumnDescriptor>(Bytes.toBytes(columnName),
+ new Pair<byte [], HColumnDescriptor>(Bytes.toBytes(columnName),
descriptor)), null);
}
@@ -981,7 +981,7 @@ public class HBaseAdmin {
throws IOException {
modifyTable(tableNameOrRegionName, HConstants.Modify.TABLE_MAJOR_COMPACT);
}
-
+
/**
* Major compacts a column family within a region or table.
* Asynchronous operation.
@@ -1036,7 +1036,7 @@ public class HBaseAdmin {
}
/**
- * Split a table or an individual region. Implicitly finds an optimal split
+ * Split a table or an individual region. Implicitly finds an optimal split
* point. Asynchronous operation.
*
* @param tableNameOrRegionName table to region to split
@@ -1045,7 +1045,7 @@ public class HBaseAdmin {
public void split(final byte [] tableNameOrRegionName) throws IOException {
modifyTable(tableNameOrRegionName, HConstants.Modify.TABLE_SPLIT);
}
-
+
public void split(final String tableNameOrRegionName,
final String splitPoint) throws IOException {
split(Bytes.toBytes(tableNameOrRegionName), Bytes.toBytes(splitPoint));
@@ -1059,7 +1059,7 @@ public class HBaseAdmin {
* @param splitPoint the explicit position to split on
* @throws IOException if a remote or network exception occurs
*/
- public void split(final byte [] tableNameOrRegionName,
+ public void split(final byte [] tableNameOrRegionName,
final byte [] splitPoint) throws IOException {
if (tableNameOrRegionName == null) {
throw new IllegalArgumentException("Pass a table name or region name");
@@ -1067,7 +1067,7 @@ public class HBaseAdmin {
byte [] tableName = tableExists(tableNameOrRegionName)?
tableNameOrRegionName: null;
byte [] regionName = tableName == null? tableNameOrRegionName: null;
- Object [] args = regionName == null?
+ Object [] args = regionName == null?
new byte [][] {splitPoint}: new byte [][] {regionName, splitPoint};
modifyTable(tableName, HConstants.Modify.TABLE_EXPLICIT_SPLIT, args);
}
@@ -1176,7 +1176,7 @@ public class HBaseAdmin {
throw RemoteExceptionHandler.decodeRemoteException(e);
}
}
-
+
private static Writable toWritable(Object o) {
if (o == null) {
return null;
@@ -1204,6 +1204,7 @@ public class HBaseAdmin {
throw new MasterNotRunningException("master has been shut down");
}
try {
+ // Shutdown the whole HBase cluster.
this.master.shutdown();
} catch (RemoteException e) {
throw RemoteExceptionHandler.decodeRemoteException(e);
@@ -1214,7 +1215,7 @@ public class HBaseAdmin {
/**
* Stop the designated RegionServer for a restart.
- *
+ *
* @param hsa
* the address of the RegionServer to stop
* @throws IOException
Modified: hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/executor/HBaseEventHandler.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/executor/HBaseEventHandler.java?rev=1369645&r1=1369644&r2=1369645&view=diff
==============================================================================
--- hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/executor/HBaseEventHandler.java (original)
+++ hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/executor/HBaseEventHandler.java Sun Aug 5 19:16:11 2012
@@ -19,6 +19,7 @@
*/
package org.apache.hadoop.hbase.executor;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -26,24 +27,26 @@ import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.hbase.executor.HBaseExecutorService.HBaseExecutorServiceType;
+import org.apache.hadoop.hbase.master.ServerManager;
+import org.apache.hadoop.hbase.util.Writables;
/**
- * Abstract base class for all HBase event handlers. Subclasses should
- * implement the process() method where the actual handling of the event
+ * Abstract base class for all HBase event handlers. Subclasses should
+ * implement the process() method where the actual handling of the event
* happens.
- *
- * HBaseEventType is a list of ALL events (which also corresponds to messages -
- * either internal to one component or between components). The event type
- * names specify the component from which the event originated, and the
+ *
+ * HBaseEventType is a list of ALL events (which also corresponds to messages -
+ * either internal to one component or between components). The event type
+ * names specify the component from which the event originated, and the
* component which is supposed to handle it.
- *
- * Listeners can listen to all the events by implementing the interface
- * HBaseEventHandlerListener, and by registering themselves as a listener. They
+ *
+ * Listeners can listen to all the events by implementing the interface
+ * HBaseEventHandlerListener, and by registering themselves as a listener. They
* will be called back before and after the process of every event.
- *
- * TODO: Rename HBaseEvent and HBaseEventType to EventHandler and EventType
- * after ZK refactor as it currently would clash with EventType from ZK and
+ *
+ * TODO: Rename HBaseEvent and HBaseEventType to EventHandler and EventType
+ * after ZK refactor as it currently would clash with EventType from ZK and
* make the code very confusing.
*/
public abstract class HBaseEventHandler implements Runnable
@@ -53,16 +56,23 @@ public abstract class HBaseEventHandler
protected HBaseEventType eventType = HBaseEventType.NONE;
// is this a region server or master?
protected boolean isRegionServer;
- // name of the server - this is needed for naming executors in case of tests
+ // name of the server - this is needed for naming executors in case of tests
// where region servers may be co-located.
protected String serverName;
+
+ protected final String regionName;
+ protected final byte[] serializedData;
+ protected final ServerManager serverManager;
+
+ protected RegionTransitionEventData hbEventData;
+
// listeners that are called before and after an event is processed
- protected static List<HBaseEventHandlerListener> eventHandlerListeners =
- Collections.synchronizedList(new ArrayList<HBaseEventHandlerListener>());
+ protected static List<HBaseEventHandlerListener> eventHandlerListeners =
+ Collections.synchronizedList(new ArrayList<HBaseEventHandlerListener>());
/**
- * This interface provides hooks to listen to various events received by the
- * queue. A class implementing this can listen to the updates by calling
+ * This interface provides hooks to listen to various events received by the
+ * queue. A class implementing this can listen to the updates by calling
* registerListener and stop receiving updates by calling unregisterListener
*/
public interface HBaseEventHandlerListener {
@@ -82,29 +92,29 @@ public abstract class HBaseEventHandler
*/
public enum HBaseEventType {
NONE (-1),
- // Messages originating from RS (NOTE: there is NO direct communication from
+ // Messages originating from RS (NOTE: there is NO direct communication from
// RS to Master). These are a result of RS updates into ZK.
RS2ZK_REGION_CLOSING (1), // RS is in process of closing a region
RS2ZK_REGION_CLOSED (2), // RS has finished closing a region
RS2ZK_REGION_OPENING (3), // RS is in process of opening a region
RS2ZK_REGION_OPENED (4), // RS has finished opening a region
-
- // Updates from master to ZK. This is done by the master and there is
+
+ // Updates from master to ZK. This is done by the master and there is
// nothing to process by either Master or RS
M2ZK_REGION_OFFLINE (50); // Master adds this region as offline in ZK
-
+
private final byte value;
-
+
/**
- * Called by the HMaster. Returns a name of the executor service given an
- * event type. Every event type has en entry - if the event should not be
+ * Called by the HMaster. Returns a name of the executor service given an
+ * event type. Every event type has en entry - if the event should not be
* handled just add the NONE executor.
* @return name of the executor service
*/
public HBaseExecutorServiceType getMasterExecutorForEvent() {
HBaseExecutorServiceType executorServiceType = null;
switch(this) {
-
+
case RS2ZK_REGION_CLOSING:
case RS2ZK_REGION_CLOSED:
executorServiceType = HBaseExecutorServiceType.MASTER_CLOSEREGION;
@@ -114,31 +124,31 @@ public abstract class HBaseEventHandler
case RS2ZK_REGION_OPENED:
executorServiceType = HBaseExecutorServiceType.MASTER_OPENREGION;
break;
-
+
case M2ZK_REGION_OFFLINE:
executorServiceType = HBaseExecutorServiceType.NONE;
break;
-
+
default:
throw new RuntimeException("Unhandled event type in the master.");
}
-
+
return executorServiceType;
}
/**
- * Called by the RegionServer. Returns a name of the executor service given an
- * event type. Every event type has en entry - if the event should not be
+ * Called by the RegionServer. Returns a name of the executor service given an
+ * event type. Every event type has en entry - if the event should not be
* handled just return a null executor name.
* @return name of the event service
*/
public static String getRSExecutorForEvent(String serverName) {
throw new RuntimeException("Unsupported operation.");
}
-
+
/**
- * Start the executor service that handles the passed in event type. The
- * server that starts these event executor services wants to handle these
+ * Start the executor service that handles the passed in event type. The
+ * server that starts these event executor services wants to handle these
* event types.
*/
public void startMasterExecutorService(String serverName) {
@@ -150,13 +160,13 @@ public abstract class HBaseEventHandler
}
public static void startRSExecutorService() {
-
+
}
HBaseEventType(int intValue) {
this.value = (byte)intValue;
}
-
+
public byte getByteValue() {
return value;
}
@@ -175,30 +185,30 @@ public abstract class HBaseEventHandler
}
}
}
-
+
/**
* Default base class constructor.
- *
- * TODO: isRegionServer and serverName will go away once we do the HMaster
- * refactor. We will end up passing a ServerStatus which should tell us both
- * the name and if it is a RS or master.
*/
- public HBaseEventHandler(boolean isRegionServer, String serverName, HBaseEventType eventType) {
+ public HBaseEventHandler(boolean isRegionServer, String serverName, HBaseEventType eventType,
+ String regionName, byte[] serializedData, ServerManager serverManager) {
this.isRegionServer = isRegionServer;
this.eventType = eventType;
this.serverName = serverName;
+ this.regionName = regionName;
+ this.serializedData = serializedData;
+ this.serverManager = serverManager;
}
-
+
/**
- * This is a wrapper around process, used to update listeners before and after
- * events are processed.
+ * This is a wrapper around process, used to update listeners before and after
+ * events are processed.
*/
public void run() {
// fire all beforeProcess listeners
for(HBaseEventHandlerListener listener : eventHandlerListeners) {
listener.beforeProcess(this);
}
-
+
// call the main process function
try {
process();
@@ -208,32 +218,32 @@ public abstract class HBaseEventHandler
// fire all afterProcess listeners
for(HBaseEventHandlerListener listener : eventHandlerListeners) {
- LOG.debug("Firing " + listener.getClass().getName() +
+ LOG.debug("Firing " + listener.getClass().getName() +
".afterProcess event listener for event " + eventType);
listener.afterProcess(this);
}
}
-
+
/**
- * This method is the main processing loop to be implemented by the various
+ * This method is the main processing loop to be implemented by the various
* subclasses.
*/
public abstract void process();
-
+
/**
* Subscribe to updates before and after processing events
*/
public static void registerListener(HBaseEventHandlerListener listener) {
eventHandlerListeners.add(listener);
}
-
+
/**
* Stop receiving updates before and after processing events
*/
public static void unregisterListener(HBaseEventHandlerListener listener) {
eventHandlerListeners.remove(listener);
}
-
+
public boolean isRegionServer() {
return isRegionServer;
}
@@ -246,7 +256,7 @@ public abstract class HBaseEventHandler
// TODO: check for isRegionServer here
return eventType.getMasterExecutorForEvent();
}
-
+
/**
* Return the event type
* @return
@@ -266,12 +276,36 @@ public abstract class HBaseEventHandler
}
serviceType.getExecutor(serverName).submit(this);
}
-
+
/**
- * Executes this event object in the caller's thread. This is a synchronous
+ * Executes this event object in the caller's thread. This is a synchronous
* way of executing the event.
*/
public void execute() {
this.run();
}
+
+ public String getRegionName() {
+ return regionName;
+ }
+
+ protected void ensureEventDataAvailable() {
+ if (hbEventData != null) {
+ return;
+ }
+
+ try {
+ hbEventData = new RegionTransitionEventData();
+ Writables.getWritable(serializedData, hbEventData);
+ } catch (IOException e) {
+ LOG.error("Could not deserialize additional args for region transition", e);
+ throw new RuntimeException(e);
+ }
+ }
+
+ public String getRegionServerName() {
+ ensureEventDataAvailable();
+ return hbEventData.getRsName();
+ }
+
}
Modified: hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/master/AssignmentManager.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/master/AssignmentManager.java?rev=1369645&r1=1369644&r2=1369645&view=diff
==============================================================================
--- hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/master/AssignmentManager.java (original)
+++ hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/master/AssignmentManager.java Sun Aug 5 19:16:11 2012
@@ -22,14 +22,14 @@ import org.apache.hadoop.hbase.util.Thre
import org.apache.hadoop.hbase.util.HasThread;
/**
- * Manages the preferences for assigning regions to specific servers.
+ * Manages the preferences for assigning regions to specific servers.
* It get the assignment plan from scanning the META region and keep this
* assignment plan updated.
- *
+ *
* The assignment manager executes the assignment plan by adding the regions
* with its most favored live region server into the transient assignment.
* Each transient assignment will be only valid for a configurable time
- * before expire. During these valid time, the region will only be assigned
+ * before expire. During these valid time, the region will only be assigned
* based on the transient assignment.
*
* All access to this class is thread-safe.
@@ -68,12 +68,12 @@ public class AssignmentManager {
* favored region server list.
*/
private AssignmentPlan assignmentPlan;
-
+
private final HMaster master;
private final Configuration conf;
private long millisecondDelay;
private POSITION[] positions;
-
+
public AssignmentManager(HMaster master) {
this.master = master;
this.conf = master.getConfiguration();
@@ -142,7 +142,7 @@ public class AssignmentManager {
// information may indicate that the server is in the process of
// shutting down.
if (info != null &&
- !master.getServerManager().isDead(info.getServerName()) &&
+ !master.getServerManager().isDeadProcessingPending(info.getServerName()) &&
master.getServerManager().getServersToServerInfo().get(info.getServerName()) != null) {
LOG.info("Add a transient assignment from the assignment plan: "
+ " region " + region.getRegionNameAsString() + " to the "
@@ -171,7 +171,7 @@ public class AssignmentManager {
}
LOG.debug("Remove the transisent assignment: region " +
region.getRegionNameAsString() + " to " +
- server.getHostNameWithPort());
+ server.getHostNameWithPort());
return true;
}
return false;
Modified: hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/master/BaseScanner.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/master/BaseScanner.java?rev=1369645&r1=1369644&r2=1369645&view=diff
==============================================================================
--- hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/master/BaseScanner.java (original)
+++ hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/master/BaseScanner.java Sun Aug 5 19:16:11 2012
@@ -24,7 +24,6 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -122,9 +121,6 @@ abstract class BaseScanner extends Chore
private final boolean rootRegion;
protected final HMaster master;
- protected boolean initialScanComplete;
-
- protected abstract boolean initialScan();
protected abstract void maintenanceScan();
// will use this variable to synchronize and make sure we aren't interrupted
@@ -138,17 +134,6 @@ abstract class BaseScanner extends Chore
master);
this.rootRegion = rootRegion;
this.master = master;
- this.initialScanComplete = false;
- }
-
- /** @return true if initial scan completed successfully */
- public boolean isInitialScanComplete() {
- return initialScanComplete;
- }
-
- @Override
- protected boolean initialChore() {
- return initialScan();
}
@Override
@@ -196,19 +181,19 @@ abstract class BaseScanner extends Chore
HConstants.FAVOREDNODES_QUALIFIER);
AssignmentManager assignmentManager =
this.master.getRegionManager().getAssignmentManager();
-
+
if (favoredNodes != null) {
// compare the update TS
- long updateTimeStamp =
+ long updateTimeStamp =
values.getLastestTimeStamp(HConstants.CATALOG_FAMILY,
HConstants.FAVOREDNODES_QUALIFIER);
- long lastUpdate =
+ long lastUpdate =
assignmentManager.getAssignmentPlanUpdateTimeStamp(region);
if (lastUpdate < updateTimeStamp) {
// need to update the persistent assignment
List<HServerAddress> servers =
RegionPlacement.getFavoredNodesList(favoredNodes);
- assignmentManager.updateAssignmentPlan(region,
+ assignmentManager.updateAssignmentPlan(region,
servers, updateTimeStamp);
}
} else {
@@ -555,15 +540,18 @@ abstract class BaseScanner extends Chore
return result;
}
- /*
- * Check the passed region is assigned. If not, add to unassigned.
- * @param regionServer
- * @param meta
- * @param info
+ /**
+ * Check the passed region ('info') is assigned. This method re-reads the state of the region
+ * from the 'meta' region if it appears unassigned, because this information might be stale. If
+ * not, add to unassigned.
+ *
+ * @param regionServer the regionserver hosting the meta/root region
+ * @param meta the meta/root region of the given region
+ * @param info the region info for the region we are checking
* @param hostnameAndPort hostname ':' port as it comes out of .META.
- * @param startCode
- * @param checkTwice should we check twice before adding a region
- * to unassigned pool.
+ * @param startCode start code of the regionserver that this region is assigned to acording to
+ * meta/root
+ * @param checkTwice should we check twice before adding a region to unassigned pool.
* @throws IOException
*/
protected void checkAssigned(final HRegionInterface regionServer,
@@ -596,14 +584,21 @@ abstract class BaseScanner extends Chore
* a dead server. Regions that were on a dead server will get reassigned
* by ProcessServerShutdown
*/
+
+ boolean processingServerAsDead = false;
+ if (serverName != null) {
+ synchronized (master.getServerManager().deadServerStatusLock) {
+ processingServerAsDead =
+ this.master.getServerManager().isDeadProcessingPending(serverName);
+ storedInfo = this.master.getServerManager().getServerInfo(serverName);
+ }
+ }
+
if (info == null || info.isOffline() ||
this.master.getRegionManager().regionIsInTransition(info.getRegionNameAsString()) ||
- (serverName != null && this.master.getServerManager().isDead(serverName))) {
+ (serverName != null && processingServerAsDead)) {
return;
}
- if (serverName != null) {
- storedInfo = this.master.getServerManager().getServerInfo(serverName);
- }
// If we can't find the HServerInfo, then add it to the list of
// unassigned regions.
@@ -619,6 +614,9 @@ abstract class BaseScanner extends Chore
// Now get the region assigned
this.master.getRegionManager().setUnassigned(info, true);
}
+ } else if (info.isMetaTable()) {
+ MetaRegion m = new MetaRegion(storedInfo.getServerAddress(), info);
+ master.getRegionManager().putMetaRegionOnline(m);
}
}
if (tryAgain) {
@@ -639,7 +637,7 @@ abstract class BaseScanner extends Chore
* Interrupt thread regardless of what it's doing
*/
public void interruptAndStop() {
- synchronized(scannerLock){
+ synchronized(scannerLock) {
if (isAlive()) {
stopThread();
super.interrupt();
Modified: hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/master/HMaster.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/master/HMaster.java?rev=1369645&r1=1369644&r2=1369645&view=diff
==============================================================================
--- hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/master/HMaster.java (original)
+++ hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/master/HMaster.java Sun Aug 5 19:16:11 2012
@@ -33,7 +33,6 @@ import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
-import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.NavigableMap;
@@ -67,7 +66,6 @@ import org.apache.hadoop.hbase.HConstant
import org.apache.hadoop.hbase.HConstants.Modify;
import org.apache.hadoop.hbase.HMsg;
import org.apache.hadoop.hbase.HRegionInfo;
-import org.apache.hadoop.hbase.HRegionLocation;
import org.apache.hadoop.hbase.HServerAddress;
import org.apache.hadoop.hbase.HServerInfo;
import org.apache.hadoop.hbase.HTableDescriptor;
@@ -114,6 +112,7 @@ import org.apache.hadoop.hbase.util.Slee
import org.apache.hadoop.hbase.util.Threads;
import org.apache.hadoop.hbase.util.VersionInfo;
import org.apache.hadoop.hbase.util.Writables;
+import org.apache.hadoop.hbase.zookeeper.LegacyRootZNodeUpdater;
import org.apache.hadoop.hbase.zookeeper.ZooKeeperWrapper;
import org.apache.hadoop.io.MapWritable;
import org.apache.hadoop.io.Text;
@@ -174,7 +173,9 @@ public class HMaster extends HasThread i
// Metrics is set when we call run.
private MasterMetrics metrics;
+ /** A lock used for serial log splitting */
final Lock splitLogLock = new ReentrantLock();
+
final boolean distributedLogSplitting;
SplitLogManager splitLogManager;
@@ -188,7 +189,7 @@ public class HMaster extends HasThread i
private final Sleeper sleeper;
// Keep around for convenience.
private final FileSystem fs;
- // Is the fileystem ok?
+ // Is the filesystem ok?
private volatile boolean fsOk = true;
// The Path to the old logs dir
private final Path oldLogDir;
@@ -199,12 +200,17 @@ public class HMaster extends HasThread i
private final ServerConnection connection;
private ServerManager serverManager;
private RegionManager regionManager;
+ private ZKUnassignedWatcher unassignedWatcher;
private long lastFragmentationQuery = -1L;
private Map<String, Integer> fragmentation = null;
private RegionServerOperationQueue regionServerOperationQueue;
- /** True if this is the master that started the cluster. */
+ /**
+ * True if this is the master that started the cluster. We mostly use this for unit testing, as
+ * our master failover workflow does not depend on this anymore.
+ */
+ @Deprecated
private boolean isClusterStartup;
private long masterStartupTime = Long.MAX_VALUE;
@@ -220,14 +226,14 @@ public class HMaster extends HasThread i
private volatile boolean isActiveMaster = false;
public ThreadPoolExecutor logSplitThreadPool;
-
+
public RegionPlacementPolicy regionPlacement;
/** Log directories split on startup for testing master failover */
private List<String> logDirsSplitOnStartup;
private boolean shouldAssignRegionsWithFavoredNodes = false;
-
+
/**
* The number of dead server log split requests received. This is not
* incremented during log splitting on startup. This field is never
@@ -270,7 +276,6 @@ public class HMaster extends HasThread i
// the primary master has written the address to ZK. So this has to be done
// before we race to write our address to zookeeper.
initializeZooKeeper();
- detectClusterStartup();
this.numRetries = conf.getInt("hbase.client.retries.number", 2);
this.threadWakeFrequency = conf.getInt(HConstants.THREAD_WAKE_FREQUENCY,
@@ -338,7 +343,7 @@ public class HMaster extends HasThread i
final String masterName = getServerName();
// initialize the thread pool for non-distributed log splitting.
- int maxSplitLogThread =
+ int maxSplitLogThread =
conf.getInt("hbase.master.splitLogThread.max", 1000);
logSplitThreadPool = Threads.getBoundedCachedThreadPool(
maxSplitLogThread, 30L, TimeUnit.SECONDS,
@@ -354,7 +359,7 @@ public class HMaster extends HasThread i
});
regionPlacement = new RegionPlacement(this.conf);
-
+
// Only read favored nodes if using the assignment-based load balancer.
this.shouldAssignRegionsWithFavoredNodes = conf.getClass(
HConstants.LOAD_BALANCER_IMPL, Object.class).equals(
@@ -391,6 +396,18 @@ public class HMaster extends HasThread i
return shouldAssignRegionsWithFavoredNodes;
}
+ void startZKUnassignedWatcher() throws IOException {
+ if (unassignedWatcher != null) {
+ LOG.error("ZK unassigned watcher already started", new Throwable());
+ return;
+ }
+
+ // Start the unassigned watcher - which will create the unassigned region
+ // in ZK. If ZK unassigned events happen before the initial scan of the ZK unassigned
+ // directory is complete, they will be queued for further processing.
+ unassignedWatcher = new ZKUnassignedWatcher(this);
+ }
+
/**
* @return true if successfully became primary master
*/
@@ -402,8 +419,6 @@ public class HMaster extends HasThread i
zooKeeperWrapper.close();
return false;
}
-
- detectClusterStartup();
isActiveMaster = true;
synchronized(this) {
@@ -414,17 +429,6 @@ public class HMaster extends HasThread i
new RegionServerOperationQueue(this.conf, serverManager,
getClosedStatus());
-
- // Start the unassigned watcher - which will create the unassigned region
- // in ZK. This is needed before RegionManager() constructor tries to assign
- // the root region.
- try {
- ZKUnassignedWatcher.start(this.conf, this);
- } catch (IOException e) {
- LOG.error("Failed to start ZK unassigned region watcher", e);
- throw new RuntimeException(e);
- }
-
// start the "close region" executor service
HBaseEventType.RS2ZK_REGION_CLOSED.startMasterExecutorService(
address.toString());
@@ -447,10 +451,6 @@ public class HMaster extends HasThread i
return true;
}
- public void detectClusterStartup() {
- isClusterStartup = (zooKeeperWrapper.scanRSDirectory().size() == 0);
- }
-
public ThreadPoolExecutor getLogSplitThreadPool() {
return this.logSplitThreadPool;
}
@@ -522,10 +522,11 @@ public class HMaster extends HasThread i
}
/**
- * Returns true if this master process was responsible for starting the
- * cluster.
+ * Returns true if this master process was responsible for starting the cluster. Only used in
+ * unit tests.
*/
- public boolean isClusterStartup() {
+ @Deprecated
+ boolean isClusterStartup() {
return isClusterStartup;
}
@@ -747,26 +748,68 @@ public class HMaster extends HasThread i
return;
}
- if (closed.get()) {
- LOG.info("Master is closing, not starting the main loop");
+ if (isStopped()) {
+ LOG.info("Master is shutting down, not starting the main loop");
return;
}
+
MonitoredTask startupStatus =
TaskMonitor.get().createStatus("Master startup");
startupStatus.setDescription("Master startup");
clusterStateRecovery = new ZKClusterStateRecovery(this, connection);
try {
- joinCluster();
- initPreferredAssignment();
- startupStatus.setStatus("Initializing master service threads");
- startServiceThreads();
- masterStartupTime = System.currentTimeMillis();
- startupStatus.markComplete("Initialization successful");
+ if (!isStopped() && !shouldAssignRegionsWithFavoredNodes()) {
+ // This is only done if we are using the old mechanism for locality-based assignment
+ // not relying on the favored node functionality in HDFS.
+ initPreferredAssignment();
+ }
+
+ if (!isStopped()) {
+ clusterStateRecovery.registerLiveRegionServers();
+ isClusterStartup = clusterStateRecovery.isClusterStartup(); // for testing
+ }
+
+ if (!isStopped() || isClusterShutdownRequested()) {
+ // Start the server so that region servers are running before we start
+ // splitting logs and before we start assigning regions. XXX What will
+ // happen if master starts receiving requests before regions are assigned?
+ // NOTE: If the master bind port is 0 (e.g. in unit tests) we initialize the RPC server
+ // earlier and do nothing here.
+ // TODO: move this to startServiceThreads once we break the dependency of distributed log
+ // splitting on regionserver check-in.
+ initRpcServer(address);
+ rpcServer.start();
+ }
+
+ if (!isStopped()) {
+ splitLogAfterStartup();
+ }
+
+ if (!isStopped()) {
+ startZKUnassignedWatcher();
+ }
+
+ if (!isStopped()) {
+ startupStatus.setStatus("Initializing master service threads");
+ startServiceThreads();
+ masterStartupTime = System.currentTimeMillis();
+ startupStatus.markComplete("Initialization successful");
+ }
} catch (IOException e) {
LOG.fatal("Unhandled exception. Master quits.", e);
startupStatus.cleanup();
+ zooKeeperWrapper.close();
return;
}
+
+ if (isStopped()) {
+ startupStatus.markComplete("Initialization aborted, shutting down");
+ }
+
+ if (!isStopped()) {
+ clusterStateRecovery.backgroundRecoverRegionStateFromZK();
+ }
+
try {
/* Main processing loop */
FINISHED: while (!this.closed.get()) {
@@ -804,6 +847,7 @@ public class HMaster extends HasThread i
closed.set(true);
startShutdown();
+ startupStatus.cleanup();
if (clusterShutdownRequested.get()) {
// Wait for all the remaining region servers to report in. Only doing
@@ -812,15 +856,12 @@ public class HMaster extends HasThread i
}
serverManager.joinThreads();
- /*
- * Clean up and close up shop
- */
if (this.infoServer != null) {
LOG.info("Stopping infoServer");
try {
this.infoServer.stop();
} catch (Exception ex) {
- ex.printStackTrace();
+ LOG.error("Error stopping info server", ex);
}
}
if (this.rpcServer != null) {
@@ -956,78 +997,29 @@ public class HMaster extends HasThread i
return regionLocalityMap;
}
-
- /*
- * Joins cluster. Checks to see if this instance of HBase is fresh or the
- * master was started following a failover. In the second case, it inspects
- * the region server directory and gets their regions assignment.
- */
- private void joinCluster() throws IOException {
- LOG.debug("Checking cluster state...");
-
- clusterStateRecovery.registerLiveRegionServers();
-
- // Check if this is a fresh start of the cluster
- if (clusterStateRecovery.liveRegionServersAtStartup().isEmpty()) {
- LOG.debug("Master fresh start, proceeding with normal startup");
- return;
+ private void startSplitLogManager() {
+ if (this.distributedLogSplitting) {
+ // splitLogManager must be started before starting rpcServer because
+ // region-servers dying will trigger log splitting
+ this.splitLogManager = new SplitLogManager(zooKeeperWrapper, conf,
+ getStopper(), address.toString());
+ this.splitLogManager.finishInitialization();
}
-
- // Failover case.
- LOG.info("Master failover, ZK inspection begins...");
- // only read the rootlocation if it is failover
- HServerAddress rootLocation =
- this.zooKeeperWrapper.readRootRegionLocation();
- boolean isRootRegionAssigned = false;
- Map <byte[], HRegionInfo> assignedRegions =
- new HashMap<byte[], HRegionInfo>();
- // We must:
- // - contact every region server to add them to the regionservers list
- // - get their current regions assignment
- // TODO: Run in parallel?
- for (String serverName : clusterStateRecovery.liveRegionServersAtStartup()) {
- HServerAddress address = HServerInfo.fromServerName(serverName).getServerAddress();
- HRegionInfo[] regions = null;
- try {
- HRegionInterface hri =
- this.connection.getHRegionConnection(address, false);
- HServerInfo info = hri.getHServerInfo();
- LOG.debug("Inspection found server " + info.getServerName());
- regions = hri.getRegionsAssignment();
- } catch (IOException e) {
- LOG.error("Failed contacting " + address.toString(), e);
- continue;
- }
- for (HRegionInfo r: regions) {
- if (r.isRootRegion()) {
- this.connection.setRootRegionLocation(new HRegionLocation(r, rootLocation));
- this.regionManager.setRootRegionLocation(rootLocation);
- // Undo the unassign work in the RegionManager constructor
- this.regionManager.removeRegion(r);
- isRootRegionAssigned = true;
- } else if (r.isMetaRegion()) {
- MetaRegion m = new MetaRegion(new HServerAddress(address), r);
- this.regionManager.addMetaRegionToScan(m);
- }
- assignedRegions.put(r.getRegionName(), r);
- }
- }
- LOG.info("Inspection found " + assignedRegions.size() + " regions, " +
- (isRootRegionAssigned ? "with -ROOT-" : "but -ROOT- was MIA"));
}
- /*
- * Inspect the log directory to recover any log file without
- * an active region server.
+ /**
+ * Inspect the log directory to recover any log file without an active region
+ * server.
*/
private void splitLogAfterStartup() {
+ startSplitLogManager();
boolean retrySplitting = !conf.getBoolean("hbase.hlog.split.skip.errors",
HLog.SPLIT_SKIP_ERRORS_DEFAULT);
List<String> serverNames = new ArrayList<String>();
try {
do {
- if (this.clusterShutdownRequested.get()) {
- LOG.warn("Cluster is shutting down, aborting log splitting");
+ if (isStopped()) {
+ LOG.warn("Master is shutting down, aborting log splitting");
return;
}
try {
@@ -1053,7 +1045,7 @@ public class HMaster extends HasThread i
serverNames.add(serverName);
} else {
LOG.info("Log folder " + status.getPath() +
- " belongs to an existing region server");
+ " belongs to an existing region server, not splitting");
}
}
logDirsSplitOnStartup = serverNames;
@@ -1070,7 +1062,7 @@ public class HMaster extends HasThread i
checkFileSystem(false);
try {
- if (retrySplitting) {
+ if (retrySplitting && !isStopped()) {
Thread.sleep(30000); //30s
}
} catch (InterruptedException e) {
@@ -1101,6 +1093,10 @@ public class HMaster extends HasThread i
long splitTime = 0, splitLogSize = 0, splitCount = 0;
List<Path> logDirs = new ArrayList<Path>();
for (String serverName : serverNames) {
+ if (isStopped()) {
+ LOG.warn("Master is shutting down, stopping log directory scan");
+ return;
+ }
Path logDir = new Path(this.rootdir,
HLog.getHLogDirectoryName(serverName));
// rename the directory so a rogue RS doesn't create more HLogs
@@ -1135,13 +1131,23 @@ public class HMaster extends HasThread i
// it is ok to call handleDeadWorkers with "rsname.splitting". These
// altered names will just get ignored
for (String serverName : serverNames) {
+ if (isStopped()) {
+ LOG.warn("Master is shutting down, stopping distributed log " +
+ "splitting");
+ return;
+ }
splitLogManager.handleDeadWorker(serverName);
}
splitLogManager.splitLogDistributed(logDirs);
} else {
+ // Serial log splitting.
// splitLogLock ensures that dead region servers' logs are processed
// one at a time
for (Path logDir : logDirs) {
+ if (isStopped()) {
+ LOG.warn("Master is shutting down, stopping serial log splitting");
+ return;
+ }
this.splitLogLock.lock();
try {
HLog.splitLog(this.rootdir, logDir, oldLogDir, this.fs,
@@ -1189,24 +1195,9 @@ public class HMaster extends HasThread i
this.infoServer.setAttribute(MASTER, this);
this.infoServer.start();
}
- if (this.distributedLogSplitting) {
- // splitLogManager must be started before starting rpcServer because
- // region-servers dying will trigger log splitting
- this.splitLogManager = new SplitLogManager(zooKeeperWrapper, conf,
- getStopper(), address.toString());
- this.splitLogManager.finishInitialization();
- }
- // Start the server so that region servers are running before we start
- // splitting logs and before we start assigning regions. XXX What will
- // happen if master starts receiving requests before regions are assigned?
- // NOTE: If the master bind port is 0 (e.g. in unit tests) we initialize the RPC server
- // earlier and do nothing here.
- initRpcServer(this.address);
- this.rpcServer.start();
if (LOG.isDebugEnabled()) {
LOG.debug("Started service threads");
}
- splitLogAfterStartup();
} catch (IOException e) {
if (e instanceof RemoteException) {
try {
@@ -1215,14 +1206,19 @@ public class HMaster extends HasThread i
LOG.warn("thread start", ex);
}
}
- // Something happened during startup. Shut things down.
+ // Something happened during startup. Stop the entire HBase cluster
+ // without quiescing region servers.
this.closed.set(true);
LOG.error("Failed startup", e);
}
}
- /*
+ /**
* Start shutting down the master. This does NOT trigger a cluster shutdown.
+ * However, if cluster shutdown has been triggered, this will indicate that
+ * it is now OK to stop regionservers, as it sets the master to the "closed"
+ * state. Therefore, only call this on cluster shutdown when all region
+ * servers have been quiesced.
*/
void startShutdown() {
this.closed.set(true);
@@ -1317,7 +1313,7 @@ public class HMaster extends HasThread i
stopped = true;
stopReason = "cluster shutdown";
}
-
+
/** Shutdown the cluster quickly, don't quiesce regionservers */
private void shutdownClusterNow() {
closed.set(true);
@@ -1465,7 +1461,7 @@ public class HMaster extends HasThread i
* Get the assignment domain for the table.
* Currently the domain would be generated by shuffling all the online
* region servers.
- *
+ *
* It would be easy to extend for the multi-tenancy in the future.
* @param tableName
* @return the assignment domain for the table.
@@ -1474,18 +1470,18 @@ public class HMaster extends HasThread i
// Get all the online region servers
List<HServerAddress> onlineRSList =
this.serverManager.getOnlineRegionServerList();
-
+
// Shuffle the server list based on the tableName
Random random = new Random(tableName.hashCode());
Collections.shuffle(onlineRSList, random);
-
+
// Add the shuffled server list into the assignment domain
AssignmentDomain domain = new AssignmentDomain(this.conf);
domain.addServers(onlineRSList);
-
+
return domain;
}
-
+
@Override
public void deleteTable(final byte [] tableName) throws IOException {
lockTable(tableName, "delete");
@@ -1906,8 +1902,7 @@ public class HMaster extends HasThread i
return status;
}
- // TODO ryan rework this function
- /*
+ /**
* Get HRegionInfo from passed META map of row values.
* Returns null if none found (and logs fact that expected COL_REGIONINFO
* was missing). Utility method used by scanners of META tables.
@@ -1924,6 +1919,9 @@ public class HMaster extends HasThread i
StringBuilder sb = new StringBuilder();
NavigableMap<byte[], byte[]> infoMap =
res.getFamilyMap(HConstants.CATALOG_FAMILY);
+ if (infoMap == null) {
+ return null;
+ }
for (byte [] e: infoMap.keySet()) {
if (sb.length() > 0) {
sb.append(", ");
@@ -2239,7 +2237,7 @@ public class HMaster extends HasThread i
public StoppableMaster getStopper() {
return this;
}
-
+
public StopStatus getClosedStatus() {
return new StopStatus() {
@Override
@@ -2249,4 +2247,8 @@ public class HMaster extends HasThread i
};
}
+ ZKUnassignedWatcher getUnassignedWatcher() {
+ return unassignedWatcher;
+ }
}
+
Modified: hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/master/MetaScanner.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/master/MetaScanner.java?rev=1369645&r1=1369644&r2=1369645&view=diff
==============================================================================
--- hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/master/MetaScanner.java (original)
+++ hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/master/MetaScanner.java Sun Aug 5 19:16:11 2012
@@ -39,7 +39,7 @@ import java.util.concurrent.TimeUnit;
*/
class MetaScanner extends BaseScanner {
/** Initial work for the meta scanner is queued up here */
- private volatile BlockingQueue<MetaRegion> metaRegionsToScan =
+ private final BlockingQueue<MetaRegion> metaRegionsToScan =
new LinkedBlockingQueue<MetaRegion>();
private final List<MetaRegion> metaRegionsToRescan =
@@ -59,7 +59,6 @@ class MetaScanner extends BaseScanner {
// things should be back to normal.
private boolean scanOneMetaRegion(MetaRegion region) {
while (!this.master.isClosed() &&
- !this.master.getRegionManager().isInitialRootScanComplete() &&
this.master.getRegionManager().getRootRegionLocation() == null) {
sleep();
}
@@ -98,31 +97,6 @@ class MetaScanner extends BaseScanner {
}
@Override
- protected boolean initialScan() {
- MetaRegion region = null;
- while (!this.master.isClosed() &&
- (region == null && metaRegionsToScan.size() > 0) &&
- !metaRegionsScanned()) {
- try {
- region = metaRegionsToScan.poll(this.master.getThreadWakeFrequency(),
- TimeUnit.MILLISECONDS);
- } catch (InterruptedException e) {
- // continue
- }
- if (region == null && metaRegionsToRescan.size() != 0) {
- region = metaRegionsToRescan.remove(0);
- }
- if (region != null) {
- if (!scanOneMetaRegion(region)) {
- metaRegionsToRescan.add(region);
- }
- }
- }
- initialScanComplete = true;
- return true;
- }
-
- @Override
protected void maintenanceScan() {
List<MetaRegion> regions =
this.master.getRegionManager().getListOfOnlineMetaRegions();
@@ -132,24 +106,19 @@ class MetaScanner extends BaseScanner {
regionCount++;
}
LOG.info("All " + regionCount + " .META. region(s) scanned");
- metaRegionsScanned();
+ notfiyAfterScan();
}
/*
* Called by the meta scanner when it has completed scanning all meta
* regions. This wakes up any threads that were waiting for this to happen.
- * @param totalRows Total rows scanned.
- * @param regionCount Count of regions in .META. table.
- * @return False if number of meta regions matches count of online regions.
*/
- private synchronized boolean metaRegionsScanned() {
- if (!this.master.getRegionManager().isInitialRootScanComplete() ||
- this.master.getRegionManager().numMetaRegions() !=
- this.master.getRegionManager().numOnlineMetaRegions()) {
- return false;
+ private synchronized void notfiyAfterScan() {
+ if (this.master.getRegionManager().numMetaRegions() <=
+ this.master.getRegionManager().numOnlineMetaRegions()) {
+ // All meta regions are online.
+ notifyAll();
}
- notifyAll();
- return true;
}
/**
@@ -159,9 +128,8 @@ class MetaScanner extends BaseScanner {
synchronized boolean waitForMetaRegionsOrClose() {
while (!this.master.isClosed()) {
synchronized (master.getRegionManager()) {
- if (this.master.getRegionManager().isInitialRootScanComplete() &&
- this.master.getRegionManager().numMetaRegions() ==
- this.master.getRegionManager().numOnlineMetaRegions()) {
+ if (this.master.getRegionManager().numMetaRegions() <=
+ this.master.getRegionManager().numOnlineMetaRegions()) {
break;
}
}
@@ -180,4 +148,8 @@ class MetaScanner extends BaseScanner {
void addMetaRegionToScan(MetaRegion m) {
metaRegionsToScan.add(m);
}
-}
\ No newline at end of file
+
+ public int getNumMetaRegionsToScan() {
+ return metaRegionsToScan.size();
+ }
+}
Modified: hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/master/ProcessRegionOpen.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/master/ProcessRegionOpen.java?rev=1369645&r1=1369644&r2=1369645&view=diff
==============================================================================
--- hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/master/ProcessRegionOpen.java (original)
+++ hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/master/ProcessRegionOpen.java Sun Aug 5 19:16:11 2012
@@ -46,10 +46,6 @@ public class ProcessRegionOpen extends P
public ProcessRegionOpen(HMaster master, HServerInfo info,
HRegionInfo regionInfo) {
super(master, info.getServerName(), regionInfo);
- if (info == null) {
- throw new NullPointerException("HServerInfo cannot be null; " +
- "hbase-958 debugging");
- }
this.serverInfo = info;
}
@@ -67,61 +63,55 @@ public class ProcessRegionOpen extends P
// is online.
return RegionServerOperationResult.OPERATION_DELAYED;
}
- HRegionInterface server =
- master.getServerConnection().getHRegionConnection(getMetaRegion().getServer());
- LOG.info(regionInfo.getRegionNameAsString() + " open on " +
- serverInfo.getServerName());
-
- // Register the newly-available Region's location.
- Put p = new Put(regionInfo.getRegionName());
- p.add(HConstants.CATALOG_FAMILY, HConstants.SERVER_QUALIFIER,
- Bytes.toBytes(serverInfo.getHostnamePort()));
- p.add(HConstants.CATALOG_FAMILY, HConstants.STARTCODE_QUALIFIER,
- Bytes.toBytes(serverInfo.getStartCode()));
- server.put(metaRegionName, p);
- LOG.info("Updated row " + regionInfo.getRegionNameAsString() +
- " in region " + Bytes.toString(metaRegionName) + " with startcode=" +
- serverInfo.getStartCode() + ", server=" + serverInfo.getHostnamePort());
- synchronized (master.getRegionManager()) {
+ writeToMeta(getMetaRegion());
+ RegionManager regionManager = master.getRegionManager();
+ synchronized (regionManager) {
if (isMetaTable) {
// It's a meta region.
MetaRegion m =
new MetaRegion(new HServerAddress(serverInfo.getServerAddress()),
regionInfo);
- if (!master.getRegionManager().isInitialMetaScanComplete()) {
- // Put it on the queue to be scanned for the first time.
- if (LOG.isDebugEnabled()) {
- LOG.debug("Adding " + m.toString() + " to regions to scan");
- }
- master.getRegionManager().addMetaRegionToScan(m);
- } else {
- // Add it to the online meta regions
- if (LOG.isDebugEnabled()) {
- LOG.debug("Adding to onlineMetaRegions: " + m.toString());
- }
- master.getRegionManager().putMetaRegionOnline(m);
- // Interrupting the Meta Scanner sleep so that it can
- // process regions right away
- master.getRegionManager().metaScannerThread.triggerNow();
+ // Add it to the online meta regions
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Adding to onlineMetaRegions: " + m.toString());
}
+ regionManager.putMetaRegionOnline(m);
+ // Interrupting the Meta Scanner sleep so that it can
+ // process regions right away
+ regionManager.metaScannerThread.triggerNow();
}
// If updated successfully, remove from pending list if the state
// is consistent. For example, a disable could be called before the
// synchronization.
- if(master.getRegionManager().
- isOfflined(regionInfo.getRegionNameAsString())) {
+ if (regionManager.isOfflined(regionInfo.getRegionNameAsString())) {
LOG.warn("We opened a region while it was asked to be closed.");
ZooKeeperWrapper zkWrapper =
ZooKeeperWrapper.getInstance(master.getConfiguration(),
master.getZKWrapperName());
zkWrapper.deleteUnassignedRegion(regionInfo.getEncodedName());
} else {
- master.getRegionManager().removeRegion(regionInfo);
+ regionManager.removeRegion(regionInfo);
}
return RegionServerOperationResult.OPERATION_SUCCEEDED;
}
}
+ void writeToMeta(MetaRegion region) throws IOException {
+ HRegionInterface server =
+ master.getServerConnection().getHRegionConnection(region.getServer());
+ LOG.info(regionInfo.getRegionNameAsString() + " open on " + serverInfo.getServerName());
+ // Register the newly-available Region's location.
+ Put p = new Put(regionInfo.getRegionName());
+ p.add(HConstants.CATALOG_FAMILY, HConstants.SERVER_QUALIFIER,
+ Bytes.toBytes(serverInfo.getHostnamePort()));
+ p.add(HConstants.CATALOG_FAMILY, HConstants.STARTCODE_QUALIFIER,
+ Bytes.toBytes(serverInfo.getStartCode()));
+ server.put(region.getRegionName(), p);
+ LOG.info("Updated row " + regionInfo.getRegionNameAsString() + " in region "
+ + Bytes.toString(region.getRegionName()) + " with startcode=" + serverInfo.getStartCode()
+ + ", server=" + serverInfo.getHostnamePort());
+ }
+
@Override
protected int getPriority() {
return 0; // highest priority
Modified: hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/master/ProcessRegionStatusChange.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/master/ProcessRegionStatusChange.java?rev=1369645&r1=1369644&r2=1369645&view=diff
==============================================================================
--- hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/master/ProcessRegionStatusChange.java (original)
+++ hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/master/ProcessRegionStatusChange.java Sun Aug 5 19:16:11 2012
@@ -52,8 +52,8 @@ abstract class ProcessRegionStatusChange
available = false;
}
} else {
- if (!master.getRegionManager().isInitialRootScanComplete() ||
- !metaTableAvailable()) {
+ // This operation is for a user table.
+ if (!metaTableAvailable()) {
// The root region has not been scanned or the meta table is not
// available so we can't proceed.
available = false;
@@ -74,9 +74,13 @@ abstract class ProcessRegionStatusChange
this.metaRegionName = this.metaRegion.getRegionName();
}
}
+ if (metaRegion == null) {
+ throw new NullPointerException("Could not identify meta region: " +
+ "isMetaTable=" + isMetaTable + ", regionInfo=" + regionInfo);
+ }
return this.metaRegion;
}
-
+
public HRegionInfo getRegionInfo() {
return regionInfo;
}