예제 #1
0
void OpObserverShardingImpl::shardObserveTransactionPrepareOrUnpreparedCommit(
    OperationContext* opCtx, const std::vector<repl::ReplOperation>& stmts) {

    for (const auto stmt : stmts) {
        auto const nss = stmt.getNss();

        AutoGetCollection autoColl(opCtx, nss, MODE_IS);
        auto csr = CollectionShardingRuntime::get(opCtx, nss);
        auto csrLock = CollectionShardingRuntime::CSRLock::lock(opCtx, csr);
        auto msm = MigrationSourceManager::get(csr, csrLock);
        if (!msm) {
            continue;
        }

        auto const opType = stmt.getOpType();

        // We pass an empty opTime to observers because retryable write history doesn't care about
        // writes in transactions.
        if (opType == repl::OpTypeEnum::kInsert) {
            msm->getCloner()->onInsertOp(opCtx, stmt.getObject(), {});
        } else if (opType == repl::OpTypeEnum::kUpdate) {
            if (auto updateDoc = stmt.getObject2()) {
                msm->getCloner()->onUpdateOp(
                    opCtx, stmt.getPreImageDocumentKey(), *updateDoc, {}, {});
            }
        } else if (opType == repl::OpTypeEnum::kDelete) {
            if (isMigratingWithCSRLock(csr, csrLock, stmt.getObject())) {
                msm->getCloner()->onDeleteOp(
                    opCtx, getDocumentKey(opCtx, nss, stmt.getObject()), {}, {});
            }
        }
    }
}
예제 #2
0
void OpObserverShardingImpl::shardObserveInsertOp(OperationContext* opCtx,
                                                  const NamespaceString nss,
                                                  const BSONObj& insertedDoc,
                                                  const repl::OpTime& opTime,
                                                  const bool fromMigrate,
                                                  const bool inMultiDocumentTransaction) {
    auto* const csr = (nss == NamespaceString::kSessionTransactionsTableNamespace || fromMigrate)
        ? nullptr
        : CollectionShardingRuntime::get(opCtx, nss);

    if (!csr) {
        return;
    }

    csr->checkShardVersionOrThrow(opCtx);

    if (inMultiDocumentTransaction) {
        assertIntersectingChunkHasNotMoved(opCtx, csr, insertedDoc);
        return;
    }

    auto csrLock = CollectionShardingRuntime::CSRLock::lock(opCtx, csr);
    auto msm = MigrationSourceManager::get(csr, csrLock);
    if (msm) {
        msm->getCloner()->onInsertOp(opCtx, insertedDoc, opTime);
    }
}
bool OpObserverShardingImpl::isMigrating(OperationContext* opCtx,
                                         NamespaceString const& nss,
                                         BSONObj const& docToDelete) {
    auto css = CollectionShardingRuntime::get(opCtx, nss);
    auto msm = MigrationSourceManager::get(css);
    return msm && msm->getCloner()->isDocumentInMigratingChunk(docToDelete);
}
void OpObserverShardingImpl::shardObserveUpdateOp(OperationContext* opCtx,
                                                  const NamespaceString nss,
                                                  const BSONObj& updatedDoc,
                                                  const repl::OpTime& opTime,
                                                  const repl::OpTime& prePostImageOpTime,
                                                  const bool inMultiDocumentTransaction) {
    auto* const css = CollectionShardingRuntime::get(opCtx, nss);
    css->checkShardVersionOrThrow(opCtx);

    auto msm = MigrationSourceManager::get(css);
    if (msm) {
        msm->getCloner()->onUpdateOp(opCtx, updatedDoc, opTime, prePostImageOpTime);
    }

    if (inMultiDocumentTransaction && repl::ReadConcernArgs::get(opCtx).getArgsAtClusterTime()) {
        assertIntersectingChunkHasNotMoved(opCtx, css, updatedDoc);
    }
}
예제 #5
0
void OpObserverShardingImpl::shardObserveDeleteOp(OperationContext* opCtx,
                                                  const NamespaceString nss,
                                                  const BSONObj& documentKey,
                                                  const repl::OpTime& opTime,
                                                  const repl::OpTime& preImageOpTime,
                                                  const bool inMultiDocumentTransaction) {
    auto* const csr = CollectionShardingRuntime::get(opCtx, nss);
    csr->checkShardVersionOrThrow(opCtx);

    if (inMultiDocumentTransaction) {
        assertIntersectingChunkHasNotMoved(opCtx, csr, documentKey);
        return;
    }

    auto csrLock = CollectionShardingRuntime::CSRLock::lock(opCtx, csr);
    auto msm = MigrationSourceManager::get(csr, csrLock);

    if (msm && getIsMigrating(opCtx)) {
        msm->getCloner()->onDeleteOp(opCtx, documentKey, opTime, preImageOpTime);
    }
}
void OpObserverShardingImpl::shardObserveInsertOp(OperationContext* opCtx,
                                                  const NamespaceString nss,
                                                  const BSONObj& insertedDoc,
                                                  const repl::OpTime& opTime,
                                                  const bool fromMigrate,
                                                  const bool inMultiDocumentTransaction) {
    auto* const css = (nss == NamespaceString::kSessionTransactionsTableNamespace || fromMigrate)
        ? nullptr
        : CollectionShardingRuntime::get(opCtx, nss);
    if (css) {
        css->checkShardVersionOrThrow(opCtx);

        auto msm = MigrationSourceManager::get(css);
        if (msm) {
            msm->getCloner()->onInsertOp(opCtx, insertedDoc, opTime);
        }

        if (inMultiDocumentTransaction &&
            repl::ReadConcernArgs::get(opCtx).getArgsAtClusterTime()) {
            assertIntersectingChunkHasNotMoved(opCtx, css, insertedDoc);
        }
    }
}
예제 #7
0
    void BaseClonerTest::testLifeCycle() {
        // GetDiagnosticString
        ASSERT_FALSE(getCloner()->getDiagnosticString().empty());

        // IsActiveAfterStart
        ASSERT_FALSE(getCloner()->isActive());
        ASSERT_OK(getCloner()->start());
        ASSERT_TRUE(getCloner()->isActive());
        tearDown();

        // StartWhenActive
        setUp();
        ASSERT_OK(getCloner()->start());
        ASSERT_TRUE(getCloner()->isActive());
        ASSERT_NOT_OK(getCloner()->start());
        ASSERT_TRUE(getCloner()->isActive());
        tearDown();

        // CancelWithoutStart
        setUp();
        ASSERT_FALSE(getCloner()->isActive());
        getCloner()->cancel();
        ASSERT_FALSE(getCloner()->isActive());
        tearDown();

        // WaitWithoutStart
        setUp();
        ASSERT_FALSE(getCloner()->isActive());
        getCloner()->wait();
        ASSERT_FALSE(getCloner()->isActive());
        tearDown();

        // ShutdownBeforeStart
        setUp();
        getExecutor().shutdown();
        ASSERT_NOT_OK(getCloner()->start());
        ASSERT_FALSE(getCloner()->isActive());
        tearDown();

        // StartAndCancel
        setUp();
        ASSERT_OK(getCloner()->start());
        scheduleNetworkResponse(BSON("ok" << 1));
        getCloner()->cancel();
        finishProcessingNetworkResponse();
        ASSERT_EQUALS(ErrorCodes::CallbackCanceled, getStatus().code());
        ASSERT_FALSE(getCloner()->isActive());
        tearDown();

        // StartButShutdown
        setUp();
        ASSERT_OK(getCloner()->start());
        scheduleNetworkResponse(BSON("ok" << 1));
        getExecutor().shutdown();
        // Network interface should not deliver mock response to callback.
        finishProcessingNetworkResponse();
        ASSERT_EQUALS(ErrorCodes::CallbackCanceled, getStatus().code());
        ASSERT_FALSE(getCloner()->isActive());
    }