// config.h
/**
* Copyright (C) 2008 10gen Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*/
/* This file is things related to the "grid configuration":
- what machines make up the db component of our cloud
- where various ranges of things live
*/
#pragma once
#include "../db/namespace.h"
#include "../client/model.h"
#include "mongo/client/dbclient_rs.h"
#include "chunk.h"
#include "shard.h"
#include "shardkey.h"
namespace mongo {
class ConfigServer;
class DBConfig;
typedef boost::shared_ptr DBConfigPtr;
extern DBConfigPtr configServerPtr;
extern ConfigServer& configServer;
/**
* top level configuration for a database
*/
class DBConfig {
struct CollectionInfo {
CollectionInfo() {
_dirty = false;
_dropped = false;
}
CollectionInfo( const BSONObj& in );
bool isSharded() const {
return _cm.get();
}
ChunkManagerPtr getCM() const {
return _cm;
}
void resetCM( ChunkManager * cm ) {
verify(cm);
verify(_cm); // this has to be already sharded
_cm.reset( cm );
}
void shard( ChunkManager* cm );
void unshard();
bool isDirty() const { return _dirty; }
bool wasDropped() const { return _dropped; }
void save( const string& ns , DBClientBase* conn );
bool unique() const { return _unqiue; }
BSONObj key() const { return _key; }
private:
BSONObj _key;
bool _unqiue;
ChunkManagerPtr _cm;
bool _dirty;
bool _dropped;
};
typedef map Collections;
public:
DBConfig( string name )
: _name( name ) ,
_primary("config","") ,
_shardingEnabled(false),
_lock("DBConfig") ,
_hitConfigServerLock( "DBConfig::_hitConfigServerLock" ) {
verify( name.size() );
}
virtual ~DBConfig() {}
string getName() const { return _name; };
/**
* @return if anything in this db is partitioned or not
*/
bool isShardingEnabled() {
return _shardingEnabled;
}
void enableSharding( bool save = true );
/* Makes all the configuration changes necessary to shard a new collection.
* Optionally, chunks will be created based on a set of specified initial split points, and
* distributed in a round-robin fashion onto a set of initial shards. If no initial shards
* are specified, only the primary will be used.
*
* WARNING: It's not safe to place initial chunks onto non-primary shards using this method.
* The initShards parameter allows legacy behavior expected by map-reduce.
*/
ChunkManagerPtr shardCollection( const string& ns ,
ShardKeyPattern fieldsAndOrder ,
bool unique ,
vector* initPoints = 0,
vector* initShards = 0 );
/**
@return true if there was sharding info to remove
*/
bool removeSharding( const string& ns );
/**
* @return whether or not the 'ns' collection is partitioned
*/
bool isSharded( const string& ns );
// Atomically returns *either* the chunk manager *or* the primary shard for the collection,
// neither if the collection doesn't exist.
void getChunkManagerOrPrimary( const string& ns, ChunkManagerPtr& manager, ShardPtr& primary );
ChunkManagerPtr getChunkManager( const string& ns , bool reload = false, bool forceReload = false );
ChunkManagerPtr getChunkManagerIfExists( const string& ns , bool reload = false, bool forceReload = false );
const Shard& getShard( const string& ns );
/**
* @return the correct for shard for the ns
* if the namespace is sharded, will return NULL
*/
ShardPtr getShardIfExists( const string& ns );
const Shard& getPrimary() const {
uassert( 8041 , (string)"no primary shard configured for db: " + _name , _primary.ok() );
return _primary;
}
void setPrimary( const std::string& s );
bool load();
bool reload();
bool dropDatabase( string& errmsg );
// model stuff
// lockless loading
void serialize(BSONObjBuilder& to);
void unserialize(const BSONObj& from);
void getAllShards(set& shards) const;
void getAllShardedCollections(set& namespaces) const;
protected:
/**
lockless
*/
bool _isSharded( const string& ns );
bool _dropShardedCollections( int& num, set& allServers , string& errmsg );
bool _load();
bool _reload();
void _save( bool db = true, bool coll = true );
string _name; // e.g. "alleyinsider"
Shard _primary; // e.g. localhost , mongo.foo.com:9999
bool _shardingEnabled;
//map _sharded; // { "alleyinsider.blog.posts" : { ts : 1 } , ... ] - all ns that are sharded
//map _shards; // this will only have entries for things that have been looked at
Collections _collections;
mutable mongo::mutex _lock; // TODO: change to r/w lock ??
mutable mongo::mutex _hitConfigServerLock;
};
class ConfigServer : public DBConfig {
public:
ConfigServer();
~ConfigServer();
bool ok( bool checkConsistency = false );
virtual string modelServer() {
uassert( 10190 , "ConfigServer not setup" , _primary.ok() );
return _primary.getConnString();
}
/**
call at startup, this will initiate connection to the grid db
*/
bool init( vector configHosts );
bool init( const std::string& s );
bool allUp();
bool allUp( string& errmsg );
int dbConfigVersion();
int dbConfigVersion( DBClientBase& conn );
void reloadSettings();
/**
* @return 0 = ok, otherwise error #
*/
int checkConfigVersion( bool upgrade );
/**
* Create a metadata change log entry in the config.changelog collection.
*
* @param what e.g. "split" , "migrate"
* @param ns to which collection the metadata change is being applied
* @param msg additional info about the metadata change
*
* This call is guaranteed never to throw.
*/
void logChange( const string& what , const string& ns , const BSONObj& detail = BSONObj() );
ConnectionString getConnectionString() const {
return ConnectionString( _primary.getConnString() , ConnectionString::SYNC );
}
void replicaSetChange( const ReplicaSetMonitor * monitor );
static int VERSION;
/**
* check to see if all config servers have the same state
* will try tries time to make sure not catching in a bad state
*/
bool checkConfigServersConsistent( string& errmsg , int tries = 4 ) const;
private:
string getHost( const std::string& name , bool withPort );
vector _config;
};
} // namespace mongo