summaryrefslogtreecommitdiff
path: root/db
diff options
context:
space:
mode:
authorDwight <dwight@10gen.com>2011-11-17 10:11:15 -0500
committerDwight <dwight@10gen.com>2011-11-17 10:11:15 -0500
commit30c7b82757b8147b589d6586fb84860e44fc9763 (patch)
treefe601c4af1f729fd6bf59667d6c589485c8ed788 /db
parent66697eb748642f57cf7e67a84313ea6c6ca28fb9 (diff)
parent4aa2c8b92b5007f9a8401ccc069b88a3b6a17f3c (diff)
downloadmongo-30c7b82757b8147b589d6586fb84860e44fc9763.tar.gz
Merge branch 'master' of github.com:mongodb/mongo
Diffstat (limited to 'db')
-rw-r--r--db/client.h9
-rw-r--r--db/cloner.cpp2
-rw-r--r--db/d_concurrency.cpp17
-rw-r--r--db/d_concurrency.h38
-rw-r--r--db/database.cpp7
-rw-r--r--db/database.h7
-rw-r--r--db/db.h2
-rw-r--r--db/instance.cpp6
-rw-r--r--db/instance.h2
-rw-r--r--db/namespace.h67
-rw-r--r--db/namespace_common.h121
-rw-r--r--db/repl/rs_sync.cpp32
12 files changed, 219 insertions, 91 deletions
diff --git a/db/client.h b/db/client.h
index 14a8a94433a..9d05a14cd95 100644
--- a/db/client.h
+++ b/db/client.h
@@ -141,8 +141,6 @@ namespace mongo {
*/
bool sometimes(unsigned howOften) { return ++_sometimes % howOften == 0; }
- public:
-
/* set _god=true temporarily, safely */
class GodScope {
bool _prev;
@@ -221,9 +219,14 @@ namespace mongo {
string _ns;
Database * _db;
-
}; // class Client::Context
+ struct LockStatus {
+ LockStatus() : db(), coll() { }
+ int db;
+ int coll;
+ } lockStatus;
+
}; // class Client
/** get the Client object for this thread. */
diff --git a/db/cloner.cpp b/db/cloner.cpp
index 0e995fb2a35..db848914c2b 100644
--- a/db/cloner.cpp
+++ b/db/cloner.cpp
@@ -266,7 +266,7 @@ namespace mongo {
string temp = ctx.db()->name + ".system.namespaces";
BSONObj config = conn->findOne( temp , BSON( "name" << ns ) );
if ( config["options"].isABSONObj() )
- if ( ! userCreateNS( ns.c_str() , config["options"].Obj() , errmsg, true , 0 ) )
+ if ( ! userCreateNS( ns.c_str() , config["options"].Obj() , errmsg, logForRepl , 0 ) )
return false;
}
diff --git a/db/d_concurrency.cpp b/db/d_concurrency.cpp
new file mode 100644
index 00000000000..6c6bdf60be4
--- /dev/null
+++ b/db/d_concurrency.cpp
@@ -0,0 +1,17 @@
+#include "../pch.h"
+#include "database.h"
+#include "d_concurrency.h"
+#include "../util/concurrency/threadlocal.h"
+#include "../util/concurrency/rwlock.h"
+#include "client.h"
+
+using namespace std;
+
+namespace mongo {
+
+ LockCollectionForReading::LockCollectionForReading(const char *ns)
+ {
+//...
+ }
+
+}
diff --git a/db/d_concurrency.h b/db/d_concurrency.h
new file mode 100644
index 00000000000..8143137c3a2
--- /dev/null
+++ b/db/d_concurrency.h
@@ -0,0 +1,38 @@
+// @file d_concurrency.h
+
+#pragma once
+
+//#include "mongomutex.h"
+
+namespace mongo {
+
+ /* these may be used recursively as long as you do not
+ try to go from sharable to exclusive
+ */
+
+ //void assertDbLocked();
+ //void assertCollectionLocked();
+
+ /*class LockDatabaseExclusively : boost::noncopyable {
+ public:
+ LockDatabaseExclusively(const char *db);
+ };*/
+
+ /*class LockCollectionUpgradably : boost::noncopyable {
+ public:
+ LockCollectionUpgradably(const char *ns);
+ };*/
+
+ class LockCollectionForReading : boost::noncopyable {
+ Database *db;
+ public:
+ LockCollectionForReading(const char *ns);
+ ~LockCollectionForReading();
+ };
+
+ class LockCollectionExclusively : boost::noncopyable {
+ public:
+ LockCollectionExclusively(const char *ns);
+ };
+
+}
diff --git a/db/database.cpp b/db/database.cpp
index 7b47cd4e516..5b617bba141 100644
--- a/db/database.cpp
+++ b/db/database.cpp
@@ -284,13 +284,6 @@ namespace mongo {
return true;
}
- bool Database::validDBName( const string& ns ) {
- if ( ns.size() == 0 || ns.size() > 64 )
- return false;
- size_t good = strcspn( ns.c_str() , "/\\. \"" );
- return good == ns.size();
- }
-
void Database::flushFiles( bool sync ) const {
dbMutex.assertAtLeastReadLocked();
for ( unsigned i=0; i<files.size(); i++ ) {
diff --git a/db/database.h b/db/database.h
index 3522f52d935..384494cb119 100644
--- a/db/database.h
+++ b/db/database.h
@@ -19,9 +19,12 @@
#pragma once
#include "cmdline.h"
+#include "namespace.h"
namespace mongo {
+ class Extent;
+ class MongoDataFile;
class ClientCursor;
struct ByLocKey;
typedef map<ByLocKey, ClientCursor*> CCByLoc;
@@ -103,8 +106,6 @@ namespace mongo {
return ns[name.size()] == '.';
}
- static bool validDBName( const string& ns );
-
/**
* @throws DatabaseDifferCaseCode if the name is a duplicate based on
* case insensitive matching.
@@ -128,6 +129,8 @@ namespace mongo {
const string profileName; // "alleyinsider.system.profile"
CCByLoc ccByLoc;
int magic; // used for making sure the object is still loaded in memory
+
+ RWLockBase dbLock; // d_concurrency.h
};
} // namespace mongo
diff --git a/db/db.h b/db/db.h
index f3e6b05c40e..bcac5b697b5 100644
--- a/db/db.h
+++ b/db/db.h
@@ -117,7 +117,7 @@ namespace mongo {
string _todb( const string& ns ) const {
string d = __todb( ns );
- uassert( 13280 , (string)"invalid db name: " + ns , Database::validDBName( d ) );
+ uassert( 13280 , (string)"invalid db name: " + ns , NamespaceString::validDBName( d ) );
return d;
}
diff --git a/db/instance.cpp b/db/instance.cpp
index 5e20726daa6..485e8d3da54 100644
--- a/db/instance.cpp
+++ b/db/instance.cpp
@@ -41,6 +41,7 @@
#include "ops/update.h"
#include "ops/delete.h"
#include "ops/query.h"
+#include "d_concurrency.h"
namespace mongo {
@@ -473,7 +474,8 @@ namespace mongo {
writelock lk;
- // writelock is used to synchronize stepdowns w/ writes
+ // void ReplSetImpl::relinquish() uses big write lock so
+ // this is thus synchronized given our lock above.
uassert( 10054 , "not master", isMasterNs( ns ) );
// if this ever moves to outside of lock, need to adjust check Client::Context::_finishInit
@@ -666,7 +668,9 @@ namespace mongo {
}
writelock lk(ns);
+ //LockCollectionExclusively lk(ns);
+ // CONCURRENCY TODO: is being read locked in big log sufficient here?
// writelock is used to synchronize stepdowns w/ writes
uassert( 10058 , "not master", isMasterNs(ns) );
diff --git a/db/instance.h b/db/instance.h
index 90f422955cb..9dde729997d 100644
--- a/db/instance.h
+++ b/db/instance.h
@@ -34,7 +34,7 @@ namespace mongo {
and debugging.
*/
class DiagLog {
- ofstream *f;
+ ofstream *f; // note this is never freed
/* 0 = off; 1 = writes, 2 = reads, 3 = both
7 = log a few reads, and all writes.
*/
diff --git a/db/namespace.h b/db/namespace.h
index 885ccee046f..23d60ff14fc 100644
--- a/db/namespace.h
+++ b/db/namespace.h
@@ -19,6 +19,7 @@
#pragma once
#include "../pch.h"
+#include "namespace_common.h"
#include "jsobj.h"
#include "querypattern.h"
#include "diskloc.h"
@@ -27,46 +28,6 @@
namespace mongo {
- /* in the mongo source code, "client" means "database". */
-
- const int MaxDatabaseNameLen = 256; // max str len for the db name, including null char
-
- /* e.g.
- NamespaceString ns("acme.orders");
- cout << ns.coll; // "orders"
- */
- class NamespaceString {
- public:
- string db;
- string coll; // note collection names can have periods in them for organizing purposes (e.g. "system.indexes")
-
- NamespaceString( const char * ns ) { init(ns); }
- NamespaceString( const string& ns ) { init(ns.c_str()); }
- string ns() const { return db + '.' + coll; }
- bool isSystem() const { return strncmp(coll.c_str(), "system.", 7) == 0; }
-
- /**
- * @return true if ns is 'normal'. $ used for collections holding index data, which do not contain BSON objects in their records.
- * special case for the local.oplog.$main ns -- naming it as such was a mistake.
- */
- static bool normal(const char* ns) {
- const char *p = strchr(ns, '$');
- if( p == 0 )
- return true;
- return strcmp( ns, "local.oplog.$main" ) == 0;
- }
-
- static bool special(const char *ns) {
- return !normal(ns) || strstr(ns, ".system.");
- }
- private:
- void init(const char *ns) {
- const char *p = strchr(ns, '.');
- if( p == 0 ) return;
- db = string(ns, p - ns);
- coll = p + 1;
- }
- };
#pragma pack(1)
/* This helper class is used to make the HashMap below in NamespaceIndex e.g. see line:
@@ -663,31 +624,5 @@ namespace mongo {
// (Arguments should include db name)
void renameNamespace( const char *from, const char *to );
- // "database.a.b.c" -> "database"
- inline void nsToDatabase(const char *ns, char *database) {
- const char *p = ns;
- char *q = database;
- while ( *p != '.' ) {
- if ( *p == 0 )
- break;
- *q++ = *p++;
- }
- *q = 0;
- if (q-database>=MaxDatabaseNameLen) {
- log() << "nsToDatabase: ns too long. terminating, buf overrun condition" << endl;
- dbexit( EXIT_POSSIBLE_CORRUPTION );
- }
- }
- inline string nsToDatabase(const char *ns) {
- char buf[MaxDatabaseNameLen];
- nsToDatabase(ns, buf);
- return buf;
- }
- inline string nsToDatabase(const string& ns) {
- size_t i = ns.find( '.' );
- if ( i == string::npos )
- return ns;
- return ns.substr( 0 , i );
- }
} // namespace mongo
diff --git a/db/namespace_common.h b/db/namespace_common.h
new file mode 100644
index 00000000000..b237a0b9280
--- /dev/null
+++ b/db/namespace_common.h
@@ -0,0 +1,121 @@
+// namespace_common.h
+
+/**
+* Copyright (C) 2008 10gen Inc.
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Affero General Public License, version 3,
+* as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Affero General Public License for more details.
+*
+* You should have received a copy of the GNU Affero General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#pragma once
+
+#include <string>
+
+
+/**
+ * this file contains basics utilities for handling namespaces
+ */
+namespace mongo {
+
+ using std::string;
+
+ /* in the mongo source code, "client" means "database". */
+
+ const int MaxDatabaseNameLen = 256; // max str len for the db name, including null char
+
+ /* e.g.
+ NamespaceString ns("acme.orders");
+ cout << ns.coll; // "orders"
+ */
+ class NamespaceString {
+ public:
+ string db;
+ string coll; // note collection names can have periods in them for organizing purposes (e.g. "system.indexes")
+
+ NamespaceString( const char * ns ) { init(ns); }
+ NamespaceString( const string& ns ) { init(ns.c_str()); }
+ string ns() const { return db + '.' + coll; }
+ bool isSystem() const { return strncmp(coll.c_str(), "system.", 7) == 0; }
+
+ /**
+ * @return true if ns is 'normal'. $ used for collections holding index data, which do not contain BSON objects in their records.
+ * special case for the local.oplog.$main ns -- naming it as such was a mistake.
+ */
+ static bool normal(const char* ns) {
+ const char *p = strchr(ns, '$');
+ if( p == 0 )
+ return true;
+ return strcmp( ns, "local.oplog.$main" ) == 0;
+ }
+
+ static bool special(const char *ns) {
+ return !normal(ns) || strstr(ns, ".system.");
+ }
+
+ /**
+ * samples:
+ * good:
+ * foo
+ * bar
+ * foo-bar
+ * bad:
+ * foo bar
+ * foo.bar
+ * foo"bar
+ *
+ * @param db - a possible database name
+ * @return if db is an allowed database name
+ */
+ static bool validDBName( const string& db ) {
+ if ( db.size() == 0 || db.size() > 64 )
+ return false;
+ size_t good = strcspn( db.c_str() , "/\\. \"" );
+ return good == db.size();
+ }
+
+ private:
+ void init(const char *ns) {
+ const char *p = strchr(ns, '.');
+ if( p == 0 ) return;
+ db = string(ns, p - ns);
+ coll = p + 1;
+ }
+ };
+
+ // "database.a.b.c" -> "database"
+ inline void nsToDatabase(const char *ns, char *database) {
+ const char *p = ns;
+ char *q = database;
+ while ( *p != '.' ) {
+ if ( *p == 0 )
+ break;
+ *q++ = *p++;
+ }
+ *q = 0;
+ if (q-database>=MaxDatabaseNameLen) {
+ log() << "nsToDatabase: ns too long. terminating, buf overrun condition" << endl;
+ dbexit( EXIT_POSSIBLE_CORRUPTION );
+ }
+ }
+ inline string nsToDatabase(const char *ns) {
+ char buf[MaxDatabaseNameLen];
+ nsToDatabase(ns, buf);
+ return buf;
+ }
+ inline string nsToDatabase(const string& ns) {
+ size_t i = ns.find( '.' );
+ if ( i == string::npos )
+ return ns;
+ return ns.substr( 0 , i );
+ }
+
+}
diff --git a/db/repl/rs_sync.cpp b/db/repl/rs_sync.cpp
index 3f864bb850c..9450fd5078f 100644
--- a/db/repl/rs_sync.cpp
+++ b/db/repl/rs_sync.cpp
@@ -120,10 +120,28 @@ namespace mongo {
OpTime ts;
time_t start = time(0);
unsigned long long n = 0;
- while( 1 ) {
+ int fails = 0;
+ while( ts < minValid ) {
try {
- if( !r.more() )
- break;
+ // There are some special cases with initial sync (see the catch block), so we
+ // don't want to break out of this while until we've reached minvalid. Thus, we'll
+ // keep trying to requery.
+ if( !r.more() ) {
+ OCCASIONALLY log() << "replSet initial sync oplog: no more records" << endl;
+ sleepsecs(1);
+
+ r.resetCursor();
+ r.tailingQueryGTE(rsoplog, lastOpTimeWritten);
+ if ( !r.haveCursor() ) {
+ if (fails++ > 30) {
+ log() << "replSet initial sync tried to query oplog 30 times, giving up" << endl;
+ return false;
+ }
+ }
+
+ continue;
+ }
+
BSONObj o = r.nextSafe(); /* note we might get "not master" at some point */
ts = o["ts"]._opTime();
@@ -161,10 +179,6 @@ namespace mongo {
}
}
- if ( ts > minValid ) {
- break;
- }
-
getDur().commitIfNeeded();
}
catch (DBException& e) {
@@ -191,8 +205,8 @@ namespace mongo {
return false;
}
- // otherwise, whatever
- break;
+ // otherwise, whatever, we'll break out of the loop and catch
+ // anything that's really wrong in syncTail
}
}
return true;