diff --git a/hadoop-common-project/hadoop-common/CHANGES.txt b/hadoop-common-project/hadoop-common/CHANGES.txt
index 00715abda9e..1ff04f8d7cb 100644
--- a/hadoop-common-project/hadoop-common/CHANGES.txt
+++ b/hadoop-common-project/hadoop-common/CHANGES.txt
@@ -223,6 +223,9 @@ Release 0.23.3 - UNRELEASED
HADOOP-8193. Refactor FailoverController/HAAdmin code to add an abstract
class for "target" services. (todd)
+ HADOOP-8212. Improve ActiveStandbyElector's behavior when session expires
+ (todd)
+
OPTIMIZATIONS
BUG FIXES
diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/ActiveStandbyElector.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/ActiveStandbyElector.java
index 56cba81139e..b77187b7939 100644
--- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/ActiveStandbyElector.java
+++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ha/ActiveStandbyElector.java
@@ -21,6 +21,8 @@ package org.apache.hadoop.ha;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -32,6 +34,7 @@ import org.apache.zookeeper.data.ACL;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.WatchedEvent;
+import org.apache.zookeeper.Watcher.Event;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.AsyncCallback.*;
@@ -60,8 +63,7 @@ import com.google.common.base.Preconditions;
*/
@InterfaceAudience.Private
@InterfaceStability.Evolving
-public class ActiveStandbyElector implements Watcher, StringCallback,
- StatCallback {
+public class ActiveStandbyElector implements StatCallback, StringCallback {
/**
* Callback interface to interact with the ActiveStandbyElector object.
@@ -156,6 +158,9 @@ public class ActiveStandbyElector implements Watcher, StringCallback,
private final String zkBreadCrumbPath;
private final String znodeWorkingDir;
+ private Lock sessionReestablishLockForTests = new ReentrantLock();
+ private boolean wantToBeInElection;
+
/**
* Create a new ActiveStandbyElector object
* The elector is created by providing to it the Zookeeper configuration, the
@@ -274,6 +279,8 @@ public class ActiveStandbyElector implements Watcher, StringCallback,
}
}
}
+
+ LOG.info("Successfully created " + znodeWorkingDir + " in ZK.");
}
/**
@@ -290,13 +297,14 @@ public class ActiveStandbyElector implements Watcher, StringCallback,
* if a failover occurs due to dropping out of the election.
*/
public synchronized void quitElection(boolean needFence) {
- LOG.debug("Yielding from election");
+ LOG.info("Yielding from election");
if (!needFence && state == State.ACTIVE) {
// If active is gracefully going back to standby mode, remove
// our permanent znode so no one fences us.
tryDeleteOwnBreadCrumbNode();
}
reset();
+ wantToBeInElection = false;
}
/**
@@ -343,13 +351,9 @@ public class ActiveStandbyElector implements Watcher, StringCallback,
@Override
public synchronized void processResult(int rc, String path, Object ctx,
String name) {
+ if (isStaleClient(ctx)) return;
LOG.debug("CreateNode result: " + rc + " for path: " + path
+ " connectionState: " + zkConnectionState);
- if (zkClient == null) {
- // zkClient is nulled before closing the connection
- // this is the callback with session expired after we closed the session
- return;
- }
Code code = Code.get(rc);
if (isSuccess(code)) {
@@ -386,6 +390,10 @@ public class ActiveStandbyElector implements Watcher, StringCallback,
}
errorMessage = errorMessage
+ ". Not retrying further znode create connection errors.";
+ } else if (isSessionExpired(code)) {
+ // This isn't fatal - the client Watcher will re-join the election
+ LOG.warn("Lock acquisition failed because session was lost");
+ return;
}
fatalError(errorMessage);
@@ -397,13 +405,9 @@ public class ActiveStandbyElector implements Watcher, StringCallback,
@Override
public synchronized void processResult(int rc, String path, Object ctx,
Stat stat) {
+ if (isStaleClient(ctx)) return;
LOG.debug("StatNode result: " + rc + " for path: " + path
+ " connectionState: " + zkConnectionState);
- if (zkClient == null) {
- // zkClient is nulled before closing the connection
- // this is the callback with session expired after we closed the session
- return;
- }
Code code = Code.get(rc);
if (isSuccess(code)) {
@@ -447,22 +451,18 @@ public class ActiveStandbyElector implements Watcher, StringCallback,
/**
* interface implementation of Zookeeper watch events (connection and node)
*/
- @Override
- public synchronized void process(WatchedEvent event) {
+ synchronized void processWatchEvent(ZooKeeper zk, WatchedEvent event) {
Event.EventType eventType = event.getType();
+ if (isStaleClient(zk)) return;
LOG.debug("Watcher event type: " + eventType + " with state:"
+ event.getState() + " for path:" + event.getPath()
+ " connectionState: " + zkConnectionState);
- if (zkClient == null) {
- // zkClient is nulled before closing the connection
- // this is the callback with session expired after we closed the session
- return;
- }
if (eventType == Event.EventType.None) {
// the connection state has changed
switch (event.getState()) {
case SyncConnected:
+ LOG.info("Session connected.");
// if the listener was asked to move to safe state then it needs to
// be undone
ConnectionState prevConnectionState = zkConnectionState;
@@ -472,6 +472,8 @@ public class ActiveStandbyElector implements Watcher, StringCallback,
}
break;
case Disconnected:
+ LOG.info("Session disconnected. Entering neutral mode...");
+
// ask the app to move to safe state because zookeeper connection
// is not active and we dont know our state
zkConnectionState = ConnectionState.DISCONNECTED;
@@ -480,6 +482,7 @@ public class ActiveStandbyElector implements Watcher, StringCallback,
case Expired:
// the connection got terminated because of session timeout
// call listener to reconnect
+ LOG.info("Session expired. Entering neutral mode and rejoining...");
enterNeutralMode();
reJoinElection();
break;
@@ -527,7 +530,9 @@ public class ActiveStandbyElector implements Watcher, StringCallback,
* @throws IOException
*/
protected synchronized ZooKeeper getNewZooKeeper() throws IOException {
- return new ZooKeeper(zkHostPort, zkSessionTimeout, this);
+ ZooKeeper zk = new ZooKeeper(zkHostPort, zkSessionTimeout, null);
+ zk.register(new WatcherWithClientRef(zk));
+ return zk;
}
private void fatalError(String errorMessage) {
@@ -550,13 +555,42 @@ public class ActiveStandbyElector implements Watcher, StringCallback,
}
createRetryCount = 0;
+ wantToBeInElection = true;
createLockNodeAsync();
}
private void reJoinElection() {
- LOG.debug("Trying to re-establish ZK session");
- terminateConnection();
- joinElectionInternal();
+ LOG.info("Trying to re-establish ZK session");
+
+ // Some of the test cases rely on expiring the ZK sessions and
+ // ensuring that the other node takes over. But, there's a race
+ // where the original lease holder could reconnect faster than the other
+ // thread manages to take the lock itself. This lock allows the
+ // tests to block the reconnection. It's a shame that this leaked
+ // into non-test code, but the lock is only acquired here so will never
+ // be contended.
+ sessionReestablishLockForTests.lock();
+ try {
+ terminateConnection();
+ joinElectionInternal();
+ } finally {
+ sessionReestablishLockForTests.unlock();
+ }
+ }
+
+ @VisibleForTesting
+ void preventSessionReestablishmentForTests() {
+ sessionReestablishLockForTests.lock();
+ }
+
+ @VisibleForTesting
+ void allowSessionReestablishmentForTests() {
+ sessionReestablishLockForTests.unlock();
+ }
+
+ @VisibleForTesting
+ long getZKSessionIdForTests() {
+ return zkClient.getSessionId();
}
private boolean reEstablishSession() {
@@ -605,6 +639,7 @@ public class ActiveStandbyElector implements Watcher, StringCallback,
}
private void becomeActive() {
+ assert wantToBeInElection;
if (state != State.ACTIVE) {
try {
Stat oldBreadcrumbStat = fenceOldActive();
@@ -727,12 +762,14 @@ public class ActiveStandbyElector implements Watcher, StringCallback,
}
private void createLockNodeAsync() {
- zkClient.create(zkLockFilePath, appData, zkAcl, CreateMode.EPHEMERAL, this,
- null);
+ zkClient.create(zkLockFilePath, appData, zkAcl, CreateMode.EPHEMERAL,
+ this, zkClient);
}
private void monitorLockNodeAsync() {
- zkClient.exists(zkLockFilePath, this, this, null);
+ zkClient.exists(zkLockFilePath,
+ new WatcherWithClientRef(zkClient), this,
+ zkClient);
}
private String createWithRetries(final String path, final byte[] data,
@@ -778,10 +815,47 @@ public class ActiveStandbyElector implements Watcher, StringCallback,
}
}
}
-
+
private interface ZKAction {
T run() throws KeeperException, InterruptedException;
}
+
+ /**
+ * The callbacks and watchers pass a reference to the ZK client
+ * which made the original call. We don't want to take action
+ * based on any callbacks from prior clients after we quit
+ * the election.
+ * @param ctx the ZK client passed into the watcher
+ * @return true if it matches the current client
+ */
+ private synchronized boolean isStaleClient(Object ctx) {
+ Preconditions.checkNotNull(ctx);
+ if (zkClient != (ZooKeeper)ctx) {
+ LOG.warn("Ignoring stale result from old client with sessionId " +
+ String.format("0x%08x", ((ZooKeeper)ctx).getSessionId()));
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Watcher implementation which keeps a reference around to the
+ * original ZK connection, and passes it back along with any
+ * events.
+ */
+ private final class WatcherWithClientRef implements Watcher {
+ private final ZooKeeper zk;
+
+ private WatcherWithClientRef(ZooKeeper zk) {
+ this.zk = zk;
+ }
+
+ @Override
+ public void process(WatchedEvent event) {
+ ActiveStandbyElector.this.processWatchEvent(
+ zk, event);
+ }
+ }
private static boolean isSuccess(Code code) {
return (code == Code.OK);
@@ -794,6 +868,10 @@ public class ActiveStandbyElector implements Watcher, StringCallback,
private static boolean isNodeDoesNotExist(Code code) {
return (code == Code.NONODE);
}
+
+ private static boolean isSessionExpired(Code code) {
+ return (code == Code.SESSIONEXPIRED);
+ }
private static boolean shouldRetry(Code code) {
switch (code) {
diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ha/ActiveStandbyElectorTestUtil.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ha/ActiveStandbyElectorTestUtil.java
new file mode 100644
index 00000000000..e24cf87aa83
--- /dev/null
+++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ha/ActiveStandbyElectorTestUtil.java
@@ -0,0 +1,53 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.ha;
+
+import java.util.Arrays;
+
+import org.apache.hadoop.test.MultithreadedTestUtil.TestContext;
+import org.apache.zookeeper.KeeperException.NoNodeException;
+import org.apache.zookeeper.data.Stat;
+import org.apache.zookeeper.server.ZooKeeperServer;
+
+public abstract class ActiveStandbyElectorTestUtil {
+
+ public static void waitForActiveLockData(TestContext ctx,
+ ZooKeeperServer zks, String parentDir, byte[] activeData)
+ throws Exception {
+ while (true) {
+ if (ctx != null) {
+ ctx.checkException();
+ }
+ try {
+ Stat stat = new Stat();
+ byte[] data = zks.getZKDatabase().getData(
+ parentDir + "/" +
+ ActiveStandbyElector.LOCK_FILENAME, stat, null);
+ if (activeData != null &&
+ Arrays.equals(activeData, data)) {
+ return;
+ }
+ } catch (NoNodeException nne) {
+ if (activeData == null) {
+ return;
+ }
+ }
+ Thread.sleep(50);
+ }
+ }
+}
diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ha/TestActiveStandbyElector.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ha/TestActiveStandbyElector.java
index f3b551ad834..b9786aea36a 100644
--- a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ha/TestActiveStandbyElector.java
+++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ha/TestActiveStandbyElector.java
@@ -26,6 +26,7 @@ import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.KeeperException.Code;
import org.apache.zookeeper.WatchedEvent;
+import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.Watcher.Event;
import org.apache.zookeeper.data.ACL;
@@ -111,7 +112,7 @@ public class TestActiveStandbyElector {
public void testJoinElection() {
elector.joinElection(data);
Mockito.verify(mockZK, Mockito.times(1)).create(ZK_LOCK_NAME, data,
- Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL, elector, null);
+ Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL, elector, mockZK);
}
/**
@@ -123,7 +124,7 @@ public class TestActiveStandbyElector {
mockNoPriorActive();
elector.joinElection(data);
- elector.processResult(Code.OK.intValue(), ZK_LOCK_NAME, null,
+ elector.processResult(Code.OK.intValue(), ZK_LOCK_NAME, mockZK,
ZK_LOCK_NAME);
Mockito.verify(mockApp, Mockito.times(1)).becomeActive();
verifyExistCall(1);
@@ -133,14 +134,14 @@ public class TestActiveStandbyElector {
Stat stat = new Stat();
stat.setEphemeralOwner(1L);
Mockito.when(mockZK.getSessionId()).thenReturn(1L);
- elector.processResult(Code.OK.intValue(), ZK_LOCK_NAME, null, stat);
+ elector.processResult(Code.OK.intValue(), ZK_LOCK_NAME, mockZK, stat);
// should not call neutral mode/standby/active
Mockito.verify(mockApp, Mockito.times(0)).enterNeutralMode();
Mockito.verify(mockApp, Mockito.times(0)).becomeStandby();
Mockito.verify(mockApp, Mockito.times(1)).becomeActive();
// another joinElection not called.
Mockito.verify(mockZK, Mockito.times(1)).create(ZK_LOCK_NAME, data,
- Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL, elector, null);
+ Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL, elector, mockZK);
// no new monitor called
verifyExistCall(1);
}
@@ -155,7 +156,7 @@ public class TestActiveStandbyElector {
mockPriorActive(fakeOldActiveData);
elector.joinElection(data);
- elector.processResult(Code.OK.intValue(), ZK_LOCK_NAME, null,
+ elector.processResult(Code.OK.intValue(), ZK_LOCK_NAME, mockZK,
ZK_LOCK_NAME);
// Application fences active.
Mockito.verify(mockApp, Mockito.times(1)).fenceOldActive(
@@ -173,7 +174,7 @@ public class TestActiveStandbyElector {
public void testQuitElectionRemovesBreadcrumbNode() throws Exception {
mockNoPriorActive();
elector.joinElection(data);
- elector.processResult(Code.OK.intValue(), ZK_LOCK_NAME, null,
+ elector.processResult(Code.OK.intValue(), ZK_LOCK_NAME, mockZK,
ZK_LOCK_NAME);
// Writes its own active info
Mockito.verify(mockZK, Mockito.times(1)).create(
@@ -197,7 +198,7 @@ public class TestActiveStandbyElector {
public void testCreateNodeResultBecomeStandby() {
elector.joinElection(data);
- elector.processResult(Code.NODEEXISTS.intValue(), ZK_LOCK_NAME, null,
+ elector.processResult(Code.NODEEXISTS.intValue(), ZK_LOCK_NAME, mockZK,
ZK_LOCK_NAME);
Mockito.verify(mockApp, Mockito.times(1)).becomeStandby();
verifyExistCall(1);
@@ -210,7 +211,7 @@ public class TestActiveStandbyElector {
public void testCreateNodeResultError() {
elector.joinElection(data);
- elector.processResult(Code.APIERROR.intValue(), ZK_LOCK_NAME, null,
+ elector.processResult(Code.APIERROR.intValue(), ZK_LOCK_NAME, mockZK,
ZK_LOCK_NAME);
Mockito.verify(mockApp, Mockito.times(1)).notifyFatalError(
"Received create error from Zookeeper. code:APIERROR " +
@@ -227,13 +228,13 @@ public class TestActiveStandbyElector {
elector.joinElection(data);
- elector.processResult(Code.CONNECTIONLOSS.intValue(), ZK_LOCK_NAME, null,
+ elector.processResult(Code.CONNECTIONLOSS.intValue(), ZK_LOCK_NAME, mockZK,
ZK_LOCK_NAME);
- elector.processResult(Code.CONNECTIONLOSS.intValue(), ZK_LOCK_NAME, null,
+ elector.processResult(Code.CONNECTIONLOSS.intValue(), ZK_LOCK_NAME, mockZK,
ZK_LOCK_NAME);
- elector.processResult(Code.CONNECTIONLOSS.intValue(), ZK_LOCK_NAME, null,
+ elector.processResult(Code.CONNECTIONLOSS.intValue(), ZK_LOCK_NAME, mockZK,
ZK_LOCK_NAME);
- elector.processResult(Code.CONNECTIONLOSS.intValue(), ZK_LOCK_NAME, null,
+ elector.processResult(Code.CONNECTIONLOSS.intValue(), ZK_LOCK_NAME, mockZK,
ZK_LOCK_NAME);
// 4 errors results in fatalError
Mockito
@@ -246,20 +247,20 @@ public class TestActiveStandbyElector {
elector.joinElection(data);
// recreate connection via getNewZooKeeper
Assert.assertEquals(2, count);
- elector.processResult(Code.CONNECTIONLOSS.intValue(), ZK_LOCK_NAME, null,
+ elector.processResult(Code.CONNECTIONLOSS.intValue(), ZK_LOCK_NAME, mockZK,
ZK_LOCK_NAME);
- elector.processResult(Code.NODEEXISTS.intValue(), ZK_LOCK_NAME, null,
+ elector.processResult(Code.NODEEXISTS.intValue(), ZK_LOCK_NAME, mockZK,
ZK_LOCK_NAME);
verifyExistCall(1);
Stat stat = new Stat();
stat.setEphemeralOwner(1L);
Mockito.when(mockZK.getSessionId()).thenReturn(1L);
- elector.processResult(Code.OK.intValue(), ZK_LOCK_NAME, null, stat);
+ elector.processResult(Code.OK.intValue(), ZK_LOCK_NAME, mockZK, stat);
Mockito.verify(mockApp, Mockito.times(1)).becomeActive();
verifyExistCall(1);
Mockito.verify(mockZK, Mockito.times(6)).create(ZK_LOCK_NAME, data,
- Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL, elector, null);
+ Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL, elector, mockZK);
}
/**
@@ -270,16 +271,16 @@ public class TestActiveStandbyElector {
public void testCreateNodeResultRetryBecomeStandby() {
elector.joinElection(data);
- elector.processResult(Code.CONNECTIONLOSS.intValue(), ZK_LOCK_NAME, null,
+ elector.processResult(Code.CONNECTIONLOSS.intValue(), ZK_LOCK_NAME, mockZK,
ZK_LOCK_NAME);
- elector.processResult(Code.NODEEXISTS.intValue(), ZK_LOCK_NAME, null,
+ elector.processResult(Code.NODEEXISTS.intValue(), ZK_LOCK_NAME, mockZK,
ZK_LOCK_NAME);
verifyExistCall(1);
Stat stat = new Stat();
stat.setEphemeralOwner(0);
Mockito.when(mockZK.getSessionId()).thenReturn(1L);
- elector.processResult(Code.OK.intValue(), ZK_LOCK_NAME, null, stat);
+ elector.processResult(Code.OK.intValue(), ZK_LOCK_NAME, mockZK, stat);
Mockito.verify(mockApp, Mockito.times(1)).becomeStandby();
verifyExistCall(1);
}
@@ -293,19 +294,19 @@ public class TestActiveStandbyElector {
public void testCreateNodeResultRetryNoNode() {
elector.joinElection(data);
- elector.processResult(Code.CONNECTIONLOSS.intValue(), ZK_LOCK_NAME, null,
+ elector.processResult(Code.CONNECTIONLOSS.intValue(), ZK_LOCK_NAME, mockZK,
ZK_LOCK_NAME);
- elector.processResult(Code.CONNECTIONLOSS.intValue(), ZK_LOCK_NAME, null,
+ elector.processResult(Code.CONNECTIONLOSS.intValue(), ZK_LOCK_NAME, mockZK,
ZK_LOCK_NAME);
- elector.processResult(Code.NODEEXISTS.intValue(), ZK_LOCK_NAME, null,
+ elector.processResult(Code.NODEEXISTS.intValue(), ZK_LOCK_NAME, mockZK,
ZK_LOCK_NAME);
verifyExistCall(1);
- elector.processResult(Code.NONODE.intValue(), ZK_LOCK_NAME, null,
+ elector.processResult(Code.NONODE.intValue(), ZK_LOCK_NAME, mockZK,
(Stat) null);
Mockito.verify(mockApp, Mockito.times(1)).enterNeutralMode();
Mockito.verify(mockZK, Mockito.times(4)).create(ZK_LOCK_NAME, data,
- Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL, elector, null);
+ Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL, elector, mockZK);
}
/**
@@ -313,13 +314,13 @@ public class TestActiveStandbyElector {
*/
@Test
public void testStatNodeRetry() {
- elector.processResult(Code.CONNECTIONLOSS.intValue(), ZK_LOCK_NAME, null,
+ elector.processResult(Code.CONNECTIONLOSS.intValue(), ZK_LOCK_NAME, mockZK,
(Stat) null);
- elector.processResult(Code.CONNECTIONLOSS.intValue(), ZK_LOCK_NAME, null,
+ elector.processResult(Code.CONNECTIONLOSS.intValue(), ZK_LOCK_NAME, mockZK,
(Stat) null);
- elector.processResult(Code.CONNECTIONLOSS.intValue(), ZK_LOCK_NAME, null,
+ elector.processResult(Code.CONNECTIONLOSS.intValue(), ZK_LOCK_NAME, mockZK,
(Stat) null);
- elector.processResult(Code.CONNECTIONLOSS.intValue(), ZK_LOCK_NAME, null,
+ elector.processResult(Code.CONNECTIONLOSS.intValue(), ZK_LOCK_NAME, mockZK,
(Stat) null);
Mockito
.verify(mockApp, Mockito.times(1))
@@ -334,7 +335,7 @@ public class TestActiveStandbyElector {
@Test
public void testStatNodeError() {
elector.processResult(Code.RUNTIMEINCONSISTENCY.intValue(), ZK_LOCK_NAME,
- null, (Stat) null);
+ mockZK, (Stat) null);
Mockito.verify(mockApp, Mockito.times(0)).enterNeutralMode();
Mockito.verify(mockApp, Mockito.times(1)).notifyFatalError(
"Received stat error from Zookeeper. code:RUNTIMEINCONSISTENCY");
@@ -354,7 +355,7 @@ public class TestActiveStandbyElector {
// first SyncConnected should not do anything
Mockito.when(mockEvent.getState()).thenReturn(
Event.KeeperState.SyncConnected);
- elector.process(mockEvent);
+ elector.processWatchEvent(mockZK, mockEvent);
Mockito.verify(mockZK, Mockito.times(0)).exists(Mockito.anyString(),
Mockito.anyBoolean(), Mockito. anyObject(),
Mockito.