diff options
author | Eliot Horowitz <eliot@10gen.com> | 2012-10-15 12:26:00 -0400 |
---|---|---|
committer | Eliot Horowitz <eliot@10gen.com> | 2012-10-15 18:07:07 -0400 |
commit | ed8c12d161bcbff667a08712f6111a806465f4be (patch) | |
tree | a88da8dd233463dd22bfcb8aa40204f08425538a | |
parent | b327e6eaeb79852148dbe3c70588f09c746a9e24 (diff) | |
download | mongo-ed8c12d161bcbff667a08712f6111a806465f4be.tar.gz |
use orderded_map for NamespaceDetailsTransient
-rw-r--r-- | src/mongo/db/cap.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/instance.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/namespace_details.cpp | 60 | ||||
-rw-r--r-- | src/mongo/db/namespace_details.h | 46 | ||||
-rw-r--r-- | src/mongo/db/pdfile.cpp | 2 |
5 files changed, 66 insertions, 46 deletions
diff --git a/src/mongo/db/cap.cpp b/src/mongo/db/cap.cpp index 6309eb6adb9..0cccf39dff2 100644 --- a/src/mongo/db/cap.cpp +++ b/src/mongo/db/cap.cpp @@ -433,7 +433,7 @@ namespace mongo { // Clear all references to this namespace. ClientCursor::invalidate( ns ); - NamespaceDetailsTransient::clearForPrefix( ns ); + NamespaceDetailsTransient::resetCollection( ns ); // Get a writeable reference to 'this' and reset all pertinent // attributes. diff --git a/src/mongo/db/instance.cpp b/src/mongo/db/instance.cpp index 22205d2b0fa..fa1a2b5c684 100644 --- a/src/mongo/db/instance.cpp +++ b/src/mongo/db/instance.cpp @@ -544,7 +544,7 @@ namespace mongo { prefix += '.'; ClientCursor::invalidate(prefix.c_str()); - NamespaceDetailsTransient::clearForPrefix( prefix.c_str() ); + NamespaceDetailsTransient::eraseDB( prefix ); dbHolderW().erase( db, path ); ctx->_clear(); diff --git a/src/mongo/db/namespace_details.cpp b/src/mongo/db/namespace_details.cpp index 19f3eef4c49..4ff11e2c1fb 100644 --- a/src/mongo/db/namespace_details.cpp +++ b/src/mongo/db/namespace_details.cpp @@ -617,8 +617,7 @@ namespace mongo { SimpleMutex NamespaceDetailsTransient::_qcMutex("qc"); SimpleMutex NamespaceDetailsTransient::_isMutex("is"); - map< string, shared_ptr< NamespaceDetailsTransient > > NamespaceDetailsTransient::_nsdMap; - typedef map< string, shared_ptr< NamespaceDetailsTransient > >::iterator ouriter; + NamespaceDetailsTransient::DMap NamespaceDetailsTransient::_nsdMap; void NamespaceDetailsTransient::reset() { Lock::assertWriteLocked(_ns); @@ -627,8 +626,15 @@ namespace mongo { _indexSpecs.clear(); } - /*static*/ NOINLINE_DECL NamespaceDetailsTransient& NamespaceDetailsTransient::make_inlock(const char *ns) { - shared_ptr< NamespaceDetailsTransient > &t = _nsdMap[ ns ]; + NamespaceDetailsTransient::CMap& NamespaceDetailsTransient::get_cmap_inlock(const string& ns) { + CMap*& m = _nsdMap[ns]; + if ( ! m ) + m = new CMap(); + return *m; + } + + /*static*/ NOINLINE_DECL NamespaceDetailsTransient& NamespaceDetailsTransient::make_inlock(const string& ns) { + shared_ptr< NamespaceDetailsTransient > &t = get_cmap_inlock(ns)[ ns ]; verify( t.get() == 0 ); Database *database = cc().database(); verify( database ); @@ -644,7 +650,7 @@ namespace mongo { // note with repair there could be two databases with the same ns name. // that is NOT handled here yet! TODO // repair may not use nsdt though not sure. anyway, requires work. - NamespaceDetailsTransient::NamespaceDetailsTransient(Database *db, const char *ns) : + NamespaceDetailsTransient::NamespaceDetailsTransient(Database *db, const string& ns) : _ns(ns), _keysComputed(false), _qcWriteCount() { dassert(db); @@ -652,34 +658,30 @@ namespace mongo { NamespaceDetailsTransient::~NamespaceDetailsTransient() { } - - void NamespaceDetailsTransient::clearForPrefix(const char *prefix) { + + void NamespaceDetailsTransient::resetCollection(const string& ns ) { SimpleMutex::scoped_lock lk(_qcMutex); - vector< string > found; - for( ouriter i = _nsdMap.begin(); i != _nsdMap.end(); ++i ) { - if ( strncmp( i->first.c_str(), prefix, strlen( prefix ) ) == 0 ) { - found.push_back( i->first ); - Lock::assertWriteLocked(i->first); - } - } - for( vector< string >::iterator i = found.begin(); i != found.end(); ++i ) { - _nsdMap[ *i ].reset(); - } + Lock::assertWriteLocked(ns); + get_cmap_inlock(ns)[ns].reset(); } - - void NamespaceDetailsTransient::eraseForPrefix(const char *prefix) { + + void NamespaceDetailsTransient::eraseDB(const string& db) { SimpleMutex::scoped_lock lk(_qcMutex); - vector< string > found; - for( ouriter i = _nsdMap.begin(); i != _nsdMap.end(); ++i ) { - if ( strncmp( i->first.c_str(), prefix, strlen( prefix ) ) == 0 ) { - found.push_back( i->first ); - Lock::assertWriteLocked(i->first); - } - } - for( vector< string >::iterator i = found.begin(); i != found.end(); ++i ) { - _nsdMap.erase(*i); + Lock::assertWriteLocked(db); + + DMap::iterator i = _nsdMap.find( db ); + if ( i != _nsdMap.end() ) { + delete i->second; + _nsdMap.erase( i ); } } + + void NamespaceDetailsTransient::eraseCollection(const string& ns) { + SimpleMutex::scoped_lock lk(_qcMutex); + Lock::assertWriteLocked(ns); + get_cmap_inlock(ns).erase(ns); + } + void NamespaceDetailsTransient::computeIndexKeys() { _indexKeys.clear(); @@ -802,7 +804,7 @@ namespace mongo { // index details across commands are in cursors and nsd // transient (including query cache) so clear these. ClientCursor::invalidate( from ); - NamespaceDetailsTransient::eraseForPrefix( from ); + NamespaceDetailsTransient::eraseCollection( from ); NamespaceDetails *details = ni->details( from ); ni->add_ns( to, *details ); diff --git a/src/mongo/db/namespace_details.h b/src/mongo/db/namespace_details.h index 043c5a76d7e..76eb3d0bf7a 100644 --- a/src/mongo/db/namespace_details.h +++ b/src/mongo/db/namespace_details.h @@ -19,15 +19,16 @@ #pragma once #include "mongo/pch.h" - #include "mongo/db/d_concurrency.h" #include "mongo/db/diskloc.h" #include "mongo/db/index.h" #include "mongo/db/jsobj.h" #include "mongo/db/mongommf.h" #include "mongo/db/namespace.h" +#include "mongo/db/namespacestring.h" #include "mongo/db/queryoptimizercursor.h" #include "mongo/db/querypattern.h" +#include "mongo/platform/unordered_map.h" #include "mongo/util/hashtab.h" namespace mongo { @@ -429,18 +430,33 @@ namespace mongo { //Database *database; const string _ns; void reset(); - static std::map< string, shared_ptr< NamespaceDetailsTransient > > _nsdMap; + + // < db -> < fullns -> NDT > > + typedef unordered_map< string, shared_ptr<NamespaceDetailsTransient> > CMap; + typedef unordered_map< string, CMap*, NamespaceDBHash, NamespaceDBEquals > DMap; + static DMap _nsdMap; - NamespaceDetailsTransient(Database*,const char *ns); + NamespaceDetailsTransient(Database*,const string& ns); public: ~NamespaceDetailsTransient(); void addedIndex() { reset(); } void deletedIndex() { reset(); } - /* Drop cached information on all namespaces beginning with the specified prefix. - Can be useful as index namespaces share the same start as the regular collection. - SLOW - sequential scan of all NamespaceDetailsTransient objects */ - static void clearForPrefix(const char *prefix); - static void eraseForPrefix(const char *prefix); + + /** + * reset stats for a given collection + */ + static void resetCollection(const string& ns ); + + /** + * remove entry for a collection + */ + static void eraseCollection(const string& ns); + + /** + * remove all entries for db + */ + static void eraseDB(const string& db); + /** * @return a cursor interface to the query optimizer. The implementation may utilize a @@ -538,7 +554,8 @@ namespace mongo { private: int _qcWriteCount; map<QueryPattern,CachedQueryPlan> _qcCache; - static NamespaceDetailsTransient& make_inlock(const char *ns); + static NamespaceDetailsTransient& make_inlock(const string& ns); + static CMap& get_cmap_inlock(const string& ns); public: static SimpleMutex _qcMutex; @@ -548,7 +565,7 @@ namespace mongo { Creates a NamespaceDetailsTransient before returning if one DNE. todo: avoid creating too many on erroneous ns queries. */ - static NamespaceDetailsTransient& get_inlock(const char *ns); + static NamespaceDetailsTransient& get_inlock(const string& ns); static NamespaceDetailsTransient& get(const char *ns) { // todo : _qcMutex will create bottlenecks in our parallelism @@ -577,10 +594,11 @@ namespace mongo { }; /* NamespaceDetailsTransient */ - inline NamespaceDetailsTransient& NamespaceDetailsTransient::get_inlock(const char *ns) { - std::map< string, shared_ptr< NamespaceDetailsTransient > >::iterator i = _nsdMap.find(ns); - if( i != _nsdMap.end() && - i->second.get() ) { // could be null ptr from clearForPrefix + inline NamespaceDetailsTransient& NamespaceDetailsTransient::get_inlock(const string& ns) { + CMap& m = get_cmap_inlock(ns); + CMap::iterator i = m.find( ns ); + if ( i != m.end() && + i->second.get() ) { // could be null ptr from clearForPrefix return *i->second; } return make_inlock(ns); diff --git a/src/mongo/db/pdfile.cpp b/src/mongo/db/pdfile.cpp index ae13301060b..548a41f87f1 100644 --- a/src/mongo/db/pdfile.cpp +++ b/src/mongo/db/pdfile.cpp @@ -1004,7 +1004,7 @@ namespace mongo { result.append("ns", name.c_str()); ClientCursor::invalidate(name.c_str()); Top::global.collectionDropped( name ); - NamespaceDetailsTransient::eraseForPrefix( name.c_str() ); + NamespaceDetailsTransient::eraseCollection( name ); dropNS(name); } |