You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by gc...@apache.org on 2012/12/18 21:13:54 UTC
svn commit: r1423616 - in /hbase/branches/0.94/src:
main/java/org/apache/hadoop/hbase/
main/java/org/apache/hadoop/hbase/zookeeper/ main/resources/
test/java/org/apache/hadoop/hbase/zookeeper/
Author: gchanan
Date: Tue Dec 18 20:13:53 2012
New Revision: 1423616
URL: http://svn.apache.org/viewvc?rev=1423616&view=rev
Log:
HBASE-6775 Use ZK.multi when available for HBASE-6710 0.92/0.94 compatibility fix
Modified:
hbase/branches/0.94/src/main/java/org/apache/hadoop/hbase/HConstants.java
hbase/branches/0.94/src/main/java/org/apache/hadoop/hbase/zookeeper/RecoverableZooKeeper.java
hbase/branches/0.94/src/main/java/org/apache/hadoop/hbase/zookeeper/ZKTable.java
hbase/branches/0.94/src/main/java/org/apache/hadoop/hbase/zookeeper/ZKUtil.java
hbase/branches/0.94/src/main/resources/hbase-default.xml
hbase/branches/0.94/src/test/java/org/apache/hadoop/hbase/zookeeper/TestZKTable.java
hbase/branches/0.94/src/test/java/org/apache/hadoop/hbase/zookeeper/TestZKTableReadOnly.java
Modified: hbase/branches/0.94/src/main/java/org/apache/hadoop/hbase/HConstants.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.94/src/main/java/org/apache/hadoop/hbase/HConstants.java?rev=1423616&r1=1423615&r2=1423616&view=diff
==============================================================================
--- hbase/branches/0.94/src/main/java/org/apache/hadoop/hbase/HConstants.java (original)
+++ hbase/branches/0.94/src/main/java/org/apache/hadoop/hbase/HConstants.java Tue Dec 18 20:13:53 2012
@@ -157,6 +157,9 @@ public final class HConstants {
/** Default value for ZooKeeper session timeout */
public static final int DEFAULT_ZK_SESSION_TIMEOUT = 180 * 1000;
+ /** Configuration key for whether to use ZK.multi */
+ public static final String ZOOKEEPER_USEMULTI = "hbase.zookeeper.useMulti";
+
/** Parameter name for port region server listens on. */
public static final String REGIONSERVER_PORT = "hbase.regionserver.port";
Modified: hbase/branches/0.94/src/main/java/org/apache/hadoop/hbase/zookeeper/RecoverableZooKeeper.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.94/src/main/java/org/apache/hadoop/hbase/zookeeper/RecoverableZooKeeper.java?rev=1423616&r1=1423615&r2=1423616&view=diff
==============================================================================
--- hbase/branches/0.94/src/main/java/org/apache/hadoop/hbase/zookeeper/RecoverableZooKeeper.java (original)
+++ hbase/branches/0.94/src/main/java/org/apache/hadoop/hbase/zookeeper/RecoverableZooKeeper.java Tue Dec 18 20:13:53 2012
@@ -22,6 +22,7 @@ package org.apache.hadoop.hbase.zookeepe
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.util.ArrayList;
+import java.util.LinkedList;
import java.util.List;
import org.apache.commons.logging.Log;
@@ -32,11 +33,16 @@ import org.apache.hadoop.hbase.util.Retr
import org.apache.zookeeper.AsyncCallback;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.Op;
+import org.apache.zookeeper.OpResult;
import org.apache.zookeeper.Watcher;
+import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.ZooKeeper.States;
import org.apache.zookeeper.data.ACL;
import org.apache.zookeeper.data.Stat;
+import org.apache.zookeeper.proto.CreateRequest;
+import org.apache.zookeeper.proto.SetDataRequest;
/**
* A zookeeper that can handle 'recoverable' errors.
@@ -490,6 +496,61 @@ public class RecoverableZooKeeper {
}
}
+ /**
+ * Convert Iterable of {@link ZKOp} we got into the ZooKeeper.Op
+ * instances to actually pass to multi (need to do this in order to appendMetaData).
+ */
+ private Iterable<Op> prepareZKMulti(Iterable<Op> ops)
+ throws UnsupportedOperationException {
+ if(ops == null) return null;
+
+ List<Op> preparedOps = new LinkedList<Op>();
+ for (Op op : ops) {
+ if (op.getType() == ZooDefs.OpCode.create) {
+ CreateRequest create = (CreateRequest)op.toRequestRecord();
+ preparedOps.add(Op.create(create.getPath(), appendMetaData(create.getData()),
+ create.getAcl(), create.getFlags()));
+ } else if (op.getType() == ZooDefs.OpCode.delete) {
+ // no need to appendMetaData for delete
+ preparedOps.add(op);
+ } else if (op.getType() == ZooDefs.OpCode.setData) {
+ SetDataRequest setData = (SetDataRequest)op.toRequestRecord();
+ preparedOps.add(Op.setData(setData.getPath(), appendMetaData(setData.getData()),
+ setData.getVersion()));
+ } else {
+ throw new UnsupportedOperationException("Unexpected ZKOp type: " + op.getClass().getName());
+ }
+ }
+ return preparedOps;
+ }
+
+ /**
+ * Run multiple operations in a transactional manner. Retry before throwing exception
+ */
+ public List<OpResult> multi(Iterable<Op> ops)
+ throws KeeperException, InterruptedException {
+ RetryCounter retryCounter = retryCounterFactory.create();
+ Iterable<Op> multiOps = prepareZKMulti(ops);
+ while (true) {
+ try {
+ return zk.multi(multiOps);
+ } catch (KeeperException e) {
+ switch (e.code()) {
+ case CONNECTIONLOSS:
+ case SESSIONEXPIRED:
+ case OPERATIONTIMEOUT:
+ retryOrThrow(retryCounter, e, "multi");
+ break;
+
+ default:
+ throw e;
+ }
+ }
+ retryCounter.sleepUntilNextRetry();
+ retryCounter.useRetry();
+ }
+ }
+
private String findPreviousSequentialNode(String path)
throws KeeperException, InterruptedException {
int lastSlashIdx = path.lastIndexOf('/');
Modified: hbase/branches/0.94/src/main/java/org/apache/hadoop/hbase/zookeeper/ZKTable.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.94/src/main/java/org/apache/hadoop/hbase/zookeeper/ZKTable.java?rev=1423616&r1=1423615&r2=1423616&view=diff
==============================================================================
--- hbase/branches/0.94/src/main/java/org/apache/hadoop/hbase/zookeeper/ZKTable.java (original)
+++ hbase/branches/0.94/src/main/java/org/apache/hadoop/hbase/zookeeper/ZKTable.java Tue Dec 18 20:13:53 2012
@@ -21,6 +21,7 @@ package org.apache.hadoop.hbase.zookeepe
import java.util.HashMap;
import java.util.HashSet;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -29,6 +30,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.hbase.master.AssignmentManager;
import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.hadoop.hbase.zookeeper.ZKUtil.ZKUtilOp;
import org.apache.zookeeper.KeeperException;
/**
@@ -228,16 +230,19 @@ public class ZKTable {
}
}
synchronized (this.cache) {
+ List<ZKUtilOp> ops = new LinkedList<ZKUtilOp>();
if (settingToEnabled) {
- ZKUtil.deleteNodeFailSilent(this.watcher, znode92);
+ ops.add(ZKUtilOp.deleteNodeFailSilent(znode92));
}
else {
- ZKUtil.setData(this.watcher, znode92, Bytes.toBytes(state.toString()));
+ ops.add(ZKUtilOp.setData(znode92, Bytes.toBytes(state.toString())));
}
- // Set the current format znode after the 0.92 format znode.
+ // If not running multi-update either because of configuration or failure,
+ // set the current format znode after the 0.92 format znode.
// This is so in the case of failure, the AssignmentManager is guaranteed to
// see the state was not applied, since it uses the current format znode internally.
- ZKUtil.setData(this.watcher, znode, Bytes.toBytes(state.toString()));
+ ops.add(ZKUtilOp.setData(znode, Bytes.toBytes(state.toString())));
+ ZKUtil.multiOrSequential(this.watcher, ops, true);
this.cache.put(tableName, state);
}
}
@@ -292,13 +297,16 @@ public class ZKTable {
public void setDeletedTable(final String tableName)
throws KeeperException {
synchronized (this.cache) {
- ZKUtil.deleteNodeFailSilent(this.watcher,
- ZKUtil.joinZNode(this.watcher.masterTableZNode92, tableName));
- // Delete the current format znode after the 0.92 format znode.
- // This is so in the case of failure, the AssignmentManager is guaranteed to
- // see the table was not deleted, since it uses the current format znode internally.
- ZKUtil.deleteNodeFailSilent(this.watcher,
- ZKUtil.joinZNode(this.watcher.masterTableZNode, tableName));
+ List<ZKUtilOp> ops = new LinkedList<ZKUtilOp>();
+ ops.add(ZKUtilOp.deleteNodeFailSilent(
+ ZKUtil.joinZNode(this.watcher.masterTableZNode92, tableName)));
+ // If not running multi-update either because of configuration or failure,
+ // delete the current format znode after the 0.92 format znode. This is so in the case of
+ // failure, the AssignmentManager is guaranteed to see the table was not deleted, since it
+ // uses the current format znode internally.
+ ops.add(ZKUtilOp.deleteNodeFailSilent(
+ ZKUtil.joinZNode(this.watcher.masterTableZNode, tableName)));
+ ZKUtil.multiOrSequential(this.watcher, ops, true);
if (this.cache.remove(tableName) == null) {
LOG.warn("Moving table " + tableName + " state to deleted but was " +
"already deleted");
Modified: hbase/branches/0.94/src/main/java/org/apache/hadoop/hbase/zookeeper/ZKUtil.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.94/src/main/java/org/apache/hadoop/hbase/zookeeper/ZKUtil.java?rev=1423616&r1=1423615&r2=1423616&view=diff
==============================================================================
--- hbase/branches/0.94/src/main/java/org/apache/hadoop/hbase/zookeeper/ZKUtil.java (original)
+++ hbase/branches/0.94/src/main/java/org/apache/hadoop/hbase/zookeeper/ZKUtil.java Tue Dec 18 20:13:53 2012
@@ -26,6 +26,8 @@ import java.io.PrintWriter;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
@@ -39,15 +41,22 @@ import org.apache.hadoop.hbase.ServerNam
import org.apache.hadoop.hbase.executor.RegionTransitionData;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.Threads;
+import org.apache.hadoop.hbase.zookeeper.ZKUtil.ZKUtilOp.CreateAndFailSilent;
+import org.apache.hadoop.hbase.zookeeper.ZKUtil.ZKUtilOp.DeleteNodeFailSilent;
+import org.apache.hadoop.hbase.zookeeper.ZKUtil.ZKUtilOp.SetData;
import org.apache.zookeeper.AsyncCallback;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.KeeperException.NoNodeException;
+import org.apache.zookeeper.Op;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.ACL;
import org.apache.zookeeper.data.Stat;
+import org.apache.zookeeper.proto.CreateRequest;
+import org.apache.zookeeper.proto.DeleteRequest;
+import org.apache.zookeeper.proto.SetDataRequest;
/**
* Internal HBase utility class for ZooKeeper.
@@ -249,9 +258,6 @@ public class ZKUtil {
/**
* Check if the specified node exists. Sets no watches.
*
- * Returns true if node exists, false if not. Returns an exception if there
- * is an unexpected zookeeper exception.
- *
* @param zkw zk reference
* @param znode path of node to watch
* @return version of the node if it exists, -1 if does not exist
@@ -700,7 +706,13 @@ public class ZKUtil {
*/
public static void setData(ZooKeeperWatcher zkw, String znode, byte [] data)
throws KeeperException, KeeperException.NoNodeException {
- setData(zkw, znode, data, -1);
+ setData(zkw, (SetData)ZKUtilOp.setData(znode, data));
+ }
+
+ private static void setData(ZooKeeperWatcher zkw, SetData setData)
+ throws KeeperException, KeeperException.NoNodeException {
+ SetDataRequest sd = (SetDataRequest)toZooKeeperOp(zkw, setData).toRequestRecord();
+ setData(zkw, sd.getPath(), sd.getData(), sd.getVersion());
}
public static boolean isSecureZooKeeper(Configuration conf) {
@@ -896,14 +908,20 @@ public class ZKUtil {
* @throws KeeperException if unexpected zookeeper exception
*/
public static void createAndFailSilent(ZooKeeperWatcher zkw,
- String znode)
+ String znode) throws KeeperException {
+ createAndFailSilent(zkw,
+ (CreateAndFailSilent)ZKUtilOp.createAndFailSilent(znode, new byte[0]));
+ }
+
+ private static void createAndFailSilent(ZooKeeperWatcher zkw, CreateAndFailSilent cafs)
throws KeeperException {
+ CreateRequest create = (CreateRequest)toZooKeeperOp(zkw, cafs).toRequestRecord();
+ String znode = create.getPath();
try {
RecoverableZooKeeper zk = zkw.getRecoverableZooKeeper();
waitForZKConnectionIfAuthenticating(zkw);
if (zk.exists(znode, false) == null) {
- zk.create(znode, new byte[0], createACL(zkw,znode),
- CreateMode.PERSISTENT);
+ zk.create(znode, create.getData(), create.getAcl(), CreateMode.fromFlag(create.getFlags()));
}
} catch(KeeperException.NodeExistsException nee) {
} catch(KeeperException.NoAuthException nee){
@@ -989,8 +1007,15 @@ public class ZKUtil {
*/
public static void deleteNodeFailSilent(ZooKeeperWatcher zkw, String node)
throws KeeperException {
+ deleteNodeFailSilent(zkw,
+ (DeleteNodeFailSilent)ZKUtilOp.deleteNodeFailSilent(node));
+ }
+
+ private static void deleteNodeFailSilent(ZooKeeperWatcher zkw,
+ DeleteNodeFailSilent dnfs) throws KeeperException {
+ DeleteRequest delete = (DeleteRequest)toZooKeeperOp(zkw, dnfs).toRequestRecord();
try {
- zkw.getRecoverableZooKeeper().delete(node, -1);
+ zkw.getRecoverableZooKeeper().delete(delete.getPath(), delete.getVersion());
} catch(KeeperException.NoNodeException nne) {
} catch(InterruptedException ie) {
zkw.interruptedException(ie);
@@ -1038,6 +1063,209 @@ public class ZKUtil {
}
}
+ /**
+ * Represents an action taken by ZKUtil, e.g. createAndFailSilent.
+ * These actions are higher-level than {@link ZKOp} actions, which represent
+ * individual actions in the ZooKeeper API, like create.
+ */
+ public abstract static class ZKUtilOp {
+ private String path;
+
+ private ZKUtilOp(String path) {
+ this.path = path;
+ }
+
+ /**
+ * @return a createAndFailSilent ZKUtilOp
+ */
+ public static ZKUtilOp createAndFailSilent(String path, byte[] data) {
+ return new CreateAndFailSilent(path, data);
+ }
+
+ /**
+ * @return a deleteNodeFailSilent ZKUtilOP
+ */
+ public static ZKUtilOp deleteNodeFailSilent(String path) {
+ return new DeleteNodeFailSilent(path);
+ }
+
+ /**
+ * @return a setData ZKUtilOp
+ */
+ public static ZKUtilOp setData(String path, byte [] data) {
+ return new SetData(path, data);
+ }
+
+ /**
+ * @return path to znode where the ZKOp will occur
+ */
+ public String getPath() {
+ return path;
+ }
+
+ /**
+ * ZKUtilOp representing createAndFailSilent in ZooKeeper
+ * (attempt to create node, ignore error if already exists)
+ */
+ public static class CreateAndFailSilent extends ZKUtilOp {
+ private byte [] data;
+
+ private CreateAndFailSilent(String path, byte [] data) {
+ super(path);
+ this.data = data;
+ }
+
+ public byte[] getData() {
+ return data;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof CreateAndFailSilent)) return false;
+
+ CreateAndFailSilent op = (CreateAndFailSilent) o;
+ return getPath().equals(op.getPath()) && Arrays.equals(data, op.data);
+ }
+ }
+
+ /**
+ * ZKUtilOp representing deleteNodeFailSilent in ZooKeeper
+ * (attempt to delete node, ignore error if node doesn't exist)
+ */
+ public static class DeleteNodeFailSilent extends ZKUtilOp {
+ private DeleteNodeFailSilent(String path) {
+ super(path);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof DeleteNodeFailSilent)) return false;
+
+ return super.equals(o);
+ }
+ }
+
+ /**
+ * @return ZKUtilOp representing setData in ZooKeeper
+ */
+ public static class SetData extends ZKUtilOp {
+ private byte [] data;
+
+ private SetData(String path, byte [] data) {
+ super(path);
+ this.data = data;
+ }
+
+ public byte[] getData() {
+ return data;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof SetData)) return false;
+
+ SetData op = (SetData) o;
+ return getPath().equals(op.getPath()) && Arrays.equals(data, op.data);
+ }
+ }
+ }
+
+ /**
+ * Convert from ZKUtilOp to ZKOp
+ */
+ private static Op toZooKeeperOp(ZooKeeperWatcher zkw, ZKUtilOp op)
+ throws UnsupportedOperationException {
+ if(op == null) return null;
+
+ if (op instanceof CreateAndFailSilent) {
+ CreateAndFailSilent cafs = (CreateAndFailSilent)op;
+ return Op.create(cafs.getPath(), cafs.getData(), createACL(zkw, cafs.getPath()),
+ CreateMode.PERSISTENT);
+ } else if (op instanceof DeleteNodeFailSilent) {
+ DeleteNodeFailSilent dnfs = (DeleteNodeFailSilent)op;
+ return Op.delete(dnfs.getPath(), -1);
+ } else if (op instanceof SetData) {
+ SetData sd = (SetData)op;
+ return Op.setData(sd.getPath(), sd.getData(), -1);
+ } else {
+ throw new UnsupportedOperationException("Unexpected ZKUtilOp type: "
+ + op.getClass().getName());
+ }
+ }
+
+ /**
+ * If hbase.zookeeper.useMulti is true, use ZooKeeper's multi-update functionality.
+ * Otherwise, run the list of operations sequentially.
+ *
+ * If all of the following are true:
+ * - runSequentialOnMultiFailure is true
+ * - hbase.zookeeper.useMulti is true
+ * - on calling multi, we get a ZooKeeper exception that can be handled by a sequential call(*)
+ * Then:
+ * - we retry the operations one-by-one (sequentially)
+ *
+ * Note *: an example is receiving a NodeExistsException from a "create" call. Without multi,
+ * a user could call "createAndFailSilent" to ensure that a node exists if they don't care who
+ * actually created the node (i.e. the NodeExistsException from ZooKeeper is caught).
+ * This will cause all operations in the multi to fail, however, because
+ * the NodeExistsException that zk.create throws will fail the multi transaction.
+ * In this case, if the previous conditions hold, the commands are run sequentially, which should
+ * result in the correct final state, but means that the operations will not run atomically.
+ *
+ * @throws KeeperException
+ */
+ public static void multiOrSequential(ZooKeeperWatcher zkw, List<ZKUtilOp> ops,
+ boolean runSequentialOnMultiFailure) throws KeeperException {
+ if (ops == null) return;
+ boolean useMulti = zkw.getConfiguration().getBoolean(HConstants.ZOOKEEPER_USEMULTI, false);
+
+ if (useMulti) {
+ List<Op> zkOps = new LinkedList<Op>();
+ for (ZKUtilOp op : ops) {
+ zkOps.add(toZooKeeperOp(zkw, op));
+ }
+ try {
+ zkw.getRecoverableZooKeeper().multi(zkOps);
+ } catch (KeeperException ke) {
+ switch (ke.code()) {
+ case NODEEXISTS:
+ case NONODE:
+ case BADVERSION:
+ case NOAUTH:
+ // if we get an exception that could be solved by running sequentially
+ // (and the client asked us to), then break out and run sequentially
+ if (runSequentialOnMultiFailure) {
+ LOG.info("On call to ZK.multi, received exception: " + ke.toString() + "."
+ + " Attempting to run operations sequentially because"
+ + " runSequentialOnMultiFailure is: " + runSequentialOnMultiFailure + ".");
+ break;
+ }
+ default:
+ throw ke;
+ }
+ } catch (InterruptedException ie) {
+ zkw.interruptedException(ie);
+ }
+ }
+
+ // run sequentially
+ for (ZKUtilOp op : ops) {
+ if (op instanceof CreateAndFailSilent) {
+ createAndFailSilent(zkw, (CreateAndFailSilent)op);
+ } else if (op instanceof DeleteNodeFailSilent) {
+ deleteNodeFailSilent(zkw, (DeleteNodeFailSilent)op);
+ } else if (op instanceof SetData) {
+ setData(zkw, (SetData)op);
+ } else {
+ throw new UnsupportedOperationException("Unexpected ZKUtilOp type: "
+ + op.getClass().getName());
+ }
+ }
+ }
+
//
// ZooKeeper cluster information
//
Modified: hbase/branches/0.94/src/main/resources/hbase-default.xml
URL: http://svn.apache.org/viewvc/hbase/branches/0.94/src/main/resources/hbase-default.xml?rev=1423616&r1=1423615&r2=1423616&view=diff
==============================================================================
--- hbase/branches/0.94/src/main/resources/hbase-default.xml (original)
+++ hbase/branches/0.94/src/main/resources/hbase-default.xml Tue Dec 18 20:13:53 2012
@@ -690,6 +690,17 @@
for more information.
</description>
</property>
+ <property>
+ <name>hbase.zookeeper.useMulti</name>
+ <value>false</value>
+ <description>Instructs HBase to make use of ZooKeeper's multi-update functionality.
+ This allows certain ZooKeeper operations to complete more quickly and prevents some issues
+ with rare ZooKeeper failure scenarios (see the release note of HBASE-6710 for an example).
+ IMPORTANT: only set this to true if all ZooKeeper servers in the cluster are on version 3.4+
+ and will not be downgraded. ZooKeeper versions before 3.4 do not support multi-update and will
+ not fail gracefully if multi-update is invoked (see ZOOKEEPER-1495).
+ </description>
+ </property>
<!-- End of properties used to generate ZooKeeper host:port quorum list. -->
<!--
Modified: hbase/branches/0.94/src/test/java/org/apache/hadoop/hbase/zookeeper/TestZKTable.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.94/src/test/java/org/apache/hadoop/hbase/zookeeper/TestZKTable.java?rev=1423616&r1=1423615&r2=1423616&view=diff
==============================================================================
--- hbase/branches/0.94/src/test/java/org/apache/hadoop/hbase/zookeeper/TestZKTable.java (original)
+++ hbase/branches/0.94/src/test/java/org/apache/hadoop/hbase/zookeeper/TestZKTable.java Tue Dec 18 20:13:53 2012
@@ -27,6 +27,7 @@ import java.io.IOException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.*;
import org.apache.hadoop.hbase.zookeeper.ZKTable.TableState;
import org.apache.zookeeper.KeeperException;
@@ -110,14 +111,9 @@ public class TestZKTable {
assertFalse(zkt.isTablePresent(name));
}
- /**
- * Test that ZK table writes table state in formats expected by 0.92 and 0.94 clients
- */
- @Test
- public void test9294Compatibility() throws Exception {
- final String tableName = "test9294Compatibility";
-
- ZooKeeperWatcher zkw = new ZooKeeperWatcher(TEST_UTIL.getConfiguration(),
+ private void runTest9294CompatibilityTest(String tableName, Configuration conf)
+ throws Exception {
+ ZooKeeperWatcher zkw = new ZooKeeperWatcher(conf,
tableName, abortable, true);
ZKTable zkt = new ZKTable(zkw);
zkt.setEnabledTable(tableName);
@@ -129,6 +125,22 @@ public class TestZKTable {
}
/**
+ * Test that ZK table writes table state in formats expected by 0.92 and 0.94 clients
+ */
+ @Test
+ public void test9294Compatibility() throws Exception {
+ // without useMulti
+ String tableName = "test9294Compatibility";
+ runTest9294CompatibilityTest(tableName, TEST_UTIL.getConfiguration());
+
+ // with useMulti
+ tableName = "test9294CompatibilityWithMulti";
+ Configuration conf = HBaseConfiguration.create(TEST_UTIL.getConfiguration());
+ conf.setBoolean(HConstants.ZOOKEEPER_USEMULTI, true);
+ runTest9294CompatibilityTest(tableName, conf);
+ }
+
+ /**
* RecoverableZookeeper that throws a KeeperException after throwExceptionInNumOperations
*/
class ThrowingRecoverableZookeeper extends RecoverableZooKeeper {
@@ -170,14 +182,17 @@ public class TestZKTable {
* Because two ZooKeeper nodes are written for each table state transition
* {@link ZooKeeperWatcher#masterTableZNode} and {@link ZooKeeperWatcher#masterTableZNode92}
* it is possible that we fail in between the two operations and are left with
- * inconsistent state. Check that we can get back to a consistent state by
- * retrying the operation.
+ * inconsistent state (when hbase.zookeeper.useMulti is false).
+ * Check that we can get back to a consistent state by retrying the operation.
*/
@Test
public void testDisableTableRetry() throws Exception {
final String tableName = "testDisableTableRetry";
- ZooKeeperWatcher zkw = new ZooKeeperWatcher(TEST_UTIL.getConfiguration(),
+ Configuration conf = TEST_UTIL.getConfiguration();
+ // test only relevant if useMulti is false
+ conf.setBoolean(HConstants.ZOOKEEPER_USEMULTI, false);
+ ZooKeeperWatcher zkw = new ZooKeeperWatcher(conf,
tableName, abortable, true);
ThrowingRecoverableZookeeper throwing = new ThrowingRecoverableZookeeper(zkw);
ZooKeeperWatcher spyZookeeperWatcher = Mockito.spy(zkw);
@@ -211,7 +226,10 @@ public class TestZKTable {
public void testEnableTableRetry() throws Exception {
final String tableName = "testEnableTableRetry";
- ZooKeeperWatcher zkw = new ZooKeeperWatcher(TEST_UTIL.getConfiguration(),
+ Configuration conf = TEST_UTIL.getConfiguration();
+ // test only relevant if useMulti is false
+ conf.setBoolean(HConstants.ZOOKEEPER_USEMULTI, false);
+ ZooKeeperWatcher zkw = new ZooKeeperWatcher(conf,
tableName, abortable, true);
ThrowingRecoverableZookeeper throwing = new ThrowingRecoverableZookeeper(zkw);
ZooKeeperWatcher spyZookeeperWatcher = Mockito.spy(zkw);
@@ -245,7 +263,10 @@ public class TestZKTable {
public void testDeleteTableRetry() throws Exception {
final String tableName = "testEnableTableRetry";
- ZooKeeperWatcher zkw = new ZooKeeperWatcher(TEST_UTIL.getConfiguration(),
+ Configuration conf = TEST_UTIL.getConfiguration();
+ // test only relevant if useMulti is false
+ conf.setBoolean(HConstants.ZOOKEEPER_USEMULTI, false);
+ ZooKeeperWatcher zkw = new ZooKeeperWatcher(conf,
tableName, abortable, true);
ThrowingRecoverableZookeeper throwing = new ThrowingRecoverableZookeeper(zkw);
ZooKeeperWatcher spyZookeeperWatcher = Mockito.spy(zkw);
Modified: hbase/branches/0.94/src/test/java/org/apache/hadoop/hbase/zookeeper/TestZKTableReadOnly.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.94/src/test/java/org/apache/hadoop/hbase/zookeeper/TestZKTableReadOnly.java?rev=1423616&r1=1423615&r2=1423616&view=diff
==============================================================================
--- hbase/branches/0.94/src/test/java/org/apache/hadoop/hbase/zookeeper/TestZKTableReadOnly.java (original)
+++ hbase/branches/0.94/src/test/java/org/apache/hadoop/hbase/zookeeper/TestZKTableReadOnly.java Tue Dec 18 20:13:53 2012
@@ -68,33 +68,53 @@ public class TestZKTableReadOnly {
return ZKTableReadOnly.isEnabledTable(zkw, tableName);
}
+ private void runClientCompatiblityWith92ZNodeTest(String tableName, Configuration conf)
+ throws Exception {
+ ZooKeeperWatcher zkw = new ZooKeeperWatcher(conf,
+ tableName, abortable, true);
+ assertTrue(enableAndCheckEnabled(zkw, tableName));
+ }
/**
- * Test that client ZK reader can handle the 0.92 table znode format.
+ * Test that client ZK reader can handle the 0.92 table format znode.
*/
@Test
public void testClientCompatibilityWith92ZNode() throws Exception {
- final String tableName = "testClientCompatibilityWith92ZNode";
-
+ // test without useMulti
+ String tableName = "testClientCompatibilityWith92ZNode";
// Set the client to read from the 0.92 table znode format
Configuration conf = HBaseConfiguration.create(TEST_UTIL.getConfiguration());
String znode92 = conf.get("zookeeper.znode.masterTableEnableDisable92", "table92");
conf.set("zookeeper.znode.clientTableEnableDisable", znode92);
+ runClientCompatiblityWith92ZNodeTest(tableName, conf);
- ZooKeeperWatcher zkw = new ZooKeeperWatcher(conf,
+ // test with useMulti
+ tableName = "testClientCompatibilityWith92ZNodeUseMulti";
+ conf.setBoolean(HConstants.ZOOKEEPER_USEMULTI, true);
+ runClientCompatiblityWith92ZNodeTest(tableName, conf);
+ }
+
+ private void runClientCompatibilityWith94ZNodeTest(String tableName, Configuration conf)
+ throws Exception {
+ ZooKeeperWatcher zkw = new ZooKeeperWatcher(TEST_UTIL.getConfiguration(),
tableName, abortable, true);
assertTrue(enableAndCheckEnabled(zkw, tableName));
}
/**
- * Test that client ZK reader can handle the current (0.94) table format znode
+ * Test that client ZK reader can handle the current (0.94) table format znode.
*/
@Test
public void testClientCompatibilityWith94ZNode() throws Exception {
- final String tableName = "testClientCompatibilityWith94ZNode";
+ String tableName = "testClientCompatibilityWith94ZNode";
- ZooKeeperWatcher zkw = new ZooKeeperWatcher(TEST_UTIL.getConfiguration(),
- tableName, abortable, true);
- assertTrue(enableAndCheckEnabled(zkw, tableName));
+ // without useMulti
+ runClientCompatibilityWith94ZNodeTest(tableName, TEST_UTIL.getConfiguration());
+
+ // with useMulti
+ tableName = "testClientCompatiblityWith94ZNodeUseMulti";
+ Configuration conf = HBaseConfiguration.create(TEST_UTIL.getConfiguration());
+ conf.setBoolean(HConstants.ZOOKEEPER_USEMULTI, true);
+ runClientCompatibilityWith94ZNodeTest(tableName, conf);
}
@org.junit.Rule