diff options
author | Dwight <dwight@10gen.com> | 2011-11-17 10:11:15 -0500 |
---|---|---|
committer | Dwight <dwight@10gen.com> | 2011-11-17 10:11:15 -0500 |
commit | 30c7b82757b8147b589d6586fb84860e44fc9763 (patch) | |
tree | fe601c4af1f729fd6bf59667d6c589485c8ed788 /db | |
parent | 66697eb748642f57cf7e67a84313ea6c6ca28fb9 (diff) | |
parent | 4aa2c8b92b5007f9a8401ccc069b88a3b6a17f3c (diff) | |
download | mongo-30c7b82757b8147b589d6586fb84860e44fc9763.tar.gz |
Merge branch 'master' of github.com:mongodb/mongo
Diffstat (limited to 'db')
-rw-r--r-- | db/client.h | 9 | ||||
-rw-r--r-- | db/cloner.cpp | 2 | ||||
-rw-r--r-- | db/d_concurrency.cpp | 17 | ||||
-rw-r--r-- | db/d_concurrency.h | 38 | ||||
-rw-r--r-- | db/database.cpp | 7 | ||||
-rw-r--r-- | db/database.h | 7 | ||||
-rw-r--r-- | db/db.h | 2 | ||||
-rw-r--r-- | db/instance.cpp | 6 | ||||
-rw-r--r-- | db/instance.h | 2 | ||||
-rw-r--r-- | db/namespace.h | 67 | ||||
-rw-r--r-- | db/namespace_common.h | 121 | ||||
-rw-r--r-- | db/repl/rs_sync.cpp | 32 |
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 @@ -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; |