bool waitForTick(const std::shared_ptr<PermissionsRunnable>& runnable) {
  size_t now = runnable->ticks;
  size_t timeout = 1000;
  size_t delay = 0;
  while (delay < timeout) {
    sleepFor(20);
    if (runnable->ticks > now) {
      return true;
    }
    sleepFor(200);
    delay += 220;
  }
  return false;
}
 MONGO_FAIL_POINT_BLOCK(setYieldAllLocksWait, customWait) {
     const BSONObj& data = customWait.getData();
     BSONElement customWaitNS = data["namespace"];
     if (!customWaitNS || planExecNS.ns() == customWaitNS.str()) {
         sleepFor(Milliseconds(data["waitForMillis"].numberInt()));
     }
 }
void ShardingUptimeReporter::startPeriodicThread() {
    invariant(!_thread.joinable());

    _thread = stdx::thread([] {
        Client::initThread("Uptime reporter");

        const std::string hostName(getHostNameCached());
        const std::string instanceId(constructInstanceIdString(hostName));
        const Timer upTimeTimer;

        while (!globalInShutdownDeprecated()) {
            {
                auto opCtx = cc().makeOperationContext();
                reportStatus(opCtx.get(), instanceId, hostName, upTimeTimer);

                auto status = Grid::get(opCtx.get())
                                  ->getBalancerConfiguration()
                                  ->refreshAndCheck(opCtx.get());
                if (!status.isOK()) {
                    warning() << "failed to refresh mongos settings" << causedBy(status);
                }
            }

            MONGO_IDLE_THREAD_BLOCK;
            sleepFor(kUptimeReportInterval);
        }
    });
}
void ShardingUptimeReporter::startPeriodicThread() {
    invariant(!_thread.joinable());

    _thread = stdx::thread([this] {
        Client::initThread("Uptime reporter");

        const std::string instanceId(constructInstanceIdString());
        const Timer upTimeTimer;

        while (!inShutdown()) {
            {
                auto txn = cc().makeOperationContext();
                reportStatus(txn.get(), instanceId, upTimeTimer);

                auto status =
                    Grid::get(txn.get())->getBalancerConfiguration()->refreshAndCheck(txn.get());
                if (!status.isOK()) {
                    warning() << "failed to refresh mongos settings" << causedBy(status);
                }
            }

            sleepFor(kUptimeReportInterval);
        }
    });
}
Example #5
0
void showLoad(){
    printf("|");
    sleepFor(100);
    printf("\b");
    fflush(stdout);
    printf("/");
    sleepFor(100);
    printf("\b");
    fflush(stdout);
    printf("-");
    sleepFor(100);
    printf("\b");
    fflush(stdout);
    printf("|");
    sleepFor(100);
    printf("\b");
    fflush(stdout);
    printf("/");
    sleepFor(100);
    printf("\b");
    fflush(stdout);
    printf("-");
    sleepFor(100);
    printf("\b");
    fflush(stdout);
    printf("|");
    sleepFor(100);
    printf("\b");
    fflush(stdout);
}
Example #6
0
void waitForConfig(std::shared_ptr<TestConfigPlugin>& plugin, size_t count) {
  // Max wait of 3 seconds.
  size_t delay = 3000;
  while (delay > 0) {
    if (plugin->genConfigCount > count) {
      break;
    }
    delay -= 20;
    sleepFor(20);
  }
}
Example #7
0
 bool socketExistsLocal(const std::string& check_path) {
   // Wait until the runnable/thread created the socket.
   int delay = 0;
   while (delay < kTimeout) {
     if (osquery::socketExists(check_path).ok()) {
       return true;
     }
     sleepFor(kDelay);
     delay += kDelay;
   }
   return false;
 }
Example #8
0
 bool socketExists(const std::string& socket_path) {
   // Wait until the runnable/thread created the socket.
   int delay = 0;
   while (delay < kTimeoutUS) {
     if (pathExists(socket_path).ok() && isReadable(socket_path).ok()) {
       return true;
     }
     sleepFor(kDelayUS / 1000);
     delay += kDelayUS;
   }
   return false;
 }
Example #9
0
  QueryData query(const std::string& sql, int attempts = 3) {
    // Calling open will except if the socket does not exist.
    QueryData qd;
    for (int i = 0; i < attempts; ++i) {
      try {
        ExtensionManagerClient client(socket_path);

        client.query(sql, qd);
      } catch (const std::exception& /* e */) {
        sleepFor(kDelay);
      }
    }

    return qd;
  }
Example #10
0
  bool ping(int attempts = 3) {
    // Calling open will except if the socket does not exist.
    for (int i = 0; i < attempts; ++i) {
      try {
        ExtensionManagerClient client(socket_path);

        auto status = client.ping();
        return (status.getCode() == (int)ExtensionCode::EXT_SUCCESS);
      } catch (const std::exception& /* e */) {
        sleepFor(kDelay);
      }
    }

    return false;
  }
Example #11
0
void WriteUnitOfWork::commit() {
    invariant(!_committed);
    invariant(!_released);
    invariant(_opCtx->_ruState == RecoveryUnitState::kActiveUnitOfWork);
    if (_toplevel) {
        if (MONGO_FAIL_POINT(sleepBeforeCommit)) {
            sleepFor(Milliseconds(100));
        }

        _opCtx->recoveryUnit()->commitUnitOfWork();
        _opCtx->_ruState = RecoveryUnitState::kNotInUnitOfWork;
    }
    _opCtx->lockState()->endWriteUnitOfWork();
    _committed = true;
}
Example #12
0
  bool ping(int attempts = 3) {
    // Calling open will except if the socket does not exist.
    ExtensionStatus status;
    for (int i = 0; i < attempts; ++i) {
      try {
        EXManagerClient client(socket_path);
        client.get()->ping(status);
        return (status.code == ExtensionCode::EXT_SUCCESS);
      } catch (const std::exception& e) {
        sleepFor(kDelayUS / 1000);
      }
    }

    return false;
  }
Example #13
0
Status checkStalePid(const std::string& content) {
  int pid;
  try {
    pid = boost::lexical_cast<int>(content);
  } catch (const boost::bad_lexical_cast& e) {
    if (FLAGS_force) {
      return Status(0, "Force loading and not parsing pidfile");
    } else {
      return Status(1, "Could not parse pidfile");
    }
  }

  PlatformProcess target(pid);
  int status = 0;

  // The pid is running, check if it is an osqueryd process by name.
  std::stringstream query_text;

  query_text << "SELECT name FROM processes WHERE pid = " << pid
             << " AND name LIKE 'osqueryd%';";

  auto q = SQL(query_text.str());
  if (!q.ok()) {
    return Status(1, "Error querying processes: " + q.getMessageString());
  }

  if (q.rows().size() > 0) {
    // If the process really is osqueryd, return an "error" status.
    if (FLAGS_force) {
      // The caller may choose to abort the existing daemon with --force.
      // Do not use SIGQUIT as it will cause a crash on OS X.
      status = target.kill() ? 0 : -1;
      sleepFor(1000);

      return Status(status, "Tried to force remove the existing osqueryd");
    }

    return Status(1, "osqueryd (" + content + ") is already running");
  } else {
    LOG(INFO) << "Found stale process for osqueryd (" << content
              << ") removing pidfile";
  }

  return Status(0, "OK");
}
Example #14
0
// static
void QueryYield::yieldAllLocks(OperationContext* txn,
                               RecordFetcher* fetcher,
                               const std::string& planExecNS) {
    // Things have to happen here in a specific order:
    //   1) Tell the RecordFetcher to do any setup which needs to happen inside locks
    //   2) Release lock mgr locks
    //   3) Go to sleep
    //   4) Touch the record we're yielding on, if there is one (RecordFetcher::fetch)
    //   5) Reacquire lock mgr locks

    Locker* locker = txn->lockState();

    Locker::LockSnapshot snapshot;

    if (fetcher) {
        fetcher->setup();
    }

    // Nothing was unlocked, just return, yielding is pointless.
    if (!locker->saveLockStateAndUnlock(&snapshot)) {
        return;
    }

    // Top-level locks are freed, release any potential low-level (storage engine-specific
    // locks). If we are yielding, we are at a safe place to do so.
    txn->recoveryUnit()->abandonSnapshot();

    MONGO_FAIL_POINT_BLOCK(setYieldAllLocksWait, customWait) {
        const BSONObj& data = customWait.getData();
        BSONElement customWaitNS = data["namespace"];
        if (!customWaitNS || planExecNS == customWaitNS.str()) {
            sleepFor(stdx::chrono::milliseconds(data["waitForMillis"].numberInt()));
        }
    }

    // Track the number of yields in CurOp.
    CurOp::get(txn)->yielded();

    if (fetcher) {
        fetcher->fetch();
    }

    locker->restoreLockState(snapshot);
}
Example #15
0
  QueryData query(const std::string& sql, int attempts = 3) {
    // Calling open will except if the socket does not exist.
    ExtensionResponse response;
    for (int i = 0; i < attempts; ++i) {
      try {
        EXManagerClient client(socket_path);
        client.get()->query(response, sql);
      } catch (const std::exception& e) {
        sleepFor(kDelayUS / 1000);
      }
    }

    QueryData qd;
    for (const auto& row : response.response) {
      qd.push_back(row);
    }

    return qd;
  }
SignedLogicalTime LogicalTimeValidator::signLogicalTime(OperationContext* opCtx,
                                                        const LogicalTime& newTime) {
    auto keyManager = _getKeyManagerCopy();
    auto keyStatusWith = keyManager->getKeyForSigning(nullptr, newTime);
    auto keyStatus = keyStatusWith.getStatus();

    while (keyStatus == ErrorCodes::KeyNotFound && LogicalClock::get(opCtx)->isEnabled()) {
        keyManager->refreshNow(opCtx);

        keyStatusWith = keyManager->getKeyForSigning(nullptr, newTime);
        keyStatus = keyStatusWith.getStatus();

        if (keyStatus == ErrorCodes::KeyNotFound) {
            sleepFor(kRefreshIntervalIfErrored);
        }
    }

    uassertStatusOK(keyStatus);
    return _getProof(keyStatusWith.getValue(), newTime);
}
Example #17
0
AutoGetCollection::AutoGetCollection(OperationContext* opCtx,
                                     const NamespaceString& nss,
                                     LockMode modeDB,
                                     LockMode modeColl,
                                     ViewMode viewMode)
    : _viewMode(viewMode),
      _autoDb(opCtx, nss.db(), modeDB),
      _collLock(opCtx->lockState(), nss.ns(), modeColl),
      _coll(_autoDb.getDb() ? _autoDb.getDb()->getCollection(opCtx, nss) : nullptr) {
    Database* db = _autoDb.getDb();
    // If the database exists, but not the collection, check for views.
    if (_viewMode == ViewMode::kViewsForbidden && db && !_coll &&
        db->getViewCatalog()->lookup(opCtx, nss.ns()))
        uasserted(ErrorCodes::CommandNotSupportedOnView,
                  str::stream() << "Namespace " << nss.ns() << " is a view, not a collection");

    // Wait for a configured amount of time after acquiring locks if the failpoint is enabled.
    MONGO_FAIL_POINT_BLOCK(setAutoGetCollectionWait, customWait) {
        const BSONObj& data = customWait.getData();
        sleepFor(Milliseconds(data["waitForMillis"].numberInt()));
    }
}
Example #18
0
void Balancer::run() {
    Client::initThread("Balancer");

    // This is the body of a BackgroundJob so if we throw here we're basically ending the balancer
    // thread prematurely.
    while (!inShutdown()) {
        auto txn = cc().makeOperationContext();
        if (!_init(txn.get())) {
            log() << "will retry to initialize balancer in one minute";
            sleepsecs(60);
            continue;
        }

        break;
    }

    Seconds balanceRoundInterval(kBalanceRoundDefaultInterval);

    while (!inShutdown()) {
        auto txn = cc().makeOperationContext();

        BalanceRoundDetails roundDetails;

        try {
            // ping has to be first so we keep things in the config server in sync
            _ping(txn.get(), false);

            MONGO_FAIL_POINT_BLOCK(balancerRoundIntervalSetting, scopedBalancerRoundInterval) {
                const BSONObj& data = scopedBalancerRoundInterval.getData();
                balanceRoundInterval = Seconds(data["sleepSecs"].numberInt());
            }

            // Use fresh shard state and balancer settings
            Grid::get(txn.get())->shardRegistry()->reload(txn.get());

            auto balancerConfig = Grid::get(txn.get())->getBalancerConfiguration();
            Status refreshStatus = balancerConfig->refreshAndCheck(txn.get());
            if (!refreshStatus.isOK()) {
                warning() << "Skipping balancing round" << causedBy(refreshStatus);
                sleepFor(balanceRoundInterval);
                continue;
            }

            // now make sure we should even be running
            if (!balancerConfig->isBalancerActive() || MONGO_FAIL_POINT(skipBalanceRound)) {
                LOG(1) << "skipping balancing round because balancing is disabled";

                // Ping again so scripts can determine if we're active without waiting
                _ping(txn.get(), true);

                sleepFor(balanceRoundInterval);
                continue;
            }

            uassert(13258, "oids broken after resetting!", _checkOIDs(txn.get()));

            {
                auto scopedDistLock = grid.catalogManager(txn.get())
                                          ->distLock(txn.get(),
                                                     "balancer",
                                                     "doing balance round",
                                                     DistLockManager::kSingleLockAttemptTimeout);

                if (!scopedDistLock.isOK()) {
                    LOG(1) << "skipping balancing round" << causedBy(scopedDistLock.getStatus());

                    // Ping again so scripts can determine if we're active without waiting
                    _ping(txn.get(), true);

                    sleepFor(balanceRoundInterval);  // no need to wake up soon
                    continue;
                }

                LOG(1) << "*** start balancing round. "
                       << "waitForDelete: " << balancerConfig->waitForDelete()
                       << ", secondaryThrottle: "
                       << balancerConfig->getSecondaryThrottle().toBSON();

                OCCASIONALLY warnOnMultiVersion(
                    uassertStatusOK(_clusterStats->getStats(txn.get())));

                Status status = _enforceTagRanges(txn.get());
                if (!status.isOK()) {
                    warning() << "Failed to enforce tag ranges" << causedBy(status);
                } else {
                    LOG(1) << "Done enforcing tag range boundaries.";
                }

                const auto candidateChunks = uassertStatusOK(
                    _chunkSelectionPolicy->selectChunksToMove(txn.get(), _balancedLastTime));

                if (candidateChunks.empty()) {
                    LOG(1) << "no need to move any chunk";
                    _balancedLastTime = 0;
                } else {
                    _balancedLastTime = _moveChunks(txn.get(),
                                                    candidateChunks,
                                                    balancerConfig->getSecondaryThrottle(),
                                                    balancerConfig->waitForDelete());

                    roundDetails.setSucceeded(static_cast<int>(candidateChunks.size()),
                                              _balancedLastTime);

                    grid.catalogManager(txn.get())
                        ->logAction(txn.get(), "balancer.round", "", roundDetails.toBSON());
                }

                LOG(1) << "*** End of balancing round";
            }

            // Ping again so scripts can determine if we're active without waiting
            _ping(txn.get(), true);

            sleepFor(_balancedLastTime ? kShortBalanceRoundInterval : balanceRoundInterval);
        } catch (const std::exception& e) {
            log() << "caught exception while doing balance: " << e.what();

            // Just to match the opening statement if in log level 1
            LOG(1) << "*** End of balancing round";

            // This round failed, tell the world!
            roundDetails.setFailed(e.what());

            grid.catalogManager(txn.get())
                ->logAction(txn.get(), "balancer.round", "", roundDetails.toBSON());

            // Sleep a fair amount before retrying because of the error
            sleepFor(balanceRoundInterval);
        }
    }
}
/**
 * Outline:
 *
 * 1. Get oplog with session info from the source shard.
 * 2. For each oplog entry, convert to type 'n' if not yet type 'n' while preserving all info
 *    needed for retryable writes.
 * 3. Also update the sessionCatalog for every oplog entry.
 * 4. Once the source shard returned an empty oplog buffer, it means that this should enter
 *    ReadyToCommit state and wait for the commit signal (by calling finish()).
 * 5. Once finish() is called, keep on trying to get more oplog from the source shard until it
 *    returns an empty result again.
 * 6. Wait for writes to be committed to majority of the replica set.
 */
void SessionCatalogMigrationDestination::_retrieveSessionStateFromSource(ServiceContext* service) {
    Client::initThread(
        "sessionCatalogMigration-" + _migrationSessionId.toString(), service, nullptr);

    auto uniqueCtx = cc().makeOperationContext();
    auto opCtx = uniqueCtx.get();

    bool oplogDrainedAfterCommiting = false;
    ProcessOplogResult lastResult;
    repl::OpTime lastOpTimeWaited;

    while (true) {
        {
            stdx::lock_guard<stdx::mutex> lk(_mutex);
            if (_state == State::ErrorOccurred) {
                return;
            }
        }

        try {
            auto nextBatch = getNextSessionOplogBatch(opCtx, _fromShard, _migrationSessionId);
            BSONArray oplogArray(nextBatch[kOplogField].Obj());
            BSONArrayIteratorSorted oplogIter(oplogArray);

            if (!oplogIter.more()) {
                {
                    stdx::lock_guard<stdx::mutex> lk(_mutex);
                    if (_state == State::Committing) {
                        // The migration is considered done only when it gets an empty result from
                        // the source shard while this is in state committing. This is to make sure
                        // that it doesn't miss any new oplog created between the time window where
                        // this depleted the buffer from the source shard and receiving the commit
                        // command.
                        if (oplogDrainedAfterCommiting) {
                            break;
                        }

                        oplogDrainedAfterCommiting = true;
                    }
                }

                WriteConcernResult wcResult;
                auto wcStatus =
                    waitForWriteConcern(opCtx, lastResult.oplogTime, kMajorityWC, &wcResult);
                if (!wcStatus.isOK()) {
                    _errorOccurred(wcStatus.toString());
                    return;
                }

                // We depleted the buffer at least once, transition to ready for commit.
                {
                    stdx::lock_guard<stdx::mutex> lk(_mutex);
                    // Note: only transition to "ready to commit" if state is not error/force stop.
                    if (_state == State::Migrating) {
                        _state = State::ReadyToCommit;
                        _isStateChanged.notify_all();
                    }
                }

                if (lastOpTimeWaited == lastResult.oplogTime) {
                    // We got an empty result at least twice in a row from the source shard so
                    // space it out a little bit so we don't hammer the shard.
                    opCtx->sleepFor(Milliseconds(200));
                }

                lastOpTimeWaited = lastResult.oplogTime;
            }

            while (oplogIter.more()) {
                lastResult = processSessionOplog(opCtx, oplogIter.next().Obj(), lastResult);
            }
        } catch (const DBException& excep) {
            if (excep.code() == ErrorCodes::ConflictingOperationInProgress ||
                excep.code() == ErrorCodes::TransactionTooOld) {
                // This means that the server has a newer txnNumber than the oplog being migrated,
                // so just skip it.
                continue;
            }

            if (excep.code() == ErrorCodes::CommandNotFound) {
                // TODO: remove this after v3.7
                //
                // This means that the donor shard is running at an older version so it is safe to
                // just end this because there is no session information to transfer.
                break;
            }

            _errorOccurred(excep.toString());
            return;
        }
    }

    WriteConcernResult wcResult;
    auto wcStatus = waitForWriteConcern(opCtx, lastResult.oplogTime, kMajorityWC, &wcResult);
    if (!wcStatus.isOK()) {
        _errorOccurred(wcStatus.toString());
        return;
    }

    {
        stdx::lock_guard<stdx::mutex> lk(_mutex);
        _state = State::Done;
        _isStateChanged.notify_all();
    }
}
StatusWith<DistLockManager::ScopedDistLock> ReplSetDistLockManager::lock(
    StringData name, StringData whyMessage, milliseconds waitFor, milliseconds lockTryInterval) {
    Timer timer(_serviceContext->getTickSource());
    Timer msgTimer(_serviceContext->getTickSource());

    while (waitFor <= milliseconds::zero() || milliseconds(timer.millis()) < waitFor) {
        OID lockSessionID = OID::gen();
        string who = str::stream() << _processID << ":" << getThreadName();

        auto lockExpiration = _lockExpiration;
        MONGO_FAIL_POINT_BLOCK(setDistLockTimeout, customTimeout) {
            const BSONObj& data = customTimeout.getData();
            lockExpiration = stdx::chrono::milliseconds(data["timeoutMs"].numberInt());
        }
        LOG(1) << "trying to acquire new distributed lock for " << name
               << " ( lock timeout : " << durationCount<Milliseconds>(lockExpiration)
               << " ms, ping interval : " << durationCount<Milliseconds>(_pingInterval)
               << " ms, process : " << _processID << " )"
               << " with lockSessionID: " << lockSessionID << ", why: " << whyMessage;

        auto lockResult =
            _catalog->grabLock(name, lockSessionID, who, _processID, Date_t::now(), whyMessage);

        auto status = lockResult.getStatus();

        if (status.isOK()) {
            // Lock is acquired since findAndModify was able to successfully modify
            // the lock document.
            LOG(0) << "distributed lock '" << name << "' acquired, ts : " << lockSessionID;
            return ScopedDistLock(lockSessionID, this);
        }

        if (status != ErrorCodes::LockStateChangeFailed) {
            // An error occurred but the write might have actually been applied on the
            // other side. Schedule an unlock to clean it up just in case.
            queueUnlock(lockSessionID);
            return status;
        }

        // Get info from current lock and check if we can overtake it.
        auto getLockStatusResult = _catalog->getLockByName(name);
        const auto& getLockStatus = getLockStatusResult.getStatus();

        if (!getLockStatusResult.isOK() && getLockStatus != ErrorCodes::LockNotFound) {
            return getLockStatus;
        }

        // Note: Only attempt to overtake locks that actually exists. If lock was not
        // found, use the normal grab lock path to acquire it.
        if (getLockStatusResult.isOK()) {
            auto currentLock = getLockStatusResult.getValue();
            auto canOvertakeResult = canOvertakeLock(currentLock, lockExpiration);

            if (!canOvertakeResult.isOK()) {
                return canOvertakeResult.getStatus();
            }

            if (canOvertakeResult.getValue()) {
                auto overtakeResult = _catalog->overtakeLock(name,
                                                             lockSessionID,
                                                             currentLock.getLockID(),
                                                             who,
                                                             _processID,
                                                             Date_t::now(),
                                                             whyMessage);

                const auto& overtakeStatus = overtakeResult.getStatus();

                if (overtakeResult.isOK()) {
                    // Lock is acquired since findAndModify was able to successfully modify
                    // the lock document.

                    LOG(0) << "lock '" << name << "' successfully forced";
                    LOG(0) << "distributed lock '" << name << "' acquired, ts : " << lockSessionID;
                    return ScopedDistLock(lockSessionID, this);
                }

                if (overtakeStatus != ErrorCodes::LockStateChangeFailed) {
                    // An error occurred but the write might have actually been applied on the
                    // other side. Schedule an unlock to clean it up just in case.
                    queueUnlock(lockSessionID);
                    return overtakeStatus;
                }
            }
        }

        LOG(1) << "distributed lock '" << name << "' was not acquired.";

        if (waitFor == milliseconds::zero()) {
            break;
        }

        // Periodically message for debugging reasons
        if (msgTimer.seconds() > 10) {
            LOG(0) << "waited " << timer.seconds() << "s for distributed lock " << name << " for "
                   << whyMessage;

            msgTimer.reset();
        }

        milliseconds timeRemaining =
            std::max(milliseconds::zero(), waitFor - milliseconds(timer.millis()));
        sleepFor(std::min(lockTryInterval, timeRemaining));
    }

    return {ErrorCodes::LockBusy, str::stream() << "timed out waiting for " << name};
}
int main(int argc, char* argv[]) {
    signal(SIGINT, sig_int);
    unsigned int unslept = sleepFor(1);
    printf("sleepFor returned: %u\n", unslept);
    return 0;
}
StatusWith<DistLockManager::ScopedDistLock> LegacyDistLockManager::lock(
    OperationContext* txn,
    StringData name,
    StringData whyMessage,
    milliseconds waitFor,
    milliseconds lockTryInterval) {
    auto distLock = stdx::make_unique<DistributedLock>(_configServer, name.toString());

    {
        stdx::lock_guard<stdx::mutex> sl(_mutex);

        if (_isStopped) {
            return Status(ErrorCodes::LockBusy, "legacy distlock manager is stopped");
        }

        if (_pingerEnabled) {
            auto pingStatus = _pinger->startPing(*(distLock.get()), kDefaultPingInterval);
            if (!pingStatus.isOK()) {
                return pingStatus;
            }
        }
    }

    auto lastStatus =
        Status(ErrorCodes::LockBusy, str::stream() << "timed out waiting for " << name);

    Timer timer;
    Timer msgTimer;
    while (waitFor <= milliseconds::zero() || milliseconds(timer.millis()) < waitFor) {
        bool acquired = false;
        BSONObj lockDoc;
        try {
            acquired = distLock->lock_try(
                whyMessage.toString(), &lockDoc, durationCount<Seconds>(kDefaultSocketTimeout));

            if (!acquired) {
                lastStatus = Status(ErrorCodes::LockBusy,
                                    str::stream() << "Lock for " << whyMessage << " is taken.");
            }
        } catch (const LockException& lockExcep) {
            OID needUnlockID(lockExcep.getMustUnlockID());
            if (needUnlockID.isSet()) {
                _pinger->addUnlockOID(needUnlockID);
            }

            lastStatus = lockExcep.toStatus();
        } catch (...) {
            lastStatus = exceptionToStatus();
        }

        if (acquired) {
            verify(!lockDoc.isEmpty());

            auto locksTypeResult = LocksType::fromBSON(lockDoc);
            if (!locksTypeResult.isOK()) {
                return StatusWith<ScopedDistLock>(
                    ErrorCodes::UnsupportedFormat,
                    str::stream() << "error while parsing lock document: " << lockDoc << " : "
                                  << locksTypeResult.getStatus().toString());
            }
            const LocksType& lock = locksTypeResult.getValue();
            dassert(lock.isLockIDSet());

            {
                stdx::lock_guard<stdx::mutex> sl(_mutex);
                _lockMap.insert(std::make_pair(lock.getLockID(), std::move(distLock)));
            }

            return ScopedDistLock(txn, lock.getLockID(), this);
        }

        if (waitFor == milliseconds::zero())
            break;

        if (lastStatus != ErrorCodes::LockBusy) {
            return lastStatus;
        }

        // Periodically message for debugging reasons
        if (msgTimer.seconds() > 10) {
            log() << "waited " << timer.seconds() << "s for distributed lock " << name << " for "
                  << whyMessage << ": " << lastStatus.toString();

            msgTimer.reset();
        }

        milliseconds timeRemaining =
            std::max(milliseconds::zero(), waitFor - milliseconds(timer.millis()));
        sleepFor(std::min(lockTryInterval, timeRemaining));
    }

    return lastStatus;
}
Example #23
0
void Balancer::run() {
    Client::initThread("Balancer");

    // This is the body of a BackgroundJob so if we throw here we're basically ending the balancer
    // thread prematurely.
    while (!inShutdown()) {
        auto txn = cc().makeOperationContext();
        if (!_init(txn.get())) {
            log() << "will retry to initialize balancer in one minute";
            sleepsecs(60);
            continue;
        }

        break;
    }

    Seconds balanceRoundInterval(kBalanceRoundDefaultInterval);

    while (!inShutdown()) {
        auto txn = cc().makeOperationContext();

        BalanceRoundDetails roundDetails;

        try {
            // ping has to be first so we keep things in the config server in sync
            _ping(txn.get());

            MONGO_FAIL_POINT_BLOCK(balancerRoundIntervalSetting, scopedBalancerRoundInterval) {
                const BSONObj& data = scopedBalancerRoundInterval.getData();
                balanceRoundInterval = Seconds(data["sleepSecs"].numberInt());
            }

            BSONObj balancerResult;

            // use fresh shard state
            grid.shardRegistry()->reload(txn.get());

            // refresh chunk size (even though another balancer might be active)
            Chunk::refreshChunkSize(txn.get());

            auto balSettingsResult = grid.catalogManager(txn.get())->getGlobalSettings(
                txn.get(), SettingsType::BalancerDocKey);
            const bool isBalSettingsAbsent =
                balSettingsResult.getStatus() == ErrorCodes::NoMatchingDocument;
            if (!balSettingsResult.isOK() && !isBalSettingsAbsent) {
                warning() << balSettingsResult.getStatus();
                return;
            }

            const SettingsType& balancerConfig =
                isBalSettingsAbsent ? SettingsType{} : balSettingsResult.getValue();

            // now make sure we should even be running
            if ((!isBalSettingsAbsent && !Chunk::shouldBalance(balancerConfig)) ||
                MONGO_FAIL_POINT(skipBalanceRound)) {
                LOG(1) << "skipping balancing round because balancing is disabled";

                // Ping again so scripts can determine if we're active without waiting
                _ping(txn.get(), true);

                sleepFor(balanceRoundInterval);
                continue;
            }

            uassert(13258, "oids broken after resetting!", _checkOIDs(txn.get()));

            {
                auto scopedDistLock = grid.catalogManager(txn.get())
                                          ->distLock(txn.get(),
                                                     "balancer",
                                                     "doing balance round",
                                                     DistLockManager::kSingleLockAttemptTimeout);

                if (!scopedDistLock.isOK()) {
                    LOG(1) << "skipping balancing round" << causedBy(scopedDistLock.getStatus());

                    // Ping again so scripts can determine if we're active without waiting
                    _ping(txn.get(), true);

                    sleepFor(balanceRoundInterval);  // no need to wake up soon
                    continue;
                }

                const bool waitForDelete =
                    (balancerConfig.isWaitForDeleteSet() ? balancerConfig.getWaitForDelete()
                                                         : false);

                MigrationSecondaryThrottleOptions secondaryThrottle(
                    MigrationSecondaryThrottleOptions::create(
                        MigrationSecondaryThrottleOptions::kDefault));
                if (balancerConfig.isKeySet()) {
                    secondaryThrottle =
                        uassertStatusOK(MigrationSecondaryThrottleOptions::createFromBalancerConfig(
                            balancerConfig.toBSON()));
                }

                LOG(1) << "*** start balancing round. "
                       << "waitForDelete: " << waitForDelete
                       << ", secondaryThrottle: " << secondaryThrottle.toBSON();

                const auto candidateChunks = uassertStatusOK(_getCandidateChunks(txn.get()));

                if (candidateChunks.empty()) {
                    LOG(1) << "no need to move any chunk";
                    _balancedLastTime = 0;
                } else {
                    _balancedLastTime =
                        _moveChunks(txn.get(), candidateChunks, secondaryThrottle, waitForDelete);

                    roundDetails.setSucceeded(static_cast<int>(candidateChunks.size()),
                                              _balancedLastTime);

                    grid.catalogManager(txn.get())
                        ->logAction(txn.get(), "balancer.round", "", roundDetails.toBSON());
                }

                LOG(1) << "*** End of balancing round";
            }

            // Ping again so scripts can determine if we're active without waiting
            _ping(txn.get(), true);

            sleepFor(_balancedLastTime ? kShortBalanceRoundInterval : balanceRoundInterval);
        } catch (const std::exception& e) {
            log() << "caught exception while doing balance: " << e.what();

            // Just to match the opening statement if in log level 1
            LOG(1) << "*** End of balancing round";

            // This round failed, tell the world!
            roundDetails.setFailed(e.what());

            grid.catalogManager(txn.get())
                ->logAction(txn.get(), "balancer.round", "", roundDetails.toBSON());

            // Sleep a fair amount before retrying because of the error
            sleepFor(balanceRoundInterval);
        }
    }
}
Example #24
0
int main()
{
    char loading = 0;
    char wrongCommand = 0;
    char win = 0;
    bool inGame = true;
    char AttsServers = 20;
    char VerizonServers = 20;
    int VerizonAttack = 0;
    int DeadServers = 0;
    int ServerLose = 0;
    char password[] = "atts";
    char givenPassword[10];
    char ID[50];
    char IDAdmin[] = "root";
    char Continue[] = "CONTINUE";
    char Manual[] = "MANUAL";
    char Restart[] = "RESTART";
    char Ranking[] = "RANKING";
    char Mitm[] = "MITM";
    char OverCPU[] = "OVERCPU";
    char Fix[] = "FIX";
    char givenCommand[20];
    char Exit[] = "EXIT";
    char Name[50];
    char lineManual[TAILLE_MAX] = "";

    srand(time(NULL));

    FILE* manual = NULL;
    FILE* ranking = NULL;

    printf("Connection to ATTS' servers");
    sleepFor(1000);

    loading = 0;

    while (loading < 10)
    {
        showLoad();
        loading ++;
    }

    printf("\nConnection established\n");
    sleepFor(500);
    printf("Please enter your ID\n");
    printf("ID : ");
    scanf("%s", ID);
    sleepFor(500);

    if (strcmp(ID, IDAdmin) == 0)
    {
        printf("Hi Admin, please enter your password");
    }

    else
    {
        printf("\nWrong ID. You will be rejected by the server in 5 seconds");
        sleepFor(5000);
        return 0;
    }

    printf("\nPassword : "******"%s", givenPassword);

    loading = 0;

    while (loading < 5)
    {
        showLoad();
        loading ++;
    }

    printf("\b");

    if (strcmp(givenPassword, password) == 0)
    {
        printf("Access Granted\n");

        loading = 0;

        while (loading < 5)
        {
            showLoad();
            loading ++;
        }

    printf("\b");
    }

    else
    {
        printf("Wrong password. You will be rejected by the server in 5 seconds");
        sleepFor(5000);
        return 0;
    }

    while (wrongCommand != 1)
    {

        printf("You are now connected, to see the manual type MANUAL, to see the ranking type\nRANKING else type CONTINUE\n");
        printf("command : ");
        scanf("%s", givenCommand);

        loading = 0;

        while (loading < 5)
        {
            showLoad();
            loading ++;
        }

        printf("\b");

        if (strcmp(givenCommand, Manual) == 0)
        {
            manual = fopen("manual.txt", "r");

            if (manual != NULL)
            {
                while (fgets(lineManual, TAILLE_MAX, manual) != NULL)
                {
                    printf("%s", lineManual);
                    sleepFor(500);
                }

                printf("\ncommand :");
                scanf("%s", givenCommand);

                if (strcmp(givenCommand, Restart) == 0)
                {
                    wrongCommand = 0;
                }

                else if (strcmp(givenCommand, Exit) == 0)
                {
                    printf("The program will stop in few seconds");
                    sleepFor(5000);
                    return 0;
                }

                else
                {
                    printf("Wrong command");
                }
            }

            else
            {
                printf("Unknown error detected during the manual opening, the program will restart automatically in few seconds\n");
                sleepFor(5000);
            }

        }

        else if (strcmp(givenCommand, Ranking) == 0)
        {
            ranking = fopen("ranking.txt", "r");

            if (ranking != NULL)
            {
                while (fgets(lineManual, TAILLE_MAX, ranking) != NULL)
                {
                    printf("%s", lineManual);
                    sleepFor(500);
                }

                printf("\nWhen you have read everything you can type RESTART or EXIT");
                printf("\ncommand :");
                scanf("%s", givenCommand);

                if (strcmp(givenCommand, Restart) == 0)
                {
                    wrongCommand = 0;
                }

                else if (strcmp(givenCommand, Exit) == 0)
                {
                    printf("The program will stop in few seconds");
                    sleepFor(5000);
                    return 0;
                }

                else
                {
                    printf("Wrong command");
                }
            }

            else
            {
                printf("Unknown error detected during the ranking file opening, the program will restart automatically in few seconds\n");
                sleepFor(5000);
            }
        }

        else if (strcmp(givenCommand, Continue) == 0)
        {
            printf("Welcome in the Servers Administration Center SAC\nComponents are loading");

            loading = 0;

            while (loading < 10)
            {
                showLoad();
                loading ++;
            }

            printf("\b");

            printf("\nComponents are ready to use\nVerizon is trying to hack your servers but you knew that was planned today!\nIt is your turn!");
            while (inGame != false)
            {
                printf("\ncommand : ");
                scanf("%s", givenCommand);

                loading = 0;

                while (loading < 2)
                {
                    showLoad();
                    loading ++;
                }

                printf("\b");

                if (strcmp(givenCommand, Mitm) == 0)
                {
                    printf("\nVerizon's servers hacked, they lost one server!");

                    VerizonServers --;

                    loading = 0;

                    while (loading < 2)
                    {
                        showLoad();
                        loading ++;
                    }

                    printf("\b");

                    VerizonAttack = rand() % 3;

                    if (VerizonAttack == 0)
                    {
                        printf("\nVerizon uses the MITM method, you lose 1 server");
                        AttsServers --;
                    }

                    else if (VerizonAttack == 1)
                    {
                        printf("\nVerizon allocates a server to overheat your CPU");
                        DeadServers = rand() % 5;
                        sleepFor(500);

                        if (DeadServers == 0)
                        {
                            printf("\nVerizon wastes his attack, you keep all of your servers");
                        }

                        else if (DeadServers == 1)
                        {
                            printf("\nVerizon kills 1 of your servers");
                            AttsServers --;
                        }

                        else if (DeadServers == 2)
                        {
                            printf("\nVerizon kills 2 of your servers");
                            AttsServers -= 2;
                        }

                        else if (DeadServers == 3)
                        {
                            printf("\nVerizon kills 3 of your servers");
                            AttsServers -= 3;
                        }

                        else
                        {
                            printf("\nVerizon kills 4 of your servers");
                            AttsServers -= 4;
                        }

                        sleepFor(500);

                        ServerLose = rand() % 2;

                        if (ServerLose == 0)
                        {
                            printf("\nBy using one of his servers, Verizon lose one of his servers");
                            VerizonServers --;
                        }

                        else
                        {
                            printf("\nVerizon hacks you with his server but don't broke it");
                        }
                    }

                    else
                    {
                        printf("\nVerizon fixes a server");
                        VerizonServers ++;
                    }

                    printf("\nYou have %d servers and Verizon has %d servers...", AttsServers, VerizonServers);
                }

                else if (strcmp(givenCommand, OverCPU) == 0)
                {
                        printf("\nYou allocate a server to overheat their CPU");
                        DeadServers = rand() % 5;
                        sleepFor(500);

                        if (DeadServers == 0)
                        {
                            printf("\nYou waste your attack, they keep all of their servers");
                        }

                        else if (DeadServers == 1)
                        {
                            printf("\nYou kill 1 of their servers");
                            VerizonServers --;
                        }

                        else if (DeadServers == 2)
                        {
                            printf("\nYou kill 2 of their servers");
                            VerizonServers -= 2;
                        }

                        else if (DeadServers == 3)
                        {
                            printf("\nYou kill 3 of their servers");
                            VerizonServers -= 3;
                        }

                        else
                        {
                            printf("\nYou kill 4 of their servers");
                            VerizonServers -= 4;
                        }

                        sleepFor(500);

                        ServerLose = rand() % 2;

                        if (ServerLose == 0)
                        {
                            printf("\nBy using one of his servers, you lose one of your servers");
                            AttsServers --;
                        }

                        else
                        {
                            printf("\nYou hack Verizon with your server but don't broke it");
                        }

                        VerizonAttack = rand() % 3;

                    if (VerizonAttack == 0)
                    {
                        printf("\nVerizon uses the MITM method, you lose 1 server");
                        AttsServers --;
                    }

                    else if (VerizonAttack == 1)
                    {
                        printf("\nVerizon allocates a server to overheat your CPU");
                        DeadServers = rand() % 5;
                        sleepFor(500);

                        if (DeadServers == 0)
                        {
                            printf("\nVerizon wastes his attack, you keep all of your servers");
                        }

                        else if (DeadServers == 1)
                        {
                            printf("\nVerizon kills 1 of your servers");
                            AttsServers --;
                        }

                        else if (DeadServers == 2)
                        {
                            printf("\nVerizon kills 2 of your servers");
                            AttsServers -=2;
                        }

                        else if (DeadServers == 3)
                        {
                            printf("\nVerizon kills 3 of your servers");
                            AttsServers -=3;
                        }

                        else
                        {
                            printf("\nVerizon kills 4 of your servers");
                            AttsServers -=4;
                        }

                        sleepFor(500);

                        ServerLose = rand() % 2;

                        if (ServerLose == 0)
                        {
                            printf("\nBy using one of his servers, Verizon lose one of his servers");
                            VerizonServers --;
                        }

                        else
                        {
                            printf("\nVerizon hacks you with his server but don't broke it");
                        }
                    }

                    else
                    {
                        printf("\nVerizon fixes a server");
                        VerizonServers ++;
                    }

                    printf("\nYou have %d servers and Verizon has %d servers...", AttsServers, VerizonServers);
                }

                else if (strcmp(givenCommand, Fix) == 0)
                {
                    printf("\nYou fix 1 of your servers");
                    AttsServers ++;

                    VerizonAttack = rand() % 3;

                    if (VerizonAttack == 0)
                    {
                        printf("\nVerizon uses the MITM method, you lose 1 server");
                        AttsServers --;
                    }

                    else if (VerizonAttack == 1)
                    {
                        printf("\nVerizon allocates a server to overheat your CPU");
                        DeadServers = rand() % 5;
                        sleepFor(500);

                        if (DeadServers == 0)
                        {
                            printf("\nVerizon wastes his attack, you keep all of your servers");
                        }

                        else if (DeadServers == 1)
                        {
                            printf("\nVerizon kills 1 of your servers");
                            AttsServers --;
                        }

                        else if (DeadServers == 2)
                        {
                            printf("\nVerizon kills 2 of your servers");
                            AttsServers --;
                            AttsServers --;
                        }

                        else if (DeadServers == 3)
                        {
                            printf("\nVerizon kills 3 of your servers");
                            AttsServers --;
                            AttsServers --;
                            AttsServers --;
                        }

                        else
                        {
                            printf("\nVerizon kills 4 of your servers");
                            AttsServers --;
                            AttsServers --;
                            AttsServers --;
                            AttsServers --;
                        }

                        sleepFor(500);

                        ServerLose = rand() % 2;

                        if (ServerLose == 0)
                        {
                            printf("\nBy using one of his servers, Verizon lose one of his servers");
                            VerizonServers --;
                        }

                        else
                        {
                            printf("\nVerizon hacks you with his server but don't broke it");
                        }
                    }

                    else
                    {
                        printf("\nVerizon fixes a server");
                        VerizonServers ++;
                    }

                    printf("\nYou have %d servers and Verizon has %d servers...", AttsServers, VerizonServers);
                }

                else
                {
                    printf("Wrong command! Retry");
                }

                if (AttsServers <= 0)
                {
                    printf("\nYou lose");
                    printf("\nVerizon hits you and kept %d servers", VerizonServers);
                    AttsServers = 20;
                    VerizonServers = 20;
                    inGame = false;
                }
                else if (VerizonServers <= 0)
                {
                    printf("\nYou win!");
                    printf("\nYou hit Verizon, you kept %d servers and ATTS became\nthe biggest company because of you!\n", AttsServers);
                    printf("\nPlease enter your name : ");
                    scanf("%s", Name);
                    printf("%s's Bank Account : 2450$", Name);
                    sleepFor(250);
                    printf("\b\b");
                    sleepFor(250);
                    printf("\b");
                    sleepFor(250);
                    printf("\b");
                    sleepFor(250);
                    printf("\b");
                    sleepFor(250);
                    loading = 0;
                    while(loading <= 15){
                        printf("9");
                        sleepFor(250);
                        loading++;
                    }
                    printf("$");
                    sleepFor(500);
                    printf("\nDear %s,\nTo thank you, we send you a bit of money\nand we promote you Security Team CHIEF!\nCongratulations,\nATTS Inc CEO, Hugues KADI", Name);

                    ranking = fopen("ranking.txt", "a");
                    fprintf(ranking, "\n%s hit Verizon and kept %d servers!", Name, AttsServers);

                    AttsServers = 20;
                    VerizonServers = 20;

                    inGame = false;
                }
            }

                printf("\ncommand RESTART or EXIT : ");
                scanf("%s", givenCommand);

                if (strcmp(givenCommand, Restart) == 0)
                {
                    wrongCommand = 0;
                }

                else if (strcmp(givenCommand, Exit) == 0)
                {
                    printf("The program will stop in few seconds");
                    sleepFor(5000);
                    return 0;
                }

                else
                {
                    printf("Wrong command");
                }


        }

        else if (strcmp(givenCommand, Exit) == 0)
        {
            printf("The program will stop in few seconds");
            sleepFor(5000);
            return 0;
        }

        else
        {
            printf("Wrong command\n");
        }

    }
    return 0;
}
Example #25
0
 void sleepUntil(const SteadyClockTimePoint& t)
 {
   sleepFor(t - SteadyClock::now());
 }
StatusWith<DistLockManager::ScopedDistLock> ReplSetDistLockManager::lock(
    OperationContext* txn,
    StringData name,
    StringData whyMessage,
    milliseconds waitFor,
    milliseconds lockTryInterval) {
    Timer timer(_serviceContext->getTickSource());
    Timer msgTimer(_serviceContext->getTickSource());

    // Counts how many attempts have been made to grab the lock, which have failed with network
    // error. This value is reset for each lock acquisition attempt because these are
    // independent write operations.
    int networkErrorRetries = 0;

    // Distributed lock acquisition works by tring to update the state of the lock to 'taken'. If
    // the lock is currently taken, we will back off and try the acquisition again, repeating this
    // until the lockTryInterval has been reached. If a network error occurs at each lock
    // acquisition attempt, the lock acquisition will be retried immediately.
    while (waitFor <= milliseconds::zero() || milliseconds(timer.millis()) < waitFor) {
        const OID lockSessionID = OID::gen();
        const string who = str::stream() << _processID << ":" << getThreadName();

        auto lockExpiration = _lockExpiration;
        MONGO_FAIL_POINT_BLOCK(setDistLockTimeout, customTimeout) {
            const BSONObj& data = customTimeout.getData();
            lockExpiration = stdx::chrono::milliseconds(data["timeoutMs"].numberInt());
        }

        LOG(1) << "trying to acquire new distributed lock for " << name
               << " ( lock timeout : " << durationCount<Milliseconds>(lockExpiration)
               << " ms, ping interval : " << durationCount<Milliseconds>(_pingInterval)
               << " ms, process : " << _processID << " )"
               << " with lockSessionID: " << lockSessionID << ", why: " << whyMessage;

        auto lockResult = _catalog->grabLock(
            txn, name, lockSessionID, who, _processID, Date_t::now(), whyMessage);

        auto status = lockResult.getStatus();

        if (status.isOK()) {
            // Lock is acquired since findAndModify was able to successfully modify
            // the lock document.
            log() << "distributed lock '" << name << "' acquired for '" << whyMessage
                  << "', ts : " << lockSessionID;
            return ScopedDistLock(txn, lockSessionID, this);
        }

        // If a network error occurred, unlock the lock synchronously and try again
        if (ShardRegistry::kAllRetriableErrors.count(status.code()) &&
            networkErrorRetries < kMaxNumLockAcquireRetries) {
            LOG(1) << "Failed to acquire distributed lock because of retriable error. Retrying "
                      "acquisition by first unlocking the stale entry, which possibly exists now"
                   << causedBy(status);

            networkErrorRetries++;

            status = _catalog->unlock(txn, lockSessionID);
            if (status.isOK()) {
                // We certainly do not own the lock, so we can retry
                continue;
            }

            // Fall-through to the error checking logic below
            invariant(status != ErrorCodes::LockStateChangeFailed);

            LOG(1)
                << "Failed to retry acqusition of distributed lock. No more attempts will be made"
                << causedBy(status);
        }

        if (status != ErrorCodes::LockStateChangeFailed) {
            // An error occurred but the write might have actually been applied on the
            // other side. Schedule an unlock to clean it up just in case.
            queueUnlock(lockSessionID);
            return status;
        }

        // Get info from current lock and check if we can overtake it.
        auto getLockStatusResult = _catalog->getLockByName(txn, name);
        const auto& getLockStatus = getLockStatusResult.getStatus();

        if (!getLockStatusResult.isOK() && getLockStatus != ErrorCodes::LockNotFound) {
            return getLockStatus;
        }

        // Note: Only attempt to overtake locks that actually exists. If lock was not
        // found, use the normal grab lock path to acquire it.
        if (getLockStatusResult.isOK()) {
            auto currentLock = getLockStatusResult.getValue();
            auto canOvertakeResult = canOvertakeLock(txn, currentLock, lockExpiration);

            if (!canOvertakeResult.isOK()) {
                return canOvertakeResult.getStatus();
            }

            if (canOvertakeResult.getValue()) {
                auto overtakeResult = _catalog->overtakeLock(txn,
                                                             name,
                                                             lockSessionID,
                                                             currentLock.getLockID(),
                                                             who,
                                                             _processID,
                                                             Date_t::now(),
                                                             whyMessage);

                const auto& overtakeStatus = overtakeResult.getStatus();

                if (overtakeResult.isOK()) {
                    // Lock is acquired since findAndModify was able to successfully modify
                    // the lock document.

                    LOG(0) << "lock '" << name << "' successfully forced";
                    LOG(0) << "distributed lock '" << name << "' acquired, ts : " << lockSessionID;
                    return ScopedDistLock(txn, lockSessionID, this);
                }

                if (overtakeStatus != ErrorCodes::LockStateChangeFailed) {
                    // An error occurred but the write might have actually been applied on the
                    // other side. Schedule an unlock to clean it up just in case.
                    queueUnlock(lockSessionID);
                    return overtakeStatus;
                }
            }
        }

        LOG(1) << "distributed lock '" << name << "' was not acquired.";

        if (waitFor == milliseconds::zero()) {
            break;
        }

        // Periodically message for debugging reasons
        if (msgTimer.seconds() > 10) {
            LOG(0) << "waited " << timer.seconds() << "s for distributed lock " << name << " for "
                   << whyMessage;

            msgTimer.reset();
        }

        // A new lock acquisition attempt will begin now (because the previous found the lock to be
        // busy, so reset the retries counter)
        networkErrorRetries = 0;

        const milliseconds timeRemaining =
            std::max(milliseconds::zero(), waitFor - milliseconds(timer.millis()));
        sleepFor(std::min(lockTryInterval, timeRemaining));
    }

    return {ErrorCodes::LockBusy, str::stream() << "timed out waiting for " << name};
}