/* * Class: org_apache_mesos_state_ZooKeeperState * Method: __names_cancel * Signature: (J)Z */ JNIEXPORT jboolean JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1names_1cancel (JNIEnv* env, jobject thiz, jlong jfuture) { Future<vector<string> >* future = (Future<vector<string> >*) jfuture; if (!future->isDiscarded()) { future->discard(); return (jboolean) future->isDiscarded(); } return (jboolean) true; }
void LeaderContenderProcess::cancelled(const Future<bool>& result) { CHECK_READY(candidacy); LOG(INFO) << "Membership cancelled: " << candidacy->id(); // Can be called as a result of either withdraw() or server side // expiration. CHECK(withdrawing.isSome() || watching.isSome()); CHECK(!result.isDiscarded()); if (result.isFailed()) { if (withdrawing.isSome()) { withdrawing.get()->fail(result.failure()); } if (watching.isSome()) { watching.get()->fail(result.failure()); } } else { if (withdrawing.isSome()) { withdrawing.get()->set(result); } if (watching.isSome()) { watching.get()->set(Nothing()); } } }
Future<bool> LeaderContenderProcess::withdraw() { if (contending.isNone()) { // Nothing to withdraw because the contender has not contended. return false; } if (withdrawing.isSome()) { // Repeated calls to withdraw get the same result. return withdrawing.get(); } withdrawing = new Promise<bool>(); CHECK(!candidacy.isDiscarded()); if (candidacy.isPending()) { // If we have not obtained the candidacy yet, we withdraw after // it is obtained. LOG(INFO) << "Withdraw requested before the candidacy is obtained; will " << "withdraw after it happens"; candidacy.onAny(defer(self(), &Self::cancel)); } else if (candidacy.isReady()) { cancel(); } else { // We have failed to obtain the candidacy so we do not need to // cancel it. return false; } return withdrawing.get()->future(); }
/* * Class: org_apache_mesos_state_ZooKeeperState * Method: __expunge_is_cancelled * Signature: (J)Z */ JNIEXPORT jboolean JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1expunge_1is_1cancelled (JNIEnv* env, jobject thiz, jlong jfuture) { Future<bool>* future = (Future<bool>*) jfuture; return (jboolean) future->isDiscarded(); }
/* * Class: org_apache_mesos_state_AbstractState * Method: __expunge_get * Signature: (J)Ljava/lang/Boolean; */ JNIEXPORT jobject JNICALL Java_org_apache_mesos_state_AbstractState__1_1expunge_1get (JNIEnv* env, jobject thiz, jlong jfuture) { Future<bool>* future = (Future<bool>*) jfuture; future->await(); if (future->isFailed()) { jclass clazz = env->FindClass("java/util/concurrent/ExecutionException"); env->ThrowNew(clazz, future->failure().c_str()); return NULL; } else if (future->isDiscarded()) { // TODO(benh): Consider throwing an ExecutionException since we // never return true for 'isCancelled'. jclass clazz = env->FindClass("java/util/concurrent/CancellationException"); env->ThrowNew(clazz, "Future was discarded"); return NULL; } CHECK_READY(*future); if (future->get()) { jclass clazz = env->FindClass("java/lang/Boolean"); return env->GetStaticObjectField( clazz, env->GetStaticFieldID(clazz, "TRUE", "Ljava/lang/Boolean;")); } jclass clazz = env->FindClass("java/lang/Boolean"); return env->GetStaticObjectField( clazz, env->GetStaticFieldID(clazz, "FALSE", "Ljava/lang/Boolean;")); }
/* * Class: org_apache_mesos_state_AbstractState * Method: __fetch_get * Signature: (J)Lorg/apache/mesos/state/Variable; */ JNIEXPORT jobject JNICALL Java_org_apache_mesos_state_AbstractState__1_1fetch_1get (JNIEnv* env, jobject thiz, jlong jfuture) { Future<Variable>* future = (Future<Variable>*) jfuture; future->await(); if (future->isFailed()) { jclass clazz = env->FindClass("java/util/concurrent/ExecutionException"); env->ThrowNew(clazz, future->failure().c_str()); return nullptr; } else if (future->isDiscarded()) { // TODO(benh): Consider throwing an ExecutionException since we // never return true for 'isCancelled'. jclass clazz = env->FindClass("java/util/concurrent/CancellationException"); env->ThrowNew(clazz, "Future was discarded"); return nullptr; } CHECK_READY(*future); Variable* variable = new Variable(future->get()); // Variable variable = new Variable(); jclass clazz = env->FindClass("org/apache/mesos/state/Variable"); jmethodID _init_ = env->GetMethodID(clazz, "<init>", "()V"); jobject jvariable = env->NewObject(clazz, _init_); jfieldID __variable = env->GetFieldID(clazz, "__variable", "J"); env->SetLongField(jvariable, __variable, (jlong) variable); return jvariable; }
/* * Class: org_apache_mesos_state_ZooKeeperState * Method: __expunge_get * Signature: (J)Ljava/lang/Boolean; */ JNIEXPORT jobject JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1expunge_1get (JNIEnv* env, jobject thiz, jlong jfuture) { Future<bool>* future = (Future<bool>*) jfuture; future->await(); if (future->isFailed()) { jclass clazz = env->FindClass("java/util/concurrent/ExecutionException"); env->ThrowNew(clazz, future->failure().c_str()); return NULL; } else if (future->isDiscarded()) { jclass clazz = env->FindClass("java/util/concurrent/CancellationException"); env->ThrowNew(clazz, "Future was discarded"); return NULL; } CHECK(future->isReady()); if (future->get()) { jclass clazz = env->FindClass("java/lang/Boolean"); return env->GetStaticObjectField( clazz, env->GetStaticFieldID(clazz, "TRUE", "Ljava/lang/Boolean;")); } jclass clazz = env->FindClass("java/lang/Boolean"); return env->GetStaticObjectField( clazz, env->GetStaticFieldID(clazz, "FALSE", "Ljava/lang/Boolean;")); }
/* * Class: org_apache_mesos_state_ZooKeeperState * Method: __fetch_get * Signature: (J)Lorg/apache/mesos/state/Variable; */ JNIEXPORT jobject JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1fetch_1get (JNIEnv* env, jobject thiz, jlong jfuture) { Future<Variable>* future = (Future<Variable>*) jfuture; future->await(); if (future->isFailed()) { jclass clazz = env->FindClass("java/util/concurrent/ExecutionException"); env->ThrowNew(clazz, future->failure().c_str()); return NULL; } else if (future->isDiscarded()) { jclass clazz = env->FindClass("java/util/concurrent/CancellationException"); env->ThrowNew(clazz, "Future was discarded"); return NULL; } CHECK(future->isReady()); Variable* variable = new Variable(future->get()); // Variable variable = new Variable(); jclass clazz = env->FindClass("org/apache/mesos/state/Variable"); jmethodID _init_ = env->GetMethodID(clazz, "<init>", "()V"); jobject jvariable = env->NewObject(clazz, _init_); jfieldID __variable = env->GetFieldID(clazz, "__variable", "J"); env->SetLongField(jvariable, __variable, (jlong) variable); return jvariable; }
void _healthCheck() { if (check.has_http()) { promise.fail("HTTP health check is not supported"); } else if (check.has_command()) { const CommandInfo& command = check.command(); map<string, string> environment; foreach (const Environment_Variable& variable, command.environment().variables()) { environment[variable.name()] = variable.value(); } VLOG(2) << "Launching health command: " << command.value(); Try<Subprocess> external = process::subprocess( command.value(), // Reading from STDIN instead of PIPE because scripts // seeing an open STDIN pipe might behave differently // and we do not expect to pass any value from STDIN // or PIPE. Subprocess::FD(STDIN_FILENO), Subprocess::FD(STDERR_FILENO), Subprocess::FD(STDERR_FILENO), environment); if (external.isError()) { promise.fail("Error creating subprocess for healthcheck"); } else { Future<Option<int> > status = external.get().status(); status.await(Seconds(check.timeout_seconds())); if (!status.isReady()) { string msg = "Shell command check failed with reason: "; if (status.isFailed()) { msg += "failed with error: " + status.failure(); } else if (status.isDiscarded()) { msg += "status future discarded"; } else { msg += "status still pending after timeout " + stringify(Seconds(check.timeout_seconds())); } promise.fail(msg); return; } int statusCode = status.get().get(); if (statusCode != 0) { string message = "Health command check " + WSTRINGIFY(statusCode); failure(message); } else { success(); } } } else {
/* * Class: org_apache_mesos_state_AbstractState * Method: __names_get_timeout * Signature: (JJLjava/util/concurrent/TimeUnit;)Ljava/util/Iterator; */ JNIEXPORT jobject JNICALL Java_org_apache_mesos_state_AbstractState__1_1names_1get_1timeout (JNIEnv* env, jobject thiz, jlong jfuture, jlong jtimeout, jobject junit) { Future<set<string> >* future = (Future<set<string> >*) jfuture; jclass clazz = env->GetObjectClass(junit); // long seconds = unit.toSeconds(time); jmethodID toSeconds = env->GetMethodID(clazz, "toSeconds", "(J)J"); jlong jseconds = env->CallLongMethod(junit, toSeconds, jtimeout); Seconds seconds(jseconds); if (future->await(seconds)) { if (future->isFailed()) { clazz = env->FindClass("java/util/concurrent/ExecutionException"); env->ThrowNew(clazz, future->failure().c_str()); return NULL; } else if (future->isDiscarded()) { // TODO(benh): Consider throwing an ExecutionException since we // never return true for 'isCancelled'. clazz = env->FindClass("java/util/concurrent/CancellationException"); env->ThrowNew(clazz, "Future was discarded"); return NULL; } CHECK_READY(*future); // List names = new ArrayList(); clazz = env->FindClass("java/util/ArrayList"); jmethodID _init_ = env->GetMethodID(clazz, "<init>", "()V"); jobject jnames = env->NewObject(clazz, _init_); jmethodID add = env->GetMethodID(clazz, "add", "(Ljava/lang/Object;)Z"); foreach (const string& name, future->get()) { jobject jname = convert<string>(env, name); env->CallBooleanMethod(jnames, add, jname); } // Iterator iterator = jnames.iterator(); jmethodID iterator = env->GetMethodID(clazz, "iterator", "()Ljava/util/Iterator;"); jobject jiterator = env->CallObjectMethod(jnames, iterator); return jiterator; } clazz = env->FindClass("java/util/concurrent/TimeoutException"); env->ThrowNew(clazz, "Failed to wait for future within timeout"); return NULL; }
void LeaderDetectorProcess::watched(Future<set<Group::Membership> > memberships) { CHECK(!memberships.isDiscarded()); if (memberships.isFailed()) { LOG(ERROR) << "Failed to watch memberships: " << memberships.failure(); leader = None(); foreach (Promise<Option<Group::Membership> >* promise, promises) { promise->fail(memberships.failure()); delete promise; }
/* * Class: org_apache_mesos_state_AbstractState * Method: __store_get_timeout * Signature: (JJLjava/util/concurrent/TimeUnit;)Lorg/apache/mesos/state/Variable; */ JNIEXPORT jobject JNICALL Java_org_apache_mesos_state_AbstractState__1_1store_1get_1timeout (JNIEnv* env, jobject thiz, jlong jfuture, jlong jtimeout, jobject junit) { Future<Option<Variable> >* future = (Future<Option<Variable> >*) jfuture; jclass clazz = env->GetObjectClass(junit); // long seconds = unit.toSeconds(time); jmethodID toSeconds = env->GetMethodID(clazz, "toSeconds", "(J)J"); jlong jseconds = env->CallLongMethod(junit, toSeconds, jtimeout); Seconds seconds(jseconds); if (future->await(seconds)) { if (future->isFailed()) { clazz = env->FindClass("java/util/concurrent/ExecutionException"); env->ThrowNew(clazz, future->failure().c_str()); return NULL; } else if (future->isDiscarded()) { // TODO(benh): Consider throwing an ExecutionException since we // never return true for 'isCancelled'. clazz = env->FindClass("java/util/concurrent/CancellationException"); env->ThrowNew(clazz, "Future was discarded"); return NULL; } CHECK_READY(*future); if (future->get().isSome()) { Variable* variable = new Variable(future->get().get()); // Variable variable = new Variable(); clazz = env->FindClass("org/apache/mesos/state/Variable"); jmethodID _init_ = env->GetMethodID(clazz, "<init>", "()V"); jobject jvariable = env->NewObject(clazz, _init_); jfieldID __variable = env->GetFieldID(clazz, "__variable", "J"); env->SetLongField(jvariable, __variable, (jlong) variable); return jvariable; } return NULL; } clazz = env->FindClass("java/util/concurrent/TimeoutException"); env->ThrowNew(clazz, "Failed to wait for future within timeout"); return NULL; }
void LeaderDetectorProcess::watched(const Future<set<Group::Membership> >& memberships) { CHECK(!memberships.isDiscarded()); if (memberships.isFailed()) { LOG(ERROR) << "Failed to watch memberships: " << memberships.failure(); // Setting this error stops the watch loop and the detector // transitions to an erroneous state. Further calls to detect() // will directly fail as a result. error = Error(memberships.failure()); leader = None(); foreach (Promise<Option<Group::Membership> >* promise, promises) { promise->fail(memberships.failure()); delete promise; }
// See the comment below as to why subprocess is passed to cleanup. inline void cleanup( const Future<Option<int> >& result, Promise<Option<int> >* promise, const Subprocess& subprocess) { CHECK(!result.isPending()); CHECK(!result.isDiscarded()); if (result.isFailed()) { promise->fail(result.failure()); } else { promise->set(result.get()); } delete promise; }
void waited(const Future<T>& future) { if (future.isFailed()) { promise->fail("Collect failed: " + future.failure()); terminate(this); } else if (future.isDiscarded()) { promise->fail("Collect failed: future discarded"); terminate(this); } else { assert(future.isReady()); values.push_back(future.get()); if (futures.size() == values.size()) { promise->set(values); terminate(this); } } }
/* * Class: org_apache_mesos_state_AbstractState * Method: __expunge_get_timeout * Signature: (JJLjava/util/concurrent/TimeUnit;)Ljava/lang/Boolean; */ JNIEXPORT jobject JNICALL Java_org_apache_mesos_state_AbstractState__1_1expunge_1get_1timeout (JNIEnv* env, jobject thiz, jlong jfuture, jlong jtimeout, jobject junit) { Future<bool>* future = (Future<bool>*) jfuture; jclass clazz = env->GetObjectClass(junit); // long seconds = unit.toSeconds(time); jmethodID toSeconds = env->GetMethodID(clazz, "toSeconds", "(J)J"); jlong jseconds = env->CallLongMethod(junit, toSeconds, jtimeout); Seconds seconds(jseconds); if (future->await(seconds)) { if (future->isFailed()) { clazz = env->FindClass("java/util/concurrent/ExecutionException"); env->ThrowNew(clazz, future->failure().c_str()); return NULL; } else if (future->isDiscarded()) { // TODO(benh): Consider throwing an ExecutionException since we // never return true for 'isCancelled'. clazz = env->FindClass("java/util/concurrent/CancellationException"); env->ThrowNew(clazz, "Future was discarded"); return NULL; } CHECK_READY(*future); if (future->get()) { jclass clazz = env->FindClass("java/lang/Boolean"); return env->GetStaticObjectField( clazz, env->GetStaticFieldID(clazz, "TRUE", "Ljava/lang/Boolean;")); } jclass clazz = env->FindClass("java/lang/Boolean"); return env->GetStaticObjectField( clazz, env->GetStaticFieldID(clazz, "FALSE", "Ljava/lang/Boolean;")); } clazz = env->FindClass("java/util/concurrent/TimeoutException"); env->ThrowNew(clazz, "Failed to wait for future within timeout"); return NULL; }
/* * Class: org_apache_mesos_state_ZooKeeperState * Method: __fetch_get_timeout * Signature: (JJLjava/util/concurrent/TimeUnit;)Lorg/apache/mesos/state/Variable; */ JNIEXPORT jobject JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1fetch_1get_1timeout (JNIEnv* env, jobject thiz, jlong jfuture, jlong jtimeout, jobject junit) { Future<Variable>* future = (Future<Variable>*) jfuture; jclass clazz = env->GetObjectClass(junit); // long seconds = unit.toSeconds(time); jmethodID toSeconds = env->GetMethodID(clazz, "toSeconds", "(J)J"); jlong jseconds = env->CallLongMethod(junit, toSeconds, jtimeout); Seconds seconds(jseconds); if (future->await(seconds)) { if (future->isFailed()) { clazz = env->FindClass("java/util/concurrent/ExecutionException"); env->ThrowNew(clazz, future->failure().c_str()); return NULL; } else if (future->isDiscarded()) { clazz = env->FindClass("java/util/concurrent/CancellationException"); env->ThrowNew(clazz, "Future was discarded"); return NULL; } CHECK(future->isReady()); Variable* variable = new Variable(future->get()); // Variable variable = new Variable(); clazz = env->FindClass("org/apache/mesos/state/Variable"); jmethodID _init_ = env->GetMethodID(clazz, "<init>", "()V"); jobject jvariable = env->NewObject(clazz, _init_); jfieldID __variable = env->GetFieldID(clazz, "__variable", "J"); env->SetLongField(jvariable, __variable, (jlong) variable); return jvariable; } clazz = env->FindClass("java/util/concurrent/TimeoutException"); env->ThrowNew(clazz, "Failed to wait for future within timeout"); return NULL; }
void _read(const Pipe::Reader& reader, const Future<Result<Event>>& event) { CHECK(!event.isDiscarded()); // Ignore enqueued events from the previous Subscribe call reader. if (subscribed.isNone() || subscribed->reader != reader) { VLOG(1) << "Ignoring event from old stale connection"; return; } CHECK_EQ(SUBSCRIBED, state); CHECK_SOME(connectionId); // This could happen if the agent process died while sending a response. if (event.isFailed()) { LOG(ERROR) << "Failed to decode the stream of events: " << event.failure(); disconnected(connectionId.get(), event.failure()); return; } // This could happen if the agent failed over after sending an event. if (event->isNone()) { const string error = "End-Of-File received from agent. The agent closed " "the event stream"; LOG(ERROR) << error; disconnected(connectionId.get(), error); return; } if (event->isError()) { error("Failed to de-serialize event: " + event->error()); return; } receive(event.get().get(), false); read(); }
/* * Class: org_apache_mesos_state_ZooKeeperState * Method: __names_get * Signature: (J)Ljava/util/Iterator; */ JNIEXPORT jobject JNICALL Java_org_apache_mesos_state_ZooKeeperState__1_1names_1get (JNIEnv* env, jobject thiz, jlong jfuture) { Future<vector<string> >* future = (Future<vector<string> >*) jfuture; future->await(); if (future->isFailed()) { jclass clazz = env->FindClass("java/util/concurrent/ExecutionException"); env->ThrowNew(clazz, future->failure().c_str()); return NULL; } else if (future->isDiscarded()) { jclass clazz = env->FindClass("java/util/concurrent/CancellationException"); env->ThrowNew(clazz, "Future was discarded"); return NULL; } CHECK(future->isReady()); // List names = new ArrayList(); jclass clazz = env->FindClass("java/util/ArrayList"); jmethodID _init_ = env->GetMethodID(clazz, "<init>", "()V"); jobject jnames = env->NewObject(clazz, _init_); jmethodID add = env->GetMethodID(clazz, "add", "(Ljava/lang/Object;)Z"); foreach (const string& name, future->get()) { jobject jname = convert<string>(env, name); env->CallBooleanMethod(jnames, add, jname); } // Iterator iterator = jnames.iterator(); jmethodID iterator = env->GetMethodID(clazz, "iterator", "()Ljava/util/Iterator;"); jobject jiterator = env->CallObjectMethod(jnames, iterator); return jiterator; }
void LeaderContenderProcess::joined() { CHECK(!candidacy.isDiscarded()); // Cannot be watching because the candidacy is not obtained yet. CHECK_NONE(watching); CHECK_SOME(contending); if (candidacy.isFailed()) { // The promise 'withdrawing' will be set to false in cancel(). contending.get()->fail(candidacy.failure()); return; } if (withdrawing.isSome()) { LOG(INFO) << "Joined group after the contender started withdrawing"; // The promise 'withdrawing' will be set to 'false' in subsequent // 'cancel()' call. return; } LOG(INFO) << "New candidate (id='" << candidacy->id() << "') has entered the contest for leadership"; // Transition to 'watching' state. watching = new Promise<Nothing>(); // Notify the client. if (contending.get()->set(watching.get()->future())) { // Continue to watch that our membership is not removed (if the // client still cares about it). candidacy->cancelled() .onAny(defer(self(), &Self::cancelled, lambda::_1)); } }
void _send( const UUID& _connectionId, const Call& call, const Future<Response>& response) { // It is possible that the agent process failed before a response could // be received. if (connectionId != _connectionId) { return; } CHECK(!response.isDiscarded()); CHECK(state == SUBSCRIBING || state == SUBSCRIBED) << state; // This can happen if the agent process is restarted or a network blip // caused the socket to timeout. Eventually, the executor would // detect the socket disconnection via the disconnected callback. if (response.isFailed()) { LOG(ERROR) << "Request for call type " << call.type() << " failed: " << response.failure(); return; } if (response->code == process::http::Status::OK) { // Only SUBSCRIBE call should get a "200 OK" response. CHECK_EQ(Call::SUBSCRIBE, call.type()); CHECK_EQ(response->type, Response::PIPE); CHECK_SOME(response->reader); state = SUBSCRIBED; Pipe::Reader reader = response->reader.get(); auto deserializer = lambda::bind(deserialize<Event>, contentType, lambda::_1); Owned<Reader<Event>> decoder( new Reader<Event>(Decoder<Event>(deserializer), reader)); subscribed = SubscribedResponse {reader, decoder}; read(); return; } if (response->code == process::http::Status::ACCEPTED) { // Only non SUBSCRIBE calls should get a "202 Accepted" response. CHECK_NE(Call::SUBSCRIBE, call.type()); return; } // We reset the state to connected if the subscribe call did not // succceed (e.g., the agent has not yet set up HTTP routes). The executor // can then retry the subscribe call. if (call.type() == Call::SUBSCRIBE) { state = CONNECTED; } if (response->code == process::http::Status::SERVICE_UNAVAILABLE) { // This could happen if the agent is still in the process of recovery. LOG(WARNING) << "Received '" << response->status << "' (" << response->body << ") for " << call.type(); return; } if (response->code == process::http::Status::NOT_FOUND) { // This could happen if the agent libprocess process has not yet set up // HTTP routes. LOG(WARNING) << "Received '" << response->status << "' (" << response->body << ") for " << call.type(); return; } // We should not be able to get here since we already do validation // of calls before sending them to the agent. error("Received unexpected '" + response->status + "' (" + response->body + ") for " + stringify(call.type())); }
void PosixDiskIsolatorProcess::_collect( const ContainerID& containerId, const string& path, const Future<Bytes>& future) { if (future.isDiscarded()) { LOG(INFO) << "Checking disk usage at '" << path << "' for container " << containerId << " has been cancelled"; } else if (future.isFailed()) { LOG(ERROR) << "Checking disk usage at '" << path << "' for container " << containerId << " has failed: " << future.failure(); } if (!infos.contains(containerId)) { // The container might have just been destroyed. return; } const Owned<Info>& info = infos[containerId]; if (!info->paths.contains(path)) { // The path might have just been removed from this container's // resources. return; } // Check if the disk usage exceeds the quota. If yes, report the // limitation. We keep collecting the disk usage for 'path' by // initiating another round of disk usage check. The check will be // throttled by DiskUsageCollector. if (future.isReady()) { // Save the last disk usage. info->paths[path].lastUsage = future.get(); // We need to ignore the quota enforcement check for MOUNT type // disk resources because its quota will be enforced by the // underlying filesystem. bool isDiskSourceMount = false; foreach (const Resource& resource, info->paths[path].quota) { if (resource.has_disk() && resource.disk().has_source() && resource.disk().source().type() == Resource::DiskInfo::Source::MOUNT) { isDiskSourceMount = true; } } if (flags.enforce_container_disk_quota && !isDiskSourceMount) { Option<Bytes> quota = info->paths[path].quota.disk(); CHECK_SOME(quota); if (future.get() > quota.get()) { info->limitation.set( protobuf::slave::createContainerLimitation( Resources(info->paths[path].quota), "Disk usage (" + stringify(future.get()) + ") exceeds quota (" + stringify(quota.get()) + ")", TaskStatus::REASON_CONTAINER_LIMITATION_DISK)); } } }
int main(int argc, char** argv) { Flags flags; flags.setUsageMessage("Usage: " + Path(argv[0]).basename() + " <master>"); // Load flags from environment and command line, and remove // them from argv. Try<flags::Warnings> load = flags.load(None(), &argc, &argv); if (flags.help) { cout << flags.usage() << endl; return EXIT_SUCCESS; } if (load.isError()) { cerr << flags.usage(load.error()) << endl; return EXIT_FAILURE; } // Log any flag warnings. foreach (const flags::Warning& warning, load->warnings) { cerr << warning.message << endl; } // 'master' argument must be the only argument left after parsing. if (argc != 2) { cerr << flags.usage("There must be only one argument: <master>") << endl; return EXIT_FAILURE; } string master = argv[1]; Try<mesos::master::detector::MasterDetector*> detector = mesos::master::detector::MasterDetector::create(master); if (detector.isError()) { cerr << "Failed to create a master detector: " << detector.error() << endl; return EXIT_FAILURE; } Future<Option<MasterInfo>> masterInfo = detector.get()->detect(); if (!masterInfo.await(flags.timeout)) { cerr << "Failed to detect master from '" << master << "' within " << flags.timeout << endl; return -1; } else { CHECK(!masterInfo.isDiscarded()); if (masterInfo.isFailed()) { cerr << "Failed to detect master from '" << master << "': " << masterInfo.failure() << endl; return EXIT_FAILURE; } } // The future is not satisfied unless the result is Some. CHECK_SOME(masterInfo.get()); cout << strings::remove(masterInfo.get().get().pid(), "master@") << endl; return EXIT_SUCCESS; }
Try<Nothing> Initialize::execute(int argc, char** argv) { flags.setUsageMessage( "Usage: " + name() + " [option]\n" "\n" "This command is used to initialize the log.\n" "\n"); // Configure the tool by parsing command line arguments. if (argc > 0 && argv != NULL) { Try<Nothing> load = flags.load(None(), argc, argv); if (load.isError()) { return Error(flags.usage(load.error())); } if (flags.help) { return Error(flags.usage()); } process::initialize(); logging::initialize(argv[0], flags); } if (flags.path.isNone()) { return Error(flags.usage("Missing required option --path")); } // Setup the timeout if specified. Option<Timeout> timeout = None(); if (flags.timeout.isSome()) { timeout = Timeout::in(flags.timeout.get()); } Replica replica(flags.path.get()); // Get the current status of the replica. Future<Metadata::Status> status = replica.status(); if (timeout.isSome()) { status.await(timeout.get().remaining()); } else { status.await(); } if (status.isPending()) { return Error("Timed out while getting replica status"); } else if (status.isDiscarded()) { return Error("Failed to get status of replica (discarded future)"); } else if (status.isFailed()) { return Error(status.failure()); } // We only initialize a log if it is empty. if (status.get() != Metadata::EMPTY) { return Error("The log is not empty"); } // Update the status of the replica to VOTING. Future<bool> update = replica.update(Metadata::VOTING); if (timeout.isSome()) { update.await(timeout.get().remaining()); } else { update.await(); } if (update.isPending()) { return Error("Timed out while setting replica status"); } else if (update.isDiscarded()) { return Error("Failed to set replica status (discarded future)"); } else if (update.isFailed()) { return Error(update.failure()); } return Nothing(); }
void _healthCheck() { if (check.has_http()) { promise.fail("HTTP health check is not supported"); return; } if (!check.has_command()) { promise.fail("No check found in health check"); return; } const CommandInfo& command = check.command(); map<string, string> environment = os::environment(); foreach (const Environment::Variable& variable, command.environment().variables()) { environment[variable.name()] = variable.value(); } // Launch the subprocess. Option<Try<Subprocess>> external = None(); if (command.shell()) { // Use the shell variant. if (!command.has_value()) { promise.fail("Shell command is not specified"); return; } VLOG(2) << "Launching health command '" << command.value() << "'"; external = process::subprocess( command.value(), Subprocess::PATH("/dev/null"), Subprocess::FD(STDERR_FILENO), Subprocess::FD(STDERR_FILENO), environment); } else { // Use the exec variant. if (!command.has_value()) { promise.fail("Executable path is not specified"); return; } vector<string> argv; foreach (const string& arg, command.arguments()) { argv.push_back(arg); } VLOG(2) << "Launching health command [" << command.value() << ", " << strings::join(", ", argv) << "]"; external = process::subprocess( command.value(), argv, Subprocess::PATH("/dev/null"), Subprocess::FD(STDERR_FILENO), Subprocess::FD(STDERR_FILENO), None(), environment); } CHECK_SOME(external); if (external.get().isError()) { failure("Error creating subprocess for healthcheck: " + external.get().error()); return; } pid_t commandPid = external.get().get().pid(); Future<Option<int>> status = external.get().get().status(); status.await(Seconds(check.timeout_seconds())); if (!status.isReady()) { string msg = "Command check failed with reason: "; if (status.isFailed()) { msg += "failed with error: " + status.failure(); } else if (status.isDiscarded()) { msg += "status future discarded"; } else { msg += "status still pending after timeout " + stringify(Seconds(check.timeout_seconds())); } if (commandPid != -1) { // Cleanup the external command process. os::killtree(commandPid, SIGKILL); VLOG(1) << "Kill health check command " << commandPid; } failure(msg); return; } int statusCode = status.get().get(); if (statusCode != 0) { string message = "Health command check " + WSTRINGIFY(statusCode); failure(message); } else { success(); } }