00001
00002
00019 #pragma once
00020
00021 #include "../pch.h"
00022
00023 #include "../bson/util/atomic_int.h"
00024 #include "../client/dbclient.h"
00025 #include "../client/distlock.h"
00026
00027 #include "shardkey.h"
00028 #include "shard.h"
00029 #include "util.h"
00030
00031 namespace mongo {
00032
00033 class DBConfig;
00034 class Chunk;
00035 class ChunkRange;
00036 class ChunkManager;
00037 class ChunkRangeMangager;
00038 class ChunkObjUnitTest;
00039
00040 typedef shared_ptr<Chunk> ChunkPtr;
00041
00042
00043 typedef map<BSONObj,ChunkPtr,BSONObjCmp> ChunkMap;
00044 typedef map<BSONObj,shared_ptr<ChunkRange>,BSONObjCmp> ChunkRangeMap;
00045
00046 typedef shared_ptr<ChunkManager> ChunkManagerPtr;
00047
00055 class Chunk : boost::noncopyable, public boost::enable_shared_from_this<Chunk> {
00056 public:
00057 Chunk( ChunkManager * info );
00058 Chunk( ChunkManager * info , const BSONObj& min, const BSONObj& max, const Shard& shard);
00059
00060
00061
00062
00063
00064 void serialize(BSONObjBuilder& to, ShardChunkVersion myLastMod=0);
00065 void unserialize(const BSONObj& from);
00066
00067
00068
00069
00070
00071 const BSONObj& getMin() const { return _min; }
00072 const BSONObj& getMax() const { return _max; }
00073 void setMin(const BSONObj& o) { _min = o; }
00074 void setMax(const BSONObj& o) { _max = o; }
00075
00076
00077 bool minIsInf() const;
00078 bool maxIsInf() const;
00079
00080 bool contains( const BSONObj& obj ) const;
00081
00082 string genID() const;
00083 static string genID( const string& ns , const BSONObj& min );
00084
00085
00086
00087
00088
00089 void appendShortVersion( const char * name , BSONObjBuilder& b );
00090
00091 ShardChunkVersion getLastmod() const { return _lastmod; }
00092 void setLastmod( ShardChunkVersion v ) { _lastmod = v; }
00093
00094
00095
00096
00097
00103 bool splitIfShould( long dataWritten );
00104
00113 ChunkPtr singleSplit( bool force , BSONObj& res );
00114
00122 ChunkPtr multiSplit( const vector<BSONObj>& splitPoints , BSONObj& res );
00123
00129 void pickMedianKey( BSONObj& medianKey ) const;
00130
00137 void pickSplitVector( vector<BSONObj>& splitPoints , int chunkSize , int maxPoints = 0, int maxObjs = 0) const;
00138
00139
00140
00141
00142
00148 bool moveIfShould( ChunkPtr newShard = ChunkPtr() );
00149
00158 bool moveAndCommit( const Shard& to , long long chunkSize , BSONObj& res );
00159
00164 long getPhysicalSize() const;
00165
00166
00167
00168
00169 int countObjects(int maxcount=0) const;
00170
00171
00172
00173
00174
00175 static string chunkMetadataNS;
00176 static int MaxChunkSize;
00177 static int MaxObjectPerChunk;
00178
00179
00180
00181
00182 string toString() const;
00183
00184 friend ostream& operator << (ostream& out, const Chunk& c) { return (out << c.toString()); }
00185 bool operator==(const Chunk& s) const;
00186 bool operator!=(const Chunk& s) const { return ! ( *this == s ); }
00187
00188 string getns() const;
00189 const char * getNS() { return "config.chunks"; }
00190 Shard getShard() const { return _shard; }
00191 const ChunkManager* getManager() const { return _manager; }
00192
00193
00194 private:
00195
00196
00197 ChunkManager * _manager;
00198
00199 BSONObj _min;
00200 BSONObj _max;
00201 Shard _shard;
00202 ShardChunkVersion _lastmod;
00203
00204
00205
00206 long _dataWritten;
00207
00208
00209
00215 BSONObj _getExtremeKey( int sort ) const;
00216
00218 void _setDataWritten();
00219
00220 ShardKeyPattern skey() const;
00221 };
00222
00223 class ChunkRange {
00224 public:
00225 const ChunkManager* getManager() const { return _manager; }
00226 Shard getShard() const { return _shard; }
00227
00228 const BSONObj& getMin() const { return _min; }
00229 const BSONObj& getMax() const { return _max; }
00230
00231
00232 bool contains(const BSONObj& obj) const;
00233
00234 ChunkRange(ChunkMap::const_iterator begin, const ChunkMap::const_iterator end)
00235 : _manager(begin->second->getManager())
00236 , _shard(begin->second->getShard())
00237 , _min(begin->second->getMin())
00238 , _max(prior(end)->second->getMax()) {
00239 assert( begin != end );
00240
00241 DEV while (begin != end) {
00242 assert(begin->second->getManager() == _manager);
00243 assert(begin->second->getShard() == _shard);
00244 ++begin;
00245 }
00246 }
00247
00248
00249 ChunkRange(const ChunkRange& min, const ChunkRange& max)
00250 : _manager(min.getManager())
00251 , _shard(min.getShard())
00252 , _min(min.getMin())
00253 , _max(max.getMax()) {
00254 assert(min.getShard() == max.getShard());
00255 assert(min.getManager() == max.getManager());
00256 assert(min.getMax() == max.getMin());
00257 }
00258
00259 friend ostream& operator<<(ostream& out, const ChunkRange& cr) {
00260 return (out << "ChunkRange(min=" << cr._min << ", max=" << cr._max << ", shard=" << cr._shard <<")");
00261 }
00262
00263 private:
00264 const ChunkManager* _manager;
00265 const Shard _shard;
00266 const BSONObj _min;
00267 const BSONObj _max;
00268 };
00269
00270
00271 class ChunkRangeManager {
00272 public:
00273 const ChunkRangeMap& ranges() const { return _ranges; }
00274
00275 void clear() { _ranges.clear(); }
00276
00277 void reloadAll(const ChunkMap& chunks);
00278 void reloadRange(const ChunkMap& chunks, const BSONObj& min, const BSONObj& max);
00279
00280
00281 void assertValid() const;
00282
00283 ChunkRangeMap::const_iterator upper_bound(const BSONObj& o) const { return _ranges.upper_bound(o); }
00284 ChunkRangeMap::const_iterator lower_bound(const BSONObj& o) const { return _ranges.lower_bound(o); }
00285
00286 private:
00287
00288 void _insertRange(ChunkMap::const_iterator begin, const ChunkMap::const_iterator end);
00289
00290 ChunkRangeMap _ranges;
00291 };
00292
00293
00294
00295
00296
00297
00298
00299 class ChunkManager {
00300 public:
00301
00302 ChunkManager( string ns , ShardKeyPattern pattern , bool unique );
00303 virtual ~ChunkManager();
00304
00305 string getns() const { return _ns; }
00306
00307 int numChunks() const { rwlock lk( _lock , false ); return _chunkMap.size(); }
00308 bool hasShardKey( const BSONObj& obj );
00309
00310 void createFirstChunk( const Shard& shard );
00311 ChunkPtr findChunk( const BSONObj& obj , bool retry = false );
00312 ChunkPtr findChunkOnServer( const Shard& shard ) const;
00313
00314 const ShardKeyPattern& getShardKey() const { return _key; }
00315 bool isUnique() const { return _unique; }
00316
00317 void maybeChunkCollection();
00318
00319 void getShardsForQuery( set<Shard>& shards , const BSONObj& query );
00320 void getAllShards( set<Shard>& all );
00321 void getShardsForRange(set<Shard>& shards, const BSONObj& min, const BSONObj& max);
00322
00323 string toString() const;
00324
00325 ShardChunkVersion getVersion( const Shard& shard ) const;
00326 ShardChunkVersion getVersion() const;
00327
00331 unsigned long long getSequenceNumber() const { return _sequenceNumber; }
00332
00333 void getInfo( BSONObjBuilder& b ) {
00334 b.append( "key" , _key.key() );
00335 b.appendBool( "unique" , _unique );
00336 }
00337
00341 void drop( ChunkManagerPtr me );
00342
00343 void _printChunks() const;
00344
00345 int getCurrentDesiredChunkSize() const;
00346
00347 private:
00348 void _reload();
00349 void _reload_inlock();
00350 void _load();
00351
00352 void ensureIndex_inlock();
00353
00354 string _ns;
00355 ShardKeyPattern _key;
00356 bool _unique;
00357
00358 ChunkMap _chunkMap;
00359 ChunkRangeManager _chunkRanges;
00360
00361 set<Shard> _shards;
00362
00363 unsigned long long _sequenceNumber;
00364
00365 mutable RWLock _lock;
00366 DistributedLock _nsLock;
00367
00368 friend class Chunk;
00369 friend class ChunkRangeManager;
00370 static AtomicUInt NextSequenceNumber;
00371
00372 bool _isValid() const;
00373 };
00374
00375
00376
00377 class ChunkCmp {
00378 public:
00379 ChunkCmp( const BSONObj &order = BSONObj() ) : _cmp( order ) {}
00380 bool operator()( const Chunk &l, const Chunk &r ) const {
00381 return _cmp(l.getMin(), r.getMin());
00382 }
00383 bool operator()( const ptr<Chunk> l, const ptr<Chunk> r ) const {
00384 return operator()(*l, *r);
00385 }
00386
00387
00388 bool operator()( const ChunkRange &l, const ChunkRange &r ) const {
00389 return _cmp(l.getMin(), r.getMin());
00390 }
00391 bool operator()( const shared_ptr<ChunkRange> l, const shared_ptr<ChunkRange> r ) const {
00392 return operator()(*l, *r);
00393 }
00394 private:
00395 BSONObjCmp _cmp;
00396 };
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407 inline string Chunk::genID() const { return genID(_manager->getns(), _min); }
00408
00409 bool setShardVersion( DBClientBase & conn , const string& ns , ShardChunkVersion version , bool authoritative , BSONObj& result );
00410
00411 }