You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by be...@apache.org on 2014/01/14 21:05:02 UTC

[11/15] git commit: Upgraded to ZooKeeper 3.4.5.

Upgraded to ZooKeeper 3.4.5.

In order to build Mesos with clang we need to upgrade
ZooKeeper. Unfortunately, Mesos leveraged some internal APIs of
ZooKeeper that changed so this commit required some refactorings.

Review: https://reviews.apache.org/r/16657


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/9bfbc2c3
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/9bfbc2c3
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/9bfbc2c3

Branch: refs/heads/master
Commit: 9bfbc2c3197e29e50ff8c36544fb6a8d9eafdca9
Parents: 70aeb47
Author: Benjamin Hindman <be...@gmail.com>
Authored: Sun Dec 29 22:42:19 2013 -0700
Committer: Benjamin Hindman <be...@gmail.com>
Committed: Tue Jan 14 12:00:40 2014 -0800

----------------------------------------------------------------------
 3rdparty/versions.am                |   2 +-
 3rdparty/zookeeper-3.3.4.tar.gz     | Bin 13543276 -> 0 bytes
 3rdparty/zookeeper-3.4.5.tar.gz     | Bin 0 -> 16402010 bytes
 src/Makefile.am                     |   1 +
 src/jvm/jvm.cpp                     | 106 +++++++++++++++++++++++++++-
 src/jvm/jvm.hpp                     |  82 ++++++++++++++++++++--
 src/jvm/org/apache/log4j.cpp        |   5 +-
 src/jvm/org/apache/log4j.hpp        |   5 +-
 src/jvm/org/apache/zookeeper.cpp    |  15 ++++
 src/jvm/org/apache/zookeeper.hpp    | 115 +++++++++++++++++--------------
 src/python/setup.py.in              |   2 +-
 src/tests/zookeeper.cpp             |  38 +++++++---
 src/tests/zookeeper_test_server.cpp |  53 +++++++++-----
 src/tests/zookeeper_test_server.hpp |   2 +-
 14 files changed, 328 insertions(+), 98 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/9bfbc2c3/3rdparty/versions.am
----------------------------------------------------------------------
diff --git a/3rdparty/versions.am b/3rdparty/versions.am
index 5932e1f..102d6f4 100644
--- a/3rdparty/versions.am
+++ b/3rdparty/versions.am
@@ -21,4 +21,4 @@
 
 BOTO_VERSION = 2.0b2
 DISTRIBUTE_VERSION = 0.6.26
-ZOOKEEPER_VERSION = 3.3.4
+ZOOKEEPER_VERSION = 3.4.5

http://git-wip-us.apache.org/repos/asf/mesos/blob/9bfbc2c3/3rdparty/zookeeper-3.3.4.tar.gz
----------------------------------------------------------------------
diff --git a/3rdparty/zookeeper-3.3.4.tar.gz b/3rdparty/zookeeper-3.3.4.tar.gz
deleted file mode 100644
index 09d4924..0000000
Binary files a/3rdparty/zookeeper-3.3.4.tar.gz and /dev/null differ

http://git-wip-us.apache.org/repos/asf/mesos/blob/9bfbc2c3/3rdparty/zookeeper-3.4.5.tar.gz
----------------------------------------------------------------------
diff --git a/3rdparty/zookeeper-3.4.5.tar.gz b/3rdparty/zookeeper-3.4.5.tar.gz
new file mode 100644
index 0000000..1a547fe
Binary files /dev/null and b/3rdparty/zookeeper-3.4.5.tar.gz differ

http://git-wip-us.apache.org/repos/asf/mesos/blob/9bfbc2c3/src/Makefile.am
----------------------------------------------------------------------
diff --git a/src/Makefile.am b/src/Makefile.am
index 4f04dc6..288a5cc 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -598,6 +598,7 @@ libjava_la_SOURCES =							\
 	jvm/java/net.hpp						\
 	jvm/org/apache/log4j.cpp					\
 	jvm/org/apache/log4j.hpp					\
+	jvm/org/apache/zookeeper.cpp					\
 	jvm/org/apache/zookeeper.hpp
 
 libjava_la_CPPFLAGS = $(MESOS_CPPFLAGS)

http://git-wip-us.apache.org/repos/asf/mesos/blob/9bfbc2c3/src/jvm/jvm.cpp
----------------------------------------------------------------------
diff --git a/src/jvm/jvm.cpp b/src/jvm/jvm.cpp
index 17ab12e..6eb3a34 100644
--- a/src/jvm/jvm.cpp
+++ b/src/jvm/jvm.cpp
@@ -272,14 +272,35 @@ Jvm::Method Jvm::findStaticMethod(const MethodSignature& signature)
 }
 
 
-Jvm::Field Jvm::findStaticField(const Class& clazz, const std::string& name)
+Jvm::Field Jvm::findField(
+    const Class& clazz,
+    const std::string& name,
+    const std::string& signature)
+{
+  Env env;
+
+  jfieldID id = env->GetFieldID(
+      findClass(clazz),
+      name.c_str(),
+      signature.c_str());
+
+  check(env);
+
+  return Jvm::Field(clazz, id);
+}
+
+
+Jvm::Field Jvm::findStaticField(
+    const Class& clazz,
+    const std::string& name,
+    const std::string& signature)
 {
   Env env;
 
   jfieldID id = env->GetStaticFieldID(
       findClass(clazz),
       name.c_str(),
-      clazz.signature().c_str());
+      signature.c_str());
 
   check(env);
 
@@ -300,6 +321,78 @@ jobject Jvm::invoke(const Constructor& ctor, ...)
 
 
 template <>
+void Jvm::setField<jobject>(jobject receiver, const Field& field, jobject o)
+{
+  Env env;
+  env->SetObjectField(receiver, field.id, o);
+  check(env);
+}
+
+
+template <>
+void Jvm::setField<bool>(jobject receiver, const Field& field, bool b)
+{
+  Env env;
+  env->SetBooleanField(receiver, field.id, b);
+  check(env);
+}
+
+
+template <>
+void Jvm::setField<char>(jobject receiver, const Field& field, char c)
+{
+  Env env;
+  env->SetCharField(receiver, field.id, c);
+  check(env);
+}
+
+
+template <>
+void Jvm::setField<short>(jobject receiver, const Field& field, short s)
+{
+  Env env;
+  env->SetShortField(receiver, field.id, s);
+  check(env);
+}
+
+
+template <>
+void Jvm::setField<int>(jobject receiver, const Field& field, int i)
+{
+  Env env;
+  env->SetIntField(receiver, field.id, i);
+  check(env);
+}
+
+
+template <>
+void Jvm::setField<long>(jobject receiver, const Field& field, long l)
+{
+  Env env;
+  env->SetLongField(receiver, field.id, l);
+  check(env);
+}
+
+
+template <>
+void Jvm::setField<float>(jobject receiver, const Field& field, float f)
+{
+  Env env;
+  env->SetFloatField(receiver, field.id, f);
+  check(env);
+}
+
+
+template <>
+void Jvm::setField<double>(jobject receiver, const Field& field, double d)
+{
+  Env env;
+  env->SetDoubleField(receiver, field.id, d);
+  check(env);
+}
+
+
+template <>
 jobject Jvm::getStaticField<jobject>(const Field& field)
 {
   Env env;
@@ -421,9 +514,16 @@ jclass Jvm::findClass(const Class& clazz)
 {
   Env env;
 
+  jclass jclazz = env->FindClass(clazz.name.c_str());
+
+  if (env->ExceptionCheck()) {
+    env->ExceptionDescribe();
+    LOG(FATAL) << "Failed to find class " << clazz.name;
+  }
+
   // TODO(John Sirois): Consider CHECK_NOTNULL -> return Option if
   // re-purposing this code outside of tests.
-  return CHECK_NOTNULL(env->FindClass(clazz.name.c_str()));
+  return CHECK_NOTNULL(jclazz);
 }
 
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/9bfbc2c3/src/jvm/jvm.hpp
----------------------------------------------------------------------
diff --git a/src/jvm/jvm.hpp b/src/jvm/jvm.hpp
index a3ea86a..b4dff78 100644
--- a/src/jvm/jvm.hpp
+++ b/src/jvm/jvm.hpp
@@ -234,8 +234,11 @@ public:
       : object(Jvm::get()->newGlobalRef(_object)) {}
 
     Object(const Object& that)
+      : object(NULL)
     {
-      object = Jvm::get()->newGlobalRef(that.object);
+      if (that.object != NULL) {
+        object = Jvm::get()->newGlobalRef(that.object);
+      }
     }
 
     ~Object()
@@ -249,8 +252,11 @@ public:
     {
       if (object != NULL) {
         Jvm::get()->deleteGlobalRef(object);
+        object = NULL;
+      }
+      if (that.object != NULL) {
+        object = Jvm::get()->newGlobalRef(that.object);
       }
-      object = Jvm::get()->newGlobalRef(that.object);
       return *this;
     }
 
@@ -265,16 +271,63 @@ public:
     jobject object;
   };
 
+
+  class Null : public Object {};
+
+
+  template <typename T, const char* name, const char* signature>
+  class Variable
+  {
+  public:
+    Variable(const Class& _clazz)
+      : clazz(_clazz)
+    {
+      // Check that T extends Object.
+      { T* t = NULL; Object* o = t; (void) o; }
+    }
+
+    Variable(const Class& _clazz, const Object& _object)
+      : clazz(_clazz), object(_object)
+    {
+      // Check that T extends Object.
+      { T* t = NULL; Object* o = t; (void) o; }
+    }
+
+    // TODO(benh): Implement cast operator (like in StaticVariable).
+    // This requires implementing Jvm::getField too.
+
+    template <typename U>
+    Variable& operator = (const U& u)
+    {
+      // Check that U extends Object (but not necessarily T since U
+      // might be 'Null').
+      { U* u = NULL; Object* o = u; (void) o; }
+
+      // Note that we actually look up the field lazily (upon first
+      // assignment operator) so that we don't possibly create the JVM
+      // too early.
+      static Field field = Jvm::get()->findField(clazz, name, signature);
+
+      Jvm::get()->setField<jobject>(object, field, u);
+
+      return *this;
+    }
+
+    void bind(const Object& _object) { object = _object; }
+
+  private:
+    const Class clazz;
+    Object object; // Not const so we can do late binding.
+  };
+
   // Helper for providing access to static variables in a class. You
   // can use this to delay the variable lookup until it's actually
   // accessed in order to keep the JVM from getting constructed too
   // early. See Level in jvm/org/apache/log4j.hpp for an example.
-  // TODO(benh): Make this work for instance variables too (i.e.,
-  // StaticVariable -> Variable).
   // TODO(benh): Provide template specialization for primitive
   // types (e.g., StaticVariable<int>, StaticVariable<short>,
   // StaticVariable<std::string>).
-  template <typename T, const char* name>
+  template <typename T, const char* name, const char* signature>
   class StaticVariable
   {
   public:
@@ -290,7 +343,8 @@ public:
       // Note that we actually look up the field lazily (upon first
       // invocation operator) so that we don't possibly create the JVM
       // too early.
-      static Field field = Jvm::get()->findStaticField(clazz, name);
+      static Field field =
+        Jvm::get()->findStaticField(clazz, name, signature);
       T t;
       t.object = Jvm::get()->getStaticField<jobject>(field);
       return t;
@@ -339,9 +393,20 @@ public:
   jstring string(const std::string& s);
 
   Constructor findConstructor(const ConstructorFinder& finder);
+
   Method findMethod(const MethodSignature& signature);
+
   Method findStaticMethod(const MethodSignature& signature);
-  Field findStaticField(const Class& clazz, const std::string& name);
+
+  Field findField(
+      const Class& clazz,
+      const std::string& name,
+      const std::string& signature);
+
+  Field findStaticField(
+      const Class& clazz,
+      const std::string& name,
+      const std::string& signature);
 
   // TODO(John Sirois): Add "type checking" to variadic method
   // calls. Possibly a way to do this with typelists, type
@@ -356,6 +421,9 @@ public:
   T invokeStatic(const Method& method, ...);
 
   template <typename T>
+  void setField(jobject receiver, const Field& field, T t);
+
+  template <typename T>
   T getStaticField(const Field& field);
 
   // Checks the exception state of an environment.

http://git-wip-us.apache.org/repos/asf/mesos/blob/9bfbc2c3/src/jvm/org/apache/log4j.cpp
----------------------------------------------------------------------
diff --git a/src/jvm/org/apache/log4j.cpp b/src/jvm/org/apache/log4j.cpp
index b73df8c..105629c 100644
--- a/src/jvm/org/apache/log4j.cpp
+++ b/src/jvm/org/apache/log4j.cpp
@@ -5,10 +5,11 @@ namespace apache {
 namespace log4j {
 
 // Static storage and initialization.
+const char LEVEL_OFF_SIGNATURE[] = "Lorg/apache/log4j/Level;";
 const char LEVEL_OFF[] = "OFF";
 
-Jvm::StaticVariable<Level, LEVEL_OFF> Level::OFF =
-  Jvm::StaticVariable<Level, LEVEL_OFF>(
+Jvm::StaticVariable<Level, LEVEL_OFF, LEVEL_OFF_SIGNATURE> Level::OFF =
+  Jvm::StaticVariable<Level, LEVEL_OFF, LEVEL_OFF_SIGNATURE>(
       Jvm::Class::named("org/apache/log4j/Level"));
 
 } // namespace log4j {

http://git-wip-us.apache.org/repos/asf/mesos/blob/9bfbc2c3/src/jvm/org/apache/log4j.hpp
----------------------------------------------------------------------
diff --git a/src/jvm/org/apache/log4j.hpp b/src/jvm/org/apache/log4j.hpp
index 6b5ba4b..0913a6b 100644
--- a/src/jvm/org/apache/log4j.hpp
+++ b/src/jvm/org/apache/log4j.hpp
@@ -8,15 +8,16 @@ namespace apache {
 namespace log4j {
 
 // Forward declaration.
+extern const char LEVEL_OFF_SIGNATURE[];
 extern const char LEVEL_OFF[];
 
 
 class Level : public Jvm::Object // TODO(benh): Extends Priority.
 {
 public:
-  friend class Jvm::StaticVariable<Level, LEVEL_OFF>;
+  friend class Jvm::StaticVariable<Level, LEVEL_OFF, LEVEL_OFF_SIGNATURE>;
 
-  static Jvm::StaticVariable<Level, LEVEL_OFF> OFF;
+  static Jvm::StaticVariable<Level, LEVEL_OFF, LEVEL_OFF_SIGNATURE> OFF;
 
   Level() {} // No default constuctors.
 };

http://git-wip-us.apache.org/repos/asf/mesos/blob/9bfbc2c3/src/jvm/org/apache/zookeeper.cpp
----------------------------------------------------------------------
diff --git a/src/jvm/org/apache/zookeeper.cpp b/src/jvm/org/apache/zookeeper.cpp
new file mode 100644
index 0000000..192b647
--- /dev/null
+++ b/src/jvm/org/apache/zookeeper.cpp
@@ -0,0 +1,15 @@
+#include <jvm/org/apache/zookeeper.hpp>
+
+namespace org {
+namespace apache {
+namespace zookeeper {
+namespace server {
+
+const char ZOOKEEPERSERVER_SESSIONTRACKER_SIGNATURE[] =
+  "Lorg/apache/zookeeper/server/SessionTracker;";
+const char ZOOKEEPERSERVER_SESSIONTRACKER[] = "sessionTracker";
+
+} // namespace server {
+} // namespace zookeeper {
+} // namespace apache {
+} // namespace org {

http://git-wip-us.apache.org/repos/asf/mesos/blob/9bfbc2c3/src/jvm/org/apache/zookeeper.hpp
----------------------------------------------------------------------
diff --git a/src/jvm/org/apache/zookeeper.hpp b/src/jvm/org/apache/zookeeper.hpp
index 2b78a25..392e749 100644
--- a/src/jvm/org/apache/zookeeper.hpp
+++ b/src/jvm/org/apache/zookeeper.hpp
@@ -6,11 +6,16 @@
 #include <jvm/java/io.hpp>
 #include <jvm/java/net.hpp>
 
-// Package 'org.apache.zookeeper.persistence'.
+
+// Package 'org.apache.zookeeper.server'.
 
 namespace org {
 namespace apache {
 namespace zookeeper {
+namespace server {
+
+// Package 'org.apache.zookeeper.server.persistence'.
+
 namespace persistence {
 
 class FileTxnSnapLog : public Jvm::Object
@@ -32,17 +37,14 @@ public:
 };
 
 } // namespace persistence {
-} // namespace zookeeper {
-} // namespace apache {
-} // namespace org {
 
 
-// Package 'org.apache.zookeeper.server'.
+class SessionTracker : public Jvm::Object {};
+
+
+extern const char ZOOKEEPERSERVER_SESSIONTRACKER_SIGNATURE[];
+extern const char ZOOKEEPERSERVER_SESSIONTRACKER[];
 
-namespace org {
-namespace apache {
-namespace zookeeper {
-namespace server {
 
 class ZooKeeperServer : public Jvm::Object
 {
@@ -65,6 +67,8 @@ public:
 
   ZooKeeperServer(const persistence::FileTxnSnapLog& txnLogFactory,
                   const DataTreeBuilder& treeBuilder)
+    : sessionTracker(
+        Jvm::Class::named("org/apache/zookeeper/server/ZooKeeperServer"))
   {
     static Jvm::Constructor constructor = Jvm::get()->findConstructor(
         Jvm::Class::named("org/apache/zookeeper/server/ZooKeeperServer")
@@ -78,6 +82,11 @@ public:
 
     object = Jvm::get()->invoke(
         constructor, (jobject) txnLogFactory, (jobject) treeBuilder);
+
+    // We need to "bind" the 'sessionTracker' Variable after we assign
+    // 'object' above so that '*this' is a Jvm::Object instance that
+    // doesn't point to a NULL jobject.
+    sessionTracker.bind(*this);
   }
 
   void setMaxSessionTimeout(int max)
@@ -142,64 +151,64 @@ public:
 
     Jvm::get()->invoke<void>(object, method, sessionId);
   }
+
+  Jvm::Variable<SessionTracker,
+                ZOOKEEPERSERVER_SESSIONTRACKER,
+                ZOOKEEPERSERVER_SESSIONTRACKER_SIGNATURE> sessionTracker;
 };
 
 
-class NIOServerCnxn : public Jvm::Object
+// TODO(benh): Extends ServerCnxnFactory implements Runnable.
+class NIOServerCnxnFactory : public Jvm::Object
 {
 public:
-  class Factory : public Jvm::Object // TODO(benh): Extends Thread.
+  NIOServerCnxnFactory()
   {
-  public:
-    Factory(const java::net::InetSocketAddress& addr)
-    {
-      static Jvm::Constructor constructor = Jvm::get()->findConstructor(
-          Jvm::Class::named(
-              "org/apache/zookeeper/server/NIOServerCnxn$Factory")
-          .constructor()
-          .parameter(Jvm::Class::named("java/net/InetSocketAddress")));
+    static Jvm::Constructor constructor = Jvm::get()->findConstructor(
+        Jvm::Class::named(
+            "org/apache/zookeeper/server/NIOServerCnxnFactory")
+        .constructor());
 
-      object = Jvm::get()->invoke(constructor, (jobject) addr);
-    }
+    object = Jvm::get()->invoke(constructor);
+  }
 
-    void startup(const ZooKeeperServer& zks)
-    {
-      static Jvm::Method method = Jvm::get()->findMethod(
-          Jvm::Class::named(
-              "org/apache/zookeeper/server/NIOServerCnxn$Factory")
-          .method("startup")
-          .parameter(Jvm::Class::named(
-                         "org/apache/zookeeper/server/ZooKeeperServer"))
-          .returns(Jvm::get()->voidClass));
+  void configure(const java::net::InetSocketAddress& addr, int maxcc)
+  {
+    static Jvm::Method method = Jvm::get()->findMethod(
+        Jvm::Class::named(
+            "org/apache/zookeeper/server/NIOServerCnxnFactory")
+        .method("configure")
+        .parameter(Jvm::Class::named("java/net/InetSocketAddress"))
+        .parameter(Jvm::get()->intClass)
+        .returns(Jvm::get()->voidClass));
 
-      Jvm::get()->invoke<void>(object, method, (jobject) zks);
-    }
 
-    bool isAlive()
-    {
-      static Jvm::Method method = Jvm::get()->findMethod(
-          Jvm::Class::named(
-              "org/apache/zookeeper/server/NIOServerCnxn$Factory")
-          .method("isAlive")
-          .returns(Jvm::get()->booleanClass));
+    Jvm::get()->invoke<void>(object, method, (jobject) addr, maxcc);
+  }
 
-      return Jvm::get()->invoke<bool>(object, method);
-    }
+  void startup(const ZooKeeperServer& zks)
+  {
+    static Jvm::Method method = Jvm::get()->findMethod(
+        Jvm::Class::named(
+            "org/apache/zookeeper/server/NIOServerCnxnFactory")
+        .method("startup")
+        .parameter(Jvm::Class::named(
+                       "org/apache/zookeeper/server/ZooKeeperServer"))
+        .returns(Jvm::get()->voidClass));
 
-    void shutdown()
-    {
-      static Jvm::Method method = Jvm::get()->findMethod(
-          Jvm::Class::named(
-              "org/apache/zookeeper/server/NIOServerCnxn$Factory")
-          .method("shutdown")
-          .returns(Jvm::get()->voidClass));
+    Jvm::get()->invoke<void>(object, method, (jobject) zks);
+  }
 
-      Jvm::get()->invoke<void>(object, method);
-    }
-  };
+  void shutdown()
+  {
+    static Jvm::Method method = Jvm::get()->findMethod(
+        Jvm::Class::named(
+            "org/apache/zookeeper/server/NIOServerCnxnFactory")
+        .method("shutdown")
+        .returns(Jvm::get()->voidClass));
 
-private:
-  NIOServerCnxn() {} // No default constructors.
+    Jvm::get()->invoke<void>(object, method);
+  }
 };
 
 } // namespace server {

http://git-wip-us.apache.org/repos/asf/mesos/blob/9bfbc2c3/src/python/setup.py.in
----------------------------------------------------------------------
diff --git a/src/python/setup.py.in b/src/python/setup.py.in
index 47cea7c..02f00ef 100644
--- a/src/python/setup.py.in
+++ b/src/python/setup.py.in
@@ -20,7 +20,7 @@ src_python_dist = os.path.join('src', 'python', 'dist')
 src_python_native = os.path.join('src', 'python', 'native')
 
 leveldb = os.path.join('3rdparty', 'leveldb')
-zookeeper = os.path.join('3rdparty', 'zookeeper-3.3.4', 'src', 'c')
+zookeeper = os.path.join('3rdparty', 'zookeeper-3.4.5', 'src', 'c')
 libprocess = os.path.join('3rdparty', 'libprocess')
 
 # Even though a statically compiled libprocess should include glog,

http://git-wip-us.apache.org/repos/asf/mesos/blob/9bfbc2c3/src/tests/zookeeper.cpp
----------------------------------------------------------------------
diff --git a/src/tests/zookeeper.cpp b/src/tests/zookeeper.cpp
index 8462f1f..f5ae23c 100644
--- a/src/tests/zookeeper.cpp
+++ b/src/tests/zookeeper.cpp
@@ -20,7 +20,9 @@
 
 #include <gtest/gtest.h>
 
-#include <queue>
+#include <list>
+#include <string>
+#include <vector>
 
 #include <jvm/jvm.hpp>
 
@@ -29,6 +31,8 @@
 
 #include <stout/check.hpp>
 #include <stout/lambda.hpp>
+#include <stout/path.hpp>
+#include <stout/os.hpp>
 
 #include "common/lock.hpp"
 
@@ -38,6 +42,10 @@
 #include "tests/zookeeper.hpp"
 #include "tests/zookeeper_test_server.hpp"
 
+using std::list;
+using std::string;
+using std::vector;
+
 namespace mesos {
 namespace internal {
 namespace tests {
@@ -48,16 +56,24 @@ const Duration ZooKeeperTest::NO_TIMEOUT = Milliseconds(5000);
 void ZooKeeperTest::SetUpTestCase()
 {
   if (!Jvm::created()) {
-    std::string zkHome = flags.build_dir +
-      "/3rdparty/zookeeper-" ZOOKEEPER_VERSION;
+    string zkHome =
+      path::join(flags.build_dir, "/3rdparty/zookeeper-" ZOOKEEPER_VERSION);
+
+    string classpath = "-Djava.class.path=" +
+      path::join(zkHome, "zookeeper-" ZOOKEEPER_VERSION ".jar");
+
+    // Now add all the libraries in 'lib' too.
+    Try<list<string> > jars = os::glob(path::join(zkHome, "lib", "*.jar"));
 
-    std::string classpath = "-Djava.class.path=" +
-      zkHome + "/zookeeper-" ZOOKEEPER_VERSION ".jar:" +
-      zkHome + "/lib/log4j-1.2.15.jar";
+    CHECK_SOME(jars);
+
+    foreach (const string& jar, jars.get()) {
+      classpath += ":" + jar;
+    }
 
-    LOG(INFO) << "Using classpath setup: " << classpath << std::endl;
+    LOG(INFO) << "Using Java classpath: " << classpath;
 
-    std::vector<std::string> options;
+    vector<string> options;
     options.push_back(classpath);
     Try<Jvm*> jvm = Jvm::create(options);
     CHECK_SOME(jvm);
@@ -103,7 +119,7 @@ void ZooKeeperTest::TestWatcher::process(
     ZooKeeper* zk,
     int type,
     int state,
-    const std::string& path)
+    const string& path)
 {
   Lock lock(&mutex);
   events.push(Event(type, state, path));
@@ -127,13 +143,13 @@ void ZooKeeperTest::TestWatcher::awaitSessionEvent(int state)
 
 static bool isCreated(
     const ZooKeeperTest::TestWatcher::Event& event,
-    const std::string& path)
+    const string& path)
 {
   return event.type == ZOO_CHILD_EVENT && event.path == path;
 }
 
 
-void ZooKeeperTest::TestWatcher::awaitCreated(const std::string& path)
+void ZooKeeperTest::TestWatcher::awaitCreated(const string& path)
 {
   awaitEvent(lambda::bind(&isCreated, lambda::_1, path));
 }

http://git-wip-us.apache.org/repos/asf/mesos/blob/9bfbc2c3/src/tests/zookeeper_test_server.cpp
----------------------------------------------------------------------
diff --git a/src/tests/zookeeper_test_server.cpp b/src/tests/zookeeper_test_server.cpp
index 62b4e0b..a8c9b1c 100644
--- a/src/tests/zookeeper_test_server.cpp
+++ b/src/tests/zookeeper_test_server.cpp
@@ -30,9 +30,9 @@
 
 #include "tests/zookeeper_test_server.hpp"
 
-using org::apache::zookeeper::persistence::FileTxnSnapLog;
+using org::apache::zookeeper::server::persistence::FileTxnSnapLog;
 
-using org::apache::zookeeper::server::NIOServerCnxn;
+using org::apache::zookeeper::server::NIOServerCnxnFactory;
 using org::apache::zookeeper::server::ZooKeeperServer;
 
 namespace mesos {
@@ -114,32 +114,51 @@ std::string ZooKeeperTestServer::connectString() const
 
 void ZooKeeperTestServer::shutdownNetwork()
 {
-  if (started && connectionFactory && connectionFactory->isAlive()) {
+  if (connectionFactory != NULL && started) {
     connectionFactory->shutdown();
     delete connectionFactory;
     connectionFactory = NULL;
-    LOG(INFO) << "Shutdown ZooKeeperTestServer on port " << port << std::endl;
+    started = false;
+    LOG(INFO) << "Shutdown ZooKeeperTestServer on port " << port;
   }
 }
 
 
 int ZooKeeperTestServer::startNetwork()
 {
-  connectionFactory = new NIOServerCnxn::Factory(
-      java::net::InetSocketAddress(port));
-
-  connectionFactory->startup(*zooKeeperServer);
-
-  if (port == 0) {
-    // We save the ephemeral port so if/when we restart the network
-    // the clients will reconnect to the same server. Note that this
-    // might not actually be kosher because it's possible that another
-    // process could bind to our ephemeral port after we unbind.
-    port = zooKeeperServer->getClientPort();
+  if (!started) {
+    connectionFactory = new NIOServerCnxnFactory();
+
+    // We use '-1' to allow an unlimited number of connections for his
+    // connection factory instance.
+    connectionFactory->configure(java::net::InetSocketAddress(port), -1);
+
+    // It's possible that we are restarting the network, but not the
+    // server. Unfortunately, we can't just invoke 'startup' on the
+    // NIOServerCnxnFactory because of a bug in ZooKeeperServer (see
+    // MESOS-670). We remedy this with a giant hack: by setting the
+    // 'sessionTracker' variable on ZooKeeperServer to null then a new
+    // instance will get created and everything will work out. Until
+    // ZooKeeper provides mechanisms for doing in-memory testing this
+    // hack (or something like it) will need to exist. This hack is
+    // specific to ZooKeeper 3.4.5 and may need to change if up
+    // upgrade ZooKeeper.
+    zooKeeperServer->sessionTracker = Jvm::Null();
+
+    connectionFactory->startup(*zooKeeperServer);
+
+    if (port == 0) {
+      // We save the ephemeral port so if/when we restart the network
+      // the clients will reconnect to the same server. Note that this
+      // might not actually be kosher because it's possible that another
+      // process could bind to our ephemeral port after we unbind.
+      port = zooKeeperServer->getClientPort();
+    }
+
+    LOG(INFO) << "Started ZooKeeperTestServer on port " << port;
+    started = true;
   }
 
-  LOG(INFO) << "Started ZooKeeperTestServer on port " << port;
-  started = true;
   return port;
 }
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/9bfbc2c3/src/tests/zookeeper_test_server.hpp
----------------------------------------------------------------------
diff --git a/src/tests/zookeeper_test_server.hpp b/src/tests/zookeeper_test_server.hpp
index e612621..e415ce6 100644
--- a/src/tests/zookeeper_test_server.hpp
+++ b/src/tests/zookeeper_test_server.hpp
@@ -74,7 +74,7 @@ public:
 
 private:
   org::apache::zookeeper::server::ZooKeeperServer* zooKeeperServer;
-  org::apache::zookeeper::server::NIOServerCnxn::Factory* connectionFactory;
+  org::apache::zookeeper::server::NIOServerCnxnFactory* connectionFactory;
 
   int port;
   bool started;