|
@@ -21,6 +21,8 @@ package org.apache.zookeeper.test;
|
|
|
import java.io.File;
|
|
|
import java.util.List;
|
|
|
|
|
|
+import org.slf4j.Logger;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
import org.apache.zookeeper.CreateMode;
|
|
|
import org.apache.zookeeper.PortAssignment;
|
|
|
import org.apache.zookeeper.WatchedEvent;
|
|
@@ -37,11 +39,19 @@ import org.apache.zookeeper.server.persistence.TxnLog.TxnIterator;
|
|
|
import org.apache.zookeeper.txn.TxnHeader;
|
|
|
import org.junit.Assert;
|
|
|
import org.junit.Test;
|
|
|
+import org.apache.zookeeper.server.DataTree;
|
|
|
+import org.apache.zookeeper.server.DataNode;
|
|
|
+import org.apache.zookeeper.txn.CreateTxn;
|
|
|
+import org.apache.zookeeper.txn.DeleteTxn;
|
|
|
+import org.apache.zookeeper.txn.TxnHeader;
|
|
|
+import org.apache.zookeeper.ZooDefs.OpCode;
|
|
|
+import org.apache.jute.Record;
|
|
|
|
|
|
public class LoadFromLogTest extends ZKTestCase implements Watcher {
|
|
|
private static String HOSTPORT = "127.0.0.1:" + PortAssignment.unique();
|
|
|
private static final int CONNECTION_TIMEOUT = 3000;
|
|
|
private static final int NUM_MESSAGES = 300;
|
|
|
+ protected static final Logger LOG = LoggerFactory.getLogger(LoadFromLogTest.class);
|
|
|
|
|
|
// setting up the quorum has a transaction overhead for creating and closing the session
|
|
|
private static final int TRANSACTION_OVERHEAD = 2;
|
|
@@ -104,4 +114,75 @@ public class LoadFromLogTest extends ZKTestCase implements Watcher {
|
|
|
// do nothing
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * For ZOOKEEPER-1046. Verify if cversion and pzxid if incremented
|
|
|
+ * after create/delete failure during restore.
|
|
|
+ */
|
|
|
+ @Test
|
|
|
+ public void testTxnFailure() throws Exception {
|
|
|
+ long count = 1;
|
|
|
+ File tmpDir = ClientBase.createTmpDir();
|
|
|
+ FileTxnSnapLog logFile = new FileTxnSnapLog(tmpDir, tmpDir);
|
|
|
+ DataTree dt = new DataTree();
|
|
|
+ dt.createNode("/test", new byte[0], null, 0, 1, 1);
|
|
|
+ for (count = 1; count <= 3; count++) {
|
|
|
+ dt.createNode("/test/" + count, new byte[0], null, 0, count,
|
|
|
+ System.currentTimeMillis());
|
|
|
+ }
|
|
|
+ DataNode zk = dt.getNode("/test");
|
|
|
+
|
|
|
+ // Make create to fail, then verify cversion.
|
|
|
+ LOG.info("Attempting to create " + "/test/" + (count - 1));
|
|
|
+ doOp(logFile, OpCode.create, "/test/" + (count - 1), dt, zk);
|
|
|
+
|
|
|
+ // Make delete fo fail, then verify cversion.
|
|
|
+ LOG.info("Attempting to delete " + "/test/" + (count + 1));
|
|
|
+ doOp(logFile, OpCode.delete, "/test/" + (count + 1), dt, zk);
|
|
|
+ }
|
|
|
+ /*
|
|
|
+ * Does create/delete depending on the type and verifies
|
|
|
+ * if cversion before the operation is 1 less than cversion afer.
|
|
|
+ */
|
|
|
+ private void doOp(FileTxnSnapLog logFile, int type, String path,
|
|
|
+ DataTree dt, DataNode parent) throws Exception {
|
|
|
+ int lastSlash = path.lastIndexOf('/');
|
|
|
+ String parentName = path.substring(0, lastSlash);
|
|
|
+
|
|
|
+ long prevCversion = parent.stat.getCversion();
|
|
|
+ long prevPzxid = parent.stat.getPzxid();
|
|
|
+ List<String> child = dt.getChildren(parentName, null, null);
|
|
|
+ String childStr = "";
|
|
|
+ for (String s : child) {
|
|
|
+ childStr += s + " ";
|
|
|
+ }
|
|
|
+ LOG.info("Children: " + childStr + " for " + parentName);
|
|
|
+ LOG.info("(cverions, pzxid): " + prevCversion + ", " + prevPzxid);
|
|
|
+
|
|
|
+ Record txn = null;
|
|
|
+ TxnHeader txnHeader = null;
|
|
|
+ if (type == OpCode.delete) {
|
|
|
+ txn = new DeleteTxn(path);
|
|
|
+ txnHeader = new TxnHeader(0xabcd, 0x123, prevPzxid + 1,
|
|
|
+ System.currentTimeMillis(), OpCode.delete);
|
|
|
+ } else if (type == OpCode.create) {
|
|
|
+ txnHeader = new TxnHeader(0xabcd, 0x123, prevPzxid + 1,
|
|
|
+ System.currentTimeMillis(), OpCode.create);
|
|
|
+ txn = new CreateTxn(path, new byte[0], null, false);
|
|
|
+ }
|
|
|
+ logFile.processTransaction(txnHeader, dt, null, txn);
|
|
|
+
|
|
|
+ long newCversion = parent.stat.getCversion();
|
|
|
+ long newPzxid = parent.stat.getPzxid();
|
|
|
+ child = dt.getChildren(parentName, null, null);
|
|
|
+ childStr = "";
|
|
|
+ for (String s : child) {
|
|
|
+ childStr += s + " ";
|
|
|
+ }
|
|
|
+ LOG.info("Children: " + childStr + " for " + parentName);
|
|
|
+ LOG.info("(cverions, pzxid): " +newCversion + ", " + newPzxid);
|
|
|
+ Assert.assertTrue("<cversion, pzxid> verification failed. Expected: <" +
|
|
|
+ (prevCversion + 1) + ", " + (prevPzxid + 1) + ">, found: <" +
|
|
|
+ newCversion + ", " + newPzxid + ">",
|
|
|
+ (newCversion == prevCversion + 1 && newPzxid == prevPzxid + 1));
|
|
|
+ }
|
|
|
}
|