diff options
author | Eliot Horowitz <eliot@10gen.com> | 2011-04-11 05:50:45 -0400 |
---|---|---|
committer | Eliot Horowitz <eliot@10gen.com> | 2011-04-11 14:23:23 -0400 |
commit | d0882e2ef57703200d3fa4eeedf18b91ca297384 (patch) | |
tree | 25088c8feeb217671eb7a7b5bfc95b61f69abe69 | |
parent | abfa5faccbc52bf1ce1e96c8071fa1318c338480 (diff) | |
download | mongo-d0882e2ef57703200d3fa4eeedf18b91ca297384.tar.gz |
fix staticShardInfo to be thread safe SERVER-2929
-rw-r--r-- | s/shard.cpp | 96 |
1 files changed, 57 insertions, 39 deletions
diff --git a/s/shard.cpp b/s/shard.cpp index dbfd8f965c2..c1e3b56b01d 100644 --- a/s/shard.cpp +++ b/s/shard.cpp @@ -25,6 +25,8 @@ namespace mongo { + typedef shared_ptr<Shard> ShardPtr; + class StaticShardInfo { public: StaticShardInfo() : _mutex("StaticShardInfo") { } @@ -48,9 +50,9 @@ namespace mongo { // the config state intact. The rationale is that this way we could drop shards that // were removed without reinitializing the config DB information. - map<string,Shard>::iterator i = _lookup.find( "config" ); + ShardMap::iterator i = _lookup.find( "config" ); if ( i != _lookup.end() ) { - Shard config = i->second; + ShardPtr config = i->second; _lookup.clear(); _lookup[ "config" ] = config; } @@ -75,14 +77,14 @@ namespace mongo { isDraining = isDrainingElem.Bool(); } - Shard s( name , host , maxSize , isDraining ); + ShardPtr s( new Shard( name , host , maxSize , isDraining ) ); _lookup[name] = s; _installHost( host , s ); } } - const Shard& find( const string& ident ) { + ShardPtr find( const string& ident ) { string mykey = ident; { @@ -94,7 +96,7 @@ namespace mongo { { scoped_lock lk( _mutex ); - map<string,Shard>::iterator i = _lookup.find( mykey ); + ShardMap::iterator i = _lookup.find( mykey ); if ( i != _lookup.end() ) return i->second; @@ -104,23 +106,24 @@ namespace mongo { reload(); scoped_lock lk( _mutex ); - map<string,Shard>::iterator i = _lookup.find( mykey ); + ShardMap::iterator i = _lookup.find( mykey ); massert( 13129 , (string)"can't find shard for: " + mykey , i != _lookup.end() ); return i->second; } 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] = s; + _lookup[name] = ss; if ( setAddr ) - _installHost( s.getConnString() , s ); + _installHost( s.getConnString() , ss ); } - void _installHost( const string& host , const Shard& s ) { + void _installHost( const string& host , const ShardPtr& s ) { _lookup[host] = s; - const ConnectionString& cs = s.getAddress(); + const ConnectionString& cs = s->getAddress(); if ( cs.type() == ConnectionString::SET ) { if ( cs.getSetName().size() ) _lookup[ cs.getSetName() ] = s; @@ -134,9 +137,9 @@ namespace mongo { 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 ) { + for ( ShardMap::iterator i = _lookup.begin(); i!=_lookup.end(); ) { + ShardPtr s = i->second; + if ( s->getName() == name ) { _lookup.erase(i++); } else { @@ -145,35 +148,49 @@ namespace mongo { } } - void getAllShards( vector<Shard>& all ) const { + void getAllShards( vector<ShardPtr>& all ) const { scoped_lock lk( _mutex ); std::set<string> seen; - for ( map<string,Shard>::const_iterator i = _lookup.begin(); i!=_lookup.end(); ++i ) { - const Shard& s = i->second; - if ( s.getName() == "config" ) + for ( ShardMap::const_iterator i = _lookup.begin(); i!=_lookup.end(); ++i ) { + const ShardPtr& s = i->second; + if ( s->getName() == "config" ) continue; - if ( seen.count( s.getName() ) ) + if ( seen.count( s->getName() ) ) continue; - seen.insert( s.getName() ); + seen.insert( s->getName() ); all.push_back( s ); } } + + void getAllShards( vector<Shard>& all ) const { + scoped_lock lk( _mutex ); + std::set<string> seen; + for ( ShardMap::const_iterator i = _lookup.begin(); i!=_lookup.end(); ++i ) { + const ShardPtr& s = i->second; + if ( s->getName() == "config" ) + continue; + if ( seen.count( s->getName() ) ) + continue; + seen.insert( s->getName() ); + all.push_back( *s ); + } + } + bool isAShardNode( const string& addr ) const { scoped_lock lk( _mutex ); // check direct nods or set names - map<string,Shard>::const_iterator i = _lookup.find( addr ); + ShardMap::const_iterator i = _lookup.find( addr ); if ( i != _lookup.end() ) return true; // check for set nodes - for ( map<string,Shard>::const_iterator i = _lookup.begin(); i!=_lookup.end(); ++i ) { + for ( ShardMap::const_iterator i = _lookup.begin(); i!=_lookup.end(); ++i ) { if ( i->first == "config" ) continue; - const Shard& s = i->second; - if ( s.containsNode( addr ) ) + if ( i->second->containsNode( addr ) ) return true; } @@ -185,8 +202,8 @@ namespace mongo { BSONObjBuilder b( _lookup.size() + 50 ); - for ( map<string,Shard>::const_iterator i = _lookup.begin(); i!=_lookup.end(); ++i ) { - b.append( i->first , i->second.getConnString() ); + for ( ShardMap::const_iterator i = _lookup.begin(); i!=_lookup.end(); ++i ) { + b.append( i->first , i->second->getConnString() ); } result.append( "map" , b.obj() ); @@ -195,7 +212,8 @@ namespace mongo { } private: - map<string,Shard> _lookup; + typedef map<string,ShardPtr> ShardMap; + ShardMap _lookup; mutable mongo::mutex _mutex; } staticShardInfo; @@ -242,14 +260,14 @@ namespace mongo { } void Shard::reset( const string& ident ) { - const Shard& s = staticShardInfo.find( ident ); - massert( 13128 , (string)"can't find shard for: " + ident , s.ok() ); - _name = s._name; - _addr = s._addr; - _cs = s._cs; + ShardPtr s = staticShardInfo.find( ident ); + massert( 13128 , (string)"can't find shard for: " + ident , s->ok() ); + _name = s->_name; + _addr = s->_addr; + _cs = s->_cs; _rsInit(); - _maxSize = s._maxSize; - _isDraining = s._isDraining; + _maxSize = s->_maxSize; + _isDraining = s->_isDraining; } bool Shard::containsNode( const string& node ) const { @@ -271,10 +289,10 @@ namespace mongo { } void Shard::printShardInfo( ostream& out ) { - vector<Shard> all; - getAllShards( all ); + vector<ShardPtr> all; + staticShardInfo.getAllShards( all ); for ( unsigned i=0; i<all.size(); i++ ) - out << all[i].toString() << "\n"; + out << all[i]->toString() << "\n"; out.flush(); } @@ -306,7 +324,7 @@ namespace mongo { } Shard Shard::pick( const Shard& current ) { - vector<Shard> all; + vector<ShardPtr> all; staticShardInfo.getAllShards( all ); if ( all.size() == 0 ) { staticShardInfo.reload(); @@ -316,13 +334,13 @@ namespace mongo { } // if current shard was provided, pick a different shard only if it is a better choice - ShardStatus best = all[0].getStatus(); + 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(); + ShardStatus t = all[i]->getStatus(); if ( t < best ) best = t; } |