From 2aa64fb929114812c453d52614fe318fc9ddcedb Mon Sep 17 00:00:00 2001 From: Eliot Horowitz Date: Wed, 29 Jun 2011 00:49:30 -0400 Subject: [PATCH] less thrashing when config changes --- s/chunk.cpp | 45 ++++++++++++++++++++------------------------- s/chunk.h | 7 ++++++- s/config.cpp | 7 ++++++- 3 files changed, 32 insertions(+), 27 deletions(-) diff --git a/s/chunk.cpp b/s/chunk.cpp index 079c6aa1765..8a19f18116f 100644 --- a/s/chunk.cpp +++ b/s/chunk.cpp @@ -504,11 +504,13 @@ namespace mongo { while (tries--) { ChunkMap chunkMap; set shards; + ShardVersionMap shardVersions; Timer t; - _load(chunkMap, shards); + _load(chunkMap, shards, shardVersions); { int ms = t.millis(); - log( ms < 100 ) << "time to load chunks for " << ns << ": " << ms << "ms" << endl; + log() << "ChunkManager: time to load chunks for " << ns << ": " << ms << "ms" + << " sequenceNumber: " << _sequenceNumber << endl; } if (_isValid(chunkMap)) { @@ -517,6 +519,7 @@ namespace mongo { // to worry about that here. const_cast(_chunkMap).swap(chunkMap); const_cast&>(_shards).swap(shards); + const_cast(_shardVersions).swap(shardVersions); const_cast(_chunkRanges).reloadAll(_chunkMap); return; } @@ -538,7 +541,7 @@ namespace mongo { return grid.getDBConfig(getns())->getChunkManager(getns(), force); } - void ChunkManager::_load(ChunkMap& chunkMap, set& shards) const { + void ChunkManager::_load(ChunkMap& chunkMap, set& shards, ShardVersionMap& shardVersions) { ScopedDbConnection conn( configServer.modelServer() ); // TODO really need the sort? @@ -555,7 +558,16 @@ namespace mongo { chunkMap[c->getMax()] = c; shards.insert(c->getShard()); + + // set global max + if ( c->getLastmod() > _version ) + _version = c->getLastmod(); + + // set shard max + ShardChunkVersion& shardMax = shardVersions[c->getShard()]; + if ( c->getLastmod() > shardMax ) + shardMax = c->getLastmod(); } conn.done(); } @@ -841,31 +853,14 @@ namespace mongo { } ShardChunkVersion ChunkManager::getVersion( const Shard& shard ) const { - // TODO: cache or something? - - ShardChunkVersion max = 0; - - for ( ChunkMap::const_iterator i=_chunkMap.begin(); i!=_chunkMap.end(); ++i ) { - ChunkPtr c = i->second; - DEV assert( c ); - if ( c->getShard() != shard ) - continue; - if ( c->getLastmod() > max ) - max = c->getLastmod(); - } - return max; + ShardVersionMap::const_iterator i = _shardVersions.find( shard ); + if ( i == _shardVersions.end() ) + return 0; + return i->second; } ShardChunkVersion ChunkManager::getVersion() const { - ShardChunkVersion max = 0; - - for ( ChunkMap::const_iterator i=_chunkMap.begin(); i!=_chunkMap.end(); ++i ) { - ChunkPtr c = i->second; - if ( c->getLastmod() > max ) - max = c->getLastmod(); - } - - return max; + return _version; } string ChunkManager::toString() const { diff --git a/s/chunk.h b/s/chunk.h index 3d5963065b3..4c36dd1ad9c 100644 --- a/s/chunk.h +++ b/s/chunk.h @@ -283,6 +283,7 @@ namespace mongo { */ class ChunkManager { public: + typedef map ShardVersionMap; ChunkManager( string ns , ShardKeyPattern pattern , bool unique ); @@ -332,7 +333,7 @@ namespace mongo { ChunkManagerPtr reload(bool force=true) const; // doesn't modify self! // helpers for constructor - void _load(ChunkMap& chunks, set& shards) const; + void _load(ChunkMap& chunks, set& shards, ShardVersionMap& shardVersions); static bool _isValid(const ChunkMap& chunks); // All members should be const for thread-safety @@ -345,6 +346,10 @@ namespace mongo { const set _shards; + const ShardVersionMap _shardVersions; // max version per shard + + ShardChunkVersion _version; // max version of any chunk + mutable mutex _mutex; // only used with _nsLock mutable DistributedLock _nsLock; diff --git a/s/config.cpp b/s/config.cpp index 99e401f92ac..f5ee2c8c577 100644 --- a/s/config.cpp +++ b/s/config.cpp @@ -226,7 +226,12 @@ namespace mongo { CollectionInfo& ci = _collections[ns]; massert( 14822 , (string)"state changed in the middle: " + ns , ci.isSharded() || ci.wasDropped() ); - ci.resetCM( temp.release() ); + if ( temp->getVersion() > ci.getCM()->getVersion() ) { + // we only want to reset if we're newer + // otherwise we go into a bad cycle + ci.resetCM( temp.release() ); + } + return ci.getCM(); }