void AddToSetNode::setValueForNewElement(mutablebson::Element* element) const { BSONObj emptyArray; invariantOK(element->setValueArray(emptyArray)); for (auto&& elem : _elements) { auto toAdd = element->getDocument().makeElement(elem); invariantOK(element->pushBack(toAdd)); } }
std::unique_ptr<PlanExecutor> InternalPlanner::indexScan(OperationContext* txn, const Collection* collection, const IndexDescriptor* descriptor, const BSONObj& startKey, const BSONObj& endKey, bool endKeyInclusive, PlanExecutor::YieldPolicy yieldPolicy, Direction direction, int options) { auto ws = stdx::make_unique<WorkingSet>(); std::unique_ptr<PlanStage> root = _indexScan(txn, ws.get(), collection, descriptor, startKey, endKey, endKeyInclusive, direction, options); auto executor = PlanExecutor::make(txn, std::move(ws), std::move(root), collection, yieldPolicy); invariantOK(executor.getStatus()); return std::move(executor.getValue()); }
void ShardingEgressMetadataHookForMongos::_saveGLEStats(const BSONObj& metadata, StringData hostString) { if (!haveClient()) { // Client will be present only when write commands are used. return; } auto swShardingMetadata = rpc::ShardingMetadata::readFromMetadata(metadata); if (swShardingMetadata.getStatus() == ErrorCodes::NoSuchKey) { return; } else if (!swShardingMetadata.isOK()) { warning() << "Got invalid sharding metadata " << redact(swShardingMetadata.getStatus()) << " metadata object was '" << redact(metadata) << "'"; return; } auto shardConn = ConnectionString::parse(hostString.toString()); // If we got the reply from this host, we expect that its 'hostString' must be valid. if (!shardConn.isOK()) { severe() << "got bad host string in saveGLEStats: " << hostString; } invariantOK(shardConn.getStatus()); auto shardingMetadata = std::move(swShardingMetadata.getValue()); auto& clientInfo = cc(); LOG(4) << "saveGLEStats lastOpTime:" << shardingMetadata.getLastOpTime() << " electionId:" << shardingMetadata.getLastElectionId(); ClusterLastErrorInfo::get(clientInfo) ->addHostOpTime( shardConn.getValue(), HostOpTime(shardingMetadata.getLastOpTime(), shardingMetadata.getLastElectionId())); }
void ClusterCursorManager::checkInCursor(std::unique_ptr<ClusterClientCursor> cursor, const NamespaceString& nss, CursorId cursorId, CursorState cursorState) { stdx::unique_lock<stdx::mutex> lk(_mutex); invariant(cursor); const bool remotesExhausted = cursor->remotesExhausted(); CursorEntry* entry = getEntry_inlock(nss, cursorId); invariant(entry); entry->returnCursor(std::move(cursor)); if (cursorState == CursorState::NotExhausted || entry->getKillPending()) { return; } if (!remotesExhausted) { // The cursor still has open remote cursors that need to be cleaned up. Schedule for // deletion by the reaper thread by setting the kill pending flag. entry->setKillPending(); return; } // The cursor is exhausted, is not already scheduled for deletion, and does not have any // remote cursor state left to clean up. We can delete the cursor right away. auto detachedCursor = detachCursor_inlock(nss, cursorId); invariantOK(detachedCursor.getStatus()); // Deletion of the cursor can happen out of the lock. lk.unlock(); detachedCursor.getValue().reset(); }
static NOINLINE_DECL stdx::cv_status cvWaitUntilWithClockSource(ClockSource* clockSource, stdx::condition_variable& cv, stdx::unique_lock<stdx::mutex>& m, Date_t deadline) { if (deadline <= clockSource->now()) { return stdx::cv_status::timeout; } struct AlarmInfo { stdx::mutex controlMutex; stdx::mutex* waitMutex; stdx::condition_variable* waitCV; stdx::cv_status cvWaitResult = stdx::cv_status::no_timeout; }; auto alarmInfo = std::make_shared<AlarmInfo>(); alarmInfo->waitCV = &cv; alarmInfo->waitMutex = m.mutex(); invariantOK(clockSource->setAlarm(deadline, [alarmInfo] { stdx::lock_guard<stdx::mutex> controlLk(alarmInfo->controlMutex); alarmInfo->cvWaitResult = stdx::cv_status::timeout; if (!alarmInfo->waitMutex) { return; } stdx::lock_guard<stdx::mutex> waitLk(*alarmInfo->waitMutex); alarmInfo->waitCV->notify_all(); })); cv.wait(m); m.unlock(); stdx::lock_guard<stdx::mutex> controlLk(alarmInfo->controlMutex); m.lock(); alarmInfo->waitMutex = nullptr; alarmInfo->waitCV = nullptr; return alarmInfo->cvWaitResult; }
std::unique_ptr<PlanExecutor> InternalPlanner::deleteWithIndexScan( OperationContext* txn, Collection* collection, const DeleteStageParams& params, const IndexDescriptor* descriptor, const BSONObj& startKey, const BSONObj& endKey, bool endKeyInclusive, PlanExecutor::YieldPolicy yieldPolicy, Direction direction) { auto ws = stdx::make_unique<WorkingSet>(); std::unique_ptr<PlanStage> root = _indexScan(txn, ws.get(), collection, descriptor, startKey, endKey, endKeyInclusive, direction, InternalPlanner::IXSCAN_FETCH); root = stdx::make_unique<DeleteStage>(txn, params, ws.get(), collection, root.release()); auto executor = PlanExecutor::make(txn, std::move(ws), std::move(root), collection, yieldPolicy); invariantOK(executor.getStatus()); return std::move(executor.getValue()); }
ChunkVersion forceShardFilteringMetadataRefresh(OperationContext* opCtx, const NamespaceString& nss) { invariant(!opCtx->lockState()->isLocked()); invariant(!opCtx->getClient()->isInDirectClient()); auto const shardingState = ShardingState::get(opCtx); invariantOK(shardingState->canAcceptShardedCommands()); const auto routingInfo = uassertStatusOK( Grid::get(opCtx)->catalogCache()->getCollectionRoutingInfoWithRefresh(opCtx, nss)); const auto cm = routingInfo.cm(); if (!cm) { // No chunk manager, so unsharded. // Exclusive collection lock needed since we're now changing the metadata AutoGetCollection autoColl(opCtx, nss, MODE_IX, MODE_X); auto css = CollectionShardingState::get(opCtx, nss); css->refreshMetadata(opCtx, nullptr); return ChunkVersion::UNSHARDED(); } { AutoGetCollection autoColl(opCtx, nss, MODE_IS); auto css = CollectionShardingState::get(opCtx, nss); // We already have newer version if (css->getMetadata() && css->getMetadata()->getCollVersion().epoch() == cm->getVersion().epoch() && css->getMetadata()->getCollVersion() >= cm->getVersion()) { LOG(1) << "Skipping refresh of metadata for " << nss << " " << css->getMetadata()->getCollVersion() << " with an older " << cm->getVersion(); return css->getMetadata()->getShardVersion(); } } // Exclusive collection lock needed since we're now changing the metadata AutoGetCollection autoColl(opCtx, nss, MODE_IX, MODE_X); auto css = CollectionShardingState::get(opCtx, nss); // We already have newer version if (css->getMetadata() && css->getMetadata()->getCollVersion().epoch() == cm->getVersion().epoch() && css->getMetadata()->getCollVersion() >= cm->getVersion()) { LOG(1) << "Skipping refresh of metadata for " << nss << " " << css->getMetadata()->getCollVersion() << " with an older " << cm->getVersion(); return css->getMetadata()->getShardVersion(); } std::unique_ptr<CollectionMetadata> newCollectionMetadata = stdx::make_unique<CollectionMetadata>(cm, shardingState->getShardName()); css->refreshMetadata(opCtx, std::move(newCollectionMetadata)); return css->getMetadata()->getShardVersion(); }
std::unique_ptr<MatchExpression> InternalSchemaObjectMatchExpression::shallowClone() const { auto clone = stdx::make_unique<InternalSchemaObjectMatchExpression>(); invariantOK(clone->init(_sub->shallowClone(), path())); if (getTag()) { clone->setTag(getTag()->clone()); } return std::move(clone); }
BSONObj BalanceChunkRequest::serializeToRebalanceCommandForConfig(const ChunkType& chunk) { invariantOK(chunk.validate()); BSONObjBuilder cmdBuilder; cmdBuilder.append(kConfigSvrMoveChunk, 1); cmdBuilder.appendElements(chunk.toBSON()); return cmdBuilder.obj(); }
ModifierNode::ModifyResult SetNode::updateExistingElement( mutablebson::Element* element, std::shared_ptr<FieldRef> elementPath) const { // If 'element' is deserialized, then element.getValue() will be EOO, which will never equal // _val. if (element->getValue().binaryEqualValues(_val)) { return ModifyResult::kNoOp; } else { invariantOK(element->setValueBSONElement(_val)); return ModifyResult::kNormalUpdate; } }
std::unique_ptr<MatchExpression> TextMatchExpression::shallowClone() const { auto expr = stdx::make_unique<TextMatchExpression>(); // We initialize _ftsQuery here directly rather than calling init(), to avoid needing to examine // the index catalog. expr->_ftsQuery = _ftsQuery; invariantOK(expr->setPath("_fts")); if (getTag()) { expr->setTag(getTag()->clone()); } return std::move(expr); }
void ClusterCursorManager::PinnedCursor::returnAndKillCursor() { invariant(_cursor); // Inform the manager that the cursor should be killed. invariantOK(_manager->killCursor(_nss, _cursorId)); // Return the cursor to the manager. It will be deleted on the next call to // ClusterCursorManager::reapZombieCursors(). // // The value of the argument to returnCursor() doesn't matter; the cursor will be kept as a // zombie. returnCursor(CursorState::NotExhausted); }
Status ActionSet::parseActionSetFromString(const std::string& actionsString, ActionSet* result) { std::vector<std::string> actionsList; splitStringDelim(actionsString, &actionsList, ','); std::vector<std::string> unrecognizedActions; Status status = parseActionSetFromStringVector(actionsList, result, &unrecognizedActions); invariantOK(status); if (unrecognizedActions.empty()) { return Status::OK(); } std::string unrecognizedActionsString; joinStringDelim(unrecognizedActions, &unrecognizedActionsString, ','); return Status( ErrorCodes::FailedToParse, str::stream() << "Unrecognized action privilege strings: " << unrecognizedActionsString); }
std::unique_ptr<PlanExecutor> InternalPlanner::deleteWithCollectionScan( OperationContext* txn, Collection* collection, const DeleteStageParams& params, PlanExecutor::YieldPolicy yieldPolicy, Direction direction, const RecordId& startLoc) { auto ws = stdx::make_unique<WorkingSet>(); auto root = _collectionScan(txn, ws.get(), collection, direction, startLoc); root = stdx::make_unique<DeleteStage>(txn, params, ws.get(), collection, root.release()); auto executor = PlanExecutor::make(txn, std::move(ws), std::move(root), collection, yieldPolicy); invariantOK(executor.getStatus()); return std::move(executor.getValue()); }
Status onShardVersionMismatch(OperationContext* opCtx, const NamespaceString& nss, ChunkVersion shardVersionReceived) noexcept { invariant(!opCtx->lockState()->isLocked()); invariant(!opCtx->getClient()->isInDirectClient()); auto const shardingState = ShardingState::get(opCtx); invariantOK(shardingState->canAcceptShardedCommands()); LOG(2) << "Metadata refresh requested for " << nss.ns() << " at shard version " << shardVersionReceived; ShardingStatistics::get(opCtx).countStaleConfigErrors.addAndFetch(1); // Ensure any ongoing migrations have completed auto& oss = OperationShardingState::get(opCtx); oss.waitForMigrationCriticalSectionSignal(opCtx); const auto currentShardVersion = [&] { AutoGetCollection autoColl(opCtx, nss, MODE_IS); const auto currentMetadata = CollectionShardingState::get(opCtx, nss)->getMetadata(); if (currentMetadata) { return currentMetadata->getShardVersion(); } return ChunkVersion::UNSHARDED(); }(); if (currentShardVersion.epoch() == shardVersionReceived.epoch() && currentShardVersion.majorVersion() >= shardVersionReceived.majorVersion()) { // Don't need to remotely reload if we're in the same epoch and the requested version is // smaller than the one we know about. This means that the remote side is behind. return Status::OK(); } try { forceShardFilteringMetadataRefresh(opCtx, nss); return Status::OK(); } catch (const DBException& ex) { log() << "Failed to refresh metadata for collection" << nss << causedBy(redact(ex)); return ex.toStatus(); } }
Status ActionSet::parseActionSetFromStringVector(const std::vector<std::string>& actionsVector, ActionSet* result, std::vector<std::string>* unrecognizedActions) { result->removeAllActions(); for (size_t i = 0; i < actionsVector.size(); i++) { ActionType action; Status status = ActionType::parseActionFromString(actionsVector[i], &action); if (status == ErrorCodes::FailedToParse) { unrecognizedActions->push_back(actionsVector[i]); } else { invariantOK(status); if (action == ActionType::anyAction) { result->addAllActions(); return Status::OK(); } result->addAction(action); } } return Status::OK(); }
BSONObj BalanceChunkRequest::serializeToMoveCommandForConfig( const ChunkType& chunk, const ShardId& newShardId, int64_t maxChunkSizeBytes, const MigrationSecondaryThrottleOptions& secondaryThrottle, bool waitForDelete) { invariantOK(chunk.validate()); BSONObjBuilder cmdBuilder; cmdBuilder.append(kConfigSvrMoveChunk, 1); cmdBuilder.appendElements(chunk.toBSON()); cmdBuilder.append(kToShardId, newShardId); cmdBuilder.append(kMaxChunkSizeBytes, static_cast<long long>(maxChunkSizeBytes)); { BSONObjBuilder secondaryThrottleBuilder(cmdBuilder.subobjStart(kSecondaryThrottle)); secondaryThrottle.append(&secondaryThrottleBuilder); secondaryThrottleBuilder.doneFast(); } cmdBuilder.append(kWaitForDelete, waitForDelete); return cmdBuilder.obj(); }
ModifierNode::ModifyResult BitNode::updateExistingElement( mutablebson::Element* element, std::shared_ptr<FieldRef> elementPath) const { if (!element->isIntegral()) { mutablebson::Element idElem = mutablebson::findFirstChildNamed(element->getDocument().root(), "_id"); uasserted(ErrorCodes::BadValue, str::stream() << "Cannot apply $bit to a value of non-integral type." << idElem.toString() << " has the field " << element->getFieldName() << " of non-integer type " << typeName(element->getType())); } SafeNum value = applyOpList(element->getValueSafeNum()); if (!value.isIdentical(element->getValueSafeNum())) { invariantOK(element->setValueSafeNum(value)); return ModifyResult::kNormalUpdate; } else { return ModifyResult::kNoOp; } }
// Uses the collator factory to convert the BSON representation of a collator to a // CollatorInterface. Returns null if the BSONObj is empty. We expect the stored collation to be // valid, since it gets validated on collection create. std::unique_ptr<CollatorInterface> parseCollation(OperationContext* opCtx, const NamespaceString& nss, BSONObj collationSpec) { if (collationSpec.isEmpty()) { return {nullptr}; } auto collator = CollatorFactoryInterface::get(opCtx->getServiceContext())->makeFromBSON(collationSpec); // If the collection's default collator has a version not currently supported by our ICU // integration, shut down the server. Errors other than IncompatibleCollationVersion should not // be possible, so these are an invariant rather than fassert. if (collator == ErrorCodes::IncompatibleCollationVersion) { log() << "Collection " << nss << " has a default collation which is incompatible with this version: " << collationSpec; fassertFailedNoTrace(40144); } invariantOK(collator.getStatus()); return std::move(collator.getValue()); }
ModifierNode::ModifyResult AddToSetNode::updateExistingElement( mutablebson::Element* element, std::shared_ptr<FieldRef> elementPath) const { uassert(ErrorCodes::BadValue, str::stream() << "Cannot apply $addToSet to non-array field. Field named '" << element->getFieldName() << "' has non-array type " << typeName(element->getType()), element->getType() == BSONType::Array); // Find the set of elements that do not already exist in the array 'element'. std::vector<BSONElement> elementsToAdd; for (auto&& elem : _elements) { auto shouldAdd = true; for (auto existingElem = element->leftChild(); existingElem.ok(); existingElem = existingElem.rightSibling()) { if (existingElem.compareWithBSONElement(elem, _collator, false) == 0) { shouldAdd = false; break; } } if (shouldAdd) { elementsToAdd.push_back(elem); } } if (elementsToAdd.empty()) { return ModifyResult::kNoOp; } for (auto&& elem : elementsToAdd) { auto toAdd = element->getDocument().makeElement(elem); invariantOK(element->pushBack(toAdd)); } return ModifyResult::kNormalUpdate; }
StatusWith<TextMatchExpressionBase::TextParams> ExtensionsCallback::extractTextMatchExpressionParams(BSONElement text) { TextMatchExpressionBase::TextParams params; if (text.type() != Object) { return {ErrorCodes::BadValue, "$text expects an object"}; } BSONObj queryObj = text.Obj(); // // Parse required fields. // Status queryStatus = bsonExtractStringField(queryObj, "$search", ¶ms.query); if (!queryStatus.isOK()) { return queryStatus; } // // Parse optional fields. // int expectedFieldCount = 1; Status languageStatus = bsonExtractStringField(queryObj, "$language", ¶ms.language); if (languageStatus == ErrorCodes::TypeMismatch) { return languageStatus; } else if (languageStatus == ErrorCodes::NoSuchKey) { params.language = std::string(); } else { invariantOK(languageStatus); expectedFieldCount++; } Status caseSensitiveStatus = bsonExtractBooleanField(queryObj, "$caseSensitive", ¶ms.caseSensitive); if (caseSensitiveStatus == ErrorCodes::TypeMismatch) { return caseSensitiveStatus; } else if (caseSensitiveStatus == ErrorCodes::NoSuchKey) { params.caseSensitive = TextMatchExpressionBase::kCaseSensitiveDefault; } else { invariantOK(caseSensitiveStatus); expectedFieldCount++; } Status diacriticSensitiveStatus = bsonExtractBooleanField(queryObj, "$diacriticSensitive", ¶ms.diacriticSensitive); if (diacriticSensitiveStatus == ErrorCodes::TypeMismatch) { return diacriticSensitiveStatus; } else if (diacriticSensitiveStatus == ErrorCodes::NoSuchKey) { params.diacriticSensitive = TextMatchExpressionBase::kDiacriticSensitiveDefault; } else { invariantOK(diacriticSensitiveStatus); expectedFieldCount++; } if (queryObj.nFields() != expectedFieldCount) { return {ErrorCodes::BadValue, "extra fields in $text"}; } return {std::move(params)}; }
void BitNode::setValueForNewElement(mutablebson::Element* element) const { SafeNum value = applyOpList(SafeNum(static_cast<int32_t>(0))); invariantOK(element->setValueSafeNum(value)); }
std::unique_ptr<MatchExpression> InternalSchemaMatchArrayIndexMatchExpression::shallowClone() const { auto clone = stdx::make_unique<InternalSchemaMatchArrayIndexMatchExpression>(); invariantOK(clone->init(path(), _index, _expression->shallowClone())); return std::move(clone); }
void SetNode::setValueForNewElement(mutablebson::Element* element) const { invariantOK(element->setValueBSONElement(_val)); }