Commit 9e097b5e authored by Flavio Paiva Junqueira's avatar Flavio Paiva Junqueira
Browse files

ZOOKEEPER-1858. JMX checks - potential race conditions while stopping and...

ZOOKEEPER-1858. JMX checks - potential race conditions while stopping and starting server (Rakesh R via fpj)



git-svn-id: https://svn.apache.org/repos/asf/zookeeper/branches/branch-3.4@1561069 13f79535-47bb-0310-9956-ffa450edef68
parent 1de1bdc3
......@@ -227,6 +227,9 @@ BUGFIXES:
ZOOKEEPER-1837. Fix JMXEnv checks (potential race conditions)
(Germán Blanco via fpj)
ZOOKEEPER-1858. JMX checks - potential race conditions while stopping
and starting server (Rakesh R via fpj)
IMPROVEMENTS:
ZOOKEEPER-1564. Allow JUnit test build with IBM Java
......
......@@ -27,15 +27,20 @@ import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import junit.framework.TestCase;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.PortAssignment;
......@@ -188,7 +193,7 @@ public abstract class ClientBase extends ZKTestCase {
}
if (allClients != null) {
allClients.add(zk);
JMXEnv.ensureAll("0x" + Long.toHexString(zk.getSessionId()));
JMXEnv.ensureAll(getHexSessionId(zk.getSessionId()));
} else {
// test done - close the zk, not needed
zk.close();
......@@ -439,8 +444,46 @@ public abstract class ClientBase extends ZKTestCase {
serverFactory = createNewServerInstance(serverFactory, hostPort,
maxCnxns);
startServerInstance(tmpDir, serverFactory, hostPort);
// ensure that only server and data bean are registered
JMXEnv.ensureOnly("InMemoryDataTree", "StandaloneServer_port");
// ensure that server and data bean are registered
Set<ObjectName> children = JMXEnv.ensureParent("InMemoryDataTree",
"StandaloneServer_port");
// Remove beans which are related to zk client sessions. Strong
// assertions cannot be done for these client sessions because
// registeration of these beans with server will happen only on their
// respective reconnection interval
verifyUnexpectedBeans(children);
}
private void verifyUnexpectedBeans(Set<ObjectName> children) {
if (allClients != null) {
for (ZooKeeper zkc : allClients) {
Iterator<ObjectName> childItr = children.iterator();
while (childItr.hasNext()) {
ObjectName clientBean = childItr.next();
if (clientBean.toString().contains(
getHexSessionId(zkc.getSessionId()))) {
LOG.info("found name:" + zkc.getSessionId()
+ " client bean:" + clientBean.toString());
childItr.remove();
}
}
}
}
for (ObjectName bean : children) {
LOG.info("unexpected:" + bean.toString());
}
TestCase.assertEquals("Unexpected bean exists!", 0, children.size());
}
/**
* Returns a string representation of the given long value session id
*
* @param sessionId
* long value of session id
* @return string representation of session id
*/
protected static String getHexSessionId(long sessionId) {
return "0x" + Long.toHexString(sessionId);
}
protected void stopServer() throws Exception {
......
......@@ -55,7 +55,7 @@ public class FourLetterWordsQuorumTest extends QuorumBase {
verify(hp, "cons", "queued");
TestableZooKeeper zk = createClient(hp);
String sid = "0x" + Long.toHexString(zk.getSessionId());
String sid = getHexSessionId(zk.getSessionId());
verify(hp, "stat", "queued");
verify(hp, "srvr", "Outstanding");
......
......@@ -57,7 +57,7 @@ public class FourLetterWordsTest extends ClientBase {
verify("cons", "queued");
TestableZooKeeper zk = createClient();
String sid = "0x" + Long.toHexString(zk.getSessionId());
String sid = getHexSessionId(zk.getSessionId());
verify("stat", "queued");
verify("srvr", "Outstanding");
......
......@@ -204,4 +204,70 @@ public class JMXEnv {
}
}
/**
* Ensure that the specified parent names are registered. Note that these
* are components of the name. It waits in a loop up to 60 seconds before
* failing if there is a mismatch. This will return the beans which are not
* matched.
*
* {@link https://issues.apache.org/jira/browse/ZOOKEEPER-1858}
*
* @param expectedNames
* - expected beans
* @return the beans which are not matched with the given expected names
*
* @throws IOException
* @throws InterruptedException
*
*/
public static Set<ObjectName> ensureParent(String... expectedNames)
throws IOException, InterruptedException {
LOG.info("ensureParent:" + Arrays.toString(expectedNames));
Set<ObjectName> beans;
int nTry = 0;
Set<ObjectName> found = new HashSet<ObjectName>();
do {
if (nTry++ > 0) {
Thread.sleep(500);
}
try {
beans = conn().queryNames(
new ObjectName(CommonNames.DOMAIN + ":*"), null);
} catch (MalformedObjectNameException e) {
throw new RuntimeException(e);
}
found.clear();
for (String name : expectedNames) {
LOG.info("expect:" + name);
for (ObjectName bean : beans) {
// check the existence of name in bean
if (compare(bean.toString(), name)) {
LOG.info("found:" + name + " " + bean);
found.add(bean);
break;
}
}
beans.removeAll(found);
}
} while (expectedNames.length != found.size() && nTry < 120);
TestCase.assertEquals("expected " + Arrays.toString(expectedNames),
expectedNames.length, found.size());
return beans;
}
/**
* Comparing that the given name exists in the bean. For component beans,
* the component name will be present at the end of the bean name
*
* For example 'StandaloneServer' will present in the bean name like
* 'org.apache.ZooKeeperService:name0=StandaloneServer_port-1'
*/
private static boolean compare(String bean, String name) {
String[] names = bean.split("=");
if (names.length > 0 && names[names.length - 1].contains(name)) {
return true;
}
return false;
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment