diff options
author | Dianna Hohensee <dianna.hohensee@mongodb.com> | 2020-07-08 15:56:16 -0400 |
---|---|---|
committer | Dianna Hohensee <dianna.hohensee@mongodb.com> | 2020-07-09 20:37:24 -0400 |
commit | 678f6f9df2d72db7060d4fff412886298f7a97af (patch) | |
tree | df1720dccb69b87ce7890fd4598a61e15bae773a | |
parent | 1be7ba53b01be6d44e133e3e0f0ecc242628eb19 (diff) | |
download | mongo-678f6f9df2d72db7060d4fff412886298f7a97af.tar.gz |
SERVER-49366 Allow presence of 'recordPreImages' in collection metadata in standalone mode
(cherry picked from commit bf3b9a1e6d52dddbb9ed85c113d613ffbc866e13)
-rw-r--r-- | jstests/noPassthrough/recordPreImages_standalone_mode.js | 144 | ||||
-rw-r--r-- | jstests/noPassthrough/record_preimage_startup_validation.js | 9 | ||||
-rw-r--r-- | src/mongo/db/catalog/collection_impl.cpp | 6 |
3 files changed, 144 insertions, 15 deletions
diff --git a/jstests/noPassthrough/recordPreImages_standalone_mode.js b/jstests/noPassthrough/recordPreImages_standalone_mode.js new file mode 100644 index 00000000000..26d32c84e45 --- /dev/null +++ b/jstests/noPassthrough/recordPreImages_standalone_mode.js @@ -0,0 +1,144 @@ +/** + * Test that standalones are able to startup with 'recordPreImages' set in collection metadata; and + * that 'recordPreImages' is inactive in standalone mode. + * + * @tags: [ + * # Servers are restarted in this test and the data must be retained. + * requires_persistence, + * # This test uses a replica set and must avoid replica set incompatible test suites, like the + * # test suite that turns journaling off. + * requires_replication, + * ] + */ + +(function() { +'use strict'; + +/** + * Fetch the collection information on database 'nodeDB' for collection 'collName'. Expects the + * collection to exist. + */ +const findCollectionInfo = function(nodeDB, collName) { + let collInfos = nodeDB.getCollectionInfos(); + assert.gt(collInfos.length, 0, "The database is empty"); + + let collInfo = collInfos.filter(function(z) { + return z.name == collName; + }); + + assert.eq(collInfo.length, 1); + return collInfo[0]; +}; + +/** + * Prints out all of the oplog collection entries on 'node'. + */ +function printOplog(node) { + let cursor = node.getDB('local').oplog.rs.find(); + while (cursor.hasNext()) { + jsTest.log("Oplog entry: " + tojson(cursor.next())); + } +} + +/** + * A --replSet server should be able to set 'recordPreImages' on a collection and then be restarted + * in standalone mode successfully. + */ + +jsTest.log("Starting up a 1-node replica set"); + +var rst = new ReplSetTest({nodes: 1}); +rst.startSet(); +rst.initiate(); + +const dbName = 'record_preimage_standalone_mode_test_db'; +const collName = 'testColl'; +let primary = rst.getPrimary(); +let testDB = primary.getDB(dbName); +let testColl = testDB.getCollection(collName); + +jsTest.log("Creating a collection with 'recordPreImages' set to true and adding some data"); + +assert.commandWorked(testDB.runCommand({create: collName, recordPreImages: true})); +assert.eq(findCollectionInfo(testDB, collName).options.recordPreImages, true); + +assert.commandWorked(testColl.insert({a: 1, b: 1})); +assert.commandWorked(testColl.update({a: 1}, {a: 2, b: 2})); +// Ensure all of the writes make it to disk before checkpointing below. +assert.commandWorked(testColl.update({a: 2}, {a: 3, b: 3}, {writeConcern: {w: 1, j: true}})); + +jsTest.log("Forcing a checkpoint to be taken"); + +// Ensure that the standalone can recover all of the writes from the last checkpoint because +// standalone mode does not run recovery from the oplog. The last write with j:true write concern +// ensured that the data reached disk, and now fsync will checkpoint that data. +assert.commandWorked(primary.adminCommand({fsync: 1})); + +jsTest.log("Restarting the replica set member as a standalone node"); + +printOplog(primary); // Debugging aid. + +let replicaSetNodeId = rst.getNodeId(primary); +let replicaSetNodeDbpath = primary.dbpath; +jsTest.log("replicaSetNodeId: " + replicaSetNodeId + + ", replicaSetNodeDbpath: " + replicaSetNodeDbpath); + +rst.stop(replicaSetNodeId); + +let standaloneConn = MongoRunner.runMongod({ + dbpath: replicaSetNodeDbpath, + noCleanData: true, +}); + +let standaloneDB = standaloneConn.getDB(dbName); +let standaloneColl = standaloneDB.getCollection(collName); +let standaloneOplogColl = standaloneConn.getDB('local').oplog.rs; + +assert.eq(findCollectionInfo(standaloneDB, collName).options.recordPreImages, true); + +/** + * A standalone mode server should be able to do writes without triggering the 'recordPreImages' + * feature because oplog entries are not written in standalone mode: the 'recordPreImages' setting + * causes additional oplog entries to be written. + */ + +const numOplogEntriesBefore = standaloneOplogColl.find().itcount(); + +jsTest.log( + "Updating some data in the collection with 'recordPreImages' set to check that nothing " + + "happens in standalone mode"); + +assert.commandWorked(standaloneColl.insert({c: 1, d: 1})); +assert.commandWorked(standaloneColl.update({c: 1}, {c: 2, d: 2})); +assert.commandWorked(standaloneColl.update({c: 2}, {c: 3, d: 3})); + +jsTest.log( + "Checking that no oplog entries were produced for 'recordPreImages': the feature is inactive"); + +printOplog(standaloneConn); // Debugging aid. + +const numOplogEntriesAfter = standaloneOplogColl.find().itcount(); +assert.eq(numOplogEntriesBefore, numOplogEntriesAfter); + +jsTest.log("Shutting down standalone"); + +MongoRunner.stopMongod(standaloneConn); + +jsTest.log("Restarting the node as a replica set member again and doing some writes"); + +rst.start(replicaSetNodeId, {}, true /*restart*/); + +primary = rst.getPrimary(); +testDB = primary.getDB(dbName); +testColl = testDB.getCollection(collName); + +// Check that everything is still working properly after being in standalone mode. +assert.eq(findCollectionInfo(testDB, collName).options.recordPreImages, true); + +assert.commandWorked(testColl.update({a: 3}, {a: 4, b: 4})); +assert.commandWorked(testColl.update({a: 4}, {a: 5, b: 5})); + +jsTest.log("Shutting down replica set"); + +rst.stopSet(); +}()); diff --git a/jstests/noPassthrough/record_preimage_startup_validation.js b/jstests/noPassthrough/record_preimage_startup_validation.js index f9f3f16b23f..39cee347c02 100644 --- a/jstests/noPassthrough/record_preimage_startup_validation.js +++ b/jstests/noPassthrough/record_preimage_startup_validation.js @@ -8,15 +8,6 @@ 'use strict'; /** - * Test that a standalone cannot record pre-images. - */ - -let conn = MongoRunner.runMongod({}); -assert.commandFailedWithCode(conn.getDB("test").runCommand({create: "test", recordPreImages: true}), - ErrorCodes.InvalidOptions); -MongoRunner.stopMongod(conn); - -/** * Find the collection information on database 'nodeDB' for collection 'collName'. */ const findCollectionInfo = function(nodeDB, collName) { diff --git a/src/mongo/db/catalog/collection_impl.cpp b/src/mongo/db/catalog/collection_impl.cpp index 0e02b848366..5071257bef0 100644 --- a/src/mongo/db/catalog/collection_impl.cpp +++ b/src/mongo/db/catalog/collection_impl.cpp @@ -238,12 +238,6 @@ Status validatePreImageRecording(OperationContext* opCtx, const NamespaceString& "recordPreImages collection option is not supported on shards or config servers"}; } - auto replCoord = repl::ReplicationCoordinator::get(opCtx); - if (!replCoord->isReplEnabled()) { - return {ErrorCodes::InvalidOptions, - "recordPreImages collection option depends on being in a replica set"}; - } - return Status::OK(); } |