diff options
author | Greg Studer <greg@10gen.com> | 2013-12-05 13:51:02 -0500 |
---|---|---|
committer | Greg Studer <greg@10gen.com> | 2013-12-08 13:36:48 -0500 |
commit | e7f4f01001866bddd5a2d20f9f80e50c037f4fe6 (patch) | |
tree | 7b4b95588a59c9f257a1345c0609657ab911615e | |
parent | 9a1b20453b318801c344850879023427c812c047 (diff) | |
download | mongo-e7f4f01001866bddd5a2d20f9f80e50c037f4fe6.tar.gz |
SERVER-11869 support for external gle opTime for w > 1
-rw-r--r-- | jstests/replsets/gle_explicit_optime.js | 57 | ||||
-rw-r--r-- | src/mongo/db/dbcommands.cpp | 13 |
2 files changed, 67 insertions, 3 deletions
diff --git a/jstests/replsets/gle_explicit_optime.js b/jstests/replsets/gle_explicit_optime.js new file mode 100644 index 00000000000..77c526e981d --- /dev/null +++ b/jstests/replsets/gle_explicit_optime.js @@ -0,0 +1,57 @@ +// +// Tests the use of the wOpTime option in getLastError +// + +var rst = new ReplSetTest({ nodes : 2 }); +rst.startSet(); +rst.initiate(); + +var primary = rst.getPrimary(); +var secondary = rst.getSecondary(); + +var coll = primary.getCollection( "foo.bar" ); + +// Insert a doc and replicate it to two servers +coll.insert({ some : "doc" }); +var gleObj = coll.getDB().getLastErrorObj( 2 ); // w : 2 +assert.eq( null, gleObj.err ); +var opTimeBeforeFailure = gleObj.lastOp; + +// Lock the secondary +secondary.getDB("admin").fsyncLock(); + +// Insert a doc and replicate it to the primary only +coll.insert({ some : "doc" }); +gleObj = coll.getDB().getLastErrorObj( 1 ); // w : 1 +assert.eq( null, gleObj.err ); +var opTimeAfterFailure = gleObj.lastOp; + +printjson(opTimeBeforeFailure); +printjson(opTimeAfterFailure); +printjson( primary.getDB("admin").runCommand({ replSetGetStatus : true }) ); + +// Create a new connection with new client and no opTime +var newClientConn = new Mongo( primary.host ); + +// New client has no set opTime, so w : 2 has no impact +gleObj = newClientConn.getCollection( coll.toString() ).getDB().getLastErrorObj( 2 ); // w : 2 +assert.eq( null, gleObj.err ); + +// Using an explicit optime on the new client should work if the optime is earlier than the +// secondary was locked +var gleOpTimeBefore = { getLastError : true, w : 2, wOpTime : opTimeBeforeFailure }; +gleObj = newClientConn.getCollection( coll.toString() ).getDB().runCommand( gleOpTimeBefore ); +assert.eq( null, gleObj.err ); + +// Using an explicit optime on the new client should not work if the optime is later than the +// secondary was locked +var gleOpTimeAfter = { getLastError : true, w : 2, wtimeout : 1000, wOpTime : opTimeAfterFailure }; +gleObj = newClientConn.getCollection( coll.toString() ).getDB().runCommand( gleOpTimeAfter ); +assert.neq( null, gleObj.err ); +assert( gleObj.wtimeout ); + +jsTest.log("DONE!"); + +// Unlock the secondary +secondary.getDB("admin").fsyncUnlock(); +rst.stopSet(); diff --git a/src/mongo/db/dbcommands.cpp b/src/mongo/db/dbcommands.cpp index 8b8252f68a6..fb6be132171 100644 --- a/src/mongo/db/dbcommands.cpp +++ b/src/mongo/db/dbcommands.cpp @@ -178,9 +178,9 @@ namespace mongo { } } - if ( err ) { + if ( err && cmdObj["wOpTime"].eoo() ) { // doesn't make sense to wait for replication - // if there was an error + // if there was an error and we aren't explicitly waiting for another wOpTime return true; } @@ -200,7 +200,14 @@ namespace mongo { long long passes = 0; char buf[32]; - OpTime op(c.getLastOp()); + + OpTime op; + if ( cmdObj["wOpTime"].type() == Timestamp ) { + op = OpTime( cmdObj["wOpTime"].date() ); + } + else { + op = c.getLastOp(); + } if ( op.isNull() ) { if ( anyReplEnabled() ) { |