Status V2UserDocumentParser::parseRoleName(const BSONObj& roleObject, RoleName* result) { BSONElement roleNameElement; BSONElement roleSourceElement; Status status = _extractRoleDocumentElements(roleObject, &roleNameElement, &roleSourceElement); if (!status.isOK()) return status; *result = RoleName(roleNameElement.str(), roleSourceElement.str()); return status; }
intrusive_ptr<DocumentSource> DocumentSourceOut::createFromBson( BSONElement elem, const intrusive_ptr<ExpressionContext>& pExpCtx) { uassert(16990, str::stream() << "$out only supports a string argument, not " << typeName(elem.type()), elem.type() == String); NamespaceString outputNs(pExpCtx->ns.db().toString() + '.' + elem.str()); uassert(17385, "Can't $out to special collection: " + elem.str(), !outputNs.isSpecial()); return new DocumentSourceOut(outputNs, pExpCtx); }
intrusive_ptr<DocumentSource> DocumentSourceOut::createFromBson( BSONElement elem, const intrusive_ptr<ExpressionContext>& pExpCtx) { uassert(16990, str::stream() << "$out only supports a string argument, not " << typeName(elem.type()), elem.type() == String); uassert(ErrorCodes::InvalidOptions, "$out can only be used with the 'local' read concern level", !pExpCtx->opCtx->recoveryUnit()->isReadingFromMajorityCommittedSnapshot()); NamespaceString outputNs(pExpCtx->ns.db().toString() + '.' + elem.str()); uassert(17385, "Can't $out to special collection: " + elem.str(), !outputNs.isSpecial()); return new DocumentSourceOut(outputNs, pExpCtx); }
Status bsonExtractStringField(const BSONObj& object, StringData fieldName, std::string* out) { BSONElement element; Status status = bsonExtractTypedField(object, fieldName, String, &element); if (status.isOK()) *out = element.str(); return status; }
HashedIndexType::HashedIndexType( const IndexPlugin* plugin , const IndexSpec* spec ) : IndexType( plugin , spec ) , _keyPattern( spec->keyPattern ) { //change these if single-field limitation lifted later uassert( 16241 , "Currently only single field hashed index supported." , _keyPattern.toBSON().nFields() == 1 ); uassert( 16242 , "Currently hashed indexes cannot guarantee uniqueness. Use a regular index." , ! (spec->info).getField("unique").booleanSafe() ); //Default _seed to 0 if "seed" is not included in the index spec //or if the value of "seed" is not a number _seed = (spec->info).getField("seed").numberInt(); //Default _isSparse to false if "sparse" is not included in the index spec //or if the value of "sparse" is not a boolean _isSparse = (spec->info).getField("sparse").booleanSafe(); //In case we have hashed indexes based on other hash functions in //the future, we store a hashVersion number. If hashVersion changes, // "makeSingleKey" will need to change accordingly. //Defaults to 0 if "hashVersion" is not included in the index spec //or if the value of "hashversion" is not a number _hashVersion = (spec->info).getField("hashVersion").numberInt(); //Get the hashfield name BSONElement firstElt = spec->keyPattern.firstElement(); massert( 16243 , "error: no hashed index field" , firstElt.str().compare( HASHED_INDEX_TYPE_IDENTIFIER ) == 0 ); _hashedField = firstElt.fieldName(); }
Status saslExtractPayload(const BSONObj& cmdObj, std::string* payload, BSONType* type) { BSONElement payloadElement; Status status = bsonExtractField(cmdObj, saslCommandPayloadFieldName, &payloadElement); if (!status.isOK()) return status; *type = payloadElement.type(); if (payloadElement.type() == BinData) { const char* payloadData; int payloadLen; payloadData = payloadElement.binData(payloadLen); if (payloadLen < 0) return Status(ErrorCodes::InvalidLength, "Negative payload length"); *payload = std::string(payloadData, payloadData + payloadLen); } else if (payloadElement.type() == String) { try { *payload = base64::decode(payloadElement.str()); } catch (UserException& e) { return Status(ErrorCodes::FailedToParse, e.what()); } } else { return Status(ErrorCodes::TypeMismatch, (str::stream() << "Wrong type for field; expected BinData or String for " << payloadElement)); } return Status::OK(); }
intrusive_ptr<DocumentSource> DocumentSourceOut::createFromBson( BSONElement elem, const intrusive_ptr<ExpressionContext>& expCtx) { auto mode = WriteModeEnum::kModeReplaceCollection; std::set<FieldPath> uniqueKey; NamespaceString outputNs; boost::optional<ChunkVersion> targetCollectionVersion; if (elem.type() == BSONType::String) { outputNs = NamespaceString(expCtx->ns.db().toString() + '.' + elem.str()); uniqueKey.emplace("_id"); } else if (elem.type() == BSONType::Object) { auto spec = DocumentSourceOutSpec::parse(IDLParserErrorContext("$out"), elem.embeddedObject()); mode = spec.getMode(); // Retrieve the target database from the user command, otherwise use the namespace from the // expression context. auto dbName = spec.getTargetDb() ? *spec.getTargetDb() : expCtx->ns.db(); outputNs = NamespaceString(dbName, spec.getTargetCollection()); std::tie(uniqueKey, targetCollectionVersion) = expCtx->inMongos ? resolveUniqueKeyOnMongoS(expCtx, spec, outputNs) : resolveUniqueKeyOnMongoD(expCtx, spec, outputNs); } else { uasserted(16990, str::stream() << "$out only supports a string or object argument, not " << typeName(elem.type())); } return create(std::move(outputNs), expCtx, mode, std::move(uniqueKey), targetCollectionVersion); }
/** * Given a database name and a BSONElement representing an array of roles, populates * "outPrivileges" with the privileges associated with the given roles on the named database. * * Returns Status::OK() on success. */ static Status _getPrivilegesFromRoles(const std::string& dbname, const BSONElement& rolesElement, std::vector<Privilege>* outPrivileges) { static const char privilegesTypeMismatchMessage[] = "Roles must be enumerated in an array of strings."; if (dbname == PrivilegeSet::WILDCARD_RESOURCE) { return Status(ErrorCodes::BadValue, PrivilegeSet::WILDCARD_RESOURCE + " is an invalid database name."); } if (rolesElement.type() != Array) return Status(ErrorCodes::TypeMismatch, privilegesTypeMismatchMessage); for (BSONObjIterator iter(rolesElement.embeddedObject()); iter.more(); iter.next()) { BSONElement roleElement = *iter; if (roleElement.type() != String) return Status(ErrorCodes::TypeMismatch, privilegesTypeMismatchMessage); Status status = _addPrivilegesForSystemRole(dbname, roleElement.str(), outPrivileges); if (!status.isOK()) return status; } return Status::OK(); }
MONGO_FAIL_POINT_BLOCK(setYieldAllLocksWait, customWait) { const BSONObj& data = customWait.getData(); BSONElement customWaitNS = data["namespace"]; if (!customWaitNS || planExecNS.ns() == customWaitNS.str()) { sleepFor(Milliseconds(data["waitForMillis"].numberInt())); } }
BSONObj SyncTail::getMissingDoc(OperationContext* txn, Database* db, const BSONObj& o) { OplogReader missingObjReader; // why are we using OplogReader to run a non-oplog query? const char* ns = o.getStringField("ns"); // capped collections Collection* collection = db->getCollection(ns); if (collection && collection->isCapped()) { log() << "missing doc, but this is okay for a capped collection (" << ns << ")"; return BSONObj(); } const int retryMax = 3; for (int retryCount = 1; retryCount <= retryMax; ++retryCount) { if (retryCount != 1) { // if we are retrying, sleep a bit to let the network possibly recover sleepsecs(retryCount * retryCount); } try { bool ok = missingObjReader.connect(HostAndPort(_hostname)); if (!ok) { warning() << "network problem detected while connecting to the " << "sync source, attempt " << retryCount << " of " << retryMax << endl; continue; // try again } } catch (const SocketException&) { warning() << "network problem detected while connecting to the " << "sync source, attempt " << retryCount << " of " << retryMax << endl; continue; // try again } // get _id from oplog entry to create query to fetch document. const BSONElement opElem = o.getField("op"); const bool isUpdate = !opElem.eoo() && opElem.str() == "u"; const BSONElement idElem = o.getObjectField(isUpdate ? "o2" : "o")["_id"]; if (idElem.eoo()) { severe() << "cannot fetch missing document without _id field: " << o.toString(); fassertFailedNoTrace(28742); } BSONObj query = BSONObjBuilder().append(idElem).obj(); BSONObj missingObj; try { missingObj = missingObjReader.findOne(ns, query); } catch (const SocketException&) { warning() << "network problem detected while fetching a missing document from the " << "sync source, attempt " << retryCount << " of " << retryMax << endl; continue; // try again } catch (DBException& e) { error() << "assertion fetching missing object: " << e.what() << endl; throw; } // success! return missingObj; } // retry count exceeded msgasserted(15916, str::stream() << "Can no longer connect to initial sync source: " << _hostname); }
string DBClientWithCommands::getLastError() { BSONObj info = getLastErrorDetailed(); BSONElement e = info["err"]; if( e.eoo() ) return ""; if( e.type() == Object ) return e.toString(); return e.str(); }
void ExpressionParams::parseHashParams(const BSONObj& infoObj, HashSeed* seedOut, int* versionOut, std::string* fieldOut) { // Default _seed to DEFAULT_HASH_SEED if "seed" is not included in the index spec // or if the value of "seed" is not a number // *** WARNING *** // Choosing non-default seeds will invalidate hashed sharding // Changing the seed default will break existing indexes and sharded collections if (infoObj["seed"].eoo()) { *seedOut = BSONElementHasher::DEFAULT_HASH_SEED; } else { *seedOut = infoObj["seed"].numberInt(); } // In case we have hashed indexes based on other hash functions in the future, we store // a hashVersion number. If hashVersion changes, "makeSingleHashKey" will need to change // accordingly. Defaults to 0 if "hashVersion" is not included in the index spec or if // the value of "hashversion" is not a number *versionOut = infoObj["hashVersion"].numberInt(); // Get the hashfield name BSONElement firstElt = infoObj.getObjectField("key").firstElement(); massert(16765, "error: no hashed index field", firstElt.str().compare(IndexNames::HASHED) == 0); *fieldOut = firstElt.fieldName(); }
string DBClientWithCommands::getLastError() { BSONObj info; runCommand("admin", getlasterrorcmdobj, info); BSONElement e = info["err"]; if( e.eoo() ) return ""; if( e.type() == Object ) return e.toString(); return e.str(); }
MONGO_FAIL_POINT_BLOCK(planExecutorAlwaysDead, customKill) { const BSONObj& data = customKill.getData(); BSONElement customKillNS = data["namespace"]; if (!customKillNS || _ns == customKillNS.str()) { deregisterExec(); kill("hit planExecutorAlwaysDead fail point"); } }
TEST(ExtractBSON, ExtractField) { BSONObj obj = BSON("a" << 1 << "b" << "hello"); BSONElement element; ASSERT_OK(bsonExtractField(obj, "a", &element)); ASSERT_EQUALS(1, element.Int()); ASSERT_OK(bsonExtractField(obj, "b", &element)); ASSERT_EQUALS(std::string("hello"), element.str()); ASSERT_EQUALS(ErrorCodes::NoSuchKey, bsonExtractField(obj, "c", &element)); }
Status V2UserDocumentParser::parseRoleData(const BSONObj& roleObject, User::RoleData* result) { BSONElement roleNameElement; BSONElement roleSourceElement; BSONElement canDelegateElement; BSONElement hasRoleElement; Status status = _extractRoleDocumentElements( roleObject, &roleNameElement, &roleSourceElement, &canDelegateElement, &hasRoleElement); if (!status.isOK()) return status; result->name = RoleName(roleNameElement.str(), roleSourceElement.str()); result->canDelegate = canDelegateElement.eoo() ? false : canDelegateElement.trueValue(); result->hasRole = hasRoleElement.eoo() ? true : hasRoleElement.trueValue(); return status; }
intrusive_ptr<DocumentSource> DocumentSourceUnwind::createFromBson( BSONElement elem, const intrusive_ptr<ExpressionContext>& pExpCtx) { // $unwind accepts either the legacy "{$unwind: '$path'}" syntax, or a nested document with // extra options. string prefixedPathString; bool preserveNullAndEmptyArrays = false; boost::optional<string> indexPath; if (elem.type() == Object) { for (auto&& subElem : elem.Obj()) { if (subElem.fieldNameStringData() == "path") { uassert(28808, str::stream() << "expected a string as the path for $unwind stage, got " << typeName(subElem.type()), subElem.type() == String); prefixedPathString = subElem.str(); } else if (subElem.fieldNameStringData() == "preserveNullAndEmptyArrays") { uassert(28809, str::stream() << "expected a boolean for the preserveNullAndEmptyArrays " "option to $unwind stage, got " << typeName(subElem.type()), subElem.type() == Bool); preserveNullAndEmptyArrays = subElem.Bool(); } else if (subElem.fieldNameStringData() == "includeArrayIndex") { uassert(28810, str::stream() << "expected a non-empty string for the includeArrayIndex " " option to $unwind stage, got " << typeName(subElem.type()), subElem.type() == String && !subElem.String().empty()); indexPath = subElem.String(); uassert(28822, str::stream() << "includeArrayIndex option to $unwind stage should not be " "prefixed with a '$': " << (*indexPath), (*indexPath)[0] != '$'); } else { uasserted(28811, str::stream() << "unrecognized option to $unwind stage: " << subElem.fieldNameStringData()); } } } else if (elem.type() == String) { prefixedPathString = elem.str(); } else { uasserted( 15981, str::stream() << "expected either a string or an object as specification for $unwind stage, got " << typeName(elem.type())); } uassert(28812, "no path specified to $unwind stage", !prefixedPathString.empty()); uassert(28818, str::stream() << "path option to $unwind stage should be prefixed with a '$': " << prefixedPathString, prefixedPathString[0] == '$'); string pathString(Expression::removeFieldPrefix(prefixedPathString)); return DocumentSourceUnwind::create(pExpCtx, pathString, preserveNullAndEmptyArrays, indexPath); }
virtual bool run(const string &db, BSONObj &cmdObj, int options, string &errmsg, BSONObjBuilder &result, bool fromRepl) { BSONElement e = cmdObj.firstElement(); string dest = e.str(); if (dest.empty()) { errmsg = "invalid destination directory: '" + dest + "'"; return false; } Manager manager(cc()); return manager.start(dest, errmsg, result); }
TEST(ExtractBSON, ExtractTypedField) { BSONObj obj = BSON("a" << 1 << "b" << "hello"); BSONElement element; ASSERT_OK(bsonExtractTypedField(obj, "a", NumberInt, &element)); ASSERT_EQUALS(1, element.Int()); ASSERT_OK(bsonExtractTypedField(obj, "b", String, &element)); ASSERT_EQUALS(std::string("hello"), element.str()); ASSERT_EQUALS(ErrorCodes::NoSuchKey, bsonExtractTypedField(obj, "c", String, &element)); ASSERT_EQUALS(ErrorCodes::TypeMismatch, bsonExtractTypedField(obj, "a", String, &element)); ASSERT_EQUALS(ErrorCodes::TypeMismatch, bsonExtractTypedField(obj, "b", NumberDouble, &element)); }
StatusWith<UpdateZoneKeyRangeRequest> UpdateZoneKeyRangeRequest::_parseFromCommand( const BSONObj& cmdObj, bool forMongos) { string rawNS; auto parseNamespaceStatus = bsonExtractStringField( cmdObj, (forMongos ? kMongosUpdateZoneKeyRange : kConfigsvrUpdateZoneKeyRange), &rawNS); if (!parseNamespaceStatus.isOK()) { return parseNamespaceStatus; } NamespaceString ns(rawNS); if (!ns.isValid()) { return {ErrorCodes::InvalidNamespace, str::stream() << rawNS << " is not a valid namespace"}; } auto parseRangeStatus = ChunkRange::fromBSON(cmdObj); if (!parseRangeStatus.isOK()) { return parseRangeStatus.getStatus(); } BSONElement zoneElem; auto parseZoneNameStatus = bsonExtractField(cmdObj, kZoneName, &zoneElem); if (!parseZoneNameStatus.isOK()) { return parseZoneNameStatus; } bool isRemove = false; string zoneName; if (zoneElem.type() == String) { zoneName = zoneElem.str(); } else if (zoneElem.isNull()) { isRemove = true; } else { return {ErrorCodes::TypeMismatch, str::stream() << "\"" << kZoneName << "\" had the wrong type. Expected " << typeName(String) << " or " << typeName(jstNULL) << ", found " << typeName(zoneElem.type())}; } if (isRemove) { return UpdateZoneKeyRangeRequest(std::move(ns), std::move(parseRangeStatus.getValue())); } return UpdateZoneKeyRangeRequest( std::move(ns), std::move(parseRangeStatus.getValue()), std::move(zoneName)); }
/** * Suppress the "err" and "code" field if they are coming from a previous write error and * are not related to write concern. Also removes any write stats information (e.g. "n") * * Also, In some cases, 2.4 GLE w/ wOpTime can give us duplicate "err" and "code" fields b/c of * reporting a previous error. The later field is what we want - dedup and use later field. * * Returns the stripped GLE response. */ BSONObj stripNonWCInfo( const BSONObj& gleResponse ) { BSONObjIterator it( gleResponse ); BSONObjBuilder builder; BSONElement codeField; // eoo BSONElement errField; // eoo while ( it.more() ) { BSONElement el = it.next(); StringData fieldName( el.fieldName() ); if ( fieldName.compare( "err" ) == 0 ) { errField = el; } else if ( fieldName.compare( "code" ) == 0 ) { codeField = el; } else if ( fieldName.compare( "n" ) == 0 || fieldName.compare( "nModified" ) == 0 || fieldName.compare( "upserted" ) == 0 || fieldName.compare( "updatedExisting" ) == 0 ) { // Suppress field } else { builder.append( el ); } } if ( !codeField.eoo() ) { if ( !gleResponse["ok"].trueValue() ) { // The last code will be from the write concern builder.append( codeField ); } else { // The code is from a non-wc error on this connection - suppress it } } if ( !errField.eoo() ) { string err = errField.str(); if ( err == "norepl" || err == "noreplset" || err == "timeout" ) { // Append err if it's from a write concern issue builder.append( errField ); } else { // Suppress non-write concern err as null, but we need to report null err if ok if ( gleResponse["ok"].trueValue() ) builder.appendNull( errField.fieldName() ); } } return builder.obj(); }
Status bsonExtractStringFieldWithDefault(const BSONObj& object, StringData fieldName, StringData defaultValue, std::string* out) { BSONElement element; Status status = bsonExtractTypedFieldImpl(object, fieldName, String, &element, true); if (status == ErrorCodes::NoSuchKey) { *out = defaultValue.toString(); return Status::OK(); } if (status.isOK()) *out = element.str(); return status; }
StatusWith<CountRequest> CountRequest::parseFromBSON(const std::string& dbname, const BSONObj& cmdObj) { BSONElement firstElt = cmdObj.firstElement(); const std::string coll = (firstElt.type() == BSONType::String) ? firstElt.str() : ""; const std::string ns = str::stream() << dbname << "." << coll; if (!nsIsFull(ns)) { return Status(ErrorCodes::BadValue, "invalid collection name"); } // We don't validate that "query" is a nested object due to SERVER-15456. CountRequest request(ns, cmdObj.getObjectField(kQueryField)); // Limit if (cmdObj[kLimitField].isNumber()) { long long limit = cmdObj[kLimitField].numberLong(); // For counts, limit and -limit mean the same thing. if (limit < 0) { limit = -limit; } request.setLimit(limit); } else if (cmdObj[kLimitField].ok()) { return Status(ErrorCodes::BadValue, "limit value is not a valid number"); } // Skip if (cmdObj[kSkipField].isNumber()) { long long skip = cmdObj[kSkipField].numberLong(); if (skip < 0) { return Status(ErrorCodes::BadValue, "skip value is negative in count query"); } request.setSkip(skip); } else if (cmdObj[kSkipField].ok()) { return Status(ErrorCodes::BadValue, "skip value is not a valid number"); } // Hint if (Object == cmdObj[kHintField].type()) { request.setHint(cmdObj[kHintField].Obj()); } else if (String == cmdObj[kHintField].type()) { const std::string hint = cmdObj.getStringField(kHintField); request.setHint(BSON("$hint" << hint)); } return request; }
void calc_meta_graph() { BSONObj o, p, q; BSONObj emptyObj = BSONObj(); if (metaGraph) delete metaGraph; metaGraph = new Graph(); auto_ptr<DBClientCursor> cursor = connection->query("memprof_datasets.stdlib_groups", emptyObj); while( cursor->more() ) { o = cursor->next(); int id = o.getIntField("_id"); set<string> list; auto_ptr<DBClientCursor> rcursor = connection->query("memprof_datasets.stdlib_refs", BSON("_id" << BSON("$in" << o["members"]))); while( rcursor->more() ) { p = rcursor->next(); BSONObjIterator i( p["refs"].embeddedObject() ); while ( i.more() ) { BSONElement e = i.next(); list.insert(e.str()); } } vector<string> list_v(list.begin(), list.end()); set<int> refs; auto_ptr<DBClientCursor> gcursor = connection->query("memprof_datasets.stdlib_groups", BSON("members" << BSON("$in" << list_v))); while( gcursor->more() ) { q = gcursor->next(); int r = q.getIntField("_id"); if (r != id) refs.insert(r); } if (refs.size() > 0) { vector<int> refs_v(refs.begin(), refs.end()); connection->update("memprof_datasets.stdlib_groups", BSON("_id" << id), BSON("$set" << BSON("refs" << refs_v))); (*metaGraph)[id] = refs; } } cout << endl << " created w/ size: " << metaGraph->size(); }
intrusive_ptr<DocumentSource> DocumentSourceUnwind::createFromBson( BSONElement elem, const intrusive_ptr<ExpressionContext> &pExpCtx) { /* The value of $unwind should just be a field path. */ uassert(15981, str::stream() << "the " << unwindName << " field path must be specified as a string", elem.type() == String); string prefixedPathString(elem.str()); string pathString(Expression::removeFieldPrefix(prefixedPathString)); intrusive_ptr<DocumentSourceUnwind> pUnwind(new DocumentSourceUnwind(pExpCtx)); pUnwind->unwindPath(FieldPath(pathString)); return pUnwind; }
static void do_each_child(string node, node_callback_with_data cb, void *data) { BSONObj o; Query q = QUERY("_id" << node << "refs" << BSON("$exists" << true)); auto_ptr<DBClientCursor> cursor = connection->query("memprof_datasets.stdlib_refs", q, 1); while( cursor->more() ) { o = cursor->next(); BSONObjIterator i( o["refs"].embeddedObject() ); while ( i.more() ) { BSONElement e = i.next(); cb(e.str(), data); } break; // only one result } }
// static void QueryYield::yieldAllLocks(OperationContext* txn, RecordFetcher* fetcher, const std::string& planExecNS) { // Things have to happen here in a specific order: // 1) Tell the RecordFetcher to do any setup which needs to happen inside locks // 2) Release lock mgr locks // 3) Go to sleep // 4) Touch the record we're yielding on, if there is one (RecordFetcher::fetch) // 5) Reacquire lock mgr locks Locker* locker = txn->lockState(); Locker::LockSnapshot snapshot; if (fetcher) { fetcher->setup(); } // Nothing was unlocked, just return, yielding is pointless. if (!locker->saveLockStateAndUnlock(&snapshot)) { return; } // Top-level locks are freed, release any potential low-level (storage engine-specific // locks). If we are yielding, we are at a safe place to do so. txn->recoveryUnit()->abandonSnapshot(); MONGO_FAIL_POINT_BLOCK(setYieldAllLocksWait, customWait) { const BSONObj& data = customWait.getData(); BSONElement customWaitNS = data["namespace"]; if (!customWaitNS || planExecNS == customWaitNS.str()) { sleepFor(stdx::chrono::milliseconds(data["waitForMillis"].numberInt())); } } // Track the number of yields in CurOp. CurOp::get(txn)->yielded(); if (fetcher) { fetcher->fetch(); } locker->restoreLockState(snapshot); }
ShardStatus Shard::getStatus() const { BSONObj listDatabases; uassert(28589, str::stream() << "call to listDatabases on " << getConnString().toString() << " failed: " << listDatabases, runCommand("admin", BSON("listDatabases" << 1), listDatabases)); BSONElement totalSizeElem = listDatabases["totalSize"]; uassert(28590, "totalSize field not found in listDatabases", totalSizeElem.isNumber()); BSONObj serverStatus; uassert(28591, str::stream() << "call to serverStatus on " << getConnString().toString() << " failed: " << serverStatus, runCommand("admin", BSON("serverStatus" << 1), serverStatus)); BSONElement versionElement = serverStatus["version"]; uassert(28599, "version field not found in serverStatus", versionElement.type() == String); return ShardStatus(totalSizeElem.numberLong(), versionElement.str()); }
HashAccessMethod::HashAccessMethod(BtreeInMemoryState* btreeState) : BtreeBasedAccessMethod(btreeState) { const IndexDescriptor* descriptor = btreeState->descriptor(); const string HASHED_INDEX_TYPE_IDENTIFIER = "hashed"; //change these if single-field limitation lifted later uassert(16763, "Currently only single field hashed index supported." , 1 == descriptor->getNumFields()); uassert(16764, "Currently hashed indexes cannot guarantee uniqueness. Use a regular index.", !descriptor->unique()); // Default _seed to DEFAULT_HASH_SEED if "seed" is not included in the index spec // or if the value of "seed" is not a number // *** WARNING *** // Choosing non-default seeds will invalidate hashed sharding // Changing the seed default will break existing indexes and sharded collections if ( descriptor->getInfoElement( "seed" ).eoo() ) { _seed = BSONElementHasher::DEFAULT_HASH_SEED; } else { _seed = descriptor->getInfoElement("seed").numberInt(); } //In case we have hashed indexes based on other hash functions in //the future, we store a hashVersion number. If hashVersion changes, // "makeSingleKey" will need to change accordingly. //Defaults to 0 if "hashVersion" is not included in the index spec //or if the value of "hashversion" is not a number _hashVersion = descriptor->getInfoElement("hashVersion").numberInt(); //Get the hashfield name BSONElement firstElt = descriptor->keyPattern().firstElement(); massert(16765, "error: no hashed index field", firstElt.str().compare(HASHED_INDEX_TYPE_IDENTIFIER) == 0); _hashedField = firstElt.fieldName(); }
HashedIndexType::HashedIndexType( const IndexPlugin* plugin , const IndexSpec* spec ) : IndexType( plugin , spec ) , _keyPattern( spec->keyPattern ) { //change these if single-field limitation lifted later uassert( 16241 , "Currently only single field hashed index supported." , _keyPattern.toBSON().nFields() == 1 ); uassert( 16242 , "Currently hashed indexes cannot guarantee uniqueness. Use a regular index." , ! (spec->info).getField("unique").booleanSafe() ); //Default _seed to 0 if "seed" is not included in the index spec //or if the value of "seed" is not a number _seed = (spec->info).getField("seed").numberInt(); //Default _isSparse to false if "sparse" is not included in the index spec //or if the value of "sparse" is not a boolean _isSparse = (spec->info).getField("sparse").booleanSafe(); //In case we have hashed indexes based on other hash functions in //the future, we store a hashVersion number. If hashVersion changes, // "makeSingleKey" will need to change accordingly. //Defaults to 0 if "hashVersion" is not included in the index spec //or if the value of "hashversion" is not a number _hashVersion = (spec->info).getField("hashVersion").numberInt(); //Get the hashfield name BSONElement firstElt = spec->keyPattern.firstElement(); massert( 16243 , "error: no hashed index field" , firstElt.str().compare( HASHED_INDEX_TYPE_IDENTIFIER ) == 0 ); _hashedField = firstElt.fieldName(); // Explicit null valued fields and missing fields are both represented in hashed indexes // using the hash value of the null BSONElement. This is partly for historical reasons // (hash of null was used in the initial release of hashed indexes and changing would alter // the data format). Additionally, in certain places the hashed index code and the index // bound calculation code assume null and missing are indexed identically. BSONObj nullObj = BSON( "" << BSONNULL ); _missingKey = BSON( "" << makeSingleKey( nullObj.firstElement(), _seed, _hashVersion ) ); }