void _delete( Request& r , DbMessage& d, ShardManager* manager ){ int flags = d.pullInt(); bool justOne = flags & 1; uassert( "bad delete message" , d.moreJSObjs() ); BSONObj pattern = d.nextJsObj(); if ( manager->hasShardKey( pattern ) ){ Shard& s = manager->findShard( pattern ); doWrite( dbDelete , r , s.getServer() ); return; } if ( ! justOne && ! pattern.hasField( "_id" ) ) throw UserException( "can only delete with a non-shard key pattern if can delete as many as we find" ); vector<Shard*> shards; manager->getShardsForQuery( shards , pattern ); set<string> seen; for ( vector<Shard*>::iterator i=shards.begin(); i!=shards.end(); i++){ Shard * s = *i; if ( seen.count( s->getServer() ) ) continue; seen.insert( s->getServer() ); doWrite( dbDelete , r , s->getServer() ); } }
void ShardManager::ensureIndex(){ set<string> seen; for ( vector<Shard*>::const_iterator i=_shards.begin(); i!=_shards.end(); i++ ){ Shard* s = *i; if ( seen.count( s->getServer() ) ) continue; seen.insert( s->getServer() ); s->ensureIndex(); } }
Shard* ShardManager::findShardOnServer( const string& server ) const { for ( vector<Shard*>::const_iterator i=_shards.begin(); i!=_shards.end(); i++ ){ Shard* s = *i; if ( s->getServer() == server ) return s; } return 0; }
ServerShardVersion ShardManager::getVersion( const string& server ) const{ // TODO: cache or something? ServerShardVersion max = 0; for ( vector<Shard*>::const_iterator i=_shards.begin(); i!=_shards.end(); i++ ){ Shard* s = *i; if ( s->getServer() != server ) continue; if ( s->_lastmod > max ) max = s->_lastmod; } return max; }
virtual void queryOp( Request& r ){ QueryMessage q( r.d() ); log(3) << "shard query: " << q.ns << " " << q.query << endl; if ( q.ntoreturn == 1 && strstr(q.ns, ".$cmd") ) throw UserException( "something is wrong, shouldn't see a command here" ); ShardManager * info = r.getShardManager(); assert( info ); Query query( q.query ); vector<Shard*> shards; info->getShardsForQuery( shards , query.getFilter() ); set<ServerAndQuery> servers; map<string,int> serverCounts; for ( vector<Shard*>::iterator i = shards.begin(); i != shards.end(); i++ ){ servers.insert( (*i)->getServer() ); int& num = serverCounts[(*i)->getServer()]; num++; } ShardedCursor * cursor = 0; BSONObj sort = query.getSort(); if ( sort.isEmpty() ){ // 1. no sort, can just hit them in serial cursor = new SerialServerShardedCursor( servers , q ); } else { int shardKeyOrder = info->getShardKey().canOrder( sort ); if ( shardKeyOrder ){ // 2. sort on shard key, can do in serial intelligently set<ServerAndQuery> buckets; for ( vector<Shard*>::iterator i = shards.begin(); i != shards.end(); i++ ){ Shard * s = *i; BSONObj extra = BSONObj(); if ( serverCounts[s->getServer()] > 1 ){ BSONObjBuilder b; s->getFilter( b ); extra = b.obj(); } buckets.insert( ServerAndQuery( s->getServer() , extra , s->getMin() ) ); } cursor = new SerialServerShardedCursor( buckets , q , shardKeyOrder ); } else { // 3. sort on non-sharded key, pull back a portion from each server and iterate slowly cursor = new ParallelSortShardedCursor( servers , q , sort ); } } assert( cursor ); if ( ! cursor->sendNextBatch( r ) ){ delete( cursor ); return; } log(6) << "storing cursor : " << cursor->getId() << endl; cursorCache.store( cursor ); }