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 2012/03/27 19:56:25 UTC

svn commit: r1305932 [2/2] - in /incubator/mesos/trunk: hadoop/ include/mesos/ src/ src/deploy/ src/detector/ src/examples/ src/examples/java/ src/examples/python/ src/exec/ src/java/jni/ src/java/src/org/apache/mesos/ src/launcher/ src/master/ src/mes...

Modified: incubator/mesos/trunk/src/master/master.cpp
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/src/master/master.cpp?rev=1305932&r1=1305931&r2=1305932&view=diff
==============================================================================
--- incubator/mesos/trunk/src/master/master.cpp (original)
+++ incubator/mesos/trunk/src/master/master.cpp Tue Mar 27 17:56:23 2012
@@ -265,7 +265,7 @@ vector<Slave*> Master::getActiveSlaves()
 
 void Master::initialize()
 {
-  LOG(INFO) << "Master started at mesos://" << self();
+  LOG(INFO) << "Master started on " << string(self()).substr(7);
 
   // The master ID is currently comprised of the current date, the IP
   // address and port from self() and the OS PID.
@@ -332,7 +332,6 @@ void Master::initialize()
 
   install<ReregisterFrameworkMessage>(
       &Master::reregisterFramework,
-      &ReregisterFrameworkMessage::framework_id,
       &ReregisterFrameworkMessage::framework,
       &ReregisterFrameworkMessage::failover);
 
@@ -532,7 +531,6 @@ void Master::registerFramework(const Fra
     LOG(INFO) << framework << " registering as root, but "
       << "root submissions are disabled on this cluster";
     FrameworkErrorMessage message;
-    message.set_code(1);
     message.set_message("User 'root' is not allowed to run frameworks");
     reply(message);
     delete framework;
@@ -543,8 +541,7 @@ void Master::registerFramework(const Fra
 }
 
 
-void Master::reregisterFramework(const FrameworkID& frameworkId,
-                                 const FrameworkInfo& frameworkInfo,
+void Master::reregisterFramework(const FrameworkInfo& frameworkInfo,
                                  bool failover)
 {
   if (!elected) {
@@ -553,19 +550,18 @@ void Master::reregisterFramework(const F
     return;
   }
 
-  if (frameworkId == "") {
+  if (!frameworkInfo.has_id() || frameworkInfo.id() == "") {
     LOG(ERROR) << "Framework re-registering without an id!";
     FrameworkErrorMessage message;
-    message.set_code(1);
     message.set_message("Framework reregistered without a framework id");
     reply(message);
     return;
   }
 
-  LOG(INFO) << "Re-registering framework " << frameworkId
+  LOG(INFO) << "Re-registering framework " << frameworkInfo.id()
             << " at " << from;
 
-  if (frameworks.count(frameworkId) > 0) {
+  if (frameworks.count(frameworkInfo.id()) > 0) {
     // Using the "failover" of the scheduler allows us to keep a
     // scheduler that got partitioned but didn't die (in ZooKeeper
     // speak this means didn't lose their session) and then
@@ -576,15 +572,15 @@ void Master::reregisterFramework(const F
     // (if necessary) by the master and the master will always
     // know which scheduler is the correct one.
 
-    Framework* framework = frameworks[frameworkId];
+    Framework* framework = frameworks[frameworkInfo.id()];
 
     if (failover) {
       // TODO: Should we check whether the new scheduler has given
       // us a different framework name, user name or executor info?
-      LOG(INFO) << "Framework " << frameworkId << " failed over";
+      LOG(INFO) << "Framework " << frameworkInfo.id() << " failed over";
       failoverFramework(framework, from);
     } else {
-      LOG(INFO) << "Allowing the Framework " << frameworkId
+      LOG(INFO) << "Allowing the Framework " << frameworkInfo.id()
                 << " to re-register with an already used id";
 
       // Remove any offers sent to this framework.
@@ -599,7 +595,7 @@ void Master::reregisterFramework(const F
       }
 
       FrameworkReregisteredMessage message;
-      message.mutable_framework_id()->MergeFrom(frameworkId);
+      message.mutable_framework_id()->MergeFrom(frameworkInfo.id());
       message.mutable_master_info()->MergeFrom(info);
       reply(message);
       return;
@@ -610,7 +606,7 @@ void Master::reregisterFramework(const F
     // failed-over one is connecting. Create a Framework object and add
     // any tasks it has that have been reported by reconnecting slaves.
     Framework* framework =
-      new Framework(frameworkInfo, frameworkId, from, Clock::now());
+      new Framework(frameworkInfo, frameworkInfo.id(), from, Clock::now());
 
     // TODO(benh): Check for root submissions like above!
 
@@ -635,7 +631,7 @@ void Master::reregisterFramework(const F
     }
   }
 
-  CHECK(frameworks.count(frameworkId) > 0);
+  CHECK(frameworks.count(frameworkInfo.id()) > 0);
 
   // Broadcast the new framework pid to all the slaves. We have to
   // broadcast because an executor might be running on a slave but
@@ -643,7 +639,7 @@ void Master::reregisterFramework(const F
   // potential scalability issue ...
   foreachvalue (Slave* slave, slaves) {
     UpdateFrameworkMessage message;
-    message.mutable_framework_id()->MergeFrom(frameworkId);
+    message.mutable_framework_id()->MergeFrom(frameworkInfo.id());
     message.set_pid(from);
     send(slave->pid, message);
   }
@@ -1538,7 +1534,6 @@ void Master::failoverFramework(Framework
 
   {
     FrameworkErrorMessage message;
-    message.set_code(1);
     message.set_message("Framework failed over");
     send(oldPid, message);
   }

Modified: incubator/mesos/trunk/src/master/master.hpp
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/src/master/master.hpp?rev=1305932&r1=1305931&r2=1305932&view=diff
==============================================================================
--- incubator/mesos/trunk/src/master/master.hpp (original)
+++ incubator/mesos/trunk/src/master/master.hpp Tue Mar 27 17:56:23 2012
@@ -72,8 +72,7 @@ public:
   void noMasterDetected();
   void masterDetectionFailure();
   void registerFramework(const FrameworkInfo& frameworkInfo);
-  void reregisterFramework(const FrameworkID& frameworkId,
-                           const FrameworkInfo& frameworkInfo,
+  void reregisterFramework(const FrameworkInfo& frameworkInfo,
                            bool failover);
   void unregisterFramework(const FrameworkID& frameworkId);
   void deactivateFramework(const FrameworkID& frameworkId);
@@ -475,7 +474,7 @@ struct Framework
     }
   }
 
-  const FrameworkID id;
+  const FrameworkID id; // TODO(benh): Store this in 'info.
   const FrameworkInfo info;
 
   UPID pid;

Modified: incubator/mesos/trunk/src/mesos/main.cpp
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/src/mesos/main.cpp?rev=1305932&r1=1305931&r2=1305932&view=diff
==============================================================================
--- incubator/mesos/trunk/src/mesos/main.cpp (original)
+++ incubator/mesos/trunk/src/mesos/main.cpp Tue Mar 27 17:56:23 2012
@@ -12,17 +12,12 @@ using namespace process;
 using std::cerr;
 using std::cout;
 using std::endl;
+using std::string;
 
 
 void usage(const char* programName, const Configurator& configurator)
 {
-  cerr << "Usage: " << programName
-       << " --master=URL --name=NAME --num-replicas=NUM [...]" << endl
-       << endl
-       << "'master' may be one of:" << endl
-       << "  mesos://id@host:port" << endl
-       << "  zoo://host1:port1,host2:port2,..." << endl
-       << "  zoofile://file where file contains a host:port pair per line"
+  cerr << "Usage: " << programName << " [...]" << endl
        << endl
        << endl
        << "Supported options:" << endl
@@ -34,10 +29,26 @@ int main(int argc, char** argv)
 {
   GOOGLE_PROTOBUF_VERIFY_VERSION;
 
-  // TODO(vinod): Add options!
   Configurator configurator;
 
-  if (argc == 2 && std::string("--help") == argv[1]) {
+  // The following options are executable specific (e.g., since we
+  // only have one instance of libprocess per execution, we only want
+  // to advertise the port and ip option once, here).
+  configurator.addOption<int>("port", 'p', "Port to listen on", 5050);
+  configurator.addOption<string>("ip", "IP address to listen on");
+#ifdef MESOS_WEBUI
+  configurator.addOption<int>("webui_port", "Web UI port", 8080);
+#endif
+  configurator.addOption<string>(
+      "master",
+      'm',
+      "May be one of:\n"
+      "  host:port\n"
+      "  zk://host1:port1,host2:port2,.../path\n"
+      "  zk://username:password@host1:port1,host2:port2,.../path\n"
+      "  file://path/to/file (where file contains one of the above)");
+
+  if (argc == 2 && string("--help") == argv[1]) {
     usage(argv[0], configurator);
     exit(1);
   }
@@ -46,7 +57,7 @@ int main(int argc, char** argv)
   try {
     conf = configurator.load(argc, argv);
   } catch (const ConfigurationException& e) {
-    std::cerr << "Configuration error: " << e.what() << std::endl;
+    cerr << "Configuration error: " << e.what() << endl;
     exit(1);
   }
 
@@ -54,6 +65,7 @@ int main(int argc, char** argv)
   process::initialize();
 
   if (!conf.contains("master")) {
+    cerr << "Missing required option --master (-m)" << endl;
     usage(argv[0], configurator);
     exit(1);
   }
@@ -68,6 +80,8 @@ int main(int argc, char** argv)
   }
 
   if (!conf.contains("name")) {
+    // TODO(benh): Need to add '--name' as an option.
+    cerr << "Missing --name (-n)" << endl;
     usage(argv[0], configurator);
     exit(1);
   }

Modified: incubator/mesos/trunk/src/messages/messages.proto
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/src/messages/messages.proto?rev=1305932&r1=1305931&r2=1305932&view=diff
==============================================================================
--- incubator/mesos/trunk/src/messages/messages.proto (original)
+++ incubator/mesos/trunk/src/messages/messages.proto Tue Mar 27 17:56:23 2012
@@ -89,7 +89,6 @@ message RegisterFrameworkMessage {
 
 
 message ReregisterFrameworkMessage {
-  required FrameworkID framework_id = 1;
   required FrameworkInfo framework = 2;
   required bool failover = 3;
 }
@@ -179,7 +178,6 @@ message LostSlaveMessage {
 
 
 message FrameworkErrorMessage {
-  required int32 code = 1;
   required string message = 2;
 }
 

Modified: incubator/mesos/trunk/src/python/native/mesos_scheduler_driver_impl.cpp
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/src/python/native/mesos_scheduler_driver_impl.cpp?rev=1305932&r1=1305931&r2=1305932&view=diff
==============================================================================
--- incubator/mesos/trunk/src/python/native/mesos_scheduler_driver_impl.cpp (original)
+++ incubator/mesos/trunk/src/python/native/mesos_scheduler_driver_impl.cpp Tue Mar 27 17:56:23 2012
@@ -144,23 +144,29 @@ int MesosSchedulerDriverImpl_init(MesosS
                                   PyObject* args,
                                   PyObject* kwds)
 {
-  PyObject *pythonSchedulerObj = NULL;
-  const char* url;
-  PyObject *frameworkIdObj = NULL;
-  const char* frameworkName;
+  PyObject* schedulerObj = NULL;
+  PyObject* frameworkObj = NULL;
+  const char* master;
 
-  if (!PyArg_ParseTuple(args, "Oss|O", &pythonSchedulerObj, &frameworkName,
-                        &url, &frameworkIdObj)) {
+  if (!PyArg_ParseTuple(args, "OOs", &schedulerObj, &frameworkObj, &master)) {
     return -1;
   }
 
-  if (pythonSchedulerObj != NULL) {
+  if (schedulerObj != NULL) {
     PyObject* tmp = self->pythonScheduler;
-    Py_INCREF(pythonSchedulerObj);
-    self->pythonScheduler = pythonSchedulerObj;
+    Py_INCREF(schedulerObj);
+    self->pythonScheduler = schedulerObj;
     Py_XDECREF(tmp);
   }
 
+  FrameworkInfo framework;
+  if (frameworkObj != NULL) {
+    if (!readPythonProtobuf(frameworkObj, &framework)) {
+      PyErr_Format(PyExc_Exception, "Could not deserialize Python FrameworkInfo");
+      return -1;
+    }
+  }
+
   if (self->driver != NULL) {
     self->driver->stop();
     delete self->driver;
@@ -172,23 +178,10 @@ int MesosSchedulerDriverImpl_init(MesosS
     self->proxyScheduler = NULL;
   }
 
-  FrameworkID frameworkId;
-  if (frameworkIdObj != NULL) {
-    if (!readPythonProtobuf(frameworkIdObj, &frameworkId)) {
-      PyErr_Format(PyExc_Exception, "Could not deserialize Python FrameworkId");
-      return -1;
-    }
-  }
-
   self->proxyScheduler = new ProxyScheduler(self);
 
-  if (frameworkIdObj != NULL) {
-    self->driver = new MesosSchedulerDriver(self->proxyScheduler, frameworkName,
-                                            url, frameworkId);
-  } else {
-    self->driver = new MesosSchedulerDriver(self->proxyScheduler, frameworkName,
-                                            url);
-  }
+  self->driver =
+    new MesosSchedulerDriver(self->proxyScheduler, framework, master);
 
   return 0;
 }
@@ -347,8 +340,7 @@ PyObject* MesosSchedulerDriverImpl_reque
     }
     Request request;
     if (!readPythonProtobuf(requestObj, &request)) {
-      PyErr_Format(PyExc_Exception,
-                   "Could not deserialize Python Request");
+      PyErr_Format(PyExc_Exception, "Could not deserialize Python Request");
       return NULL;
     }
     requests.push_back(request);

Modified: incubator/mesos/trunk/src/python/native/proxy_executor.cpp
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/src/python/native/proxy_executor.cpp?rev=1305932&r1=1305931&r2=1305932&view=diff
==============================================================================
--- incubator/mesos/trunk/src/python/native/proxy_executor.cpp (original)
+++ incubator/mesos/trunk/src/python/native/proxy_executor.cpp Tue Mar 27 17:56:23 2012
@@ -30,8 +30,8 @@ using std::string;
 using std::vector;
 using std::map;
 
-
-namespace mesos { namespace python {
+namespace mesos {
+namespace python {
 
 void ProxyExecutor::registered(ExecutorDriver* driver,
                                const ExecutorInfo& executorInfo,
@@ -245,16 +245,13 @@ cleanup:
 }
 
 
-void ProxyExecutor::error(ExecutorDriver* driver,
-                          int code,
-                          const string& message)
+void ProxyExecutor::error(ExecutorDriver* driver, const string& message)
 {
   InterpreterLock lock;
   PyObject* res = PyObject_CallMethod(impl->pythonExecutor,
                                       (char*) "error",
-                                      (char*) "Ois",
+                                      (char*) "Os",
                                       impl,
-                                      code,
                                       message.c_str());
   if (res == NULL) {
     cerr << "Failed to call executor's error" << endl;
@@ -268,4 +265,5 @@ cleanup:
   Py_XDECREF(res);
 }
 
-}} /* namespace mesos { namespace python { */
+} // namespace python {
+} // namespace mesos {

Modified: incubator/mesos/trunk/src/python/native/proxy_executor.hpp
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/src/python/native/proxy_executor.hpp?rev=1305932&r1=1305931&r2=1305932&view=diff
==============================================================================
--- incubator/mesos/trunk/src/python/native/proxy_executor.hpp (original)
+++ incubator/mesos/trunk/src/python/native/proxy_executor.hpp Tue Mar 27 17:56:23 2012
@@ -26,18 +26,16 @@
 
 #include <mesos/executor.hpp>
 
-
-namespace mesos { namespace python {
+namespace mesos {
+namespace python {
 
 struct MesosExecutorDriverImpl;
 
 /**
- * Proxy Executor implementation that will call into Python
+ * Proxy Executor implementation that will call into Python.
  */
 class ProxyExecutor : public Executor
 {
-  MesosExecutorDriverImpl *impl;
-
 public:
   ProxyExecutor(MesosExecutorDriverImpl *_impl) : impl(_impl) {}
 
@@ -47,27 +45,20 @@ public:
                           const ExecutorInfo& executorInfo,
                           const FrameworkInfo& frameworkInfo,
                           const SlaveInfo& slaveInfo);
-
-  virtual void reregistered(ExecutorDriver* driver,
-                            const SlaveInfo& slaveInfo);
-
-  virtual void launchTask(ExecutorDriver* driver,
-                          const TaskInfo& task);
-
+  virtual void reregistered(ExecutorDriver* driver, const SlaveInfo& slaveInfo);
+  virtual void launchTask(ExecutorDriver* driver, const TaskInfo& task);
   virtual void killTask(ExecutorDriver* driver, const TaskID& taskId);
-
   virtual void frameworkMessage(ExecutorDriver* driver,
                                 const std::string& data);
-
   virtual void slaveLost(ExecutorDriver* driver);
-
   virtual void shutdown(ExecutorDriver* driver);
+  virtual void error(ExecutorDriver* driver, const std::string& message);
 
-  virtual void error(ExecutorDriver* driver,
-                     int code,
-                     const std::string& message);
+private:
+  MesosExecutorDriverImpl *impl;
 };
 
-}} /* namespace mesos { namespace python { */
+} // namespace python {
+} // namespace mesos {
 
-#endif /* PROXY_EXECUTOR_HPP */
+#endif // PROXY_EXECUTOR_HPP

Modified: incubator/mesos/trunk/src/python/native/proxy_scheduler.cpp
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/src/python/native/proxy_scheduler.cpp?rev=1305932&r1=1305931&r2=1305932&view=diff
==============================================================================
--- incubator/mesos/trunk/src/python/native/proxy_scheduler.cpp (original)
+++ incubator/mesos/trunk/src/python/native/proxy_scheduler.cpp Tue Mar 27 17:56:23 2012
@@ -30,8 +30,8 @@ using std::string;
 using std::vector;
 using std::map;
 
-
-namespace mesos { namespace python {
+namespace mesos {
+namespace python {
 
 void ProxyScheduler::registered(SchedulerDriver* driver,
                                 const FrameworkID& frameworkId,
@@ -259,8 +259,31 @@ cleanup:
 }
 
 
-void ProxyScheduler::slaveLost(SchedulerDriver* driver,
-                               const SlaveID& slaveId)
+void ProxyScheduler::masterLost(SchedulerDriver* driver)
+{
+  InterpreterLock lock;
+
+  PyObject* res = NULL;
+
+  res = PyObject_CallMethod(impl->pythonScheduler,
+                            (char*) "masterLost",
+                            (char*) "O",
+                            impl);
+  if (res == NULL) {
+    cerr << "Failed to call scheduler's masterLost" << endl;
+    goto cleanup;
+  }
+
+cleanup:
+  if (PyErr_Occurred()) {
+    PyErr_Print();
+    driver->abort();
+  }
+  Py_XDECREF(res);
+}
+
+
+void ProxyScheduler::slaveLost(SchedulerDriver* driver, const SlaveID& slaveId)
 {
   InterpreterLock lock;
 
@@ -333,40 +356,13 @@ cleanup:
 }
 
 
-void ProxyScheduler::masterLost(SchedulerDriver* driver)
-{
-  InterpreterLock lock;
-
-  PyObject* res = NULL;
-
-  res = PyObject_CallMethod(impl->pythonScheduler,
-                            (char*) "masterLost",
-                            (char*) "O",
-                            impl);
-  if (res == NULL) {
-    cerr << "Failed to call scheduler's masterLost" << endl;
-    goto cleanup;
-  }
-
-cleanup:
-  if (PyErr_Occurred()) {
-    PyErr_Print();
-    driver->abort();
-  }
-  Py_XDECREF(res);
-}
-
-
-void ProxyScheduler::error(SchedulerDriver* driver,
-                           int code,
-                           const string& message)
+void ProxyScheduler::error(SchedulerDriver* driver, const string& message)
 {
   InterpreterLock lock;
   PyObject* res = PyObject_CallMethod(impl->pythonScheduler,
                                       (char*) "error",
-                                      (char*) "Ois",
+                                      (char*) "Os",
                                       impl,
-                                      code,
                                       message.c_str());
   if (res == NULL) {
     cerr << "Failed to call scheduler's error" << endl;
@@ -380,4 +376,5 @@ cleanup:
   Py_XDECREF(res);
 }
 
-}} /* namespace mesos { namespace python { */
+} // namespace python {
+} // namespace mesos {

Modified: incubator/mesos/trunk/src/python/native/proxy_scheduler.hpp
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/src/python/native/proxy_scheduler.hpp?rev=1305932&r1=1305931&r2=1305932&view=diff
==============================================================================
--- incubator/mesos/trunk/src/python/native/proxy_scheduler.hpp (original)
+++ incubator/mesos/trunk/src/python/native/proxy_scheduler.hpp Tue Mar 27 17:56:23 2012
@@ -26,61 +26,47 @@
 
 #include <mesos/scheduler.hpp>
 
-
-namespace mesos { namespace python {
+namespace mesos {
+namespace python {
 
 struct MesosSchedulerDriverImpl;
 
 /**
- * Proxy Scheduler implementation that will call into Python
+ * Proxy Scheduler implementation that will call into Python.
  */
 class ProxyScheduler : public Scheduler
 {
-  MesosSchedulerDriverImpl *impl;
-
 public:
-  ProxyScheduler(MesosSchedulerDriverImpl *_impl) : impl(_impl) {}
+  ProxyScheduler(MesosSchedulerDriverImpl* _impl) : impl(_impl) {}
 
   virtual ~ProxyScheduler() {}
 
-  // Callbacks for various Mesos events.
   virtual void registered(SchedulerDriver* driver,
                           const FrameworkID& frameworkId,
                           const MasterInfo& masterInfo);
-
   virtual void reregistered(SchedulerDriver* driver,
-                          const MasterInfo& masterInfo);
-
+                            const MasterInfo& masterInfo);
   virtual void resourceOffers(SchedulerDriver* driver,
                               const std::vector<Offer>& offers);
-
-  virtual void offerRescinded(SchedulerDriver* driver,
-                              const OfferID& offerId);
-
-  virtual void statusUpdate(SchedulerDriver* driver,
-                            const TaskStatus& status);
-
+  virtual void offerRescinded(SchedulerDriver* driver, const OfferID& offerId);
+  virtual void statusUpdate(SchedulerDriver* driver, const TaskStatus& status);
   virtual void frameworkMessage(SchedulerDriver* driver,
                                 const ExecutorID& executorId,
                                 const SlaveID& slaveId,
                                 const std::string& data);
-
-  virtual void slaveLost(SchedulerDriver* driver,
-                         const SlaveID& slaveId);
-
   virtual void masterLost(SchedulerDriver* driver);
-
+  virtual void slaveLost(SchedulerDriver* driver, const SlaveID& slaveId);
   virtual void executorLost(SchedulerDriver* driver,
                             const ExecutorID& executorId,
                             const SlaveID& slaveId,
                             int status);
+  virtual void error(SchedulerDriver* driver, const std::string& message);
 
-  virtual void error(SchedulerDriver* driver,
-                     int code,
-                     const std::string& message);
-
+private:
+  MesosSchedulerDriverImpl* impl;
 };
 
-}} /* namespace mesos { namespace python { */
+} // namespace python {
+} // namespace mesos {
 
-#endif /* PROXY_SCHEDULER_HPP */
+#endif // PROXY_SCHEDULER_HPP

Modified: incubator/mesos/trunk/src/python/src/mesos.py
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/src/python/src/mesos.py?rev=1305932&r1=1305931&r2=1305932&view=diff
==============================================================================
--- incubator/mesos/trunk/src/python/src/mesos.py (original)
+++ incubator/mesos/trunk/src/python/src/mesos.py Tue Mar 27 17:56:23 2012
@@ -37,8 +37,8 @@ class Scheduler:
 
   # Default implementation of error() prints to stderr because we
   # can't make error() an abstract method in Python.
-  def error(self, driver, code, message):
-    print >> sys.stderr, "Error from Mesos: %s (code: %d)" % (message, code)
+  def error(self, driver, message):
+    print >> sys.stderr, "Error from Mesos: %s " % message
 
 
 # Interface for Mesos scheduler drivers. Users may wish to extend this
@@ -70,8 +70,8 @@ class Executor:
 
   # Default implementation of error() prints to stderr because we
   # can't make error() an abstract method in Python.
-  def error(self, driver, code, message):
-    print >> sys.stderr, "Error from Mesos: %s (code: %d)" % (message, code)
+  def error(self, driver, message):
+    print >> sys.stderr, "Error from Mesos: %s" % message
 
 
 # Interface for Mesos executor drivers. Users may wish to extend this

Modified: incubator/mesos/trunk/src/sched/sched.cpp
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/src/sched/sched.cpp?rev=1305932&r1=1305931&r2=1305932&view=diff
==============================================================================
--- incubator/mesos/trunk/src/sched/sched.cpp (original)
+++ incubator/mesos/trunk/src/sched/sched.cpp Tue Mar 27 17:56:23 2012
@@ -78,18 +78,16 @@ class SchedulerProcess : public Protobuf
 public:
   SchedulerProcess(MesosSchedulerDriver* _driver,
                    Scheduler* _scheduler,
-                   const FrameworkID& _frameworkId,
                    const FrameworkInfo& _framework,
                    pthread_mutex_t* _mutex,
                    pthread_cond_t* _cond)
     : driver(_driver),
       scheduler(_scheduler),
-      frameworkId(_frameworkId),
       framework(_framework),
       mutex(_mutex),
       cond(_cond),
       master(UPID()),
-      failover(!(_frameworkId == "")),
+      failover(_framework.has_id() && !framework.id().value().empty()),
       connected(false),
       aborted(false)
   {
@@ -137,7 +135,6 @@ public:
 
     install<FrameworkErrorMessage>(
         &SchedulerProcess::error,
-        &FrameworkErrorMessage::code,
         &FrameworkErrorMessage::message);
   }
 
@@ -183,7 +180,8 @@ protected:
 
     VLOG(1) << "Framework registered with " << frameworkId;
 
-    this->frameworkId = frameworkId;
+    framework.mutable_id()->MergeFrom(frameworkId);
+
     connected = true;
     failover = false;
 
@@ -206,7 +204,7 @@ protected:
 
     VLOG(1) << "Framework re-registered with " << frameworkId;
 
-    CHECK(this->frameworkId == frameworkId);
+    CHECK(framework.id() == frameworkId);
 
     connected = true;
     failover = false;
@@ -220,7 +218,7 @@ protected:
       return;
     }
 
-    if (frameworkId == "") {
+    if (!framework.has_id() || framework.id() == "") {
       // Touched for the very first time.
       RegisterFrameworkMessage message;
       message.mutable_framework()->MergeFrom(framework);
@@ -229,7 +227,6 @@ protected:
       // Not the first time, or failing over.
       ReregisterFrameworkMessage message;
       message.mutable_framework()->MergeFrom(framework);
-      message.mutable_framework_id()->MergeFrom(frameworkId);
       message.set_failover(failover);
       send(master, message);
     }
@@ -295,7 +292,7 @@ protected:
             << " of framework " << update.framework_id()
             << " is now in state " << status.state();
 
-    CHECK(frameworkId == update.framework_id());
+    CHECK(framework.id() == update.framework_id());
 
     // TODO(benh): Note that this maybe a duplicate status update!
     // Once we get support to try and have a more consistent view
@@ -315,7 +312,7 @@ protected:
       // since this way the message might get resent/routed after the
       // scheduler comes back online).
       StatusUpdateAcknowledgementMessage message;
-      message.mutable_framework_id()->MergeFrom(frameworkId);
+      message.mutable_framework_id()->MergeFrom(framework.id());
       message.mutable_slave_id()->MergeFrom(update.slave_id());
       message.mutable_task_id()->MergeFrom(status.task_id());
       message.set_uuid(update.uuid());
@@ -352,18 +349,18 @@ protected:
     scheduler->frameworkMessage(driver, executorId, slaveId, data);
   }
 
-  void error(int32_t code, const string& message)
+  void error(const string& message)
   {
     if (aborted) {
       VLOG(1) << "Ignoring error message because the driver is aborted!";
       return;
     }
 
-    VLOG(1) << "Got error '" << message << "' (code: " << code << ")";
+    VLOG(1) << "Got error '" << message << "'";
 
     driver->abort();
 
-    scheduler->error(driver, code, message);
+    scheduler->error(driver, message);
   }
 
   void stop(bool failover)
@@ -376,7 +373,7 @@ protected:
 
     if (connected && !failover) {
       UnregisterFrameworkMessage message;
-      message.mutable_framework_id()->MergeFrom(frameworkId);
+      message.mutable_framework_id()->MergeFrom(framework.id());
       send(master, message);
     }
 
@@ -401,10 +398,8 @@ protected:
       return;
     }
 
-    VLOG(1) << "Deactivating the framework " << frameworkId;
-
     DeactivateFrameworkMessage message;
-    message.mutable_framework_id()->MergeFrom(frameworkId);
+    message.mutable_framework_id()->MergeFrom(framework.id());
     send(master, message);
 
     Lock lock(mutex);
@@ -419,7 +414,7 @@ protected:
     }
 
     KillTaskMessage message;
-    message.mutable_framework_id()->MergeFrom(frameworkId);
+    message.mutable_framework_id()->MergeFrom(framework.id());
     message.mutable_task_id()->MergeFrom(taskId);
     send(master, message);
   }
@@ -432,7 +427,7 @@ protected:
     }
 
     ResourceRequestMessage message;
-    message.mutable_framework_id()->MergeFrom(frameworkId);
+    message.mutable_framework_id()->MergeFrom(framework.id());
     foreach (const Request& request, requests) {
       message.add_requests()->MergeFrom(request);
     }
@@ -455,7 +450,7 @@ protected:
       // should be solved by the replicated log and timeouts.
       foreach (const TaskInfo& task, tasks) {
         StatusUpdate update;
-        update.mutable_framework_id()->MergeFrom(frameworkId);
+        update.mutable_framework_id()->MergeFrom(framework.id());
         TaskStatus* status = update.mutable_status();
         status->mutable_task_id()->MergeFrom(task.task_id());
         status->set_state(TASK_LOST);
@@ -473,7 +468,7 @@ protected:
     foreach (const TaskInfo& task, tasks) {
       if (task.has_executor() == task.has_command()) {
         StatusUpdate update;
-        update.mutable_framework_id()->MergeFrom(frameworkId);
+        update.mutable_framework_id()->MergeFrom(framework.id());
         TaskStatus* status = update.mutable_status();
         status->mutable_task_id()->MergeFrom(task.task_id());
         status->set_state(TASK_LOST);
@@ -487,7 +482,7 @@ protected:
     }
 
     LaunchTasksMessage message;
-    message.mutable_framework_id()->MergeFrom(frameworkId);
+    message.mutable_framework_id()->MergeFrom(framework.id());
     message.mutable_offer_id()->MergeFrom(offerId);
     message.mutable_filters()->MergeFrom(filters);
 
@@ -522,7 +517,7 @@ protected:
     }
 
     ReviveOffersMessage message;
-    message.mutable_framework_id()->MergeFrom(frameworkId);
+    message.mutable_framework_id()->MergeFrom(framework.id());
     send(master, message);
   }
 
@@ -550,7 +545,7 @@ protected:
 
       FrameworkToExecutorMessage message;
       message.mutable_slave_id()->MergeFrom(slaveId);
-      message.mutable_framework_id()->MergeFrom(frameworkId);
+      message.mutable_framework_id()->MergeFrom(framework.id());
       message.mutable_executor_id()->MergeFrom(executorId);
       message.set_data(data);
       send(slave, message);
@@ -560,7 +555,7 @@ protected:
 
       FrameworkToExecutorMessage message;
       message.mutable_slave_id()->MergeFrom(slaveId);
-      message.mutable_framework_id()->MergeFrom(frameworkId);
+      message.mutable_framework_id()->MergeFrom(framework.id());
       message.mutable_executor_id()->MergeFrom(executorId);
       message.set_data(data);
       send(master, message);
@@ -572,7 +567,6 @@ private:
 
   MesosSchedulerDriver* driver;
   Scheduler* scheduler;
-  FrameworkID frameworkId;
   FrameworkInfo framework;
   pthread_mutex_t* mutex;
   pthread_cond_t* cond;
@@ -603,93 +597,36 @@ private:
 // (2) There is a variable called state, that represents the current
 //     state of the driver and is used to enforce its state transitions.
 
-MesosSchedulerDriver::MesosSchedulerDriver(Scheduler* scheduler,
-                                           const std::string& frameworkName,
-                                           const string& url,
-                                           const FrameworkID& frameworkId)
+MesosSchedulerDriver::MesosSchedulerDriver(
+    Scheduler* _scheduler,
+    const FrameworkInfo& _framework,
+    const string& _master)
+  : scheduler(_scheduler),
+    framework(_framework),
+    master(_master),
+    process(NULL),
+    detector(NULL),
+    status(DRIVER_NOT_STARTED)
 {
-  Configurator configurator;
-  // TODO(benh): Only register local options if this is running with
-  // 'local' or 'localquiet'! Perhaps create a registerOptions for the
-  // scheduler?
-  local::registerOptions(&configurator);
-  Configuration* conf;
-  try {
-    conf = new Configuration(configurator.load());
-  } catch (ConfigurationException& e) {
-    // TODO(benh|matei): Are error callbacks not fatal!?
-    string message = string("Configuration error: ") + e.what();
-    scheduler->error(this, 2, message);
-    conf = new Configuration();
-  }
-  conf->set("url", url); // Override URL param with the one from the user
-  initialize(scheduler, conf, frameworkId, frameworkName);
-}
-
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
 
-MesosSchedulerDriver::MesosSchedulerDriver(Scheduler* scheduler,
-                                           const std::string& frameworkName,
-                                           const map<string, string> &params,
-                                           const FrameworkID& frameworkId)
-{
+  // Load the configuration.
   Configurator configurator;
-  // TODO(benh): Only register local options if this is running with
-  // 'local' or 'localquiet'! Perhaps create a registerOptions for the
-  // scheduler?
-  local::registerOptions(&configurator);
-  Configuration* conf;
-  try {
-    conf = new Configuration(configurator.load(params));
-  } catch (ConfigurationException& e) {
-    // TODO(benh|matei): Are error callbacks not fatal?
-    string message = string("Configuration error: ") + e.what();
-    scheduler->error(this, 2, message);
-    conf = new Configuration();
-  }
-  initialize(scheduler, conf, frameworkId, frameworkName);
-}
 
+  if (master == "local" || master == "localquiet") {
+    local::registerOptions(&configurator);
+  }
 
-MesosSchedulerDriver::MesosSchedulerDriver(Scheduler* scheduler,
-                                           const std::string& frameworkName,
-                                           int argc,
-                                           char** argv,
-                                           const FrameworkID& frameworkId)
-{
-  Configurator configurator;
-  // TODO(benh): Only register local options if this is running with
-  // 'local' or 'localquiet'! Perhaps create a registerOptions for the
-  // scheduler?
-  local::registerOptions(&configurator);
-  Configuration* conf;
   try {
-    conf = new Configuration(configurator.load(argc, argv));
+    conf = new Configuration(configurator.load());
   } catch (ConfigurationException& e) {
+    status = DRIVER_ABORTED;
     string message = string("Configuration error: ") + e.what();
-    scheduler->error(this, 2, message);
-    conf = new Configuration();
+    scheduler->error(this, message);
+    return;
   }
-  initialize(scheduler, conf, frameworkId, frameworkName);
-}
 
-
-void MesosSchedulerDriver::initialize(Scheduler* _scheduler,
-                                      Configuration* _conf,
-                                      const FrameworkID& _frameworkId,
-                                      const std::string& _frameworkName)
-{
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  scheduler = _scheduler;
-  conf = _conf;
-  frameworkId = _frameworkId;
-  frameworkName = _frameworkName;
-  url = conf->get<string>("url", "local");
-  process = NULL;
-  detector = NULL;
-  status = DRIVER_NOT_STARTED;
-
-  // Create mutex and condition variable
+  // Initialize mutex and condition variable.
   pthread_mutexattr_t attr;
   pthread_mutexattr_init(&attr);
   pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
@@ -738,7 +675,7 @@ MesosSchedulerDriver::~MesosSchedulerDri
   delete conf;
 
   // Check and see if we need to shutdown a local cluster.
-  if (url == "local" || url == "localquiet") {
+  if (master == "local" || master == "localquiet") {
     local::shutdown();
   }
 }
@@ -752,30 +689,32 @@ Status MesosSchedulerDriver::start()
     return status;
   }
 
-  // Set up framework info.
-  FrameworkInfo framework;
-  framework.set_user(utils::os::user());
-  framework.set_name(frameworkName);
+  // TODO(benh): Check the user the framework wants to run tasks as,
+  // see if the current user can switch to that user, or via an
+  // authentication module ensure this is acceptable.
+
+  // If no user specified, just use the current user.
+  if (framework.user() == "") {
+    framework.set_user(utils::os::user());
+  }
 
   CHECK(process == NULL);
 
   // TODO(benh): Consider using a libprocess Latch rather than a
   // pthread mutex and condition variable for signaling.
-  process = new SchedulerProcess(this, scheduler, frameworkId,
-                                 framework, &mutex, &cond);
+  process = new SchedulerProcess(this, scheduler, framework, &mutex, &cond);
 
-  UPID pid = spawn(process);
+  spawn(process);
 
-  // Check and see if we need to launch a local cluster.
-  if (url == "local") {
-    const PID<master::Master>& master = local::launch(*conf);
-    detector = new BasicMasterDetector(master, pid);
-  } else if (url == "localquiet") {
+  // Launch a local cluster if necessary.
+  if (master == "local") {
+    detector = new BasicMasterDetector(local::launch(*conf), process->self());
+  } else if (master == "localquiet") {
     conf->set("quiet", 1);
-    const PID<master::Master>& master = local::launch(*conf);
-    detector = new BasicMasterDetector(master, pid);
+    detector = new BasicMasterDetector(local::launch(*conf), process->self());
   } else {
-    detector = MasterDetector::create(url, pid, false, false);
+    detector =
+      MasterDetector::create(master, process->self(), false, false).get();
   }
 
   return status = DRIVER_RUNNING;

Modified: incubator/mesos/trunk/src/slave/main.cpp
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/src/slave/main.cpp?rev=1305932&r1=1305931&r2=1305932&view=diff
==============================================================================
--- incubator/mesos/trunk/src/slave/main.cpp (original)
+++ incubator/mesos/trunk/src/slave/main.cpp Tue Mar 27 17:56:23 2012
@@ -16,10 +16,11 @@
  * limitations under the License.
  */
 
-#include <libgen.h>
+#include <libgen.h> // For chdir.
 
 #include "common/build.hpp"
 #include "common/logging.hpp"
+#include "common/try.hpp"
 
 #include "configurator/configurator.hpp"
 
@@ -39,13 +40,7 @@ using std::string;
 
 void usage(const char *programName, const Configurator& configurator)
 {
-  cerr << "Usage: " << programName
-       << " --master=URL [...]" << endl
-       << endl
-       << "URL may be one of:" << endl
-       << "  mesos://id@host:port" << endl
-       << "  zoo://host1:port1,host2:port2,..." << endl
-       << "  zoofile://file where file contains a host:port pair per line"
+  cerr << "Usage: " << programName << " [...]" << endl
        << endl
        << endl
        << "Supported options:" << endl
@@ -60,13 +55,24 @@ int main(int argc, char** argv)
   Configurator configurator;
   Logging::registerOptions(&configurator);
   Slave::registerOptions(&configurator);
+
+  // The following options are executable specific (e.g., since we
+  // only have one instance of libprocess per execution, we only want
+  // to advertise the port and ip option once, here).
   configurator.addOption<int>("port", 'p', "Port to listen on", 0);
   configurator.addOption<string>("ip", "IP address to listen on");
-  configurator.addOption<string>("master", 'm', "Master URL");
-  configurator.addOption<string>("isolation", 'i', "Isolation module name", "process");
+  configurator.addOption<string>("isolation", "Isolation module", "process");
 #ifdef MESOS_WEBUI
-  configurator.addOption<int>("webui_port", 'w', "Web UI port", 8081);
+  configurator.addOption<int>("webui_port", "Web UI port", 8081);
 #endif
+  configurator.addOption<string>(
+      "master",
+      'm',
+      "May be one of:\n"
+      "  host:port\n"
+      "  zk://host1:port1,host2:port2,.../path\n"
+      "  zk://username:password@host1:port1,host2:port2,.../path\n"
+      "  file://path/to/file (where file contains one of the above)");
 
   if (argc == 2 && string("--help") == argv[1]) {
     usage(argv[0], configurator);
@@ -95,9 +101,10 @@ int main(int argc, char** argv)
   process::initialize(false);
 
   if (!conf.contains("master")) {
-    cerr << "Master URL argument (--master) required." << endl;
+    cerr << "Missing required option --master (-m)" << endl;
     exit(1);
   }
+
   string master = conf["master"];
 
   string isolation = conf["isolation"];
@@ -119,11 +126,11 @@ int main(int argc, char** argv)
   Slave* slave = new Slave(conf, false, isolationModule);
   process::spawn(slave);
 
-  MasterDetector* detector = MasterDetector::create(
-      master,
-      slave->self(),
-      false,
-      Logging::isQuiet(conf));
+  Try<MasterDetector*> detector =
+    MasterDetector::create(master, slave->self(), false, Logging::isQuiet(conf));
+
+  CHECK(detector.isSome())
+    << "Failed to create a master detector: " << detector.error();
 
 #ifdef MESOS_WEBUI
   webui::start(slave->self(), conf);
@@ -132,7 +139,7 @@ int main(int argc, char** argv)
   process::wait(slave->self());
   delete slave;
 
-  MasterDetector::destroy(detector);
+  MasterDetector::destroy(detector.get());
   IsolationModule::destroy(isolationModule);
 
   return 0;

Modified: incubator/mesos/trunk/src/slave/slave.cpp
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/src/slave/slave.cpp?rev=1305932&r1=1305931&r2=1305932&view=diff
==============================================================================
--- incubator/mesos/trunk/src/slave/slave.cpp (original)
+++ incubator/mesos/trunk/src/slave/slave.cpp Tue Mar 27 17:56:23 2012
@@ -157,7 +157,7 @@ void Slave::registerOptions(Configurator
 
 void Slave::initialize()
 {
-  LOG(INFO) << "Slave started at " << self();
+  LOG(INFO) << "Slave started on " << string(self()).substr(6);
   LOG(INFO) << "Slave resources: " << resources;
 
   // Determine our hostname.
@@ -345,6 +345,7 @@ void Slave::registered(const SlaveID& sl
 {
   LOG(INFO) << "Registered with master; given slave ID " << slaveId;
   id = slaveId;
+
   connected = true;
 }
 

Copied: incubator/mesos/trunk/src/tests/attributes_tests.cpp (from r1305901, incubator/mesos/trunk/src/tests/attributes_test.cpp)
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/src/tests/attributes_tests.cpp?p2=incubator/mesos/trunk/src/tests/attributes_tests.cpp&p1=incubator/mesos/trunk/src/tests/attributes_test.cpp&r1=1305901&r2=1305932&rev=1305932&view=diff
==============================================================================
    (empty)

Modified: incubator/mesos/trunk/src/tests/exception_tests.cpp
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/src/tests/exception_tests.cpp?rev=1305932&r1=1305931&r2=1305932&view=diff
==============================================================================
--- incubator/mesos/trunk/src/tests/exception_tests.cpp (original)
+++ incubator/mesos/trunk/src/tests/exception_tests.cpp Tue Mar 27 17:56:23 2012
@@ -73,7 +73,7 @@ TEST(ExceptionTest, DeactiveFrameworkOnA
 
   MockScheduler sched;
 
-  MesosSchedulerDriver driver(&sched, "", master);
+  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master);
 
   trigger schedRegisteredCall;
 
@@ -114,7 +114,7 @@ TEST(ExceptionTest, DisallowSchedulerAct
 
   MockScheduler sched;
 
-  MesosSchedulerDriver driver(&sched, "", master);
+  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master);
 
   trigger schedRegisteredCall;
 
@@ -154,7 +154,7 @@ TEST(ExceptionTest, DisallowSchedulerCal
 
   MockScheduler sched;
 
-  MesosSchedulerDriver driver(&sched, "", master);
+  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master);
 
   EXPECT_CALL(sched, registered(&driver, _, _))
     .Times(1);
@@ -180,7 +180,7 @@ TEST(ExceptionTest, DisallowSchedulerCal
   EXPECT_CALL(sched, slaveLost(&driver, _))
       .Times(0);
 
-  EXPECT_CALL(sched, error(&driver, _, _))
+  EXPECT_CALL(sched, error(&driver, _))
       .Times(0);
 
   process::Message message;

Modified: incubator/mesos/trunk/src/tests/fault_tolerance_tests.cpp
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/src/tests/fault_tolerance_tests.cpp?rev=1305932&r1=1305931&r2=1305932&view=diff
==============================================================================
--- incubator/mesos/trunk/src/tests/fault_tolerance_tests.cpp (original)
+++ incubator/mesos/trunk/src/tests/fault_tolerance_tests.cpp Tue Mar 27 17:56:23 2012
@@ -84,7 +84,7 @@ TEST(FaultToleranceTest, SlaveLost)
   BasicMasterDetector detector(master, slave, true);
 
   MockScheduler sched;
-  MesosSchedulerDriver driver(&sched, "", master);
+  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master);
 
   vector<Offer> offers;
 
@@ -153,7 +153,7 @@ TEST(FaultToleranceTest, SlavePartitione
   PID<Master> master = local::launch(1, 2, 1 * Gigabyte, false);
 
   MockScheduler sched;
-  MesosSchedulerDriver driver(&sched, "", master);
+  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master);
 
   trigger resourceOffersCall, slaveLostCall;
 
@@ -205,7 +205,7 @@ TEST(FaultToleranceTest, SchedulerFailov
   // scheduler.
 
   MockScheduler sched1;
-  MesosSchedulerDriver driver1(&sched1, "", master);
+  MesosSchedulerDriver driver1(&sched1, DEFAULT_FRAMEWORK_INFO, master);
 
   FrameworkID frameworkId;
 
@@ -220,7 +220,7 @@ TEST(FaultToleranceTest, SchedulerFailov
   EXPECT_CALL(sched1, offerRescinded(&driver1, _))
     .Times(AtMost(1));
 
-  EXPECT_CALL(sched1, error(&driver1, _, "Framework failed over"))
+  EXPECT_CALL(sched1, error(&driver1, "Framework failed over"))
     .Times(1);
 
   driver1.start();
@@ -232,7 +232,11 @@ TEST(FaultToleranceTest, SchedulerFailov
   // gets a registered callback..
 
   MockScheduler sched2;
-  MesosSchedulerDriver driver2(&sched2, "", master, frameworkId);
+
+  FrameworkInfo framework2 = DEFAULT_FRAMEWORK_INFO;
+  framework2.mutable_id()->MergeFrom(frameworkId);
+
+  MesosSchedulerDriver driver2(&sched2, framework2, master);
 
   trigger sched2RegisteredCall;
 
@@ -274,7 +278,7 @@ TEST(FaultToleranceTest, FrameworkReliab
   PID<Master> master = local::launch(1, 2, 1 * Gigabyte, false);
 
   MockScheduler sched;
-  MesosSchedulerDriver driver(&sched, "", master);
+  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master);
 
   trigger schedRegisteredCall;
 
@@ -327,7 +331,7 @@ TEST(FaultToleranceTest, FrameworkReregi
   PID<Master> master = local::launch(1, 2, 1 * Gigabyte, false);
 
   MockScheduler sched;
-  MesosSchedulerDriver driver(&sched, "", master);
+  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master);
 
   trigger schedRegisteredCall, schedReregisteredCall;
 
@@ -414,7 +418,7 @@ TEST(FaultToleranceTest, DISABLED_TaskLo
   BasicMasterDetector detector(master, slave, true);
 
   MockScheduler sched;
-  MesosSchedulerDriver driver(&sched, "", master);
+  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master);
   vector<Offer> offers;
   trigger statusUpdateCall, resourceOffersCall;
   TaskStatus status;
@@ -524,7 +528,7 @@ TEST(FaultToleranceTest, SchedulerFailov
   // first status update message is sent to it (drop the message).
 
   MockScheduler sched1;
-  MesosSchedulerDriver driver1(&sched1, "", master);
+  MesosSchedulerDriver driver1(&sched1, DEFAULT_FRAMEWORK_INFO, master);
 
   FrameworkID frameworkId;
   vector<Offer> offers;
@@ -542,7 +546,7 @@ TEST(FaultToleranceTest, SchedulerFailov
   EXPECT_CALL(sched1, statusUpdate(&driver1, _))
     .Times(0);
 
-  EXPECT_CALL(sched1, error(&driver1, _, "Framework failed over"))
+  EXPECT_CALL(sched1, error(&driver1, "Framework failed over"))
     .Times(1);
 
   EXPECT_MESSAGE(filter, Eq(StatusUpdateMessage().GetTypeName()), _,
@@ -576,7 +580,11 @@ TEST(FaultToleranceTest, SchedulerFailov
   // timeout to kick in and another status update message is sent.
 
   MockScheduler sched2;
-  MesosSchedulerDriver driver2(&sched2, "", master, frameworkId);
+
+  FrameworkInfo framework2 = DEFAULT_FRAMEWORK_INFO;
+  framework2.mutable_id()->MergeFrom(frameworkId);
+
+  MesosSchedulerDriver driver2(&sched2, framework2, master);
 
   trigger registeredCall, statusUpdateCall;
 
@@ -649,7 +657,7 @@ TEST(FaultToleranceTest, SchedulerFailov
 
   MockScheduler sched1;
 
-  MesosSchedulerDriver driver1(&sched1, "", master);
+  MesosSchedulerDriver driver1(&sched1, DEFAULT_FRAMEWORK_INFO, master);
 
   FrameworkID frameworkId;
 
@@ -667,7 +675,7 @@ TEST(FaultToleranceTest, SchedulerFailov
                     Trigger(&sched1ResourceOfferCall)))
     .WillRepeatedly(Return());
 
-  EXPECT_CALL(sched1, error(&driver1, _, "Framework failed over"))
+  EXPECT_CALL(sched1, error(&driver1, "Framework failed over"))
     .Times(1);
 
   driver1.start();
@@ -693,7 +701,11 @@ TEST(FaultToleranceTest, SchedulerFailov
   EXPECT_EQ(TASK_RUNNING, status.state());
 
   MockScheduler sched2;
-  MesosSchedulerDriver driver2(&sched2, "", master, frameworkId);
+
+  FrameworkInfo framework2 = DEFAULT_FRAMEWORK_INFO;
+  framework2.mutable_id()->MergeFrom(frameworkId);
+
+  MesosSchedulerDriver driver2(&sched2, framework2, master);
 
   trigger sched2RegisteredCall, sched2FrameworkMessageCall;
 
@@ -758,7 +770,7 @@ TEST(FaultToleranceTest, SlaveReliableRe
   BasicMasterDetector detector(master, slave, true);
 
   MockScheduler sched;
-  MesosSchedulerDriver driver(&sched, "", master);
+  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master);
 
   trigger resourceOffersCall;
 
@@ -816,7 +828,7 @@ TEST(FaultToleranceTest, SlaveReregister
   BasicMasterDetector detector(master, slave, true);
 
   MockScheduler sched;
-  MesosSchedulerDriver driver(&sched, "", master);
+  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master);
 
   trigger resourceOffersCall;
 

Added: incubator/mesos/trunk/src/tests/master_detector_tests.cpp
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/src/tests/master_detector_tests.cpp?rev=1305932&view=auto
==============================================================================
--- incubator/mesos/trunk/src/tests/master_detector_tests.cpp (added)
+++ incubator/mesos/trunk/src/tests/master_detector_tests.cpp Tue Mar 27 17:56:23 2012
@@ -0,0 +1,117 @@
+/**
+ * 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.
+ */
+
+#include <gmock/gmock.h>
+
+#include <fstream>
+#include <map>
+#include <string>
+#include <vector>
+
+#include <mesos/executor.hpp>
+#include <mesos/scheduler.hpp>
+
+#include "common/try.hpp"
+
+#include "detector/detector.hpp"
+
+#include "master/master.hpp"
+#include "master/simple_allocator.hpp"
+
+#include "slave/slave.hpp"
+
+#include "tests/utils.hpp"
+
+using namespace mesos;
+using namespace mesos::internal;
+using namespace mesos::internal::test;
+
+using mesos::internal::master::Master;
+using mesos::internal::master::SimpleAllocator;
+
+using mesos::internal::slave::Slave;
+
+using process::PID;
+using process::UPID;
+
+using std::map;
+using std::vector;
+
+using testing::_;
+
+TEST(MasterDetector, File)
+{
+  ASSERT_TRUE(GTEST_IS_THREADSAFE);
+
+  SimpleAllocator a;
+  Master m(&a);
+  PID<Master> master = process::spawn(&m);
+
+  map<ExecutorID, Executor*> execs;
+
+  TestingIsolationModule isolationModule(execs);
+
+  Resources resources = Resources::parse("cpus:2;mem:1024");
+
+  Slave s(resources, true, &isolationModule);
+  PID<Slave> slave = process::spawn(&s);
+
+  // Write "master" to a file and use the "file://" mechanism to
+  // create a master detector for the slave. Still requires a master
+  // detector for the master first. TODO(benh): We should really make
+  // a utility for creating temporary files/directories.
+
+  BasicMasterDetector detector1(master, vector<UPID>(), true);
+
+  std::string path = "/tmp/mesos-tests_" + UUID::random().toString();
+  std::ofstream file(path.c_str());
+  ASSERT_TRUE(file.is_open());
+  file << master << std::endl;
+  file.close();
+
+  Try<MasterDetector*> detector2 =
+    MasterDetector::create("file://" + path, slave, false, true);
+
+  utils::os::rm(path);
+
+  ASSERT_TRUE(detector2.isSome());
+
+  MockScheduler sched;
+  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master);
+
+  trigger resourceOffersCall;
+
+  EXPECT_CALL(sched, registered(&driver, _, _))
+    .Times(1);
+
+  EXPECT_CALL(sched, resourceOffers(&driver, _))
+    .WillOnce(Trigger(&resourceOffersCall));
+
+  driver.start();
+
+  WAIT_UNTIL(resourceOffersCall);
+
+  driver.stop();
+  driver.join();
+
+  process::terminate(slave);
+  process::wait(slave);
+
+  process::terminate(master);
+  process::wait(master);
+}

Modified: incubator/mesos/trunk/src/tests/master_tests.cpp
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/src/tests/master_tests.cpp?rev=1305932&r1=1305931&r2=1305932&view=diff
==============================================================================
--- incubator/mesos/trunk/src/tests/master_tests.cpp (original)
+++ incubator/mesos/trunk/src/tests/master_tests.cpp Tue Mar 27 17:56:23 2012
@@ -98,7 +98,7 @@ TEST(MasterTest, TaskRunning)
   BasicMasterDetector detector(master, slave, true);
 
   MockScheduler sched;
-  MesosSchedulerDriver driver(&sched, "", master);
+  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master);
 
   vector<Offer> offers;
   TaskStatus status;
@@ -194,7 +194,7 @@ TEST(MasterTest, KillTask)
   BasicMasterDetector detector(master, slave, true);
 
   MockScheduler sched;
-  MesosSchedulerDriver driver(&sched, "", master);
+  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master);
 
   vector<Offer> offers;
   TaskStatus status;
@@ -298,7 +298,7 @@ TEST(MasterTest, FrameworkMessage)
   // first status update message is sent to it (drop the message).
 
   MockScheduler sched;
-  MesosSchedulerDriver schedDriver(&sched, "", master);
+  MesosSchedulerDriver schedDriver(&sched, DEFAULT_FRAMEWORK_INFO, master);
 
   vector<Offer> offers;
   TaskStatus status;
@@ -432,7 +432,7 @@ TEST(MasterTest, MultipleExecutors)
   BasicMasterDetector detector(master, slave, true);
 
   MockScheduler sched;
-  MesosSchedulerDriver driver(&sched, "", master);
+  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master);
 
   vector<Offer> offers;
   TaskStatus status1, status2;
@@ -540,7 +540,8 @@ TEST(MasterTest, MasterInfo)
   BasicMasterDetector detector(master, slave, true);
 
   MockScheduler sched;
-  MesosSchedulerDriver driver(&sched, "", master);
+  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master);
+
   MasterInfo masterInfo;
 
   trigger registeredCall;
@@ -601,7 +602,8 @@ TEST(MasterTest, MasterInfoOnReElection)
   BasicMasterDetector detector(master, slave, true);
 
   MockScheduler sched;
-  MesosSchedulerDriver driver(&sched, "", master);
+  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master);
+
   MasterInfo masterInfo;
 
   trigger registeredCall, reregisteredCall;
@@ -693,7 +695,8 @@ TEST(MasterTest, MasterLost)
   BasicMasterDetector detector(master, slave, true);
 
   MockScheduler sched;
-  MesosSchedulerDriver driver(&sched, "", master);
+  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master);
+
   MasterInfo masterInfo;
 
   trigger registeredCall, masterLostCall;

Modified: incubator/mesos/trunk/src/tests/resource_offers_tests.cpp
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/src/tests/resource_offers_tests.cpp?rev=1305932&r1=1305931&r2=1305932&view=diff
==============================================================================
--- incubator/mesos/trunk/src/tests/resource_offers_tests.cpp (original)
+++ incubator/mesos/trunk/src/tests/resource_offers_tests.cpp Tue Mar 27 17:56:23 2012
@@ -66,7 +66,7 @@ TEST(ResourceOffersTest, ResourceOfferWi
   PID<Master> master = local::launch(10, 2, 1 * Gigabyte, false);
 
   MockScheduler sched;
-  MesosSchedulerDriver driver(&sched, "", master);
+  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master);
 
   vector<Offer> offers;
 
@@ -108,7 +108,7 @@ TEST(ResourceOffersTest, TaskUsesNoResou
   PID<Master> master = local::launch(1, 2, 1 * Gigabyte, false);
 
   MockScheduler sched;
-  MesosSchedulerDriver driver(&sched, "", master);
+  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master);
 
   vector<Offer> offers;
 
@@ -168,7 +168,7 @@ TEST(ResourceOffersTest, TaskUsesInvalid
   PID<Master> master = local::launch(1, 2, 1 * Gigabyte, false);
 
   MockScheduler sched;
-  MesosSchedulerDriver driver(&sched, "", master);
+  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master);
 
   vector<Offer> offers;
 
@@ -233,7 +233,7 @@ TEST(ResourceOffersTest, TaskUsesMoreRes
   PID<Master> master = local::launch(1, 2, 1 * Gigabyte, false);
 
   MockScheduler sched;
-  MesosSchedulerDriver driver(&sched, "", master);
+  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master);
 
   vector<Offer> offers;
 
@@ -298,7 +298,7 @@ TEST(ResourceOffersTest, ResourcesGetReo
   PID<Master> master = local::launch(1, 2, 1 * Gigabyte, false);
 
   MockScheduler sched1;
-  MesosSchedulerDriver driver1(&sched1, "", master);
+  MesosSchedulerDriver driver1(&sched1, DEFAULT_FRAMEWORK_INFO, master);
 
   vector<Offer> offers;
 
@@ -326,7 +326,7 @@ TEST(ResourceOffersTest, ResourcesGetReo
   driver1.join();
 
   MockScheduler sched2;
-  MesosSchedulerDriver driver2(&sched2, "", master);
+  MesosSchedulerDriver driver2(&sched2, DEFAULT_FRAMEWORK_INFO, master);
 
   trigger sched2ResourceOfferCall;
 
@@ -358,7 +358,7 @@ TEST(ResourceOffersTest, ResourcesGetReo
   PID<Master> master = local::launch(1, 2, 1 * Gigabyte, false);
 
   MockScheduler sched1;
-  MesosSchedulerDriver driver1(&sched1, "", master);
+  MesosSchedulerDriver driver1(&sched1, DEFAULT_FRAMEWORK_INFO, master);
 
   vector<Offer> offers;
 
@@ -418,7 +418,7 @@ TEST(ResourceOffersTest, ResourcesGetReo
   driver1.join();
 
   MockScheduler sched2;
-  MesosSchedulerDriver driver2(&sched2, "", master);
+  MesosSchedulerDriver driver2(&sched2, DEFAULT_FRAMEWORK_INFO, master);
 
   trigger sched2ResourceOffersCall;
 
@@ -477,7 +477,7 @@ TEST(ResourceOffersTest, Request)
 
   PID<Master> master = local::launch(1, 2, 1 * Gigabyte, false, &allocator);
 
-  MesosSchedulerDriver driver(&sched, "", master);
+  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master);
 
   trigger registeredCall;
 
@@ -549,7 +549,7 @@ TEST(ResourceOffersTest, TasksExecutorIn
   BasicMasterDetector detector(master, slave, true);
 
   MockScheduler sched;
-  MesosSchedulerDriver driver(&sched, "", master);
+  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master);
 
   vector<Offer> offers;
 

Modified: incubator/mesos/trunk/src/tests/utils.hpp
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/src/tests/utils.hpp?rev=1305932&r1=1305931&r2=1305932&view=diff
==============================================================================
--- incubator/mesos/trunk/src/tests/utils.hpp (original)
+++ incubator/mesos/trunk/src/tests/utils.hpp Tue Mar 27 17:56:23 2012
@@ -80,8 +80,7 @@ void enterTestDirectory(const char* test
 
 
 /**
- * Macros to get a "default" ExecutorInfo object for testing or create
- * one out of an ExecutorID and command.
+ * Macros to get/create (default) ExecutorInfos and FrameworkInfos.
  */
 #define DEFAULT_EXECUTOR_INFO                                           \
       ({ ExecutorInfo executor;                                         \
@@ -97,6 +96,12 @@ void enterTestDirectory(const char* test
         executor; })
 
 
+#define DEFAULT_FRAMEWORK_INFO                                          \
+     ({ FrameworkInfo framework;                                        \
+        framework.set_name("default");                                  \
+        framework; })
+
+
 #define DEFAULT_EXECUTOR_ID						\
       DEFAULT_EXECUTOR_INFO.executor_id()
 
@@ -119,13 +124,13 @@ public:
                                       const ExecutorID&,
                                       const SlaveID&,
                                       const std::string&));
-  MOCK_METHOD2(slaveLost, void(SchedulerDriver*, const SlaveID&));
-  MOCK_METHOD3(error, void(SchedulerDriver*, int, const std::string&));
   MOCK_METHOD1(masterLost, void(SchedulerDriver*));
+  MOCK_METHOD2(slaveLost, void(SchedulerDriver*, const SlaveID&));
   MOCK_METHOD4(executorLost, void(SchedulerDriver*,
                                   const ExecutorID&,
                                   const SlaveID&,
                                   int));
+  MOCK_METHOD2(error, void(SchedulerDriver*, const std::string&));
 };
 
 
@@ -146,7 +151,7 @@ public:
   MOCK_METHOD2(frameworkMessage, void(ExecutorDriver*, const std::string&));
   MOCK_METHOD1(slaveLost, void(ExecutorDriver*));
   MOCK_METHOD1(shutdown, void(ExecutorDriver*));
-  MOCK_METHOD3(error, void(ExecutorDriver*, int, const std::string&));
+  MOCK_METHOD2(error, void(ExecutorDriver*, const std::string&));
 };
 
 

Added: incubator/mesos/trunk/src/tests/zookeeper_url_tests.cpp
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/src/tests/zookeeper_url_tests.cpp?rev=1305932&view=auto
==============================================================================
--- incubator/mesos/trunk/src/tests/zookeeper_url_tests.cpp (added)
+++ incubator/mesos/trunk/src/tests/zookeeper_url_tests.cpp Tue Mar 27 17:56:23 2012
@@ -0,0 +1,74 @@
+/**
+ * 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.
+ */
+
+#include <gtest/gtest.h>
+
+#include "common/try.hpp"
+
+#include "zookeeper/url.hpp"
+
+TEST(ZooKeeper, URL)
+{
+  Try<zookeeper::URL> url =
+    zookeeper::URL::parse("zk://host1:port1");
+  EXPECT_FALSE(url.isError());
+  EXPECT_TRUE(url.get().authentication.isNone());
+  EXPECT_EQ("host1:port1", url.get().servers);
+  EXPECT_EQ("/", url.get().path);
+
+  url = zookeeper::URL::parse("zk://jake:1@host1:port1");
+  EXPECT_FALSE(url.isError());
+  EXPECT_FALSE(url.get().authentication.isNone());
+  EXPECT_EQ("digest", url.get().authentication.get().scheme);
+  EXPECT_EQ("jake:1", url.get().authentication.get().credentials);
+  EXPECT_EQ("host1:port1", url.get().servers);
+  EXPECT_EQ("/", url.get().path);
+
+  url = zookeeper::URL::parse("zk://jake:1@host1:port1/");
+  EXPECT_FALSE(url.isError());
+  EXPECT_FALSE(url.get().authentication.isNone());
+  EXPECT_EQ("digest", url.get().authentication.get().scheme);
+  EXPECT_EQ("jake:1", url.get().authentication.get().credentials);
+  EXPECT_EQ("host1:port1", url.get().servers);
+  EXPECT_EQ("/", url.get().path);
+
+  url = zookeeper::URL::parse("zk://jake:1@host1:port1,host2:port2");
+  EXPECT_FALSE(url.isError());
+  EXPECT_FALSE(url.get().authentication.isNone());
+  EXPECT_EQ("digest", url.get().authentication.get().scheme);
+  EXPECT_EQ("jake:1", url.get().authentication.get().credentials);
+  EXPECT_EQ("host1:port1,host2:port2", url.get().servers);
+  EXPECT_EQ("/", url.get().path);
+
+  url = zookeeper::URL::parse("zk://jake:1@host1:port1,host2:port2/");
+  EXPECT_FALSE(url.isError());
+  EXPECT_FALSE(url.get().authentication.isNone());
+  EXPECT_EQ("digest", url.get().authentication.get().scheme);
+  EXPECT_EQ("jake:1", url.get().authentication.get().credentials);
+  EXPECT_EQ("host1:port1,host2:port2", url.get().servers);
+  EXPECT_EQ("/", url.get().path);
+
+  url =
+    zookeeper::URL::parse("zk://jake:1@host1:port1,host2:port2/path/to/znode");
+  EXPECT_FALSE(url.isError());
+  EXPECT_FALSE(url.get().authentication.isNone());
+  EXPECT_EQ("digest", url.get().authentication.get().scheme);
+  EXPECT_EQ("jake:1", url.get().authentication.get().credentials);
+  EXPECT_EQ("host1:port1,host2:port2", url.get().servers);
+  EXPECT_EQ("/path/to/znode", url.get().path);
+}

Modified: incubator/mesos/trunk/src/webui/master/index.tpl
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/src/webui/master/index.tpl?rev=1305932&r1=1305931&r2=1305932&view=diff
==============================================================================
--- incubator/mesos/trunk/src/webui/master/index.tpl (original)
+++ incubator/mesos/trunk/src/webui/master/index.tpl Tue Mar 27 17:56:23 2012
@@ -66,14 +66,13 @@
 
 % pid = state['pid'] # master@ip:port
 % _, server = pid.split("@", 1)
-% ip, _ = server.split(":", 1)
+% ip, port = server.split(":", 1)
 % format = "%a %b %d %Y %I:%M:%S %p " + time.strftime("%Z", time.gmtime())
 % start_local = datetime.fromtimestamp(state['start_time']).strftime(format)
 % start_utc = datetime.utcfromtimestamp(state['start_time']).isoformat(' ')
 
 <p>
-  Server: {{HOSTNAME}} ({{ip}})<br />
-  PID: {{state['pid']}}<br />
+  Server: {{HOSTNAME}}:{{port}} ({{ip}}:{{port}})<br />
   Built: {{state['build_date']}} by {{state['build_user']}}<br />
   Started: {{start_local}} ({{start_utc}} UTC)<br />
   ID: {{state['id']}}<br />

Modified: incubator/mesos/trunk/src/zookeeper/authentication.hpp
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/src/zookeeper/authentication.hpp?rev=1305932&r1=1305931&r2=1305932&view=diff
==============================================================================
--- incubator/mesos/trunk/src/zookeeper/authentication.hpp (original)
+++ incubator/mesos/trunk/src/zookeeper/authentication.hpp Tue Mar 27 17:56:23 2012
@@ -9,8 +9,14 @@ namespace zookeeper {
 
 struct Authentication
 {
-  std::string scheme;
-  std::string credentials;
+  Authentication(
+      const std::string& _scheme,
+      const std::string& _credentials)
+    : scheme(_scheme),
+      credentials(_credentials) {}
+
+  const std::string scheme;
+  const std::string credentials;
 };
 
 

Added: incubator/mesos/trunk/src/zookeeper/url.hpp
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/src/zookeeper/url.hpp?rev=1305932&view=auto
==============================================================================
--- incubator/mesos/trunk/src/zookeeper/url.hpp (added)
+++ incubator/mesos/trunk/src/zookeeper/url.hpp Tue Mar 27 17:56:23 2012
@@ -0,0 +1,112 @@
+/**
+ * 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.
+ */
+
+#ifndef __ZOOKEEPER_URL_HPP__
+#define __ZOOKEEPER_URL_HPP__
+
+#include <string>
+
+#include "common/option.hpp"
+#include "common/strings.hpp"
+#include "common/try.hpp"
+
+#include "zookeeper/authentication.hpp"
+
+namespace zookeeper {
+
+// Describes a ZooKeeper URL of the form:
+//
+//     zk://username:password@servers/path
+//
+// Where username:password is for the 'digest' scheme (see ZooKeeper
+// documentation regarding "access controls using ACLs") and servers
+// is of the form:
+//
+//     host1:port1,host2:port2,host3:port3
+//
+// Note that in the future we may want to support authentication
+// mechanisms other than 'digest' and have a URL of the following
+// form.
+//
+//     zk://scheme:credentials@servers/path
+class URL
+{
+public:
+  static Try<URL> parse(const std::string& url);
+
+  const Option<Authentication> authentication;
+  const std::string servers;
+  const std::string path;
+
+private:
+  URL(const std::string& _servers,
+      const std::string& _path)
+    : servers(_servers),
+      path(_path) {}
+
+  URL(const std::string& credentials,
+      const std::string& _servers,
+      const std::string& _path)
+    : servers(_servers),
+      path(_path),
+      authentication(Authentication("digest", credentials)) {}
+};
+
+
+inline Try<URL> URL::parse(const std::string& url)
+{
+  std::string s = strings::trim(url);
+
+  size_t index = s.find_first_of("zk://");
+
+  if (index != 0) {
+    return Try<URL>::error("Expecting 'zk://' at the beginning of the URL");
+  }
+
+  s = s.substr(5);
+
+  // Look for the trailing '/' (if any), that's where the path starts.
+  std::string path;
+  do {
+    index = s.find_last_of('/');
+
+    if (index == std::string::npos) {
+      break;
+    } else {
+      path = s.substr(index) + path;
+      s = s.substr(0, index);
+    }
+  } while (true);
+
+  if (path == "") {
+    path = "/";
+  }
+
+  // Look for the trailing '@' (if any), that's where servers starts.
+  index = s.find_last_of('@');
+
+  if (index != std::string::npos) {
+    return URL(s.substr(0, index), s.substr(index + 1), path);
+  } else {
+    return URL(s, path);
+  }
+}
+
+} // namespace zookeeper {
+
+#endif // __ZOOKEEPER_URL_HPP__