summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDwight <dwight@10gen.com>2012-02-29 12:26:22 -0500
committerDwight <dwight@10gen.com>2012-02-29 12:26:22 -0500
commitf9c66d821ae74a6e3bac851c3b8e66836f4cc9a6 (patch)
tree1678241d80dda8ef918fe0f3c0a12ec3fd957947
parent42a00d27e33ac5b40b4f1e5aa456432f98b8a654 (diff)
downloadmongo-f9c66d821ae74a6e3bac851c3b8e66836f4cc9a6.tar.gz
SERVER-4328 add Command::localGlobally method
-rw-r--r--src/mongo/db/cloner.cpp4
-rwxr-xr-xsrc/mongo/db/commands.cpp2
-rw-r--r--src/mongo/db/commands.h11
-rwxr-xr-xsrc/mongo/db/d_concurrency.cpp2
-rw-r--r--src/mongo/db/dbcommands.cpp13
-rw-r--r--src/mongo/db/dbeval.cpp1
-rw-r--r--src/mongo/db/oplog.cpp1
-rw-r--r--src/mongo/db/repl.cpp3
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) {