summaryrefslogtreecommitdiff
path: root/jstests/concurrency
diff options
context:
space:
mode:
authorDaniel Gottlieb <daniel.gottlieb@10gen.com>2017-01-13 13:28:29 -0500
committerDaniel Gottlieb <daniel.gottlieb@10gen.com>2017-01-13 13:28:29 -0500
commit5a4686591b4d7b4f85cf87a913b6f17ae5941ce5 (patch)
treec398300b806d56c79d5e36790be7afbcd2eb2691 /jstests/concurrency
parent5313582dae3fc0fe11d91dbbc3d2a8154de3b038 (diff)
downloadmongo-5a4686591b4d7b4f85cf87a913b6f17ae5941ce5.tar.gz
SERVER-24563 Fix race in check for DB names that differ in case only
(cherry picked from commit dceaf6bf28fb879eb23f3c022647ee3e8f15c370) Modifications for backport: src/mongo/db/catalog/database_holder.h src/mongo/db/catalog/database_holder.cpp jstests/concurrency/fsm_all_sharded_replication.js jstests/concurrency/fsm_all_sharded_replication_with_balancer.js jstests/concurrency/fsm_workloads/create_database.js
Diffstat (limited to 'jstests/concurrency')
-rw-r--r--jstests/concurrency/fsm_all_sharded_replication.js1
-rw-r--r--jstests/concurrency/fsm_all_sharded_replication_with_balancer.js1
-rw-r--r--jstests/concurrency/fsm_workloads/create_database.js140
3 files changed, 142 insertions, 0 deletions
diff --git a/jstests/concurrency/fsm_all_sharded_replication.js b/jstests/concurrency/fsm_all_sharded_replication.js
index d4068148d47..435277a2a47 100644
--- a/jstests/concurrency/fsm_all_sharded_replication.js
+++ b/jstests/concurrency/fsm_all_sharded_replication.js
@@ -9,6 +9,7 @@ var blacklist = [
'distinct.js', // SERVER-13116 distinct isn't sharding aware
'distinct_noindex.js', // SERVER-13116 distinct isn't sharding aware
'distinct_projection.js', // SERVER-13116 distinct isn't sharding aware
+ 'create_database.js', // SERVER-17397 Drops of sharded namespaces may not fully succeed
'drop_database.js', // SERVER-17397 Drops of sharded namespaces may not fully succeed
// Disabled due to SERVER-3645, '.count() can be wrong on sharded collections'.
diff --git a/jstests/concurrency/fsm_all_sharded_replication_with_balancer.js b/jstests/concurrency/fsm_all_sharded_replication_with_balancer.js
index 444f7eab3cb..59d6e0f4a61 100644
--- a/jstests/concurrency/fsm_all_sharded_replication_with_balancer.js
+++ b/jstests/concurrency/fsm_all_sharded_replication_with_balancer.js
@@ -9,6 +9,7 @@ var blacklist = [
'distinct.js', // SERVER-13116 distinct isn't sharding aware
'distinct_noindex.js', // SERVER-13116 distinct isn't sharding aware
'distinct_projection.js', // SERVER-13116 distinct isn't sharding aware
+ 'create_database.js', // SERVER-17397 Drops of sharded namespaces may not fully succeed
'drop_database.js', // SERVER-17397 Drops of sharded namespaces may not fully succeed
'remove_where.js', // SERVER-14669 Multi-removes that use $where miscount removed documents
diff --git a/jstests/concurrency/fsm_workloads/create_database.js b/jstests/concurrency/fsm_workloads/create_database.js
new file mode 100644
index 00000000000..10b619454b4
--- /dev/null
+++ b/jstests/concurrency/fsm_workloads/create_database.js
@@ -0,0 +1,140 @@
+'use strict';
+
+/**
+ * create_database.js
+ *
+ * Repeatedly creates and drops a database, with the focus on creation using different name casing.
+ * Create using all different methods, implicitly by inserting, creating views/indexes etc.
+ *
+ * Each thread uses its own database, though sometimes threads may try to create databases with
+ * names that only differ in case, expecting the appriopriate error code.
+ */
+var $config = (function() {
+
+ var data = {
+ checkCommandResult: function checkCommandResult(mayFailWithDatabaseDifferCase, res) {
+ if (mayFailWithDatabaseDifferCase && !res.ok)
+ assertAlways.commandFailedWithCode(res, ErrorCodes.DatabaseDifferCase);
+ else
+ assertAlways.commandWorked(res);
+ return res;
+ },
+
+ checkWriteResult: function checkWriteResult(mayFailWithDatabaseDifferCase, res) {
+ if (mayFailWithDatabaseDifferCase && res.hasWriteError()) {
+ assertAlways.eq(res.getWriteError().code, ErrorCodes.DatabaseDifferCase);
+ } else
+ assertAlways.writeOK(res);
+ return res;
+ }
+ };
+
+ var states = (function() {
+ function init(db, collName) {
+ var uniqueNr = this.tid;
+ var semiUniqueNr = Math.floor(uniqueNr / 2);
+
+ // The semiUniqueDBName may clash and result in a DatabaseDifferCas error on
+ // creation,
+ // while the uniqueDBName does not clash. The unique and created variables track
+ // this.
+ this.semiUniqueDBName =
+ (this.tid % 2 ? 'create_database' : 'CREATE_DATABASE') + semiUniqueNr;
+ this.uniqueDBName = 'CreateDatabase' + uniqueNr;
+ this.myDB = db.getSiblingDB(this.uniqueDBName);
+ this.created = false;
+ this.unique = true;
+ }
+
+ function useSemiUniqueDBName(db, collName) {
+ this.myDB = db.getSiblingDB(this.semiUniqueDBName);
+ this.unique = false;
+ }
+
+ function createCollection(db, collName) {
+ this.created =
+ this.checkCommandResult(!this.unique, this.myDB.createCollection(collName)).ok;
+ }
+
+ function createIndex(db, collName) {
+ var background = Math.random > 0.5;
+ var res = this.myDB.getCollection(collName).createIndex({x: 1}, {background});
+ this.created |=
+ this.checkCommandResult(!this.unique, res).createdCollectionAutomatically;
+ }
+
+ function insert(db, collName) {
+ this.created |= this.checkWriteResult(!this.created && !this.unique,
+ this.myDB.getCollection(collName).insert({x: 1}))
+ .nInserted == 1;
+ }
+
+ function upsert(db, collName) {
+ this.created |= this.checkWriteResult(!this.created && !this.unique,
+ this.myDB.getCollection(collName).update(
+ {x: 1}, {x: 2}, {upsert: 1})).nUpserted == 1;
+ }
+
+ function drop(db, collName) {
+ if (this.created)
+ assertAlways(this.myDB.getCollection(collName).drop());
+ }
+
+ function dropDatabase(db, collName) {
+ if (this.created)
+ assertAlways.commandWorked(this.myDB.dropDatabase());
+ }
+
+ function listDatabases(db, collName) {
+ for (var database of db.adminCommand({listDatabases: 1}).databases) {
+ var res = db.getSiblingDB(database.name).runCommand({listCollections: 1});
+ assertAlways.commandWorked(res);
+ assertAlways.neq(database.name, this.myDB.toString(), "this DB shouldn't exist");
+ }
+ }
+
+ return {
+ init: init,
+ useSemiUniqueDBName: useSemiUniqueDBName,
+ createCollection: createCollection,
+ createIndex: createIndex,
+ insert: insert,
+ upsert: upsert,
+ drop: drop,
+ dropDatabase: dropDatabase,
+ listDatabases: listDatabases,
+ };
+ })();
+
+ var transitions = {
+ init: {
+ useSemiUniqueDBName: 0.25,
+ createCollection: 0.375,
+ createIndex: 0.125,
+ insert: 0.125,
+ upsert: 0.125
+ },
+ useSemiUniqueDBName: {createCollection: 1.00},
+ createCollection: {dropDatabase: 0.25, createIndex: 0.25, insert: 0.25, upsert: 0.25},
+ createIndex: {insert: 0.25, upsert: 0.25, dropDatabase: 0.5},
+ insert: {dropDatabase: 0.2, drop: 0.05, insert: 0.5, upsert: 0.25},
+ upsert: {dropDatabase: 0.2, drop: 0.05, insert: 0.25, upsert: 0.5},
+ drop: {dropDatabase: 0.75, init: 0.25}, // OK to leave the empty database behind sometimes
+ dropDatabase: {init: 0.75, listDatabases: 0.25},
+ listDatabases: {init: 0.75, listDatabases: 0.25},
+ };
+
+ return {
+ data: data,
+ // We only run a few iterations to reduce the amount of data cumulatively
+ // written to disk by mmapv1. For example, setting 10 threads and 180
+ // iterations (with an expected 6 transitions per create/drop roundtrip)
+ // causes this workload to write at least 32MB (.ns and .0 files) * 10 threads
+ // * 30 iterations worth of data to disk, or about 10GB, which can be slow on
+ // test hosts.
+ threadCount: 10,
+ iterations: 180,
+ states: states,
+ transitions: transitions,
+ };
+})();