0
0
mirror of https://github.com/mongodb/mongo.git synced 2024-12-01 09:32:32 +01:00
This commit is contained in:
Aaron 2009-03-11 18:47:16 -04:00
parent 2f5201c7e7
commit 26be29395e
4 changed files with 75 additions and 33 deletions

View File

@ -269,7 +269,6 @@ namespace mongo {
string logNS = "local.temp.oplog." + string( ns );
c = conn->query( logNS.c_str(), Query(), 0, 0, 0, Option_CursorTailable );
}
cout << "start cursorId: " << c->getCursorId() << endl;
if ( c->more() ) {
replayOpLog( c.get(), query );
cursorId = c->getCursorId();
@ -278,7 +277,6 @@ namespace mongo {
massert( "Did not expect valid cursor for empty query result", c->getCursorId() == 0 );
cursorId = 0;
}
cout << "set cursorId: " << cursorId << endl;
c->decouple();
return true;
}
@ -304,8 +302,6 @@ namespace mongo {
char db[256];
nsToClient( ns, db );
cout << "using cursorId: " << cursorId << endl;
auto_ptr< DBClientCursor > cur;
{
dbtemprelease r;
@ -360,6 +356,49 @@ namespace mongo {
}
} cmdclone;
class CmdCloneCollection : public Command {
public:
virtual bool slaveOk() {
return false;
}
CmdCloneCollection() : Command("cloneCollection") { }
virtual void help( stringstream &help ) const {
help << " example: { cloneCollection: <collection ns>, from: <hostname>, query: <query> }";
}
virtual bool run(const char *ns, BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
string fromhost = cmdObj.getStringField("from");
if ( fromhost.empty() ) {
errmsg = "missing from spec";
return false;
}
string collection = cmdObj.getStringField("cloneCollection");
if ( collection.empty() ) {
errmsg = "missing cloneCollection spec";
return false;
}
BSONObj query = cmdObj.getObjectField("query");
if ( query.isEmpty() )
query = emptyObj;
BSONElement copyIndexesSpec = cmdObj.getField("copyindexes");
bool copyIndexes = copyIndexesSpec.isBoolean() ? copyIndexesSpec.boolean() : true;
// Will not be used if doesn't exist.
int logSizeMb = cmdObj.getIntField( "logSizeMb" );
/* replication note: we must logOp() not the command, but the cloned data -- if the slave
were to clone it would get a different point-in-time and not match.
*/
setClient( collection.c_str() );
log() << "cloneCollection. db:" << ns << " collection:" << collection << " from: " << fromhost << " query: " << query << endl;
Cloner c;
long long cursorId;
if ( !c.startCloneCollection( fromhost.c_str(), collection.c_str(), query, errmsg, !fromRepl, copyIndexes, logSizeMb, cursorId ) )
return false;
return c.finishCloneCollection( fromhost.c_str(), collection.c_str(), query, cursorId, errmsg);
}
} cmdclonecollection;
class CmdStartCloneCollection : public Command {
public:
virtual bool slaveOk() {
@ -407,7 +446,6 @@ namespace mongo {
b << "query" << query;
b.appendDate( "cursorId", cursorId );
BSONObj token = b.done();
log() << "returning token: " << token << endl;
result << "finishToken" << token;
}
return res;
@ -429,7 +467,6 @@ namespace mongo {
errmsg = "missing finishCloneCollection finishToken spec";
return false;
}
cout << "fromToken: " << fromToken.toString() << endl;
string fromhost = fromToken.getStringField( "fromhost" );
if ( fromhost.empty() ) {
errmsg = "missing fromhost spec";
@ -446,16 +483,9 @@ namespace mongo {
}
long long cursorId = 0;
BSONElement cursorIdToken = fromToken.getField( "cursorId" );
cout << "token type: " << cursorIdToken.type() << endl;
if ( cursorIdToken.type() == Date ) {
cout << "type date" << endl;
cursorId = cursorIdToken.date();
cout << "val: " << cursorIdToken.date() << endl;
}
// if ( cursorId == 0 ) {
// errmsg = "invalid cursorId spec";
// return false;
// }
setClient( collection.c_str() );

View File

@ -516,20 +516,17 @@ namespace mongo {
resultFlags = QueryResult::ResultFlag_CursorNotFound;
}
else {
log() << "getMore: cursorid found " << ns << " " << cursorid << endl;
start = cc->pos;
Cursor *c = cc->c.get();
c->checkLocation();
while ( 1 ) {
if ( !c->ok() ) {
cout << "tailing? : " << c->tailing() << endl;
if ( c->tailable() ) {
if ( c->advance() ) {
continue;
}
break;
}
log() << " getmore: last batch, erasing cursor " << cursorid << endl;
bool ok = ClientCursor::erase(cursorid);
assert(ok);
cursorid = 0;
@ -772,16 +769,12 @@ namespace mongo {
so_->fill(b_, filter_, n_);
}
if ( ( queryOptions_ & Option_CursorTailable ) && ntoreturn_ != 1 ) {
cout << "setting at tail" << endl;
c_->setTailable();
}
// If the tailing request succeeded.
if ( c_->tailable() ) {
saveClientCursor_ = true;
}
cout << "query complete for ns: " << qp().ns() << endl;
cout << "option tailable? : " << ( queryOptions_ & Option_CursorTailable ) << endl;
cout << "tailable? : " << c_->tailable() << endl;
setComplete();
}
virtual bool mayRecordPlan() const { return ntoreturn_ != 1; }

View File

@ -10,19 +10,19 @@ for( i = 0; i < 1000; ++i ) {
}
assert.eq( 1000, f.a.find().count() );
t.cloneCollection( "localhost:27018", "a" );
assert.eq( 1, t.cloneCollection( "localhost:27018", "a" ).ok );
assert.eq( 1000, t.a.find().count() );
t.a.drop();
t.cloneCollection( "localhost:27018", "a", { i: { $gte: 10, $lt: 20 } } );
assert.eq( 1, t.cloneCollection( "localhost:27018", "a", { i: { $gte: 10, $lt: 20 } } ).ok );
assert.eq( 10, t.a.find().count() );
t.a.drop();
assert.eq( 0, t.system.indexes.find().count() );
f.a.ensureIndex( { i: 1 } );
t.cloneCollection( "localhost:27018", "a" );
assert.eq( 1, t.cloneCollection( "localhost:27018", "a" ).ok );
assert.eq( 1, t.system.indexes.find().count() );
// Verify index works
assert.eq( 50, t.a.find( { i: 50 } ).hint( { i: 1 } ).explain().startKey.i );
@ -38,7 +38,7 @@ for( i = 0; i < 100000; ++i ) {
}
finished = false;
cc = fork( function() { t.cloneCollection( "localhost:27018", "a", {i:{$gte:0}} ); finished = true; } );
cc = fork( function() { assert.eq( 1, t.cloneCollection( "localhost:27018", "a", {i:{$gte:0}} ).ok ); finished = true; } );
cc.start();
sleep( 200 );
@ -94,3 +94,30 @@ for( i = 100000; i < 110000; ++i ) {
cc.join();
assert.eq( 110000, t.a.find().count() );
// Test startCloneCollection and finishCloneCollection commands.
f.a.drop();
t.a.drop();
for( i = 0; i < 100000; ++i ) {
f.a.save( { i: i } );
}
cc = fork( function() { return t.runCommand( {startCloneCollection:"jstests_clonecollection.a", from:"localhost:27018" } ); } );
cc.start();
sleep( 200 );
f.a.save( { i: -1 } );
ret = cc.returnData();
assert.eq( 1, ret.ok );
assert.eq( 100001, t.a.find().count() );
f.a.save( { i: -2 } );
finishToken = ret.finishToken;
// Round-tripping through JS can corrupt the cursor ids we store as BSON
// Date elements. Date( 0 ) will correspond to a cursorId value of 0, which
// makes the db start scanning from the beginning of the collection.
finishToken.cursorId = new Date( 0 );
assert.eq( 1, t.runCommand( {finishCloneCollection:finishToken} ).ok );
assert.eq( 100002, t.a.find().count() );

View File

@ -176,15 +176,7 @@ DB.prototype.cloneCollection = function(from, collection, query) {
collection = this._name + "." + collection;
query = query || {};
//this.resetIndexCache();
var ret = this._dbCommand( { startCloneCollection:collection, from:from, query:query } );
print( "ret:" );
printjson( ret );
if ( !ret.ok )
return ret;
var ret2 = this._dbCommand( {finishCloneCollection:ret.finishToken} );
print( "ret2:" );
printjson( ret2 );
return ret2;
return this._dbCommand( { cloneCollection:collection, from:from, query:query } );
}