Пример #1
0
Status waitForReadConcern(OperationContext* txn, const repl::ReadConcernArgs& readConcernArgs) {
    repl::ReplicationCoordinator* const replCoord = repl::ReplicationCoordinator::get(txn);

    if (readConcernArgs.getLevel() == repl::ReadConcernLevel::kLinearizableReadConcern) {
        if (replCoord->getReplicationMode() != repl::ReplicationCoordinator::modeReplSet) {
            // For master/slave and standalone nodes, Linearizable Read is not supported.
            return {ErrorCodes::NotAReplicaSet,
                    "node needs to be a replica set member to use read concern"};
        }

        // Replica sets running pv0 do not support linearizable read concern until further testing
        // is completed (SERVER-27025).
        if (!replCoord->isV1ElectionProtocol()) {
            return {
                ErrorCodes::IncompatibleElectionProtocol,
                "Replica sets running protocol version 0 do not support readConcern: linearizable"};
        }

        if (!readConcernArgs.getOpTime().isNull()) {
            return {ErrorCodes::FailedToParse,
                    "afterOpTime not compatible with linearizable read concern"};
        }

        if (!replCoord->getMemberState().primary()) {
            return {ErrorCodes::NotMaster,
                    "cannot satisfy linearizable read concern on non-primary node"};
        }
    }

    // Skip waiting for the OpTime when testing snapshot behavior
    if (!testingSnapshotBehaviorInIsolation && !readConcernArgs.isEmpty()) {
        Status status = replCoord->waitUntilOpTimeForRead(txn, readConcernArgs);
        if (!status.isOK()) {
            return status;
        }
    }

    if ((replCoord->getReplicationMode() == repl::ReplicationCoordinator::Mode::modeReplSet ||
         testingSnapshotBehaviorInIsolation) &&
        readConcernArgs.getLevel() == repl::ReadConcernLevel::kMajorityReadConcern) {
        // ReadConcern Majority is not supported in ProtocolVersion 0.
        if (!testingSnapshotBehaviorInIsolation && !replCoord->isV1ElectionProtocol()) {
            return {ErrorCodes::ReadConcernMajorityNotEnabled,
                    str::stream() << "Replica sets running protocol version 0 do not support "
                                     "readConcern: majority"};
        }

        const int debugLevel = serverGlobalParams.clusterRole == ClusterRole::ConfigServer ? 1 : 2;

        LOG(debugLevel) << "Waiting for 'committed' snapshot to be available for reading: "
                        << readConcernArgs;

        Status status = txn->recoveryUnit()->setReadFromMajorityCommittedSnapshot();

        // Wait until a snapshot is available.
        while (status == ErrorCodes::ReadConcernMajorityNotAvailableYet) {
            LOG(debugLevel) << "Snapshot not available yet.";
            replCoord->waitUntilSnapshotCommitted(txn, SnapshotName::min());
            status = txn->recoveryUnit()->setReadFromMajorityCommittedSnapshot();
        }

        if (!status.isOK()) {
            return status;
        }

        LOG(debugLevel) << "Using 'committed' snapshot: " << CurOp::get(txn)->query();
    }

    return Status::OK();
}