Exemple #1
0
    Shard * Shard::split( const BSONObj& m ){
        uassert( "can't split as shard that doesn't have a manager" , _manager );
        
        log(1) << " before split on: "  << m << "\n"
               << "\t self  : " << toString() << endl;

        uassert( "locking namespace on server failed" , lockNamespaceOnServer( getServer() , _ns ) );

        Shard * s = new Shard( _manager );
        s->_ns = _ns;
        s->_server = _server;
        s->_min = m.getOwned();
        s->_max = _max;
        
        s->_markModified();
        _markModified();
        
        _manager->_shards.push_back( s );
        
        _max = m.getOwned(); 
        
        log(1) << " after split:\n" 
               << "\t left : " << toString() << "\n" 
               << "\t right: "<< s->toString() << endl;
        
        
        _manager->save();
        
        return s;
    }
Exemple #2
0
    bool CmdAuthenticate::getUserObj(const string& dbname, const string& user, BSONObj& userObj, string& pwd) {
        if (user == internalSecurity.user) {
            uassert(15890, "key file must be used to log in with internal user",
                    !cmdLine.keyFile.empty());
            pwd = internalSecurity.pwd;
        }
        else {
            string systemUsers = dbname + ".system.users";
            DBConfigPtr config = grid.getDBConfig( systemUsers );
            Shard s = config->getShard( systemUsers );

            static BSONObj userPattern = BSON("user" << 1);

            scoped_ptr<ScopedDbConnection> conn(
                    ScopedDbConnection::getInternalScopedDbConnection( s.getConnString(), 30.0 ) );
            OCCASIONALLY conn->get()->ensureIndex(systemUsers, userPattern, false, "user_1");
            {
                BSONObjBuilder b;
                b << "user" << user;
                BSONObj query = b.done();
                userObj = conn->get()->findOne(systemUsers, query, 0, QueryOption_SlaveOk);
                if( userObj.isEmpty() ) {
                    log() << "auth: couldn't find user " << user << ", " << systemUsers << endl;
                    conn->done(); // return to pool
                    return false;
                }
            }

            pwd = userObj.getStringField("pwd");

            conn->done(); // return to pool
        }
        return true;
    }
    Status DBClientShardResolver::chooseWriteHost( const string& shardName,
                                                   ConnectionString* shardHost ) const {

        // Declare up here for parsing later
        string errMsg;

        // Special-case for config
        if (shardName == "config") {
            *shardHost = ConnectionString::parse( configServer.modelServer(), errMsg );
            dassert( errMsg == "" );
            return Status::OK();
        }

        //
        // First get the information about the shard from the shard cache
        //

        // Internally uses our shard cache, does no reload
        Shard shard = Shard::findIfExists( shardName );
        if ( shard.getName() == "" ) {
            return Status( ErrorCodes::ShardNotFound,
                           string("unknown shard name ") + shardName );
        }
        return findMaster(shard.getConnString().toString(), shardHost);
    }
Exemple #4
0
    ShardManager::ShardManager( DBConfig * config , string ns , ShardKeyPattern pattern ) : _config( config ) , _ns( ns ) , _key( pattern ){
        Shard temp(0);
        
        ScopedDbConnection conn( temp.modelServer() );
        auto_ptr<DBClientCursor> cursor = conn->query( temp.getNS() , BSON( "ns" <<  ns ) );
        while ( cursor->more() ){
            Shard * s = new Shard( this );
            BSONObj d = cursor->next();
            s->unserialize( d );
            _shards.push_back( s );
            s->_id = d["_id"].wrap().getOwned();
        }
        conn.done();
        
        if ( _shards.size() == 0 ){
            Shard * s = new Shard( this );
            s->_ns = ns;
            s->_min = _key.globalMin();
            s->_max = _key.globalMax();
            s->_server = config->getPrimary();
            s->_markModified();
            
            _shards.push_back( s );
            
            log() << "no shards for:" << ns << " so creating first: " << s->toString() << endl;
        }

        _sequenceNumber = ++NextSequenceNumber;
    }
Exemple #5
0
    bool Shard::moveIfShould( Shard * newShard ){
        Shard * toMove = 0;
       
        if ( newShard->countObjects() <= 1 ){
            toMove = newShard;
        }
        else if ( this->countObjects() <= 1 ){
            toMove = this;
        }
        else {
            log(1) << "don't know how to decide if i should move inner shard" << endl;
        }

        if ( ! toMove )
            return false;
        
        string newLocation = grid.pickServerForNewDB();
        if ( newLocation == getServer() ){
            // if this is the best server, then we shouldn't do anything!
            log(1) << "not moving shard: " << toString() << " b/c would move to same place  " << newLocation << " -> " << getServer() << endl;
            return 0;
        }

        log() << "moving shard (auto): " << toMove->toString() << " to: " << newLocation << " #objcets: " << toMove->countObjects() << endl;

        string errmsg;
        massert( (string)"moveAndCommit failed: " + errmsg , 
                 toMove->moveAndCommit( newLocation , errmsg ) );
        
        return true;
    }
Exemple #6
0
    bool Balancer::_checkOIDs() {
        vector<Shard> all;
        Shard::getAllShards( all );

        map<int,Shard> oids;

        for ( vector<Shard>::iterator i=all.begin(); i!=all.end(); ++i ) {
            Shard s = *i;
            BSONObj f = s.runCommand( "admin" , "features" , true );
            if ( f["oidMachine"].isNumber() ) {
                int x = f["oidMachine"].numberInt();
                if ( oids.count(x) == 0 ) {
                    oids[x] = s;
                }
                else {
                    log() << "error: 2 machines have " << x << " as oid machine piece " << s.toString() << " and " << oids[x].toString() << endl;
                    s.runCommand( "admin" , BSON( "features" << 1 << "oidReset" << 1 ) , true );
                    oids[x].runCommand( "admin" , BSON( "features" << 1 << "oidReset" << 1 ) , true );
                    return false;
                }
            }
            else {
                log() << "warning: oidMachine not set on: " << s.toString() << endl;
            }
        }
        return true;
    }
Exemple #7
0
        void _delete( Request& r , DbMessage& d, ShardManager* manager ){

            int flags = d.pullInt();
            bool justOne = flags & 1;
            
            uassert( "bad delete message" , d.moreJSObjs() );
            BSONObj pattern = d.nextJsObj();
            
            if ( manager->hasShardKey( pattern ) ){
                Shard& s = manager->findShard( pattern );
                doWrite( dbDelete , r , s.getServer() );
                return;
            }
            
            if ( ! justOne && ! pattern.hasField( "_id" ) )
                throw UserException( "can only delete with a non-shard key pattern if can delete as many as we find" );
            
            vector<Shard*> shards;
            manager->getShardsForQuery( shards , pattern );
            
            set<string> seen;
            for ( vector<Shard*>::iterator i=shards.begin(); i!=shards.end(); i++){
                Shard * s = *i;
                if ( seen.count( s->getServer() ) )
                    continue;
                seen.insert( s->getServer() );
                doWrite( dbDelete , r , s->getServer() );
            }
        }
    bool setShardVersion(DBClientBase& conn,
                         const string& ns,
                         const string& configServerPrimary,
                         ChunkVersion version,
                         ChunkManager* manager,
                         bool authoritative,
                         BSONObj& result) {

        BSONObjBuilder cmdBuilder;
        cmdBuilder.append("setShardVersion", ns);
        cmdBuilder.append("configdb", configServerPrimary);

        Shard s = Shard::make(conn.getServerAddress());
        cmdBuilder.append("shard", s.getName());
        cmdBuilder.append("shardHost", s.getConnString());

        if (ns.size() > 0) {
            version.addToBSON(cmdBuilder);
        }
        else {
            cmdBuilder.append("init", true);
        }

        if (authoritative) {
            cmdBuilder.appendBool("authoritative", 1);
        }

        BSONObj cmd = cmdBuilder.obj();

        LOG(1) << "    setShardVersion  " << s.getName() << " " << conn.getServerAddress()
               << "  " << ns << "  " << cmd
               << (manager ? string(str::stream() << " " << manager->getSequenceNumber()) : "");

        return conn.runCommand("admin", cmd, result, 0);
    }
Exemple #9
0
 Shard& ShardManager::findShard( const BSONObj & obj ){
     
     for ( vector<Shard*>::iterator i=_shards.begin(); i != _shards.end(); i++ ){
         Shard * s = *i;
         if ( s->contains( obj ) )
             return *s;
     }
     throw UserException( "couldn't find a shard which should be impossible" );
 }
Exemple #10
0
bool Shard::isIdentical(Shard *other)
{
    if (_type != other->_type) return false;
    if (count() != other->count()) return false;
    for (Shard *mine = _first, *yours = other->_first; mine;
        mine = mine->_next, yours = yours->_next)
        if (!mine->isIdentical(yours)) return false;
    return true;
}
Exemple #11
0
    Shard* ShardManager::findShardOnServer( const string& server ) const {

        for ( vector<Shard*>::const_iterator i=_shards.begin(); i!=_shards.end(); i++ ){
            Shard* s = *i;
            if ( s->getServer() == server )
                return s;
        }

        return 0;
    }
Exemple #12
0
Token *Command::arg(int idx)
{
    for(Shard *it = first(); it; it = it->next())
    {
        if(idx--) continue;
        it = it->first();
        if(!it || it->type() != BLOCK) break;
        return (Token*) it->first();
    }
    return 0;
}
Exemple #13
0
 void ShardManager::ensureIndex(){
     set<string> seen;
     
     for ( vector<Shard*>::const_iterator i=_shards.begin(); i!=_shards.end(); i++ ){
         Shard* s = *i;
         if ( seen.count( s->getServer() ) )
             continue;
         seen.insert( s->getServer() );
         s->ensureIndex();
     }
 }
Exemple #14
0
    // Deprecated, will move to the strategy itself
    Shard Request::primaryShard() const {
        assert( _didInit );

        if ( _chunkManager ) {
            if ( _chunkManager->numChunks() > 1 )
                throw UserException( 8060 , "can't call primaryShard on a sharded collection" );
            return _chunkManager->findChunk( _chunkManager->getShardKey().globalMin() )->getShard();
        }
        Shard s = _config->getShard( getns() );
        uassert( 10194 ,  "can't call primaryShard on a sharded collection!" , s.ok() );
        return s;
    }
Exemple #15
0
 void remove( const string& name ) {
     scoped_lock lk( _mutex );
     for ( map<string,Shard>::iterator i = _lookup.begin(); i!=_lookup.end(); ) {
         Shard s = i->second;
         if ( s.getName() == name ) {
             _lookup.erase(i++);
         }
         else {
             ++i;
         }
     }
 }
Exemple #16
0
 void getAllShards( vector<Shard>& all ) {
     scoped_lock lk( _mutex );
     std::set<string> seen;
     for ( map<string,Shard>::iterator i = _lookup.begin(); i!=_lookup.end(); ++i ) {
         Shard s = i->second;
         if ( s.getName() == "config" )
             continue;
         if ( seen.count( s.getName() ) )
             continue;
         seen.insert( s.getName() );
         all.push_back( s );
     }
 }
Exemple #17
0
    Status Strategy::commandOpUnsharded(const std::string& db,
                                        const BSONObj& command,
                                        int options,
                                        const std::string& versionedNS,
                                        CommandResult* cmdResult) {

        // Note that this implementation will not handle targeting retries and fails when the
        // sharding metadata is too stale
        auto status = grid.catalogCache()->getDatabase(db);
        if (!status.isOK()) {
            mongoutils::str::stream ss;
            ss << "Passthrough command failed: " << command.toString()
               << " on ns " << versionedNS << ". Caused by " << causedBy(status.getStatus());
            return Status(ErrorCodes::IllegalOperation, ss);
        }

        shared_ptr<DBConfig> conf = status.getValue();
        if (conf->isSharded(versionedNS)) {
            mongoutils::str::stream ss;
            ss << "Passthrough command failed: " << command.toString()
               << " on ns " << versionedNS << ". Cannot run on sharded namespace.";
            return Status(ErrorCodes::IllegalOperation, ss);
        }

        Shard primaryShard = conf->getPrimary();

        BSONObj shardResult;
        try {
            ShardConnection conn(primaryShard.getConnString(), "");

            // TODO: this can throw a stale config when mongos is not up-to-date -- fix.
            if (!conn->runCommand(db, command, shardResult, options)) {
                conn.done();
                return Status(ErrorCodes::OperationFailed,
                              str::stream() << "Passthrough command failed: " << command
                                            << " on ns " << versionedNS
                                            << "; result: " << shardResult);
            }
            conn.done();
        }
        catch (const DBException& ex) {
            return ex.toStatus();
        }

        // Fill out the command result.
        cmdResult->shardTarget = primaryShard;
        cmdResult->result = shardResult;
        cmdResult->target = primaryShard.getConnString();

        return Status::OK();
    }
    Status ChunkManagerTargeter::targetShardKey(const BSONObj& doc,
                                                ShardEndpoint** endpoint) const {

        invariant(NULL != _manager);
        dassert(_manager->hasShardKey(doc));

        ChunkPtr chunk = _manager->findChunkForDoc(doc);

        Shard shard = chunk->getShard();
        *endpoint = new ShardEndpoint(shard.getName(),
                                      _manager->getVersion(StringData(shard.getName())));

        return Status::OK();
    }
Exemple #19
0
bool Command::hasArg(const String& str)
{
    for(Shard *it = first(); it; it = it->next())
    {
        Block *block = (Block*) it->first();
        if(!block || block->type() != BLOCK) continue;
        for(Shard *arg = block->first(); arg; arg = arg->next())
        {
            // Blocks have only Tokens as children!
            if(((Token*)arg)->token() == str) return true;
        }
    }
    return false;
}
Exemple #20
0
    void ShardManager::save(){
        ServerShardVersion a = getVersion();
        
        for ( vector<Shard*>::const_iterator i=_shards.begin(); i!=_shards.end(); i++ ){
            Shard* s = *i;
            if ( ! s->_modified )
                continue;
            s->save( true );
            _sequenceNumber = ++NextSequenceNumber;
        }
        
        massert( "how did version get smalled" , getVersion() >= a );

        ensureIndex(); // TODO: this is too aggressive - but not really sooo bad
    }
Exemple #21
0
 ShardStatus::ShardStatus( const Shard& shard , const BSONObj& obj , const BSONObj& dblistobj )
     : _shard( shard ), _isDraining(shard.isDraining()) {
     _dataSize = dblistobj.getFieldDotted("totalUncompressedSize").numberLong();
     _hasOpsQueued = obj["writeBacksQueued"].Bool();
     _writeLock = 0; // TODO
     _mongoVersion = obj["version"].String();
 }
Exemple #22
0
    Shard Shard::pick( const Shard& current ) {
        vector<Shard> all;
        staticShardInfo.getAllShards( all );
        if ( all.size() == 0 ) {
            staticShardInfo.reload();
            staticShardInfo.getAllShards( all );
            if ( all.size() == 0 )
                return EMPTY;
        }

        // if current shard was provided, pick a different shard only if it is a better choice
        ShardStatus best = all[0].getStatus();
        if ( current != EMPTY ) {
            best = current.getStatus();
        }

        for ( size_t i=0; i<all.size(); i++ ) {
            ShardStatus t = all[i].getStatus();
            if ( t < best )
                best = t;
        }

        LOG(1) << "best shard for new allocation is " << best << endl;
        return best.shard();
    }
Exemple #23
0
Macro::Macro(const String& n, Shard *macroShard, const String& args)
: Linkable()
{
    _name = n;
    _argTypes = args;
    if (macroShard) 
    {
        // Steal macroShard's children.
        Shard *next;
        for (Shard *it = macroShard->first(); it; it = next)
        {
            next = it->next();
            _shard.add(macroShard->remove(it));
        }
    }
}
Exemple #24
0
    ServerShardVersion ShardManager::getVersion( const string& server ) const{
        // TODO: cache or something?
        
        ServerShardVersion max = 0;

        for ( vector<Shard*>::const_iterator i=_shards.begin(); i!=_shards.end(); i++ ){
            Shard* s = *i;
            if ( s->getServer() != server )
                continue;
            
            if ( s->_lastmod > max )
                max = s->_lastmod;
        }        

        return max;
    }
    ShardConnection::ShardConnection(const Shard& s, const string& ns, ChunkManagerPtr manager)
        : _addr(s.getConnString()),
          _ns(ns),
          _manager( manager ) {

        _init();
    }
Exemple #26
0
 void set( const string& name , const Shard& s , bool setName = true , bool setAddr = true ) {
     scoped_lock lk( _mutex );
     ShardPtr ss( new Shard( s ) );
     if ( setName )
         _lookup[name] = ss;
     if ( setAddr )
         _installHost( s.getConnString() , ss );
 }
Exemple #27
0
    bool Chunk::moveAndCommit(const Shard& to,
                              long long chunkSize /* bytes */,
                              const WriteConcernOptions* writeConcern,
                              bool waitForDelete,
                              int maxTimeMS,
                              BSONObj& res) const {
        uassert( 10167 ,  "can't move shard to its current location!" , getShard() != to );

        log() << "moving chunk ns: " << _manager->getns() << " moving ( " << toString() << ") "
              << _shard.toString() << " -> " << to.toString();

        Shard from = _shard;
        ScopedDbConnection fromconn(from.getConnString());

        BSONObjBuilder builder;
        builder.append("moveChunk", _manager->getns());
        builder.append("from", from.getAddress().toString());
        builder.append("to", to.getAddress().toString());
        // NEEDED FOR 2.0 COMPATIBILITY
        builder.append("fromShard", from.getName());
        builder.append("toShard", to.getName());
        ///////////////////////////////
        builder.append("min", _min);
        builder.append("max", _max);
        builder.append("maxChunkSizeBytes", chunkSize);
        builder.append("shardId", genID());
        builder.append("configdb", configServer.modelServer());

        // For legacy secondary throttle setting.
        bool secondaryThrottle = true;
        if (writeConcern &&
                writeConcern->wNumNodes <= 1 &&
                writeConcern->wMode.empty()) {
            secondaryThrottle = false;
        }

        builder.append("secondaryThrottle", secondaryThrottle);

        if (secondaryThrottle && writeConcern) {
            builder.append("writeConcern", writeConcern->toBSON());
        }

        builder.append("waitForDelete", waitForDelete);
        builder.append(LiteParsedQuery::cmdOptionMaxTimeMS, maxTimeMS);
        builder.append("epoch", _manager->getVersion().epoch());

        bool worked = fromconn->runCommand("admin", builder.done(), res);
        fromconn.done();

        LOG( worked ? 1 : 0 ) << "moveChunk result: " << res;

        // if succeeded, needs to reload to pick up the new location
        // if failed, mongos may be stale
        // reload is excessive here as the failure could be simply because collection metadata is taken
        _manager->reload();

        return worked;
    }
Exemple #28
0
    Slice::Slice(Shard& shard)
        : m_shard(shard),
          m_capacity(shard.GetSliceCapacity()),
          m_refCount(1),
          m_buffer(shard.AllocateSliceBuffer()),
          m_unallocatedCount(shard.GetSliceCapacity()),
          m_commitPendingCount(0),
          m_expiredCount(0)
    {
        Initialize();

        // Perform start up initialization of the DocTable and RowTables after
        // the buffer has been allocated.
        GetDocTable().Initialize(m_buffer);
        for (Rank r = 0; r <= c_maxRankValue; ++r)
        {
            GetRowTable(r).Initialize(m_buffer, m_shard.GetTermTable());
        }
    }
Exemple #29
0
    bool setShardVersion( DBClientBase & conn , const string& ns , ShardChunkVersion version , bool authoritative , BSONObj& result ){

        BSONObjBuilder cmdBuilder;
        cmdBuilder.append( "setShardVersion" , ns.c_str() );
        cmdBuilder.append( "configdb" , configServer.modelServer() );
        cmdBuilder.appendTimestamp( "version" , version );
        cmdBuilder.appendOID( "serverID" , &serverID );
        if ( authoritative )
            cmdBuilder.appendBool( "authoritative" , 1 );

        Shard s = Shard::make( conn.getServerAddress() );
        cmdBuilder.append( "shard" , s.getName() );
        cmdBuilder.append( "shardHost" , s.getConnString() );
        BSONObj cmd = cmdBuilder.obj();
        
        log(1) << "    setShardVersion  " << s.getName() << " " << conn.getServerAddress() << "  " << ns << "  " << cmd << " " << &conn << endl;
        
        return conn.runCommand( "admin" , cmd , result );
    }
Exemple #30
0
/**
 * An exception will be thrown if there is an error.
 */
void RuleSet::generateRule(Command *command)
{
    Rule *rule;
    Shard *it;
    GemTest *terms;

    // Create the rule object.
    if(command->isName("format"))
    {
        rule = new FormatRule(((Block*)command->last()->first())->collect());
    }
    else 
    {
        rule = new LengthRule;
    }
    terms = &rule->terms();

    // Compile the terms (command -> shards -> blocks -> tokens).
    for(it = command->first();
        it && it != command->last(); it = it->next())
    {
        if(!it->first()) continue;
        terms->addBefore(new GemTest((Token*)it->first()->first()));
    }

    if(command->isName("format"))
    {               
        // There must not be format rules with matching terms.
        removeMatching(*terms, Rule::FORMAT);
        add(rule);
    }
    else 
    {
        add(rule);
        Length *len = &((LengthRule*)rule)->length();
        // Set the lengths that were given.
        // Get last argument -> block -> first token.
        len->init((Token*)command->last()->first()->first());
        // Was this all for naught?
        if(len->isClear()) delete remove(rule);
    }
}