Esempio n. 1
0
void TaskRunner::_runTasks() {
    // We initialize cc() because ServiceContextMongoD::_newOpCtx() expects cc() to be equal to the
    // client used to create the operation context.
    Client* client = &cc();
    if (AuthorizationManager::get(client->getServiceContext())->isAuthEnabled()) {
        AuthorizationSession::get(client)->grantInternalAuthorization(client);
    }
    ServiceContext::UniqueOperationContext opCtx;

    while (Task task = _waitForNextTask()) {
        if (!opCtx) {
            opCtx = client->makeOperationContext();
        }

        NextAction nextAction = runSingleTask(task, opCtx.get(), Status::OK());

        if (nextAction != NextAction::kKeepOperationContext) {
            opCtx.reset();
        }

        if (nextAction == NextAction::kCancel) {
            break;
        }
        // Release thread back to pool after disposing if no scheduled tasks in queue.
        if (nextAction == NextAction::kDisposeOperationContext ||
            nextAction == NextAction::kInvalid) {
            stdx::lock_guard<stdx::mutex> lk(_mutex);
            if (_tasks.empty()) {
                _finishRunTasks_inlock();
                return;
            }
        }
    }
    opCtx.reset();

    std::list<Task> tasks;
    UniqueLock lk{_mutex};

    auto cancelTasks = [&]() {
        tasks.swap(_tasks);
        lk.unlock();
        // Cancel remaining tasks with a CallbackCanceled status.
        for (auto&& task : tasks) {
            runSingleTask(std::move(task),
                          nullptr,
                          Status(ErrorCodes::CallbackCanceled,
                                 "this task has been canceled by a previously invoked task"));
        }
        tasks.clear();

    };
    cancelTasks();

    lk.lock();
    _finishRunTasks_inlock();
    cancelTasks();
}
Esempio n. 2
0
void TaskRunner::_runTasks() {
    Client* client = nullptr;
    ServiceContext::UniqueOperationContext txn;

    while (Task task = _waitForNextTask()) {
        if (!txn) {
            if (!client) {
                // We initialize cc() because ServiceContextMongoD::_newOpCtx() expects cc()
                // to be equal to the client used to create the operation context.
                Client::initThreadIfNotAlready();
                client = &cc();
                if (getGlobalAuthorizationManager()->isAuthEnabled()) {
                    AuthorizationSession::get(client)->grantInternalAuthorization();
                }
            }
            txn = client->makeOperationContext();
        }

        NextAction nextAction = runSingleTask(task, txn.get(), Status::OK());

        if (nextAction != NextAction::kKeepOperationContext) {
            txn.reset();
        }

        if (nextAction == NextAction::kCancel) {
            break;
        }
        // Release thread back to pool after disposing if no scheduled tasks in queue.
        if (nextAction == NextAction::kDisposeOperationContext ||
            nextAction == NextAction::kInvalid) {
            stdx::lock_guard<stdx::mutex> lk(_mutex);
            if (_tasks.empty()) {
                _finishRunTasks_inlock();
                return;
            }
        }
    }
    txn.reset();

    std::list<Task> tasks;
    {
        stdx::lock_guard<stdx::mutex> lk(_mutex);
        tasks.swap(_tasks);
    }

    // Cancel remaining tasks with a CallbackCanceled status.
    for (auto task : tasks) {
        runSingleTask(task,
                      nullptr,
                      Status(ErrorCodes::CallbackCanceled,
                             "this task has been canceled by a previously invoked task"));
    }

    stdx::lock_guard<stdx::mutex> lk(_mutex);
    _finishRunTasks_inlock();
}