Example #1
0
    void ReplSetConfig::MemberCfg::check() const {
        mchk(_id >= 0 && _id <= 255);
        mchk(priority >= 0 && priority <= 1000);
        mchk(votes >= 0 && votes <= 100);
        uassert(13419, "this version of mongod only supports priorities 0 and 1", priority == 0 || priority == 1);
        uassert(13437, "slaveDelay requires priority be zero", slaveDelay == 0 || priority == 0);
        uassert(13438, "bad slaveDelay value", slaveDelay >= 0 && slaveDelay <= 3600 * 24 * 366);
        uassert(13439, "priority must be 0 when hidden=true", priority == 0 || !hidden);
        uassert(13477, "priority must be 0 when buildIndexes=false", buildIndexes || priority == 0);

        if (!initialSync.isEmpty()) {
            static const string legal[] = {"state", "name", "_id","optime"};
            static const set<string> legals(legal, legal + 4);
            assertOnlyHas(initialSync, legals);

            if (initialSync.hasElement("state")) {
                uassert(13525, "initialSync source state must be 1 or 2",
                        initialSync["state"].isNumber() &&
                        (initialSync["state"].Number() == 1 ||
                         initialSync["state"].Number() == 2));
            }
            if (initialSync.hasElement("name")) {
                uassert(13526, "initialSync source name must be a string",
                        initialSync["name"].type() == mongo::String);
            }
            if (initialSync.hasElement("_id")) {
                uassert(13527, "initialSync source _id must be a number",
                        initialSync["_id"].isNumber());
            }
            if (initialSync.hasElement("optime")) {
                uassert(13528, "initialSync source optime must be a timestamp",
                        initialSync["optime"].type() == mongo::Timestamp ||
                        initialSync["optime"].type() == mongo::Date);
            }
        }
    }
Example #2
0
    void ReplSetConfig::from(BSONObj o) {
        static const string legal[] = {"_id","version", "members","settings"};
        static const set<string> legals(legal, legal + 4);
        assertOnlyHas(o, legals);

        md5 = o.md5();
        _id = o["_id"].String();
        if( o["version"].ok() ) {
            version = o["version"].numberInt();
            uassert(13115, "bad " + rsConfigNs + " config: version", version > 0);
        }

        if( o["settings"].ok() ) {
            BSONObj settings = o["settings"].Obj();
            if( settings["heartbeatConnRetries "].ok() )
                ho.heartbeatConnRetries  = settings["heartbeatConnRetries "].numberInt();
            if( settings["heartbeatSleep"].ok() )
                ho.heartbeatSleepMillis = (unsigned) (settings["heartbeatSleep"].Number() * 1000);
            if( settings["heartbeatTimeout"].ok() )
                ho.heartbeatTimeoutMillis = (unsigned) (settings["heartbeatTimeout"].Number() * 1000);
            ho.check();
            try { getLastErrorDefaults = settings["getLastErrorDefaults"].Obj().copy(); }
            catch(...) { }
        }

        set<string> hosts;
        set<int> ords;
        vector<BSONElement> members;
        try {
            members = o["members"].Array();
        }
        catch(...) {
            uasserted(13131, "replSet error parsing (or missing) 'members' field in config object");
        }

        unsigned localhosts = 0;
        for( unsigned i = 0; i < members.size(); i++ ) {
            BSONObj mobj = members[i].Obj();
            MemberCfg m;
            try {
                static const string legal[] = {
                    "_id","votes","priority","host", "hidden","slaveDelay",
                    "arbiterOnly","buildIndexes","tags","initialSync" // deprecated
                };
                static const set<string> legals(legal, legal + 10);
                assertOnlyHas(mobj, legals);

                try {
                    m._id = (int) mobj["_id"].Number();
                }
                catch(...) {
                    /* TODO: use of string exceptions may be problematic for reconfig case! */
                    throw "_id must be numeric";
                }
                string s;
                try {
                    s = mobj["host"].String();
                    m.h = HostAndPort(s);
                }
                catch(...) {
                    throw string("bad or missing host field? ") + mobj.toString();
                }
                if( m.h.isLocalHost() )
                    localhosts++;
                m.arbiterOnly = mobj["arbiterOnly"].trueValue();
                m.slaveDelay = mobj["slaveDelay"].numberInt();
                if( mobj.hasElement("hidden") )
                    m.hidden = mobj["hidden"].trueValue();
                if( mobj.hasElement("buildIndexes") )
                    m.buildIndexes = mobj["buildIndexes"].trueValue();
                if( mobj.hasElement("priority") )
                    m.priority = mobj["priority"].Number();
                if( mobj.hasElement("votes") )
                    m.votes = (unsigned) mobj["votes"].Number();
                if( mobj.hasElement("tags") ) {
                    vector<BSONElement> v = mobj["tags"].Array();
                    for( unsigned i = 0; i < v.size(); i++ )
                        m.tags.insert( v[i].String() );
                }
                m.check();
            }
            catch( const char * p ) {
                log() << "replSet cfg parsing exception for members[" << i << "] " << p << rsLog;
                stringstream ss;
                ss << "replSet members[" << i << "] " << p;
                uassert(13107, ss.str(), false);
            }
            catch(DBException& e) {
                log() << "replSet cfg parsing exception for members[" << i << "] " << e.what() << rsLog;
                stringstream ss;
                ss << "bad config for member[" << i << "] " << e.what();
                uassert(13135, ss.str(), false);
            }
            if( !(ords.count(m._id) == 0 && hosts.count(m.h.toString()) == 0) ) {
                log() << "replSet " << o.toString() << rsLog;
                uassert(13108, "bad replset config -- duplicate hosts in the config object?", false);
            }
            hosts.insert(m.h.toString());
            ords.insert(m._id);
            this->members.push_back(m);
        }
        uassert(13393, "can't use localhost in repl set member names except when using it for all members", localhosts == 0 || localhosts == members.size());
        uassert(13117, "bad " + rsConfigNs + " config", !_id.empty());
    }