diff options
-rw-r--r-- | jstests/replsets/oplog_wallclock.js | 29 | ||||
-rw-r--r-- | src/mongo/db/repl/oplog.cpp | 25 | ||||
-rw-r--r-- | src/mongo/db/repl/oplog_entry.idl | 4 |
3 files changed, 53 insertions, 5 deletions
diff --git a/jstests/replsets/oplog_wallclock.js b/jstests/replsets/oplog_wallclock.js new file mode 100644 index 00000000000..899586b6561 --- /dev/null +++ b/jstests/replsets/oplog_wallclock.js @@ -0,0 +1,29 @@ +// oplog should contain the field "wt" with wallClock timestamps. +(function() { + 'use strict'; + load('jstests/replsets/rslib.js'); + + var assertLastOplogHasWT = function(primary, msg) { + const opLogEntry = getLatestOp(primary); + assert(opLogEntry.hasOwnProperty('wt'), + 'oplog entry must contain wt field: ' + tojson(opLogEntry)); + }; + + var name = 'wt_test_coll'; + var replSet = new ReplSetTest({nodes: 1, oplogSize: 2, nodeOptions: {smallfiles: ''}}); + replSet.startSet(); + replSet.initiate(); + + var primary = replSet.getPrimary(); + var collection = primary.getDB('test').getCollection(name); + + assert.writeOK(collection.insert({_id: 1, val: 'x'})); + assertLastOplogHasWT(primary, 'insert'); + + assert.writeOK(collection.update({_id: 1}, {val: 'y'})); + assertLastOplogHasWT(primary, 'update'); + + assert.writeOK(collection.remove({_id: 1})); + assertLastOplogHasWT(primary, 'remove'); + +})(); diff --git a/src/mongo/db/repl/oplog.cpp b/src/mongo/db/repl/oplog.cpp index 1f0b37d2008..bf69d4e02bd 100644 --- a/src/mongo/db/repl/oplog.cpp +++ b/src/mongo/db/repl/oplog.cpp @@ -257,7 +257,8 @@ OplogDocWriter _logOpWriter(OperationContext* opCtx, const BSONObj* o2, bool fromMigrate, OpTime optime, - long long hashNew) { + long long hashNew, + Date_t wallTime) { BSONObjBuilder b(256); b.append("ts", optime.getTimestamp()); @@ -274,6 +275,10 @@ OplogDocWriter _logOpWriter(OperationContext* opCtx, if (o2) b.append("o2", *o2); + if (wallTime != Date_t{}) { + b.appendDate("wt", wallTime); + } + return OplogDocWriter(OplogDocWriter(b.obj(), obj)); } } // end anon namespace @@ -388,8 +393,9 @@ OpTime logOp(OperationContext* opCtx, auto replMode = replCoord->getReplicationMode(); OplogSlot slot; getNextOpTime(opCtx, oplog, replCoord, replMode, 1, &slot); - auto writer = - _logOpWriter(opCtx, opstr, nss, uuid, obj, o2, fromMigrate, slot.opTime, slot.hash); + + auto writer = _logOpWriter( + opCtx, opstr, nss, uuid, obj, o2, fromMigrate, slot.opTime, slot.hash, Date_t::now()); const DocWriter* basePtr = &writer; _logOpsInner(opCtx, nss, &basePtr, 1, oplog, replMode, slot.opTime); return slot.opTime; @@ -418,9 +424,18 @@ void logOps(OperationContext* opCtx, std::unique_ptr<OplogSlot[]> slots(new OplogSlot[count]); auto replMode = replCoord->getReplicationMode(); getNextOpTime(opCtx, oplog, replCoord, replMode, count, slots.get()); + auto wallTime = Date_t::now(); for (size_t i = 0; i < count; i++) { - writers.emplace_back(_logOpWriter( - opCtx, opstr, nss, uuid, begin[i], NULL, fromMigrate, slots[i].opTime, slots[i].hash)); + writers.emplace_back(_logOpWriter(opCtx, + opstr, + nss, + uuid, + begin[i], + NULL, + fromMigrate, + slots[i].opTime, + slots[i].hash, + wallTime)); } std::unique_ptr<DocWriter const* []> basePtrs(new DocWriter const*[count]); diff --git a/src/mongo/db/repl/oplog_entry.idl b/src/mongo/db/repl/oplog_entry.idl index 9611613d1d8..5d2cdfbd429 100644 --- a/src/mongo/db/repl/oplog_entry.idl +++ b/src/mongo/db/repl/oplog_entry.idl @@ -95,3 +95,7 @@ structs: type: objectid optional: true description: "An optional _id field for tests that manually insert oplog entries" + wt: + type: date + optional: true # Optional for older than 3.6 releases + description: "A wallclock time with MS resolution" |