Example #1
0
    DBClientBase* getVersionable( DBClientBase* conn ){

        switch ( conn->type() ) {
        case ConnectionString::INVALID:
           massert( 15904, str::stream() << "cannot set version on invalid connection " << conn->toString(), false );
           return NULL;
        case ConnectionString::MASTER:
           return conn;
        case ConnectionString::PAIR:
           massert( 15905, str::stream() << "cannot set version or shard on pair connection " << conn->toString(), false );
           return NULL;
        case ConnectionString::SYNC:
           massert( 15906, str::stream() << "cannot set version or shard on sync connection " << conn->toString(), false );
           return NULL;
        case ConnectionString::CUSTOM:
           massert( 16334, str::stream() << "cannot set version or shard on custom connection " << conn->toString(), false );
           return NULL;
        case ConnectionString::SET:
           DBClientReplicaSet* set = (DBClientReplicaSet*) conn;
           return &( set->masterConn() );
        }

        verify( false );
        return NULL;
    }
Example #2
0
 DBClientBase& Tool::conn( bool slaveIfPaired ) {
     if ( slaveIfPaired && _conn->type() == ConnectionString::SET ) {
         if (!_slaveConn) {
             DBClientReplicaSet* rs = static_cast<DBClientReplicaSet*>(_conn);
             _slaveConn = &rs->slaveConn();
         }
         return *_slaveConn;
     }
     return *_conn;
 }
Example #3
0
/*
 * ok,err = replicaset:connect()
 */
static int replicaset_connect(lua_State *L) {
    DBClientReplicaSet *replicaset = userdata_to_replicaset(L, 1);

    try {
        replicaset->connect();
    } catch (std::exception &e) {
        lua_pushnil(L);
        lua_pushfstring(L, LUAMONGO_ERR_CONNECT_FAILED, LUAMONGO_REPLICASET, e.what());
        return 2;
    }

    lua_pushboolean(L, 1);
    return 1;
}
Example #4
0
int main( int argc , const char ** argv ) {
    
    unsigned nThreads = 1;
    bool print = false;

    for ( int i=1; i<argc; i++ ) {
        if ( mongoutils::str::equals( "--threads" , argv[i] ) ) {
            nThreads = atoi( argv[++i] );
        }
        else if ( mongoutils::str::equals( "--print" , argv[1] ) ) {
            print = true;
        }
        else {
            cerr << "unknown option: " << argv[i] << endl;
            return 1;
        }
            
    }

    string errmsg;
    ConnectionString cs = ConnectionString::parse( "foo/127.0.0.1" , errmsg );
    if ( ! cs.isValid() ) {
        cout << "error parsing url: " << errmsg << endl;
        return 1;
    }

    DBClientReplicaSet * conn = (DBClientReplicaSet*)cs.connect( errmsg );
    if ( ! conn ) {
        cout << "error connecting: " << errmsg << endl;
        return 2;
    }

    string collName = "test.rs1";

    conn->dropCollection( collName );
    
    vector<boost::shared_ptr<boost::thread> > threads;
    for ( unsigned i=0; i<nThreads; i++ ) {
        string errmsg;
        threads.push_back( boost::shared_ptr<boost::thread>( new boost::thread( boost::bind( workerThread , collName , print , (DBClientReplicaSet*)cs.connect(errmsg) ) ) ) );
    }
    
    for ( unsigned i=0; i<threads.size(); i++ ) {
        threads[i]->join();
    }

}
Example #5
0
    DBClientBase* ConnectionString::connect( string& errmsg, double socketTimeout ) const {
        switch ( _type ) {
        case MASTER: {
            DBClientConnection * c = new DBClientConnection(true);
            c->setSoTimeout( socketTimeout );
            log(1) << "creating new connection to:" << _servers[0] << endl;
            if ( ! c->connect( _servers[0] , errmsg ) ) {
                delete c;
                return 0;
            }
            log(1) << "connected connection!" << endl;
            return c;
        }

        case PAIR:
        case SET: {
            DBClientReplicaSet * set = new DBClientReplicaSet( _setName , _servers , socketTimeout );
            if( ! set->connect() ) {
                delete set;
                errmsg = "connect failed to set ";
                errmsg += toString();
                return 0;
            }
            return set;
        }

        case SYNC: {
            // TODO , don't copy
            list<HostAndPort> l;
            for ( unsigned i=0; i<_servers.size(); i++ )
                l.push_back( _servers[i] );
            SyncClusterConnection* c = new SyncClusterConnection( l, socketTimeout );
            return c;
        }

        case INVALID:
            throw UserException( 13421 , "trying to connect to invalid ConnectionString" );
            break;
        }

        assert( 0 );
        return 0;
    }
Example #6
0
    void ShardingConnectionHook::onCreate( DBClientBase * conn ) {
        if( !noauth ) {
            bool result;
            string err;
            LOG(2) << "calling onCreate auth for " << conn->toString() << endl;

            if ( conn->type() == ConnectionString::SET && !authOnPrimaryOnly ) {
                DBClientReplicaSet* setConn = dynamic_cast<DBClientReplicaSet*>(conn);
                verify(setConn);
                result = setConn->authAny( "local",
                                           internalSecurity.user,
                                           internalSecurity.pwd,
                                           err,
                                           false );
            }
            else {
                result = conn->auth( "local",
                                     internalSecurity.user,
                                     internalSecurity.pwd,
                                     err,
                                     false );
            }

            uassert( 15847, str::stream() << "can't authenticate to server "
                                          << conn->getServerAddress() << causedBy( err ), result );
        }

        if ( _shardedConnections && versionManager.isVersionableCB( conn ) ) {

            // We must initialize sharding on all connections, so that we get exceptions if sharding is enabled on
            // the collection.
            BSONObj result;
            bool ok = versionManager.initShardVersionCB( conn, result );

            // assert that we actually successfully setup sharding
            uassert( 15907, str::stream() << "could not initialize sharding on connection " << (*conn).toString() <<
                        ( result["errmsg"].type() == String ? causedBy( result["errmsg"].String() ) :
                                                              causedBy( (string)"unknown failure : " + result.toString() ) ), ok );

        }
    }
Example #7
0
    /**
     * @return true if had to do something
     */
    bool checkShardVersion( DBClientBase& conn_in , const string& ns , bool authoritative , int tryNumber ) {
        // TODO: cache, optimize, etc...

        WriteBackListener::init( conn_in );

        DBConfigPtr conf = grid.getDBConfig( ns );
        if ( ! conf )
            return false;

        DBClientBase* conn = 0;

        switch ( conn_in.type() ) {
        case ConnectionString::INVALID:
            assert(0);
            break;
        case ConnectionString::MASTER:
            // great
            conn = &conn_in;
            break;
        case ConnectionString::PAIR:
            assert( ! "pair not support for sharding" );
            break;
        case ConnectionString::SYNC:
            // TODO: we should check later that we aren't actually sharded on this
            conn = &conn_in;
            break;
        case ConnectionString::SET:
            DBClientReplicaSet* set = (DBClientReplicaSet*)&conn_in;
            conn = &(set->masterConn());
            break;
        }

        assert(conn);

        unsigned long long officialSequenceNumber = 0;

        ChunkManagerPtr manager;
        const bool isSharded = conf->isSharded( ns );
        if ( isSharded ) {
            manager = conf->getChunkManagerIfExists( ns , authoritative );
            // It's possible the chunk manager was reset since we checked whether sharded was true,
            // so must check this here.
            if( manager ) officialSequenceNumber = manager->getSequenceNumber();
        }

        // has the ChunkManager been reloaded since the last time we updated the connection-level version?
        // (ie., last time we issued the setShardVersions below)
        unsigned long long sequenceNumber = connectionShardStatus.getSequence(conn,ns);
        if ( sequenceNumber == officialSequenceNumber ) {
            return false;
        }


        ShardChunkVersion version = 0;
        if ( isSharded && manager ) {
            version = manager->getVersion( Shard::make( conn->getServerAddress() ) );
        }

        LOG(2) << " have to set shard version for conn: " << conn << " ns:" << ns
               << " my last seq: " << sequenceNumber << "  current: " << officialSequenceNumber
               << " version: " << version << " manager: " << manager.get()
               << endl;

        BSONObj result;
        if ( setShardVersion( *conn , ns , version , authoritative , result ) ) {
            // success!
            LOG(1) << "      setShardVersion success: " << result << endl;
            connectionShardStatus.setSequence( conn , ns , officialSequenceNumber );
            return true;
        }

        LOG(1) << "       setShardVersion failed!\n" << result << endl;

        if ( result["need_authoritative"].trueValue() )
            massert( 10428 ,  "need_authoritative set but in authoritative mode already" , ! authoritative );

        if ( ! authoritative ) {
            checkShardVersion( *conn , ns , 1 , tryNumber + 1 );
            return true;
        }
        
        if ( result["reloadConfig"].trueValue() ) {
            if( result["version"].timestampTime() == 0 ){
                // reload db
                conf->reload();
            }
            else {
                // reload config
                conf->getChunkManager( ns , true );
            }
        }

        const int maxNumTries = 7;
        if ( tryNumber < maxNumTries ) {
            LOG( tryNumber < ( maxNumTries / 2 ) ? 1 : 0 ) 
                << "going to retry checkShardVersion host: " << conn->getServerAddress() << " " << result << endl;
            sleepmillis( 10 * tryNumber );
            checkShardVersion( *conn , ns , true , tryNumber + 1 );
            return true;
        }
        
        string errmsg = str::stream() << "setShardVersion failed host: " << conn->getServerAddress() << " " << result;
        log() << "     " << errmsg << endl;
        massert( 10429 , errmsg , 0 );
        return true;
    }
    DBClientBase* ConnectionString::connect( std::string& errmsg, double socketTimeout ) const {

        switch ( _type ) {
        case MASTER: {
            DBClientConnection * c = new DBClientConnection(true);
            c->setSoTimeout( socketTimeout );
            LOG(1) << "creating new connection to:" << _servers[0];
            if ( ! c->connect( _servers[0] , errmsg ) ) {
                delete c;
                return 0;
            }
            LOG(1) << "connected connection!";
            return c;
        }

        case PAIR:
        case SET: {
            DBClientReplicaSet * set = new DBClientReplicaSet( _setName , _servers , socketTimeout );
            if( ! set->connect() ) {
                delete set;
                errmsg = "connect failed to replica set ";
                errmsg += toString();
                return 0;
            }
            return set;
        }

        case SYNC: {
            // TODO , don't copy
            std::list<HostAndPort> l;
            for ( unsigned i=0; i<_servers.size(); i++ )
                l.push_back( _servers[i] );
            SyncClusterConnection* c = new SyncClusterConnection( l, socketTimeout );
            return c;
        }

        case CUSTOM: {

            // Lock in case other things are modifying this at the same time
            boost::lock_guard<boost::mutex> lk( _connectHookMutex );

            // Allow the replacement of connections with other connections - useful for testing.

            uassert( 16335, "custom connection to " + this->toString() +
                        " specified with no connection hook", _connectHook );

            // Double-checked lock, since this will never be active during normal operation
            DBClientBase* replacementConn = _connectHook->connect( *this, errmsg, socketTimeout );

            log() << "replacing connection to " << this->toString() << " with "
                  << ( replacementConn ? replacementConn->getServerAddress() : "(empty)" );

            return replacementConn;
        }

        case INVALID:
            throw UserException( 13421 , "trying to connect to invalid ConnectionString" );
            break;
        }

        verify( 0 );
        return 0;
    }
Example #9
0
/*
 * __tostring
 */
static int replicaset_tostring(lua_State *L) {
    DBClientReplicaSet *replicaset = userdata_to_replicaset(L, 1);
    lua_pushfstring(L, "%s: %s", LUAMONGO_REPLICASET, replicaset->toString().c_str());
    return 1;
}
Example #10
0
File: rs.cpp Project: 504com/mongo
int main( int argc , const char ** argv ) {
    
    unsigned nThreads = 1;
    bool print = false;
    bool testTimeout = false;

    for ( int i=1; i<argc; i++ ) {
        if ( mongoutils::str::equals( "--threads" , argv[i] ) ) {
            nThreads = atoi( argv[++i] );
        }
        else if ( mongoutils::str::equals( "--print" , argv[i] ) ) {
            print = true;
        }
        // Run a special mode to demonstrate the DBClientReplicaSet so_timeout option.
        else if ( mongoutils::str::equals( "--testTimeout" , argv[i] ) ) {
            testTimeout = true;
        }
        else {
            cerr << "unknown option: " << argv[i] << endl;
            return EXIT_FAILURE;
        }
            
    }

    Status status = client::initialize();
    if ( !status.isOK() ) {
        std::cout << "failed to initialize the client driver: " << status.toString() << endl;
        return EXIT_FAILURE;
    }

    string errmsg;
    ConnectionString cs = ConnectionString::parse( "foo/127.0.0.1" , errmsg );
    if ( ! cs.isValid() ) {
        cout << "error parsing url: " << errmsg << endl;
        return EXIT_FAILURE;
    }

    DBClientReplicaSet * conn = static_cast<DBClientReplicaSet*>( cs.connect( errmsg, testTimeout ? 10 : 0 ) );
    if ( ! conn ) {
        cout << "error connecting: " << errmsg << endl;
        return EXIT_FAILURE;
    }

    string collName = "test.rs1";

    conn->dropCollection( collName );

    if ( testTimeout ) {
        conn->insert( collName, BSONObj() );
        try {
            conn->count( collName, BSON( "$where" << "sleep(40000)" ) );
        } catch( DBException& ) {
            return EXIT_SUCCESS;
        }
        cout << "expected socket exception" << endl;
        return EXIT_FAILURE;
    }
    
    vector<boost::shared_ptr<boost::thread> > threads;
    for ( unsigned i=0; i<nThreads; i++ ) {
        string errmsg;
        threads.push_back( boost::shared_ptr<boost::thread>( 
                               new boost::thread( 
                                   boost::bind( workerThread , 
                                                collName , 
                                                print , 
                                                static_cast<DBClientReplicaSet*>( cs.connect(errmsg) ) ) ) ) );
    }
    
    for ( unsigned i=0; i<threads.size(); i++ ) {
        threads[i]->join();
    }

    return EXIT_SUCCESS;
}