本文整理汇总了C++中CursorManager类的典型用法代码示例。如果您正苦于以下问题:C++ CursorManager类的具体用法?C++ CursorManager怎么用?C++ CursorManager使用的例子?那么, 这里精选的类代码示例或许可以为您提供帮助。
在下文中一共展示了CursorManager类的9个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: TEST_F
/**
* Test that an attempt to kill a pinned cursor succeeds with more than one client.
*/
TEST_F(CursorManagerTest, ShouldBeAbleToKillPinnedCursorMultiClient) {
CursorManager* cursorManager = useCursorManager();
const bool shouldAudit = false;
OperationContext* const pinningOpCtx = _opCtx.get();
// Pin the cursor from one client.
auto cursorPin = cursorManager->registerCursor(pinningOpCtx,
{makeFakePlanExecutor(),
kTestNss,
{},
repl::ReadConcernLevel::kLocalReadConcern,
BSONObj()});
auto cursorId = cursorPin.getCursor()->cursorid();
// Set up another client to kill the cursor.
auto killCursorClientOwned = getGlobalServiceContext()->makeClient("killCursorClient");
// Keep around a raw pointer for when we transfer ownership of killingClientOwned to the global
// current client.
Client* killCursorClient = killCursorClientOwned.get();
// Need to swap the current client in order to make an operation context.
auto pinningClient = Client::releaseCurrent();
Client::setCurrent(std::move(killCursorClientOwned));
auto killCursorOpCtx = killCursorClient->makeOperationContext();
invariant(killCursorOpCtx);
ASSERT_OK(cursorManager->killCursor(killCursorOpCtx.get(), cursorId, shouldAudit));
// The original operation should have been interrupted since the cursor was pinned.
ASSERT_EQ(pinningOpCtx->checkForInterruptNoAssert(), ErrorCodes::CursorKilled);
}
示例2: get
void CursorManager::doFrame()
{
CursorManager* manager = get();
if (manager->mCurrentCursor != nullptr && manager->isCursorShown())
{
manager->mCurrentCursor->setCurrentFrame();
}
}
示例3: TEST_F
TEST_F(CursorManagerTest,
CursorsFromCollectionCursorManagerShouldNotReportBeingManagedByGlobalCursorManager) {
CursorManager* cursorManager = useCursorManager();
auto opCtx = cc().makeOperationContext();
for (int i = 0; i < 1000; i++) {
auto cursorPin = cursorManager->registerCursor(
_opCtx.get(), {makeFakePlanExecutor(), kTestNss, {}, false, BSONObj()});
ASSERT_FALSE(CursorManager::isGloballyManagedCursor(cursorPin.getCursor()->cursorid()));
}
}
示例4: TEST_F
/**
* Test that client cursors which have been marked as killed time out and get deleted.
*/
TEST_F(CursorManagerTest, InactiveKilledCursorsShouldTimeout) {
CursorManager* cursorManager = useCursorManager();
auto clock = useClock();
// Make a cursor from the plan executor, and immediately kill it.
auto cursorPin = cursorManager->registerCursor(
_opCtx.get(),
{makeFakePlanExecutor(), NamespaceString{"test.collection"}, {}, false, BSONObj()});
cursorPin.release();
const bool collectionGoingAway = false;
cursorManager->invalidateAll(
_opCtx.get(), collectionGoingAway, "KilledCursorsShouldTimeoutTest");
// Advance the clock to simulate time passing.
clock->advance(Milliseconds(CursorManager::kDefaultCursorTimeoutMinutes));
ASSERT_EQ(1UL, cursorManager->timeoutCursors(_opCtx.get(), clock->now()));
ASSERT_EQ(0UL, cursorManager->numCursors());
}
示例5: getMore
/**
* Called by db/instance.cpp. This is the getMore entry point.
*
* pass - when QueryOption_AwaitData is in use, the caller will make repeated calls
* when this method returns an empty result, incrementing pass on each call.
* Thus, pass == 0 indicates this is the first "attempt" before any 'awaiting'.
*/
QueryResult::View getMore(OperationContext* txn,
const char* ns,
int ntoreturn,
long long cursorid,
CurOp& curop,
int pass,
bool& exhaust,
bool* isCursorAuthorized) {
// For testing, we may want to fail if we receive a getmore.
if (MONGO_FAIL_POINT(failReceivedGetmore)) {
invariant(0);
}
exhaust = false;
const NamespaceString nss(ns);
// Depending on the type of cursor being operated on, we hold locks for the whole getMore,
// or none of the getMore, or part of the getMore. The three cases in detail:
//
// 1) Normal cursor: we lock with "ctx" and hold it for the whole getMore.
// 2) Cursor owned by global cursor manager: we don't lock anything. These cursors don't
// own any collection state.
// 3) Agg cursor: we lock with "ctx", then release, then relock with "unpinDBLock" and
// "unpinCollLock". This is because agg cursors handle locking internally (hence the
// release), but the pin and unpin of the cursor must occur under the collection lock.
// We don't use our AutoGetCollectionForRead "ctx" to relock, because
// AutoGetCollectionForRead checks the sharding version (and we want the relock for the
// unpin to succeed even if the sharding version has changed).
//
// Note that we declare our locks before our ClientCursorPin, in order to ensure that the
// pin's destructor is called before the lock destructors (so that the unpin occurs under
// the lock).
boost::scoped_ptr<AutoGetCollectionForRead> ctx;
boost::scoped_ptr<Lock::DBLock> unpinDBLock;
boost::scoped_ptr<Lock::CollectionLock> unpinCollLock;
CursorManager* cursorManager;
CursorManager* globalCursorManager = CursorManager::getGlobalCursorManager();
if (globalCursorManager->ownsCursorId(cursorid)) {
cursorManager = globalCursorManager;
}
else {
ctx.reset(new AutoGetCollectionForRead(txn, nss));
Collection* collection = ctx->getCollection();
uassert( 17356, "collection dropped between getMore calls", collection );
cursorManager = collection->getCursorManager();
}
LOG(5) << "Running getMore, cursorid: " << cursorid << endl;
// This checks to make sure the operation is allowed on a replicated node. Since we are not
// passing in a query object (necessary to check SlaveOK query option), the only state where
// reads are allowed is PRIMARY (or master in master/slave). This function uasserts if
// reads are not okay.
Status status = repl::getGlobalReplicationCoordinator()->checkCanServeReadsFor(
txn,
nss,
true);
uassertStatusOK(status);
// A pin performs a CC lookup and if there is a CC, increments the CC's pin value so it
// doesn't time out. Also informs ClientCursor that there is somebody actively holding the
// CC, so don't delete it.
ClientCursorPin ccPin(cursorManager, cursorid);
ClientCursor* cc = ccPin.c();
// If we're not being called from DBDirectClient we want to associate the RecoveryUnit
// used to create the execution machinery inside the cursor with our OperationContext.
// If we throw or otherwise exit this method in a disorderly fashion, we must ensure
// that further calls to getMore won't fail, and that the provided OperationContext
// has a valid RecoveryUnit. As such, we use RAII to accomplish this.
//
// This must be destroyed before the ClientCursor is destroyed.
std::auto_ptr<ScopedRecoveryUnitSwapper> ruSwapper;
// These are set in the QueryResult msg we return.
int resultFlags = ResultFlag_AwaitCapable;
int numResults = 0;
int startingResult = 0;
const int InitialBufSize =
512 + sizeof(QueryResult::Value) + MaxBytesToReturnToClientAtOnce;
BufBuilder bb(InitialBufSize);
bb.skip(sizeof(QueryResult::Value));
if (NULL == cc) {
cursorid = 0;
resultFlags = ResultFlag_CursorNotFound;
}
//.........这里部分代码省略.........
示例6: run
bool run(OperationContext* txn,
const std::string& dbname,
BSONObj& cmdObj,
int options,
std::string& errmsg,
BSONObjBuilder& result) override {
// Counted as a getMore, not as a command.
globalOpCounters.gotGetMore();
if (txn->getClient()->isInDirectClient()) {
return appendCommandStatus(result,
Status(ErrorCodes::IllegalOperation,
"Cannot run getMore command from eval()"));
}
StatusWith<GetMoreRequest> parseStatus = GetMoreRequest::parseFromBSON(dbname, cmdObj);
if (!parseStatus.isOK()) {
return appendCommandStatus(result, parseStatus.getStatus());
}
const GetMoreRequest& request = parseStatus.getValue();
// Depending on the type of cursor being operated on, we hold locks for the whole
// getMore, or none of the getMore, or part of the getMore. The three cases in detail:
//
// 1) Normal cursor: we lock with "ctx" and hold it for the whole getMore.
// 2) Cursor owned by global cursor manager: we don't lock anything. These cursors
// don't own any collection state.
// 3) Agg cursor: we lock with "ctx", then release, then relock with "unpinDBLock" and
// "unpinCollLock". This is because agg cursors handle locking internally (hence the
// release), but the pin and unpin of the cursor must occur under the collection
// lock. We don't use our AutoGetCollectionForRead "ctx" to relock, because
// AutoGetCollectionForRead checks the sharding version (and we want the relock for
// the unpin to succeed even if the sharding version has changed).
//
// Note that we declare our locks before our ClientCursorPin, in order to ensure that
// the pin's destructor is called before the lock destructors (so that the unpin occurs
// under the lock).
std::unique_ptr<AutoGetCollectionForRead> ctx;
std::unique_ptr<Lock::DBLock> unpinDBLock;
std::unique_ptr<Lock::CollectionLock> unpinCollLock;
CursorManager* cursorManager;
CursorManager* globalCursorManager = CursorManager::getGlobalCursorManager();
if (globalCursorManager->ownsCursorId(request.cursorid)) {
cursorManager = globalCursorManager;
}
else {
ctx.reset(new AutoGetCollectionForRead(txn, request.nss));
Collection* collection = ctx->getCollection();
if (!collection) {
return appendCommandStatus(result,
Status(ErrorCodes::OperationFailed,
"collection dropped between getMore calls"));
}
cursorManager = collection->getCursorManager();
}
ClientCursorPin ccPin(cursorManager, request.cursorid);
ClientCursor* cursor = ccPin.c();
if (!cursor) {
// We didn't find the cursor.
return appendCommandStatus(result, Status(ErrorCodes::CursorNotFound, str::stream()
<< "Cursor not found, cursor id: " << request.cursorid));
}
if (request.nss.ns() != cursor->ns()) {
return appendCommandStatus(result, Status(ErrorCodes::Unauthorized, str::stream()
<< "Requested getMore on namespace '" << request.nss.ns()
<< "', but cursor belongs to a different namespace"));
}
const bool hasOwnMaxTime = CurOp::get(txn)->isMaxTimeSet();
// Validation related to awaitData.
if (isCursorAwaitData(cursor)) {
invariant(isCursorTailable(cursor));
if (!hasOwnMaxTime) {
Status status(ErrorCodes::BadValue,
str::stream() << "Must set maxTimeMS on a getMore if the initial "
<< "query had 'awaitData' set: " << cmdObj);
return appendCommandStatus(result, status);
}
if (cursor->isAggCursor()) {
Status status(ErrorCodes::BadValue,
"awaitData cannot be set on an aggregation cursor");
return appendCommandStatus(result, status);
}
}
// On early return, get rid of the cursor.
ScopeGuard cursorFreer = MakeGuard(&GetMoreCmd::cleanupCursor, txn, &ccPin, request);
if (!cursor->hasRecoveryUnit()) {
// Start using a new RecoveryUnit.
cursor->setOwnedRecoveryUnit(
getGlobalServiceContext()->getGlobalStorageEngine()->newRecoveryUnit());
}
//.........这里部分代码省略.........
示例7: getMore
/**
* Called by db/instance.cpp. This is the getMore entry point.
*/
Message getMore(OperationContext* opCtx,
const char* ns,
int ntoreturn,
long long cursorid,
bool* exhaust,
bool* isCursorAuthorized) {
invariant(ntoreturn >= 0);
CurOp& curOp = *CurOp::get(opCtx);
curOp.ensureStarted();
// For testing, we may want to fail if we receive a getmore.
if (MONGO_FAIL_POINT(failReceivedGetmore)) {
MONGO_UNREACHABLE;
}
*exhaust = false;
const NamespaceString nss(ns);
// Cursors come in one of two flavors:
// - Cursors owned by the collection cursor manager, such as those generated via the find
// command. For these cursors, we hold the appropriate collection lock for the duration of the
// getMore using AutoGetCollectionForRead.
// - Cursors owned by the global cursor manager, such as those generated via the aggregate
// command. These cursors either hold no collection state or manage their collection state
// internally, so we acquire no locks.
//
// While we only need to acquire locks in the case of a cursor which is *not* globally owned, we
// need to create an AutoStatsTracker in either case. This is responsible for updating
// statistics in CurOp and Top. We avoid using AutoGetCollectionForReadCommand because we may
// need to drop and reacquire locks when the cursor is awaitData, but we don't want to update
// the stats twice.
//
// Note that we acquire our locks before our ClientCursorPin, in order to ensure that the pin's
// destructor is called before the lock's destructor (if there is one) so that the cursor
// cleanup can occur under the lock.
UninterruptibleLockGuard noInterrupt(opCtx->lockState());
boost::optional<AutoGetCollectionForRead> readLock;
boost::optional<AutoStatsTracker> statsTracker;
CursorManager* cursorManager;
if (CursorManager::isGloballyManagedCursor(cursorid)) {
cursorManager = CursorManager::getGlobalCursorManager();
if (boost::optional<NamespaceString> nssForCurOp = nss.isGloballyManagedNamespace()
? nss.getTargetNSForGloballyManagedNamespace()
: nss) {
AutoGetDb autoDb(opCtx, nssForCurOp->db(), MODE_IS);
const auto profilingLevel = autoDb.getDb()
? boost::optional<int>{autoDb.getDb()->getProfilingLevel()}
: boost::none;
statsTracker.emplace(opCtx, *nssForCurOp, Top::LockType::NotLocked, profilingLevel);
auto view = autoDb.getDb()
? autoDb.getDb()->getViewCatalog()->lookup(opCtx, nssForCurOp->ns())
: nullptr;
uassert(
ErrorCodes::CommandNotSupportedOnView,
str::stream() << "Namespace " << nssForCurOp->ns()
<< " is a view. OP_GET_MORE operations are not supported on views. "
<< "Only clients which support the getMore command can be used to "
"query views.",
!view);
}
} else {
readLock.emplace(opCtx, nss);
const int doNotChangeProfilingLevel = 0;
statsTracker.emplace(opCtx,
nss,
Top::LockType::ReadLocked,
readLock->getDb() ? readLock->getDb()->getProfilingLevel()
: doNotChangeProfilingLevel);
Collection* collection = readLock->getCollection();
uassert(
ErrorCodes::OperationFailed, "collection dropped between getMore calls", collection);
cursorManager = collection->getCursorManager();
// This checks to make sure the operation is allowed on a replicated node. Since we are not
// passing in a query object (necessary to check SlaveOK query option), we allow reads
// whether we are PRIMARY or SECONDARY.
uassertStatusOK(
repl::ReplicationCoordinator::get(opCtx)->checkCanServeReadsFor(opCtx, nss, true));
}
LOG(5) << "Running getMore, cursorid: " << cursorid;
// A pin performs a CC lookup and if there is a CC, increments the CC's pin value so it
// doesn't time out. Also informs ClientCursor that there is somebody actively holding the
// CC, so don't delete it.
auto ccPin = cursorManager->pinCursor(opCtx, cursorid);
// These are set in the QueryResult msg we return.
int resultFlags = ResultFlag_AwaitCapable;
int numResults = 0;
int startingResult = 0;
//.........这里部分代码省略.........
示例8: getMore
/**
* Called by db/instance.cpp. This is the getMore entry point.
*/
Message getMore(OperationContext* txn,
const char* ns,
int ntoreturn,
long long cursorid,
bool* exhaust,
bool* isCursorAuthorized) {
invariant(ntoreturn >= 0);
CurOp& curOp = *CurOp::get(txn);
// For testing, we may want to fail if we receive a getmore.
if (MONGO_FAIL_POINT(failReceivedGetmore)) {
invariant(0);
}
*exhaust = false;
const NamespaceString nss(ns);
// Depending on the type of cursor being operated on, we hold locks for the whole getMore,
// or none of the getMore, or part of the getMore. The three cases in detail:
//
// 1) Normal cursor: we lock with "ctx" and hold it for the whole getMore.
// 2) Cursor owned by global cursor manager: we don't lock anything. These cursors don't own
// any collection state. These cursors are generated either by the listCollections or
// listIndexes commands, as these special cursor-generating commands operate over catalog
// data rather than targeting the data within a collection.
// 3) Agg cursor: we lock with "ctx", then release, then relock with "unpinDBLock" and
// "unpinCollLock". This is because agg cursors handle locking internally (hence the
// release), but the pin and unpin of the cursor must occur under the collection lock.
// We don't use our AutoGetCollectionForRead "ctx" to relock, because
// AutoGetCollectionForRead checks the sharding version (and we want the relock for the
// unpin to succeed even if the sharding version has changed).
//
// Note that we declare our locks before our ClientCursorPin, in order to ensure that the
// pin's destructor is called before the lock destructors (so that the unpin occurs under
// the lock).
unique_ptr<AutoGetCollectionForRead> ctx;
unique_ptr<Lock::DBLock> unpinDBLock;
unique_ptr<Lock::CollectionLock> unpinCollLock;
CursorManager* cursorManager;
if (nss.isListIndexesCursorNS() || nss.isListCollectionsCursorNS()) {
// List collections and list indexes are special cursor-generating commands whose
// cursors are managed globally, as they operate over catalog data rather than targeting
// the data within a collection.
cursorManager = CursorManager::getGlobalCursorManager();
} else {
ctx = stdx::make_unique<AutoGetCollectionOrViewForRead>(txn, nss);
auto viewCtx = static_cast<AutoGetCollectionOrViewForRead*>(ctx.get());
if (viewCtx->getView()) {
uasserted(
ErrorCodes::CommandNotSupportedOnView,
str::stream() << "Namespace " << nss.ns()
<< " is a view. OP_GET_MORE operations are not supported on views. "
<< "Only clients which support the getMore command can be used to "
"query views.");
}
Collection* collection = ctx->getCollection();
uassert(17356, "collection dropped between getMore calls", collection);
cursorManager = collection->getCursorManager();
}
LOG(5) << "Running getMore, cursorid: " << cursorid;
// This checks to make sure the operation is allowed on a replicated node. Since we are not
// passing in a query object (necessary to check SlaveOK query option), the only state where
// reads are allowed is PRIMARY (or master in master/slave). This function uasserts if
// reads are not okay.
Status status = repl::getGlobalReplicationCoordinator()->checkCanServeReadsFor(txn, nss, true);
uassertStatusOK(status);
// A pin performs a CC lookup and if there is a CC, increments the CC's pin value so it
// doesn't time out. Also informs ClientCursor that there is somebody actively holding the
// CC, so don't delete it.
auto ccPin = cursorManager->pinCursor(cursorid);
// These are set in the QueryResult msg we return.
int resultFlags = ResultFlag_AwaitCapable;
int numResults = 0;
int startingResult = 0;
const int InitialBufSize =
512 + sizeof(QueryResult::Value) + FindCommon::kMaxBytesToReturnToClientAtOnce;
BufBuilder bb(InitialBufSize);
bb.skip(sizeof(QueryResult::Value));
if (!ccPin.isOK()) {
invariant(ccPin == ErrorCodes::CursorNotFound);
cursorid = 0;
resultFlags = ResultFlag_CursorNotFound;
} else {
ClientCursor* cc = ccPin.getValue().getCursor();
//.........这里部分代码省略.........
示例9: run
/**
* Generates the next batch of results for a ClientCursor.
*
* TODO: Do we need to support some equivalent of OP_REPLY responseFlags?
*
* TODO: Is it possible to support awaitData?
*/
bool run(OperationContext* txn,
const std::string& dbname,
BSONObj& cmdObj,
int options,
std::string& errmsg,
BSONObjBuilder& result) override {
// Counted as a getMore, not as a command.
globalOpCounters.gotGetMore();
if (txn->getClient()->isInDirectClient()) {
return appendCommandStatus(result,
Status(ErrorCodes::IllegalOperation,
"Cannot run getMore command from eval()"));
}
StatusWith<GetMoreRequest> parseStatus = GetMoreRequest::parseFromBSON(dbname, cmdObj);
if (!parseStatus.isOK()) {
return appendCommandStatus(result, parseStatus.getStatus());
}
const GetMoreRequest& request = parseStatus.getValue();
// Depending on the type of cursor being operated on, we hold locks for the whole
// getMore, or none of the getMore, or part of the getMore. The three cases in detail:
//
// 1) Normal cursor: we lock with "ctx" and hold it for the whole getMore.
// 2) Cursor owned by global cursor manager: we don't lock anything. These cursors
// don't own any collection state.
// 3) Agg cursor: we lock with "ctx", then release, then relock with "unpinDBLock" and
// "unpinCollLock". This is because agg cursors handle locking internally (hence the
// release), but the pin and unpin of the cursor must occur under the collection
// lock. We don't use our AutoGetCollectionForRead "ctx" to relock, because
// AutoGetCollectionForRead checks the sharding version (and we want the relock for
// the unpin to succeed even if the sharding version has changed).
//
// Note that we declare our locks before our ClientCursorPin, in order to ensure that
// the pin's destructor is called before the lock destructors (so that the unpin occurs
// under the lock).
std::unique_ptr<AutoGetCollectionForRead> ctx;
std::unique_ptr<Lock::DBLock> unpinDBLock;
std::unique_ptr<Lock::CollectionLock> unpinCollLock;
CursorManager* cursorManager;
CursorManager* globalCursorManager = CursorManager::getGlobalCursorManager();
if (globalCursorManager->ownsCursorId(request.cursorid)) {
cursorManager = globalCursorManager;
}
else {
ctx.reset(new AutoGetCollectionForRead(txn, request.nss));
Collection* collection = ctx->getCollection();
if (!collection) {
return appendCommandStatus(result,
Status(ErrorCodes::OperationFailed,
"collection dropped between getMore calls"));
}
cursorManager = collection->getCursorManager();
}
ClientCursorPin ccPin(cursorManager, request.cursorid);
ClientCursor* cursor = ccPin.c();
if (!cursor) {
// We didn't find the cursor.
return appendCommandStatus(result, Status(ErrorCodes::CursorNotFound, str::stream()
<< "Cursor not found, cursor id: " << request.cursorid));
}
if (request.nss.ns() != cursor->ns()) {
return appendCommandStatus(result, Status(ErrorCodes::Unauthorized, str::stream()
<< "Requested getMore on namespace '" << request.nss.ns()
<< "', but cursor belongs to a different namespace"));
}
// On early return, get rid of the the cursor.
ScopeGuard cursorFreer = MakeGuard(&ClientCursorPin::deleteUnderlying, ccPin);
if (!cursor->hasRecoveryUnit()) {
// Start using a new RecoveryUnit.
cursor->setOwnedRecoveryUnit(
getGlobalServiceContext()->getGlobalStorageEngine()->newRecoveryUnit());
}
// Swap RecoveryUnit(s) between the ClientCursor and OperationContext.
ScopedRecoveryUnitSwapper ruSwapper(cursor, txn);
// Reset timeout timer on the cursor since the cursor is still in use.
cursor->setIdleTime(0);
// If the operation that spawned this cursor had a time limit set, apply leftover
// time to this getmore.
txn->getCurOp()->setMaxTimeMicros(cursor->getLeftoverMaxTimeMicros());
txn->checkForInterrupt(); // May trigger maxTimeAlwaysTimeOut fail point.
if (cursor->isAggCursor()) {
// Agg cursors handle their own locking internally.
//.........这里部分代码省略.........