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/11/26 22:21:49 UTC

svn commit: r1413856 - in /incubator/mesos/branches/0.11.0/src: Makefile.am common/units.hpp master/constants.hpp master/http.cpp master/master.cpp master/master.hpp slave/constants.hpp slave/http.cpp slave/slave.cpp slave/slave.hpp tests/master_tests.cpp

Author: benh
Date: Mon Nov 26 21:21:48 2012
New Revision: 1413856

URL: http://svn.apache.org/viewvc?rev=1413856&view=rev
Log:
Remove copy constructors from master / slave structs. Zero-copy
manipulation of completed tasks / frameworks / executors.

From: Ben Mahler <be...@gmail.com>
Review: https://reviews.apache.org/r/7845

Modified:
    incubator/mesos/branches/0.11.0/src/Makefile.am
    incubator/mesos/branches/0.11.0/src/common/units.hpp
    incubator/mesos/branches/0.11.0/src/master/constants.hpp
    incubator/mesos/branches/0.11.0/src/master/http.cpp
    incubator/mesos/branches/0.11.0/src/master/master.cpp
    incubator/mesos/branches/0.11.0/src/master/master.hpp
    incubator/mesos/branches/0.11.0/src/slave/constants.hpp
    incubator/mesos/branches/0.11.0/src/slave/http.cpp
    incubator/mesos/branches/0.11.0/src/slave/slave.cpp
    incubator/mesos/branches/0.11.0/src/slave/slave.hpp
    incubator/mesos/branches/0.11.0/src/tests/master_tests.cpp

Modified: incubator/mesos/branches/0.11.0/src/Makefile.am
URL: http://svn.apache.org/viewvc/incubator/mesos/branches/0.11.0/src/Makefile.am?rev=1413856&r1=1413855&r2=1413856&view=diff
==============================================================================
--- incubator/mesos/branches/0.11.0/src/Makefile.am (original)
+++ incubator/mesos/branches/0.11.0/src/Makefile.am Mon Nov 26 21:21:48 2012
@@ -151,18 +151,36 @@ noinst_LTLIBRARIES += libmesos_no_third_
 
 nodist_libmesos_no_third_party_la_SOURCES = $(CXX_PROTOS) $(MESSAGES_PROTOS)
 
-libmesos_no_third_party_la_SOURCES = sched/sched.cpp local/local.cpp	\
+libmesos_no_third_party_la_SOURCES =					\
+	sched/sched.cpp							\
+	local/local.cpp							\
+	master/constants.cpp						\
 	master/drf_sorter.cpp						\
-	master/frameworks_manager.cpp master/http.cpp master/master.cpp	\
-	master/slaves_manager.cpp slave/gc.cpp slave/state.cpp		\
-	slave/slave.cpp slave/http.cpp slave/isolation_module.cpp	\
-	slave/process_based_isolation_module.cpp slave/reaper.cpp	\
-	launcher/launcher.cpp exec/exec.cpp common/lock.cpp		\
-	detector/detector.cpp configurator/configurator.cpp		\
-	common/date_utils.cpp common/resources.cpp			\
-	common/attributes.cpp common/values.cpp files/files.cpp		\
-	logging/logging.cpp zookeeper/zookeeper.cpp			\
-	zookeeper/authentication.cpp zookeeper/group.cpp		\
+	master/frameworks_manager.cpp					\
+	master/http.cpp master/master.cpp				\
+	master/slaves_manager.cpp					\
+	slave/constants.cpp						\
+	slave/gc.cpp							\
+	slave/state.cpp							\
+	slave/slave.cpp							\
+	slave/http.cpp							\
+	slave/isolation_module.cpp					\
+	slave/process_based_isolation_module.cpp			\
+	slave/reaper.cpp						\
+	launcher/launcher.cpp						\
+	exec/exec.cpp							\
+	common/lock.cpp							\
+	detector/detector.cpp						\
+	configurator/configurator.cpp					\
+	common/date_utils.cpp						\
+	common/resources.cpp						\
+	common/attributes.cpp						\
+	common/values.cpp						\
+	files/files.cpp							\
+	logging/logging.cpp						\
+	zookeeper/zookeeper.cpp						\
+	zookeeper/authentication.cpp					\
+	zookeeper/group.cpp						\
 	messages/messages.proto
 
 pkginclude_HEADERS = $(top_srcdir)/include/mesos/executor.hpp	\

Modified: incubator/mesos/branches/0.11.0/src/common/units.hpp
URL: http://svn.apache.org/viewvc/incubator/mesos/branches/0.11.0/src/common/units.hpp?rev=1413856&r1=1413855&r2=1413856&view=diff
==============================================================================
--- incubator/mesos/branches/0.11.0/src/common/units.hpp (original)
+++ incubator/mesos/branches/0.11.0/src/common/units.hpp Mon Nov 26 21:21:48 2012
@@ -19,6 +19,8 @@
 #ifndef __UNITS_HPP__
 #define __UNITS_HPP__
 
+#include <stdint.h>
+
 // const int32_t Byte = 1;
 // const int32_t Kilobyte = 1024 * Byte;
 // const int32_t Megabyte = 1024 * Kilobyte;

Modified: incubator/mesos/branches/0.11.0/src/master/constants.hpp
URL: http://svn.apache.org/viewvc/incubator/mesos/branches/0.11.0/src/master/constants.hpp?rev=1413856&r1=1413855&r2=1413856&view=diff
==============================================================================
--- incubator/mesos/branches/0.11.0/src/master/constants.hpp (original)
+++ incubator/mesos/branches/0.11.0/src/master/constants.hpp Mon Nov 26 21:21:48 2012
@@ -19,6 +19,8 @@
 #ifndef __MASTER_CONSTANTS_HPP__
 #define __MASTER_CONSTANTS_HPP__
 
+#include <stdint.h>
+
 #include <stout/duration.hpp>
 
 namespace mesos {
@@ -28,37 +30,43 @@ namespace master {
 // TODO(benh): Add units after constants.
 // TODO(benh): Also make configuration options be constants.
 
+// TODO(bmahler): It appears there may be a bug with gcc-4.1.2 in which the
+// duration constants were not being initialized when having static linkage.
+// This issue did not manifest in newer gcc's. Specifically, 4.2.1 was ok.
+// So we've moved these to have external linkage but perhaps in the future
+// we can revert this.
+
 // Maximum number of slot offers to have outstanding for each framework.
-const int MAX_OFFERS_PER_FRAMEWORK = 50;
+extern const int MAX_OFFERS_PER_FRAMEWORK;
 
 // Minimum number of cpus / task.
-const uint32_t MIN_CPUS = 1;
+extern const uint32_t MIN_CPUS;
 
 // Minimum amount of memory / task.
-const uint32_t MIN_MEM = 32 * Megabyte;
+extern const uint32_t MIN_MEM;
 
 // Maximum number of CPUs per machine.
-const uint32_t MAX_CPUS = 1000 * 1000;
+extern const uint32_t MAX_CPUS;
 
 // Maximum amount of memory / machine.
-const uint32_t MAX_MEM = 1024 * 1024 * Megabyte;
+extern const uint32_t MAX_MEM;
 
 // Amount of time within which a slave PING should be received.
-const Duration SLAVE_PING_TIMEOUT = Seconds(15.0);
+extern const Duration SLAVE_PING_TIMEOUT;
 
 // Maximum number of ping timeouts until slave is considered failed.
-const uint32_t MAX_SLAVE_PING_TIMEOUTS = 5;
+extern const uint32_t MAX_SLAVE_PING_TIMEOUTS;
 
 // Maximum number of completed frameworks to store in the cache.
 // TODO(thomasm): Make configurable.
-const uint32_t MAX_COMPLETED_FRAMEWORKS = 50;
+extern const uint32_t MAX_COMPLETED_FRAMEWORKS;
 
 // Maximum number of completed tasks per framework to store in the
 // cache.  TODO(thomasm): Make configurable.
-const uint32_t MAX_COMPLETED_TASKS_PER_FRAMEWORK = 1000;
+extern const uint32_t MAX_COMPLETED_TASKS_PER_FRAMEWORK;
 
 // Time interval to check for updated watchers list.
-const Duration WHITELIST_WATCH_INTERVAL = Seconds(5.0);
+extern const Duration WHITELIST_WATCH_INTERVAL;
 
 } // namespace mesos {
 } // namespace internal {

Modified: incubator/mesos/branches/0.11.0/src/master/http.cpp
URL: http://svn.apache.org/viewvc/incubator/mesos/branches/0.11.0/src/master/http.cpp?rev=1413856&r1=1413855&r2=1413856&view=diff
==============================================================================
--- incubator/mesos/branches/0.11.0/src/master/http.cpp (original)
+++ incubator/mesos/branches/0.11.0/src/master/http.cpp Mon Nov 26 21:21:48 2012
@@ -361,8 +361,9 @@ Future<Response> state(
   {
     JSON::Array array;
 
-    foreach (const Framework& framework, master.completedFrameworks) {
-      array.values.push_back(model(framework));
+    foreach (const std::tr1::shared_ptr<Framework>& framework,
+             master.completedFrameworks) {
+      array.values.push_back(model(*framework));
     }
 
     object.values["completed_frameworks"] = array;

Modified: incubator/mesos/branches/0.11.0/src/master/master.cpp
URL: http://svn.apache.org/viewvc/incubator/mesos/branches/0.11.0/src/master/master.cpp?rev=1413856&r1=1413855&r2=1413856&view=diff
==============================================================================
--- incubator/mesos/branches/0.11.0/src/master/master.cpp (original)
+++ incubator/mesos/branches/0.11.0/src/master/master.cpp Mon Nov 26 21:21:48 2012
@@ -261,7 +261,8 @@ Master::Master(Allocator* _allocator, Fi
   : ProcessBase("master"),
     flags(),
     allocator(_allocator),
-    files(_files) {}
+    files(_files),
+    completedFrameworks(MAX_COMPLETED_FRAMEWORKS) {}
 
 
 Master::Master(Allocator* _allocator,
@@ -270,7 +271,8 @@ Master::Master(Allocator* _allocator,
   : ProcessBase("master"),
     flags(_flags),
     allocator(_allocator),
-    files(_files) {}
+    files(_files),
+    completedFrameworks(MAX_COMPLETED_FRAMEWORKS) {}
 
 
 Master::~Master()
@@ -1711,16 +1713,12 @@ void Master::removeFramework(Framework* 
 
   framework->unregisteredTime = Clock::now();
 
-  completedFrameworks.push_back(*framework);
-  if (completedFrameworks.size() > MAX_COMPLETED_FRAMEWORKS) {
-    completedFrameworks.pop_front();
-  }
-
-  // Delete it.
+  // The completedFramework buffer now owns the framework pointer.
+  completedFrameworks.push_back(std::tr1::shared_ptr<Framework>(framework));
+  
+  // Remove it.
   frameworks.erase(framework->id);
   allocator->frameworkRemoved(framework->id);
-
-  delete framework;
 }
 
 

Modified: incubator/mesos/branches/0.11.0/src/master/master.hpp
URL: http://svn.apache.org/viewvc/incubator/mesos/branches/0.11.0/src/master/master.hpp?rev=1413856&r1=1413855&r2=1413856&view=diff
==============================================================================
--- incubator/mesos/branches/0.11.0/src/master/master.hpp (original)
+++ incubator/mesos/branches/0.11.0/src/master/master.hpp Mon Nov 26 21:21:48 2012
@@ -23,6 +23,10 @@
 #include <string>
 #include <vector>
 
+#include <tr1/functional>
+
+#include <boost/circular_buffer.hpp>
+
 #include <process/http.hpp>
 #include <process/process.hpp>
 #include <process/protobuf.hpp>
@@ -181,6 +185,9 @@ protected:
   SlaveID newSlaveId();
 
 private:
+  Master(const Master&);              // No copying.
+  Master& operator = (const Master&); // No assigning.
+
   friend struct SlaveRegistrar;
   friend struct SlaveReregistrar;
 
@@ -222,7 +229,7 @@ private:
   hashmap<SlaveID, Slave*> slaves;
   hashmap<OfferID, Offer*> offers;
 
-  std::list<Framework> completedFrameworks;
+  boost::circular_buffer<std::tr1::shared_ptr<Framework> > completedFrameworks;
 
   int64_t nextFrameworkId; // Used to give each framework a unique ID.
   int64_t nextOfferId;     // Used to give each slot offer a unique ID.
@@ -366,12 +373,19 @@ struct Slave
   hashmap<FrameworkID, hashmap<ExecutorID, ExecutorInfo> > executors;
 
   // Tasks running on this slave, indexed by FrameworkID x TaskID.
+  // TODO(bmahler): The task pointer ownership complexity arises from the fact
+  // that we own the pointer here, but it's shared with the Framework struct.
+  // We should find a way to eliminate this.
   hashmap<std::pair<FrameworkID, TaskID>, Task*> tasks;
 
   // Active offers on this slave.
   hashset<Offer*> offers;
 
   SlaveObserver* observer;
+
+private:
+  Slave(const Slave&);              // No copying.
+  Slave& operator = (const Slave&); // No assigning.
 };
 
 
@@ -387,7 +401,8 @@ struct Framework
       pid(_pid),
       active(true),
       registeredTime(time),
-      reregisteredTime(time) {}
+      reregisteredTime(time),
+      completedTasks(MAX_COMPLETED_TASKS_PER_FRAMEWORK) {}
 
   ~Framework() {}
 
@@ -412,11 +427,6 @@ struct Framework
     CHECK(tasks.contains(task->task_id()));
 
     completedTasks.push_back(*task);
-
-    if (completedTasks.size() > MAX_COMPLETED_TASKS_PER_FRAMEWORK) {
-      completedTasks.pop_front();
-    }
-
     tasks.erase(task->task_id());
     resources -= task->resources();
   }
@@ -479,13 +489,17 @@ struct Framework
 
   hashmap<TaskID, Task*> tasks;
 
-  std::list<Task> completedTasks;
+  boost::circular_buffer<Task> completedTasks;
 
   hashset<Offer*> offers; // Active offers for framework.
 
   Resources resources; // Total resources (tasks + offers + executors).
 
   hashmap<SlaveID, hashmap<ExecutorID, ExecutorInfo> > executors;
+
+private:
+  Framework(const Framework&);              // No copying.
+  Framework& operator = (const Framework&); // No assigning.
 };
 
 } // namespace master {

Modified: incubator/mesos/branches/0.11.0/src/slave/constants.hpp
URL: http://svn.apache.org/viewvc/incubator/mesos/branches/0.11.0/src/slave/constants.hpp?rev=1413856&r1=1413855&r2=1413856&view=diff
==============================================================================
--- incubator/mesos/branches/0.11.0/src/slave/constants.hpp (original)
+++ incubator/mesos/branches/0.11.0/src/slave/constants.hpp Mon Nov 26 21:21:48 2012
@@ -19,25 +19,33 @@
 #ifndef __SLAVE_CONSTANTS_HPP__
 #define __SLAVE_CONSTANTS_HPP__
 
+#include <stdint.h>
+
 #include <stout/duration.hpp>
 
 namespace mesos {
 namespace internal {
 namespace slave {
 
-const Duration EXECUTOR_SHUTDOWN_GRACE_PERIOD = Seconds(5.0);
-const Duration STATUS_UPDATE_RETRY_INTERVAL = Seconds(10.0);
-const Duration GC_DELAY = Weeks(1.0);
-const Duration DISK_WATCH_INTERVAL = Minutes(1.0);
+// TODO(bmahler): It appears there may be a bug with gcc-4.1.2 in which these
+// duration constants were not being initialized when having static linkage.
+// This issue did not manifest in newer gcc's. Specifically, 4.2.1 was ok.
+// So we've moved these to have external linkage but perhaps in the future
+// we can revert this.
+
+extern const Duration EXECUTOR_SHUTDOWN_GRACE_PERIOD;
+extern const Duration STATUS_UPDATE_RETRY_INTERVAL;
+extern const Duration GC_DELAY;
+extern const Duration DISK_WATCH_INTERVAL;
 
 // Maximum number of completed frameworks to store in memory.
-const uint32_t MAX_COMPLETED_FRAMEWORKS = 50;
+extern const uint32_t MAX_COMPLETED_FRAMEWORKS;
 
 // Maximum number of completed executors per framework to store in memory.
-const uint32_t MAX_COMPLETED_EXECUTORS_PER_FRAMEWORK = 150;
+extern const uint32_t MAX_COMPLETED_EXECUTORS_PER_FRAMEWORK;
 
 // Maximum number of completed tasks per executor to store in memeory.
-const uint32_t MAX_COMPLETED_TASKS_PER_EXECUTOR = 200;
+extern const uint32_t MAX_COMPLETED_TASKS_PER_EXECUTOR;
 
 } // namespace slave {
 } // namespace internal {

Modified: incubator/mesos/branches/0.11.0/src/slave/http.cpp
URL: http://svn.apache.org/viewvc/incubator/mesos/branches/0.11.0/src/slave/http.cpp?rev=1413856&r1=1413855&r2=1413856&view=diff
==============================================================================
--- incubator/mesos/branches/0.11.0/src/slave/http.cpp (original)
+++ incubator/mesos/branches/0.11.0/src/slave/http.cpp Mon Nov 26 21:21:48 2012
@@ -233,8 +233,9 @@ JSON::Object model(const Framework& fram
   object.values["executors"] = executors;
 
   JSON::Array completedExecutors;
-  foreach (const Executor& executor, framework.completedExecutors) {
-    completedExecutors.values.push_back(model(executor));
+  foreach (const std::tr1::shared_ptr<Executor>& executor,
+           framework.completedExecutors) {
+    completedExecutors.values.push_back(model(*executor));
   }
   object.values["completed_executors"] = completedExecutors;
 
@@ -330,8 +331,9 @@ Future<Response> state(
   object.values["frameworks"] = frameworks;
 
   JSON::Array completedFrameworks;
-  foreach (const Framework& framework, slave.completedFrameworks) {
-    completedFrameworks.values.push_back(model(framework));
+  foreach (const std::tr1::shared_ptr<Framework>& framework,
+           slave.completedFrameworks) {
+    completedFrameworks.values.push_back(model(*framework));
   }
   object.values["completed_frameworks"] = completedFrameworks;
 

Modified: incubator/mesos/branches/0.11.0/src/slave/slave.cpp
URL: http://svn.apache.org/viewvc/incubator/mesos/branches/0.11.0/src/slave/slave.cpp?rev=1413856&r1=1413855&r2=1413856&view=diff
==============================================================================
--- incubator/mesos/branches/0.11.0/src/slave/slave.cpp (original)
+++ incubator/mesos/branches/0.11.0/src/slave/slave.cpp Mon Nov 26 21:21:48 2012
@@ -69,6 +69,7 @@ Slave::Slave(const Resources& _resources
     flags(),
     local(_local),
     resources(_resources),
+    completedFrameworks(MAX_COMPLETED_FRAMEWORKS),
     isolationModule(_isolationModule),
     files(_files) {}
 
@@ -80,6 +81,7 @@ Slave::Slave(const flags::Flags<logging:
   : ProcessBase(ID::generate("slave")),
     flags(_flags),
     local(_local),
+    completedFrameworks(MAX_COMPLETED_FRAMEWORKS),
     isolationModule(_isolationModule),
     files(_files)
 {
@@ -154,9 +156,6 @@ Slave::~Slave()
   // event and initiate a shut down itself.
 
   foreachvalue (Framework* framework, frameworks) {
-    foreachvalue (Executor* executor, framework->executors) {
-      delete executor;
-    }
     delete framework;
   }
 }
@@ -734,12 +733,9 @@ void Slave::statusUpdateAcknowledgement(
       if (framework->executors.size() == 0 && framework->updates.empty()) {
         frameworks.erase(framework->id);
 
-        completedFrameworks.push_back(*framework);
-        if (completedFrameworks.size() > MAX_COMPLETED_FRAMEWORKS) {
-          completedFrameworks.pop_front();
-        }
-
-        delete framework;
+        // Pass ownership of the framework pointer.
+        completedFrameworks.push_back(
+            std::tr1::shared_ptr<Framework>(framework));
       }
     }
   }
@@ -1126,12 +1122,8 @@ void Slave::shutdownExecutorTimeout(
   if (framework->executors.size() == 0) {
     frameworks.erase(framework->id);
 
-    completedFrameworks.push_back(*framework);
-    if (completedFrameworks.size() > MAX_COMPLETED_FRAMEWORKS) {
-      completedFrameworks.pop_front();
-    }
-
-    delete framework;
+    // Pass ownership of the framework pointer.
+    completedFrameworks.push_back(std::tr1::shared_ptr<Framework>(framework));
   }
 }
 

Modified: incubator/mesos/branches/0.11.0/src/slave/slave.hpp
URL: http://svn.apache.org/viewvc/incubator/mesos/branches/0.11.0/src/slave/slave.hpp?rev=1413856&r1=1413855&r2=1413856&view=diff
==============================================================================
--- incubator/mesos/branches/0.11.0/src/slave/slave.hpp (original)
+++ incubator/mesos/branches/0.11.0/src/slave/slave.hpp Mon Nov 26 21:21:48 2012
@@ -22,6 +22,10 @@
 #include <list>
 #include <string>
 
+#include <tr1/functional>
+
+#include <boost/circular_buffer.hpp>
+
 #include <process/http.hpp>
 #include <process/process.hpp>
 #include <process/protobuf.hpp>
@@ -180,6 +184,9 @@ protected:
   void checkDiskUsage();
 
 private:
+  Slave(const Slave&);              // No copying.
+  Slave& operator = (const Slave&); // No assigning.
+
   // HTTP handlers, friends of the slave in order to access state,
   // they get invoked from within the slave so there is no need to
   // use synchronization mechanisms to protect state.
@@ -208,7 +215,7 @@ private:
   Attributes attributes;
 
   hashmap<FrameworkID, Framework*> frameworks;
-  std::list<Framework> completedFrameworks;
+  boost::circular_buffer<std::tr1::shared_ptr<Framework> > completedFrameworks;
 
   IsolationModule* isolationModule;
   Files* files;
@@ -246,7 +253,8 @@ struct Executor
       uuid(_uuid),
       pid(UPID()),
       shutdown(false),
-      resources(_info.resources()) {}
+      resources(_info.resources()),
+      completedTasks(MAX_COMPLETED_TASKS_PER_EXECUTOR) {}
 
   ~Executor()
   {
@@ -293,9 +301,6 @@ struct Executor
       launchedTasks.erase(taskId);
 
       completedTasks.push_back(*task);
-      if (completedTasks.size() > MAX_COMPLETED_TASKS_PER_EXECUTOR) {
-        completedTasks.pop_front();
-      }
 
       delete task;
     }
@@ -326,7 +331,11 @@ struct Executor
   hashmap<TaskID, TaskInfo> queuedTasks;
   hashmap<TaskID, Task*> launchedTasks;
 
-  std::list<Task> completedTasks;
+  boost::circular_buffer<Task> completedTasks;
+
+private:
+  Executor(const Executor&);              // No copying.
+  Executor& operator = (const Executor&); // No assigning.
 };
 
 
@@ -340,9 +349,16 @@ struct Framework
     : id(_id),
       info(_info),
       pid(_pid),
-      flags(_flags) {}
+      flags(_flags),
+      completedExecutors(MAX_COMPLETED_EXECUTORS_PER_FRAMEWORK) {}
 
-  ~Framework() {}
+  ~Framework()
+  {
+    // We own the non-completed executor pointers, so they need to be deleted.
+    foreachvalue (Executor* executor, executors) {
+      delete executor;
+    }
+  }
 
   // Returns an ExecutorInfo for a TaskInfo (possibly
   // constructing one if the task has a CommandInfo).
@@ -418,12 +434,8 @@ struct Framework
       Executor* executor = executors[executorId];
       executors.erase(executorId);
 
-      completedExecutors.push_back(*executor);
-      if (completedExecutors.size() > MAX_COMPLETED_EXECUTORS_PER_FRAMEWORK) {
-        completedExecutors.pop_front();
-      }
-
-      delete executor;
+      // Pass ownership of the executor pointer.
+      completedExecutors.push_back(std::tr1::shared_ptr<Executor>(executor));
     }
   }
 
@@ -459,10 +471,14 @@ struct Framework
   hashmap<ExecutorID, Executor*> executors;
 
   // Up to MAX_COMPLETED_EXECUTORS_PER_FRAMEWORK completed executors.
-  std::list<Executor> completedExecutors;
+  boost::circular_buffer<std::tr1::shared_ptr<Executor> > completedExecutors;
 
   // Status updates keyed by uuid.
   hashmap<UUID, StatusUpdate> updates;
+
+private:
+  Framework(const Framework&);              // No copying.
+  Framework& operator = (const Framework&); // No assigning.
 };
 
 } // namespace slave {

Modified: incubator/mesos/branches/0.11.0/src/tests/master_tests.cpp
URL: http://svn.apache.org/viewvc/incubator/mesos/branches/0.11.0/src/tests/master_tests.cpp?rev=1413856&r1=1413855&r2=1413856&view=diff
==============================================================================
--- incubator/mesos/branches/0.11.0/src/tests/master_tests.cpp (original)
+++ incubator/mesos/branches/0.11.0/src/tests/master_tests.cpp Mon Nov 26 21:21:48 2012
@@ -170,6 +170,101 @@ TEST(MasterTest, TaskRunning)
 }
 
 
+TEST(MasterTest, ShutdownFrameworkWhileTaskRunning)
+{
+  ASSERT_TRUE(GTEST_IS_THREADSAFE);
+
+  TestAllocatorProcess a;
+  Files files;
+  Master m(&a, &files);
+  PID<Master> master = process::spawn(&m);
+
+  MockExecutor exec;
+
+  trigger shutdownCall;
+
+  EXPECT_CALL(exec, registered(_, _, _, _))
+    .Times(1);
+
+  EXPECT_CALL(exec, launchTask(_, _))
+    .WillOnce(SendStatusUpdateFromTask(TASK_RUNNING));
+
+  EXPECT_CALL(exec, shutdown(_))
+    .WillOnce(Trigger(&shutdownCall));
+
+  map<ExecutorID, Executor*> execs;
+  execs[DEFAULT_EXECUTOR_ID] = &exec;
+
+  TestingIsolationModule isolationModule(execs);
+
+  flags::Flags<logging::Flags, slave::Flags> flags;
+  flags.executor_shutdown_grace_period = Seconds(0.0);
+  flags.resources = Option<string>::some("cpus:2;mem:1024");
+  Slave s(flags, true, &isolationModule, &files);
+  PID<Slave> slave = process::spawn(&s);
+
+  BasicMasterDetector detector(master, slave, true);
+
+  MockScheduler sched;
+  MesosSchedulerDriver driver(&sched, DEFAULT_FRAMEWORK_INFO, master);
+
+  vector<Offer> offers;
+  TaskStatus status;
+
+  trigger resourceOffersCall, statusUpdateCall, resourcesChangedCall;
+
+  EXPECT_CALL(sched, registered(&driver, _, _))
+    .Times(1);
+
+  EXPECT_CALL(sched, resourceOffers(&driver, _))
+    .WillOnce(DoAll(SaveArg<1>(&offers),
+                    Trigger(&resourceOffersCall)))
+    .WillRepeatedly(Return());
+
+  EXPECT_CALL(sched, statusUpdate(&driver, _))
+    .WillOnce(DoAll(SaveArg<1>(&status), Trigger(&statusUpdateCall)));
+
+  driver.start();
+
+  WAIT_UNTIL(resourceOffersCall);
+
+  EXPECT_NE(0u, offers.size());
+
+  TaskInfo task;
+  task.set_name("");
+  task.mutable_task_id()->set_value("1");
+  task.mutable_slave_id()->MergeFrom(offers[0].slave_id());
+  task.mutable_resources()->MergeFrom(offers[0].resources());
+  task.mutable_executor()->MergeFrom(DEFAULT_EXECUTOR_INFO);
+
+  vector<TaskInfo> tasks;
+  tasks.push_back(task);
+
+  EXPECT_CALL(isolationModule,
+              resourcesChanged(_, _, Resources(offers[0].resources())))
+    .WillOnce(Trigger(&resourcesChangedCall));
+
+  driver.launchTasks(offers[0].id(), tasks);
+
+  WAIT_UNTIL(statusUpdateCall);
+
+  EXPECT_EQ(TASK_RUNNING, status.state());
+
+  WAIT_UNTIL(resourcesChangedCall);
+
+  driver.stop();
+  driver.join();
+
+  WAIT_UNTIL(shutdownCall); // Ensures MockExecutor can be deallocated.
+
+  process::terminate(slave);
+  process::wait(slave);
+
+  process::terminate(master);
+  process::wait(master);
+}
+
+
 TEST(MasterTest, KillTask)
 {
   ASSERT_TRUE(GTEST_IS_THREADSAFE);