diff options
author | Alberto Lerner <alerner@10gen.com> | 2010-07-28 14:24:55 -0400 |
---|---|---|
committer | Alberto Lerner <alerner@10gen.com> | 2010-07-28 14:24:55 -0400 |
commit | bceacf2544acfb6c3509ca8db791e90fe41c8599 (patch) | |
tree | 5c210716aa3c6911c96f55d8a6370015a76b4d5a | |
parent | 0e82f323cc1be77401021486f459e14cef359faa (diff) | |
download | mongo-bceacf2544acfb6c3509ca8db791e90fe41c8599.tar.gz |
SERVER-1292 A bit more prep, separate grid.{h,cpp} from config
-rw-r--r-- | SConstruct | 2 | ||||
-rw-r--r-- | s/balance.cpp | 1 | ||||
-rw-r--r-- | s/commands_admin.cpp | 1 | ||||
-rw-r--r-- | s/commands_public.cpp | 1 | ||||
-rw-r--r-- | s/config.cpp | 199 | ||||
-rw-r--r-- | s/config.h | 75 | ||||
-rw-r--r-- | s/grid.cpp | 226 | ||||
-rw-r--r-- | s/grid.h | 103 | ||||
-rw-r--r-- | s/request.cpp | 1 | ||||
-rw-r--r-- | s/server.cpp | 1 | ||||
-rw-r--r-- | s/strategy.cpp | 2 |
11 files changed, 339 insertions, 273 deletions
diff --git a/SConstruct b/SConstruct index 7e96a50cdb9..04fd6bd742c 100644 --- a/SConstruct +++ b/SConstruct @@ -456,7 +456,7 @@ else: coreServerFiles += scriptingFiles -coreShardFiles = [ "s/config.cpp" , "s/chunk.cpp" , "s/shard.cpp" , "s/shardkey.cpp" ] +coreShardFiles = [ "s/config.cpp" , "s/grid.cpp" , "s/chunk.cpp" , "s/shard.cpp" , "s/shardkey.cpp" ] shardServerFiles = coreShardFiles + Glob( "s/strategy*.cpp" ) + [ "s/commands_admin.cpp" , "s/commands_public.cpp" , "s/request.cpp" , "s/cursors.cpp" , "s/server.cpp" , "s/config_migrate.cpp" , "s/s_only.cpp" , "s/stats.cpp" , "s/balance.cpp" , "s/balancer_policy.cpp" , "db/cmdline.cpp" ] serverOnlyFiles += coreShardFiles + [ "s/d_logic.cpp" , "s/d_writeback.cpp" , "s/d_migrate.cpp" , "s/d_state.cpp" , "s/d_split.cpp" , "client/distlock_test.cpp" ] diff --git a/s/balance.cpp b/s/balance.cpp index 2da5689db58..f79e1d8e060 100644 --- a/s/balance.cpp +++ b/s/balance.cpp @@ -28,6 +28,7 @@ #include "shard.h" #include "config.h" #include "chunk.h" +#include "grid.h" namespace mongo { diff --git a/s/commands_admin.cpp b/s/commands_admin.cpp index 5585db8ea99..af50422cba4 100644 --- a/s/commands_admin.cpp +++ b/s/commands_admin.cpp @@ -38,6 +38,7 @@ #include "config.h" #include "chunk.h" +#include "grid.h" #include "strategy.h" #include "stats.h" diff --git a/s/commands_public.cpp b/s/commands_public.cpp index 0197c38a7bc..3dbc8ad5112 100644 --- a/s/commands_public.cpp +++ b/s/commands_public.cpp @@ -28,6 +28,7 @@ #include "config.h" #include "chunk.h" #include "strategy.h" +#include "grid.h" namespace mongo { diff --git a/s/config.cpp b/s/config.cpp index 24ef4087dce..e6bb48870c4 100644 --- a/s/config.cpp +++ b/s/config.cpp @@ -28,6 +28,7 @@ #include "server.h" #include "config.h" #include "chunk.h" +#include "grid.h" namespace mongo { @@ -236,7 +237,7 @@ namespace mongo { return true; } - + void DBConfig::_save(){ ScopedDbConnection conn( configServer.modelServer() ); @@ -384,201 +385,6 @@ namespace mongo { } } - /* --- Grid --- */ - - DBConfigPtr Grid::getDBConfig( string database , bool create ){ - { - string::size_type i = database.find( "." ); - if ( i != string::npos ) - database = database.substr( 0 , i ); - } - - if ( database == "config" ) - return configServerPtr; - - scoped_lock l( _lock ); - - DBConfigPtr& cc = _databases[database]; - if ( !cc ){ - cc.reset(new DBConfig( database )); - if ( ! cc->load() ){ - if ( create ){ - // note here that cc->primary == 0. - log() << "couldn't find database [" << database << "] in config db" << endl; - - { // lets check case - ScopedDbConnection conn( configServer.modelServer() ); - BSONObjBuilder b; - b.appendRegex( "_id" , (string)"^" + database + "$" , "i" ); - BSONObj d = conn->findOne( ShardNS::database , b.obj() ); - conn.done(); - - if ( ! d.isEmpty() ){ - cc.reset(); - stringstream ss; - ss << "can't have 2 databases that just differ on case " - << " have: " << d["_id"].String() - << " want to add: " << database; - - uasserted( DatabaseDifferCaseCode ,ss.str() ); - } - } - - if ( database == "admin" ) - cc->_primary = configServer.getPrimary(); - else - cc->_primary = Shard::pick(); - - if ( cc->_primary.ok() ){ - cc->_save(); - log() << "\t put [" << database << "] on: " << cc->_primary.toString() << endl; - } - else { - cc.reset(); - log() << "\t can't find a shard to put new db on" << endl; - uasserted( 10185 , "can't find a shard to put new db on" ); - } - } - else { - cc.reset(); - } - } - - } - - return cc; - } - - void Grid::removeDB( string database ){ - uassert( 10186 , "removeDB expects db name" , database.find( '.' ) == string::npos ); - scoped_lock l( _lock ); - _databases.erase( database ); - - } - - bool Grid::allowLocalHost() const { - return _allowLocalShard; - } - - void Grid::setAllowLocalHost( bool allow ){ - _allowLocalShard = allow; - } - - bool Grid::addShard( string* name , const string& host , long long maxSize , string* errMsg ){ - // errMsg is required but name is optional - DEV assert( errMsg ); - string nameInternal; - if ( ! name ) { - name = &nameInternal; - } - - // check whether host exists and is operative - try { - ScopedDbConnection newShardConn( host ); - newShardConn->getLastError(); - newShardConn.done(); - } - catch ( DBException& e ){ - ostringstream ss; - ss << "couldn't connect to new shard "; - ss << e.what(); - *errMsg = ss.str(); - return false; - } - - // if a name for a shard wasn't provided, pick one. - if ( name->empty() && ! _getNewShardName( name ) ){ - *errMsg = "error generating new shard name"; - return false; - } - - // build the ConfigDB shard document. - BSONObjBuilder b; - b.append( "_id" , *name ); - b.append( "host" , host ); - if ( maxSize > 0 ){ - b.append( ShardFields::maxSize.name() , maxSize ); - } - BSONObj shardDoc = b.obj(); - - { - ScopedDbConnection conn( configServer.getPrimary() ); - - // check whether this host:port is already a known shard - BSONObj old = conn->findOne( ShardNS::shard , BSON( "host" << host ) ); - if ( ! old.isEmpty() ){ - *errMsg = "host already used"; - conn.done(); - return false; - } - - log() << "going to add shard: " << shardDoc << endl; - - conn->insert( ShardNS::shard , shardDoc ); - *errMsg = conn->getLastError(); - if ( ! errMsg->empty() ){ - log() << "error adding shard: " << shardDoc << " err: " << *errMsg << endl; - return false; - } - - conn.done(); - } - - Shard::reloadShardInfo(); - return true; - } - - bool Grid::knowAboutShard( const string& name ) const{ - ShardConnection conn( configServer.getPrimary() , "" ); - BSONObj shard = conn->findOne( ShardNS::shard , BSON( "host" << name ) ); - conn.done(); - return ! shard.isEmpty(); - } - - bool Grid::_getNewShardName( string* name ) const{ - DEV assert( name ); - - bool ok = false; - int count = 0; - - ShardConnection conn( configServer.getPrimary() , "" ); - BSONObj o = conn->findOne( ShardNS::shard , Query( fromjson ( "{_id: /^shard/}" ) ).sort( BSON( "_id" << -1 ) ) ); - if ( ! o.isEmpty() ) { - string last = o["_id"].String(); - istringstream is( last.substr( 5 ) ); - is >> count; - count++; - } - if (count < 9999) { - stringstream ss; - ss << "shard" << setfill('0') << setw(4) << count; - *name = ss.str(); - ok = true; - } - conn.done(); - - return ok; - } - - bool Grid::shouldBalance() const { - ShardConnection conn( configServer.getPrimary() , "" ); - - // look for the stop balancer marker - BSONObj stopMarker = conn->findOne( ShardNS::settings, BSON( "_id" << "balancer" << "stopped" << true ) ); - conn.done(); - return stopMarker.isEmpty(); - } - - unsigned long long Grid::getNextOpTime() const { - ScopedDbConnection conn( configServer.getPrimary() ); - - BSONObj result; - massert( 10421 , "getoptime failed" , conn->simpleCommand( "admin" , &result , "getoptime" ) ); - conn.done(); - - return result["optime"]._numberLong(); - } - /* --- ConfigServer ---- */ ConfigServer::ConfigServer() : DBConfig( "config" ){ @@ -761,6 +567,5 @@ namespace mongo { DBConfigPtr configServerPtr (new ConfigServer()); ConfigServer& configServer = dynamic_cast<ConfigServer&>(*configServerPtr); - Grid grid; } diff --git a/s/config.h b/s/config.h index cbefe7283ea..c1767743acd 100644 --- a/s/config.h +++ b/s/config.h @@ -51,7 +51,6 @@ namespace mongo { static BSONField<long long> currSize; }; - class Grid; class ConfigServer; class DBConfig; @@ -59,7 +58,6 @@ namespace mongo { extern DBConfigPtr configServerPtr; extern ConfigServer& configServer; - extern Grid grid; class ChunkManager; typedef shared_ptr<ChunkManager> ChunkManagerPtr; @@ -192,82 +190,9 @@ namespace mongo { mongo::mutex _lock; // TODO: change to r/w lock ?? - friend class Grid; friend class ChunkManager; }; - /** - * stores meta-information about the grid - * TODO: used shard_ptr for DBConfig pointers - */ - class Grid { - public: - Grid() : _lock( "Grid" ) , _allowLocalShard( true ) { } - - /** - * gets the config the db. - * will return an empty DBConfig if not in db already - */ - DBConfigPtr getDBConfig( string ns , bool create=true ); - - /** - * removes db entry. - * on next getDBConfig call will fetch from db - */ - void removeDB( string db ); - - /** - * @return true if shards and config servers are allowed to use 'localhost' in address - */ - bool allowLocalHost() const; - - /** - * @param whether to allow shards and config servers to use 'localhost' in address - */ - void setAllowLocalHost( bool allow ); - - /** - * - * addShard will create a new shard in the grid. It expects a mongod process to be runing - * on the provided address. - * TODO - add the mongod's databases to the grid - * - * @param name is an optional string with the name of the shard. if ommited, grid will - * generate one and update the parameter. - * @param host is the complete address of the machine where the shard will be - * @param maxSize is the optional space quota in bytes. Zeros means there's no limitation to - * space usage - * @param errMsg is the error description in case the operation failed. - * @return true if shard was successfully added. - */ - bool addShard( string* name , const string& host , long long maxSize , string* errMsg ); - - /** - * @return true if the config database knows about a host 'name' - */ - bool knowAboutShard( const string& name ) const; - - /** - * @return true if the chunk balancing functionality is enabled - */ - bool shouldBalance() const; - - unsigned long long getNextOpTime() const; - - private: - mongo::mutex _lock; // protects _databases; TODO: change to r/w lock ?? - map<string, DBConfigPtr > _databases; // maps ns to DBConfig's - bool _allowLocalShard; // can 'localhost' be used in shard addresses? - - /** - * @param name is the chose name for the shard. Parameter is mandatory. - * @return true if it managed to generate a shard name. May return false if (currently) - * 10000 shard - */ - bool _getNewShardName( string* name ) const; - - }; - class ConfigServer : public DBConfig { public: diff --git a/s/grid.cpp b/s/grid.cpp new file mode 100644 index 00000000000..e1e6c4b40a5 --- /dev/null +++ b/s/grid.cpp @@ -0,0 +1,226 @@ +// grid.cpp + +/** +* Copyright (C) 2010 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 <http://www.gnu.org/licenses/>. +*/ + +#include "pch.h" + +#include <iomanip> + +#include "../client/connpool.h" + +#include "grid.h" +#include "shard.h" + +namespace mongo { + + DBConfigPtr Grid::getDBConfig( string database , bool create ){ + { + string::size_type i = database.find( "." ); + if ( i != string::npos ) + database = database.substr( 0 , i ); + } + + if ( database == "config" ) + return configServerPtr; + + scoped_lock l( _lock ); + + DBConfigPtr& cc = _databases[database]; + if ( !cc ){ + cc.reset(new DBConfig( database )); + if ( ! cc->load() ){ + if ( create ){ + // note here that cc->primary == 0. + log() << "couldn't find database [" << database << "] in config db" << endl; + + { // lets check case + ScopedDbConnection conn( configServer.modelServer() ); + BSONObjBuilder b; + b.appendRegex( "_id" , (string)"^" + database + "$" , "i" ); + BSONObj d = conn->findOne( ShardNS::database , b.obj() ); + conn.done(); + + if ( ! d.isEmpty() ){ + cc.reset(); + stringstream ss; + ss << "can't have 2 databases that just differ on case " + << " have: " << d["_id"].String() + << " want to add: " << database; + + uasserted( DatabaseDifferCaseCode ,ss.str() ); + } + } + + Shard primary; + if ( database == "admin" ) + primary = configServer.getPrimary(); + else + primary = Shard::pick(); + + if ( primary.ok() ){ + cc->setPrimary( primary.getName() ); // saves 'cc' to configDB + log() << "\t put [" << database << "] on: " << primary << endl; + } + else { + cc.reset(); + log() << "\t can't find a shard to put new db on" << endl; + uasserted( 10185 , "can't find a shard to put new db on" ); + } + } + else { + cc.reset(); + } + } + + } + + return cc; + } + + void Grid::removeDB( string database ){ + uassert( 10186 , "removeDB expects db name" , database.find( '.' ) == string::npos ); + scoped_lock l( _lock ); + _databases.erase( database ); + + } + + bool Grid::allowLocalHost() const { + return _allowLocalShard; + } + + void Grid::setAllowLocalHost( bool allow ){ + _allowLocalShard = allow; + } + + bool Grid::addShard( string* name , const string& host , long long maxSize , string* errMsg ){ + // errMsg is required but name is optional + DEV assert( errMsg ); + string nameInternal; + if ( ! name ) { + name = &nameInternal; + } + + // check whether host exists and is operative + try { + ScopedDbConnection newShardConn( host ); + newShardConn->getLastError(); + newShardConn.done(); + } + catch ( DBException& e ){ + ostringstream ss; + ss << "couldn't connect to new shard "; + ss << e.what(); + *errMsg = ss.str(); + return false; + } + + // if a name for a shard wasn't provided, pick one. + if ( name->empty() && ! _getNewShardName( name ) ){ + *errMsg = "error generating new shard name"; + return false; + } + + // build the ConfigDB shard document. + BSONObjBuilder b; + b.append( "_id" , *name ); + b.append( "host" , host ); + if ( maxSize > 0 ){ + b.append( ShardFields::maxSize.name() , maxSize ); + } + BSONObj shardDoc = b.obj(); + + { + ScopedDbConnection conn( configServer.getPrimary() ); + + // check whether this host:port is already a known shard + BSONObj old = conn->findOne( ShardNS::shard , BSON( "host" << host ) ); + if ( ! old.isEmpty() ){ + *errMsg = "host already used"; + conn.done(); + return false; + } + + log() << "going to add shard: " << shardDoc << endl; + + conn->insert( ShardNS::shard , shardDoc ); + *errMsg = conn->getLastError(); + if ( ! errMsg->empty() ){ + log() << "error adding shard: " << shardDoc << " err: " << *errMsg << endl; + return false; + } + + conn.done(); + } + + Shard::reloadShardInfo(); + return true; + } + + bool Grid::knowAboutShard( const string& name ) const{ + ShardConnection conn( configServer.getPrimary() , "" ); + BSONObj shard = conn->findOne( ShardNS::shard , BSON( "host" << name ) ); + conn.done(); + return ! shard.isEmpty(); + } + + bool Grid::_getNewShardName( string* name ) const{ + DEV assert( name ); + + bool ok = false; + int count = 0; + + ShardConnection conn( configServer.getPrimary() , "" ); + BSONObj o = conn->findOne( ShardNS::shard , Query( fromjson ( "{_id: /^shard/}" ) ).sort( BSON( "_id" << -1 ) ) ); + if ( ! o.isEmpty() ) { + string last = o["_id"].String(); + istringstream is( last.substr( 5 ) ); + is >> count; + count++; + } + if (count < 9999) { + stringstream ss; + ss << "shard" << setfill('0') << setw(4) << count; + *name = ss.str(); + ok = true; + } + conn.done(); + + return ok; + } + + bool Grid::shouldBalance() const { + ShardConnection conn( configServer.getPrimary() , "" ); + + // look for the stop balancer marker + BSONObj stopMarker = conn->findOne( ShardNS::settings, BSON( "_id" << "balancer" << "stopped" << true ) ); + conn.done(); + return stopMarker.isEmpty(); + } + + unsigned long long Grid::getNextOpTime() const { + ScopedDbConnection conn( configServer.getPrimary() ); + + BSONObj result; + massert( 10421 , "getoptime failed" , conn->simpleCommand( "admin" , &result , "getoptime" ) ); + conn.done(); + + return result["optime"]._numberLong(); + } + + Grid grid; + +} diff --git a/s/grid.h b/s/grid.h new file mode 100644 index 00000000000..2ebe60e3761 --- /dev/null +++ b/s/grid.h @@ -0,0 +1,103 @@ +// grid.h + +/** +* Copyright (C) 2010 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 <http://www.gnu.org/licenses/>. +*/ + +#pragma once + +#include "pch.h" + +#include "../util/concurrency/mutex.h" + +#include "config.h" // DBConfigPtr + +namespace mongo { + + /** + * stores meta-information about the grid + * TODO: used shard_ptr for DBConfig pointers + */ + class Grid { + public: + Grid() : _lock( "Grid" ) , _allowLocalShard( true ) { } + + /** + * gets the config the db. + * will return an empty DBConfig if not in db already + */ + DBConfigPtr getDBConfig( string ns , bool create=true ); + + /** + * removes db entry. + * on next getDBConfig call will fetch from db + */ + void removeDB( string db ); + + /** + * @return true if shards and config servers are allowed to use 'localhost' in address + */ + bool allowLocalHost() const; + + /** + * @param whether to allow shards and config servers to use 'localhost' in address + */ + void setAllowLocalHost( bool allow ); + + /** + * + * addShard will create a new shard in the grid. It expects a mongod process to be runing + * on the provided address. + * TODO - add the mongod's databases to the grid + * + * @param name is an optional string with the name of the shard. if ommited, grid will + * generate one and update the parameter. + * @param host is the complete address of the machine where the shard will be + * @param maxSize is the optional space quota in bytes. Zeros means there's no limitation to + * space usage + * @param errMsg is the error description in case the operation failed. + * @return true if shard was successfully added. + */ + bool addShard( string* name , const string& host , long long maxSize , string* errMsg ); + + /** + * @return true if the config database knows about a host 'name' + */ + bool knowAboutShard( const string& name ) const; + + /** + * @return true if the chunk balancing functionality is enabled + */ + bool shouldBalance() const; + + unsigned long long getNextOpTime() const; + + private: + mongo::mutex _lock; // protects _databases; TODO: change to r/w lock ?? + map<string, DBConfigPtr > _databases; // maps ns to DBConfig's + bool _allowLocalShard; // can 'localhost' be used in shard addresses? + + /** + * @param name is the chose name for the shard. Parameter is mandatory. + * @return true if it managed to generate a shard name. May return false if (currently) + * 10000 shard + */ + bool _getNewShardName( string* name ) const; + + }; + + extern Grid grid; + +} // namespace mongo diff --git a/s/request.cpp b/s/request.cpp index f8877573854..e65aa1532f0 100644 --- a/s/request.cpp +++ b/s/request.cpp @@ -33,6 +33,7 @@ #include "chunk.h" #include "stats.h" #include "cursors.h" +#include "grid.h" namespace mongo { diff --git a/s/server.cpp b/s/server.cpp index 0c78618aaea..df6b082d335 100644 --- a/s/server.cpp +++ b/s/server.cpp @@ -30,6 +30,7 @@ #include "config.h" #include "chunk.h" #include "balance.h" +#include "grid.h" namespace mongo { diff --git a/s/strategy.cpp b/s/strategy.cpp index b32ecb5c242..b3c8f5b3b5c 100644 --- a/s/strategy.cpp +++ b/s/strategy.cpp @@ -21,7 +21,9 @@ #include "../util/background.h" #include "../client/connpool.h" #include "../db/commands.h" + #include "server.h" +#include "grid.h" namespace mongo { |