summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEliot Horowitz <eliot@10gen.com>2012-10-15 12:26:00 -0400
committerEliot Horowitz <eliot@10gen.com>2012-10-15 18:07:07 -0400
commited8c12d161bcbff667a08712f6111a806465f4be (patch)
treea88da8dd233463dd22bfcb8aa40204f08425538a
parentb327e6eaeb79852148dbe3c70588f09c746a9e24 (diff)
downloadmongo-ed8c12d161bcbff667a08712f6111a806465f4be.tar.gz
use orderded_map for NamespaceDetailsTransient
-rw-r--r--src/mongo/db/cap.cpp2
-rw-r--r--src/mongo/db/instance.cpp2
-rw-r--r--src/mongo/db/namespace_details.cpp60
-rw-r--r--src/mongo/db/namespace_details.h46
-rw-r--r--src/mongo/db/pdfile.cpp2
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);
}