本文整理汇总了C++中BSONElement::_opTime方法的典型用法代码示例。如果您正苦于以下问题:C++ BSONElement::_opTime方法的具体用法?C++ BSONElement::_opTime怎么用?C++ BSONElement::_opTime使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类BSONElement
的用法示例。
在下文中一共展示了BSONElement::_opTime方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: lk
StatusWith<ReplicationCoordinatorExternalState::OpTimeAndHash>
ReplicationCoordinatorExternalStateImpl::loadLastOpTimeAndHash(
OperationContext* txn) {
try {
Lock::DBRead lk(txn->lockState(), rsoplog);
BSONObj oplogEntry;
if (!Helpers::getLast(txn, rsoplog, oplogEntry)) {
return StatusWith<OpTimeAndHash>(
ErrorCodes::NoMatchingDocument,
str::stream() << "Did not find any entries in " << rsoplog);
}
BSONElement tsElement = oplogEntry[tsFieldName];
if (tsElement.eoo()) {
return StatusWith<OpTimeAndHash>(
ErrorCodes::NoSuchKey,
str::stream() << "Most recent entry in " << rsoplog << " missing \"" <<
tsFieldName << "\" field");
}
if (tsElement.type() != Timestamp) {
return StatusWith<OpTimeAndHash>(
ErrorCodes::TypeMismatch,
str::stream() << "Expected type of \"" << tsFieldName <<
"\" in most recent " << rsoplog <<
" entry to have type Timestamp, but found " << typeName(tsElement.type()));
}
return StatusWith<OpTimeAndHash>(
OpTimeAndHash(tsElement._opTime(), oplogEntry[hashFieldName].safeNumberLong()));
}
catch (const DBException& ex) {
return StatusWith<OpTimeAndHash>(ex.toStatus());
}
}
示例2: bsonExtractOpTimeField
Status bsonExtractOpTimeField(const BSONObj& object,
const StringData& fieldName,
OpTime* out) {
BSONElement element;
Status status = bsonExtractTypedField(object, fieldName, Timestamp, &element);
if (!status.isOK())
return status;
*out = element._opTime();
return Status::OK();
}
示例3: storeOpForSlave
void ClientCursor::storeOpForSlave( DiskLoc last ) {
if ( ! ( _queryOptions & QueryOption_OplogReplay ))
return;
if ( last.isNull() )
return;
BSONElement e = last.obj()["ts"];
if ( e.type() == Date || e.type() == Timestamp )
_slaveReadTill = e._opTime();
}
示例4: newRunQuery
//.........这里部分代码省略.........
// bb is used to hold query results
// this buffer should contain either requested documents per query or
// explain information, but not both
BufBuilder bb(32768);
bb.skip(sizeof(QueryResult::Value));
// How many results have we obtained from the executor?
int numResults = 0;
// If we're replaying the oplog, we save the last time that we read.
OpTime slaveReadTill;
// Do we save the PlanExecutor in a ClientCursor for getMore calls later?
bool saveClientCursor = false;
BSONObj obj;
PlanExecutor::ExecState state;
// uint64_t numMisplacedDocs = 0;
// Get summary info about which plan the executor is using.
curop.debug().planSummary = Explain::getPlanSummary(exec.get());
while (PlanExecutor::ADVANCED == (state = exec->getNext(&obj, NULL))) {
// Add result to output buffer.
bb.appendBuf((void*)obj.objdata(), obj.objsize());
// Count the result.
++numResults;
// Possibly note slave's position in the oplog.
if (pq.getOptions().oplogReplay) {
BSONElement e = obj["ts"];
if (Date == e.type() || Timestamp == e.type()) {
slaveReadTill = e._opTime();
}
}
// TODO: only one type of 2d search doesn't support this. We need a way to pull it out
// of CanonicalQuery. :(
const bool supportsGetMore = true;
if (!supportsGetMore && (enough(pq, numResults)
|| bb.len() >= MaxBytesToReturnToClientAtOnce)) {
break;
}
else if (enoughForFirstBatch(pq, numResults, bb.len())) {
QLOG() << "Enough for first batch, wantMore=" << pq.wantMore()
<< " numToReturn=" << pq.getNumToReturn()
<< " numResults=" << numResults
<< endl;
// If only one result requested assume it's a findOne() and don't save the cursor.
if (pq.wantMore() && 1 != pq.getNumToReturn()) {
QLOG() << " executor EOF=" << exec->isEOF() << endl;
saveClientCursor = !exec->isEOF();
}
break;
}
}
// If we cache the executor later, we want to deregister it as it receives notifications
// anyway by virtue of being cached.
//
// If we don't cache the executor later, we are deleting it, so it must be deregistered.
//
// So, no matter what, deregister the executor.
exec->deregisterExec();
示例5: getOplogStartHack
Status getOplogStartHack(OperationContext* txn,
Collection* collection,
CanonicalQuery* cq,
PlanExecutor** execOut) {
invariant(cq);
auto_ptr<CanonicalQuery> autoCq(cq);
if ( collection == NULL )
return Status(ErrorCodes::InternalError,
"getOplogStartHack called with a NULL collection" );
// A query can only do oplog start finding if it has a top-level $gt or $gte predicate over
// the "ts" field (the operation's timestamp). Find that predicate and pass it to
// the OplogStart stage.
MatchExpression* tsExpr = NULL;
if (MatchExpression::AND == cq->root()->matchType()) {
// The query has an AND at the top-level. See if any of the children
// of the AND are $gt or $gte predicates over 'ts'.
for (size_t i = 0; i < cq->root()->numChildren(); ++i) {
MatchExpression* me = cq->root()->getChild(i);
if (isOplogTsPred(me)) {
tsExpr = me;
break;
}
}
}
else if (isOplogTsPred(cq->root())) {
// The root of the tree is a $gt or $gte predicate over 'ts'.
tsExpr = cq->root();
}
if (NULL == tsExpr) {
return Status(ErrorCodes::OplogOperationUnsupported,
"OplogReplay query does not contain top-level "
"$gt or $gte over the 'ts' field.");
}
DiskLoc startLoc = DiskLoc().setInvalid();
// See if the RecordStore supports the oplogStartHack
const BSONElement tsElem = extractOplogTsOptime(tsExpr);
if (tsElem.type() == Timestamp) {
StatusWith<DiskLoc> goal = oploghack::keyForOptime(tsElem._opTime());
if (goal.isOK()) {
startLoc = collection->getRecordStore()->oplogStartHack(txn, goal.getValue());
}
}
if (startLoc.isValid()) {
LOG(3) << "Using direct oplog seek";
}
else {
LOG(3) << "Using OplogStart stage";
// Fallback to trying the OplogStart stage.
WorkingSet* oplogws = new WorkingSet();
OplogStart* stage = new OplogStart(txn, collection, tsExpr, oplogws);
PlanExecutor* rawExec;
// Takes ownership of oplogws and stage.
Status execStatus = PlanExecutor::make(txn, oplogws, stage, collection,
PlanExecutor::YIELD_AUTO, &rawExec);
invariant(execStatus.isOK());
scoped_ptr<PlanExecutor> exec(rawExec);
// The stage returns a DiskLoc of where to start.
PlanExecutor::ExecState state = exec->getNext(NULL, &startLoc);
// This is normal. The start of the oplog is the beginning of the collection.
if (PlanExecutor::IS_EOF == state) {
return getExecutor(txn, collection, autoCq.release(), PlanExecutor::YIELD_AUTO,
execOut);
}
// This is not normal. An error was encountered.
if (PlanExecutor::ADVANCED != state) {
return Status(ErrorCodes::InternalError,
"quick oplog start location had error...?");
}
}
// cout << "diskloc is " << startLoc.toString() << endl;
// Build our collection scan...
CollectionScanParams params;
params.collection = collection;
params.start = startLoc;
params.direction = CollectionScanParams::FORWARD;
params.tailable = cq->getParsed().getOptions().tailable;
WorkingSet* ws = new WorkingSet();
CollectionScan* cs = new CollectionScan(txn, params, ws, cq->root());
// Takes ownership of 'ws', 'cs', and 'cq'.
return PlanExecutor::make(txn, ws, cs, autoCq.release(), collection,
PlanExecutor::YIELD_AUTO, execOut);
}
示例6: newGetMore
//.........这里部分代码省略.........
if (cc->isAggCursor) {
// Agg cursors handle their own locking internally.
ctx.reset(); // unlocks
}
CollectionMetadataPtr collMetadata = cc->getCollMetadata();
// If we're replaying the oplog, we save the last time that we read.
OpTime slaveReadTill;
// What number result are we starting at? Used to fill out the reply.
startingResult = cc->pos();
// What gives us results.
PlanExecutor* exec = cc->getExecutor();
const int queryOptions = cc->queryOptions();
// Get results out of the executor.
exec->restoreState(txn);
BSONObj obj;
PlanExecutor::ExecState state;
while (PlanExecutor::ADVANCED == (state = exec->getNext(&obj, NULL))) {
// Add result to output buffer.
bb.appendBuf((void*)obj.objdata(), obj.objsize());
// Count the result.
++numResults;
// Possibly note slave's position in the oplog.
if (queryOptions & QueryOption_OplogReplay) {
BSONElement e = obj["ts"];
if (Date == e.type() || Timestamp == e.type()) {
slaveReadTill = e._opTime();
}
}
if ((ntoreturn && numResults >= ntoreturn)
|| bb.len() > MaxBytesToReturnToClientAtOnce) {
break;
}
}
// We save the client cursor when there might be more results, and hence we may receive
// another getmore. If we receive a EOF or an error, or 'exec' is dead, then we know
// that we will not be producing more results. We indicate that the cursor is closed by
// sending a cursorId of 0 back to the client.
//
// On the other hand, if we retrieve all results necessary for this batch, then
// 'saveClientCursor' is true and we send a valid cursorId back to the client. In
// this case, there may or may not actually be more results (for example, the next call
// to getNext(...) might just return EOF).
bool saveClientCursor = false;
if (PlanExecutor::DEAD == state || PlanExecutor::EXEC_ERROR == state) {
// Propagate this error to caller.
if (PlanExecutor::EXEC_ERROR == state) {
scoped_ptr<PlanStageStats> stats(exec->getStats());
error() << "Plan executor error, stats: "
<< Explain::statsToBSON(*stats);
uasserted(17406, "getMore executor error: " +
WorkingSetCommon::toStatusString(obj));
}
// If we're dead there's no way to get more results.
saveClientCursor = false;
示例7: newRunQuery
//.........这里部分代码省略.........
OpTime slaveReadTill;
// Do we save the Runner in a ClientCursor for getMore calls later?
bool saveClientCursor = false;
// We turn on auto-yielding for the runner here. The runner registers itself with the
// active runners list in ClientCursor.
ClientCursor::registerRunner(runner.get());
runner->setYieldPolicy(Runner::YIELD_AUTO);
auto_ptr<DeregisterEvenIfUnderlyingCodeThrows> safety(
new DeregisterEvenIfUnderlyingCodeThrows(runner.get()));
BSONObj obj;
Runner::RunnerState state;
// uint64_t numMisplacedDocs = 0;
// set this outside loop. we will need to use this both within loop and when deciding
// to fill in explain information
const bool isExplain = pq.isExplain();
while (Runner::RUNNER_ADVANCED == (state = runner->getNext(&obj, NULL))) {
// Add result to output buffer. This is unnecessary if explain info is requested
if (!isExplain) {
bb.appendBuf((void*)obj.objdata(), obj.objsize());
}
// Count the result.
++numResults;
// Possibly note slave's position in the oplog.
if (pq.hasOption(QueryOption_OplogReplay)) {
BSONElement e = obj["ts"];
if (Date == e.type() || Timestamp == e.type()) {
slaveReadTill = e._opTime();
}
}
// TODO: only one type of 2d search doesn't support this. We need a way to pull it out
// of CanonicalQuery. :(
const bool supportsGetMore = true;
if (isExplain) {
if (enoughForExplain(pq, numResults)) {
break;
}
}
else if (!supportsGetMore && (enough(pq, numResults)
|| bb.len() >= MaxBytesToReturnToClientAtOnce)) {
break;
}
else if (enoughForFirstBatch(pq, numResults, bb.len())) {
QLOG() << "Enough for first batch, wantMore=" << pq.wantMore()
<< " numToReturn=" << pq.getNumToReturn()
<< " numResults=" << numResults
<< endl;
// If only one result requested assume it's a findOne() and don't save the cursor.
if (pq.wantMore() && 1 != pq.getNumToReturn()) {
QLOG() << " runner EOF=" << runner->isEOF() << endl;
saveClientCursor = !runner->isEOF();
}
break;
}
}
// If we cache the runner later, we want to deregister it as it receives notifications
// anyway by virtue of being cached.
//
示例8: newGetMore
/**
* Also called by db/ops/query.cpp. This is the new getMore entry point.
*/
QueryResult* newGetMore(const char* ns, int ntoreturn, long long cursorid, CurOp& curop,
int pass, bool& exhaust, bool* isCursorAuthorized) {
exhaust = false;
int bufSize = 512 + sizeof(QueryResult) + MaxBytesToReturnToClientAtOnce;
BufBuilder bb(bufSize);
bb.skip(sizeof(QueryResult));
// This is a read lock. TODO: There is a cursor flag for not needing this. Do we care?
Client::ReadContext ctx(ns);
QLOG() << "running getMore in new system, 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.
replVerifyReadsOk();
// 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(cursorid);
ClientCursor* cc = ccPin.c();
// These are set in the QueryResult msg we return.
int resultFlags = ResultFlag_AwaitCapable;
int numResults = 0;
int startingResult = 0;
if (NULL == cc) {
cursorid = 0;
resultFlags = ResultFlag_CursorNotFound;
}
else {
// Quote: check for spoofing of the ns such that it does not match the one originally
// there for the cursor
uassert(17011, "auth error", str::equals(ns, cc->ns().c_str()));
*isCursorAuthorized = true;
// TODO: fail point?
// If the operation that spawned this cursor had a time limit set, apply leftover
// time to this getmore.
curop.setMaxTimeMicros(cc->getLeftoverMaxTimeMicros());
killCurrentOp.checkForInterrupt(); // May trigger maxTimeAlwaysTimeOut fail point.
// TODO:
// curop.debug().query = BSONForQuery
// curop.setQuery(curop.debug().query);
// TODO: What is pass?
if (0 == pass) { cc->updateSlaveLocation(curop); }
CollectionMetadataPtr collMetadata = cc->getCollMetadata();
// If we're replaying the oplog, we save the last time that we read.
OpTime slaveReadTill;
// What number result are we starting at? Used to fill out the reply.
startingResult = cc->pos();
// What gives us results.
Runner* runner = cc->getRunner();
const int queryOptions = cc->queryOptions();
// Get results out of the runner.
runner->restoreState();
BSONObj obj;
Runner::RunnerState state;
while (Runner::RUNNER_ADVANCED == (state = runner->getNext(&obj, NULL))) {
// Add result to output buffer.
bb.appendBuf((void*)obj.objdata(), obj.objsize());
// Count the result.
++numResults;
// Possibly note slave's position in the oplog.
if (queryOptions & QueryOption_OplogReplay) {
BSONElement e = obj["ts"];
if (Date == e.type() || Timestamp == e.type()) {
slaveReadTill = e._opTime();
}
}
if ((ntoreturn && numResults >= ntoreturn)
|| bb.len() > MaxBytesToReturnToClientAtOnce) {
break;
}
}
if (Runner::RUNNER_EOF == state && 0 == numResults
&& (queryOptions & QueryOption_CursorTailable)
&& (queryOptions & QueryOption_AwaitData) && (pass < 1000)) {
// If the cursor is tailable we don't kill it if it's eof. We let it try to get
//.........这里部分代码省略.........
示例9: queryWithQueryOptimizer
/**
* Run a query with a cursor provided by the query optimizer, or FindingStartCursor.
* @yields the db lock.
*/
string queryWithQueryOptimizer( int queryOptions, const string& ns,
const BSONObj &jsobj, CurOp& curop,
const BSONObj &query, const BSONObj &order,
const shared_ptr<ParsedQuery> &pq_shared,
const BSONObj &oldPlan,
const ChunkVersion &shardingVersionAtStart,
scoped_ptr<PageFaultRetryableSection>& parentPageFaultSection,
scoped_ptr<NoPageFaultsAllowed>& noPageFault,
Message &result ) {
const ParsedQuery &pq( *pq_shared );
shared_ptr<Cursor> cursor;
QueryPlanSummary queryPlan;
if ( pq.hasOption( QueryOption_OplogReplay ) ) {
cursor = FindingStartCursor::getCursor( ns.c_str(), query, order );
}
else {
cursor = getOptimizedCursor( ns.c_str(),
query,
order,
QueryPlanSelectionPolicy::any(),
pq_shared,
false,
&queryPlan );
}
verify( cursor );
scoped_ptr<QueryResponseBuilder> queryResponseBuilder
( QueryResponseBuilder::make( pq, cursor, queryPlan, oldPlan ) );
bool saveClientCursor = false;
OpTime slaveReadTill;
ClientCursorHolder ccPointer( new ClientCursor( QueryOption_NoCursorTimeout, cursor,
ns ) );
for( ; cursor->ok(); cursor->advance() ) {
bool yielded = false;
if ( !ccPointer->yieldSometimes( ClientCursor::MaybeCovered, &yielded ) ||
!cursor->ok() ) {
cursor.reset();
queryResponseBuilder->noteYield();
// !!! TODO The queryResponseBuilder still holds cursor. Currently it will not do
// anything unsafe with the cursor in handoff(), but this is very fragile.
//
// We don't fail the query since we're fine with returning partial data if the
// collection was dropped.
// NOTE see SERVER-2454.
// TODO This is wrong. The cursor could be gone if the closeAllDatabases command
// just ran.
break;
}
if ( yielded ) {
queryResponseBuilder->noteYield();
}
if ( pq.getMaxScan() && cursor->nscanned() > pq.getMaxScan() ) {
break;
}
if ( !queryResponseBuilder->addMatch() ) {
continue;
}
// Note slave's position in the oplog.
if ( pq.hasOption( QueryOption_OplogReplay ) ) {
BSONObj current = cursor->current();
BSONElement e = current["ts"];
if ( e.type() == Date || e.type() == Timestamp ) {
slaveReadTill = e._opTime();
}
}
if ( !cursor->supportGetMore() || pq.isExplain() ) {
if ( queryResponseBuilder->enoughTotalResults() ) {
break;
}
}
else if ( queryResponseBuilder->enoughForFirstBatch() ) {
// if only 1 requested, no cursor saved for efficiency...we assume it is findOne()
if ( pq.wantMore() && pq.getNumToReturn() != 1 ) {
queryResponseBuilder->finishedFirstBatch();
if ( cursor->advance() ) {
saveClientCursor = true;
}
}
break;
}
}
if ( cursor ) {
if ( pq.hasOption( QueryOption_CursorTailable ) && pq.getNumToReturn() != 1 ) {
cursor->setTailable();
}
//.........这里部分代码省略.........
示例10: newGetMore
/**
* Also called by db/ops/query.cpp. This is the new getMore entry point.
*/
QueryResult* newGetMore(const char* ns, int ntoreturn, long long cursorid, CurOp& curop,
int pass, bool& exhaust, bool* isCursorAuthorized) {
exhaust = false;
int bufSize = 512 + sizeof(QueryResult) + MaxBytesToReturnToClientAtOnce;
BufBuilder bb(bufSize);
bb.skip(sizeof(QueryResult));
// This is a read lock. TODO: There is a cursor flag for not needing this. Do we care?
Client::ReadContext ctx(ns);
log() << "running getMore in new system, cursorid " << cursorid << endl;
// TODO: Document.
// TODO: do this when we can pass in our own parsed query
//replVerifyReadsOk();
// 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(cursorid);
ClientCursor* cc = ccPin.c();
// These are set in the QueryResult msg we return.
int resultFlags = ResultFlag_AwaitCapable;
int numResults = 0;
int startingResult = 0;
if (NULL == cc) {
cursorid = 0;
resultFlags = ResultFlag_CursorNotFound;
}
else {
// Quote: check for spoofing of the ns such that it does not match the one originally
// there for the cursor
uassert(17011, "auth error", str::equals(ns, cc->ns().c_str()));
*isCursorAuthorized = true;
// TODO: fail point?
// If the operation that spawned this cursor had a time limit set, apply leftover
// time to this getmore.
curop.setMaxTimeMicros(cc->getLeftoverMaxTimeMicros());
// TODO:
// curop.debug().query = BSONForQuery
// curop.setQuery(curop.debug().query);
// TODO: What is pass?
if (0 == pass) { cc->updateSlaveLocation(curop); }
CollectionMetadataPtr collMetadata = cc->getCollMetadata();
// If we're replaying the oplog, we save the last time that we read.
OpTime slaveReadTill;
// What number result are we starting at? Used to fill out the reply.
startingResult = cc->pos();
// What gives us results.
Runner* runner = cc->getRunner();
const int queryOptions = cc->queryOptions();
// Get results out of the runner.
// TODO: There may be special handling required for tailable cursors?
runner->restoreState();
BSONObj obj;
Runner::RunnerState state;
while (Runner::RUNNER_ADVANCED == (state = runner->getNext(&obj, NULL))) {
// If we're sharded make sure that we don't return any data that hasn't been
// migrated off of our shard yet.
if (collMetadata) {
KeyPattern kp(collMetadata->getKeyPattern());
if (!collMetadata->keyBelongsToMe(kp.extractSingleKey(obj))) { continue; }
}
// Add result to output buffer.
bb.appendBuf((void*)obj.objdata(), obj.objsize());
// Count the result.
++numResults;
// Possibly note slave's position in the oplog.
if (queryOptions & QueryOption_OplogReplay) {
BSONElement e = obj["ts"];
if (Date == e.type() || Timestamp == e.type()) {
slaveReadTill = e._opTime();
}
}
if ((numResults && numResults >= ntoreturn)
|| bb.len() > MaxBytesToReturnToClientAtOnce) {
break;
}
}
//.........这里部分代码省略.........
示例11: newRunQuery
/**
* This is called by db/ops/query.cpp. This is the entry point for answering a query.
*/
string newRunQuery(Message& m, QueryMessage& q, CurOp& curop, Message &result) {
log() << "Running query on new system: " << q.query.toString() << endl;
// This is a read lock.
Client::ReadContext ctx(q.ns, dbpath);
// Parse, canonicalize, plan, transcribe, and get a runner.
Runner* rawRunner;
CanonicalQuery* cq;
Status status = getRunner(q, &rawRunner, &cq);
if (!status.isOK()) {
uasserted(17007, "Couldn't process query " + q.query.toString()
+ " why: " + status.reason());
}
verify(NULL != rawRunner);
auto_ptr<Runner> runner(rawRunner);
// We freak out later if this changes before we're done with the query.
const ChunkVersion shardingVersionAtStart = shardingState.getVersion(q.ns);
// We use this a lot below.
const LiteParsedQuery& pq = cq->getParsed();
// TODO: Document why we do this.
// TODO: do this when we can pass in our own parsed query
//replVerifyReadsOk(&pq);
// If this exists, the collection is sharded.
// If it doesn't exist, we can assume we're not sharded.
// If we're sharded, we might encounter data that is not consistent with our sharding state.
// We must ignore this data.
CollectionMetadataPtr collMetadata;
if (!shardingState.needCollectionMetadata(pq.ns())) {
collMetadata = CollectionMetadataPtr();
}
else {
collMetadata = shardingState.getCollectionMetadata(pq.ns());
}
// Run the query.
BufBuilder bb(32768);
bb.skip(sizeof(QueryResult));
// How many results have we obtained from the runner?
int numResults = 0;
// If we're replaying the oplog, we save the last time that we read.
OpTime slaveReadTill;
// Do we save the Runner in a ClientCursor for getMore calls later?
bool saveClientCursor = false;
// We turn on auto-yielding for the runner here, so we must register it with the active
// runners list in ClientCursor.
ClientCursor::registerRunner(runner.get());
runner->setYieldPolicy(Runner::YIELD_AUTO);
BSONObj obj;
Runner::RunnerState state;
while (Runner::RUNNER_ADVANCED == (state = runner->getNext(&obj, NULL))) {
// If we're sharded make sure that we don't return any data that hasn't been migrated
// off of our shared yet.
if (collMetadata) {
// This information can change if we yield and as such we must make sure to re-fetch
// it if we yield.
KeyPattern kp(collMetadata->getKeyPattern());
// This performs excessive BSONObj creation but that's OK for now.
if (!collMetadata->keyBelongsToMe(kp.extractSingleKey(obj))) { continue; }
}
// Add result to output buffer.
bb.appendBuf((void*)obj.objdata(), obj.objsize());
// Count the result.
++numResults;
// Possibly note slave's position in the oplog.
if (pq.hasOption(QueryOption_OplogReplay)) {
BSONElement e = obj["ts"];
if (Date == e.type() || Timestamp == e.type()) {
slaveReadTill = e._opTime();
}
}
// TODO: only one type of 2d search doesn't support this. We need a way to pull it out
// of CanonicalQuery. :(
const bool supportsGetMore = true;
const bool isExplain = pq.isExplain();
if (isExplain && enoughForExplain(pq, numResults)) {
break;
}
else if (!supportsGetMore && (enough(pq, numResults)
|| bb.len() >= MaxBytesToReturnToClientAtOnce)) {
break;
}
else if (enoughForFirstBatch(pq, numResults, bb.len())) {
//.........这里部分代码省略.........
示例12: newRunQuery
//.........这里部分代码省略.........
boost::scoped_ptr<PlanInfo> planInfo;
while (Runner::RUNNER_ADVANCED == (state = runner->getNext(&obj, NULL))) {
// Add result to output buffer. This is unnecessary if explain info is requested
if (!isExplain) {
bb.appendBuf((void*)obj.objdata(), obj.objsize());
}
// Count the result.
++numResults;
// In the case of the multi plan runner, we may not be able to
// successfully retrieve plan info until after the query starts
// to run. This is because the multi plan runner doesn't know what
// plan it will end up using until it runs candidates and selects
// the best.
//
// TODO: Do we ever want to output what the MPR is comparing?
if (!gotPlanInfo) {
Status infoStatus = runner->getInfo(NULL, &rawInfo);
if (infoStatus.isOK()) {
gotPlanInfo = true;
planInfo.reset(rawInfo);
// planSummary is really a ThreadSafeString which copies the data from
// the provided pointer.
curop.debug().planSummary = planInfo->planSummary.c_str();
}
}
// Possibly note slave's position in the oplog.
if (pq.hasOption(QueryOption_OplogReplay)) {
BSONElement e = obj["ts"];
if (Date == e.type() || Timestamp == e.type()) {
slaveReadTill = e._opTime();
}
}
// TODO: only one type of 2d search doesn't support this. We need a way to pull it out
// of CanonicalQuery. :(
const bool supportsGetMore = true;
if (isExplain) {
if (enoughForExplain(pq, numResults)) {
break;
}
}
else if (!supportsGetMore && (enough(pq, numResults)
|| bb.len() >= MaxBytesToReturnToClientAtOnce)) {
break;
}
else if (enoughForFirstBatch(pq, numResults, bb.len())) {
QLOG() << "Enough for first batch, wantMore=" << pq.wantMore()
<< " numToReturn=" << pq.getNumToReturn()
<< " numResults=" << numResults
<< endl;
// If only one result requested assume it's a findOne() and don't save the cursor.
if (pq.wantMore() && 1 != pq.getNumToReturn()) {
QLOG() << " runner EOF=" << runner->isEOF() << endl;
saveClientCursor = !runner->isEOF();
}
break;
}
}
// Try to get information about the plan which the runner
// will use to execute the query, it we don't have it already.
if (!gotPlanInfo) {
示例13: initialize
Status ReplSetHeartbeatResponse::initialize(const BSONObj& doc) {
// Old versions set this even though they returned not "ok"
_mismatch = doc[kMismatchFieldName].trueValue();
if (_mismatch)
return Status(ErrorCodes::InconsistentReplicaSetNames, "replica set name doesn't match.");
// Old versions sometimes set the replica set name ("set") but ok:0
const BSONElement replSetNameElement = doc[kReplSetFieldName];
if (replSetNameElement.eoo()) {
_setName.clear();
} else if (replSetNameElement.type() != String) {
return Status(ErrorCodes::TypeMismatch,
str::stream() << "Expected \"" << kReplSetFieldName
<< "\" field in response to replSetHeartbeat to have "
"type String, but found "
<< typeName(replSetNameElement.type()));
} else {
_setName = replSetNameElement.String();
}
if (_setName.empty() && !doc[kOkFieldName].trueValue()) {
std::string errMsg = doc[kErrMsgFieldName].str();
BSONElement errCodeElem = doc[kErrorCodeFieldName];
if (errCodeElem.ok()) {
if (!errCodeElem.isNumber())
return Status(ErrorCodes::BadValue, "Error code is not a number!");
int errorCode = errCodeElem.numberInt();
return Status(ErrorCodes::Error(errorCode), errMsg);
}
return Status(ErrorCodes::UnknownError, errMsg);
}
const BSONElement hasDataElement = doc[kHasDataFieldName];
_hasDataSet = !hasDataElement.eoo();
_hasData = hasDataElement.trueValue();
const BSONElement electionTimeElement = doc[kElectionTimeFieldName];
if (electionTimeElement.eoo()) {
_electionTimeSet = false;
} else if (electionTimeElement.type() == Timestamp) {
_electionTimeSet = true;
_electionTime = electionTimeElement._opTime();
} else if (electionTimeElement.type() == Date) {
_electionTimeSet = true;
_electionTime = OpTime(electionTimeElement.date());
} else {
return Status(ErrorCodes::TypeMismatch,
str::stream() << "Expected \"" << kElectionTimeFieldName
<< "\" field in response to replSetHeartbeat "
"command to have type Date or Timestamp, but found type "
<< typeName(electionTimeElement.type()));
}
const BSONElement timeElement = doc[kTimeFieldName];
if (timeElement.eoo()) {
_timeSet = false;
} else if (timeElement.isNumber()) {
_timeSet = true;
_time = Seconds(timeElement.numberLong());
} else {
return Status(ErrorCodes::TypeMismatch,
str::stream() << "Expected \"" << kTimeFieldName
<< "\" field in response to replSetHeartbeat "
"command to have a numeric type, but found type "
<< typeName(timeElement.type()));
}
const BSONElement opTimeElement = doc[kOpTimeFieldName];
if (opTimeElement.eoo()) {
_opTimeSet = false;
} else if (opTimeElement.type() == Timestamp) {
_opTimeSet = true;
_opTime = opTimeElement._opTime();
} else if (opTimeElement.type() == Date) {
_opTimeSet = true;
_opTime = OpTime(opTimeElement.date());
} else {
return Status(ErrorCodes::TypeMismatch,
str::stream() << "Expected \"" << kOpTimeFieldName
<< "\" field in response to replSetHeartbeat "
"command to have type Date or Timestamp, but found type "
<< typeName(opTimeElement.type()));
}
const BSONElement electableElement = doc[kIsElectableFieldName];
if (electableElement.eoo()) {
_electableSet = false;
} else {
_electableSet = true;
_electable = electableElement.trueValue();
}
_isReplSet = doc[kIsReplSetFieldName].trueValue();
const BSONElement memberStateElement = doc[kMemberStateFieldName];
if (memberStateElement.eoo()) {
_stateSet = false;
} else if (memberStateElement.type() != NumberInt && memberStateElement.type() != NumberLong) {
//.........这里部分代码省略.........
示例14: newGetMore
/**
* Also called by db/ops/query.cpp. This is the new getMore entry point.
*/
QueryResult* newGetMore(const char* ns, int ntoreturn, long long cursorid, CurOp& curop,
int pass, bool& exhaust, bool* isCursorAuthorized) {
exhaust = false;
int bufSize = 512 + sizeof(QueryResult) + MaxBytesToReturnToClientAtOnce;
BufBuilder bb(bufSize);
bb.skip(sizeof(QueryResult));
// This is a read lock. TODO: There is a cursor flag for not needing this. Do we care?
Client::ReadContext ctx(ns);
// TODO: Document.
replVerifyReadsOk();
ClientCursorPin ccPin(cursorid);
ClientCursor* cc = ccPin.c();
// These are set in the QueryResult msg we return.
int resultFlags = ResultFlag_AwaitCapable;
int numResults = 0;
int startingResult = 0;
if (NULL == cc) {
cursorid = 0;
resultFlags = ResultFlag_CursorNotFound;
}
else {
// Quote: check for spoofing of the ns such that it does not match the one originally
// there for the cursor
uassert(17011, "auth error", str::equals(ns, cc->ns().c_str()));
*isCursorAuthorized = true;
// TODO: fail point?
// If the operation that spawned this cursor had a time limit set, apply leftover
// time to this getmore.
curop.setMaxTimeMicros(cc->getLeftoverMaxTimeMicros());
// TODO:
// curop.debug().query = BSONForQuery
// curop.setQuery(curop.debug().query);
// TODO: What is pass?
if (0 == pass) { cc->updateSlaveLocation(curop); }
CollectionMetadataPtr collMetadata = cc->getCollMetadata();
// If we're replaying the oplog, we save the last time that we read.
OpTime slaveReadTill;
startingResult = cc->pos();
Runner* runner = cc->getRunner();
const ParsedQuery& pq = runner->getQuery().getParsed();
// Get results out of the runner.
// TODO: There may be special handling required for tailable cursors?
runner->restoreState();
BSONObj obj;
// TODO: Differentiate EOF from error.
while (runner->getNext(&obj)) {
// If we're sharded make sure that we don't return any data that hasn't been
// migrated off of our shard yet.
if (collMetadata) {
KeyPattern kp(collMetadata->getKeyPattern());
if (!collMetadata->keyBelongsToMe(kp.extractSingleKey(obj))) { continue; }
}
// Add result to output buffer.
bb.appendBuf((void*)obj.objdata(), obj.objsize());
// Count the result.
++numResults;
// Possibly note slave's position in the oplog.
if (pq.hasOption(QueryOption_OplogReplay)) {
BSONElement e = obj["ts"];
if (Date == e.type() || Timestamp == e.type()) {
slaveReadTill = e._opTime();
}
}
if ((numResults && numResults >= ntoreturn)
|| bb.len() > MaxBytesToReturnToClientAtOnce) {
break;
}
}
cc->incPos(numResults);
runner->saveState();
// Possibly note slave's position in the oplog.
if (pq.hasOption(QueryOption_OplogReplay) && !slaveReadTill.isNull()) {
cc->slaveReadTill(slaveReadTill);
}
exhaust = pq.hasOption(QueryOption_Exhaust);
//.........这里部分代码省略.........
示例15: queryResponseBuilder
/**
* Run a query with a cursor provided by the query optimizer, or FindingStartCursor.
* @yields the db lock.
*/
const char *queryWithQueryOptimizer( Message &m, int queryOptions, const char *ns,
const BSONObj &jsobj, CurOp& curop,
const BSONObj &query, const BSONObj &order,
const shared_ptr<ParsedQuery> &pq_shared,
const BSONObj &oldPlan,
const ConfigVersion &shardingVersionAtStart,
Message &result ) {
const ParsedQuery &pq( *pq_shared );
shared_ptr<Cursor> cursor;
QueryPlanSummary queryPlan;
if ( pq.hasOption( QueryOption_OplogReplay ) ) {
cursor = FindingStartCursor::getCursor( ns, query, order );
}
else {
cursor =
NamespaceDetailsTransient::getCursor( ns, query, order, QueryPlanSelectionPolicy::any(),
0, pq_shared, &queryPlan );
}
verify( cursor );
QueryResponseBuilder queryResponseBuilder( pq, cursor, queryPlan, oldPlan );
bool saveClientCursor = false;
const char *exhaust = 0;
OpTime slaveReadTill;
ClientCursor::CleanupPointer ccPointer;
ccPointer.reset( new ClientCursor( QueryOption_NoCursorTimeout, cursor, ns ) );
for( ; cursor->ok(); cursor->advance() ) {
bool yielded = false;
if ( !ccPointer->yieldSometimes( ClientCursor::MaybeCovered, &yielded ) ||
!cursor->ok() ) {
cursor.reset();
queryResponseBuilder.noteYield();
// !!! TODO The queryResponseBuilder still holds cursor. Currently it will not do
// anything unsafe with the cursor in handoff(), but this is very fragile.
//
// We don't fail the query since we're fine with returning partial data if the
// collection was dropped.
// NOTE see SERVER-2454.
// TODO This is wrong. The cursor could be gone if the closeAllDatabases command
// just ran.
break;
}
if ( yielded ) {
queryResponseBuilder.noteYield();
}
if ( pq.getMaxScan() && cursor->nscanned() > pq.getMaxScan() ) {
break;
}
if ( !queryResponseBuilder.addMatch() ) {
continue;
}
// Note slave's position in the oplog.
if ( pq.hasOption( QueryOption_OplogReplay ) ) {
BSONObj current = cursor->current();
BSONElement e = current["ts"];
if ( e.type() == Date || e.type() == Timestamp ) {
slaveReadTill = e._opTime();
}
}
if ( !cursor->supportGetMore() || pq.isExplain() ) {
if ( queryResponseBuilder.enoughTotalResults() ) {
break;
}
}
else if ( queryResponseBuilder.enoughForFirstBatch() ) {
// if only 1 requested, no cursor saved for efficiency...we assume it is findOne()
if ( pq.wantMore() && pq.getNumToReturn() != 1 ) {
queryResponseBuilder.finishedFirstBatch();
if ( cursor->advance() ) {
saveClientCursor = true;
}
}
break;
}
}
if ( cursor ) {
if ( pq.hasOption( QueryOption_CursorTailable ) && pq.getNumToReturn() != 1 ) {
cursor->setTailable();
}
// If the tailing request succeeded.
if ( cursor->tailable() ) {
saveClientCursor = true;
}
}
//.........这里部分代码省略.........