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);