diff options
author | Dwight <dwight@10gen.com> | 2012-02-29 12:26:22 -0500 |
---|---|---|
committer | Dwight <dwight@10gen.com> | 2012-02-29 12:26:22 -0500 |
commit | f9c66d821ae74a6e3bac851c3b8e66836f4cc9a6 (patch) | |
tree | 1678241d80dda8ef918fe0f3c0a12ec3fd957947 | |
parent | 42a00d27e33ac5b40b4f1e5aa456432f98b8a654 (diff) | |
download | mongo-f9c66d821ae74a6e3bac851c3b8e66836f4cc9a6.tar.gz |
SERVER-4328 add Command::localGlobally method
-rw-r--r-- | src/mongo/db/cloner.cpp | 4 | ||||
-rwxr-xr-x | src/mongo/db/commands.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/commands.h | 11 | ||||
-rwxr-xr-x | src/mongo/db/d_concurrency.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/dbcommands.cpp | 13 | ||||
-rw-r--r-- | src/mongo/db/dbeval.cpp | 1 | ||||
-rw-r--r-- | src/mongo/db/oplog.cpp | 1 | ||||
-rw-r--r-- | src/mongo/db/repl.cpp | 3 |
8 files changed, 33 insertions, 4 deletions
diff --git a/src/mongo/db/cloner.cpp b/src/mongo/db/cloner.cpp index a417cfef8ac..171a634a11b 100644 --- a/src/mongo/db/cloner.cpp +++ b/src/mongo/db/cloner.cpp @@ -540,6 +540,7 @@ namespace mongo { } cmdclonecollection; + // SERVER-4328 todo review for concurrency thread_specific_ptr< DBClientConnection > authConn_; /* Usage: admindb.$cmd.findOne( { copydbgetnonce: 1, fromhost: <hostname> } ); @@ -603,6 +604,9 @@ namespace mongo { bool slaveOk = cmdObj["slaveOk"].trueValue(); string fromhost = cmdObj.getStringField("fromhost"); if ( fromhost.empty() ) { + // SERVER-4328 TODO local globally in this case? or just lock the two databases, but need to lock them in a well-defined order perhaps, + // and the d_concurrency code doesn't allow that yet. + /* copy from self */ stringstream ss; ss << "localhost:" << cmdLine.port; diff --git a/src/mongo/db/commands.cpp b/src/mongo/db/commands.cpp index cbe9ffc6861..3da942d8c24 100755 --- a/src/mongo/db/commands.cpp +++ b/src/mongo/db/commands.cpp @@ -74,6 +74,8 @@ namespace mongo { ss << "S ";
if( adminOnly() )
ss << "A";
+ if( lockGlobally() )
+ ss << " lockGlobally ";
ss << "</td>";
ss << "<td>";
if( helpStr != "no help defined" ) {
diff --git a/src/mongo/db/commands.h b/src/mongo/db/commands.h index 8d8ee7545f0..d03b792cedf 100644 --- a/src/mongo/db/commands.h +++ b/src/mongo/db/commands.h @@ -37,7 +37,9 @@ namespace mongo { // only makes sense for commands where 1st parm is the collection. virtual string parseNs(const string& dbname, const BSONObj& cmdObj) const; - enum LockType { READ = -1 , NONE = 0 , WRITE = 1, GLOBAL = 2 }; + // warning: isAuthorized uses the lockType() return values, and values are being passed + // around as ints so be careful as it isn't really typesafe and will need cleanup later + enum LockType { READ = -1 , NONE = 0 , WRITE = 1 }; const string name; @@ -52,12 +54,17 @@ namespace mongo { virtual bool run(const string& db, BSONObj& cmdObj, int options, string& errmsg, BSONObjBuilder& result, bool fromRepl = false ) = 0; /* - note: logTheTop() MUST be false if READ + note: logTheOp() MUST be false if READ if NONE, can't use Client::Context setup use with caution */ virtual LockType locktype() const = 0; + /** if true, lock globally instead of just the one database. by default only the one + database will be locked. + */ + virtual bool lockGlobally() const { return false; } + /* Return true if only the admin ns has privileges to run this command. */ virtual bool adminOnly() const { return false; diff --git a/src/mongo/db/d_concurrency.cpp b/src/mongo/db/d_concurrency.cpp index a0e874160c6..83612e56c76 100755 --- a/src/mongo/db/d_concurrency.cpp +++ b/src/mongo/db/d_concurrency.cpp @@ -625,12 +625,14 @@ namespace mongo { void MongoMutex::assertWriteLocked() const { if( !isWriteLocked() ) { lockState().dump(); + dassert(false); // dassert will terminate buildbot msgasserted(0, "expected write lock"); } } void MongoMutex::assertAtLeastReadLocked() const { if( !atLeastReadLocked() ) { lockState().dump(); + dassert(false); // dassert will terminate buildbot msgasserted(0, "expected read lock"); } } diff --git a/src/mongo/db/dbcommands.cpp b/src/mongo/db/dbcommands.cpp index 3344814524e..f266b1243eb 100644 --- a/src/mongo/db/dbcommands.cpp +++ b/src/mongo/db/dbcommands.cpp @@ -330,6 +330,11 @@ namespace mongo { virtual bool slaveOk() const { return false; } + + // this is suboptimal but syncDataAndTruncateJournal is called from dropDatabase, and that + // may need a global lock. + virtual bool lockGlobally() const { return true; } + virtual LockType locktype() const { return WRITE; } CmdDropDatabase() : Command("dropDatabase") {} bool run(const string& dbname, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) { @@ -1051,6 +1056,7 @@ namespace mongo { virtual bool adminOnly() const { return true; } virtual bool slaveOk() const { return false; } virtual LockType locktype() const { return WRITE; } + virtual bool lockGlobally() const { return true; } CmdCloseAllDatabases() : Command( "closeAllDatabases" ) {} bool run(const string& dbname , BSONObj& jsobj, int, string& errmsg, BSONObjBuilder& result, bool /*fromRepl*/) { @@ -1864,6 +1870,8 @@ namespace mongo { bool retval = false; if ( c->locktype() == Command::NONE ) { + assert( !c->lockGlobally() ); + // we also trust that this won't crash retval = true; @@ -1884,13 +1892,16 @@ namespace mongo { // read lock assert( ! c->logTheOp() ); string ns = c->parseNs(dbname, cmdObj); + scoped_ptr<Lock::GlobalRead> lk; + if( c->lockGlobally() ) + lk.reset( new Lock::GlobalRead() ); Client::ReadContext ctx( ns , dbpath, c->requiresAuth() ); // read locks client.curop()->ensureStarted(); retval = _execCommand(c, dbname , cmdObj , queryOptions, result , fromRepl ); } else { dassert( c->locktype() == Command::WRITE ); - writelock lk; + writelock lk( c->lockGlobally() ? "" : dbname ); client.curop()->ensureStarted(); Client::Context ctx( dbname , dbpath , c->requiresAuth() ); retval = _execCommand(c, dbname , cmdObj , queryOptions, result , fromRepl ); diff --git a/src/mongo/db/dbeval.cpp b/src/mongo/db/dbeval.cpp index 9e77d8c8097..67e110da71e 100644 --- a/src/mongo/db/dbeval.cpp +++ b/src/mongo/db/dbeval.cpp @@ -106,6 +106,7 @@ namespace mongo { return true; } + // SERVER-4328 todo review for concurrency class CmdEval : public Command { public: virtual bool slaveOk() const { diff --git a/src/mongo/db/oplog.cpp b/src/mongo/db/oplog.cpp index b3eeb06cf75..f220845d853 100644 --- a/src/mongo/db/oplog.cpp +++ b/src/mongo/db/oplog.cpp @@ -838,6 +838,7 @@ namespace mongo { return failedUpdate; } + // SERVER-4328 todo review for concurrency class ApplyOpsCmd : public Command { public: virtual bool slaveOk() const { return false; } diff --git a/src/mongo/db/repl.cpp b/src/mongo/db/repl.cpp index 5490515af6b..2f5bfde7dbe 100644 --- a/src/mongo/db/repl.cpp +++ b/src/mongo/db/repl.cpp @@ -88,7 +88,8 @@ namespace mongo { return true; } virtual bool logTheOp() { return false; } - virtual LockType locktype() const { return GLOBAL; } + virtual bool lockGlobally() const { return true; } + virtual LockType locktype() const { return WRITE; } void help(stringstream&h) const { h << "resync (from scratch) an out of date replica slave.\nhttp://www.mongodb.org/display/DOCS/Master+Slave"; } CmdResync() : Command("resync") { } virtual bool run(const string& , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) { |