Apache Mesos
executor.hpp
Go to the documentation of this file.
1 // Licensed to the Apache Software Foundation (ASF) under one
2 // or more contributor license agreements. See the NOTICE file
3 // distributed with this work for additional information
4 // regarding copyright ownership. The ASF licenses this file
5 // to you under the Apache License, Version 2.0 (the
6 // "License"); you may not use this file except in compliance
7 // with the License. You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 
17 #ifndef __MESOS_EXECUTOR_HPP__
18 #define __MESOS_EXECUTOR_HPP__
19 
20 #include <mutex>
21 #include <string>
22 
23 #include <mesos/mesos.hpp>
24 
25 // Mesos executor interface and executor driver. An executor is
26 // responsible for launching tasks in a framework specific way (i.e.,
27 // creating new threads, new processes, etc). One or more executors
28 // from the same framework may run concurrently on the same machine.
29 // Note that we use the term "executor" fairly loosely to refer to the
30 // code that implements the Executor interface (see below) as well as
31 // the program that is responsible for instantiating a new
32 // MesosExecutorDriver (also below). In fact, while a Mesos slave is
33 // responsible for (forking and) executing the "executor", there is no
34 // reason why whatever the slave executed might itself actually
35 // execute another program which actually instantiates and runs the
36 // MesosSchedulerDriver. The only contract with the slave is that the
37 // program that it invokes does not exit until the "executor" has
38 // completed. Thus, what the slave executes may be nothing more than a
39 // script which actually executes (or forks and waits) the "real"
40 // executor.
41 //
42 // IF YOU FIND YOURSELF MODIFYING COMMENTS HERE PLEASE CONSIDER MAKING
43 // THE SAME MODIFICATIONS FOR OTHER LANGUAGE BINDINGS (e.g., Java:
44 // src/java/src/org/apache/mesos, Python: src/python/src, etc.).
45 
46 // Forward declaration.
47 namespace process {
48 class Latch;
49 } // namespace process {
50 
51 namespace mesos {
52 
53 // A few forward declarations.
54 class ExecutorDriver;
55 
56 namespace internal {
57 class ExecutorProcess;
58 }
59 
60 // Callback interface to be implemented by frameworks' executors. Note
61 // that only one callback will be invoked at a time, so it is not
62 // recommended that you block within a callback because it may cause a
63 // deadlock.
64 //
65 // Each callback includes a pointer to the executor driver that was
66 // used to run this executor. The pointer will not change for the
67 // duration of an executor (i.e., from the point you do
68 // ExecutorDriver::start() to the point that ExecutorDriver::join()
69 // returns). This is intended for convenience so that an executor
70 // doesn't need to store a pointer to the driver itself.
71 //
72 // TODO(bmahler): Consider adding a usage() callback here, that
73 // provides information to the executor about its ResourceUsage.
74 class Executor
75 {
76 public:
77  // Empty virtual destructor (necessary to instantiate subclasses).
78  virtual ~Executor() {}
79 
80  // Invoked once the executor driver has been able to successfully
81  // connect with Mesos. In particular, a scheduler can pass some
82  // data to its executors through the FrameworkInfo.ExecutorInfo's
83  // data field.
84  virtual void registered(
85  ExecutorDriver* driver,
86  const ExecutorInfo& executorInfo,
87  const FrameworkInfo& frameworkInfo,
88  const SlaveInfo& slaveInfo) = 0;
89 
90  // Invoked when the executor re-registers with a restarted slave.
91  virtual void reregistered(
92  ExecutorDriver* driver,
93  const SlaveInfo& slaveInfo) = 0;
94 
95  // Invoked when the executor becomes "disconnected" from the slave
96  // (e.g., the slave is being restarted due to an upgrade).
97  virtual void disconnected(ExecutorDriver* driver) = 0;
98 
99  // Invoked when a task has been launched on this executor (initiated
100  // via Scheduler::launchTasks). Note that this task can be realized
101  // with a thread, a process, or some simple computation, however, no
102  // other callbacks will be invoked on this executor until this
103  // callback has returned.
104  virtual void launchTask(
105  ExecutorDriver* driver,
106  const TaskInfo& task) = 0;
107 
108  // Invoked when a task running within this executor has been killed
109  // (via SchedulerDriver::killTask). Note that no status update will
110  // be sent on behalf of the executor, the executor is responsible
111  // for creating a new TaskStatus (i.e., with TASK_KILLED) and
112  // invoking ExecutorDriver::sendStatusUpdate.
113  virtual void killTask(
114  ExecutorDriver* driver,
115  const TaskID& taskId) = 0;
116 
117  // Invoked when a framework message has arrived for this executor.
118  // These messages are best effort; do not expect a framework message
119  // to be retransmitted in any reliable fashion.
120  virtual void frameworkMessage(
121  ExecutorDriver* driver,
122  const std::string& data) = 0;
123 
124  // Invoked when the executor should terminate all of its currently
125  // running tasks. Note that after a Mesos has determined that an
126  // executor has terminated any tasks that the executor did not send
127  // terminal status updates for (e.g., TASK_KILLED, TASK_FINISHED,
128  // TASK_FAILED, etc) a TASK_LOST status update will be created.
129  virtual void shutdown(ExecutorDriver* driver) = 0;
130 
131  // Invoked when a fatal error has occurred with the executor and/or
132  // executor driver. The driver will be aborted BEFORE invoking this
133  // callback.
134  virtual void error(
135  ExecutorDriver* driver,
136  const std::string& message) = 0;
137 };
138 
139 
140 // Abstract interface for connecting an executor to Mesos. This
141 // interface is used both to manage the executor's lifecycle (start
142 // it, stop it, or wait for it to finish) and to interact with Mesos
143 // (e.g., send status updates, send framework messages, etc.). See
144 // MesosExecutorDriver below for a concrete example of an
145 // ExecutorDriver.
147 {
148 public:
149  // Empty virtual destructor (necessary to instantiate subclasses).
150  virtual ~ExecutorDriver() {}
151 
152  // Starts the executor driver. This needs to be called before any
153  // other driver calls are made.
154  virtual Status start() = 0;
155 
156  // Stops the executor driver.
157  virtual Status stop() = 0;
158 
159  // Aborts the driver so that no more callbacks can be made to the
160  // executor. The semantics of abort and stop have deliberately been
161  // separated so that code can detect an aborted driver (i.e., via
162  // the return status of ExecutorDriver::join, see below), and
163  // instantiate and start another driver if desired (from within the
164  // same process ... although this functionality is currently not
165  // supported for executors).
166  virtual Status abort() = 0;
167 
168  // Waits for the driver to be stopped or aborted, possibly
169  // _blocking_ the current thread indefinitely. The return status of
170  // this function can be used to determine if the driver was aborted
171  // (see mesos.proto for a description of Status).
172  virtual Status join() = 0;
173 
174  // Starts and immediately joins (i.e., blocks on) the driver.
175  virtual Status run() = 0;
176 
177  // Sends a status update to the framework scheduler, retrying as
178  // necessary until an acknowledgement has been received or the
179  // executor is terminated (in which case, a TASK_LOST status update
180  // will be sent). See Scheduler::statusUpdate for more information
181  // about status update acknowledgements.
182  virtual Status sendStatusUpdate(const TaskStatus& status) = 0;
183 
184  // Sends a message to the framework scheduler. These messages are
185  // best effort; do not expect a framework message to be
186  // retransmitted in any reliable fashion.
187  virtual Status sendFrameworkMessage(const std::string& data) = 0;
188 };
189 
190 
191 // Concrete implementation of an ExecutorDriver that connects an
192 // Executor with a Mesos slave. The MesosExecutorDriver is
193 // thread-safe.
194 //
195 // The driver is responsible for invoking the Executor callbacks as it
196 // communicates with the Mesos slave.
197 //
198 // Note that blocking on the MesosExecutorDriver (e.g., via
199 // MesosExecutorDriver::join) doesn't affect the executor callbacks in
200 // anyway because they are handled by a different thread.
201 //
202 // Note that the driver uses GLOG to do its own logging. GLOG flags
203 // can be set via environment variables, prefixing the flag name with
204 // "GLOG_", e.g., "GLOG_v=1". For Mesos specific logging flags see
205 // src/logging/flags.hpp. Mesos flags can also be set via environment
206 // variables, prefixing the flag name with "MESOS_", e.g.,
207 // "MESOS_QUIET=1".
208 //
209 // See src/examples/test_executor.cpp for an example of using the
210 // MesosExecutorDriver.
212 {
213 public:
214  // Creates a new driver that uses the specified Executor. Note, the
215  // executor pointer must outlive the driver.
216  explicit MesosExecutorDriver(Executor* executor);
217 
218  // This destructor will block indefinitely if
219  // MesosExecutorDriver::start was invoked successfully (possibly via
220  // MesosExecutorDriver::run) and MesosExecutorDriver::stop has not
221  // been invoked.
222  virtual ~MesosExecutorDriver();
223 
224  // See ExecutorDriver for descriptions of these.
225  virtual Status start();
226  virtual Status stop();
227  virtual Status abort();
228  virtual Status join();
229  virtual Status run();
230  virtual Status sendStatusUpdate(const TaskStatus& status);
231  virtual Status sendFrameworkMessage(const std::string& data);
232 
233 private:
235 
236  Executor* executor;
237 
238  // Libprocess process for communicating with slave.
240 
241  // Mutex for enforcing serial execution of all non-callbacks.
242  std::recursive_mutex mutex;
243 
244  // Latch for waiting until driver terminates.
245  process::Latch* latch;
246 
247  // Current status of the driver.
248  Status status;
249 };
250 
251 } // namespace mesos {
252 
253 #endif // __MESOS_EXECUTOR_HPP__
virtual Status start()=0
virtual void reregistered(ExecutorDriver *driver, const SlaveInfo &slaveInfo)=0
Definition: executor.hpp:146
virtual void registered(ExecutorDriver *driver, const ExecutorInfo &executorInfo, const FrameworkInfo &frameworkInfo, const SlaveInfo &slaveInfo)=0
virtual void killTask(ExecutorDriver *driver, const TaskID &taskId)=0
Result< ProcessStatus > status(pid_t pid)
Definition: proc.hpp:166
virtual void shutdown(ExecutorDriver *driver)=0
Definition: executor.hpp:211
virtual ~Executor()
Definition: executor.hpp:78
friend class internal::ExecutorProcess
Definition: executor.hpp:234
virtual Status sendStatusUpdate(const TaskStatus &status)=0
virtual ~ExecutorDriver()
Definition: executor.hpp:150
virtual Status abort()
virtual void disconnected(ExecutorDriver *driver)=0
virtual Status start()
virtual void error(ExecutorDriver *driver, const std::string &message)=0
virtual Status join()=0
Definition: executor.hpp:74
MesosExecutorDriver(Executor *executor)
Result< Process > process(pid_t pid)
Definition: freebsd.hpp:30
virtual void launchTask(ExecutorDriver *driver, const TaskInfo &task)=0
virtual void frameworkMessage(ExecutorDriver *driver, const std::string &data)=0
virtual Status stop()=0
virtual Status sendStatusUpdate(const TaskStatus &status)
virtual Status sendFrameworkMessage(const std::string &data)
Definition: latch.hpp:24
virtual Status abort()=0
virtual Status run()=0
virtual Status sendFrameworkMessage(const std::string &data)=0