summaryrefslogtreecommitdiff
path: root/s/chunk.h
diff options
context:
space:
mode:
Diffstat (limited to 's/chunk.h')
-rw-r--r--s/chunk.h279
1 files changed, 158 insertions, 121 deletions
diff --git a/s/chunk.h b/s/chunk.h
index 82f2300..43c0d95 100644
--- a/s/chunk.h
+++ b/s/chunk.h
@@ -1,9 +1,4 @@
-// shard.h
-
-/*
- A "shard" is a database (replica pair typically) which represents
- one partition of the overall database.
-*/
+// @file chunk.h
/**
* Copyright (C) 2008 10gen Inc.
@@ -24,16 +19,17 @@
#pragma once
#include "../pch.h"
-#include "../client/dbclient.h"
-#include "../client/model.h"
+
#include "../bson/util/atomic_int.h"
+#include "../client/dbclient.h"
+#include "../client/distlock.h"
+
#include "shardkey.h"
#include "shard.h"
-#include "config.h"
#include "util.h"
namespace mongo {
-
+
class DBConfig;
class Chunk;
class ChunkRange;
@@ -46,130 +42,187 @@ namespace mongo {
// key is max for each Chunk or ChunkRange
typedef map<BSONObj,ChunkPtr,BSONObjCmp> ChunkMap;
typedef map<BSONObj,shared_ptr<ChunkRange>,BSONObjCmp> ChunkRangeMap;
-
+
+ typedef shared_ptr<ChunkManager> ChunkManagerPtr;
+
/**
config.chunks
{ ns : "alleyinsider.fs.chunks" , min : {} , max : {} , server : "localhost:30001" }
-
+
x is in a shard iff
min <= x < max
- */
+ */
class Chunk : boost::noncopyable, public boost::enable_shared_from_this<Chunk> {
public:
-
Chunk( ChunkManager * info );
Chunk( ChunkManager * info , const BSONObj& min, const BSONObj& max, const Shard& shard);
-
- const BSONObj& getMin() const { return _min; }
- const BSONObj& getMax() const { return _max; }
-
- void setMin(const BSONObj& o){
- _min = o;
- }
- void setMax(const BSONObj& o){
- _max = o;
- }
-
- string getns() const;
- Shard getShard() const { return _shard; }
+ //
+ // serialization support
+ //
- void setShard( const Shard& shard );
-
- bool contains( const BSONObj& obj ) const;
+ void serialize(BSONObjBuilder& to, ShardChunkVersion myLastMod=0);
+ void unserialize(const BSONObj& from);
- string toString() const;
+ //
+ // chunk boundary support
+ //
- friend ostream& operator << (ostream& out, const Chunk& c){ return (out << c.toString()); }
+ const BSONObj& getMin() const { return _min; }
+ const BSONObj& getMax() const { return _max; }
+ void setMin(const BSONObj& o) { _min = o; }
+ void setMax(const BSONObj& o) { _max = o; }
- bool operator==(const Chunk& s) const;
-
- bool operator!=(const Chunk& s) const{
- return ! ( *this == s );
- }
-
// if min/max key is pos/neg infinity
bool minIsInf() const;
bool maxIsInf() const;
- BSONObj pickSplitPoint() const;
- ChunkPtr split();
+ bool contains( const BSONObj& obj ) const;
- void pickSplitVector( vector<BSONObj>* splitPoints ) const;
- ChunkPtr multiSplit( const vector<BSONObj>& splitPoints );
+ string genID() const;
+ static string genID( const string& ns , const BSONObj& min );
+
+ //
+ // chunk version support
+ //
+
+ void appendShortVersion( const char * name , BSONObjBuilder& b );
+
+ ShardChunkVersion getLastmod() const { return _lastmod; }
+ void setLastmod( ShardChunkVersion v ) { _lastmod = v; }
+
+ //
+ // split support
+ //
- /**
- * @return size of shard in bytes
- * talks to mongod to do this
- */
- long getPhysicalSize() const;
-
- int countObjects(int maxcount=0) const;
-
/**
* if the amount of data written nears the max size of a shard
* then we check the real size, and if its too big, we split
+ * @return if something was split
*/
bool splitIfShould( long dataWritten );
-
- /*
+
+ /**
+ * Splits this chunk at a non-specificed split key to be chosen by the mongod holding this chunk.
+ *
+ * @param force if set to true, will split the chunk regardless if the split is really necessary size wise
+ * if set to false, will only split if the chunk has reached the currently desired maximum size
+ * @param res the object containing details about the split execution
+ * @return if found a key, return a pointer to the first chunk, otherwise return a null pointer
+ */
+ ChunkPtr singleSplit( bool force , BSONObj& res );
+
+ /**
+ * Splits this chunk at the given key (or keys)
+ *
+ * @param splitPoints the vector of keys that should be used to divide this chunk
+ * @param res the object containing details about the split execution
+ * @return shared pointer to the first new Chunk or null pointer if failed
+ */
+ ChunkPtr multiSplit( const vector<BSONObj>& splitPoints , BSONObj& res );
+
+ /**
+ * Asks the mongod holding this chunk to find a key that approximately divides this chunk in two
+ *
+ * @param medianKey the key that divides this chunk, if there is one, or empty
+ */
+ void pickMedianKey( BSONObj& medianKey ) const;
+
+ /**
+ * @param splitPoints vector to be filled in
+ * @param chunkSize chunk size to target in bytes
+ * @param maxPoints limits the number of split points that are needed, zero is max (optional)
+ * @param maxObjs limits the number of objects in each chunk, zero is as max (optional)
+ */
+ void pickSplitVector( vector<BSONObj>& splitPoints , int chunkSize , int maxPoints = 0, int maxObjs = 0) const;
+
+ //
+ // migration support
+ //
+
+ /**
* moves either this shard or newShard if it makes sense too
+ *
* @return whether or not a shard was moved
*/
bool moveIfShould( ChunkPtr newShard = ChunkPtr() );
- bool moveAndCommit( const Shard& to , string& errmsg );
+ /**
+ * Issues a migrate request for this chunk
+ *
+ * @param to shard to move this chunk to
+ * @param chunSize maximum number of bytes beyond which the migrate should no go trhough
+ * @param res the object containing details about the migrate execution
+ * @return true if move was successful
+ */
+ bool moveAndCommit( const Shard& to , long long chunkSize , BSONObj& res );
- const char * getNS(){ return "config.chunks"; }
- void serialize(BSONObjBuilder& to, ShardChunkVersion myLastMod=0);
- void unserialize(const BSONObj& from);
- string modelServer() const;
-
- void appendShortVersion( const char * name , BSONObjBuilder& b );
+ /**
+ * @return size of shard in bytes
+ * talks to mongod to do this
+ */
+ long getPhysicalSize() const;
+
+ //
+ // chunk size support
+ int countObjects(int maxcount=0) const;
+
+ //
+ // public constants
+ //
+
+ static string chunkMetadataNS;
static int MaxChunkSize;
- string genID() const;
- static string genID( const string& ns , const BSONObj& min );
+ //
+ // accessors and helpers
+ //
- const ChunkManager* getManager() const { return _manager; }
-
- bool getModified() { return _modified; }
- void setModified( bool modified ) { _modified = modified; }
+ string toString() const;
- ShardChunkVersion getVersionOnConfigServer() const;
- private:
+ friend ostream& operator << (ostream& out, const Chunk& c) { return (out << c.toString()); }
+ bool operator==(const Chunk& s) const;
+ bool operator!=(const Chunk& s) const { return ! ( *this == s ); }
- bool _splitIfShould( long dataWritten );
+ string getns() const;
+ const char * getNS() { return "config.chunks"; }
+ Shard getShard() const { return _shard; }
+ const ChunkManager* getManager() const { return _manager; }
+ private:
// main shard info
-
+
ChunkManager * _manager;
- ShardKeyPattern skey() const;
BSONObj _min;
BSONObj _max;
Shard _shard;
ShardChunkVersion _lastmod;
- bool _modified;
-
// transient stuff
long _dataWritten;
-
+
// methods, etc..
-
- void _split( BSONObj& middle );
- friend class ChunkManager;
- friend class ShardObjUnitTest;
+ /**
+ * if sort 1, return lowest key
+ * if sort -1, return highest key
+ * will return empty object if have none
+ */
+ BSONObj _getExtremeKey( int sort ) const;
+
+ /** initializes _dataWritten with a random value so that a mongos restart wouldn't cause delay in splitting */
+ void _setDataWritten();
+
+ ShardKeyPattern skey() const;
};
- class ChunkRange{
+ class ChunkRange {
public:
- const ChunkManager* getManager() const{ return _manager; }
- Shard getShard() const{ return _shard; }
+ const ChunkManager* getManager() const { return _manager; }
+ Shard getShard() const { return _shard; }
const BSONObj& getMin() const { return _min; }
const BSONObj& getMax() const { return _max; }
@@ -181,11 +234,10 @@ namespace mongo {
: _manager(begin->second->getManager())
, _shard(begin->second->getShard())
, _min(begin->second->getMin())
- , _max(prior(end)->second->getMax())
- {
+ , _max(prior(end)->second->getMax()) {
assert( begin != end );
- DEV while (begin != end){
+ DEV while (begin != end) {
assert(begin->second->getManager() == _manager);
assert(begin->second->getShard() == _shard);
++begin;
@@ -197,14 +249,13 @@ namespace mongo {
: _manager(min.getManager())
, _shard(min.getShard())
, _min(min.getMin())
- , _max(max.getMax())
- {
+ , _max(max.getMax()) {
assert(min.getShard() == max.getShard());
assert(min.getManager() == max.getManager());
assert(min.getMax() == max.getMin());
}
- friend ostream& operator<<(ostream& out, const ChunkRange& cr){
+ friend ostream& operator<<(ostream& out, const ChunkRange& cr) {
return (out << "ChunkRange(min=" << cr._min << ", max=" << cr._max << ", shard=" << cr._shard <<")");
}
@@ -239,7 +290,7 @@ namespace mongo {
};
/* config.sharding
- { ns: 'alleyinsider.fs.chunks' ,
+ { ns: 'alleyinsider.fs.chunks' ,
key: { ts : 1 } ,
shards: [ { min: 1, max: 100, server: a } , { min: 101, max: 200 , server : b } ]
}
@@ -247,75 +298,61 @@ namespace mongo {
class ChunkManager {
public:
- ChunkManager( DBConfig * config , string ns , ShardKeyPattern pattern , bool unique );
+ ChunkManager( string ns , ShardKeyPattern pattern , bool unique );
virtual ~ChunkManager();
string getns() const { return _ns; }
-
+
int numChunks() const { rwlock lk( _lock , false ); return _chunkMap.size(); }
bool hasShardKey( const BSONObj& obj );
+ void createFirstChunk( const Shard& shard );
ChunkPtr findChunk( const BSONObj& obj , bool retry = false );
ChunkPtr findChunkOnServer( const Shard& shard ) const;
-
- ShardKeyPattern& getShardKey(){ return _key; }
+
const ShardKeyPattern& getShardKey() const { return _key; }
- bool isUnique(){ return _unique; }
+ bool isUnique() const { return _unique; }
void maybeChunkCollection();
-
+
void getShardsForQuery( set<Shard>& shards , const BSONObj& query );
void getAllShards( set<Shard>& all );
void getShardsForRange(set<Shard>& shards, const BSONObj& min, const BSONObj& max); // [min, max)
- void save( bool major );
-
string toString() const;
ShardChunkVersion getVersion( const Shard& shard ) const;
ShardChunkVersion getVersion() const;
- /**
- * actually does a query on the server
- * doesn't look at any local data
- */
- ShardChunkVersion getVersionOnConfigServer() const;
-
/**
* this is just an increasing number of how many ChunkManagers we have so we know if something has been updated
*/
- unsigned long long getSequenceNumber(){
- return _sequenceNumber;
- }
-
- void getInfo( BSONObjBuilder& b ){
+ unsigned long long getSequenceNumber() const { return _sequenceNumber; }
+
+ void getInfo( BSONObjBuilder& b ) {
b.append( "key" , _key.key() );
b.appendBool( "unique" , _unique );
}
-
+
/**
* @param me - so i don't get deleted before i'm done
*/
void drop( ChunkManagerPtr me );
void _printChunks() const;
-
+
+ int getCurrentDesiredChunkSize() const;
+
private:
-
void _reload();
void _reload_inlock();
void _load();
- void save_inlock( bool major );
- ShardChunkVersion getVersion_inlock() const;
void ensureIndex_inlock();
-
- DBConfig * _config;
+
string _ns;
ShardKeyPattern _key;
bool _unique;
-
- map<string,unsigned long long> _maxMarkers;
ChunkMap _chunkMap;
ChunkRangeManager _chunkRanges;
@@ -323,11 +360,9 @@ namespace mongo {
set<Shard> _shards;
unsigned long long _sequenceNumber;
-
- mutable RWLock _lock;
- // This should only be called from Chunk after it has been migrated
- void _migrationNotification(Chunk* c);
+ mutable RWLock _lock;
+ DistributedLock _nsLock;
friend class Chunk;
friend class ChunkRangeManager; // only needed for CRM::assertValid()
@@ -362,12 +397,14 @@ namespace mongo {
/*
struct chunk_lock {
chunk_lock( const Chunk* c ){
-
+
}
-
+
Chunk _c;
};
*/
inline string Chunk::genID() const { return genID(_manager->getns(), _min); }
+ bool setShardVersion( DBClientBase & conn , const string& ns , ShardChunkVersion version , bool authoritative , BSONObj& result );
+
} // namespace mongo