summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMathias Stearn <mathias@10gen.com>2014-05-01 15:09:02 -0400
committerMathias Stearn <mathias@10gen.com>2014-05-14 13:58:01 -0400
commit6378da06b637dbf86f916274c8f0457d925af6a9 (patch)
treeb07693c3b786ad9eef3e17fe1a6a670f9229cd44 /src
parent304534f11a265d8c18d788623185340c001cc26e (diff)
downloadmongo-6378da06b637dbf86f916274c8f0457d925af6a9.tar.gz
SERVER-13641 Pull TransactionExperiment up to top level request processor
Diffstat (limited to 'src')
-rw-r--r--src/mongo/db/cloner.cpp15
-rw-r--r--src/mongo/db/commands.cpp9
-rw-r--r--src/mongo/db/commands.h30
-rw-r--r--src/mongo/db/commands/apply_ops.cpp7
-rw-r--r--src/mongo/db/commands/cleanup_orphaned_cmd.cpp12
-rw-r--r--src/mongo/db/commands/collection_to_capped.cpp18
-rw-r--r--src/mongo/db/commands/compact.cpp5
-rw-r--r--src/mongo/db/commands/create_indexes.cpp11
-rw-r--r--src/mongo/db/commands/drop_indexes.cpp14
-rw-r--r--src/mongo/db/commands/find_and_modify.cpp21
-rw-r--r--src/mongo/db/commands/mr.cpp14
-rw-r--r--src/mongo/db/commands/rename_collection.cpp9
-rw-r--r--src/mongo/db/commands/test_commands.cpp19
-rw-r--r--src/mongo/db/commands/touch.cpp6
-rw-r--r--src/mongo/db/commands/validate.cpp5
-rw-r--r--src/mongo/db/commands/write_commands/batch_executor.cpp83
-rw-r--r--src/mongo/db/commands/write_commands/batch_executor.h6
-rw-r--r--src/mongo/db/commands/write_commands/write_commands.cpp6
-rw-r--r--src/mongo/db/commands/write_commands/write_commands.h4
-rw-r--r--src/mongo/db/db.cpp9
-rw-r--r--src/mongo/db/dbcommands.cpp62
-rw-r--r--src/mongo/db/dbhelpers.cpp10
-rw-r--r--src/mongo/db/dbhelpers.h3
-rw-r--r--src/mongo/db/dbwebserver.cpp38
-rw-r--r--src/mongo/db/dbwebserver.h7
-rw-r--r--src/mongo/db/instance.cpp72
-rw-r--r--src/mongo/db/instance.h11
-rw-r--r--src/mongo/db/query/new_find.cpp13
-rw-r--r--src/mongo/db/query/new_find.h8
-rw-r--r--src/mongo/db/range_deleter.cpp34
-rw-r--r--src/mongo/db/range_deleter.h11
-rw-r--r--src/mongo/db/range_deleter_db_env.cpp6
-rw-r--r--src/mongo/db/range_deleter_db_env.h3
-rw-r--r--src/mongo/db/range_deleter_mock_env.cpp3
-rw-r--r--src/mongo/db/range_deleter_mock_env.h3
-rw-r--r--src/mongo/db/range_deleter_stat_test.cpp16
-rw-r--r--src/mongo/db/range_deleter_test.cpp40
-rw-r--r--src/mongo/db/repl/oplog.cpp2
-rw-r--r--src/mongo/db/repl/replset_web_handler.cpp3
-rw-r--r--src/mongo/db/repl/resync.cpp6
-rw-r--r--src/mongo/db/restapi.cpp3
-rw-r--r--src/mongo/db/storage/mmap_v1/dur_transaction.cpp4
-rw-r--r--src/mongo/db/storage/mmap_v1/dur_transaction.h5
-rw-r--r--src/mongo/db/storage/transaction.h17
-rw-r--r--src/mongo/dbtests/dbhelper_tests.cpp4
-rw-r--r--src/mongo/dbtests/querytests.cpp3
-rw-r--r--src/mongo/s/commands_public.cpp3
-rw-r--r--src/mongo/s/d_migrate.cpp50
-rw-r--r--src/mongo/s/s_only.cpp10
-rw-r--r--src/mongo/s/server.cpp4
50 files changed, 462 insertions, 295 deletions
diff --git a/src/mongo/db/cloner.cpp b/src/mongo/db/cloner.cpp
index 37d28f334ad..96dfea73572 100644
--- a/src/mongo/db/cloner.cpp
+++ b/src/mongo/db/cloner.cpp
@@ -558,7 +558,7 @@ namespace mongo {
return Status::OK();
}
CmdClone() : Command("clone") { }
- virtual bool run(const string& dbname , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
+ virtual bool newRun(TransactionExperiment* txn, const string& dbname , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
string from = cmdObj.getStringField("clone");
if ( from.empty() )
return false;
@@ -583,10 +583,9 @@ namespace mongo {
Lock::DBWrite dbXLock(dbname);
Client::Context context( dbname );
- DurTransaction txn;
Cloner cloner;
- bool rval = cloner.go(&txn, context, from, opts, &clonedColls, errmsg);
+ bool rval = cloner.go(txn, context, from, opts, &clonedColls, errmsg);
BSONArrayBuilder barr;
barr.append( clonedColls );
@@ -630,7 +629,7 @@ namespace mongo {
"is placed at the same db.collection (namespace) as the source.\n"
;
}
- virtual bool run(const string& dbname , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
+ virtual bool newRun(TransactionExperiment* txn, const string& dbname , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
string fromhost = cmdObj.getStringField("from");
if ( fromhost.empty() ) {
errmsg = "missing 'from' parameter";
@@ -666,8 +665,7 @@ namespace mongo {
cloner.setConnection( myconn.release() );
- DurTransaction txn;
- return cloner.copyCollection(&txn, collection, query, errmsg, true, false, copyIndexes);
+ return cloner.copyCollection(txn, collection, query, errmsg, true, false, copyIndexes);
}
} cmdCloneCollection;
@@ -782,7 +780,7 @@ namespace mongo {
help << "usage: {copydb: 1, fromhost: <connection string>, fromdb: <db>, todb: <db>"
<< "[, slaveOk: <bool>, username: <username>, nonce: <nonce>, key: <key>]}";
}
- virtual bool run(const string& dbname, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
+ virtual bool newRun(TransactionExperiment* txn, const string& dbname, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
string fromhost = cmdObj.getStringField("fromhost");
bool fromSelf = fromhost.empty();
if ( fromSelf ) {
@@ -813,7 +811,6 @@ namespace mongo {
static_cast<Lock::ScopedLock*>( new Lock::GlobalWrite() ) :
static_cast<Lock::ScopedLock*>( new Lock::DBWrite( todb ) ) );
- DurTransaction txn;
Cloner cloner;
string username = cmdObj.getStringField( "username" );
@@ -847,7 +844,7 @@ namespace mongo {
cloner.setConnection(conn);
}
Client::Context ctx(todb);
- return cloner.go(&txn, ctx, fromhost, cloneOptions, NULL, errmsg );
+ return cloner.go(txn, ctx, fromhost, cloneOptions, NULL, errmsg );
}
} cmdCopyDB;
diff --git a/src/mongo/db/commands.cpp b/src/mongo/db/commands.cpp
index 045e475568f..27aba2bf5ae 100644
--- a/src/mongo/db/commands.cpp
+++ b/src/mongo/db/commands.cpp
@@ -90,6 +90,15 @@ namespace mongo {
return ResourcePattern::forExactNamespace(NamespaceString(ns));
}
+ bool Command::newRun(TransactionExperiment* txn,
+ const string& db,
+ BSONObj& cmdObj,
+ int options,
+ string& errmsg,
+ BSONObjBuilder& result,
+ bool fromRepl) {
+ return run(db, cmdObj, options, errmsg, result, fromRepl);
+ }
void Command::htmlHelp(stringstream& ss) const {
string helpStr;
diff --git a/src/mongo/db/commands.h b/src/mongo/db/commands.h
index a679dc3e5ff..36fc09d3bd1 100644
--- a/src/mongo/db/commands.h
+++ b/src/mongo/db/commands.h
@@ -33,6 +33,7 @@ namespace mongo {
class Client;
class Database;
class Timer;
+ class TransactionExperiment;
namespace mutablebson {
class Document;
@@ -70,8 +71,16 @@ namespace mutablebson {
normally do not want to log the command to the local oplog.
return value is true if succeeded. if false, set errmsg text.
+
+ Default impl forwards to private run(). It will go away soon.
*/
- virtual bool run(const string& db, BSONObj& cmdObj, int options, string& errmsg, BSONObjBuilder& result, bool fromRepl = false ) = 0;
+ virtual bool newRun(TransactionExperiment* txn,
+ const string& db,
+ BSONObj& cmdObj,
+ int options,
+ string& errmsg,
+ BSONObjBuilder& result,
+ bool fromRepl = false );
/**
* This designation for the command is only used by the 'help' call and has nothing to do
@@ -192,7 +201,8 @@ namespace mutablebson {
int queryOptions = 0);
static Command * findCommand( const string& name );
// For mongod and webserver.
- static void execCommand(Command* c,
+ static void execCommand(TransactionExperiment* txn,
+ Command* c,
Client& client,
int queryOptions,
const char *ns,
@@ -200,7 +210,8 @@ namespace mutablebson {
BSONObjBuilder& result,
bool fromRepl );
// For mongos
- static void execCommandClientBasic(Command* c,
+ static void execCommandClientBasic(TransactionExperiment* txn,
+ Command* c,
ClientBasic& client,
int queryOptions,
const char *ns,
@@ -223,6 +234,11 @@ namespace mutablebson {
static int testCommandsEnabled;
private:
+ // This method is deprecated. It should only be used by commands that don't transactions
+ virtual bool run(const string& db, BSONObj& cmdObj, int options, string& errmsg, BSONObjBuilder& result, bool fromRepl = false ) {
+ invariant(false);
+ }
+
/**
* Checks to see if the client is authorized to run the given command with the given
* parameters on the given named database.
@@ -242,6 +258,12 @@ namespace mutablebson {
bool fromRepl);
};
- bool _runCommands(const char *ns, BSONObj& jsobj, BufBuilder &b, BSONObjBuilder& anObjBuilder, bool fromRepl, int queryOptions);
+ bool _runCommands(TransactionExperiment* txn,
+ const char* ns,
+ BSONObj& jsobj,
+ BufBuilder& b,
+ BSONObjBuilder& anObjBuilder,
+ bool fromRepl,
+ int queryOptions);
} // namespace mongo
diff --git a/src/mongo/db/commands/apply_ops.cpp b/src/mongo/db/commands/apply_ops.cpp
index a189af5db6f..b86d8716d08 100644
--- a/src/mongo/db/commands/apply_ops.cpp
+++ b/src/mongo/db/commands/apply_ops.cpp
@@ -59,7 +59,7 @@ namespace mongo {
// applyOps can do pretty much anything, so require all privileges.
RoleGraph::generateUniversalPrivileges(out);
}
- virtual bool run(const string& dbname, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
+ virtual bool newRun(TransactionExperiment* txn, const string& dbname, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
if ( cmdObj.firstElement().type() != Array ) {
errmsg = "ops has to be an array";
@@ -84,7 +84,6 @@ 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
Lock::GlobalWrite globalWriteLock;
- DurTransaction txn;
// Preconditions check reads the database state, so needs to be done locked
if ( cmdObj["preCondition"].type() == Array ) {
@@ -132,7 +131,7 @@ namespace mongo {
invariant(Lock::nested());
Client::Context ctx(ns);
- bool failed = applyOperation_inlock(&txn, ctx.db(), temp, false, alwaysUpsert);
+ bool failed = applyOperation_inlock(txn, ctx.db(), temp, false, alwaysUpsert);
ab.append(!failed);
if ( failed )
errors++;
@@ -163,7 +162,7 @@ namespace mongo {
}
}
- logOp(&txn, "c", tempNS.c_str(), cmdBuilder.done());
+ logOp(txn, "c", tempNS.c_str(), cmdBuilder.done());
}
return errors == 0;
diff --git a/src/mongo/db/commands/cleanup_orphaned_cmd.cpp b/src/mongo/db/commands/cleanup_orphaned_cmd.cpp
index 5a851307535..fcc81a00c59 100644
--- a/src/mongo/db/commands/cleanup_orphaned_cmd.cpp
+++ b/src/mongo/db/commands/cleanup_orphaned_cmd.cpp
@@ -61,7 +61,8 @@ namespace mongo {
*
* If the collection is not sharded, returns CleanupResult_Done.
*/
- CleanupResult cleanupOrphanedData( const NamespaceString& ns,
+ CleanupResult cleanupOrphanedData( TransactionExperiment* txn,
+ const NamespaceString& ns,
const BSONObj& startingFromKeyConst,
bool secondaryThrottle,
BSONObj* stoppedAtKey,
@@ -116,7 +117,8 @@ namespace mongo {
// Metadata snapshot may be stale now, but deleter checks metadata again in write lock
// before delete.
- if ( !getDeleter()->deleteNow( ns.toString(),
+ if ( !getDeleter()->deleteNow( txn,
+ ns.toString(),
orphanRange.minKey,
orphanRange.maxKey,
keyPattern,
@@ -177,7 +179,8 @@ namespace mongo {
// Output
static BSONField<BSONObj> stoppedAtKeyField;
- bool run( string const &db,
+ bool newRun( TransactionExperiment* txn,
+ string const &db,
BSONObj &cmdObj,
int,
string &errmsg,
@@ -231,7 +234,8 @@ namespace mongo {
}
BSONObj stoppedAtKey;
- CleanupResult cleanupResult = cleanupOrphanedData( NamespaceString( ns ),
+ CleanupResult cleanupResult = cleanupOrphanedData( txn,
+ NamespaceString( ns ),
startingFromKey,
secondaryThrottle,
&stoppedAtKey,
diff --git a/src/mongo/db/commands/collection_to_capped.cpp b/src/mongo/db/commands/collection_to_capped.cpp
index 0ed6f1bc15d..f1a375e6694 100644
--- a/src/mongo/db/commands/collection_to_capped.cpp
+++ b/src/mongo/db/commands/collection_to_capped.cpp
@@ -142,7 +142,7 @@ namespace mongo {
NamespaceString(dbname, collection)),
targetActions));
}
- bool run(const string& dbname, BSONObj& jsobj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl ) {
+ bool newRun(TransactionExperiment* txn, const string& dbname, BSONObj& jsobj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl ) {
string from = jsobj.getStringField( "cloneCollectionAsCapped" );
string to = jsobj.getStringField( "toCollection" );
double size = jsobj.getField( "size" ).number();
@@ -155,9 +155,8 @@ namespace mongo {
Lock::DBWrite dbXLock(dbname);
Client::Context ctx(dbname);
- DurTransaction txn;
- Status status = cloneCollectionAsCapped( &txn, ctx.db(), from, to, size, temp, true );
+ Status status = cloneCollectionAsCapped( txn, ctx.db(), from, to, size, temp, true );
return appendCommandStatus( result, status );
}
} cmdCloneCollectionAsCapped;
@@ -197,12 +196,11 @@ namespace mongo {
return std::vector<BSONObj>();
}
- bool run(const string& dbname, BSONObj& jsobj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl ) {
+ bool newRun(TransactionExperiment* txn, const string& dbname, BSONObj& jsobj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl ) {
// calls renamecollection which does a global lock, so we must too:
//
Lock::GlobalWrite globalWriteLock;
Client::Context ctx(dbname);
- DurTransaction txn;
Database* db = ctx.db();
@@ -222,28 +220,28 @@ namespace mongo {
string longTmpName = str::stream() << dbname << "." << shortTmpName;
if ( db->getCollection( longTmpName ) ) {
- Status status = db->dropCollection( &txn, longTmpName );
+ Status status = db->dropCollection( txn, longTmpName );
if ( !status.isOK() )
return appendCommandStatus( result, status );
}
- Status status = cloneCollectionAsCapped( &txn, db, shortSource, shortTmpName, size, true, false );
+ Status status = cloneCollectionAsCapped( txn, db, shortSource, shortTmpName, size, true, false );
if ( !status.isOK() )
return appendCommandStatus( result, status );
verify( db->getCollection( longTmpName ) );
- status = db->dropCollection( &txn, longSource );
+ status = db->dropCollection( txn, longSource );
if ( !status.isOK() )
return appendCommandStatus( result, status );
- status = db->renameCollection( &txn, longTmpName, longSource, false );
+ status = db->renameCollection( txn, longTmpName, longSource, false );
if ( !status.isOK() )
return appendCommandStatus( result, status );
if (!fromRepl)
- logOp(&txn, "c",(dbname + ".$cmd").c_str(), jsobj);
+ logOp(txn, "c",(dbname + ".$cmd").c_str(), jsobj);
return true;
}
} cmdConvertToCapped;
diff --git a/src/mongo/db/commands/compact.cpp b/src/mongo/db/commands/compact.cpp
index 97508e62b5f..a469347d677 100644
--- a/src/mongo/db/commands/compact.cpp
+++ b/src/mongo/db/commands/compact.cpp
@@ -83,7 +83,7 @@ namespace mongo {
return IndexBuilder::killMatchingIndexBuilds(db->getCollection(ns), criteria);
}
- virtual bool run(const string& db, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
+ virtual bool newRun(TransactionExperiment* txn, const string& db, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
string coll = cmdObj.firstElement().valuestr();
if( coll.empty() || db.empty() ) {
errmsg = "no collection name specified";
@@ -145,7 +145,6 @@ namespace mongo {
Lock::DBWrite lk(ns.ns());
BackgroundOperation::assertNoBgOpInProgForNs(ns.ns());
Client::Context ctx(ns);
- DurTransaction txn;
Collection* collection = ctx.db()->getCollection(ns.ns());
if( ! collection ) {
@@ -162,7 +161,7 @@ namespace mongo {
std::vector<BSONObj> indexesInProg = stopIndexBuilds(ctx.db(), cmdObj);
- StatusWith<CompactStats> status = collection->compact( &txn, &compactOptions );
+ StatusWith<CompactStats> status = collection->compact( txn, &compactOptions );
if ( !status.isOK() )
return appendCommandStatus( result, status.getStatus() );
diff --git a/src/mongo/db/commands/create_indexes.cpp b/src/mongo/db/commands/create_indexes.cpp
index ddc9fa9b535..06b0b6e20b7 100644
--- a/src/mongo/db/commands/create_indexes.cpp
+++ b/src/mongo/db/commands/create_indexes.cpp
@@ -70,7 +70,7 @@ namespace mongo {
return b.obj();
}
- virtual bool run( const string& dbname, BSONObj& cmdObj, int options,
+ virtual bool newRun(TransactionExperiment* txn, const string& dbname, BSONObj& cmdObj, int options,
string& errmsg, BSONObjBuilder& result,
bool fromRepl = false ) {
@@ -167,13 +167,12 @@ namespace mongo {
Client::WriteContext writeContext( ns.ns(),
storageGlobalParams.dbpath,
false /* doVersion */ );
- DurTransaction txn;
Database* db = writeContext.ctx().db();
- Collection* collection = db->getCollection( &txn, ns.ns() );
+ Collection* collection = db->getCollection( txn, ns.ns() );
result.appendBool( "createdCollectionAutomatically", collection == NULL );
if ( !collection ) {
- collection = db->createCollection( &txn, ns.ns() );
+ collection = db->createCollection( txn, ns.ns() );
invariant( collection );
}
@@ -191,7 +190,7 @@ namespace mongo {
}
}
- status = collection->getIndexCatalog()->createIndex(&txn, spec, true);
+ status = collection->getIndexCatalog()->createIndex(txn, spec, true);
if ( status.code() == ErrorCodes::IndexAlreadyExists ) {
if ( !result.hasField( "note" ) )
result.append( "note", "index already exists" );
@@ -205,7 +204,7 @@ namespace mongo {
if ( !fromRepl ) {
std::string systemIndexes = ns.getSystemIndexesCollection();
- logOp( &txn, "i", systemIndexes.c_str(), spec );
+ logOp( txn, "i", systemIndexes.c_str(), spec );
}
}
diff --git a/src/mongo/db/commands/drop_indexes.cpp b/src/mongo/db/commands/drop_indexes.cpp
index f7655fdbcb3..ea60d797f69 100644
--- a/src/mongo/db/commands/drop_indexes.cpp
+++ b/src/mongo/db/commands/drop_indexes.cpp
@@ -92,12 +92,11 @@ namespace mongo {
}
CmdDropIndexes() : Command("dropIndexes", false, "deleteIndexes") { }
- bool run(const string& dbname, BSONObj& jsobj, int, string& errmsg, BSONObjBuilder& anObjBuilder, bool fromRepl) {
+ bool newRun(TransactionExperiment* txn, const string& dbname, BSONObj& jsobj, int, string& errmsg, BSONObjBuilder& anObjBuilder, bool fromRepl) {
Lock::DBWrite dbXLock(dbname);
- DurTransaction txn;
- bool ok = wrappedRun(&txn, dbname, jsobj, errmsg, anObjBuilder);
+ bool ok = wrappedRun(txn, dbname, jsobj, errmsg, anObjBuilder);
if (ok && !fromRepl)
- logOp(&txn, "c",(dbname + ".$cmd").c_str(), jsobj);
+ logOp(txn, "c",(dbname + ".$cmd").c_str(), jsobj);
return ok;
}
bool wrappedRun(TransactionExperiment* txn,
@@ -213,7 +212,7 @@ namespace mongo {
return IndexBuilder::killMatchingIndexBuilds(db->getCollection(ns), criteria);
}
- bool run(const string& dbname , BSONObj& jsobj, int, string& errmsg, BSONObjBuilder& result, bool /*fromRepl*/) {
+ bool newRun(TransactionExperiment* txn, const string& dbname , BSONObj& jsobj, int, string& errmsg, BSONObjBuilder& result, bool /*fromRepl*/) {
static DBDirectClient db;
BSONElement e = jsobj.firstElement();
@@ -223,7 +222,6 @@ namespace mongo {
Lock::DBWrite dbXLock(dbname);
Client::Context ctx(toDeleteNs);
- DurTransaction txn;
Collection* collection = ctx.db()->getCollection( toDeleteNs );
@@ -255,7 +253,7 @@ namespace mongo {
}
result.appendNumber( "nIndexesWas", collection->getIndexCatalog()->numIndexesTotal() );
- Status s = collection->getIndexCatalog()->dropAllIndexes(&txn, true);
+ Status s = collection->getIndexCatalog()->dropAllIndexes(txn, true);
if ( !s.isOK() ) {
errmsg = "dropIndexes failed";
return appendCommandStatus( result, s );
@@ -264,7 +262,7 @@ namespace mongo {
for ( list<BSONObj>::iterator i=all.begin(); i!=all.end(); i++ ) {
BSONObj o = *i;
LOG(1) << "reIndex ns: " << toDeleteNs << " index: " << o << endl;
- Status s = collection->getIndexCatalog()->createIndex(&txn, o, false);
+ Status s = collection->getIndexCatalog()->createIndex(txn, o, false);
if ( !s.isOK() )
return appendCommandStatus( result, s );
}
diff --git a/src/mongo/db/commands/find_and_modify.cpp b/src/mongo/db/commands/find_and_modify.cpp
index 34370d6907a..98aab888860 100644
--- a/src/mongo/db/commands/find_and_modify.cpp
+++ b/src/mongo/db/commands/find_and_modify.cpp
@@ -65,7 +65,7 @@ namespace mongo {
find_and_modify::addPrivilegesRequiredForFindAndModify(this, dbname, cmdObj, out);
}
/* this will eventually replace run, once sort is handled */
- bool runNoDirectClient( const string& dbname, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool) {
+ bool runNoDirectClient( TransactionExperiment* txn, const string& dbname, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool) {
verify( cmdObj["sort"].eoo() );
const string ns = dbname + '.' + cmdObj.firstElement().valuestr();
@@ -96,7 +96,7 @@ namespace mongo {
Lock::DBWrite dbXLock(dbname);
Client::Context ctx(ns);
- return runNoDirectClient( ns ,
+ return runNoDirectClient( txn, ns ,
query , fields , update ,
upsert , returnNew , remove ,
result , errmsg );
@@ -122,7 +122,8 @@ namespace mongo {
result.append( "value" , p.transform( doc ) );
}
- static bool runNoDirectClient(const string& ns,
+ static bool runNoDirectClient(TransactionExperiment* txn,
+ const string& ns,
const BSONObj& queryOriginal,
const BSONObj& fields,
const BSONObj& update,
@@ -134,8 +135,7 @@ namespace mongo {
Lock::DBWrite lk( ns );
Client::Context cx( ns );
- DurTransaction txn;
- Collection* collection = cx.db()->getCollection( &txn, ns );
+ Collection* collection = cx.db()->getCollection( txn, ns );
const WhereCallbackReal whereCallback = WhereCallbackReal(StringData(ns));
@@ -222,7 +222,7 @@ namespace mongo {
if ( remove ) {
_appendHelper(result, doc, found, fields, whereCallback);
if ( found ) {
- deleteObjects(&txn, cx.db(), ns, queryModified, true, true);
+ deleteObjects(txn, cx.db(), ns, queryModified, true, true);
BSONObjBuilder le( result.subobjStart( "lastErrorObject" ) );
le.appendNumber( "n" , 1 );
le.done();
@@ -252,8 +252,7 @@ namespace mongo {
// the shard version below, but for now no
UpdateLifecycleImpl updateLifecycle(false, requestNs);
request.setLifecycle(&updateLifecycle);
- UpdateResult res =
- mongo::update(&txn, cx.db(), request, &cc().curop()->debug());
+ UpdateResult res = mongo::update(txn, cx.db(), request, &cc().curop()->debug());
if ( !collection ) {
// collection created by an upsert
collection = cx.db()->getCollection( ns );
@@ -298,11 +297,11 @@ namespace mongo {
return true;
}
- virtual bool run(const string& dbname, BSONObj& cmdObj, int x, string& errmsg, BSONObjBuilder& result, bool y) {
- static DBDirectClient db;
+ virtual bool newRun(TransactionExperiment* txn, const string& dbname, BSONObj& cmdObj, int x, string& errmsg, BSONObjBuilder& result, bool y) {
+ DBDirectClient db(txn);
if (cmdObj["sort"].eoo()) {
- return runNoDirectClient(dbname, cmdObj, x, errmsg, result, y);
+ return runNoDirectClient(txn, dbname, cmdObj, x, errmsg, result, y);
}
const string ns = dbname + '.' + cmdObj.firstElement().valuestr();
diff --git a/src/mongo/db/commands/mr.cpp b/src/mongo/db/commands/mr.cpp
index 7c39fee77e4..7a540a8a3ef 100644
--- a/src/mongo/db/commands/mr.cpp
+++ b/src/mongo/db/commands/mr.cpp
@@ -1208,7 +1208,7 @@ namespace mongo {
addPrivilegesRequiredForMapReduce(this, dbname, cmdObj, out);
}
- bool run(const string& dbname , BSONObj& cmd, int, string& errmsg, BSONObjBuilder& result, bool fromRepl ) {
+ bool newRun(TransactionExperiment* txn, const string& dbname , BSONObj& cmd, int, string& errmsg, BSONObjBuilder& result, bool fromRepl ) {
Timer t;
Client& client = cc();
CurOp * op = client.curop();
@@ -1240,8 +1240,7 @@ namespace mongo {
BSONObjBuilder countsBuilder;
BSONObjBuilder timingBuilder;
- DurTransaction txn;
- State state( &txn, config );
+ State state( txn, config );
if ( ! state.sourceExists() ) {
errmsg = "ns doesn't exist";
return false;
@@ -1354,7 +1353,7 @@ namespace mongo {
reduceTime += t.micros();
- txn.checkForInterrupt();
+ txn->checkForInterrupt();
}
pm.hit();
@@ -1365,7 +1364,7 @@ namespace mongo {
}
pm.finished();
- txn.checkForInterrupt();
+ txn->checkForInterrupt();
// update counters
countsBuilder.appendNumber("input", numInputs);
@@ -1447,7 +1446,7 @@ namespace mongo {
actions.addAction(ActionType::internal);
out->push_back(Privilege(ResourcePattern::forClusterResource(), actions));
}
- bool run(const string& dbname , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool) {
+ bool newRun(TransactionExperiment* txn, const string& dbname , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool) {
ShardedConnectionInfo::addHook();
// legacy name
string shardedOutputCollection = cmdObj["shardedOutputCollection"].valuestrsafe();
@@ -1464,8 +1463,7 @@ namespace mongo {
CurOp * op = client.curop();
Config config( dbname , cmdObj.firstElement().embeddedObjectUserCheck() );
- DurTransaction txn;
- State state(&txn, config);
+ State state(txn, config);
state.init();
// no need for incremental collection because records are already sorted
diff --git a/src/mongo/db/commands/rename_collection.cpp b/src/mongo/db/commands/rename_collection.cpp
index cd72f781707..07bf511141b 100644
--- a/src/mongo/db/commands/rename_collection.cpp
+++ b/src/mongo/db/commands/rename_collection.cpp
@@ -91,15 +91,14 @@ namespace mongo {
IndexBuilder::restoreIndexes( indexesInProg );
}
- virtual bool run(const string& dbname, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
+ virtual bool newRun(TransactionExperiment* txn, const string& dbname, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
Lock::GlobalWrite globalWriteLock;
- DurTransaction txn;
- bool ok = wrappedRun(&txn, dbname, cmdObj, errmsg, result, fromRepl);
+ bool ok = wrappedRun(txn, dbname, cmdObj, errmsg, result, fromRepl);
if (ok && !fromRepl)
- logOp(&txn, "c",(dbname + ".$cmd").c_str(), cmdObj);
+ logOp(txn, "c",(dbname + ".$cmd").c_str(), cmdObj);
return ok;
}
- virtual bool wrappedRun(DurTransaction* txn,
+ virtual bool wrappedRun(TransactionExperiment* txn,
const string& dbname,
BSONObj& cmdObj,
string& errmsg,
diff --git a/src/mongo/db/commands/test_commands.cpp b/src/mongo/db/commands/test_commands.cpp
index 263b7af7f88..428298868b9 100644
--- a/src/mongo/db/commands/test_commands.cpp
+++ b/src/mongo/db/commands/test_commands.cpp
@@ -55,7 +55,7 @@ namespace mongo {
virtual void help( stringstream &help ) const {
help << "internal. for testing only.";
}
- virtual bool run(const string& dbname, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool) {
+ virtual bool newRun(TransactionExperiment* txn, const string& dbname, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool) {
string coll = cmdObj[ "godinsert" ].valuestrsafe();
log() << "test only command godinsert invoked coll:" << coll << endl;
uassert( 13049, "godinsert must specify a collection", !coll.empty() );
@@ -64,17 +64,16 @@ namespace mongo {
Lock::DBWrite lk(ns);
Client::Context ctx( ns );
- DurTransaction txn;
Database* db = ctx.db();
Collection* collection = db->getCollection( ns );
if ( !collection ) {
- collection = db->createCollection( &txn, ns );
+ collection = db->createCollection( txn, ns );
if ( !collection ) {
errmsg = "could not create collection";
return false;
}
}
- StatusWith<DiskLoc> res = collection->insertDocument( &txn, obj, false );
+ StatusWith<DiskLoc> res = collection->insertDocument( txn, obj, false );
return appendCommandStatus( result, res.getStatus() );
}
};
@@ -134,7 +133,7 @@ namespace mongo {
virtual void addRequiredPrivileges(const std::string& dbname,
const BSONObj& cmdObj,
std::vector<Privilege>* out) {}
- virtual bool run(const string& dbname , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool) {
+ virtual bool newRun(TransactionExperiment* txn, const string& dbname , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool) {
string coll = cmdObj[ "captrunc" ].valuestrsafe();
uassert( 13416, "captrunc must specify a collection", !coll.empty() );
NamespaceString nss( dbname, coll );
@@ -142,7 +141,6 @@ namespace mongo {
bool inc = cmdObj.getBoolField( "inc" ); // inclusive range?
Client::WriteContext ctx( nss.ns() );
- DurTransaction txn;
Collection* collection = ctx.ctx().db()->getCollection( nss.ns() );
massert( 13417, "captrunc collection not found or empty", collection);
@@ -155,7 +153,7 @@ namespace mongo {
Runner::RunnerState state = runner->getNext(NULL, &end);
massert( 13418, "captrunc invalid n", Runner::RUNNER_ADVANCED == state);
}
- collection->temp_cappedTruncateAfter( &txn, end, inc );
+ collection->temp_cappedTruncateAfter( txn, end, inc );
return true;
}
};
@@ -182,27 +180,26 @@ namespace mongo {
return IndexBuilder::killMatchingIndexBuilds(db->getCollection(ns), criteria);
}
- virtual bool run(const string& dbname , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
+ virtual bool newRun(TransactionExperiment* txn, const string& dbname , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
string coll = cmdObj[ "emptycapped" ].valuestrsafe();
uassert( 13428, "emptycapped must specify a collection", !coll.empty() );
NamespaceString nss( dbname, coll );
Client::WriteContext ctx( nss.ns() );
- DurTransaction txn;
Database* db = ctx.ctx().db();
Collection* collection = db->getCollection( nss.ns() );
massert( 13429, "emptycapped no such collection", collection );
std::vector<BSONObj> indexes = stopIndexBuilds(db, cmdObj);
- Status status = collection->truncate(&txn);
+ Status status = collection->truncate(txn);
if ( !status.isOK() )
return appendCommandStatus( result, status );
IndexBuilder::restoreIndexes(indexes);
if (!fromRepl)
- logOp(&txn, "c",(dbname + ".$cmd").c_str(), cmdObj);
+ logOp(txn, "c",(dbname + ".$cmd").c_str(), cmdObj);
return true;
}
};
diff --git a/src/mongo/db/commands/touch.cpp b/src/mongo/db/commands/touch.cpp
index 6427fba7b64..2011758f042 100644
--- a/src/mongo/db/commands/touch.cpp
+++ b/src/mongo/db/commands/touch.cpp
@@ -77,7 +77,8 @@ namespace mongo {
}
TouchCmd() : Command("touch") { }
- virtual bool run(const string& dbname,
+ virtual bool newRun(TransactionExperiment* txn,
+ const string& dbname,
BSONObj& cmdObj,
int,
string& errmsg,
@@ -104,7 +105,6 @@ namespace mongo {
}
Client::ReadContext context( nss.ns() );
- DurTransaction txn;
Database* db = context.ctx().db();
Collection* collection = db->getCollection( nss.ns() );
@@ -114,7 +114,7 @@ namespace mongo {
}
return appendCommandStatus( result,
- collection->touch( &txn,
+ collection->touch( txn,
touch_data, touch_indexes,
&result ) );
}
diff --git a/src/mongo/db/commands/validate.cpp b/src/mongo/db/commands/validate.cpp
index d9d20610b45..3fba9dd4b00 100644
--- a/src/mongo/db/commands/validate.cpp
+++ b/src/mongo/db/commands/validate.cpp
@@ -59,7 +59,7 @@ namespace mongo {
}
//{ validate: "collectionnamewithoutthedbpart" [, scandata: <bool>] [, full: <bool> } */
- bool run(const string& dbname , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl ) {
+ bool newRun(TransactionExperiment* txn, const string& dbname , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl ) {
string ns = dbname + "." + cmdObj.firstElement().valuestrsafe();
NamespaceString ns_string(ns);
@@ -76,7 +76,6 @@ namespace mongo {
}
Client::ReadContext ctx(ns_string.ns());
- DurTransaction txn;
Database* db = ctx.ctx().db();
if ( !db ) {
@@ -93,7 +92,7 @@ namespace mongo {
result.append( "ns", ns );
ValidateResults results;
- Status status = collection->validate( &txn, full, scanData, &results, &result );
+ Status status = collection->validate( txn, full, scanData, &results, &result );
if ( !status.isOK() )
return appendCommandStatus( result, status );
diff --git a/src/mongo/db/commands/write_commands/batch_executor.cpp b/src/mongo/db/commands/write_commands/batch_executor.cpp
index 160ed358bab..d7295a5458f 100644
--- a/src/mongo/db/commands/write_commands/batch_executor.cpp
+++ b/src/mongo/db/commands/write_commands/batch_executor.cpp
@@ -89,10 +89,12 @@ namespace mongo {
using mongoutils::str::stream;
- WriteBatchExecutor::WriteBatchExecutor( const BSONObj& wc,
+ WriteBatchExecutor::WriteBatchExecutor( TransactionExperiment* txn,
+ const BSONObj& wc,
Client* client,
OpCounters* opCounters,
LastError* le ) :
+ _txn(txn),
_defaultWriteConcern( wc ),
_client( client ),
_opCounters( opCounters ),
@@ -577,7 +579,10 @@ namespace mongo {
}
}
- static void finishCurrentOp( Client* client, CurOp* currentOp, WriteErrorDetail* opError ) {
+ static void finishCurrentOp( TransactionExperiment* txn,
+ Client* client,
+ CurOp* currentOp,
+ WriteErrorDetail* opError ) {
currentOp->done();
int executionTime = currentOp->debug().executionTime = currentOp->totalTimeMillis();
@@ -600,8 +605,7 @@ namespace mongo {
}
if ( currentOp->shouldDBProfile( executionTime ) ) {
- DurTransaction txn;
- profile( &txn, *client, currentOp->getOp(), *currentOp );
+ profile( txn, *client, currentOp->getOp(), *currentOp );
}
}
@@ -614,18 +618,23 @@ namespace mongo {
// - error
//
- static void singleInsert( const BSONObj& docToInsert,
+ static void singleInsert( TransactionExperiment* txn,
+ const BSONObj& docToInsert,
Collection* collection,
WriteOpResult* result );
- static void singleCreateIndex( const BSONObj& indexDesc,
+ static void singleCreateIndex( TransactionExperiment* txn,
+ const BSONObj& indexDesc,
Collection* collection,
WriteOpResult* result );
- static void multiUpdate( const BatchItemRef& updateItem,
+ static void multiUpdate( TransactionExperiment* txn,
+ const BatchItemRef& updateItem,
WriteOpResult* result );
- static void multiRemove( const BatchItemRef& removeItem, WriteOpResult* result );
+ static void multiRemove( TransactionExperiment* txn,
+ const BatchItemRef& removeItem,
+ WriteOpResult* result );
//
// WRITE EXECUTION
@@ -644,7 +653,8 @@ namespace mongo {
/**
* Constructs a new instance, for performing inserts described in "aRequest".
*/
- explicit ExecInsertsState(const BatchedCommandRequest* aRequest);
+ explicit ExecInsertsState(TransactionExperiment* txn,
+ const BatchedCommandRequest* aRequest);
/**
* Acquires the write lock and client context needed to perform the current write operation.
@@ -677,6 +687,8 @@ namespace mongo {
*/
Collection* getCollection() { return _collection; }
+ TransactionExperiment* txn;
+
// Request object describing the inserts.
const BatchedCommandRequest* request;
@@ -796,7 +808,7 @@ namespace mongo {
// particularly on operation interruption. These kinds of errors necessarily prevent
// further insertOne calls, and stop the batch. As a result, the only expected source of
// such exceptions are interruptions.
- ExecInsertsState state(&request);
+ ExecInsertsState state(_txn, &request);
normalizeInserts(request, &state.normalizedInserts);
ElapsedTracker elapsedTracker(128, 10); // 128 hits or 10 ms, matching RunnerYieldPolicy's
@@ -832,7 +844,7 @@ namespace mongo {
incOpStats( updateItem );
WriteOpResult result;
- multiUpdate( updateItem, &result );
+ multiUpdate( _txn, updateItem, &result );
if ( !result.getStats().upsertedID.isEmpty() ) {
*upsertedId = result.getStats().upsertedID;
@@ -840,7 +852,7 @@ namespace mongo {
// END CURRENT OP
incWriteStats( updateItem, result.getStats(), result.getError(), currentOp.get() );
- finishCurrentOp( _client, currentOp.get(), result.getError() );
+ finishCurrentOp( _txn, _client, currentOp.get(), result.getError() );
if ( result.getError() ) {
result.getError()->setIndex( updateItem.getItemIndex() );
@@ -859,11 +871,11 @@ namespace mongo {
WriteOpResult result;
- multiRemove( removeItem, &result );
+ multiRemove( _txn, removeItem, &result );
// END CURRENT OP
incWriteStats( removeItem, result.getStats(), result.getError(), currentOp.get() );
- finishCurrentOp( _client, currentOp.get(), result.getError() );
+ finishCurrentOp( _txn, _client, currentOp.get(), result.getError() );
if ( result.getError() ) {
result.getError()->setIndex( removeItem.getItemIndex() );
@@ -875,7 +887,9 @@ namespace mongo {
// IN-DB-LOCK CORE OPERATIONS
//
- WriteBatchExecutor::ExecInsertsState::ExecInsertsState(const BatchedCommandRequest* aRequest) :
+ WriteBatchExecutor::ExecInsertsState::ExecInsertsState(TransactionExperiment* txn,
+ const BatchedCommandRequest* aRequest) :
+ txn(txn),
request(aRequest),
currIndex(0),
_collection(NULL) {
@@ -906,8 +920,7 @@ namespace mongo {
_collection = database->getCollection(request->getTargetingNS());
if (!_collection) {
// Implicitly create if it doesn't exist
- DurTransaction txn;
- _collection = database->createCollection(&txn, request->getTargetingNS());
+ _collection = database->createCollection(txn, request->getTargetingNS());
if (!_collection) {
result->setError(
toWriteError(Status(ErrorCodes::InternalError,
@@ -948,10 +961,10 @@ namespace mongo {
try {
if (state->lockAndCheck(result)) {
if (!state->request->isInsertIndexRequest()) {
- singleInsert(insertDoc, state->getCollection(), result);
+ singleInsert(state->txn, insertDoc, state->getCollection(), result);
}
else {
- singleCreateIndex(insertDoc, state->getCollection(), result);
+ singleCreateIndex(state->txn, insertDoc, state->getCollection(), result);
}
}
}
@@ -989,7 +1002,7 @@ namespace mongo {
result.getStats(),
result.getError(),
currentOp.get());
- finishCurrentOp(_client, currentOp.get(), result.getError());
+ finishCurrentOp(_txn, _client, currentOp.get(), result.getError());
if (result.getError()) {
*error = result.releaseError();
@@ -1002,7 +1015,8 @@ namespace mongo {
*
* Might fault or error, otherwise populates the result.
*/
- static void singleInsert( const BSONObj& docToInsert,
+ static void singleInsert( TransactionExperiment* txn,
+ const BSONObj& docToInsert,
Collection* collection,
WriteOpResult* result ) {
@@ -1010,15 +1024,14 @@ namespace mongo {
Lock::assertWriteLocked( insertNS );
- DurTransaction txn;
- StatusWith<DiskLoc> status = collection->insertDocument( &txn, docToInsert, true );
+ StatusWith<DiskLoc> status = collection->insertDocument( txn, docToInsert, true );
if ( !status.isOK() ) {
result->setError(toWriteError(status.getStatus()));
}
else {
- logOp( &txn, "i", insertNS.c_str(), docToInsert );
- txn.commitIfNeeded();
+ logOp( txn, "i", insertNS.c_str(), docToInsert );
+ txn->commitIfNeeded();
result->getStats().n = 1;
}
}
@@ -1029,16 +1042,16 @@ namespace mongo {
*
* Might fault or error, otherwise populates the result.
*/
- static void singleCreateIndex( const BSONObj& indexDesc,
+ static void singleCreateIndex( TransactionExperiment* txn,
+ const BSONObj& indexDesc,
Collection* collection,
WriteOpResult* result ) {
- DurTransaction txn;
const string indexNS = collection->ns().getSystemIndexesCollection();
Lock::assertWriteLocked( indexNS );
- Status status = collection->getIndexCatalog()->createIndex(&txn, indexDesc, true);
+ Status status = collection->getIndexCatalog()->createIndex(txn, indexDesc, true);
if ( status.code() == ErrorCodes::IndexAlreadyExists ) {
result->getStats().n = 0;
@@ -1047,12 +1060,13 @@ namespace mongo {
result->setError(toWriteError(status));
}
else {
- logOp( &txn, "i", indexNS.c_str(), indexDesc );
+ logOp( txn, "i", indexNS.c_str(), indexDesc );
result->getStats().n = 1;
}
}
- static void multiUpdate( const BatchItemRef& updateItem,
+ static void multiUpdate( TransactionExperiment* txn,
+ const BatchItemRef& updateItem,
WriteOpResult* result ) {
const NamespaceString nsString(updateItem.getRequest()->getNS());
@@ -1082,10 +1096,9 @@ namespace mongo {
Client::Context ctx( nsString.ns(),
storageGlobalParams.dbpath,
false /* don't check version */ );
- DurTransaction txn;
try {
- UpdateResult res = executor.execute(&txn, ctx.db());
+ UpdateResult res = executor.execute(txn, ctx.db());
const long long numDocsModified = res.numDocsModified;
const long long numMatched = res.numMatched;
@@ -1113,7 +1126,8 @@ namespace mongo {
*
* Might fault or error, otherwise populates the result.
*/
- static void multiRemove( const BatchItemRef& removeItem,
+ static void multiRemove( TransactionExperiment* txn,
+ const BatchItemRef& removeItem,
WriteOpResult* result ) {
const NamespaceString nss( removeItem.getRequest()->getNS() );
@@ -1145,10 +1159,9 @@ namespace mongo {
Client::Context writeContext( nss.ns(),
storageGlobalParams.dbpath,
false /* don't check version */);
- DurTransaction txn;
try {
- result->getStats().n = executor.execute(&txn, writeContext.db());
+ result->getStats().n = executor.execute(txn, writeContext.db());
}
catch ( const DBException& ex ) {
status = ex.toStatus();
diff --git a/src/mongo/db/commands/write_commands/batch_executor.h b/src/mongo/db/commands/write_commands/batch_executor.h
index c45443231ef..6406474e396 100644
--- a/src/mongo/db/commands/write_commands/batch_executor.h
+++ b/src/mongo/db/commands/write_commands/batch_executor.h
@@ -43,6 +43,7 @@ namespace mongo {
class BSONObjBuilder;
class CurOp;
class OpCounters;
+ class TransactionExperiment;
struct LastError;
struct WriteOpStats;
@@ -58,7 +59,8 @@ namespace mongo {
// State object used by private execInserts. TODO: Do not expose this type.
class ExecInsertsState;
- WriteBatchExecutor( const BSONObj& defaultWriteConcern,
+ WriteBatchExecutor( TransactionExperiment* txn,
+ const BSONObj& defaultWriteConcern,
Client* client,
OpCounters* opCounters,
LastError* le );
@@ -132,6 +134,8 @@ namespace mongo {
const WriteErrorDetail* error,
CurOp* currentOp );
+ TransactionExperiment* _txn;
+
// Default write concern, if one isn't provide in the batches.
const BSONObj _defaultWriteConcern;
diff --git a/src/mongo/db/commands/write_commands/write_commands.cpp b/src/mongo/db/commands/write_commands/write_commands.cpp
index f64c1fa7545..bcc297cf4b6 100644
--- a/src/mongo/db/commands/write_commands/write_commands.cpp
+++ b/src/mongo/db/commands/write_commands/write_commands.cpp
@@ -102,7 +102,8 @@ namespace mongo {
// Write commands are counted towards their corresponding opcounters, not command opcounters.
bool WriteCmd::shouldAffectCommandCounter() const { return false; }
- bool WriteCmd::run(const string& dbName,
+ bool WriteCmd::newRun(TransactionExperiment* txn,
+ const string& dbName,
BSONObj& cmdObj,
int options,
string& errMsg,
@@ -132,7 +133,8 @@ namespace mongo {
// TODO: fix this for sane behavior where we query repl set object
if ( getLastErrorDefault ) defaultWriteConcern = *getLastErrorDefault;
- WriteBatchExecutor writeBatchExecutor(defaultWriteConcern,
+ WriteBatchExecutor writeBatchExecutor(txn,
+ defaultWriteConcern,
&cc(),
&globalOpCounters,
lastError.get());
diff --git a/src/mongo/db/commands/write_commands/write_commands.h b/src/mongo/db/commands/write_commands/write_commands.h
index f8fccacc439..c94c505d5b5 100644
--- a/src/mongo/db/commands/write_commands/write_commands.h
+++ b/src/mongo/db/commands/write_commands/write_commands.h
@@ -72,7 +72,9 @@ namespace mongo {
virtual bool shouldAffectCommandCounter() const;
// Write command entry point.
- virtual bool run(const string& dbname,
+ virtual bool newRun(
+ TransactionExperiment* txn,
+ const string& dbname,
BSONObj& cmdObj,
int options,
string& errmsg,
diff --git a/src/mongo/db/db.cpp b/src/mongo/db/db.cpp
index 2ee1b36f091..8914bb981d0 100644
--- a/src/mongo/db/db.cpp
+++ b/src/mongo/db/db.cpp
@@ -188,6 +188,7 @@ namespace mongo {
}
virtual void process( Message& m , AbstractMessagingPort* port , LastError * le) {
+ DurTransaction txn;
while ( true ) {
if ( inShutdown() ) {
log() << "got request after shutdown()" << endl;
@@ -197,7 +198,7 @@ namespace mongo {
lastError.startRequest( m , le );
DbResponse dbresponse;
- assembleResponse( m, dbresponse, port->remote() );
+ assembleResponse( &txn, m, dbresponse, port->remote() );
if ( dbresponse.response ) {
port->reply(m, *dbresponse.response, dbresponse.responseTo);
@@ -279,7 +280,9 @@ namespace mongo {
logStartup();
startReplication();
if (serverGlobalParams.isHttpInterfaceEnabled)
- boost::thread web( boost::bind(&webServerThread, new RestAdminAccess() /* takes ownership */));
+ boost::thread web( boost::bind(&webServerThread,
+ new RestAdminAccess(), // takes ownership
+ DurTransaction::factory) ); // XXX SERVER-13931
#if(TESTEXHAUST)
boost::thread thr(testExhaust);
@@ -289,8 +292,8 @@ namespace mongo {
void doDBUpgrade( const string& dbName, DataFileHeader* h ) {
- static DBDirectClient db;
DurTransaction txn;
+ DBDirectClient db(&txn);
if ( h->version == 4 && h->versionMinor == 4 ) {
verify( PDFILE_VERSION == 4 );
diff --git a/src/mongo/db/dbcommands.cpp b/src/mongo/db/dbcommands.cpp
index 97ef4247644..16e59026bee 100644
--- a/src/mongo/db/dbcommands.cpp
+++ b/src/mongo/db/dbcommands.cpp
@@ -68,7 +68,6 @@
#include "mongo/db/repl/is_master.h"
#include "mongo/db/repl/oplog.h"
#include "mongo/db/storage/extent_manager.h"
-#include "mongo/db/storage/mmap_v1/dur_transaction.h"
#include "mongo/db/storage/mmap_v1/mmap_v1_extent_manager.h"
#include "mongo/db/storage/record.h"
#include "mongo/db/structure/catalog/namespace_details.h"
@@ -192,7 +191,7 @@ namespace mongo {
CmdDropDatabase() : Command("dropDatabase") {}
- bool run(const string& dbname, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
+ bool newRun(TransactionExperiment* txn, const string& dbname, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
// disallow dropping the config database
if (serverGlobalParams.configsvr && (dbname == "config")) {
errmsg = "Cannot drop 'config' database if mongod started with --configsvr";
@@ -211,17 +210,16 @@ namespace mongo {
// and that may need a global lock.
Lock::GlobalWrite lk;
Client::Context context(dbname);
- DurTransaction txn;
log() << "dropDatabase " << dbname << " starting" << endl;
stopIndexBuilds(context.db(), cmdObj);
- dropDatabase(&txn, context.db());
+ dropDatabase(txn, context.db());
log() << "dropDatabase " << dbname << " finished";
if (!fromRepl)
- logOp(&txn, "c",(dbname + ".$cmd").c_str(), cmdObj);
+ logOp(txn, "c",(dbname + ".$cmd").c_str(), cmdObj);
}
result.append( "dropped" , dbname );
@@ -277,7 +275,7 @@ namespace mongo {
return allKilledIndexes;
}
- bool run(const string& dbname , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
+ bool newRun(TransactionExperiment* txn, const string& dbname , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
BSONElement e = cmdObj.firstElement();
if ( e.numberInt() != 1 ) {
errmsg = "bad option";
@@ -288,7 +286,6 @@ namespace mongo {
// called within, and that requires a global lock i believe.
Lock::GlobalWrite lk;
Client::Context context( dbname );
- DurTransaction txn;
log() << "repairDatabase " << dbname;
std::vector<BSONObj> indexesInProg = stopIndexBuilds(context.db(), cmdObj);
@@ -298,7 +295,7 @@ namespace mongo {
e = cmdObj.getField( "backupOriginalFiles" );
bool backupOriginalFiles = e.isBoolean() && e.boolean();
Status status =
- repairDatabase( &txn, dbname, preserveClonedFilesOnFailure, backupOriginalFiles );
+ repairDatabase( txn, dbname, preserveClonedFilesOnFailure, backupOriginalFiles );
IndexBuilder::restoreIndexes(indexesInProg);
@@ -354,13 +351,12 @@ namespace mongo {
}
- bool run(const string& dbname, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
+ bool newRun(TransactionExperiment* txn, const string& dbname, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
// Needs to be locked exclusively, because creates the system.profile collection
// in the local database.
//
Lock::DBWrite dbXLock(dbname);
Client::Context ctx(dbname);
- DurTransaction txn;
BSONElement e = cmdObj.firstElement();
result.append("was", ctx.db()->getProfilingLevel());
@@ -372,7 +368,7 @@ namespace mongo {
if ( p == -1 )
ok = true;
else if ( p >= 0 && p <= 2 ) {
- ok = ctx.db()->setProfilingLevel( &txn, p , errmsg );
+ ok = ctx.db()->setProfilingLevel( txn, p , errmsg );
}
BSONElement slow = cmdObj["slowms"];
@@ -452,7 +448,7 @@ namespace mongo {
return IndexBuilder::killMatchingIndexBuilds(db->getCollection(nsToDrop), criteria);
}
- virtual bool run(const string& dbname , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
+ virtual bool newRun(TransactionExperiment* txn, const string& dbname , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
const string nsToDrop = dbname + '.' + cmdObj.firstElement().valuestr();
if (!serverGlobalParams.quiet) {
MONGO_TLOG(0) << "CMD: drop " << nsToDrop << endl;
@@ -465,10 +461,9 @@ namespace mongo {
Lock::DBWrite dbXLock(dbname);
Client::Context ctx(nsToDrop);
- DurTransaction txn;
Database* db = ctx.db();
- Collection* coll = db->getCollection( &txn, nsToDrop );
+ Collection* coll = db->getCollection( txn, nsToDrop );
// If collection does not exist, short circuit and return.
if ( !coll ) {
errmsg = "ns not found";
@@ -482,11 +477,11 @@ namespace mongo {
result.append( "ns", nsToDrop );
result.append( "nIndexesWas", numIndexes );
- Status s = db->dropCollection( &txn, nsToDrop );
+ Status s = db->dropCollection( txn, nsToDrop );
if ( s.isOK() ) {
if (!fromRepl)
- logOp(&txn, "c",(dbname + ".$cmd").c_str(), cmdObj);
+ logOp(txn, "c",(dbname + ".$cmd").c_str(), cmdObj);
return true;
}
@@ -600,7 +595,7 @@ namespace mongo {
return Status(ErrorCodes::Unauthorized, "unauthorized");
}
- virtual bool run(const string& dbname , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl ) {
+ virtual bool newRun(TransactionExperiment* txn, const string& dbname , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl ) {
BSONObjIterator it(cmdObj);
// Extract ns from first cmdObj element.
@@ -630,11 +625,10 @@ namespace mongo {
Lock::DBWrite dbXLock(dbname);
Client::Context ctx(ns);
- DurTransaction txn;
// Create collection.
return appendCommandStatus( result,
- userCreateNS(&txn, ctx.db(), ns.c_str(), options, !fromRepl) );
+ userCreateNS(txn, ctx.db(), ns.c_str(), options, !fromRepl) );
}
} cmdCreate;
@@ -1150,12 +1144,11 @@ namespace mongo {
out->push_back(Privilege(parseResourcePattern(dbname, cmdObj), actions));
}
- bool run(const string& dbname, BSONObj& jsobj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl ) {
+ bool newRun(TransactionExperiment* txn, const string& dbname, BSONObj& jsobj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl ) {
const string ns = dbname + "." + jsobj.firstElement().valuestr();
Lock::DBWrite dbXLock(dbname);
Client::Context ctx( ns );
- DurTransaction txn;
Collection* coll = ctx.db()->getCollection( ns );
if ( !coll ) {
@@ -1181,9 +1174,9 @@ namespace mongo {
result.appendBool( "usePowerOf2Sizes_old", oldPowerOf2 );
if ( newPowerOf2 )
- coll->setUserFlag( &txn, NamespaceDetails::Flag_UsePowerOf2Sizes );
+ coll->setUserFlag( txn, NamespaceDetails::Flag_UsePowerOf2Sizes );
else
- coll->clearUserFlag( &txn, NamespaceDetails::Flag_UsePowerOf2Sizes );
+ coll->clearUserFlag( txn, NamespaceDetails::Flag_UsePowerOf2Sizes );
result.appendBool( "usePowerOf2Sizes_new", newPowerOf2 );
}
@@ -1232,7 +1225,7 @@ namespace mongo {
if ( oldExpireSecs != newExpireSecs ) {
// change expireAfterSeconds
result.appendAs( oldExpireSecs, "expireAfterSeconds_old" );
- coll->getIndexCatalog()->updateTTLSetting( &txn, idx, newExpireSecs.numberLong() );
+ coll->getIndexCatalog()->updateTTLSetting( txn, idx, newExpireSecs.numberLong() );
result.appendAs( newExpireSecs , "expireAfterSeconds_new" );
}
}
@@ -1243,7 +1236,7 @@ namespace mongo {
}
if (ok && !fromRepl)
- logOp(&txn, "c",(dbname + ".$cmd").c_str(), jsobj);
+ logOp(txn, "c",(dbname + ".$cmd").c_str(), jsobj);
return ok;
}
@@ -1394,7 +1387,8 @@ namespace mongo {
} cmdWhatsMyUri;
- bool _execCommand(Command *c,
+ bool _execCommand(TransactionExperiment* txn,
+ Command *c,
const string& dbname,
BSONObj& cmdObj,
int queryOptions,
@@ -1403,7 +1397,7 @@ namespace mongo {
bool fromRepl) {
try {
- return c->run(dbname, cmdObj, queryOptions, errmsg, result, fromRepl);
+ return c->newRun(txn, dbname, cmdObj, queryOptions, errmsg, result, fromRepl);
}
catch ( SendStaleConfigException& e ){
LOG(1) << "command failed because of stale config, can retry" << causedBy( e ) << endl;
@@ -1483,7 +1477,8 @@ namespace mongo {
- context
then calls run()
*/
- void Command::execCommand(Command * c ,
+ void Command::execCommand(TransactionExperiment* txn,
+ Command * c ,
Client& client,
int queryOptions,
const char *cmdns,
@@ -1585,7 +1580,7 @@ namespace mongo {
client.curop()->ensureStarted();
- retval = _execCommand(c, dbname, cmdObj, queryOptions, errmsg, result, fromRepl);
+ retval = _execCommand(txn, c, dbname, cmdObj, queryOptions, errmsg, result, fromRepl);
appendCommandStatus(result, retval, errmsg);
@@ -1608,7 +1603,12 @@ namespace mongo {
returns true if ran a cmd
*/
- bool _runCommands(const char *ns, BSONObj& _cmdobj, BufBuilder &b, BSONObjBuilder& anObjBuilder, bool fromRepl, int queryOptions) {
+ bool _runCommands(TransactionExperiment* txn,
+ const char* ns,
+ BSONObj& _cmdobj,
+ BufBuilder& b,
+ BSONObjBuilder& anObjBuilder,
+ bool fromRepl, int queryOptions) {
string dbname = nsToDatabase( ns );
LOG(2) << "run command " << ns << ' ' << _cmdobj << endl;
@@ -1654,7 +1654,7 @@ namespace mongo {
Command * c = e.type() ? Command::findCommand( e.fieldName() ) : 0;
if ( c ) {
- Command::execCommand(c, client, queryOptions, ns, jsobj, anObjBuilder, fromRepl);
+ Command::execCommand(txn, c, client, queryOptions, ns, jsobj, anObjBuilder, fromRepl);
}
else {
Command::appendCommandStatus(anObjBuilder,
diff --git a/src/mongo/db/dbhelpers.cpp b/src/mongo/db/dbhelpers.cpp
index 38815864034..72d60dffbcd 100644
--- a/src/mongo/db/dbhelpers.cpp
+++ b/src/mongo/db/dbhelpers.cpp
@@ -318,7 +318,8 @@ namespace mongo {
return true;
}
- long long Helpers::removeRange( const KeyRange& range,
+ long long Helpers::removeRange( TransactionExperiment* txn,
+ const KeyRange& range,
bool maxInclusive,
bool secondaryThrottle,
RemoveSaver* callback,
@@ -366,8 +367,7 @@ namespace mongo {
// Scoping for write lock.
{
Client::WriteContext ctx(ns);
- DurTransaction txn;
- Collection* collection = ctx.ctx().db()->getCollection( &txn, ns );
+ Collection* collection = ctx.ctx().db()->getCollection( txn, ns );
if ( !collection )
break;
@@ -437,8 +437,8 @@ namespace mongo {
if ( callback )
callback->goingToDelete( obj );
- logOp(&txn, "d", ns.c_str(), obj["_id"].wrap(), 0, 0, fromMigrate);
- collection->deleteDocument( &txn, rloc );
+ logOp(txn, "d", ns.c_str(), obj["_id"].wrap(), 0, 0, fromMigrate);
+ collection->deleteDocument( txn, rloc );
numDeleted++;
}
diff --git a/src/mongo/db/dbhelpers.h b/src/mongo/db/dbhelpers.h
index 660ef27f926..c10c6f24a21 100644
--- a/src/mongo/db/dbhelpers.h
+++ b/src/mongo/db/dbhelpers.h
@@ -162,7 +162,8 @@ namespace mongo {
* Does oplog the individual document deletions.
* // TODO: Refactor this mechanism, it is growing too large
*/
- static long long removeRange( const KeyRange& range,
+ static long long removeRange( TransactionExperiment* txn,
+ const KeyRange& range,
bool maxInclusive = false,
bool secondaryThrottle = false,
RemoveSaver* callback = NULL,
diff --git a/src/mongo/db/dbwebserver.cpp b/src/mongo/db/dbwebserver.cpp
index cfd6c747e38..e63ad58f0d8 100644
--- a/src/mongo/db/dbwebserver.cpp
+++ b/src/mongo/db/dbwebserver.cpp
@@ -50,6 +50,7 @@
#include "mongo/db/db.h"
#include "mongo/db/instance.h"
#include "mongo/db/stats/snapshots.h"
+#include "mongo/db/storage/mmap_v1/dur_transaction.h"
#include "mongo/util/admin_access.h"
#include "mongo/util/md5.hpp"
#include "mongo/util/mongoutils/html.h"
@@ -73,13 +74,20 @@ namespace mongo {
class DbWebServer : public MiniWebServer {
public:
- DbWebServer(const string& ip, int port, const AdminAccess* webUsers)
- : MiniWebServer("admin web console", ip, port), _webUsers(webUsers) {
+ DbWebServer(const string& ip,
+ int port,
+ const AdminAccess* webUsers,
+ TransactionExperiment::Factory transactionFactory)
+ : MiniWebServer("admin web console", ip, port),
+ _webUsers(webUsers),
+ _transactionFactory(transactionFactory) {
+
WebStatusPlugin::initAll();
}
private:
const AdminAccess* _webUsers; // not owned here
+ const TransactionExperiment::Factory _transactionFactory;
void doUnlockedStuff(stringstream& ss) {
/* this is in the header already ss << "port: " << port << '\n'; */
@@ -179,6 +187,9 @@ namespace mongo {
vector<string>& headers, // if completely empty, content-type: text/html will be added
const SockAddr &from
) {
+
+ boost::scoped_ptr<TransactionExperiment> txn(_transactionFactory()); // XXX SERVER-13931
+
if ( url.size() > 1 ) {
if ( ! allowed( rq , headers, from ) ) {
@@ -206,7 +217,7 @@ namespace mongo {
uassert(13453, "server not started with --jsonp",
callback.empty() || serverGlobalParams.jsonp);
- handler->handle( rq , url , params , responseMsg , responseCode , headers , from );
+ handler->handle( txn.get(), rq , url , params , responseMsg , responseCode , headers , from );
if (responseCode == 200 && !callback.empty()) {
responseMsg = callback + '(' + responseMsg + ')';
@@ -410,7 +421,8 @@ namespace mongo {
public:
FavIconHandler() : DbWebHandler( "favicon.ico" , 0 , false ) {}
- virtual void handle( const char *rq, const std::string& url, BSONObj params,
+ virtual void handle( TransactionExperiment* txn,
+ const char *rq, const std::string& url, BSONObj params,
string& responseMsg, int& responseCode,
vector<string>& headers, const SockAddr &from ) {
responseCode = 404;
@@ -424,7 +436,8 @@ namespace mongo {
public:
StatusHandler() : DbWebHandler( "_status" , 1 , false ) {}
- virtual void handle( const char *rq, const std::string& url, BSONObj params,
+ virtual void handle( TransactionExperiment* txn,
+ const char *rq, const std::string& url, BSONObj params,
string& responseMsg, int& responseCode,
vector<string>& headers, const SockAddr &from ) {
headers.push_back( "Content-Type: application/json;charset=utf-8" );
@@ -459,7 +472,7 @@ namespace mongo {
string errmsg;
BSONObjBuilder sub;
- if ( ! c->run( "admin.$cmd" , co , 0, errmsg , sub , false ) )
+ if ( ! c->newRun( txn, "admin.$cmd" , co , 0, errmsg , sub , false ) )
buf.append( cmd , errmsg );
else
buf.append( cmd , sub.obj() );
@@ -475,7 +488,8 @@ namespace mongo {
public:
CommandListHandler() : DbWebHandler( "_commands" , 1 , true ) {}
- virtual void handle( const char *rq, const std::string& url, BSONObj params,
+ virtual void handle( TransactionExperiment* txn,
+ const char *rq, const std::string& url, BSONObj params,
string& responseMsg, int& responseCode,
vector<string>& headers, const SockAddr &from ) {
headers.push_back( "Content-Type: text/html;charset=utf-8" );
@@ -527,7 +541,8 @@ namespace mongo {
return _cmd(cmd) != 0;
}
- virtual void handle( const char *rq, const std::string& url, BSONObj params,
+ virtual void handle( TransactionExperiment* txn,
+ const char *rq, const std::string& url, BSONObj params,
string& responseMsg, int& responseCode,
vector<string>& headers, const SockAddr &from ) {
string cmd;
@@ -540,7 +555,7 @@ namespace mongo {
Client& client = cc();
BSONObjBuilder result;
- Command::execCommand(c, client, 0, "admin.", cmdObj , result, false);
+ Command::execCommand(txn, c, client, 0, "admin.", cmdObj , result, false);
responseCode = 200;
@@ -561,11 +576,12 @@ namespace mongo {
// --- external ----
- void webServerThread(const AdminAccess* adminAccess) {
+ void webServerThread(const AdminAccess* adminAccess,
+ TransactionExperiment::Factory transactionFactory) {
boost::scoped_ptr<const AdminAccess> adminAccessPtr(adminAccess); // adminAccess is owned here
Client::initThread("websvr");
const int p = serverGlobalParams.port + 1000;
- DbWebServer mini(serverGlobalParams.bind_ip, p, adminAccessPtr.get());
+ DbWebServer mini(serverGlobalParams.bind_ip, p, adminAccessPtr.get(), transactionFactory);
mini.setupSockets();
mini.initAndListen();
cc().shutdown();
diff --git a/src/mongo/db/dbwebserver.h b/src/mongo/db/dbwebserver.h
index 894ad574baf..445f3f2ef33 100644
--- a/src/mongo/db/dbwebserver.h
+++ b/src/mongo/db/dbwebserver.h
@@ -34,6 +34,7 @@
#include "mongo/util/admin_access.h"
#include "mongo/util/net/sock.h"
+#include "mongo/db/storage/transaction.h"
namespace mongo {
@@ -54,7 +55,8 @@ namespace mongo {
virtual bool requiresREST( const string& url ) const { return _requiresREST; }
- virtual void handle( const char *rq, // the full request
+ virtual void handle( TransactionExperiment* txn,
+ const char *rq, // the full request
const std::string& url,
BSONObj params,
// set these and return them:
@@ -94,8 +96,7 @@ namespace mongo {
static vector<WebStatusPlugin*> * _plugins;
};
-
- void webServerThread( const AdminAccess* admins );
+ void webServerThread( const AdminAccess* admins, TransactionExperiment::Factory transactionFactory );
string prettyHostName();
};
diff --git a/src/mongo/db/instance.cpp b/src/mongo/db/instance.cpp
index 4db14c1d689..ab711aab742 100644
--- a/src/mongo/db/instance.cpp
+++ b/src/mongo/db/instance.cpp
@@ -96,11 +96,11 @@ namespace mongo {
inline void opread(Message& m) { if( _diaglog.getLevel() & 2 ) _diaglog.readop((char *) m.singleData(), m.header()->len); }
inline void opwrite(Message& m) { if( _diaglog.getLevel() & 1 ) _diaglog.writeop((char *) m.singleData(), m.header()->len); }
- void receivedKillCursors(Message& m);
- void receivedUpdate(Message& m, CurOp& op);
- void receivedDelete(Message& m, CurOp& op);
- void receivedInsert(Message& m, CurOp& op);
- bool receivedGetMore(DbResponse& dbresponse, Message& m, CurOp& curop );
+ void receivedKillCursors(TransactionExperiment* txn, Message& m);
+ void receivedUpdate(TransactionExperiment* txn, Message& m, CurOp& op);
+ void receivedDelete(TransactionExperiment* txn, Message& m, CurOp& op);
+ void receivedInsert(TransactionExperiment* txn, Message& m, CurOp& op);
+ bool receivedGetMore(TransactionExperiment* txn, DbResponse& dbresponse, Message& m, CurOp& curop );
int nloggedsome = 0;
#define LOGWITHRATELIMIT if( ++nloggedsome < 1000 || nloggedsome % 100 == 0 )
@@ -232,7 +232,7 @@ namespace mongo {
replyToQuery(0, m, dbresponse, obj);
}
- static bool receivedQuery(Client& c, DbResponse& dbresponse, Message& m ) {
+ static bool receivedQuery(TransactionExperiment* txn, Client& c, DbResponse& dbresponse, Message& m ) {
bool ok = true;
MSGID responseTo = m.header()->id;
@@ -253,7 +253,7 @@ namespace mongo {
audit::logQueryAuthzCheck(client, ns, q.query, status.code());
uassertStatusOK(status);
}
- dbresponse.exhaustNS = newRunQuery(m, q, op, *resp);
+ dbresponse.exhaustNS = newRunQuery(txn, m, q, op, *resp);
verify( !resp->empty() );
}
catch ( SendStaleConfigException& e ){
@@ -329,7 +329,10 @@ namespace mongo {
}
// Returns false when request includes 'end'
- void assembleResponse( Message &m, DbResponse &dbresponse, const HostAndPort& remote ) {
+ void assembleResponse( TransactionExperiment* txn,
+ Message& m,
+ DbResponse& dbresponse,
+ const HostAndPort& remote ) {
// before we lock...
int op = m.operation();
@@ -418,10 +421,10 @@ namespace mongo {
if ( op == dbQuery ) {
if ( handlePossibleShardedMessage( m , &dbresponse ) )
return;
- receivedQuery(c , dbresponse, m );
+ receivedQuery(txn, c , dbresponse, m );
}
else if ( op == dbGetMore ) {
- if ( ! receivedGetMore(dbresponse, m, currentOp) )
+ if ( ! receivedGetMore(txn, dbresponse, m, currentOp) )
shouldLog = true;
}
else if ( op == dbMsg ) {
@@ -451,20 +454,20 @@ namespace mongo {
if ( op == dbKillCursors ) {
currentOp.ensureStarted();
logThreshold = 10;
- receivedKillCursors(m);
+ receivedKillCursors(txn, m);
}
else if ( !nsString.isValid() ) {
// Only killCursors doesn't care about namespaces
uassert( 16257, str::stream() << "Invalid ns [" << ns << "]", false );
}
else if ( op == dbInsert ) {
- receivedInsert(m, currentOp);
+ receivedInsert(txn, m, currentOp);
}
else if ( op == dbUpdate ) {
- receivedUpdate(m, currentOp);
+ receivedUpdate(txn, m, currentOp);
}
else if ( op == dbDelete ) {
- receivedDelete(m, currentOp);
+ receivedDelete(txn, m, currentOp);
}
else {
mongo::log() << " operation isn't supported: " << op << endl;
@@ -503,8 +506,7 @@ namespace mongo {
LOG(1) << "note: not profiling because doing fsync+lock" << endl;
}
else {
- DurTransaction txn;
- profile(&txn, c, op, currentOp);
+ profile(txn, c, op, currentOp);
}
}
@@ -512,7 +514,7 @@ namespace mongo {
debug.reset();
} /* assembleResponse() */
- void receivedKillCursors(Message& m) {
+ void receivedKillCursors(TransactionExperiment* txn, Message& m) {
int *x = (int *) m.singleData()->_data;
x++; // reserved
int n = *x++;
@@ -561,7 +563,7 @@ namespace mongo {
delete database; // closes files
}
- void receivedUpdate(Message& m, CurOp& op) {
+ void receivedUpdate(TransactionExperiment* txn, Message& m, CurOp& op) {
DbMessage d(m);
NamespaceString ns(d.getns());
uassertStatusOK( userAllowedWriteNS( ns ) );
@@ -609,15 +611,14 @@ namespace mongo {
return;
Client::Context ctx( ns );
- DurTransaction txn;
- UpdateResult res = executor.execute(&txn, ctx.db());
+ UpdateResult res = executor.execute(txn, ctx.db());
// for getlasterror
lastError.getSafe()->recordUpdate( res.existing , res.numMatched , res.upserted );
}
- void receivedDelete(Message& m, CurOp& op) {
+ void receivedDelete(TransactionExperiment* txn, Message& m, CurOp& op) {
DbMessage d(m);
NamespaceString ns(d.getns());
uassertStatusOK( userAllowedWriteNS( ns ) );
@@ -649,16 +650,15 @@ namespace mongo {
return;
Client::Context ctx(ns);
- DurTransaction txn;
- long long n = executor.execute(&txn, ctx.db());
+ long long n = executor.execute(txn, ctx.db());
lastError.getSafe()->recordDelete( n );
op.debug().ndeleted = n;
}
QueryResult* emptyMoreResult(long long);
- bool receivedGetMore(DbResponse& dbresponse, Message& m, CurOp& curop ) {
+ bool receivedGetMore(TransactionExperiment* txn, DbResponse& dbresponse, Message& m, CurOp& curop ) {
bool ok = true;
DbMessage d(m);
@@ -854,7 +854,7 @@ namespace mongo {
op.debug().ninserted = i;
}
- void receivedInsert(Message& m, CurOp& op) {
+ void receivedInsert(TransactionExperiment* txn, Message& m, CurOp& op) {
DbMessage d(m);
const char *ns = d.getns();
op.debug().ns = ns;
@@ -889,13 +889,12 @@ namespace mongo {
return;
Client::Context ctx(ns);
- DurTransaction txn;
if (multi.size() > 1) {
const bool keepGoing = d.reservedField() & InsertOption_ContinueOnError;
- insertMulti(&txn, ctx, keepGoing, ns, multi, op);
+ insertMulti(txn, ctx, keepGoing, ns, multi, op);
} else {
- checkAndInsert(&txn, ctx, ns, multi[0]);
+ checkAndInsert(txn, ctx, ns, multi[0]);
globalOpCounters.incInsertInWriteLock(1);
op.debug().ninserted = 1;
}
@@ -942,6 +941,15 @@ namespace mongo {
return false;
}
+ DBDirectClient::DBDirectClient()
+ : _txnOwned(new DurTransaction),
+ _txn(_txnOwned.get())
+ {}
+
+ DBDirectClient::DBDirectClient(TransactionExperiment* txn)
+ : _txn(txn)
+ {}
+
QueryOptions DBDirectClient::_lookupAvailableOptions() {
// Exhaust mode is not available in DBDirectClient.
return QueryOptions(DBClientBase::_lookupAvailableOptions() & ~QueryOption_Exhaust);
@@ -965,11 +973,11 @@ namespace {
if ( lastError._get() )
lastError.startRequest( toSend, lastError._get() );
DbResponse dbResponse;
- assembleResponse( toSend, dbResponse , _clientHost );
+ assembleResponse( _txn, toSend, dbResponse , _clientHost );
verify( dbResponse.response );
dbResponse.response->concat(); // can get rid of this if we make response handling smarter
response = *dbResponse.response;
- getDur().commitIfNeeded();
+ _txn->commitIfNeeded();
return true;
}
@@ -978,8 +986,8 @@ namespace {
if ( lastError._get() )
lastError.startRequest( toSend, lastError._get() );
DbResponse dbResponse;
- assembleResponse( toSend, dbResponse , _clientHost );
- getDur().commitIfNeeded();
+ assembleResponse( _txn, toSend, dbResponse , _clientHost );
+ _txn->commitIfNeeded();
}
auto_ptr<DBClientCursor> DBDirectClient::query(const string &ns, Query query, int nToReturn , int nToSkip ,
diff --git a/src/mongo/db/instance.h b/src/mongo/db/instance.h
index d848f6f1c09..50a988917ad 100644
--- a/src/mongo/db/instance.h
+++ b/src/mongo/db/instance.h
@@ -35,6 +35,7 @@
#include "mongo/db/client.h"
#include "mongo/db/curop-inl.h"
#include "mongo/db/dbmessage.h"
+#include "mongo/db/storage/transaction.h"
#include "mongo/db/storage_options.h"
namespace mongo {
@@ -67,7 +68,10 @@ namespace mongo {
extern DiagLog _diaglog;
- void assembleResponse( Message &m, DbResponse &dbresponse, const HostAndPort &client );
+ void assembleResponse( TransactionExperiment* txn,
+ Message& m,
+ DbResponse& dbresponse,
+ const HostAndPort &client );
void getDatabaseNames(vector<std::string> &names,
const std::string& usePath = storageGlobalParams.dbpath);
@@ -82,6 +86,9 @@ namespace mongo {
*/
class DBDirectClient : public DBClientBase {
public:
+ DBDirectClient(); // DEPRECATED
+ DBDirectClient(TransactionExperiment* txn); // txn must outlive this object
+
using DBClientBase::query;
virtual auto_ptr<DBClientCursor> query(const string &ns, Query query, int nToReturn = 0, int nToSkip = 0,
@@ -126,6 +133,8 @@ namespace mongo {
private:
static HostAndPort _clientHost;
+ boost::scoped_ptr<TransactionExperiment> _txnOwned;
+ TransactionExperiment* _txn; // Points either to _txnOwned or a passed-in transaction.
};
extern int lockFile;
diff --git a/src/mongo/db/query/new_find.cpp b/src/mongo/db/query/new_find.cpp
index 40990a0baa6..9236cb92333 100644
--- a/src/mongo/db/query/new_find.cpp
+++ b/src/mongo/db/query/new_find.cpp
@@ -109,7 +109,8 @@ namespace {
namespace mongo {
// TODO: Move this and the other command stuff in newRunQuery outta here and up a level.
- static bool runCommands(const char *ns,
+ static bool runCommands(TransactionExperiment* txn,
+ const char *ns,
BSONObj& jsobj,
CurOp& curop,
BufBuilder &b,
@@ -117,7 +118,7 @@ namespace mongo {
bool fromRepl,
int queryOptions) {
try {
- return _runCommands(ns, jsobj, b, anObjBuilder, fromRepl, queryOptions);
+ return _runCommands(txn, ns, jsobj, b, anObjBuilder, fromRepl, queryOptions);
}
catch( SendStaleConfigException& ){
throw;
@@ -397,7 +398,11 @@ namespace mongo {
return Status::OK();
}
- std::string newRunQuery(Message& m, QueryMessage& q, CurOp& curop, Message &result) {
+ std::string newRunQuery(TransactionExperiment* txn,
+ Message& m,
+ QueryMessage& q,
+ CurOp& curop,
+ Message &result) {
// Validate the namespace.
const char *ns = q.ns;
uassert(16332, "can't have an empty ns", ns[0]);
@@ -424,7 +429,7 @@ namespace mongo {
bb.skip(sizeof(QueryResult));
BSONObjBuilder cmdResBuf;
- if (!runCommands(ns, q.query, curop, bb, cmdResBuf, false, q.queryOptions)) {
+ if (!runCommands(txn, ns, q.query, curop, bb, cmdResBuf, false, q.queryOptions)) {
uasserted(13530, "bad or malformed command request?");
}
diff --git a/src/mongo/db/query/new_find.h b/src/mongo/db/query/new_find.h
index 2977a83ab51..149bcce9b0a 100644
--- a/src/mongo/db/query/new_find.h
+++ b/src/mongo/db/query/new_find.h
@@ -39,6 +39,8 @@
namespace mongo {
+ class TransactionExperiment;
+
/**
* Called from the getMore entry point in ops/query.cpp.
*/
@@ -48,6 +50,10 @@ namespace mongo {
/**
* Run the query 'q' and place the result in 'result'.
*/
- std::string newRunQuery(Message& m, QueryMessage& q, CurOp& curop, Message &result);
+ std::string newRunQuery(TransactionExperiment* txn,
+ Message& m,
+ QueryMessage& q,
+ CurOp& curop,
+ Message &result);
} // namespace mongo
diff --git a/src/mongo/db/range_deleter.cpp b/src/mongo/db/range_deleter.cpp
index 0ea7e44e4ec..229f7e82060 100644
--- a/src/mongo/db/range_deleter.cpp
+++ b/src/mongo/db/range_deleter.cpp
@@ -73,7 +73,8 @@ namespace mongo {
struct RangeDeleter::RangeDeleteEntry {
RangeDeleteEntry():
secondaryThrottle(true),
- notifyDone(NULL) {
+ notifyDone(NULL),
+ transactionFactory(TransactionExperiment::factoryNULL) { // XXX SERVER-13931
}
std::string ns;
@@ -99,6 +100,8 @@ namespace mongo {
// Important invariant: Can only be set and used by one thread.
Notification* notifyDone;
+ TransactionExperiment::Factory transactionFactory;
+
// For debugging only
BSONObj toBSON() const {
return BSON("ns" << ns
@@ -193,7 +196,8 @@ namespace mongo {
}
}
- bool RangeDeleter::queueDelete(const std::string& ns,
+ bool RangeDeleter::queueDelete(TransactionExperiment::Factory transactionFactory,
+ const std::string& ns,
const BSONObj& min,
const BSONObj& max,
const BSONObj& shardKeyPattern,
@@ -204,6 +208,7 @@ namespace mongo {
if (errMsg == NULL) errMsg = &dummy;
auto_ptr<RangeDeleteEntry> toDelete(new RangeDeleteEntry);
+ toDelete->transactionFactory = transactionFactory;
toDelete->ns = ns;
toDelete->min = min.getOwned();
toDelete->max = max.getOwned();
@@ -247,7 +252,8 @@ namespace mongo {
return true;
}
- bool RangeDeleter::deleteNow(const std::string& ns,
+ bool RangeDeleter::deleteNow(TransactionExperiment* txn,
+ const std::string& ns,
const BSONObj& min,
const BSONObj& max,
const BSONObj& shardKeyPattern,
@@ -323,7 +329,7 @@ namespace mongo {
sleepmillis(checkIntervalMillis);
}
- bool result = _env->deleteRange(ns, min, max, shardKeyPattern,
+ bool result = _env->deleteRange(txn, ns, min, max, shardKeyPattern,
secondaryThrottle, errMsg);
{
@@ -468,14 +474,18 @@ namespace mongo {
_stats->incInProgressDeletes_inlock();
}
- if (!_env->deleteRange(nextTask->ns,
- nextTask->min,
- nextTask->max,
- nextTask->shardKeyPattern,
- nextTask->secondaryThrottle,
- &errMsg)) {
- warning() << "Error encountered while trying to delete range: "
- << errMsg << endl;
+ {
+ boost::scoped_ptr<TransactionExperiment> txn(nextTask->transactionFactory()); // XXX SERVER-13931
+ if (!_env->deleteRange(txn.get(),
+ nextTask->ns,
+ nextTask->min,
+ nextTask->max,
+ nextTask->shardKeyPattern,
+ nextTask->secondaryThrottle,
+ &errMsg)) {
+ warning() << "Error encountered while trying to delete range: "
+ << errMsg << endl;
+ }
}
{
diff --git a/src/mongo/db/range_deleter.h b/src/mongo/db/range_deleter.h
index b8fd0789c5a..653fb0105b0 100644
--- a/src/mongo/db/range_deleter.h
+++ b/src/mongo/db/range_deleter.h
@@ -37,6 +37,7 @@
#include "mongo/base/string_data.h"
#include "mongo/db/clientcursor.h"
#include "mongo/db/jsobj.h"
+#include "mongo/db/storage/transaction.h"
#include "mongo/util/concurrency/mutex.h"
#include "mongo/util/concurrency/synchronization.h"
@@ -44,6 +45,7 @@ namespace mongo {
struct RangeDeleterEnv;
class RangeDeleterStats;
+ class TransactionExperiment;
/**
* Class for deleting documents for a given namespace and range. It contains a queue of
@@ -129,7 +131,8 @@ namespace mongo {
* Returns true if the task is queued and false If the given range is blacklisted,
* is already queued, or stopWorkers() was called.
*/
- bool queueDelete(const std::string& ns,
+ bool queueDelete(TransactionExperiment::Factory transactionFactory,
+ const std::string& ns,
const BSONObj& min,
const BSONObj& max,
const BSONObj& shardKeyPattern,
@@ -144,7 +147,8 @@ namespace mongo {
* Returns true if the deletion was performed. False if the range is blacklisted,
* was already queued, or stopWorkers() was called.
*/
- bool deleteNow(const std::string& ns,
+ bool deleteNow(TransactionExperiment* txn,
+ const std::string& ns,
const BSONObj& min,
const BSONObj& max,
const BSONObj& shardKeyPattern,
@@ -284,7 +288,8 @@ namespace mongo {
* Must be a synchronous call. Docs should be deleted after call ends.
* Must not throw Exceptions.
*/
- virtual bool deleteRange(const StringData& ns,
+ virtual bool deleteRange(TransactionExperiment* txn,
+ const StringData& ns,
const BSONObj& inclusiveLower,
const BSONObj& exclusiveUpper,
const BSONObj& shardKeyPattern,
diff --git a/src/mongo/db/range_deleter_db_env.cpp b/src/mongo/db/range_deleter_db_env.cpp
index 3d2f61c221c..71a0ca86796 100644
--- a/src/mongo/db/range_deleter_db_env.cpp
+++ b/src/mongo/db/range_deleter_db_env.cpp
@@ -54,7 +54,8 @@ namespace mongo {
* 5. Delete range.
* 6. Wait until the majority of the secondaries catch up.
*/
- bool RangeDeleterDBEnv::deleteRange(const StringData& ns,
+ bool RangeDeleterDBEnv::deleteRange(TransactionExperiment* txn,
+ const StringData& ns,
const BSONObj& inclusiveLower,
const BSONObj& exclusiveUpper,
const BSONObj& keyPattern,
@@ -80,7 +81,8 @@ namespace mongo {
try {
long long numDeleted =
- Helpers::removeRange(KeyRange(ns.toString(),
+ Helpers::removeRange(txn,
+ KeyRange(ns.toString(),
inclusiveLower,
exclusiveUpper,
keyPattern),
diff --git a/src/mongo/db/range_deleter_db_env.h b/src/mongo/db/range_deleter_db_env.h
index b55389e3edd..01089fc9d3d 100644
--- a/src/mongo/db/range_deleter_db_env.h
+++ b/src/mongo/db/range_deleter_db_env.h
@@ -51,7 +51,8 @@ namespace mongo {
*
* Does not throw Exceptions.
*/
- virtual bool deleteRange(const StringData& ns,
+ virtual bool deleteRange(TransactionExperiment* txn,
+ const StringData& ns,
const BSONObj& inclusiveLower,
const BSONObj& exclusiveUpper,
const BSONObj& keyPattern,
diff --git a/src/mongo/db/range_deleter_mock_env.cpp b/src/mongo/db/range_deleter_mock_env.cpp
index 536d463417e..22ecff1bea4 100644
--- a/src/mongo/db/range_deleter_mock_env.cpp
+++ b/src/mongo/db/range_deleter_mock_env.cpp
@@ -100,7 +100,8 @@ namespace mongo {
return _deleteList.back();
}
- bool RangeDeleterMockEnv::deleteRange(const StringData& ns,
+ bool RangeDeleterMockEnv::deleteRange(TransactionExperiment* txn,
+ const StringData& ns,
const BSONObj& min,
const BSONObj& max,
const BSONObj& shardKeyPattern,
diff --git a/src/mongo/db/range_deleter_mock_env.h b/src/mongo/db/range_deleter_mock_env.h
index 7b1cd3932e3..4ba3e686d9d 100644
--- a/src/mongo/db/range_deleter_mock_env.h
+++ b/src/mongo/db/range_deleter_mock_env.h
@@ -126,7 +126,8 @@ namespace mongo {
* but simply keeps a record of it. Can also be paused by pauseDeletes and
* resumed with resumeDeletes.
*/
- bool deleteRange(const StringData& ns,
+ bool deleteRange(TransactionExperiment* txn,
+ const StringData& ns,
const BSONObj& min,
const BSONObj& max,
const BSONObj& shardKeyPattern,
diff --git a/src/mongo/db/range_deleter_stat_test.cpp b/src/mongo/db/range_deleter_stat_test.cpp
index 6de5f15d196..695da1d8a26 100644
--- a/src/mongo/db/range_deleter_stat_test.cpp
+++ b/src/mongo/db/range_deleter_stat_test.cpp
@@ -48,6 +48,9 @@ namespace {
using mongo::RangeDeleter;
using mongo::RangeDeleterMockEnv;
using mongo::RangeDeleterStats;
+ using mongo::TransactionExperiment;
+
+ TransactionExperiment* const noTxn = NULL; // MockEnv doesn't need txn XXX SERVER-13931
TEST(NoDeletes, InitialState) {
RangeDeleterMockEnv* env = new RangeDeleterMockEnv();
@@ -85,7 +88,8 @@ namespace {
string errMsg;
Notification notifyDone;
- ASSERT_TRUE(deleter.queueDelete(ns,
+ ASSERT_TRUE(deleter.queueDelete(TransactionExperiment::factoryNULL,
+ ns,
BSON("x" << 0),
BSON("x" << 10),
BSON("x" << 1),
@@ -127,7 +131,8 @@ namespace {
Notification deleteDone;
string errMsg;
- ASSERT_TRUE(deleter.queueDelete(ns,
+ ASSERT_TRUE(deleter.queueDelete(TransactionExperiment::factoryNULL, // XXX SERVER-13931
+ ns,
BSON("x" << 0),
BSON("x" << 10),
BSON("x" << 1),
@@ -170,7 +175,8 @@ namespace {
string errMsg;
Notification notifyDone;
- ASSERT_TRUE(deleter.queueDelete(ns,
+ ASSERT_TRUE(deleter.queueDelete(TransactionExperiment::factoryNULL, // XXX SERVER-13931
+ ns,
BSON("x" << 0),
BSON("x" << 10),
BSON("x" << 1),
@@ -213,6 +219,7 @@ namespace {
string errMsg;
boost::thread deleterThread = boost::thread(boost::bind(&RangeDeleter::deleteNow,
&deleter,
+ noTxn,
ns,
BSON("x" << 0),
BSON("x" << 10),
@@ -256,6 +263,7 @@ namespace {
string errMsg;
boost::thread deleterThread = boost::thread(boost::bind(&RangeDeleter::deleteNow,
&deleter,
+ noTxn,
ns,
BSON("x" << 0),
BSON("x" << 10),
@@ -296,7 +304,7 @@ namespace {
const string ns("test.user");
string errMsg;
- ASSERT_TRUE(deleter.deleteNow(ns, BSON("x" << 0), BSON("x" << 10),
+ ASSERT_TRUE(deleter.deleteNow(noTxn, ns, BSON("x" << 0), BSON("x" << 10),
BSON("x" << 1), true, &errMsg));
const BSONObj stats(deleter.getStats()->toBSON());
diff --git a/src/mongo/db/range_deleter_test.cpp b/src/mongo/db/range_deleter_test.cpp
index 23a93da14b0..1bc2ac0beae 100644
--- a/src/mongo/db/range_deleter_test.cpp
+++ b/src/mongo/db/range_deleter_test.cpp
@@ -49,6 +49,9 @@ namespace {
using mongo::RangeDeleter;
using mongo::RangeDeleterMockEnv;
using mongo::RangeDeleterStats;
+ using mongo::TransactionExperiment;
+
+ TransactionExperiment* const noTxn = NULL; // MockEnv doesn't need txn XXX SERVER-13931
// Capped sleep interval is 640 mSec, Nyquist frequency is 1280 mSec => round up to 2 sec.
const int MAX_IMMEDIATE_DELETE_WAIT_SECS = 2;
@@ -62,7 +65,8 @@ namespace {
deleter.stopWorkers();
string errMsg;
- ASSERT_FALSE(deleter.queueDelete("test.user",
+ ASSERT_FALSE(deleter.queueDelete(TransactionExperiment::factoryNULL, // XXX SERVER-13931
+ "test.user",
BSON("x" << 120),
BSON("x" << 200),
BSON("x" << 1),
@@ -84,7 +88,8 @@ namespace {
env->addCursorId(ns, 345);
Notification notifyDone;
- ASSERT_TRUE(deleter.queueDelete(ns, BSON("x" << 0), BSON("x" << 10), BSON("x" << 1),
+ ASSERT_TRUE(deleter.queueDelete(TransactionExperiment::factoryNULL, // XXX SERVER-13931
+ ns, BSON("x" << 0), BSON("x" << 10), BSON("x" << 1),
true, &notifyDone, NULL /* errMsg not needed */));
env->waitForNthGetCursor(1u);
@@ -122,7 +127,8 @@ namespace {
env->addCursorId(ns, 345);
Notification notifyDone;
- ASSERT_TRUE(deleter.queueDelete(ns, BSON("x" << 0), BSON("x" << 10), BSON("x" << 1),
+ ASSERT_TRUE(deleter.queueDelete(TransactionExperiment::factoryNULL, // XXX SERVER-13931
+ ns, BSON("x" << 0), BSON("x" << 10), BSON("x" << 1),
true, &notifyDone, NULL /* errMsg not needed */));
@@ -145,6 +151,7 @@ namespace {
string errMsg;
boost::thread deleterThread = boost::thread(boost::bind(&RangeDeleter::deleteNow,
&deleter,
+ noTxn,
ns,
BSON("x" << 0),
BSON("x" << 10),
@@ -194,6 +201,7 @@ namespace {
string errMsg;
boost::thread deleterThread = boost::thread(boost::bind(&RangeDeleter::deleteNow,
&deleter,
+ noTxn,
ns,
BSON("x" << 0),
BSON("x" << 10),
@@ -238,7 +246,8 @@ namespace {
env->pauseDeletes();
Notification notifyDone1;
- ASSERT_TRUE(deleter.queueDelete(ns,
+ ASSERT_TRUE(deleter.queueDelete(TransactionExperiment::factoryNULL, // XXX SERVER-13931
+ ns,
BSON("x" << 10),
BSON("x" << 20),
BSON("x" << 1),
@@ -256,7 +265,8 @@ namespace {
ASSERT_EQUALS(1, inProgressCount);
Notification notifyDone2;
- ASSERT_TRUE(deleter.queueDelete(blockedNS,
+ ASSERT_TRUE(deleter.queueDelete(TransactionExperiment::factoryNULL, // XXX SERVER-13931
+ blockedNS,
BSON("x" << 20),
BSON("x" << 30),
BSON("x" << 1),
@@ -265,7 +275,8 @@ namespace {
NULL /* don't care errMsg */));
Notification notifyDone3;
- ASSERT_TRUE(deleter.queueDelete(ns,
+ ASSERT_TRUE(deleter.queueDelete(TransactionExperiment::factoryNULL, // XXX SERVER-13931
+ ns,
BSON("x" << 30),
BSON("x" << 40),
BSON("x" << 1),
@@ -352,12 +363,13 @@ namespace {
ASSERT_TRUE(errMsg.empty());
errMsg.clear();
- ASSERT_FALSE(deleter.queueDelete(ns, BSON("x" << 120), BSON("x" << 140), BSON("x" << 1),
+ ASSERT_FALSE(deleter.queueDelete(TransactionExperiment::factoryNULL, // XXX SERVER-13931
+ ns, BSON("x" << 120), BSON("x" << 140), BSON("x" << 1),
false, NULL /* notifier not needed */, &errMsg));
ASSERT_FALSE(errMsg.empty());
errMsg.clear();
- ASSERT_FALSE(deleter.deleteNow(ns, BSON("x" << 120), BSON("x" << 140),
+ ASSERT_FALSE(deleter.deleteNow(noTxn, ns, BSON("x" << 120), BSON("x" << 140),
BSON("x" << 1), false, &errMsg));
ASSERT_FALSE(errMsg.empty());
@@ -400,7 +412,8 @@ namespace {
env->addCursorId(ns, 58);
Notification notifyDone;
- deleter.queueDelete(ns, BSON("x" << 0), BSON("x" << 10), BSON("x" << 1),
+ deleter.queueDelete(TransactionExperiment::factoryNULL, // XXX SERVER-13931
+ ns, BSON("x" << 0), BSON("x" << 10), BSON("x" << 1),
false, &notifyDone, NULL /* errMsg not needed */);
string errMsg;
@@ -430,6 +443,7 @@ namespace {
string delErrMsg;
boost::thread deleterThread = boost::thread(boost::bind(&RangeDeleter::deleteNow,
&deleter,
+ noTxn,
ns,
BSON("x" << 64),
BSON("x" << 70),
@@ -468,7 +482,7 @@ namespace {
ASSERT_FALSE(deleter.removeFromBlackList(ns, BSON("x" << 1234), BSON("x" << 9000)));
// Range should still be blacklisted
- ASSERT_FALSE(deleter.deleteNow(ns, BSON("x" << 2000), BSON("x" << 4000), BSON("x" << 1),
+ ASSERT_FALSE(deleter.deleteNow(noTxn, ns, BSON("x" << 2000), BSON("x" << 4000), BSON("x" << 1),
false, NULL /* errMsg not needed */));
deleter.stopWorkers();
@@ -485,14 +499,14 @@ namespace {
ASSERT_TRUE(errMsg.empty());
errMsg.clear();
- ASSERT_FALSE(deleter.deleteNow(ns, BSON("x" << 600), BSON("x" << 700),
+ ASSERT_FALSE(deleter.deleteNow(noTxn, ns, BSON("x" << 600), BSON("x" << 700),
BSON("x" << 1), false, &errMsg));
ASSERT_FALSE(errMsg.empty());
ASSERT_TRUE(deleter.removeFromBlackList(ns, BSON("x" << 500), BSON("x" << 801)));
errMsg.clear();
- ASSERT_TRUE(deleter.deleteNow(ns, BSON("x" << 600), BSON("x" << 700),
+ ASSERT_TRUE(deleter.deleteNow(noTxn, ns, BSON("x" << 600), BSON("x" << 700),
BSON("x" << 1), false, &errMsg));
ASSERT_TRUE(errMsg.empty());
@@ -507,7 +521,7 @@ namespace {
deleter.addToBlackList("foo.bar", BSON("x" << 100), BSON("x" << 200),
NULL /* errMsg not needed */);
- ASSERT_TRUE(deleter.deleteNow("test.user", BSON("x" << 120), BSON("x" << 140),
+ ASSERT_TRUE(deleter.deleteNow(noTxn, "test.user", BSON("x" << 120), BSON("x" << 140),
BSON("x" << 1), true, NULL /* errMsg not needed */));
deleter.stopWorkers();
diff --git a/src/mongo/db/repl/oplog.cpp b/src/mongo/db/repl/oplog.cpp
index 0be9d7a9bd6..61cb23f914b 100644
--- a/src/mongo/db/repl/oplog.cpp
+++ b/src/mongo/db/repl/oplog.cpp
@@ -705,7 +705,7 @@ namespace mongo {
while (!done) {
BufBuilder bb;
BSONObjBuilder ob;
- _runCommands(ns, o, bb, ob, true, 0);
+ _runCommands(txn, ns, o, bb, ob, true, 0);
// _runCommands takes care of adjusting opcounters for command counting.
Status status = Command::getStatusFromCommandResult(ob.done());
switch (status.code()) {
diff --git a/src/mongo/db/repl/replset_web_handler.cpp b/src/mongo/db/repl/replset_web_handler.cpp
index 27ce6a61853..5cd7b14ae48 100644
--- a/src/mongo/db/repl/replset_web_handler.cpp
+++ b/src/mongo/db/repl/replset_web_handler.cpp
@@ -53,7 +53,8 @@ namespace {
return startsWith( url , "/_replSet" );
}
- virtual void handle( const char *rq, const std::string& url, BSONObj params,
+ virtual void handle( TransactionExperiment* txn,
+ const char *rq, const std::string& url, BSONObj params,
string& responseMsg, int& responseCode,
vector<string>& headers, const SockAddr &from ) {
diff --git a/src/mongo/db/repl/resync.cpp b/src/mongo/db/repl/resync.cpp
index 1adc44903e6..1c4322d81cd 100644
--- a/src/mongo/db/repl/resync.cpp
+++ b/src/mongo/db/repl/resync.cpp
@@ -57,7 +57,8 @@ namespace mongo {
}
CmdResync() : Command("resync") { }
- virtual bool run(const string& dbname,
+ virtual bool newRun(TransactionExperiment* txn,
+ const string& dbname,
BSONObj& cmdObj,
int,
string& errmsg,
@@ -67,7 +68,6 @@ namespace mongo {
const std::string ns = parseNs(dbname, cmdObj);
Lock::GlobalWrite globalWriteLock;
Client::Context ctx(ns);
- DurTransaction txn;
if (replSettings.usingReplSets()) {
if (theReplSet->isPrimary()) {
@@ -90,7 +90,7 @@ namespace mongo {
if ( !waitForSyncToFinish( errmsg ) )
return false;
- ReplSource::forceResyncDead( &txn, "client" );
+ ReplSource::forceResyncDead( txn, "client" );
result.append( "info", "triggered resync for all sources" );
return true;
}
diff --git a/src/mongo/db/restapi.cpp b/src/mongo/db/restapi.cpp
index bb06d522491..bb2243272ea 100644
--- a/src/mongo/db/restapi.cpp
+++ b/src/mongo/db/restapi.cpp
@@ -66,7 +66,8 @@ namespace mongo {
url.find_last_of( '/' ) > 0;
}
- virtual void handle( const char *rq, const std::string& url, BSONObj params,
+ virtual void handle( TransactionExperiment* txn,
+ const char *rq, const std::string& url, BSONObj params,
string& responseMsg, int& responseCode,
vector<string>& headers, const SockAddr &from ) {
diff --git a/src/mongo/db/storage/mmap_v1/dur_transaction.cpp b/src/mongo/db/storage/mmap_v1/dur_transaction.cpp
index b4b904527c9..147dc9a71e2 100644
--- a/src/mongo/db/storage/mmap_v1/dur_transaction.cpp
+++ b/src/mongo/db/storage/mmap_v1/dur_transaction.cpp
@@ -74,4 +74,8 @@ namespace mongo {
return Status( ErrorCodes::Interrupted, killed );
}
+ TransactionExperiment* DurTransaction::factory() {
+ return new DurTransaction();
+ }
+
} // namespace mongo
diff --git a/src/mongo/db/storage/mmap_v1/dur_transaction.h b/src/mongo/db/storage/mmap_v1/dur_transaction.h
index c6fe30e98b4..b4a2bd009e3 100644
--- a/src/mongo/db/storage/mmap_v1/dur_transaction.h
+++ b/src/mongo/db/storage/mmap_v1/dur_transaction.h
@@ -62,6 +62,11 @@ namespace mongo {
virtual Status checkForInterruptNoAssert() const;
+ /**
+ * Returns a DurTransaction. Caller takes ownership.
+ */
+ static TransactionExperiment* factory();
+
};
} // namespace mongo
diff --git a/src/mongo/db/storage/transaction.h b/src/mongo/db/storage/transaction.h
index a025b8f283f..2684342e542 100644
--- a/src/mongo/db/storage/transaction.h
+++ b/src/mongo/db/storage/transaction.h
@@ -125,6 +125,23 @@ namespace mongo {
return x;
}
+ /**
+ * Returns a TransactionExperiment. Caller takes ownership.
+ *
+ * This interface is used for functions that need to create transactions (aka OpCtx), but
+ * don't know which implementation they should create. It allows the calling code to make
+ * that decision for them.
+ *
+ * TODO come up with a better Factory API once we split this class up (SERVER-13931).
+ */
+ typedef TransactionExperiment* (*Factory)();
+
+ /**
+ * A TransactionExperiment::Factory that always returns NULL. For things that shouldn't be
+ * touching their txns such as mongos or some unittests.
+ */
+ static TransactionExperiment* factoryNULL() { return NULL; }
+
protected:
TransactionExperiment() {}
};
diff --git a/src/mongo/dbtests/dbhelper_tests.cpp b/src/mongo/dbtests/dbhelper_tests.cpp
index 8ee890939fb..d3347cc6e6c 100644
--- a/src/mongo/dbtests/dbhelper_tests.cpp
+++ b/src/mongo/dbtests/dbhelper_tests.cpp
@@ -29,6 +29,7 @@
#include "mongo/client/dbclientcursor.h"
#include "mongo/db/catalog/collection.h"
#include "mongo/db/dbhelpers.h"
+#include "mongo/db/storage/mmap_v1/dur_transaction.h"
#include "mongo/dbtests/dbtests.h"
#include "mongo/unittest/unittest.h"
@@ -56,13 +57,14 @@ namespace mongo {
{
// Remove _id range [_min, _max).
+ DurTransaction txn;
Lock::DBWrite lk( ns );
Client::Context ctx( ns );
KeyRange range( ns,
BSON( "_id" << _min ),
BSON( "_id" << _max ),
BSON( "_id" << 1 ) );
- Helpers::removeRange( range );
+ Helpers::removeRange( &txn, range );
}
// Check that the expected documents remain.
diff --git a/src/mongo/dbtests/querytests.cpp b/src/mongo/dbtests/querytests.cpp
index 4ce36bbe88f..0c7c77138bc 100644
--- a/src/mongo/dbtests/querytests.cpp
+++ b/src/mongo/dbtests/querytests.cpp
@@ -1438,7 +1438,8 @@ namespace QueryTests {
DbMessage dbMessage( message );
QueryMessage queryMessage( dbMessage );
Message result;
- string exhaust = newRunQuery( message, queryMessage, *cc().curop(), result );
+ DurTransaction txn;
+ string exhaust = newRunQuery( &txn, message, queryMessage, *cc().curop(), result );
ASSERT( exhaust.size() );
ASSERT_EQUALS( string( ns() ), exhaust );
}
diff --git a/src/mongo/s/commands_public.cpp b/src/mongo/s/commands_public.cpp
index caed4bb8f82..0e29d5563b3 100644
--- a/src/mongo/s/commands_public.cpp
+++ b/src/mongo/s/commands_public.cpp
@@ -2543,7 +2543,8 @@ namespace mongo {
}
ClientInfo *client = ClientInfo::get();
- execCommandClientBasic(c, *client, queryOptions, ns, jsobj, anObjBuilder, false);
+ TransactionExperiment* noTxn = NULL; // mongos doesn't use transactions SERVER-13931
+ execCommandClientBasic(noTxn, c, *client, queryOptions, ns, jsobj, anObjBuilder, false);
}
} // namespace mongo
diff --git a/src/mongo/s/d_migrate.cpp b/src/mongo/s/d_migrate.cpp
index 29f06ab5f90..5a98b4825f0 100644
--- a/src/mongo/s/d_migrate.cpp
+++ b/src/mongo/s/d_migrate.cpp
@@ -771,7 +771,7 @@ namespace mongo {
return parseNsFullyQualified(dbname, cmdObj);
}
- bool run(const string& dbname, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool) {
+ bool newRun(TransactionExperiment* txn, const string& dbname, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool) {
// 1. parse options
// 2. make sure my view is complete and lock
// 3. start migrate
@@ -1486,7 +1486,8 @@ namespace mongo {
string errMsg;
// This is an immediate delete, and as a consequence, there could be more
// deletes happening simultaneously than there are deleter worker threads.
- if (!deleter->deleteNow(ns,
+ if (!deleter->deleteNow(txn,
+ ns,
min.getOwned(),
max.getOwned(),
shardKeyPattern.getOwned(),
@@ -1499,7 +1500,8 @@ namespace mongo {
log() << "forking for cleanup of chunk data" << migrateLog;
string errMsg;
- if (!deleter->queueDelete(ns,
+ if (!deleter->queueDelete(DurTransaction::factory,
+ ns,
min.getOwned(),
max.getOwned(),
shardKeyPattern.getOwned(),
@@ -1567,9 +1569,9 @@ namespace mongo {
active = true;
}
- void go() {
+ void go(TransactionExperiment* txn) {
try {
- _go();
+ _go(txn);
}
catch ( std::exception& e ) {
state = FAIL;
@@ -1594,7 +1596,7 @@ namespace mongo {
setActive( false );
}
- void _go() {
+ void _go(TransactionExperiment* txn) {
verify( getActive() );
verify( state == READY );
verify( ! min.isEmpty() );
@@ -1615,7 +1617,6 @@ namespace mongo {
{
// 0. copy system.namespaces entry if collection doesn't already exist
Client::WriteContext ctx( ns );
- DurTransaction txn;
// Only copy if ns doesn't already exist
Database* db = ctx.ctx().db();
Collection* collection = db->getCollection( ns );
@@ -1624,14 +1625,14 @@ namespace mongo {
string system_namespaces = nsToDatabase(ns) + ".system.namespaces";
BSONObj entry = conn->findOne( system_namespaces, BSON( "name" << ns ) );
if ( entry["options"].isABSONObj() ) {
- Status status = userCreateNS( &txn, db, ns, entry["options"].Obj(), true, 0 );
+ Status status = userCreateNS( txn, db, ns, entry["options"].Obj(), true, 0 );
if ( !status.isOK() ) {
warning() << "failed to create collection [" << ns << "] "
<< " with options: " << status;
}
}
else {
- db->createCollection( &txn, ns );
+ db->createCollection( txn, ns );
}
}
}
@@ -1651,9 +1652,8 @@ namespace mongo {
for ( unsigned i=0; i<all.size(); i++ ) {
BSONObj idx = all[i];
Client::WriteContext ctx( ns );
- DurTransaction txn;
Database* db = ctx.ctx().db();
- Collection* collection = db->getCollection( &txn, ns );
+ Collection* collection = db->getCollection( txn, ns );
if ( !collection ) {
errmsg = str::stream() << "collection dropped during migration: " << ns;
warning() << errmsg;
@@ -1661,7 +1661,7 @@ namespace mongo {
return;
}
- Status status = collection->getIndexCatalog()->createIndex(&txn, idx, false);
+ Status status = collection->getIndexCatalog()->createIndex(txn, idx, false);
if ( !status.isOK() && status.code() != ErrorCodes::IndexAlreadyExists ) {
errmsg = str::stream() << "failed to create index before migrating data. "
<< " idx: " << idx
@@ -1672,7 +1672,7 @@ namespace mongo {
}
// make sure to create index on secondaries as well
- logOp( &txn, "i", db->getSystemIndexesName().c_str(), idx,
+ logOp( txn, "i", db->getSystemIndexesName().c_str(), idx,
NULL, NULL, true /* fromMigrate */ );
}
@@ -1684,7 +1684,8 @@ namespace mongo {
// 2. delete any data already in range
Helpers::RemoveSaver rs( "moveChunk" , ns , "preCleanup" );
KeyRange range( ns, min, max, shardKeyPattern );
- long long num = Helpers::removeRange( range,
+ long long num = Helpers::removeRange( txn,
+ range,
false, /*maxInclusive*/
secondaryThrottle, /* secondaryThrottle */
/*callback*/
@@ -1717,7 +1718,8 @@ namespace mongo {
if (state == FAIL || state == ABORT) {
string errMsg;
- if (!getDeleter()->queueDelete(ns, min, max, shardKeyPattern, secondaryThrottle,
+ if (!getDeleter()->queueDelete(DurTransaction::factory, // XXX SERVER-13931
+ ns, min, max, shardKeyPattern, secondaryThrottle,
NULL /* notifier */, &errMsg)) {
warning() << "Failed to queue delete for migrate abort: " << errMsg << endl;
}
@@ -1746,7 +1748,6 @@ namespace mongo {
BSONObj o = i.next().Obj();
{
Client::WriteContext cx( ns );
- DurTransaction txn;
BSONObj localDoc;
if ( willOverrideLocalId( cx.ctx().db(), o, &localDoc ) ) {
@@ -1762,7 +1763,7 @@ namespace mongo {
uasserted( 16976, errMsg );
}
- Helpers::upsert( &txn, ns, o, true );
+ Helpers::upsert( txn, ns, o, true );
}
thisTime++;
numCloned++;
@@ -1802,7 +1803,7 @@ namespace mongo {
if ( res["size"].number() == 0 )
break;
- apply( res , &lastOpApplied );
+ apply( txn, res , &lastOpApplied );
const int maxIterations = 3600*50;
int i;
@@ -1870,7 +1871,7 @@ namespace mongo {
return;
}
- if ( res["size"].number() > 0 && apply( res , &lastOpApplied ) )
+ if ( res["size"].number() > 0 && apply( txn, res , &lastOpApplied ) )
continue;
if ( state == ABORT ) {
@@ -1927,7 +1928,7 @@ namespace mongo {
}
- bool apply( const BSONObj& xfer , ReplTime* lastOpApplied ) {
+ bool apply( TransactionExperiment* txn, const BSONObj& xfer , ReplTime* lastOpApplied ) {
ReplTime dummy;
if ( lastOpApplied == NULL ) {
lastOpApplied = &dummy;
@@ -1960,7 +1961,8 @@ namespace mongo {
// TODO: create a better interface to remove objects directly
KeyRange range( ns, id, id, idIndexPattern );
- Helpers::removeRange( range ,
+ Helpers::removeRange( txn,
+ range ,
true , /*maxInclusive*/
false , /* secondaryThrottle */
serverGlobalParams.moveParanoia ? &rs : 0 , /*callback*/
@@ -1975,7 +1977,6 @@ namespace mongo {
BSONObjIterator i( xfer["reload"].Obj() );
while ( i.more() ) {
Client::WriteContext cx(ns);
- DurTransaction txn;
BSONObj it = i.next().Obj();
@@ -1994,7 +1995,7 @@ namespace mongo {
}
// We are in write lock here, so sure we aren't killing
- Helpers::upsert( &txn, ns , it , true );
+ Helpers::upsert( txn, ns , it , true );
*lastOpApplied = cx.ctx().getClient()->getLastOp().asDate();
didAnything = true;
@@ -2133,11 +2134,12 @@ namespace mongo {
void migrateThread() {
Client::initThread( "migrateThread" );
+ DurTransaction txn;
if (getGlobalAuthorizationManager()->isAuthEnabled()) {
ShardedConnectionInfo::addHook();
cc().getAuthorizationSession()->grantInternalAuthorization();
}
- migrateStatus.go();
+ migrateStatus.go(&txn);
cc().shutdown();
}
diff --git a/src/mongo/s/s_only.cpp b/src/mongo/s/s_only.cpp
index 2b8a28ebdc3..a0b1ed2063b 100644
--- a/src/mongo/s/s_only.cpp
+++ b/src/mongo/s/s_only.cpp
@@ -91,17 +91,19 @@ namespace mongo {
// Need a version that takes a Client to match the mongod interface so the web server can call
// execCommand and not need to worry if it's in a mongod or mongos.
- void Command::execCommand(Command * c,
+ void Command::execCommand(TransactionExperiment* txn,
+ Command * c,
Client& client,
int queryOptions,
const char *ns,
BSONObj& cmdObj,
BSONObjBuilder& result,
bool fromRepl ) {
- execCommandClientBasic(c, client, queryOptions, ns, cmdObj, result, fromRepl);
+ execCommandClientBasic(txn, c, client, queryOptions, ns, cmdObj, result, fromRepl);
}
- void Command::execCommandClientBasic(Command * c ,
+ void Command::execCommandClientBasic(TransactionExperiment* txn,
+ Command * c ,
ClientBasic& client,
int queryOptions,
const char *ns,
@@ -129,7 +131,7 @@ namespace mongo {
std::string errmsg;
bool ok;
try {
- ok = c->run( dbname , cmdObj, queryOptions, errmsg, result, false );
+ ok = c->newRun( txn, dbname , cmdObj, queryOptions, errmsg, result, false );
}
catch (DBException& e) {
ok = false;
diff --git a/src/mongo/s/server.cpp b/src/mongo/s/server.cpp
index 68dc10c8b1e..cffe8e51bea 100644
--- a/src/mongo/s/server.cpp
+++ b/src/mongo/s/server.cpp
@@ -268,7 +268,9 @@ static bool runMongosServer( bool doUpgrade ) {
#endif
if (serverGlobalParams.isHttpInterfaceEnabled)
- boost::thread web( boost::bind(&webServerThread, new NoAdminAccess() /* takes ownership */) );
+ boost::thread web( boost::bind(&webServerThread,
+ new NoAdminAccess(), // takes ownership
+ TransactionExperiment::factoryNULL) ); // XXX SERVER-13931
Status status = getGlobalAuthorizationManager()->initialize();
if (!status.isOK()) {