Exemplo n.º 1
0
void ClusterCursorManager::reapZombieCursors() {
    // List all zombie cursors under the manager lock, and kill them one-by-one while not holding
    // the lock (ClusterClientCursor::kill() is blocking, so we don't want to hold a lock while
    // issuing the kill).

    stdx::unique_lock<stdx::mutex> lk(_mutex);
    std::vector<std::pair<NamespaceString, CursorId>> zombieCursorDescriptors;
    for (auto& nsContainerPair : _namespaceToContainerMap) {
        const NamespaceString& nss = nsContainerPair.first;
        for (auto& cursorIdEntryPair : nsContainerPair.second.entryMap) {
            CursorId cursorId = cursorIdEntryPair.first;
            const CursorEntry& entry = cursorIdEntryPair.second;
            if (!entry.getKillPending()) {
                continue;
            }
            zombieCursorDescriptors.emplace_back(nss, cursorId);
        }
    }

    for (auto& namespaceCursorIdPair : zombieCursorDescriptors) {
        StatusWith<std::unique_ptr<ClusterClientCursor>> zombieCursor =
            detachCursor_inlock(namespaceCursorIdPair.first, namespaceCursorIdPair.second);
        if (!zombieCursor.isOK()) {
            // Cursor in use, or has already been deleted.
            continue;
        }

        lk.unlock();
        zombieCursor.getValue()->kill();
        lk.lock();
        // Cursor deleted as it goes out of scope.
    }
}
Exemplo n.º 2
0
void ClusterCursorManager::checkInCursor(std::unique_ptr<ClusterClientCursor> cursor,
                                         const NamespaceString& nss,
                                         CursorId cursorId,
                                         CursorState cursorState) {
    stdx::unique_lock<stdx::mutex> lk(_mutex);

    invariant(cursor);

    const bool remotesExhausted = cursor->remotesExhausted();

    CursorEntry* entry = getEntry_inlock(nss, cursorId);
    invariant(entry);

    entry->returnCursor(std::move(cursor));

    if (cursorState == CursorState::NotExhausted || entry->getKillPending()) {
        return;
    }

    if (!remotesExhausted) {
        // The cursor still has open remote cursors that need to be cleaned up. Schedule for
        // deletion by the reaper thread by setting the kill pending flag.
        entry->setKillPending();
        return;
    }

    // The cursor is exhausted, is not already scheduled for deletion, and does not have any
    // remote cursor state left to clean up. We can delete the cursor right away.
    auto detachedCursor = detachCursor_inlock(nss, cursorId);
    invariantOK(detachedCursor.getStatus());

    // Deletion of the cursor can happen out of the lock.
    lk.unlock();
    detachedCursor.getValue().reset();
}