summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorGeert Bosch <geert@mongodb.com>2014-11-20 14:26:43 -0500
committerGeert Bosch <geert@mongodb.com>2014-11-21 13:18:53 -0500
commite7f6c56327afa51847a95d9d5bc6399209856c10 (patch)
tree93a6f8b98d13ff81bd21a2ffc9f312e4ff662123 /src/mongo
parente5644e2ca12a60df677cb8e8dfc70f19a9423b0a (diff)
downloadmongo-e7f6c56327afa51847a95d9d5bc6399209856c10.tar.gz
SERVER-16192: Add ScopedTransaction to automatically commitAndRestart()
Diffstat (limited to 'src/mongo')
-rw-r--r--src/mongo/db/catalog/database.cpp1
-rw-r--r--src/mongo/db/client.cpp3
-rw-r--r--src/mongo/db/client.h1
-rw-r--r--src/mongo/db/cloner.cpp2
-rw-r--r--src/mongo/db/commands/apply_ops.cpp2
-rw-r--r--src/mongo/db/commands/clone.cpp1
-rw-r--r--src/mongo/db/commands/collection_to_capped.cpp2
-rw-r--r--src/mongo/db/commands/compact.cpp1
-rw-r--r--src/mongo/db/commands/copydb.cpp2
-rw-r--r--src/mongo/db/commands/cpuprofile.cpp2
-rw-r--r--src/mongo/db/commands/create_indexes.cpp1
-rw-r--r--src/mongo/db/commands/drop_indexes.cpp2
-rw-r--r--src/mongo/db/commands/find_and_modify.cpp2
-rw-r--r--src/mongo/db/commands/fsync.cpp2
-rw-r--r--src/mongo/db/commands/list_databases.cpp1
-rw-r--r--src/mongo/db/commands/mr.cpp5
-rw-r--r--src/mongo/db/commands/rename_collection.cpp1
-rw-r--r--src/mongo/db/commands/test_commands.cpp3
-rw-r--r--src/mongo/db/commands/write_commands/batch_executor.cpp4
-rw-r--r--src/mongo/db/db.cpp3
-rw-r--r--src/mongo/db/dbcommands.cpp7
-rw-r--r--src/mongo/db/dbeval.cpp1
-rw-r--r--src/mongo/db/exec/stagedebug_cmd.cpp1
-rw-r--r--src/mongo/db/index_builder.cpp1
-rw-r--r--src/mongo/db/index_rebuilder.cpp1
-rw-r--r--src/mongo/db/instance.cpp5
-rw-r--r--src/mongo/db/operation_context.h32
-rw-r--r--src/mongo/db/ops/update_executor.cpp1
-rw-r--r--src/mongo/db/repl/bgsync.cpp1
-rw-r--r--src/mongo/db/repl/master_slave.cpp10
-rw-r--r--src/mongo/db/repl/minvalid.cpp5
-rw-r--r--src/mongo/db/repl/network_interface_impl.cpp1
-rw-r--r--src/mongo/db/repl/oplog.cpp4
-rw-r--r--src/mongo/db/repl/repl_coordinator_external_state_impl.cpp2
-rw-r--r--src/mongo/db/repl/repl_coordinator_impl.cpp1
-rw-r--r--src/mongo/db/repl/resync.cpp1
-rw-r--r--src/mongo/db/repl/rs_initialsync.cpp2
-rw-r--r--src/mongo/db/repl/sync_source_feedback.cpp1
-rw-r--r--src/mongo/db/repl/sync_tail.cpp3
-rw-r--r--src/mongo/db/storage/mmap_v1/dur_recover.cpp1
-rw-r--r--src/mongo/db/ttl.cpp1
-rw-r--r--src/mongo/dbtests/basictests.cpp1
-rw-r--r--src/mongo/dbtests/dbhelper_tests.cpp1
-rw-r--r--src/mongo/dbtests/indexcatalogtests.cpp2
-rw-r--r--src/mongo/dbtests/namespacetests.cpp2
-rw-r--r--src/mongo/dbtests/query_stage_fetch.cpp1
-rw-r--r--src/mongo/dbtests/querytests.cpp3
-rw-r--r--src/mongo/dbtests/repltests.cpp7
-rw-r--r--src/mongo/dbtests/rollbacktests.cpp14
-rw-r--r--src/mongo/s/d_merge.cpp1
-rw-r--r--src/mongo/s/d_migrate.cpp9
-rw-r--r--src/mongo/s/d_split.cpp1
-rw-r--r--src/mongo/s/d_state.cpp3
53 files changed, 167 insertions, 1 deletions
diff --git a/src/mongo/db/catalog/database.cpp b/src/mongo/db/catalog/database.cpp
index 3d29797a620..dc15eebd60d 100644
--- a/src/mongo/db/catalog/database.cpp
+++ b/src/mongo/db/catalog/database.cpp
@@ -532,6 +532,7 @@ namespace mongo {
}
void dropAllDatabasesExceptLocal(OperationContext* txn) {
+ ScopedTransaction transaction(txn, MODE_X);
Lock::GlobalWrite lk(txn->lockState());
vector<string> n;
diff --git a/src/mongo/db/client.cpp b/src/mongo/db/client.cpp
index d1ed1a927c8..c6eeef0ff8c 100644
--- a/src/mongo/db/client.cpp
+++ b/src/mongo/db/client.cpp
@@ -198,7 +198,8 @@ namespace mongo {
AutoGetOrCreateDb::AutoGetOrCreateDb(OperationContext* txn,
const StringData& ns,
LockMode mode)
- : _dbLock(txn->lockState(), ns, mode),
+ : _transaction(txn, MODE_IX),
+ _dbLock(txn->lockState(), ns, mode),
_db(dbHolder().get(txn, ns)) {
invariant(mode == MODE_IX || mode == MODE_X);
_justCreated = false;
diff --git a/src/mongo/db/client.h b/src/mongo/db/client.h
index 5fe44c85b09..eb1dc8a91ad 100644
--- a/src/mongo/db/client.h
+++ b/src/mongo/db/client.h
@@ -113,6 +113,7 @@ namespace mongo {
Lock::DBLock& lock() { return _dbLock; }
private:
+ ScopedTransaction _transaction;
Lock::DBLock _dbLock; // not const, as we may need to relock for implicit create
Database* _db;
bool _justCreated;
diff --git a/src/mongo/db/cloner.cpp b/src/mongo/db/cloner.cpp
index 58e8d03c49d..452916c15cf 100644
--- a/src/mongo/db/cloner.cpp
+++ b/src/mongo/db/cloner.cpp
@@ -111,6 +111,7 @@ namespace mongo {
invariant(from_collection.coll() != "system.indexes");
// XXX: can probably take dblock instead
+ ScopedTransaction transaction(txn, MODE_X);
Lock::GlobalWrite lk(txn->lockState());
// Make sure database still exists after we resume from the temp release
@@ -317,6 +318,7 @@ namespace mongo {
const NamespaceString nss(ns);
const string dbname = nss.db().toString();
+ ScopedTransaction transaction(txn, MODE_IX);
Lock::DBLock dbWrite(txn->lockState(), dbname, MODE_X);
Database* db = dbHolder().openDb(txn, dbname);
diff --git a/src/mongo/db/commands/apply_ops.cpp b/src/mongo/db/commands/apply_ops.cpp
index 4b2858d9505..c7aa7de3888 100644
--- a/src/mongo/db/commands/apply_ops.cpp
+++ b/src/mongo/db/commands/apply_ops.cpp
@@ -82,6 +82,7 @@ namespace mongo {
// SERVER-4328 todo : is global ok or does this take a long time? i believe multiple
// ns used so locking individually requires more analysis
+ ScopedTransaction transaction(txn, MODE_X);
Lock::GlobalWrite globalWriteLock(txn->lockState());
DBDirectClient db(txn);
@@ -137,6 +138,7 @@ namespace mongo {
// We do not have a wrapping WriteUnitOfWork so it is possible for a journal
// commit to happen with a subset of ops applied.
// TODO figure out what to do about this.
+ ScopedTransaction transaction(txn, MODE_IX);
Lock::DBLock lk(txn->lockState(), nsToDatabaseSubstring(ns), MODE_X);
invariant(txn->lockState()->isRecursive());
diff --git a/src/mongo/db/commands/clone.cpp b/src/mongo/db/commands/clone.cpp
index 2acc7b1e452..ddf2775c55f 100644
--- a/src/mongo/db/commands/clone.cpp
+++ b/src/mongo/db/commands/clone.cpp
@@ -114,6 +114,7 @@ namespace mongo {
set<string> clonedColls;
+ ScopedTransaction transaction(txn, MODE_IX);
Lock::DBLock dbXLock(txn->lockState(), dbname, MODE_X);
Cloner cloner;
diff --git a/src/mongo/db/commands/collection_to_capped.cpp b/src/mongo/db/commands/collection_to_capped.cpp
index 9e0f2615038..52769976cfd 100644
--- a/src/mongo/db/commands/collection_to_capped.cpp
+++ b/src/mongo/db/commands/collection_to_capped.cpp
@@ -161,6 +161,7 @@ namespace mongo {
return false;
}
+ ScopedTransaction transaction(txn, MODE_IX);
Lock::DBLock dbXLock(txn->lockState(), dbname, MODE_X);
Client::Context ctx(txn, dbname);
@@ -214,6 +215,7 @@ namespace mongo {
bool fromRepl ) {
// calls renamecollection which does a global lock, so we must too:
//
+ ScopedTransaction transaction(txn, MODE_X);
Lock::GlobalWrite globalWriteLock(txn->lockState());
Client::Context ctx(txn, dbname);
diff --git a/src/mongo/db/commands/compact.cpp b/src/mongo/db/commands/compact.cpp
index 2bc8a330c57..66d8f353e17 100644
--- a/src/mongo/db/commands/compact.cpp
+++ b/src/mongo/db/commands/compact.cpp
@@ -146,6 +146,7 @@ namespace mongo {
compactOptions.validateDocuments = cmdObj["validate"].trueValue();
+ ScopedTransaction transaction(txn, MODE_IX);
Lock::DBLock lk(txn->lockState(), db, MODE_X);
BackgroundOperation::assertNoBgOpInProgForNs(ns.ns());
Client::Context ctx(txn, ns);
diff --git a/src/mongo/db/commands/copydb.cpp b/src/mongo/db/commands/copydb.cpp
index a04a25a50d6..e5d6df6d3d8 100644
--- a/src/mongo/db/commands/copydb.cpp
+++ b/src/mongo/db/commands/copydb.cpp
@@ -215,10 +215,12 @@ namespace mongo {
if (fromSelf) {
// SERVER-4328 todo lock just the two db's not everything for the fromself case
+ ScopedTransaction transaction(txn, MODE_X);
Lock::GlobalWrite lk(txn->lockState());
return cloner.go(txn, todb, fromhost, cloneOptions, NULL, errmsg);
}
+ ScopedTransaction transaction(txn, MODE_IX);
Lock::DBLock lk (txn->lockState(), todb, MODE_X);
return cloner.go(txn, todb, fromhost, cloneOptions, NULL, errmsg);
}
diff --git a/src/mongo/db/commands/cpuprofile.cpp b/src/mongo/db/commands/cpuprofile.cpp
index d279f4b51d1..44cae32b50c 100644
--- a/src/mongo/db/commands/cpuprofile.cpp
+++ b/src/mongo/db/commands/cpuprofile.cpp
@@ -133,6 +133,7 @@ namespace mongo {
std::string &errmsg,
BSONObjBuilder &result,
bool fromRepl ) {
+ ScopedTransaction transaction(txn, MODE_IX);
Lock::DBLock dbXLock(txn->lockState(), db, MODE_X);
// The lock here is just to prevent concurrency, nothing will write.
Client::Context ctx(txn, db);
@@ -152,6 +153,7 @@ namespace mongo {
std::string &errmsg,
BSONObjBuilder &result,
bool fromRepl ) {
+ ScopedTransaction transaction(txn, MODE_IX);
Lock::DBLock dbXLock(txn->lockState(), db, MODE_X);
Client::Context ctx(txn, db);
diff --git a/src/mongo/db/commands/create_indexes.cpp b/src/mongo/db/commands/create_indexes.cpp
index 7b27aee91bb..67cd6bdff33 100644
--- a/src/mongo/db/commands/create_indexes.cpp
+++ b/src/mongo/db/commands/create_indexes.cpp
@@ -136,6 +136,7 @@ namespace mongo {
// now we know we have to create index(es)
// Note: createIndexes command does not currently respect shard versioning.
+ ScopedTransaction transaction(txn, MODE_IX);
Lock::DBLock dbLock(txn->lockState(), ns.db(), MODE_X);
Database* db = dbHolder().get(txn, ns.db());
if (!db) {
diff --git a/src/mongo/db/commands/drop_indexes.cpp b/src/mongo/db/commands/drop_indexes.cpp
index 1e92d0e0f21..85e212efbdd 100644
--- a/src/mongo/db/commands/drop_indexes.cpp
+++ b/src/mongo/db/commands/drop_indexes.cpp
@@ -104,6 +104,7 @@ namespace mongo {
CmdDropIndexes() : Command("dropIndexes", false, "deleteIndexes") { }
bool run(OperationContext* txn, const string& dbname, BSONObj& jsobj, int, string& errmsg, BSONObjBuilder& anObjBuilder, bool fromRepl) {
+ ScopedTransaction transaction(txn, MODE_IX);
Lock::DBLock dbXLock(txn->lockState(), dbname, MODE_X);
WriteUnitOfWork wunit(txn);
bool ok = wrappedRun(txn, dbname, jsobj, errmsg, anObjBuilder);
@@ -245,6 +246,7 @@ namespace mongo {
LOG(0) << "CMD: reIndex " << toDeleteNs << endl;
+ ScopedTransaction transaction(txn, MODE_IX);
Lock::DBLock dbXLock(txn->lockState(), dbname, MODE_X);
Client::Context ctx(txn, toDeleteNs);
diff --git a/src/mongo/db/commands/find_and_modify.cpp b/src/mongo/db/commands/find_and_modify.cpp
index c6f7f7fca97..ce9e8dd2849 100644
--- a/src/mongo/db/commands/find_and_modify.cpp
+++ b/src/mongo/db/commands/find_and_modify.cpp
@@ -126,6 +126,7 @@ namespace mongo {
if ( !ok && errmsg == "no-collection" ) {
// Take X lock so we can create collection, then re-run operation.
+ ScopedTransaction transaction(txn, MODE_IX);
Lock::DBLock lk(txn->lockState(), dbname, MODE_X);
Client::Context ctx(txn, ns, false /* don't check version */);
Database* db = ctx.db();
@@ -402,6 +403,7 @@ namespace mongo {
}
}
+ ScopedTransaction transaction(txn, MODE_IX);
Lock::DBLock dbXLock(txn->lockState(), dbname, MODE_X);
Client::Context ctx(txn, ns);
diff --git a/src/mongo/db/commands/fsync.cpp b/src/mongo/db/commands/fsync.cpp
index 69f04cf547c..fb4e41bb4b7 100644
--- a/src/mongo/db/commands/fsync.cpp
+++ b/src/mongo/db/commands/fsync.cpp
@@ -134,6 +134,7 @@ namespace mongo {
// the simple fsync command case
if (sync) {
// can this be GlobalRead? and if it can, it should be nongreedy.
+ ScopedTransaction transaction(txn, MODE_X);
Lock::GlobalWrite w(txn->lockState());
getDur().commitNow(txn);
@@ -152,6 +153,7 @@ namespace mongo {
SimpleMutex::scoped_lock lkf(filesLockedFsync);
OperationContextImpl txn; // XXX?
+ ScopedTransaction transaction(&txn, MODE_X);
Lock::GlobalWrite global(txn.lockState()); // No WriteUnitOfWork needed
SimpleMutex::scoped_lock lk(fsyncCmd.m);
diff --git a/src/mongo/db/commands/list_databases.cpp b/src/mongo/db/commands/list_databases.cpp
index e852e30617f..c84f38333b9 100644
--- a/src/mongo/db/commands/list_databases.cpp
+++ b/src/mongo/db/commands/list_databases.cpp
@@ -87,6 +87,7 @@ namespace mongo {
b.append( "name", dbname );
{
+ ScopedTransaction transaction(txn, MODE_IS);
Lock::DBLock dbLock(txn->lockState(), dbname, MODE_IS);
Database* db = dbHolder().get( txn, dbname );
diff --git a/src/mongo/db/commands/mr.cpp b/src/mongo/db/commands/mr.cpp
index 72af37852fe..331ab2dfee5 100644
--- a/src/mongo/db/commands/mr.cpp
+++ b/src/mongo/db/commands/mr.cpp
@@ -334,6 +334,7 @@ namespace mongo {
if (_useIncremental) {
// We don't want to log the deletion of incLong as it isn't replicated. While
// harmless, this would lead to a scary looking warning on the secondaries.
+ ScopedTransaction(_txn, MODE_IX);
Lock::DBLock lk(_txn->lockState(),
nsToDatabaseSubstring(_config.incLong),
MODE_X);
@@ -538,6 +539,7 @@ namespace mongo {
invariant( !txn->lockState()->isLocked() );
+ ScopedTransaction transaction(txn, MODE_X);
Lock::GlobalWrite lock(txn->lockState()); // TODO(erh): this is how it was, but seems it doesn't need to be global
return postProcessCollectionNonAtomic(txn, op, pm);
}
@@ -576,6 +578,7 @@ namespace mongo {
if (_config.outputOptions.outType == Config::REPLACE ||
_safeCount(_db, _config.outputOptions.finalNamespace) == 0) {
+ ScopedTransaction transaction(txn, MODE_X);
Lock::GlobalWrite lock(txn->lockState()); // TODO(erh): why global???
// replace: just rename from temp to final collection name, dropping previous collection
_db.dropCollection( _config.outputOptions.finalNamespace );
@@ -598,6 +601,7 @@ namespace mongo {
_safeCount(_db, _config.tempNamespace, BSONObj()));
auto_ptr<DBClientCursor> cursor = _db.query(_config.tempNamespace , BSONObj());
while (cursor->more()) {
+ ScopedTransaction(_txn, MODE_IX);
Lock::DBLock lock(_txn->lockState(),
nsToDatabaseSubstring(_config.outputOptions.finalNamespace),
MODE_X);
@@ -617,6 +621,7 @@ namespace mongo {
_safeCount(_db, _config.tempNamespace, BSONObj()));
auto_ptr<DBClientCursor> cursor = _db.query( _config.tempNamespace , BSONObj() );
while ( cursor->more() ) {
+ ScopedTransaction transaction(txn, MODE_X);
Lock::GlobalWrite lock(txn->lockState()); // TODO(erh) why global?
BSONObj temp = cursor->nextSafe();
BSONObj old;
diff --git a/src/mongo/db/commands/rename_collection.cpp b/src/mongo/db/commands/rename_collection.cpp
index ed548cc3bf9..9f5ff7b54fc 100644
--- a/src/mongo/db/commands/rename_collection.cpp
+++ b/src/mongo/db/commands/rename_collection.cpp
@@ -112,6 +112,7 @@ namespace mongo {
string& errmsg,
BSONObjBuilder& result,
bool fromRepl) {
+ ScopedTransaction transaction(txn, MODE_X);
Lock::GlobalWrite globalWriteLock(txn->lockState());
string source = cmdObj.getStringField( name.c_str() );
string target = cmdObj.getStringField( "to" );
diff --git a/src/mongo/db/commands/test_commands.cpp b/src/mongo/db/commands/test_commands.cpp
index 73c0911d58d..cb1245508da 100644
--- a/src/mongo/db/commands/test_commands.cpp
+++ b/src/mongo/db/commands/test_commands.cpp
@@ -66,6 +66,7 @@ namespace mongo {
string ns = dbname + "." + coll;
BSONObj obj = cmdObj[ "obj" ].embeddedObjectUserCheck();
+ ScopedTransaction transaction(txn, MODE_IX);
Lock::DBLock lk(txn->lockState(), dbname, MODE_X);
WriteUnitOfWork wunit(txn);
Client::Context ctx(txn, ns );
@@ -117,10 +118,12 @@ namespace mongo {
}
if(cmdObj.getBoolField("w")) {
+ ScopedTransaction transaction(txn, MODE_X);
Lock::GlobalWrite lk(txn->lockState());
sleepmillis(millis);
}
else {
+ ScopedTransaction transaction(txn, MODE_S);
Lock::GlobalRead lk(txn->lockState());
sleepmillis(millis);
}
diff --git a/src/mongo/db/commands/write_commands/batch_executor.cpp b/src/mongo/db/commands/write_commands/batch_executor.cpp
index 17552185f0e..7fed228ed3f 100644
--- a/src/mongo/db/commands/write_commands/batch_executor.cpp
+++ b/src/mongo/db/commands/write_commands/batch_executor.cpp
@@ -736,6 +736,7 @@ namespace mongo {
private:
bool _lockAndCheckImpl(WriteOpResult* result, bool intentLock=true);
+ ScopedTransaction _transaction;
// Guard object for the write lock on the target database.
scoped_ptr<Lock::DBLock> _writeLock;
scoped_ptr<Lock::CollectionLock> _collLock;
@@ -943,6 +944,7 @@ namespace mongo {
txn(txn),
request(aRequest),
currIndex(0),
+ _transaction(txn, MODE_IX),
_collection(NULL) {
}
@@ -1200,6 +1202,7 @@ namespace mongo {
}
if ( createCollection ) {
+ ScopedTransaction transaction(txn, MODE_IX);
Lock::DBLock lk(txn->lockState(), nsString.db(), MODE_X);
Client::Context ctx(txn, nsString.ns(), false /* don't check version */);
Database* db = ctx.db();
@@ -1216,6 +1219,7 @@ namespace mongo {
}
///////////////////////////////////////////
+ ScopedTransaction transaction(txn, MODE_IX);
Lock::DBLock dbLock(txn->lockState(), nsString.db(), MODE_IX);
Lock::CollectionLock colLock(txn->lockState(),
nsString.ns(),
diff --git a/src/mongo/db/db.cpp b/src/mongo/db/db.cpp
index 34d915bced6..060943b5e7c 100644
--- a/src/mongo/db/db.cpp
+++ b/src/mongo/db/db.cpp
@@ -252,6 +252,7 @@ namespace mongo {
OperationContextImpl txn;
+ ScopedTransaction transaction(&txn, MODE_X);
Lock::GlobalWrite lk(txn.lockState());
AutoGetOrCreateDb autoDb(&txn, "local", mongo::MODE_X);
Database* db = autoDb.getDb();
@@ -310,6 +311,7 @@ namespace mongo {
*/
static unsigned long long checkIfReplMissingFromCommandLine(OperationContext* txn) {
// This is helpful for the query below to work as you can't open files when readlocked
+ ScopedTransaction transaction(txn, MODE_X);
Lock::GlobalWrite lk(txn->lockState());
if (!repl::getGlobalReplicationCoordinator()->getSettings().usingReplSets()) {
DBDirectClient c(txn);
@@ -322,6 +324,7 @@ namespace mongo {
LOG(1) << "enter repairDatabases (to check pdfile version #)" << endl;
OperationContextImpl txn;
+ ScopedTransaction transaction(&txn, MODE_X);
Lock::GlobalWrite lk(txn.lockState());
vector<string> dbNames;
diff --git a/src/mongo/db/dbcommands.cpp b/src/mongo/db/dbcommands.cpp
index 0c6164f8f3a..6ffe89f1820 100644
--- a/src/mongo/db/dbcommands.cpp
+++ b/src/mongo/db/dbcommands.cpp
@@ -202,6 +202,7 @@ namespace mongo {
{
// TODO: SERVER-4328 Don't lock globally
+ ScopedTransaction transaction(txn, MODE_X);
Lock::GlobalWrite lk(txn->lockState());
if (dbHolder().get(txn, dbname) == NULL) {
return true; // didn't exist, was no-op
@@ -286,6 +287,7 @@ namespace mongo {
}
// TODO: SERVER-4328 Don't lock globally
+ ScopedTransaction transaction(txn, MODE_X);
Lock::GlobalWrite lk(txn->lockState());
Client::Context context(txn, dbname );
@@ -358,6 +360,7 @@ namespace mongo {
// Needs to be locked exclusively, because creates the system.profile collection
// in the local database.
//
+ ScopedTransaction transaction(txn, MODE_IX);
Lock::DBLock dbXLock(txn->lockState(), dbname, MODE_X);
Client::Context ctx(txn, dbname);
@@ -413,6 +416,7 @@ namespace mongo {
// This doesn't look like it requires exclusive DB lock, because it uses its own diag
// locking, but originally the lock was set to be WRITE, so preserving the behaviour.
//
+ ScopedTransaction transaction(txn, MODE_IX);
Lock::DBLock dbXLock(txn->lockState(), dbname, MODE_X);
Client::Context ctx(txn, dbname);
@@ -482,6 +486,7 @@ namespace mongo {
return false;
}
+ ScopedTransaction transaction(txn, MODE_IX);
Lock::DBLock dbXLock(txn->lockState(), dbname, MODE_X);
Client::Context ctx(txn, nsToDrop);
Database* db = ctx.db();
@@ -582,6 +587,7 @@ namespace mongo {
!options["capped"].trueValue() || options["size"].isNumber() ||
options.hasField("$nExtents"));
+ ScopedTransaction transaction(txn, MODE_IX);
Lock::DBLock dbXLock(txn->lockState(), dbname, MODE_X);
WriteUnitOfWork wunit(txn);
Client::Context ctx(txn, ns);
@@ -998,6 +1004,7 @@ namespace mongo {
const std::string ns = dbname + "." + collName;
+ ScopedTransaction transaction(txn, MODE_IX);
Lock::DBLock dbXLock(txn->lockState(), dbname, MODE_X);
WriteUnitOfWork wunit(txn);
Client::Context ctx(txn, ns );
diff --git a/src/mongo/db/dbeval.cpp b/src/mongo/db/dbeval.cpp
index d3f3901c7d1..a371469c73b 100644
--- a/src/mongo/db/dbeval.cpp
+++ b/src/mongo/db/dbeval.cpp
@@ -150,6 +150,7 @@ namespace mongo {
return dbEval(txn, dbname, cmdObj, result, errmsg);
}
+ ScopedTransaction transaction(txn, MODE_X);
Lock::GlobalWrite lk(txn->lockState());
// No WriteUnitOfWork necessary, as dbEval will create its own, see "nolock" case above
Client::Context ctx(txn, dbname );
diff --git a/src/mongo/db/exec/stagedebug_cmd.cpp b/src/mongo/db/exec/stagedebug_cmd.cpp
index 493b28cb567..5ae063eed2d 100644
--- a/src/mongo/db/exec/stagedebug_cmd.cpp
+++ b/src/mongo/db/exec/stagedebug_cmd.cpp
@@ -121,6 +121,7 @@ namespace mongo {
// TODO A write lock is currently taken here to accommodate stages that perform writes
// (e.g. DeleteStage). This should be changed to use a read lock for read-only
// execution trees.
+ ScopedTransaction transaction(txn, MODE_IX);
Lock::DBLock lk(txn->lockState(), dbname, MODE_X);
Client::Context ctx(txn, dbname);
diff --git a/src/mongo/db/index_builder.cpp b/src/mongo/db/index_builder.cpp
index 1047d9a44d6..f784c5064e0 100644
--- a/src/mongo/db/index_builder.cpp
+++ b/src/mongo/db/index_builder.cpp
@@ -72,6 +72,7 @@ namespace mongo {
txn.getCurOp()->reset(HostAndPort(), dbInsert);
NamespaceString ns(_index["ns"].String());
+ ScopedTransaction transaction(&txn, MODE_IX);
Lock::DBLock dlk(txn.lockState(), ns.db(), MODE_X);
Client::Context ctx(&txn, ns.getSystemIndexesCollection());
diff --git a/src/mongo/db/index_rebuilder.cpp b/src/mongo/db/index_rebuilder.cpp
index e684bdc0baa..b23270e3afe 100644
--- a/src/mongo/db/index_rebuilder.cpp
+++ b/src/mongo/db/index_rebuilder.cpp
@@ -64,6 +64,7 @@ namespace {
// This write lock is held throughout the index building process
// for this namespace.
+ ScopedTransaction transaction(txn, MODE_IX);
Lock::DBLock lk(txn->lockState(), nsToDatabaseSubstring(ns), MODE_X);
Client::Context ctx(txn, ns);
diff --git a/src/mongo/db/instance.cpp b/src/mongo/db/instance.cpp
index 9c97fccecdb..57f5cf5fb2b 100644
--- a/src/mongo/db/instance.cpp
+++ b/src/mongo/db/instance.cpp
@@ -573,6 +573,7 @@ namespace {
uassertStatusOK(executor.prepare());
// Tentatively take an intent lock, fix up if we need to create the collection
+ ScopedTransaction transaction(txn, MODE_IX);
Lock::DBLock dbLock(txn->lockState(), ns.db(), MODE_IX);
if (dbHolder().get(txn, ns.db()) == NULL) {
// If DB doesn't exist, don't implicitly create it in Client::Context
@@ -606,6 +607,7 @@ namespace {
UpdateExecutor executor(txn, &request, &op.debug());
uassertStatusOK(executor.prepare());
+ ScopedTransaction transaction(txn, MODE_IX);
Lock::DBLock dbLock(txn->lockState(), ns.db(), MODE_X);
Client::Context ctx(txn, ns);
Database* db = ctx.db();
@@ -968,6 +970,7 @@ namespace {
{
const bool isIndexBuild = (nsToCollectionSubstring(ns) == "system.indexes");
const LockMode mode = isIndexBuild ? MODE_X : MODE_IX;
+ ScopedTransaction transaction(txn, MODE_IX);
Lock::DBLock dbLock(txn->lockState(), nsString.db(), mode);
Lock::CollectionLock collLock(txn->lockState(), nsString.ns(), mode);
@@ -995,6 +998,7 @@ namespace {
}
// Collection didn't exist so try again with MODE_X
+ ScopedTransaction transaction(txn, MODE_IX);
Lock::DBLock dbLock(txn->lockState(), nsString.db(), MODE_X);
// CONCURRENCY TODO: is being read locked in big log sufficient here?
@@ -1057,6 +1061,7 @@ namespace {
repl::getGlobalReplicationCoordinator()->shutdown();
+ ScopedTransaction transaction(&txn, MODE_X);
Lock::GlobalWrite lk(txn.lockState());
log() << "now exiting" << endl;
diff --git a/src/mongo/db/operation_context.h b/src/mongo/db/operation_context.h
index 3897fa4820d..fcdd3724c62 100644
--- a/src/mongo/db/operation_context.h
+++ b/src/mongo/db/operation_context.h
@@ -33,6 +33,7 @@
#include "mongo/base/string_data.h"
#include "mongo/db/storage/recovery_unit.h"
#include "mongo/db/concurrency/locker.h"
+#include "mongo/db/concurrency/d_concurrency.h"
namespace mongo {
@@ -175,4 +176,35 @@ namespace mongo {
bool _ended;
};
+ class Database;
+
+ /**
+ * RAII-style class to mark the scope of a transaction. ScopedTransactions may be nested.
+ * An outermost ScopedTransaction calls commitAndRestart() on destruction, so that the storage
+ * engine can release resources, such as snapshots or locks, that it may have acquired during
+ * the transaction. Note that any writes are committed in nested WriteUnitOfWork scopes,
+ * so write conflicts cannot happen on completing a ScopedTransaction.
+ *
+ * TODO: The ScopedTransaction should hold the global lock
+ */
+ class ScopedTransaction {
+ MONGO_DISALLOW_COPYING(ScopedTransaction);
+ public:
+ /**
+ * The mode for the transaction indicates whether the transaction will write (MODE_IX) or
+ * only read (MODE_IS), or needs to run without other writers (MODE_S) or any other
+ * operations (MODE_X) on the server.
+ */
+ ScopedTransaction(OperationContext* txn, LockMode mode) : _txn(txn) { }
+
+ ~ScopedTransaction() {
+ if (!_txn->lockState()->isLocked()) {
+ _txn->recoveryUnit()->commitAndRestart();
+ }
+ }
+
+ private:
+ OperationContext* _txn;
+ };
+
} // namespace mongo
diff --git a/src/mongo/db/ops/update_executor.cpp b/src/mongo/db/ops/update_executor.cpp
index bd95b062024..23645123af9 100644
--- a/src/mongo/db/ops/update_executor.cpp
+++ b/src/mongo/db/ops/update_executor.cpp
@@ -137,6 +137,7 @@ namespace mongo {
locker->isLockHeldForMode( ResourceId( RESOURCE_DATABASE, nsString.db() ),
MODE_X ) );
+ ScopedTransaction transaction(_txn, MODE_IX);
Lock::DBLock lk(_txn->lockState(), nsString.db(), MODE_X);
WriteUnitOfWork wuow(_txn);
diff --git a/src/mongo/db/repl/bgsync.cpp b/src/mongo/db/repl/bgsync.cpp
index cf6be9c7cac..e5b2cbe032d 100644
--- a/src/mongo/db/repl/bgsync.cpp
+++ b/src/mongo/db/repl/bgsync.cpp
@@ -521,6 +521,7 @@ namespace {
long long BackgroundSync::_readLastAppliedHash(OperationContext* txn) {
BSONObj oplogEntry;
try {
+ ScopedTransaction transaction(txn, MODE_IX);
Lock::DBLock lk(txn->lockState(), "local", MODE_X);
bool success = Helpers::getLast(txn, rsoplog, oplogEntry);
if (!success) {
diff --git a/src/mongo/db/repl/master_slave.cpp b/src/mongo/db/repl/master_slave.cpp
index 4aea655198b..543afab4fbb 100644
--- a/src/mongo/db/repl/master_slave.cpp
+++ b/src/mongo/db/repl/master_slave.cpp
@@ -170,6 +170,7 @@ namespace repl {
bool exists = Helpers::getSingleton(txn, "local.me", _me);
if (!exists || !_me.hasField("host") || _me["host"].String() != myname) {
+ ScopedTransaction transaction(txn, MODE_IX);
Lock::DBLock dblk(txn->lockState(), "local", MODE_X);
WriteUnitOfWork wunit(txn);
// clean out local.me
@@ -820,6 +821,7 @@ namespace repl {
}
// obviously global isn't ideal, but non-repl set is old so
// keeping it simple
+ ScopedTransaction transaction(txn, MODE_X);
Lock::GlobalWrite lk(txn->lockState());
save(txn);
}
@@ -871,6 +873,7 @@ namespace repl {
log() << "repl: " << ns << " oplog is empty" << endl;
}
{
+ ScopedTransaction transaction(txn, MODE_X);
Lock::GlobalWrite lk(txn->lockState());
save(txn);
}
@@ -943,6 +946,7 @@ namespace repl {
const bool moreInitialSyncsPending = !addDbNextPass.empty() && n;
if ( moreInitialSyncsPending || !oplogReader.more() ) {
+ ScopedTransaction transaction(txn, MODE_X);
Lock::GlobalWrite lk(txn->lockState());
if (tailing) {
@@ -959,6 +963,7 @@ namespace repl {
OCCASIONALLY if( n > 0 && ( n > 100000 || time(0) - saveLast > 60 ) ) {
// periodically note our progress, in case we are doing a lot of work and crash
+ ScopedTransaction transaction(txn, MODE_X);
Lock::GlobalWrite lk(txn->lockState());
syncedTo = nextOpTime;
// can't update local log ts since there are pending operations from our peer
@@ -1000,6 +1005,7 @@ namespace repl {
verify( justOne );
oplogReader.putBack( op );
_sleepAdviceTime = nextOpTime.getSecs() + replSettings.slavedelay + 1;
+ ScopedTransaction transaction(txn, MODE_X);
Lock::GlobalWrite lk(txn->lockState());
if ( n > 0 ) {
syncedTo = last;
@@ -1082,6 +1088,7 @@ namespace repl {
int _replMain(OperationContext* txn, ReplSource::SourceVector& sources, int& nApplied) {
{
ReplInfo r("replMain load sources");
+ ScopedTransaction transaction(txn, MODE_X);
Lock::GlobalWrite lk(txn->lockState());
ReplSource::loadAll(txn, sources);
@@ -1153,6 +1160,7 @@ namespace repl {
while ( 1 ) {
int s = 0;
{
+ ScopedTransaction transaction(txn, MODE_X);
Lock::GlobalWrite lk(txn->lockState());
if ( replAllDead ) {
// throttledForceResyncDead can throw
@@ -1184,6 +1192,7 @@ namespace repl {
}
{
+ ScopedTransaction transaction(txn, MODE_X);
Lock::GlobalWrite lk(txn->lockState());
verify( syncing == 1 );
syncing--;
@@ -1310,6 +1319,7 @@ namespace repl {
}
OperationContextImpl txn; // XXX
+ ScopedTransaction transaction(&txn, MODE_S);
Lock::GlobalRead lk(txn.lockState());
for( unsigned i = a; i <= b; i++ ) {
diff --git a/src/mongo/db/repl/minvalid.cpp b/src/mongo/db/repl/minvalid.cpp
index 30a22a611ea..0005f364963 100644
--- a/src/mongo/db/repl/minvalid.cpp
+++ b/src/mongo/db/repl/minvalid.cpp
@@ -50,17 +50,20 @@ namespace {
} // namespace
void clearInitialSyncFlag(OperationContext* txn) {
+ ScopedTransaction transaction(txn, MODE_IX);
Lock::DBLock lk(txn->lockState(), "local", MODE_X);
Helpers::putSingleton(txn, minvalidNS, BSON("$unset" << initialSyncFlag));
}
void setInitialSyncFlag(OperationContext* txn) {
+ ScopedTransaction transaction(txn, MODE_IX);
Lock::DBLock lk(txn->lockState(), "local", MODE_X);
Helpers::putSingleton(txn, minvalidNS, BSON("$set" << initialSyncFlag));
}
bool getInitialSyncFlag() {
OperationContextImpl txn;
+ ScopedTransaction transaction(&txn, MODE_IX);
Lock::DBLock lk(txn.lockState(), "local", MODE_X);
BSONObj mv;
bool found = Helpers::getSingleton( &txn, minvalidNS, mv);
@@ -72,11 +75,13 @@ namespace {
}
void setMinValid(OperationContext* ctx, OpTime ts) {
+ ScopedTransaction transaction(ctx, MODE_IX);
Lock::DBLock lk(ctx->lockState(), "local", MODE_X);
Helpers::putSingleton(ctx, minvalidNS, BSON("$set" << BSON("ts" << ts)));
}
OpTime getMinValid(OperationContext* txn) {
+ ScopedTransaction transaction(txn, MODE_IS);
Lock::DBLock lk(txn->lockState(), "local", MODE_S);
BSONObj mv;
bool found = Helpers::getSingleton(txn, minvalidNS, mv);
diff --git a/src/mongo/db/repl/network_interface_impl.cpp b/src/mongo/db/repl/network_interface_impl.cpp
index d84d2148210..b459260f2ef 100644
--- a/src/mongo/db/repl/network_interface_impl.cpp
+++ b/src/mongo/db/repl/network_interface_impl.cpp
@@ -535,6 +535,7 @@ namespace {
const stdx::function<void (OperationContext*)>& callback) {
Client::initThreadIfNotAlready();
OperationContextImpl txn;
+ ScopedTransaction transaction(&txn, MODE_X);
Lock::GlobalWrite lk(txn.lockState());
callback(&txn);
}
diff --git a/src/mongo/db/repl/oplog.cpp b/src/mongo/db/repl/oplog.cpp
index 9842d675f16..0f68a52a6a8 100644
--- a/src/mongo/db/repl/oplog.cpp
+++ b/src/mongo/db/repl/oplog.cpp
@@ -149,6 +149,7 @@ namespace repl {
todo : make _logOpRS() call this so we don't repeat ourself?
*/
OpTime _logOpObjRS(OperationContext* txn, const BSONObj& op) {
+ ScopedTransaction transaction(txn, MODE_IX);
Lock::DBLock lk(txn->lockState(), "local", MODE_X);
const OpTime ts = op["ts"]._opTime();
@@ -265,6 +266,7 @@ namespace repl {
return;
}
+ ScopedTransaction transaction(txn, MODE_IX);
Lock::DBLock lk(txn->lockState(), "local", MODE_IX);
Lock::CollectionLock lk2(txn->lockState(), rsoplog, MODE_IX);
@@ -335,6 +337,7 @@ namespace repl {
return;
}
+ ScopedTransaction transaction(txn, MODE_IX);
Lock::DBLock lk(txn->lockState(), "local", MODE_IX);
if( logNS == 0 ) {
@@ -459,6 +462,7 @@ namespace repl {
}
void createOplog(OperationContext* txn) {
+ ScopedTransaction transaction(txn, MODE_X);
Lock::GlobalWrite lk(txn->lockState());
const char * ns = "local.oplog.$main";
diff --git a/src/mongo/db/repl/repl_coordinator_external_state_impl.cpp b/src/mongo/db/repl/repl_coordinator_external_state_impl.cpp
index 48bdf194987..c6c15238363 100644
--- a/src/mongo/db/repl/repl_coordinator_external_state_impl.cpp
+++ b/src/mongo/db/repl/repl_coordinator_external_state_impl.cpp
@@ -125,6 +125,7 @@ namespace {
std::string myname = getHostName();
OID myRID;
{
+ ScopedTransaction transaction(txn, MODE_IX);
Lock::DBLock lock(txn->lockState(), meDatabaseName, MODE_X);
BSONObj me;
@@ -171,6 +172,7 @@ namespace {
OperationContext* txn,
const BSONObj& config) {
try {
+ ScopedTransaction transaction(txn, MODE_IX);
Lock::DBLock dbWriteLock(txn->lockState(), configDatabaseName, MODE_X);
Helpers::putSingleton(txn, configCollectionName, config);
return Status::OK();
diff --git a/src/mongo/db/repl/repl_coordinator_impl.cpp b/src/mongo/db/repl/repl_coordinator_impl.cpp
index ad835cc531d..ca95291f26e 100644
--- a/src/mongo/db/repl/repl_coordinator_impl.cpp
+++ b/src/mongo/db/repl/repl_coordinator_impl.cpp
@@ -529,6 +529,7 @@ namespace {
}
lk.unlock();
boost::scoped_ptr<OperationContext> txn(_externalState->createOperationContext("rsDrain"));
+ ScopedTransaction transaction(txn.get(), MODE_X);
Lock::GlobalWrite globalWriteLock(txn->lockState());
lk.lock();
if (!_isWaitingForDrainToComplete) {
diff --git a/src/mongo/db/repl/resync.cpp b/src/mongo/db/repl/resync.cpp
index fc47875005b..61cb3e4632b 100644
--- a/src/mongo/db/repl/resync.cpp
+++ b/src/mongo/db/repl/resync.cpp
@@ -66,6 +66,7 @@ namespace repl {
BSONObjBuilder& result,
bool fromRepl) {
+ ScopedTransaction transaction(txn, MODE_X);
Lock::GlobalWrite globalWriteLock(txn->lockState());
ReplicationCoordinator* replCoord = getGlobalReplicationCoordinator();
diff --git a/src/mongo/db/repl/rs_initialsync.cpp b/src/mongo/db/repl/rs_initialsync.cpp
index b349d81a1f0..efdf411bc4c 100644
--- a/src/mongo/db/repl/rs_initialsync.cpp
+++ b/src/mongo/db/repl/rs_initialsync.cpp
@@ -116,6 +116,7 @@ namespace {
options.syncIndexes = ! dataPass;
// Make database stable
+ ScopedTransaction transaction(txn, MODE_IX);
Lock::DBLock dbWrite(txn->lockState(), db, MODE_X);
if (!cloner.go(txn, db, host, options, NULL, err, &errCode)) {
@@ -200,6 +201,7 @@ namespace {
if (!init->syncApply(txn, op)) {
bool retry;
{
+ ScopedTransaction transaction(txn, MODE_X);
Lock::GlobalWrite lk(txn->lockState());
retry = init->shouldRetry(txn, op);
}
diff --git a/src/mongo/db/repl/sync_source_feedback.cpp b/src/mongo/db/repl/sync_source_feedback.cpp
index 71c1c6f0485..677cb8c7e2c 100644
--- a/src/mongo/db/repl/sync_source_feedback.cpp
+++ b/src/mongo/db/repl/sync_source_feedback.cpp
@@ -77,6 +77,7 @@ namespace repl {
void SyncSourceFeedback::ensureMe(OperationContext* txn) {
string myname = getHostName();
{
+ ScopedTransaction transaction(txn, MODE_IX);
Lock::DBLock dlk(txn->lockState(), "local", MODE_X);
Client::Context ctx(txn, "local");
diff --git a/src/mongo/db/repl/sync_tail.cpp b/src/mongo/db/repl/sync_tail.cpp
index b779fb6e16b..e191f96c1b1 100644
--- a/src/mongo/db/repl/sync_tail.cpp
+++ b/src/mongo/db/repl/sync_tail.cpp
@@ -474,6 +474,7 @@ namespace repl {
namespace {
void tryToGoLiveAsASecondary(OperationContext* txn, ReplicationCoordinator* replCoord) {
+ ScopedTransaction transaction(txn, MODE_S);
Lock::GlobalRead readLock(txn->lockState());
if (replCoord->getMaintenanceMode()) {
@@ -647,6 +648,7 @@ namespace {
OpTime lastOpTime;
{
OperationContextImpl txn; // XXX?
+ ScopedTransaction transaction(&txn, MODE_IX);
Lock::DBLock lk(txn.lockState(), "local", MODE_X);
WriteUnitOfWork wunit(&txn);
@@ -757,6 +759,7 @@ namespace {
if (!st->syncApply(&txn, *it)) {
bool status;
{
+ ScopedTransaction transaction(&txn, MODE_X);
Lock::GlobalWrite lk(txn.lockState());
status = st->shouldRetry(&txn, *it);
}
diff --git a/src/mongo/db/storage/mmap_v1/dur_recover.cpp b/src/mongo/db/storage/mmap_v1/dur_recover.cpp
index 82642630bbd..75d8ec93556 100644
--- a/src/mongo/db/storage/mmap_v1/dur_recover.cpp
+++ b/src/mongo/db/storage/mmap_v1/dur_recover.cpp
@@ -602,6 +602,7 @@ namespace mongo {
// we use a lock so that exitCleanly will wait for us
// to finish (or at least to notice what is up and stop)
OperationContextImpl txn;
+ ScopedTransaction transaction(&txn, MODE_X);
Lock::GlobalWrite lk(txn.lockState());
// can't lock groupCommitMutex here as
diff --git a/src/mongo/db/ttl.cpp b/src/mongo/db/ttl.cpp
index 3a6258462e3..9e1413ce973 100644
--- a/src/mongo/db/ttl.cpp
+++ b/src/mongo/db/ttl.cpp
@@ -137,6 +137,7 @@ namespace mongo {
vector<BSONObj>* indexes ) {
invariant( indexes && indexes->empty() );
+ ScopedTransaction transaction( txn, MODE_IS );
Lock::DBLock dbLock( txn->lockState(), dbName, MODE_IS );
Database* db = dbHolder().get( txn, dbName );
diff --git a/src/mongo/dbtests/basictests.cpp b/src/mongo/dbtests/basictests.cpp
index 35cafb2fc9b..a6883bc68df 100644
--- a/src/mongo/dbtests/basictests.cpp
+++ b/src/mongo/dbtests/basictests.cpp
@@ -353,6 +353,7 @@ namespace BasicTests {
public:
void run() {
OperationContextImpl txn;
+ ScopedTransaction transaction(&txn, MODE_X);
Lock::GlobalWrite lk(txn.lockState());
Database db("dbtests_basictests_ownsns", NULL );
diff --git a/src/mongo/dbtests/dbhelper_tests.cpp b/src/mongo/dbtests/dbhelper_tests.cpp
index 95ce55b4132..d84990e80fe 100644
--- a/src/mongo/dbtests/dbhelper_tests.cpp
+++ b/src/mongo/dbtests/dbhelper_tests.cpp
@@ -63,6 +63,7 @@ namespace mongo {
{
// Remove _id range [_min, _max).
+ ScopedTransaction transaction(&txn, MODE_IX);
Lock::DBLock lk(txn.lockState(), nsToDatabaseSubstring(ns), MODE_X);
Client::Context ctx(&txn, ns );
diff --git a/src/mongo/dbtests/indexcatalogtests.cpp b/src/mongo/dbtests/indexcatalogtests.cpp
index c9903f6d4a2..a9819ba10b3 100644
--- a/src/mongo/dbtests/indexcatalogtests.cpp
+++ b/src/mongo/dbtests/indexcatalogtests.cpp
@@ -33,6 +33,7 @@ namespace IndexCatalogTests {
public:
IndexIteratorTests() {
OperationContextImpl txn;
+ ScopedTransaction transaction(&txn, MODE_IX);
Lock::DBLock lk(txn.lockState(), nsToDatabaseSubstring(_ns), MODE_X);
Client::Context ctx(&txn, _ns);
WriteUnitOfWork wuow(&txn);
@@ -45,6 +46,7 @@ namespace IndexCatalogTests {
~IndexIteratorTests() {
OperationContextImpl txn;
+ ScopedTransaction transaction(&txn, MODE_IX);
Lock::DBLock lk(txn.lockState(), nsToDatabaseSubstring(_ns), MODE_X);
Client::Context ctx(&txn, _ns);
WriteUnitOfWork wuow(&txn);
diff --git a/src/mongo/dbtests/namespacetests.cpp b/src/mongo/dbtests/namespacetests.cpp
index 4914dbc325e..762b14d8e69 100644
--- a/src/mongo/dbtests/namespacetests.cpp
+++ b/src/mongo/dbtests/namespacetests.cpp
@@ -526,6 +526,7 @@ namespace NamespaceTests {
OperationContextImpl txn;
+ ScopedTransaction transaction(&txn, MODE_IX);
Lock::DBLock lk(txn.lockState(), dbName, MODE_X);
bool justCreated;
@@ -569,6 +570,7 @@ namespace NamespaceTests {
OperationContextImpl txn;
+ ScopedTransaction transaction(&txn, MODE_IX);
Lock::DBLock lk(txn.lockState(), dbName, MODE_X);
bool justCreated;
diff --git a/src/mongo/dbtests/query_stage_fetch.cpp b/src/mongo/dbtests/query_stage_fetch.cpp
index b1f6084e1f5..c126f3e0d7f 100644
--- a/src/mongo/dbtests/query_stage_fetch.cpp
+++ b/src/mongo/dbtests/query_stage_fetch.cpp
@@ -147,6 +147,7 @@ namespace QueryStageFetch {
class FetchStageFilter : public QueryStageFetchBase {
public:
void run() {
+ ScopedTransaction transaction(&_txn, MODE_IX);
Lock::DBLock lk(_txn.lockState(), nsToDatabaseSubstring(ns()), MODE_X);
Client::Context ctx(&_txn, ns());
Database* db = ctx.db();
diff --git a/src/mongo/dbtests/querytests.cpp b/src/mongo/dbtests/querytests.cpp
index c9cf3886711..43e882e8250 100644
--- a/src/mongo/dbtests/querytests.cpp
+++ b/src/mongo/dbtests/querytests.cpp
@@ -161,6 +161,7 @@ namespace QueryTests {
void run() {
// We don't normally allow empty objects in the database, but test that we can find
// an empty object (one might be allowed inside a reserved namespace at some point).
+ ScopedTransaction transaction(&_txn, MODE_X);
Lock::GlobalWrite lk(_txn.lockState());
Client::Context ctx(&_txn, "unittests.querytests" );
@@ -632,6 +633,7 @@ namespace QueryTests {
}
void run() {
const char *ns = "unittests.querytests.OplogReplaySlaveReadTill";
+ ScopedTransaction transaction(&_txn, MODE_IX);
Lock::DBLock lk(_txn.lockState(), "unittests", MODE_X);
Client::Context ctx(&_txn, ns );
@@ -1071,6 +1073,7 @@ namespace QueryTests {
class DirectLocking : public ClientBase {
public:
void run() {
+ ScopedTransaction transaction(&_txn, MODE_X);
Lock::GlobalWrite lk(_txn.lockState());
Client::Context ctx(&_txn, "unittests.DirectLocking");
_client.remove( "a.b", BSONObj() );
diff --git a/src/mongo/dbtests/repltests.cpp b/src/mongo/dbtests/repltests.cpp
index 25e677ee3bd..f8ebd0d45bd 100644
--- a/src/mongo/dbtests/repltests.cpp
+++ b/src/mongo/dbtests/repltests.cpp
@@ -131,6 +131,7 @@ namespace ReplTests {
return _client.findOne( cllNS(), BSONObj() );
}
int count() const {
+ ScopedTransaction transaction(&_txn, MODE_X);
Lock::GlobalWrite lk(_txn.lockState());
Client::Context ctx(&_txn, ns() );
Database* db = ctx.db();
@@ -151,6 +152,7 @@ namespace ReplTests {
}
int opCount() {
OperationContextImpl txn;
+ ScopedTransaction transaction(&txn, MODE_X);
Lock::GlobalWrite lk(txn.lockState());
Client::Context ctx(&txn, cllNS() );
@@ -171,6 +173,7 @@ namespace ReplTests {
return count;
}
void applyAllOperations() {
+ ScopedTransaction transaction(&_txn, MODE_X);
Lock::GlobalWrite lk(_txn.lockState());
vector< BSONObj > ops;
{
@@ -202,6 +205,7 @@ namespace ReplTests {
}
}
void printAll( const char *ns ) {
+ ScopedTransaction transaction(&_txn, MODE_X);
Lock::GlobalWrite lk(_txn.lockState());
Client::Context ctx(&_txn, ns );
@@ -223,6 +227,7 @@ namespace ReplTests {
}
// These deletes don't get logged.
void deleteAll( const char *ns ) const {
+ ScopedTransaction transaction(&_txn, MODE_X);
Lock::GlobalWrite lk(_txn.lockState());
Client::Context ctx(&_txn, ns );
WriteUnitOfWork wunit(&_txn);
@@ -244,6 +249,7 @@ namespace ReplTests {
wunit.commit();
}
void insert( const BSONObj &o ) const {
+ ScopedTransaction transaction(&_txn, MODE_X);
Lock::GlobalWrite lk(_txn.lockState());
Client::Context ctx(&_txn, ns() );
WriteUnitOfWork wunit(&_txn);
@@ -1409,6 +1415,7 @@ namespace ReplTests {
bool threw = false;
BSONObj o = BSON("ns" << ns() << "o" << BSON("foo" << "bar") << "o2" << BSON("_id" << "in oplog" << "foo" << "bar"));
+ ScopedTransaction transaction(&_txn, MODE_X);
Lock::GlobalWrite lk(_txn.lockState());
// this should fail because we can't connect
diff --git a/src/mongo/dbtests/rollbacktests.cpp b/src/mongo/dbtests/rollbacktests.cpp
index 793ad9389e8..684f824b4a1 100644
--- a/src/mongo/dbtests/rollbacktests.cpp
+++ b/src/mongo/dbtests/rollbacktests.cpp
@@ -46,6 +46,7 @@ namespace RollbackTests {
namespace {
void dropDatabase( OperationContext* txn, const NamespaceString& nss ) {
+ ScopedTransaction transaction(txn, MODE_X);
Lock::GlobalWrite globalWriteLock( txn->lockState() );
Database* db = dbHolder().get( txn, nss.db() );
@@ -60,6 +61,7 @@ namespace {
return std::find( names.begin(), names.end(), ns ) != names.end();
}
void createCollection( OperationContext* txn, const NamespaceString& nss ) {
+ ScopedTransaction transaction( txn, MODE_IX );
Lock::DBLock dbXLock( txn->lockState(), nss.db(), MODE_X );
Client::Context ctx( txn, nss.ns() );
{
@@ -155,6 +157,7 @@ namespace {
NamespaceString nss( ns );
dropDatabase( &txn, nss );
+ ScopedTransaction transaction(&txn, MODE_IX);
Lock::DBLock dbXLock( txn.lockState(), nss.db(), MODE_X );
Client::Context ctx( &txn, ns );
{
@@ -184,6 +187,7 @@ namespace {
NamespaceString nss( ns );
dropDatabase( &txn, nss );
+ ScopedTransaction transaction(&txn, MODE_IX);
Lock::DBLock dbXLock( txn.lockState(), nss.db(), MODE_X );
Client::Context ctx( &txn, ns );
{
@@ -225,6 +229,7 @@ namespace {
dropDatabase( &txn, source );
dropDatabase( &txn, target );
+ ScopedTransaction transaction(&txn, MODE_X);
Lock::GlobalWrite globalWriteLock( txn.lockState() );
Client::Context ctx( &txn, source );
@@ -272,6 +277,7 @@ namespace {
dropDatabase( &txn, source );
dropDatabase( &txn, target );
+ ScopedTransaction transaction(&txn, MODE_X);
Lock::GlobalWrite globalWriteLock( txn.lockState() );
Client::Context ctx( &txn, source );
@@ -332,6 +338,7 @@ namespace {
OperationContextImpl txn;
dropDatabase( &txn, nss );
+ ScopedTransaction transaction(&txn, MODE_IX);
Lock::DBLock dbXLock( txn.lockState(), nss.db(), MODE_X );
Client::Context ctx( &txn, nss );
@@ -382,6 +389,7 @@ namespace {
OperationContextImpl txn;
dropDatabase( &txn, nss );
+ ScopedTransaction transaction(&txn, MODE_IX);
Lock::DBLock dbXLock( txn.lockState(), nss.db(), MODE_X );
Client::Context ctx( &txn, nss );
@@ -416,6 +424,7 @@ namespace {
OperationContextImpl txn;
dropDatabase( &txn, nss );
+ ScopedTransaction transaction(&txn, MODE_IX);
Lock::DBLock dbXLock( txn.lockState(), nss.db(), MODE_X );
Client::Context ctx( &txn, nss );
@@ -467,6 +476,7 @@ namespace {
dropDatabase( &txn, nss );
createCollection( &txn, nss );
+ ScopedTransaction transaction(&txn, MODE_IX);
Lock::DBLock dbIXLock( txn.lockState(), nss.db(), MODE_IX );
Lock::CollectionLock collXLock( txn.lockState(), ns, MODE_X );
@@ -509,6 +519,7 @@ namespace {
dropDatabase( &txn, nss );
createCollection( &txn, nss );
+ ScopedTransaction transaction(&txn, MODE_IX);
Lock::DBLock dbIXLock( txn.lockState(), nss.db(), MODE_IX );
Lock::CollectionLock collXLock( txn.lockState(), ns, MODE_X );
@@ -563,6 +574,7 @@ namespace {
dropDatabase( &txn, nss );
createCollection( &txn, nss );
+ ScopedTransaction transaction(&txn, MODE_IX);
Lock::DBLock dbIXLock( txn.lockState(), nss.db(), MODE_IX );
Lock::CollectionLock collXLock( txn.lockState(), ns, MODE_X );
@@ -607,6 +619,7 @@ namespace {
dropDatabase( &txn, nss );
createCollection( &txn, nss );
+ ScopedTransaction transaction(&txn, MODE_IX);
Lock::DBLock dbIXLock( txn.lockState(), nss.db(), MODE_IX );
Lock::CollectionLock collXLock( txn.lockState(), ns, MODE_X );
@@ -669,6 +682,7 @@ namespace {
OperationContextImpl txn;
NamespaceString nss( ns );
dropDatabase( &txn, nss );
+ ScopedTransaction transaction(&txn, MODE_IX);
Lock::DBLock dbXLock( txn.lockState(), nss.db(), MODE_X );
Client::Context ctx( &txn, nss.ns() );
string idxNameA = "indexA";
diff --git a/src/mongo/s/d_merge.cpp b/src/mongo/s/d_merge.cpp
index e1cc54b6cea..87682902f8e 100644
--- a/src/mongo/s/d_merge.cpp
+++ b/src/mongo/s/d_merge.cpp
@@ -295,6 +295,7 @@ namespace mongo {
//
{
+ ScopedTransaction transaction(txn, MODE_IX);
Lock::DBLock writeLk(txn->lockState(), nss.db(), MODE_IX);
Lock::CollectionLock collLock(txn->lockState(), nss.ns(), MODE_X);
shardingState.mergeChunks(txn, nss.ns(), minKey, maxKey, mergeVersion);
diff --git a/src/mongo/s/d_migrate.cpp b/src/mongo/s/d_migrate.cpp
index 528f57764d8..d76a32997cd 100644
--- a/src/mongo/s/d_migrate.cpp
+++ b/src/mongo/s/d_migrate.cpp
@@ -298,6 +298,7 @@ namespace mongo {
// TODO: Change this. This is a bad hack for protecting some of the data structures
// below that were not properly synchronized with the intended latches in some
// usages.
+ ScopedTransaction transaction(txn, MODE_IX);
Lock::DBLock dbLock(txn->lockState(), nsToDatabaseSubstring(_ns), MODE_IX);
Lock::CollectionLock collLock(txn->lockState(), _ns, MODE_X);
log() << "MigrateFromStatus::done coll lock for " << _ns << " acquired" << endl;
@@ -1312,6 +1313,7 @@ namespace mongo {
myVersion.incMajor();
{
+ ScopedTransaction transaction(txn, MODE_IX);
Lock::DBLock lk(txn->lockState(), nsToDatabaseSubstring(ns), MODE_IX);
Lock::CollectionLock collLock(txn->lockState(), ns, MODE_X);
verify( myVersion > shardingState.getVersion( ns ) );
@@ -1348,6 +1350,7 @@ namespace mongo {
log() << "moveChunk migrate commit not accepted by TO-shard: " << res
<< " resetting shard version to: " << origShardVersion << migrateLog;
{
+ ScopedTransaction transaction(txn, MODE_IX);
Lock::DBLock dbLock(txn->lockState(), nsToDatabaseSubstring(ns), MODE_IX);
Lock::CollectionLock collLock(txn->lockState(), ns, MODE_X);
@@ -1522,6 +1525,7 @@ namespace mongo {
<< "failed migration" << endl;
{
+ ScopedTransaction transaction(txn, MODE_IX);
Lock::DBLock dbLock(txn->lockState(), nsToDatabaseSubstring(ns), MODE_IX);
Lock::CollectionLock collLock(txn->lockState(), ns, MODE_X);
@@ -1730,6 +1734,7 @@ namespace mongo {
if ( getState() != DONE ) {
// Unprotect the range if needed/possible on unsuccessful TO migration
+ ScopedTransaction transaction(txn, MODE_IX);
Lock::DBLock dbLock(txn->lockState(), nsToDatabaseSubstring(ns), MODE_IX);
Lock::CollectionLock collLock(txn->lockState(), ns, MODE_X);
@@ -1791,6 +1796,7 @@ namespace mongo {
indexSpecs.insert(indexSpecs.begin(), indexes.begin(), indexes.end());
}
+ ScopedTransaction transaction(txn, MODE_IX);
Lock::DBLock lk(txn->lockState(), nsToDatabaseSubstring(ns), MODE_X);
Client::Context ctx(txn, ns);
Database* db = ctx.db();
@@ -1876,6 +1882,7 @@ namespace mongo {
{
// Protect the range by noting that we're now starting a migration to it
+ ScopedTransaction transaction(txn, MODE_IX);
Lock::DBLock dbLock(txn->lockState(), nsToDatabaseSubstring(ns), MODE_IX);
Lock::CollectionLock collLock(txn->lockState(), ns, MODE_X);
@@ -2159,6 +2166,7 @@ namespace mongo {
bool didAnything = false;
if ( xfer["deleted"].isABSONObj() ) {
+ ScopedTransaction transaction(txn, MODE_IX);
Lock::DBLock dlk(txn->lockState(), nsToDatabaseSubstring(ns), MODE_IX);
Helpers::RemoveSaver rs( "moveChunk" , ns , "removedDuring" );
@@ -2290,6 +2298,7 @@ namespace mongo {
{
// Get global lock to wait for write to be commited to journal.
+ ScopedTransaction transaction(txn, MODE_S);
Lock::GlobalRead lk(txn->lockState());
// if durability is on, force a write to journal
diff --git a/src/mongo/s/d_split.cpp b/src/mongo/s/d_split.cpp
index 428f94eff19..fc897132594 100644
--- a/src/mongo/s/d_split.cpp
+++ b/src/mongo/s/d_split.cpp
@@ -793,6 +793,7 @@ namespace mongo {
//
{
+ ScopedTransaction transaction(txn, MODE_IX);
Lock::DBLock writeLk(txn->lockState(), nsToDatabaseSubstring(ns), MODE_IX);
Lock::CollectionLock collLock(txn->lockState(), ns, MODE_X);
diff --git a/src/mongo/s/d_state.cpp b/src/mongo/s/d_state.cpp
index 0fe9b482132..b6e3c55663c 100644
--- a/src/mongo/s/d_state.cpp
+++ b/src/mongo/s/d_state.cpp
@@ -595,6 +595,7 @@ namespace mongo {
{
// Exclusive collection lock needed since we're now potentially changing the metadata,
// and don't want reads/writes to be ongoing.
+ ScopedTransaction transaction(txn, MODE_IX);
Lock::DBLock dbLock(txn->lockState(), nsToDatabaseSubstring(ns), MODE_IX);
Lock::CollectionLock collLock(txn->lockState(), ns, MODE_X);
@@ -977,6 +978,7 @@ namespace mongo {
return true;
}
+ ScopedTransaction transaction(txn, MODE_X);
Lock::GlobalWrite lk(txn->lockState());
return checkConfigOrInit(txn, configdb, authoritative, errmsg, result, true);
}
@@ -1265,6 +1267,7 @@ namespace mongo {
}
bool run(OperationContext* txn, const string& dbname, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool) {
+ ScopedTransaction transaction(txn, MODE_IX);
Lock::DBLock dbXLock(txn->lockState(), dbname, MODE_X);
Client::Context ctx(txn, dbname);