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(); }
void HealthCheckerProcess::_healthCheck() { Future<Nothing> checkResult; switch (check.type()) { case HealthCheck::COMMAND: { checkResult = _commandHealthCheck(); break; } case HealthCheck::HTTP: { checkResult = _httpHealthCheck(); break; } case HealthCheck::TCP: { checkResult = _tcpHealthCheck(); break; } default: { UNREACHABLE(); } } checkResult.onAny(defer(self(), &Self::__healthCheck, lambda::_1)); }
void CheckerProcess::performCheck() { if (paused) { return; } Stopwatch stopwatch; stopwatch.start(); // There are 3 checks (CMD/HTTP/TCP) for 3 runtimes (PLAIN/DOCKER/NESTED) // for 2 different OSes (Linux/Windows), so we have a 3x3x2 matrix of // possibilities. Luckily, a lot of the cases have the same implementation, // so we don't need to have 18 different code paths. // // Here is a matrix of all the different implementations with explanations. // Note that the format is "Linux/Windows", so the Linux implementation is // before Windows if they differ. // // | CMD | HTTP | TCP // --------+------+------+------- // Plain | A*/A | B | C // Docker | D | B*/E | C*/F // Nested | G/- | B | C // // Explanations: // - A, B, C: Standard check launched directly by the library's user, i.e., // the executor. Specifically, it launches the given command for CMD checks, // `curl` for HTTP checks, and `mesos-tcp-connect` for TCP checks. // - A*, B*, C*: On Linux, the proper namespaces will be entered, which are // the optional "mnt" for CMD and the required "net" for Docker HTTP/TCP. // These checks are executed by the library's user, i.e., the executor. // - D: Delegate the command to Docker by wrapping the command with // `docker exec` to run in the container's namespaces. // - E, F: On Windows, delegate the network checks to Docker by wrapping the // check with the `docker run --network=container:id ...` command to // run the check in the container's namespaces. // - G: The library uses Agent API to delegate running the command in a // nested container on Linux. // - '-': Not implemented (nested command checks on Windows). check.visit( [=](const check::Command& cmd) { Future<int> future = runtime.visit( [=](const runtime::Plain& plain) { // Case A* and A return commandCheck(cmd, plain); }, [=](const runtime::Docker& docker) { // Case D return dockerCommandCheck(cmd, docker); }, [=](const runtime::Nested& nested) { // Case G return nestedCommandCheck(cmd, nested); }); future.onAny(defer( self(), &Self::processCommandCheckResult, stopwatch, lambda::_1)); }, [=](const check::Http& http) { Future<int> future = runtime.visit( [=](const runtime::Plain& plain) { // Case B return httpCheck(http, plain); }, [=](const runtime::Docker& docker) { #ifdef __WINDOWS__ // Case E return dockerHttpCheck(http, docker); #else // Case B* return httpCheck( http, runtime::Plain{docker.namespaces, docker.taskPid}); #endif // __WINDOWS__ }, [=](const runtime::Nested&) { // Case B return httpCheck(http, None()); }); future.onAny(defer( self(), &Self::processHttpCheckResult, stopwatch, lambda::_1)); }, [=](const check::Tcp& tcp) { Future<bool> future = runtime.visit( [=](const runtime::Plain& plain) { // Case C return tcpCheck(tcp, plain); }, [=](const runtime::Docker& docker) { #ifdef __WINDOWS__ // Case F return dockerTcpCheck(tcp, docker); #else // Case C* return tcpCheck( tcp, runtime::Plain{docker.namespaces, docker.taskPid}); #endif // __WINDOWS__ }, [=](const runtime::Nested&) { // Case C return tcpCheck(tcp, None()); }); future.onAny( defer(self(), &Self::processTcpCheckResult, stopwatch, lambda::_1)); }); }