Ejemplo n.º 1
0
int ReplicaSetConfig::getVoterPosition(int memberIdx) const {
    int pos = 0;
    int idx = 0;
    for (auto mem = membersBegin(); mem != membersEnd(); ++mem) {
        if (idx == memberIdx) {
            break;
        }

        if (mem->isVoter()) {
            pos++;
        }
        idx++;
    }
    return pos;
}
Ejemplo n.º 2
0
Status MemberConfig::validate() const {
    if (_id < 0 || _id > 255) {
        return Status(ErrorCodes::BadValue,
                      str::stream() << kIdFieldName << " field value of " << _id
                                    << " is out of range.");
    }

    if (_priority < 0 || _priority > 1000) {
        return Status(ErrorCodes::BadValue,
                      str::stream() << kPriorityFieldName << " field value of " << _priority
                                    << " is out of range");
    }
    if (_votes != 0 && _votes != 1) {
        return Status(ErrorCodes::BadValue,
                      str::stream() << kVotesFieldName << " field value is " << _votes
                                    << " but must be 0 or 1");
    }
    if (_arbiterOnly) {
        if (!_tags.empty()) {
            return Status(ErrorCodes::BadValue, "Cannot set tags on arbiters.");
        }
        if (!isVoter()) {
            return Status(ErrorCodes::BadValue, "Arbiter must vote (cannot have 0 votes)");
        }
    }
    if (_slaveDelay < Seconds(0) || _slaveDelay > kMaxSlaveDelay) {
        return Status(ErrorCodes::BadValue,
                      str::stream() << kSlaveDelayFieldName << " field value of "
                                    << durationCount<Seconds>(_slaveDelay)
                                    << " seconds is out of range");
    }
    // Check for additional electable requirements, when priority is non zero
    if (_priority != 0) {
        if (_votes == 0) {
            return Status(ErrorCodes::BadValue, "priority must be 0 when non-voting (votes:0)");
        }
        if (_slaveDelay > Seconds(0)) {
            return Status(ErrorCodes::BadValue, "priority must be 0 when slaveDelay is used");
        }
        if (_hidden) {
            return Status(ErrorCodes::BadValue, "priority must be 0 when hidden=true");
        }
        if (!_buildIndexes) {
            return Status(ErrorCodes::BadValue, "priority must be 0 when buildIndexes=false");
        }
    }
    return Status::OK();
}
Ejemplo n.º 3
0
    VoteRequester::Algorithm::Algorithm(const ReplicaSetConfig& rsConfig,
                                        long long candidateId,
                                        long long term,
                                        OpTime lastOplogEntry) :
            _rsConfig(rsConfig),
            _candidateId(candidateId),
            _term(term),
            _lastOplogEntry(lastOplogEntry) {

        // populate targets with all voting members that aren't this node
        for (auto member = _rsConfig.membersBegin(); member != _rsConfig.membersEnd(); member++) {
            if (member->isVoter() && member->getId() != candidateId) {
                _targets.push_back(member->getHostAndPort());
            }
        }
    }
Ejemplo n.º 4
0
Status MemberConfig::initialize(const BSONObj& mcfg, ReplicaSetTagConfig* tagConfig) {
    Status status = bsonCheckOnlyHasFields(
        "replica set member configuration", mcfg, kLegalMemberConfigFieldNames);
    if (!status.isOK())
        return status;

    //
    // Parse _id field.
    //
    BSONElement idElement = mcfg[kIdFieldName];
    if (idElement.eoo()) {
        return Status(ErrorCodes::NoSuchKey, str::stream() << kIdFieldName << " field is missing");
    }
    if (!idElement.isNumber()) {
        return Status(ErrorCodes::TypeMismatch,
                      str::stream() << kIdFieldName << " field has non-numeric type "
                                    << typeName(idElement.type()));
    }
    _id = idElement.numberInt();

    //
    // Parse h field.
    //
    std::string hostAndPortString;
    status = bsonExtractStringField(mcfg, kHostFieldName, &hostAndPortString);
    if (!status.isOK())
        return status;
    boost::trim(hostAndPortString);
    status = _host.initialize(hostAndPortString);
    if (!status.isOK())
        return status;
    if (!_host.hasPort()) {
        // make port explicit even if default.
        _host = HostAndPort(_host.host(), _host.port());
    }

    //
    // Parse votes field.
    //
    BSONElement votesElement = mcfg[kVotesFieldName];
    if (votesElement.eoo()) {
        _votes = kVotesFieldDefault;
    } else if (votesElement.isNumber()) {
        _votes = votesElement.numberInt();
    } else {
        return Status(ErrorCodes::TypeMismatch,
                      str::stream() << kVotesFieldName << " field value has non-numeric type "
                                    << typeName(votesElement.type()));
    }

    //
    // Parse priority field.
    //
    BSONElement priorityElement = mcfg[kPriorityFieldName];
    if (priorityElement.eoo()) {
        _priority = kPriorityFieldDefault;
    } else if (priorityElement.isNumber()) {
        _priority = priorityElement.numberDouble();
    } else {
        return Status(ErrorCodes::TypeMismatch,
                      str::stream() << kPriorityFieldName << " field has non-numeric type "
                                    << typeName(priorityElement.type()));
    }

    //
    // Parse arbiterOnly field.
    //
    status = bsonExtractBooleanFieldWithDefault(
        mcfg, kArbiterOnlyFieldName, kArbiterOnlyFieldDefault, &_arbiterOnly);
    if (!status.isOK())
        return status;

    //
    // Parse slaveDelay field.
    //
    BSONElement slaveDelayElement = mcfg[kSlaveDelayFieldName];
    if (slaveDelayElement.eoo()) {
        _slaveDelay = kSlaveDelayFieldDefault;
    } else if (slaveDelayElement.isNumber()) {
        _slaveDelay = Seconds(slaveDelayElement.numberInt());
    } else {
        return Status(ErrorCodes::TypeMismatch,
                      str::stream() << kSlaveDelayFieldName << " field value has non-numeric type "
                                    << typeName(slaveDelayElement.type()));
    }

    //
    // Parse hidden field.
    //
    status =
        bsonExtractBooleanFieldWithDefault(mcfg, kHiddenFieldName, kHiddenFieldDefault, &_hidden);
    if (!status.isOK())
        return status;

    //
    // Parse buildIndexes field.
    //
    status = bsonExtractBooleanFieldWithDefault(
        mcfg, kBuildIndexesFieldName, kBuildIndexesFieldDefault, &_buildIndexes);
    if (!status.isOK())
        return status;

    //
    // Parse "tags" field.
    //
    _tags.clear();
    BSONElement tagsElement;
    status = bsonExtractTypedField(mcfg, kTagsFieldName, Object, &tagsElement);
    if (status.isOK()) {
        for (BSONObj::iterator tagIter(tagsElement.Obj()); tagIter.more();) {
            const BSONElement& tag = tagIter.next();
            if (tag.type() != String) {
                return Status(ErrorCodes::TypeMismatch,
                              str::stream() << "tags." << tag.fieldName()
                                            << " field has non-string value of type "
                                            << typeName(tag.type()));
            }
            _tags.push_back(tagConfig->makeTag(tag.fieldNameStringData(), tag.valueStringData()));
        }
    } else if (ErrorCodes::NoSuchKey != status) {
        return status;
    }

    //
    // Add internal tags based on other member properties.
    //

    // Add a voter tag if this non-arbiter member votes; use _id for uniquity.
    const std::string id = str::stream() << _id;
    if (isVoter() && !_arbiterOnly) {
        _tags.push_back(tagConfig->makeTag(kInternalVoterTagName, id));
    }

    // Add an electable tag if this member is electable.
    if (isElectable()) {
        _tags.push_back(tagConfig->makeTag(kInternalElectableTagName, id));
    }

    // Add a tag for generic counting of this node.
    if (!_arbiterOnly) {
        _tags.push_back(tagConfig->makeTag(kInternalAllTagName, id));
    }

    return Status::OK();
}