0
0
mirror of https://github.com/mongodb/mongo.git synced 2024-11-30 00:56:44 +01:00

SERVER-2060 allow an index to be validated for sharding

This commit is contained in:
Alberto Lerner 2011-01-10 09:12:34 -08:00
parent 3907c971ee
commit 95883498e5
2 changed files with 114 additions and 0 deletions

View File

@ -0,0 +1,40 @@
// -------------------------
// CHECKSHARDINGINDEX TEST UTILS
// -------------------------
f = db.jstests_shardingindex;
f.drop();
// -------------------------
// Case 1: all entries filled or empty should make a valid index
//
f.drop();
f.ensureIndex( { x: 1 , y: 1 } );
assert.eq( 0 , f.count() , "1. initial count should be zero" );
res = db.runCommand( { checkShardingIndex: "test.jstests_shardingindex" , keyPattern: {x:1, y:1} , force: true });
assert.eq( true , res.ok, "1a" );
f.save( { x: 1 , y : 1 } );
assert.eq( 1 , f.count() , "1. count after initial insert should be 1" );
res = db.runCommand( { checkShardingIndex: "test.jstests_shardingindex" , keyPattern: {x:1, y:1} , force: true });
assert.eq( true , res.ok , "1b" );
// -------------------------
// Case 2: entry with null values would make an index unsuitable
//
f.drop();
f.ensureIndex( { x: 1 , y: 1 } );
assert.eq( 0 , f.count() , "2. initial count should be zero" );
f.save( { x: 1 , y : 1 } );
f.save( { y: 2 } );
assert.eq( 2 , f.count() , "2. count after initial insert should be 2" );
res = db.runCommand( { checkShardingIndex: "test.jstests_shardingindex" , keyPattern: {x:1, y:1} , force: true });
assert.eq( false , res.ok , "2a" );
print("PASSED");

View File

@ -124,6 +124,80 @@ namespace mongo {
}
} cmdMedianKey;
class CheckShardingIndex : public Command {
public:
CheckShardingIndex() : Command( "checkShardingIndex" , false ) {}
virtual bool slaveOk() const { return false; }
virtual LockType locktype() const { return READ; }
virtual void help( stringstream &help ) const {
help << "Internal command.\n";
}
bool run(const string& dbname, BSONObj& jsobj, string& errmsg, BSONObjBuilder& result, bool fromRepl ) {
const char* ns = jsobj.getStringField( "checkShardingIndex" );
BSONObj keyPattern = jsobj.getObjectField( "keyPattern" );
// If min and max are not provided use the "minKey" and "maxKey" for the sharding key pattern.
BSONObj min = jsobj.getObjectField( "min" );
BSONObj max = jsobj.getObjectField( "max" );
if ( min.isEmpty() && max.isEmpty() ) {
BSONObjBuilder minBuilder;
BSONObjBuilder maxBuilder;
BSONForEach(key, keyPattern) {
minBuilder.appendMinKey( key.fieldName() );
maxBuilder.appendMaxKey( key.fieldName() );
}
min = minBuilder.obj();
max = maxBuilder.obj();
}
else if ( min.isEmpty() || max.isEmpty() ) {
errmsg = "either provide both min and max or leave both empty";
return false;
}
Client::Context ctx( ns );
NamespaceDetails *d = nsdetails( ns );
if ( ! d ) {
errmsg = "ns not found";
return false;
}
IndexDetails *idx = cmdIndexDetailsForRange( ns , errmsg , min , max , keyPattern );
if ( idx == NULL ) {
errmsg = "couldn't find index over splitting key";
return false;
}
BtreeCursor * bc = new BtreeCursor( d , d->idxNo(*idx) , *idx , min , max , false , 1 );
shared_ptr<Cursor> c( bc );
scoped_ptr<ClientCursor> cc( new ClientCursor( QueryOption_NoCursorTimeout , c , ns ) );
if ( ! cc->ok() ) {
// range is empty
return true;
}
// for now, the only check is that all shard keys are filled
// TODO if $exist for nulls were picking the index, it could be used instead efficiently
while ( cc->ok() ) {
BSONObj currKey = c->currKey();
BSONForEach(key, currKey) {
if ( key.type() == jstNULL ) {
ostringstream os;
os << "found null value in key " << bc->prettyKey( currKey );
log() << "checkShardingIndex for '" << ns << "' failed: " << os.str() << endl;
errmsg = os.str();
return false;
}
}
cc->advance();
}
return true;
}
} cmdCheckShardingIndex;
class SplitVector : public Command {
public:
SplitVector() : Command( "splitVector" , false ) {}