Example #1
0
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));
    }
}
Example #2
0
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()));
}
Example #4
0
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();
}
Example #5
0
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;
}
Example #6
0
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());
}
Example #7
0
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();
}
Example #10
0
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;
    }
}
Example #11
0
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);
}
Example #13
0
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);
}
Example #14
0
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());
}
Example #15
0
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();
    }
}
Example #16
0
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();
}
Example #18
0
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;
    }
}
Example #19
0
// 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());
}
Example #20
0
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", &params.query);
    if (!queryStatus.isOK()) {
        return queryStatus;
    }

    //
    // Parse optional fields.
    //

    int expectedFieldCount = 1;

    Status languageStatus = bsonExtractStringField(queryObj, "$language", &params.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", &params.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", &params.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)};
}
Example #22
0
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);
}
Example #24
0
void SetNode::setValueForNewElement(mutablebson::Element* element) const {
    invariantOK(element->setValueBSONElement(_val));
}