2008-11-09 23:49:37 +01:00
|
|
|
// shard.cpp
|
2008-09-15 15:14:42 +02:00
|
|
|
|
|
|
|
/**
|
2009-02-18 16:10:39 +01:00
|
|
|
* 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 <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
2008-09-15 15:14:42 +02:00
|
|
|
|
|
|
|
#include "stdafx.h"
|
2008-11-09 23:49:37 +01:00
|
|
|
#include "shard.h"
|
2009-02-13 03:09:06 +01:00
|
|
|
#include "config.h"
|
2009-02-18 16:10:39 +01:00
|
|
|
#include "../util/unittest.h"
|
2009-02-26 18:01:24 +01:00
|
|
|
#include "../client/connpool.h"
|
2008-09-15 15:14:42 +02:00
|
|
|
|
2009-01-14 23:09:51 +01:00
|
|
|
namespace mongo {
|
2009-02-18 05:31:27 +01:00
|
|
|
|
|
|
|
// ------- Shard --------
|
2009-02-03 23:10:44 +01:00
|
|
|
|
2009-02-26 18:01:24 +01:00
|
|
|
Shard::Shard( ShardManager * manager ) : _manager( manager ){
|
2009-02-20 19:46:57 +01:00
|
|
|
_modified = false;
|
2009-02-18 05:31:27 +01:00
|
|
|
}
|
|
|
|
|
2009-02-20 19:46:57 +01:00
|
|
|
void Shard::setServer( string s ){
|
|
|
|
_server = s;
|
|
|
|
_modified = true;
|
2009-01-15 16:17:11 +01:00
|
|
|
}
|
2009-02-26 18:01:24 +01:00
|
|
|
|
2009-02-18 05:31:27 +01:00
|
|
|
bool Shard::contains( const BSONObj& obj ){
|
|
|
|
return
|
2009-02-26 18:01:24 +01:00
|
|
|
_manager->getShardKey().compare( getMin() , obj ) <= 0 &&
|
|
|
|
_manager->getShardKey().compare( obj , getMax() ) < 0;
|
2009-02-18 05:31:27 +01:00
|
|
|
}
|
|
|
|
|
2009-02-26 18:01:24 +01:00
|
|
|
Shard * Shard::split(){
|
|
|
|
return split( _manager->getShardKey().middle( getMin() , getMax() ) );
|
2009-02-19 23:32:19 +01:00
|
|
|
}
|
2009-02-18 05:31:27 +01:00
|
|
|
|
2009-02-26 18:01:24 +01:00
|
|
|
Shard * Shard::split( const BSONObj& m ){
|
|
|
|
uassert( "can't split as shard that doesn't have a manager" , _manager );
|
|
|
|
|
|
|
|
Shard * s = new Shard( _manager );
|
|
|
|
s->_ns = _ns;
|
|
|
|
s->_server = _server;
|
|
|
|
s->_min = m.getOwned();
|
|
|
|
s->_max = _max;
|
|
|
|
|
|
|
|
s->_modified = true;
|
|
|
|
_modified = true;
|
2009-02-18 05:31:27 +01:00
|
|
|
|
2009-02-26 18:01:24 +01:00
|
|
|
_manager->_shards.push_back( s );
|
|
|
|
|
|
|
|
_max = m.getOwned();
|
|
|
|
|
|
|
|
return s;
|
2009-02-18 05:31:27 +01:00
|
|
|
}
|
2009-02-26 18:01:24 +01:00
|
|
|
|
2009-02-18 05:31:27 +01:00
|
|
|
bool Shard::operator==( const Shard& s ){
|
|
|
|
return
|
2009-02-26 18:01:24 +01:00
|
|
|
_manager->getShardKey().compare( _min , s._min ) == 0 &&
|
|
|
|
_manager->getShardKey().compare( _max , s._max ) == 0
|
2009-02-18 05:31:27 +01:00
|
|
|
;
|
|
|
|
}
|
|
|
|
|
2009-02-20 19:46:57 +01:00
|
|
|
void Shard::getFilter( BSONObjBuilder& b ){
|
2009-02-26 18:01:24 +01:00
|
|
|
_manager->_key.getFilter( b , _min , _max );
|
2009-02-20 19:46:57 +01:00
|
|
|
}
|
|
|
|
|
2009-02-26 18:01:24 +01:00
|
|
|
void Shard::serialize(BSONObjBuilder& to){
|
|
|
|
to << "ns" << _ns;
|
|
|
|
to << "min" << _min;
|
|
|
|
to << "max" << _max;
|
|
|
|
to << "server" << _server;
|
|
|
|
}
|
|
|
|
|
2009-02-27 16:37:13 +01:00
|
|
|
void Shard::unserialize(const BSONObj& from){
|
2009-02-26 18:01:24 +01:00
|
|
|
_ns = from.getStringField( "ns" );
|
|
|
|
_min = from.getObjectField( "min" ).getOwned();
|
|
|
|
_max = from.getObjectField( "max" ).getOwned();
|
|
|
|
_server = from.getStringField( "server" );
|
|
|
|
|
|
|
|
uassert( "Shard needs a ns" , ! _ns.empty() );
|
|
|
|
uassert( "Shard needs a server" , ! _ns.empty() );
|
2009-02-20 19:46:57 +01:00
|
|
|
|
2009-02-26 18:01:24 +01:00
|
|
|
uassert( "Shard needs a min" , ! _min.isEmpty() );
|
|
|
|
uassert( "Shard needs a max" , ! _max.isEmpty() );
|
|
|
|
}
|
|
|
|
|
|
|
|
string Shard::modelServer() {
|
|
|
|
// TODO: this could move around?
|
|
|
|
return configServer.modelServer();
|
2009-02-20 19:46:57 +01:00
|
|
|
}
|
2009-02-18 05:31:27 +01:00
|
|
|
|
|
|
|
string Shard::toString() const {
|
2009-02-26 18:01:24 +01:00
|
|
|
stringstream ss;
|
|
|
|
ss << "shard ns:" << _ns << " server: " << _server << " min: " << _min << " max: " << _max;
|
|
|
|
return ss.str();
|
2009-02-18 05:31:27 +01:00
|
|
|
}
|
2009-02-26 18:01:24 +01:00
|
|
|
|
|
|
|
// ------- ShardManager --------
|
|
|
|
|
|
|
|
ShardManager::ShardManager( DBConfig * config , string ns , ShardKeyPattern pattern ) : _config( config ) , _ns( ns ) , _key( pattern ){
|
|
|
|
Shard temp(0);
|
|
|
|
|
|
|
|
ScopedDbConnection conn( temp.modelServer() );
|
|
|
|
auto_ptr<DBClientCursor> cursor = conn->query( temp.getNS() , BSON( "ns" << ns ) );
|
|
|
|
while ( cursor->more() ){
|
|
|
|
Shard * s = new Shard( this );
|
|
|
|
BSONObj d = cursor->next();
|
|
|
|
s->unserialize( d );
|
|
|
|
_shards.push_back( s );
|
|
|
|
}
|
|
|
|
conn.done();
|
|
|
|
|
|
|
|
if ( _shards.size() == 0 ){
|
|
|
|
Shard * s = new Shard( this );
|
|
|
|
s->_ns = ns;
|
|
|
|
s->_min = _key.globalMin();
|
|
|
|
s->_max = _key.globalMax();
|
|
|
|
s->_server = config->getPrimary();
|
|
|
|
s->_modified = true;
|
2009-02-18 05:31:27 +01:00
|
|
|
|
2009-02-26 18:01:24 +01:00
|
|
|
_shards.push_back( s );
|
2009-02-18 05:31:27 +01:00
|
|
|
|
2009-02-26 18:01:24 +01:00
|
|
|
log() << "no shards for:" << ns << " so creating first: " << s->toString() << endl;
|
|
|
|
}
|
2009-02-18 05:31:27 +01:00
|
|
|
}
|
2009-02-26 18:01:24 +01:00
|
|
|
|
|
|
|
ShardManager::~ShardManager(){
|
2009-02-18 05:31:27 +01:00
|
|
|
for ( vector<Shard*>::iterator i=_shards.begin(); i != _shards.end(); i++ ){
|
|
|
|
delete( *i );
|
|
|
|
}
|
|
|
|
_shards.clear();
|
|
|
|
}
|
|
|
|
|
2009-02-26 18:01:24 +01:00
|
|
|
bool ShardManager::hasShardKey( const BSONObj& obj ){
|
2009-02-20 16:46:42 +01:00
|
|
|
return _key.hasShardKey( obj );
|
|
|
|
}
|
|
|
|
|
2009-02-26 18:01:24 +01:00
|
|
|
Shard& ShardManager::findShard( const BSONObj & obj ){
|
|
|
|
|
2009-02-18 05:31:27 +01:00
|
|
|
for ( vector<Shard*>::iterator i=_shards.begin(); i != _shards.end(); i++ ){
|
|
|
|
Shard * s = *i;
|
|
|
|
if ( s->contains( obj ) )
|
|
|
|
return *s;
|
|
|
|
}
|
|
|
|
throw UserException( "couldn't find a shard which should be impossible" );
|
|
|
|
}
|
2009-02-22 05:39:41 +01:00
|
|
|
|
2009-02-26 18:01:24 +01:00
|
|
|
int ShardManager::getShardsForQuery( vector<Shard*>& shards , const BSONObj& query ){
|
2009-02-22 05:39:41 +01:00
|
|
|
int added = 0;
|
|
|
|
|
|
|
|
for ( vector<Shard*>::iterator i=_shards.begin(); i != _shards.end(); i++ ){
|
|
|
|
Shard* s = *i;
|
|
|
|
if ( _key.relevantForQuery( query , s ) ){
|
|
|
|
shards.push_back( s );
|
|
|
|
added++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return added;
|
|
|
|
}
|
2009-02-17 20:41:31 +01:00
|
|
|
|
2009-02-26 18:01:24 +01:00
|
|
|
void ShardManager::save(){
|
|
|
|
for ( vector<Shard*>::const_iterator i=_shards.begin(); i!=_shards.end(); i++ ){
|
|
|
|
Shard* s = *i;
|
|
|
|
if ( ! s->_modified )
|
|
|
|
continue;
|
|
|
|
s->save( true );
|
2009-02-17 21:34:52 +01:00
|
|
|
}
|
|
|
|
}
|
2009-02-19 18:55:01 +01:00
|
|
|
|
2009-02-26 18:01:24 +01:00
|
|
|
string ShardManager::toString() const {
|
2009-02-18 05:31:27 +01:00
|
|
|
stringstream ss;
|
2009-02-26 18:01:24 +01:00
|
|
|
ss << "ShardManager: " << _ns << " key:" << _key.toString() << "\n";
|
2009-02-18 05:31:27 +01:00
|
|
|
for ( vector<Shard*>::const_iterator i=_shards.begin(); i!=_shards.end(); i++ ){
|
|
|
|
const Shard* s = *i;
|
|
|
|
ss << "\t" << s->toString() << "\n";
|
|
|
|
}
|
|
|
|
return ss.str();
|
|
|
|
}
|
2009-02-26 18:01:24 +01:00
|
|
|
|
2009-02-18 16:10:39 +01:00
|
|
|
|
|
|
|
class ShardObjUnitTest : public UnitTest {
|
|
|
|
public:
|
2009-02-26 18:01:24 +01:00
|
|
|
void runShard(){
|
|
|
|
Shard s(0);
|
2009-02-18 16:10:39 +01:00
|
|
|
{
|
2009-02-26 18:01:24 +01:00
|
|
|
BSONObj a = BSON( "ns" << "a.fs.chunks" <<
|
|
|
|
"min" << BSON( "num" << 0 ) <<
|
|
|
|
"max" << BSON( "num" << 100 ) <<
|
|
|
|
"server" << "localhost:30000" );
|
|
|
|
s.unserialize( a );
|
2009-02-18 16:10:39 +01:00
|
|
|
|
2009-02-26 18:01:24 +01:00
|
|
|
BSONObjBuilder b;
|
|
|
|
s.serialize( b );
|
2009-02-18 16:10:39 +01:00
|
|
|
|
2009-02-26 18:01:24 +01:00
|
|
|
assert( a.toString() == b.obj().toString() );
|
2009-02-18 16:10:39 +01:00
|
|
|
}
|
2009-02-18 05:31:27 +01:00
|
|
|
|
2009-02-26 18:01:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void run(){
|
|
|
|
runShard();
|
2009-02-18 16:10:39 +01:00
|
|
|
log(1) << "shardObjTest passed" << endl;
|
|
|
|
}
|
|
|
|
} shardObjTest;
|
2009-02-18 05:31:27 +01:00
|
|
|
|
2009-01-14 23:09:51 +01:00
|
|
|
|
|
|
|
} // namespace mongo
|