bool _run(OperationContext* txn, const string& , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) { if( cmdObj["replSetReconfig"].type() != Object ) { errmsg = "no configuration specified"; return false; } ReplicationCoordinator::ReplSetReconfigArgs parsedArgs; parsedArgs.newConfigObj = cmdObj["replSetReconfig"].Obj(); parsedArgs.force = cmdObj.hasField("force") && cmdObj["force"].trueValue(); Status status = getGlobalReplicationCoordinator()->processReplSetReconfig(txn, parsedArgs, &result); return appendCommandStatus(result, status); }
Status checkAuthForApplyOpsCommand(OperationContext* txn, const std::string& dbname, const BSONObj& cmdObj) { AuthorizationSession* authSession = AuthorizationSession::get(txn->getClient()); ApplyOpsValidity validity = validateApplyOpsCommand(cmdObj); if (validity == ApplyOpsValidity::kNeedsSuperuser) { std::vector<Privilege> universalPrivileges; RoleGraph::generateUniversalPrivileges(&universalPrivileges); if (!authSession->isAuthorizedForPrivileges(universalPrivileges)) { return Status(ErrorCodes::Unauthorized, "Unauthorized"); } return Status::OK(); } fassert(40314, validity == ApplyOpsValidity::kOk); boost::optional<DisableDocumentValidation> maybeDisableValidation; if (shouldBypassDocumentValidationForCommand(cmdObj)) maybeDisableValidation.emplace(txn); const bool alwaysUpsert = cmdObj.hasField("alwaysUpsert") ? cmdObj["alwaysUpsert"].trueValue() : true; checkBSONType(BSONType::Array, cmdObj.firstElement()); for (const BSONElement& e : cmdObj.firstElement().Array()) { checkBSONType(BSONType::Object, e); Status status = checkOperationAuthorization(txn, dbname, e.Obj(), alwaysUpsert); if (!status.isOK()) { return status; } } BSONElement preconditions = cmdObj["preCondition"]; if (!preconditions.eoo()) { for (const BSONElement& precondition : preconditions.Array()) { checkBSONType(BSONType::Object, precondition); BSONElement nsElem = precondition.Obj()["ns"]; checkBSONType(BSONType::String, nsElem); NamespaceString nss(nsElem.checkAndGetStringData()); if (!authSession->isAuthorizedForActionsOnResource( ResourcePattern::forExactNamespace(nss), ActionType::find)) { return Status(ErrorCodes::Unauthorized, "Unauthorized to check precondition"); } } } return Status::OK(); }
StatusWith<std::vector<BSONElement>> DatabasesCloner::_parseListDatabasesResponse( BSONObj dbResponse) { if (!dbResponse.hasField("databases")) { return Status(ErrorCodes::BadValue, "The 'listDatabases' response does not contain a 'databases' field."); } BSONElement response = dbResponse["databases"]; try { return response.Array(); } catch (const AssertionException&) { return Status(ErrorCodes::BadValue, "The 'listDatabases' response is unable to be transformed into an array."); } }
bool run( const string& db, BSONObj& cmdObj, int options, string& errmsg, BSONObjBuilder& result, bool fromRepl = false ) { if (cmdObj.hasField("reset")) { ReplSetConfig::OPLOG_VERSION = ReplSetConfig::OPLOG_VERSION_CURRENT; } else { ReplSetConfig::OPLOG_VERSION = ReplSetConfig::OPLOG_VERSION_TEST; } return true; }
StatusWith<std::vector<BSONElement>> CollectionCloner::_parseParallelCollectionScanResponse( BSONObj resp) { if (!resp.hasField("cursors")) { return Status(ErrorCodes::CursorNotFound, "The 'parallelCollectionScan' response does not contain a 'cursors' field."); } BSONElement response = resp["cursors"]; if (response.type() == BSONType::Array) { return response.Array(); } else { return Status( ErrorCodes::FailedToParse, "The 'parallelCollectionScan' response is unable to be transformed into an array."); } }
virtual bool run(OperationContext* txn, const string& , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) { if( !check(errmsg, result) ) return false; bool force = cmdObj.hasField("force") && cmdObj["force"].trueValue(); int secs = (int) cmdObj.firstElement().numberInt(); if( secs == 0 ) secs = 60; Status status = getGlobalReplicationCoordinator()->stepDown( force, ReplicationCoordinator::Milliseconds(0), ReplicationCoordinator::Milliseconds(secs * 1000)); return appendCommandStatus(result, status); }
int CMongodbModel::GetIntFieldValue(BSONObj boRecord, string strFieldName, int iExceptionValue) { int iValue = iExceptionValue; if (boRecord.hasField(strFieldName)) { try { iValue = boRecord.getIntField(strFieldName.c_str()); } catch(exception& ex) {} } return iValue; }
Status V1UserDocumentParser::initializeUserCredentialsFromUserDocument( User* user, const BSONObj& privDoc) const { User::CredentialData credentials; if (privDoc.hasField(AuthorizationManager::PASSWORD_FIELD_NAME)) { credentials.password = privDoc[AuthorizationManager::PASSWORD_FIELD_NAME].String(); credentials.isExternal = false; } else if (privDoc.hasField(AuthorizationManager::V1_USER_SOURCE_FIELD_NAME)) { std::string userSource = privDoc[AuthorizationManager::V1_USER_SOURCE_FIELD_NAME].String(); if (userSource != "$external") { return Status(ErrorCodes::UnsupportedFormat, "Cannot extract credentials from user documents without a password " "and with userSource != \"$external\""); } else { credentials.isExternal = true; } } else { return Status(ErrorCodes::UnsupportedFormat, "Invalid user document: must have one of \"pwd\" and \"userSource\""); } user->setCredentials(credentials); return Status::OK(); }
Status AuthzManagerExternalStateMock::updateOne(OperationContext* txn, const NamespaceString& collectionName, const BSONObj& query, const BSONObj& updatePattern, bool upsert, const BSONObj& writeConcern) { namespace mmb = mutablebson; UpdateDriver::Options updateOptions; UpdateDriver driver(updateOptions); Status status = driver.parse(updatePattern); if (!status.isOK()) return status; BSONObjCollection::iterator iter; status = _findOneIter(collectionName, query, &iter); mmb::Document document; if (status.isOK()) { document.reset(*iter, mmb::Document::kInPlaceDisabled); BSONObj logObj; status = driver.update(StringData(), &document, &logObj); if (!status.isOK()) return status; BSONObj newObj = document.getObject().copy(); *iter = newObj; BSONObj idQuery = driver.makeOplogEntryQuery(newObj, false); if (_authzManager) { _authzManager->logOp(txn, "u", collectionName.ns().c_str(), logObj, &idQuery); } return Status::OK(); } else if (status == ErrorCodes::NoMatchingDocument && upsert) { if (query.hasField("_id")) { document.root().appendElement(query["_id"]); } status = driver.populateDocumentWithQueryFields(query, NULL, document); if (!status.isOK()) { return status; } status = driver.update(StringData(), &document); if (!status.isOK()) { return status; } return insert(txn, collectionName, document.getObject(), writeConcern); } else { return status; } }
bool run( const string& db, BSONObj& cmdObj, int options, string& errmsg, BSONObjBuilder& result, bool fromRepl = false ) { if (cmdObj.hasField("keepOplogAlive")) { uint64_t val = cmdObj["keepOplogAlive"].numberLong(); if (theReplSet) { theReplSet->setKeepOplogAlivePeriod(val); } } return true; }
Status AuthorizationManager::buildPrivilegeSet(const std::string& dbname, const PrincipalName& principal, const BSONObj& privilegeDocument, PrivilegeSet* result) { if (!privilegeDocument.hasField(ROLES_FIELD_NAME)) { // Old-style (v2.2 and prior) privilege document return _buildPrivilegeSetFromOldStylePrivilegeDocument(dbname, principal, privilegeDocument, result); } else { return _buildPrivilegeSetFromExtendedPrivilegeDocument( dbname, principal, privilegeDocument, result); } }
/* **************************************************************************** * * setCount - */ static void setCount(long long inc, const BSONObj& subOrig, BSONObjBuilder* b) { if (subOrig.hasField(CSUB_COUNT)) { long long count = getIntOrLongFieldAsLongF(subOrig, CSUB_COUNT); setCount(count + inc, b); } else { // In this case we only add if inc is different from 0 if (inc > 0) { setCount(inc, b); } } }
Status LiteParsedQuery::init(const string& ns, int ntoskip, int ntoreturn, int queryOptions, const BSONObj& queryObj, const BSONObj& proj, bool fromQueryMessage) { _ns = ns; _ntoskip = ntoskip; _ntoreturn = ntoreturn; _options = queryOptions; _proj = proj.getOwned(); if (_ntoskip < 0) { return Status(ErrorCodes::BadValue, "bad skip value in query"); } if (_ntoreturn < 0) { // _ntoreturn greater than zero is simply a hint on how many objects to send back per // "cursor batch". A negative number indicates a hard limit. _wantMore = false; _ntoreturn = -_ntoreturn; } if (fromQueryMessage) { BSONElement queryField = queryObj["query"]; if (!queryField.isABSONObj()) { queryField = queryObj["$query"]; } if (queryField.isABSONObj()) { _filter = queryField.embeddedObject().getOwned(); Status status = initFullQuery(queryObj); if (!status.isOK()) { return status; } } else { // TODO: Does this ever happen? _filter = queryObj.getOwned(); } } else { // This is the debugging code path. _filter = queryObj.getOwned(); } _hasReadPref = queryObj.hasField("$readPreference"); if (!isValidSortOrder(_sort)) { return Status(ErrorCodes::BadValue, "bad sort specification"); } _sort = normalizeSortOrder(_sort); return Status::OK(); }
void createCollectionWithOptions(BSONObj obj) { BSONObjIterator i(obj); // Rebuild obj as a command object for the "create" command. // - {create: <name>} comes first, where <name> is the new name for the collection // - elements with type Undefined get skipped over BSONObjBuilder bo; bo.append("create", _curcoll); while (i.more()) { BSONElement e = i.next(); if (strcmp(e.fieldName(), "create") == 0) { continue; } if (e.type() == Undefined) { log() << _curns << ": skipping undefined field: " << e.fieldName() << endl; continue; } bo.append(e); } obj = bo.obj(); BSONObj fields = BSON("options" << 1); scoped_ptr<DBClientCursor> cursor(conn().query(_curdb + ".system.namespaces", Query(BSON("name" << _curns)), 0, 0, &fields)); bool createColl = true; if (cursor->more()) { createColl = false; BSONObj nsObj = cursor->next(); if (!nsObj.hasField("options") || !optionsSame(obj, nsObj["options"].Obj())) { log() << "WARNING: collection " << _curns << " exists with different options than are in the metadata.json file and not using --drop. Options in the metadata file will be ignored." << endl; } } if (!createColl) { return; } BSONObj info; if (!conn().runCommand(_curdb, obj, info)) { uasserted(15936, "Creating collection " + _curns + " failed. Errmsg: " + info["errmsg"].String()); } else { log() << "\tCreated collection " << _curns << " with options: " << obj.jsonString() << endl; } }
/* **************************************************************************** * * setSubject - */ static void setSubject(Subscription* s, const BSONObj& r) { // Entities std::vector<BSONElement> ents = getField(r, CSUB_ENTITIES).Array(); for (unsigned int ix = 0; ix < ents.size(); ++ix) { BSONObj ent = ents[ix].embeddedObject(); std::string id = getStringField(ent, CSUB_ENTITY_ID); std::string type = ent.hasField(CSUB_ENTITY_TYPE)? getStringField(ent, CSUB_ENTITY_TYPE) : ""; std::string isPattern = getStringField(ent, CSUB_ENTITY_ISPATTERN); EntID en; if (isFalse(isPattern)) { en.id = id; } else { en.idPattern = id; } en.type = type; s->subject.entities.push_back(en); } // Condition std::vector<BSONElement> conds = getField(r, CSUB_CONDITIONS).Array(); for (unsigned int ix = 0; ix < conds.size(); ++ix) { BSONObj cond = conds[ix].embeddedObject(); // The ONCHANGE check is needed, as a subscription could mix different conditions types in DB if (std::string(getStringField(cond, CSUB_CONDITIONS_TYPE)) == "ONCHANGE") { std::vector<BSONElement> condValues = getField(cond, CSUB_CONDITIONS_VALUE).Array(); for (unsigned int jx = 0; jx < condValues.size(); ++jx) { std::string attr = condValues[jx].String(); s->subject.condition.attributes.push_back(attr); } } } // Note that current DB model is based on NGSIv1 and doesn't consider expressions. Thus // subject.condition.expression cannot be filled. The implemetion will be enhanced once // the DB model gets defined // TBD }
/* **************************************************************************** * * setDescription - */ static void setDescription(const SubscriptionUpdate& subUp, const BSONObj& subOrig, BSONObjBuilder* b) { if (subUp.descriptionProvided) { setDescription(subUp, b); } else { if (subOrig.hasField(CSUB_DESCRIPTION)) { std::string description = getStringFieldF(subOrig, CSUB_DESCRIPTION); b->append(CSUB_DESCRIPTION, description); LM_T(LmtMongo, ("Subscription description: %s", description.c_str())); } } }
Value DocumentSourceCursor::serialize(bool explain) const { // we never parse a documentSourceCursor, so we only serialize for explain if (!explain) return Value(); // Get planner-level explain info from the underlying PlanExecutor. BSONObjBuilder explainBuilder; Status explainStatus(ErrorCodes::InternalError, ""); { const NamespaceString nss(_ns); AutoGetCollectionForRead autoColl(pExpCtx->opCtx, nss); massert(17392, "No _exec. Were we disposed before explained?", _exec); _exec->restoreState(pExpCtx->opCtx); explainStatus = Explain::explainStages(pExpCtx->opCtx, _exec.get(), ExplainCommon::QUERY_PLANNER, &explainBuilder); _exec->saveState(); } MutableDocument out; out["query"] = Value(_query); if (!_sort.isEmpty()) out["sort"] = Value(_sort); if (_limit) out["limit"] = Value(_limit->getLimit()); if (!_projection.isEmpty()) out["fields"] = Value(_projection); // Add explain results from the query system into the agg explain output. if (explainStatus.isOK()) { BSONObj explainObj = explainBuilder.obj(); invariant(explainObj.hasField("queryPlanner")); out["queryPlanner"] = Value(explainObj["queryPlanner"]); } else { out["planError"] = Value(explainStatus.toString()); } return Value(DOC(getSourceName() << out.freezeToValue())); }
/* **************************************************************************** * * setThrottling - */ static void setThrottling(const SubscriptionUpdate& subUp, const BSONObj& subOrig, BSONObjBuilder* b) { if (subUp.throttlingProvided) { setThrottling(subUp, b); } else { if (subOrig.hasField(CSUB_THROTTLING)) { long long throttling = getIntOrLongFieldAsLongF(subOrig, CSUB_THROTTLING); b->append(CSUB_THROTTLING, throttling); LM_T(LmtMongo, ("Subscription throttling: %lu", throttling)); } } }
/* **************************************************************************** * * setStatus - */ static void setStatus(const SubscriptionUpdate& subUp, const BSONObj& subOrig, BSONObjBuilder* b) { if (subUp.statusProvided) { setStatus(subUp, b); } else { if (subOrig.hasField(CSUB_STATUS)) { std::string status = getStringFieldF(subOrig, CSUB_STATUS); b->append(CSUB_STATUS, status); LM_T(LmtMongo, ("Subscription status: %s", status.c_str())); } } }
/* **************************************************************************** * * setExpiration - */ static void setExpiration(const SubscriptionUpdate& subUp, const BSONObj& subOrig, BSONObjBuilder* b) { if (subUp.expiresProvided) { setExpiration(subUp, b); } else { if (subOrig.hasField(CSUB_EXPIRATION)) { int64_t expires = getIntOrLongFieldAsLongF(subOrig, CSUB_EXPIRATION); b->append(CSUB_EXPIRATION, (long long) expires); LM_T(LmtMongo, ("Subscription expiration: %lu", expires)); } } }
Status ShardingEgressMetadataHook::_advanceConfigOptimeFromShard(ShardId shardId, const BSONObj& metadataObj) { try { auto shard = grid.shardRegistry()->getShardNoReload(shardId); if (!shard) { return Status::OK(); } // Update our notion of the config server opTime from the configOpTime in the response. if (shard->isConfig()) { // Config servers return the config opTime as part of their own metadata. if (metadataObj.hasField(rpc::kReplSetMetadataFieldName)) { auto parseStatus = rpc::ReplSetMetadata::readFromMetadata(metadataObj); if (!parseStatus.isOK()) { return parseStatus.getStatus(); } // Use the last committed optime to advance config optime. // For successful majority writes, we could use the optime of the last op // from us and lastOpCommitted is always greater than or equal to it. // On majority write failures, the last visible optime would be incorrect // due to rollback as explained in SERVER-24630 and the last committed optime // is safe to use. const auto& replMetadata = parseStatus.getValue(); auto opTime = replMetadata.getLastOpCommitted(); grid.advanceConfigOpTime(opTime); } } else { // Regular shards return the config opTime as part of ConfigServerMetadata. auto parseStatus = rpc::ConfigServerMetadata::readFromMetadata(metadataObj); if (!parseStatus.isOK()) { return parseStatus.getStatus(); } const auto& configMetadata = parseStatus.getValue(); auto opTime = configMetadata.getOpTime(); if (opTime.is_initialized()) { grid.advanceConfigOpTime(opTime.get()); } } return Status::OK(); } catch (...) { return exceptionToStatus(); } }
BSONObj ShardedCursor::concatQuery( const BSONObj& query , const BSONObj& extraFilter ){ if ( ! query.hasField( "query" ) ) return _concatFilter( query , extraFilter ); BSONObjBuilder b; BSONObjIterator i( query ); while ( i.more() ){ BSONElement e = i.next(); if ( strcmp( e.fieldName() , "query" ) ){ b.append( e ); continue; } b.append( "query" , _concatFilter( e.embeddedObjectUserCheck() , extraFilter ) ); } return b.obj(); }
void WriteResult::_createWriteError(const BSONObj& error, const std::vector<WriteOperation*>& ops) { int batchIndex = _getIntOrDefault(error, "index"); int code = _getIntOrDefault(error, "code", kUnknownError); BSONObjBuilder bob; bob.append("index", static_cast<long long>(ops[batchIndex]->getBulkIndex())); bob.append("code", code); bob.append("errmsg", error.getStringField("errmsg")); BSONObjBuilder builder; ops[batchIndex]->appendSelfToBSONObj(&builder); bob.append("op", builder.obj()); if (error.hasField("errInfo")) bob.append("details", error.getObjectField("errInfo")); _writeErrors.push_back(bob.obj()); }
Status AuthorizationManager::buildPrivilegeSet(const std::string& dbname, const PrincipalName& principal, const BSONObj& privilegeDocument, PrivilegeSet* result) { if (!privilegeDocument.hasField("privileges")) { // Old-style (v2.2 and prior) privilege document return _buildPrivilegeSetFromOldStylePrivilegeDocument(dbname, principal, privilegeDocument, result); } else { return Status(ErrorCodes::UnsupportedFormat, mongoutils::str::stream() << "Invalid privilege document received when " "trying to extract privileges: " << privilegeDocument, 0); } }
Status AuthzManagerExternalStateMock::updateOne( const NamespaceString& collectionName, const BSONObj& query, const BSONObj& updatePattern, bool upsert, const BSONObj& writeConcern) { namespace mmb = mutablebson; UpdateDriver::Options updateOptions; updateOptions.upsert = upsert; UpdateDriver driver(updateOptions); Status status = driver.parse(updatePattern); if (!status.isOK()) return status; BSONObjCollection::iterator iter; status = _findOneIter(collectionName, query, &iter); mmb::Document document; if (status.isOK()) { document.reset(*iter, mmb::Document::kInPlaceDisabled); status = driver.update(StringData(), &document, NULL); if (!status.isOK()) return status; *iter = document.getObject().copy(); return Status::OK(); } else if (status == ErrorCodes::NoMatchingDocument && upsert) { if (query.hasField("_id")) { document.root().appendElement(query["_id"]); } status = driver.createFromQuery(query, document); if (!status.isOK()) { return status; } status = driver.update(StringData(), &document, NULL); if (!status.isOK()) { return status; } return insert(collectionName, document.getObject(), writeConcern); } else { return status; } }
BSONObj CMongodbModel::ConvertBSONObj(BSONObj boRecord, map<string, string> mapField) { BSONObjBuilder bobCenRecord; map<string, string>::iterator mit; int iFieldType; try{ for (mit = mapField.begin(); mit != mapField.end(); mit++) { if (boRecord.hasField(mit->second)){ iFieldType = boRecord[mit->second].type(); switch (iFieldType) { case BSON_STRING_TYPE: bobCenRecord.append(mit->first, boRecord.getStringField(mit->second.c_str())); break; case BSON_INT_TYPE: bobCenRecord.append(mit->first, boRecord[mit->second]._numberInt()); break; case BSON_TIMESTAMP_TYPE: bobCenRecord.append(mit->first, boRecord[mit->second]._numberLong()); break; case BSON_LONG_LONG_TYPE: bobCenRecord.append(mit->first, boRecord[mit->second]._numberLong()); break; default: bobCenRecord.append(mit->first, boRecord[mit->second].toString(false)); } } else{ bobCenRecord.append(mit->first, ""); } } } catch (exception &ex) { stringstream strErrorMess; string strLog; strErrorMess << ex.what() << "][" << __FILE__ << "|" << __LINE__; strLog = CUtilities::FormatLog(ERROR_MSG, "CMongodbModel", "ConvertBSONObj", "exception:" + strErrorMess.str()); CUtilities::WriteErrorLog(ERROR_MSG, strLog); } return bobCenRecord.obj(); }
/* CmdObj has the form {"hash" : <thingToHash>} * or {"hash" : <thingToHash>, "seed" : <number> } * Result has the form * {"key" : <thingTohash>, "seed" : <int>, "out": NumberLong(<hash>)} * * Example use in the shell: *> db.runCommand({hash: "hashthis", seed: 1}) *> {"key" : "hashthis", *> "seed" : 1, *> "out" : NumberLong(6271151123721111923), *> "ok" : 1 } **/ bool run(OperationContext* txn, const string& db, BSONObj& cmdObj, int options, string& errmsg, BSONObjBuilder& result){ result.appendAs(cmdObj.firstElement(),"key"); int seed = 0; if (cmdObj.hasField("seed")){ if (! cmdObj["seed"].isNumber()) { errmsg += "seed must be a number"; return false; } seed = cmdObj["seed"].numberInt(); } result.append( "seed" , seed ); result.append( "out" , BSONElementHasher::hash64( cmdObj.firstElement() , seed ) ); return true; }
Status ServerSelectionMetadata::upconvert(const BSONObj& legacyCommand, const int legacyQueryFlags, BSONObjBuilder* commandBob, BSONObjBuilder* metadataBob) { // The secondaryOK option is equivalent to the slaveOk bit being set on legacy commands. if (legacyQueryFlags & QueryOption_SlaveOk) { metadataBob->append(kSecondaryOkFieldName, 1); } // First we need to check if we have a wrapped command. That is, a command of the form // {'$query': { 'commandName': 1, ...}, '$someOption': 5, ....}. Curiously, the field name // of the wrapped query can be either '$query', or 'query'. auto swUnwrapped = unwrapCommand(legacyCommand); if (!swUnwrapped.isOK()) { return swUnwrapped.getStatus(); } BSONObj maybeUnwrapped; bool wasWrapped; std::tie(wasWrapped, maybeUnwrapped) = swUnwrapped.getValue(); if (wasWrapped) { // Check if legacyCommand has an invalid $maxTimeMS option. // TODO: Move this check elsewhere when we handle upconverting/downconverting maxTimeMS. if (legacyCommand.hasField("$maxTimeMS")) { return Status(ErrorCodes::InvalidOptions, "cannot use $maxTimeMS query option with " "commands; use maxTimeMS command option " "instead"); } // If the command was wrapped, we can write out the upconverted command now, as there // is nothing else we need to remove from it. commandBob->appendElements(maybeUnwrapped); return extractWrappedReadPreference(legacyCommand, metadataBob); } // If the command was not wrapped, we need to check for a readPreference sent by mongos // on the $queryOptions field of the command. If it is set, we remove it from the // upconverted command, so we need to pass the command builder along. return extractUnwrappedReadPreference(maybeUnwrapped, commandBob, metadataBob); }
// Compares 2 BSONObj representing collection options. Returns true if the objects // represent different options. Ignores the "create" field. bool optionsSame(BSONObj obj1, BSONObj obj2) { int nfields = 0; BSONObjIterator i(obj1); while ( i.more() ) { BSONElement e = i.next(); if (!obj2.hasField(e.fieldName())) { if (strcmp(e.fieldName(), "create") == 0) { continue; } else { return false; } } nfields++; if (e != obj2[e.fieldName()]) { return false; } } return nfields == obj2.nFields(); }
void _delete( Request& r , DbMessage& d, ChunkManagerPtr manager ){ int flags = d.pullInt(); bool justOne = flags & 1; uassert( 10203 , "bad delete message" , d.moreJSObjs() ); BSONObj pattern = d.nextJsObj(); set<Shard> shards; int left = 5; while ( true ){ try { manager->getShardsForQuery( shards , pattern ); log(2) << "delete : " << pattern << " \t " << shards.size() << " justOne: " << justOne << endl; if ( shards.size() == 1 ){ doWrite( dbDelete , r , *shards.begin() ); return; } break; } catch ( StaleConfigException& e ){ if ( left <= 0 ) throw e; left--; log() << "delete failed b/c of StaleConfigException, retrying " << " left:" << left << " ns: " << r.getns() << " patt: " << pattern << endl; r.reset( false ); shards.clear(); manager = r.getChunkManager(); } } if ( justOne && ! pattern.hasField( "_id" ) ) throw UserException( 8015 , "can only delete with a non-shard key pattern if can delete as many as we find" ); for ( set<Shard>::iterator i=shards.begin(); i!=shards.end(); i++){ int * x = (int*)(r.d().afterNS()); x[0] |= RemoveOption_Broadcast; doWrite( dbDelete , r , *i , false ); } }