diff options
author | Eliot Horowitz <eliot@10gen.com> | 2013-06-25 19:42:11 -0400 |
---|---|---|
committer | Eliot Horowitz <eliot@10gen.com> | 2013-06-26 22:36:37 -0400 |
commit | 692f1859a032a92e54f08b1a2a130fa99590b1d0 (patch) | |
tree | cb5704667f7ec4254b3a837e2f2668cfbaacafe5 | |
parent | bd0713e9a67f67b19944841275007f6fc6ee1c69 (diff) | |
download | mongo-692f1859a032a92e54f08b1a2a130fa99590b1d0.tar.gz |
clean NamespaceString so that it can be the thing passed around
32 files changed, 406 insertions, 240 deletions
diff --git a/src/mongo/SConscript b/src/mongo/SConscript index 078c495b0f9..9f64c07d780 100644 --- a/src/mongo/SConscript +++ b/src/mongo/SConscript @@ -484,6 +484,7 @@ serverOnlyFiles = [ "db/curop.cpp", "db/instance.cpp", "db/client.cpp", "db/database.cpp", + "db/background.cpp", "db/pdfile.cpp", "db/cursor.cpp", "db/query_optimizer.cpp", diff --git a/src/mongo/client/dbclient.cpp b/src/mongo/client/dbclient.cpp index 0eeb29b3315..9dd39934d9b 100644 --- a/src/mongo/client/dbclient.cpp +++ b/src/mongo/client/dbclient.cpp @@ -436,10 +436,9 @@ namespace mongo { } unsigned long long DBClientWithCommands::count(const string &myns, const BSONObj& query, int options, int limit, int skip ) { - NamespaceString ns(myns); BSONObj cmd = _countCmd( myns , query , options , limit , skip ); BSONObj res; - if( !runCommand(ns.db.c_str(), cmd, res, options) ) + if( !runCommand(nsToDatabase(myns), cmd, res, options) ) uasserted(11010,string("count fails:") + res.toString()); return res["n"].numberLong(); } @@ -447,7 +446,7 @@ namespace mongo { BSONObj DBClientWithCommands::_countCmd(const string &myns, const BSONObj& query, int options, int limit, int skip ) { NamespaceString ns(myns); BSONObjBuilder b; - b.append( "count" , ns.coll ); + b.append( "count" , ns.coll() ); b.append( "query" , query ); if ( limit ) b.append( "limit" , limit ); @@ -1198,7 +1197,7 @@ namespace mongo { void DBClientWithCommands::dropIndex( const string& ns , const string& indexName ) { BSONObj info; if ( ! runCommand( nsToDatabase( ns ) , - BSON( "deleteIndexes" << NamespaceString( ns ).coll << "index" << indexName ) , + BSON( "deleteIndexes" << nsToCollectionSubstring(ns) << "index" << indexName ) , info ) ) { LOG(_logLevel) << "dropIndex failed: " << info << endl; uassert( 10007 , "dropIndex failed" , 0 ); @@ -1208,9 +1207,12 @@ namespace mongo { void DBClientWithCommands::dropIndexes( const string& ns ) { BSONObj info; - uassert( 10008 , "dropIndexes failed" , runCommand( nsToDatabase( ns ) , - BSON( "deleteIndexes" << NamespaceString( ns ).coll << "index" << "*") , - info ) ); + uassert( 10008, + "dropIndexes failed", + runCommand( nsToDatabase( ns ), + BSON( "deleteIndexes" << nsToCollectionSubstring(ns) << "index" << "*"), + info ) + ); resetIndexCache(); } diff --git a/src/mongo/client/parallel.cpp b/src/mongo/client/parallel.cpp index 725ffc486e6..8afbfdbbe95 100644 --- a/src/mongo/client/parallel.cpp +++ b/src/mongo/client/parallel.cpp @@ -673,7 +673,7 @@ namespace mongo { void ParallelSortClusteredCursor::_handleStaleNS( const NamespaceString& staleNS, bool forceReload, bool fullReload ){ - DBConfigPtr config = grid.getDBConfig( staleNS.db ); + DBConfigPtr config = grid.getDBConfig( staleNS.db() ); // Reload db if needed, make sure it works if( config && fullReload && ! config->reload() ){ @@ -770,7 +770,7 @@ namespace mongo { bool returnPartial = ( _qSpec.options() & QueryOption_PartialResults ); bool specialVersion = _cInfo.versionedNS.size() > 0; bool specialFilter = ! _cInfo.cmdFilter.isEmpty(); - NamespaceString ns = specialVersion ? _cInfo.versionedNS : _qSpec.ns(); + NamespaceString ns( specialVersion ? _cInfo.versionedNS : _qSpec.ns() ); ChunkManagerPtr manager; ShardPtr primary; @@ -792,7 +792,7 @@ namespace mongo { if( isVersioned() ){ - DBConfigPtr config = grid.getDBConfig( ns.db ); // Gets or loads the config + DBConfigPtr config = grid.getDBConfig( ns.db() ); // Gets or loads the config uassert( 15989, "database not found for parallel cursor request", config ); // Try to get either the chunk manager or the primary shard @@ -978,7 +978,7 @@ namespace mongo { catch( StaleConfigException& e ){ // Our version isn't compatible with the current version anymore on at least one shard, need to retry immediately - NamespaceString staleNS = e.getns(); + NamespaceString staleNS( e.getns() ); // For legacy reasons, this may not be set in the exception :-( if( staleNS.size() == 0 ) staleNS = ns; // ns is the *versioned* namespace, be careful of this @@ -1195,7 +1195,7 @@ namespace mongo { if( staleNSExceptions.size() ){ for( map<string,StaleConfigException>::iterator i = staleNSExceptions.begin(), end = staleNSExceptions.end(); i != end; ++i ){ - const string& staleNS = i->first; + NamespaceString staleNS( i->first ); const StaleConfigException& exception = i->second; bool forceReload, fullReload; diff --git a/src/mongo/client/syncclusterconnection.cpp b/src/mongo/client/syncclusterconnection.cpp index 4b00221798e..82cdc8da1ac 100644 --- a/src/mongo/client/syncclusterconnection.cpp +++ b/src/mongo/client/syncclusterconnection.cpp @@ -317,8 +317,8 @@ namespace mongo { void SyncClusterConnection::insert( const string &ns, BSONObj obj , int flags) { uassert(13119, - (string)"SyncClusterConnection::insert obj has to have an _id: " + obj.jsonString(), - NamespaceString(ns).coll == "system.indexes" || obj["_id"].type()); + str::stream() << "SyncClusterConnection::insert obj has to have an _id: " << obj, + nsToCollectionSubstring(ns) == "system.indexes" || obj["_id"].type()); string errmsg; if ( ! prepare( errmsg ) ) diff --git a/src/mongo/db/auth/auth_index_d.cpp b/src/mongo/db/auth/auth_index_d.cpp index 3ce6c0de43f..270c3aeea9b 100644 --- a/src/mongo/db/auth/auth_index_d.cpp +++ b/src/mongo/db/auth/auth_index_d.cpp @@ -50,9 +50,10 @@ namespace { std::string systemUsers = dbname.toString() + ".system.users"; Client::WriteContext wctx(systemUsers); - createSystemIndexes(systemUsers); + NamespaceString systemUsersNS( systemUsers ); + createSystemIndexes(systemUsersNS); - NamespaceDetails* nsd = nsdetails(systemUsers.c_str()); + NamespaceDetails* nsd = nsdetails(systemUsers); if (nsd == NULL) return; @@ -90,7 +91,7 @@ namespace { } void createSystemIndexes(const NamespaceString& ns) { - if (ns.coll == "system.users") { + if (ns.coll() == "system.users") { try { Helpers::ensureIndex(ns.ns().c_str(), extendedSystemUsersKeyPattern, diff --git a/src/mongo/db/auth/authorization_session.cpp b/src/mongo/db/auth/authorization_session.cpp index 2fbbcbd1bf3..24f28251f27 100644 --- a/src/mongo/db/auth/authorization_session.cpp +++ b/src/mongo/db/auth/authorization_session.cpp @@ -234,17 +234,18 @@ namespace { Privilege AuthorizationSession::_modifyPrivilegeForSpecialCases(const Privilege& privilege) { ActionSet newActions; newActions.addAllActionsFromSet(privilege.getActions()); - std::string collectionName = NamespaceString(privilege.getResource()).coll; - if (collectionName == "system.users") { + NamespaceString ns( privilege.getResource() ); + + if (ns.coll() == "system.users") { newActions.removeAction(ActionType::find); newActions.removeAction(ActionType::insert); newActions.removeAction(ActionType::update); newActions.removeAction(ActionType::remove); newActions.addAction(ActionType::userAdmin); - } else if (collectionName == "system.profile") { + } else if (ns.coll() == "system.profile") { newActions.removeAction(ActionType::find); newActions.addAction(ActionType::profileRead); - } else if (collectionName == "system.indexes" && newActions.contains(ActionType::find)) { + } else if (ns.coll() == "system.indexes" && newActions.contains(ActionType::find)) { newActions.removeAction(ActionType::find); newActions.addAction(ActionType::indexRead); } diff --git a/src/mongo/db/auth/authorization_session_test.cpp b/src/mongo/db/auth/authorization_session_test.cpp index 24f1b26dac0..ba21badbe5b 100644 --- a/src/mongo/db/auth/authorization_session_test.cpp +++ b/src/mongo/db/auth/authorization_session_test.cpp @@ -79,13 +79,13 @@ namespace { std::string user = query[AuthorizationManager::USER_NAME_FIELD_NAME].String(); std::string userSource; if (!query[AuthorizationManager::USER_SOURCE_FIELD_NAME].trueValue()) { - userSource = nsstring.db; + userSource = nsstring.db().toString(); } else { userSource = query[AuthorizationManager::USER_SOURCE_FIELD_NAME].String(); } *result = mapFindWithDefault(_privilegeDocs, - std::make_pair(nsstring.db, + std::make_pair(nsstring.db().toString(), UserName(user, userSource)), BSON("invalid" << 1)); return !(*result)["invalid"].trueValue(); diff --git a/src/mongo/db/background.cpp b/src/mongo/db/background.cpp new file mode 100644 index 00000000000..c57c3a5e919 --- /dev/null +++ b/src/mongo/db/background.cpp @@ -0,0 +1,78 @@ +// background.cpp + +/** +* Copyright (C) 2010 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/>. +*/ + +#include "mongo/db/background.h" + +namespace mongo { + + SimpleMutex BackgroundOperation::m("bg"); + std::map<std::string, unsigned> BackgroundOperation::dbsInProg; + std::set<std::string> BackgroundOperation::nsInProg; + + bool BackgroundOperation::inProgForDb(const StringData& db) { + SimpleMutex::scoped_lock lk(m); + return dbsInProg[db.toString()] > 0; + } + + bool BackgroundOperation::inProgForNs(const StringData& ns) { + SimpleMutex::scoped_lock lk(m); + return nsInProg.count(ns.toString()) > 0; + } + + void BackgroundOperation::assertNoBgOpInProgForDb(const StringData& db) { + uassert(12586, + "cannot perform operation: a background operation is currently running for this database", + !inProgForDb(db)); + } + + void BackgroundOperation::assertNoBgOpInProgForNs(const StringData& ns) { + uassert(12587, + "cannot perform operation: a background operation is currently running for this collection", + !inProgForNs(ns)); + } + + BackgroundOperation::BackgroundOperation(const StringData& ns) : _ns(ns) { + SimpleMutex::scoped_lock lk(m); + dbsInProg[_ns.db().toString()]++; + nsInProg.insert(_ns.ns()); + } + + BackgroundOperation::~BackgroundOperation() { + SimpleMutex::scoped_lock lk(m); + dbsInProg[_ns.db().toString()]--; + nsInProg.erase(_ns.ns()); + } + + void BackgroundOperation::dump(std::stringstream& ss) { + SimpleMutex::scoped_lock lk(m); + if( nsInProg.size() ) { + ss << "\n<b>Background Jobs in Progress</b>\n"; + for( std::set<std::string>::iterator i = nsInProg.begin(); i != nsInProg.end(); i++ ) + ss << " " << *i << '\n'; + } + for( std::map<std::string,unsigned>::iterator i = dbsInProg.begin(); i != dbsInProg.end(); i++ ) { + if( i->second ) + ss << "database " << i->first << ": " << i->second << '\n'; + } + } + + + + +} // namespace mongo + diff --git a/src/mongo/db/background.h b/src/mongo/db/background.h index 0b76abf3a8e..bfc48404fb3 100644 --- a/src/mongo/db/background.h +++ b/src/mongo/db/background.h @@ -21,7 +21,14 @@ #pragma once +#include <map> +#include <set> +#include <string> +#include <sstream> + +#include "mongo/base/string_data.h" #include "mongo/db/namespacestring.h" +#include "mongo/util/concurrency/mutex.h" namespace mongo { @@ -37,21 +44,21 @@ namespace mongo { */ class BackgroundOperation : public boost::noncopyable { public: - static bool inProgForDb(const char *db); - static bool inProgForNs(const char *ns); - static void assertNoBgOpInProgForDb(const char *db); - static void assertNoBgOpInProgForNs(const char *ns); - static void dump(stringstream&); + static bool inProgForDb(const StringData& db); + static bool inProgForNs(const StringData& ns); + static void assertNoBgOpInProgForDb(const StringData& db); + static void assertNoBgOpInProgForNs(const StringData& ns); + static void dump(std::stringstream&); /* check for in progress before instantiating */ - BackgroundOperation(const char *ns); + BackgroundOperation(const StringData& ns); virtual ~BackgroundOperation(); private: NamespaceString _ns; - static map<string, unsigned> dbsInProg; - static set<string> nsInProg; + static std::map<std::string, unsigned> dbsInProg; + static std::set<std::string> nsInProg; static SimpleMutex m; }; diff --git a/src/mongo/db/cloner.cpp b/src/mongo/db/cloner.cpp index 82a68e75e19..8168a68bd44 100644 --- a/src/mongo/db/cloner.cpp +++ b/src/mongo/db/cloner.cpp @@ -140,7 +140,7 @@ namespace mongo { BSONObj js = tmp; if ( isindex ) { - verify(NamespaceString(from_collection).coll == "system.indexes"); + verify(nsToCollectionSubstring(from_collection) == "system.indexes"); js = fixindex(tmp); storedForLater->push_back( js.getOwned() ); continue; diff --git a/src/mongo/db/commands.cpp b/src/mongo/db/commands.cpp index b80861c757a..54c8f393f30 100644 --- a/src/mongo/db/commands.cpp +++ b/src/mongo/db/commands.cpp @@ -49,12 +49,14 @@ namespace mongo { false); } - string Command::parseNsFullyQualified(const string& dbname, const BSONObj& cmdObj) const { + string Command::parseNsFullyQualified(const string& dbname, const BSONObj& cmdObj) const { string s = cmdObj.firstElement().valuestr(); NamespaceString nss(s); // these are for security, do not remove: - massert(15962, "need to specify namespace" , !nss.db.empty() ); - massert(15966, str::stream() << "dbname not ok in Command::parseNsFullyQualified: " << dbname , dbname == nss.db || dbname == "admin" ); + massert(15962, "need to specify namespace" , !nss.db().empty() ); + massert(15966, + str::stream() << "dbname not ok in Command::parseNsFullyQualified: " + << dbname , dbname == nss.db() || dbname == "admin" ); return s; } diff --git a/src/mongo/db/commands/rename_collection_common.cpp b/src/mongo/db/commands/rename_collection_common.cpp index 51ca4bbe6fa..540a82a8b7e 100644 --- a/src/mongo/db/commands/rename_collection_common.cpp +++ b/src/mongo/db/commands/rename_collection_common.cpp @@ -35,7 +35,7 @@ namespace rename_collection { ActionSet sourceActions; ActionSet targetActions; - if (sourceNS.db == targetNS.db) { + if (sourceNS.db() == targetNS.db()) { sourceActions.addAction(ActionType::renameCollectionSameDB); targetActions.addAction(ActionType::renameCollectionSameDB); } else { diff --git a/src/mongo/db/compact.cpp b/src/mongo/db/compact.cpp index ccce11779ce..77cfd7a2413 100644 --- a/src/mongo/db/compact.cpp +++ b/src/mongo/db/compact.cpp @@ -259,7 +259,7 @@ namespace mongo { // build indexes NamespaceString s(ns); - string si = s.db + ".system.indexes"; + string si = s.db().toString() + ".system.indexes"; for( int i = 0; i < nidx; i++ ) { killCurrentOp.checkForInterrupt(false); BSONObj info = indexSpecs[i]; diff --git a/src/mongo/db/database.cpp b/src/mongo/db/database.cpp index 1cfa49afca6..1d151241830 100644 --- a/src/mongo/db/database.cpp +++ b/src/mongo/db/database.cpp @@ -347,7 +347,7 @@ namespace mongo { // we don't enforce the quota on "special" namespaces as that could lead to problems -- e.g. // rejecting an index insert after inserting the main record. !NamespaceString::special( ns ) && - NamespaceString( ns ).db != "local"; + nsToDatabaseSubstring( ns ) != "local"; } MongoDataFile* Database::suitableFile( const char *ns, int sizeNeeded, bool preallocate, bool enforceQuota ) { diff --git a/src/mongo/db/instance.cpp b/src/mongo/db/instance.cpp index a92748d6a1d..a4ce2ce8c9c 100644 --- a/src/mongo/db/instance.cpp +++ b/src/mongo/db/instance.cpp @@ -515,7 +515,7 @@ namespace mongo { oplogCheckCloseDatabase( database ); // oplog caches some things, dirty its caches - if( BackgroundOperation::inProgForDb(db.c_str()) ) { + if( BackgroundOperation::inProgForDb(db) ) { log() << "warning: bg op in prog during close db? " << db << endl; } @@ -808,7 +808,7 @@ namespace mongo { const char *ns = d.getns(); op.debug().ns = ns; - bool isIndexWrite = NamespaceString(ns).coll == "system.indexes"; + bool isIndexWrite = nsToCollectionSubstring(ns) == "system.indexes"; // Auth checking for index writes happens further down in this function. if (!isIndexWrite) { diff --git a/src/mongo/db/matcher/expression_where.cpp b/src/mongo/db/matcher/expression_where.cpp index c7010eeb4a2..6dab7b9a8b2 100644 --- a/src/mongo/db/matcher/expression_where.cpp +++ b/src/mongo/db/matcher/expression_where.cpp @@ -67,7 +67,7 @@ namespace mongo { _userScope = scope.getOwned(); NamespaceString nswrapper( _ns ); - _scope = globalScriptEngine->getPooledScope( nswrapper.db.c_str(), "where" ); + _scope = globalScriptEngine->getPooledScope( nswrapper.db().toString(), "where" ); _func = _scope->createFunction( _code.c_str() ); if ( !_func ) diff --git a/src/mongo/db/namespace_details.cpp b/src/mongo/db/namespace_details.cpp index 4767f79954d..a787570b07f 100644 --- a/src/mongo/db/namespace_details.cpp +++ b/src/mongo/db/namespace_details.cpp @@ -850,7 +850,7 @@ namespace mongo { void NamespaceDetails::syncUserFlags( const string& ns ) { Lock::assertWriteLocked( ns ); - string system_namespaces = NamespaceString( ns ).db + ".system.namespaces"; + string system_namespaces = nsToDatabaseSubstring(ns).toString() + ".system.namespaces"; BSONObj oldEntry; verify( Helpers::findOne( system_namespaces , BSON( "name" << ns ) , oldEntry ) ); diff --git a/src/mongo/db/namespacestring-inl.h b/src/mongo/db/namespacestring-inl.h new file mode 100644 index 00000000000..9ee99c0caef --- /dev/null +++ b/src/mongo/db/namespacestring-inl.h @@ -0,0 +1,123 @@ +// namespacestring-inl.h + + +/** +* Copyright (C) 2013 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/>. +*/ + +namespace mongo { + + inline StringData NamespaceString::db() const { + return _dotIndex == string::npos ? + StringData() : + StringData( _ns.c_str(), _dotIndex ); + } + + inline StringData NamespaceString::coll() const { + return _dotIndex == string::npos ? + StringData() : + StringData( _ns.c_str() + _dotIndex + 1, _ns.size() - 1 - _dotIndex ); + } + + inline bool NamespaceString::normal(const StringData& ns) { + if ( ns.find( '$' ) == string::npos ) + return true; + return oplog(ns); + } + + inline bool NamespaceString::oplog(const StringData& ns) { + return ns == "local.oplog.rs" || ns == "local.oplog.$main"; + } + + inline bool NamespaceString::special(const StringData& ns) { + return !normal(ns) || ns.find( ".system." ) != string::npos; + } + + inline bool NamespaceString::validDBName( const StringData& dbin ) { + // XXX + string db = dbin.toString(); + + if ( db.size() == 0 || db.size() > 64 ) + return false; +#ifdef _WIN32 + // We prohibit all FAT32-disallowed characters on Windows + size_t good = strcspn( db.c_str() , "/\\. \"*<>:|?" ); +#else + // For non-Windows platforms we are much more lenient + size_t good = strcspn( db.c_str() , "/\\. \"" ); +#endif + return good == db.size(); + } + + inline bool NamespaceString::validCollectionName(const StringData& ns){ + size_t idx = ns.find( '.' ); + if ( idx == string::npos ) + return false; + + if ( idx + 1 >= ns.size() ) + return false; + + return normal( ns ); + } + + inline NamespaceString::NamespaceString( const StringData& nsIn ) { + _ns = nsIn.toString(); // copy to our buffer + _dotIndex = _ns.find( '.' ); + } + + inline int nsDBHash( const string& ns ) { + int hash = 7; + for ( size_t i = 0; i < ns.size(); i++ ) { + if ( ns[i] == '.' ) + break; + hash += 11 * ( ns[i] ); + hash *= 3; + } + return hash; + } + + inline bool nsDBEquals( const string& a, const string& b ) { + for ( size_t i = 0; i < a.size(); i++ ) { + + if ( a[i] == '.' ) { + // b has to either be done or a '.' + + if ( b.size() == i ) + return true; + + if ( b[i] == '.' ) + return true; + + return false; + } + + // a is another character + if ( b.size() == i ) + return false; + + if ( b[i] != a[i] ) + return false; + } + + // a is done + // make sure b is done + if ( b.size() == a.size() || + b[a.size()] == '.' ) + return true; + + return false; + } + +} diff --git a/src/mongo/db/namespacestring.h b/src/mongo/db/namespacestring.h index d108bbaac72..6d2501068a8 100644 --- a/src/mongo/db/namespacestring.h +++ b/src/mongo/db/namespacestring.h @@ -20,6 +20,7 @@ #include <string> +#include "mongo/base/string_data.h" #include "mongo/util/assert_util.h" namespace mongo { @@ -36,86 +37,60 @@ namespace mongo { */ class NamespaceString { public: - string db; - string coll; // note collection names can have periods in them for organizing purposes (e.g. "system.indexes") + NamespaceString( const StringData& ns ); - NamespaceString( const char * ns ) { init(ns); } - NamespaceString( const string& ns ) { init(ns.c_str()); } + StringData db() const; + StringData coll() const; - string ns() const { return db + '.' + coll; } + const string& ns() const { return _ns; } - bool isSystem() const { return strncmp(coll.c_str(), "system.", 7) == 0; } - bool isCommand() const { return coll == "$cmd"; } + operator string() const { return _ns; } + string toString() const { return _ns; } + + size_t size() const { return _ns.size(); } + + bool isSystem() const { return coll().startsWith( "system." ); } + bool isCommand() const { return coll() == "$cmd"; } /** * @return true if the namespace is valid. Special namespaces for internal use are considered as valid. */ - bool isValid() const { - return validDBName( db ) && !coll.empty(); - } - - operator string() const { return ns(); } + bool isValid() const { return validDBName( db() ) && !coll().empty(); } - bool operator==( const string& nsIn ) const { return nsIn == ns(); } - bool operator==( const char* nsIn ) const { return (string)nsIn == ns(); } - bool operator==( const NamespaceString& nsIn ) const { return nsIn.db == db && nsIn.coll == coll; } + bool operator==( const string& nsIn ) const { return nsIn == _ns; } + bool operator==( const NamespaceString& nsIn ) const { return nsIn._ns == _ns; } - bool operator!=( const string& nsIn ) const { return nsIn != ns(); } - bool operator!=( const char* nsIn ) const { return (string)nsIn != ns(); } - bool operator!=( const NamespaceString& nsIn ) const { return nsIn.db != db || nsIn.coll != coll; } - - size_t size() const { return ns().size(); } - - string toString() const { return ns(); } + bool operator!=( const string& nsIn ) const { return nsIn != _ns; } + bool operator!=( const NamespaceString& nsIn ) const { return nsIn._ns != _ns; } /** * @return true if ns is 'normal'. A "$" is used for namespaces holding index data, * which do not contain BSON objects in their records. ("oplog.$main" is the exception) */ - static bool normal(const char* ns) { - const char *p = strchr(ns, '$'); - if( p == 0 ) - return true; - return oplog(ns); - } + static bool normal(const StringData& ns); /** * @return true if the ns is an oplog one, otherwise false. */ - static bool oplog(const char* ns) { - return StringData(ns) == StringData("local.oplog.rs") || StringData(ns) == StringData("local.oplog.$main"); - } + static bool oplog(const StringData& ns); - static bool special(const char *ns) { - return !normal(ns) || strstr(ns, ".system."); - } + static bool special(const StringData& ns); /** * samples: - * good: - * foo + * 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; -#ifdef _WIN32 - // We prohibit all FAT32-disallowed characters on Windows - size_t good = strcspn( db.c_str() , "/\\. \"*<>:|?" ); -#else - // For non-Windows platforms we are much more lenient - size_t good = strcspn( db.c_str() , "/\\. \"" ); -#endif - return good == db.size(); - } + static bool validDBName( const StringData& dbin ); /** * samples: @@ -124,23 +99,18 @@ namespace mongo { * bad: * foo. * - * @param dbcoll - a possible collection name of the form db.coll + * @param ns - a full namesapce (a.b) * @return if db.coll is an allowed collection name */ - static bool validCollectionName(const char* dbcoll){ - const char *c = strchr( dbcoll, '.' ); - return (c != NULL) && (c[1] != '\0') && normal(dbcoll); - } + static bool validCollectionName(const StringData& ns); private: - void init(const char *ns) { - const char *p = strchr(ns, '.'); - if( p == 0 ) return; - db = string(ns, p - ns); - coll = p + 1; - } + + string _ns; + size_t _dotIndex; }; + // "database.a.b.c" -> "database" inline StringData nsToDatabaseSubstring( const StringData& ns ) { size_t i = ns.find( '.' ); @@ -163,59 +133,28 @@ namespace mongo { return nsToDatabaseSubstring( ns ).toString(); } + // "database.a.b.c" -> "database" + inline StringData nsToCollectionSubstring( const StringData& ns ) { + size_t i = ns.find( '.' ); + massert(16886, "nsToCollectionSubstring: no .", i != string::npos ); + return ns.substr( i + 1 ); + } + + /** * NamespaceDBHash and NamespaceDBEquals allow you to do something like * unordered_map<string,int,NamespaceDBHash,NamespaceDBEquals> * and use the full namespace for the string * but comparisons are done only on the db piece */ - + /** * this can change, do not store on disk */ - inline int nsDBHash( const string& ns ) { - int hash = 7; - for ( size_t i = 0; i < ns.size(); i++ ) { - if ( ns[i] == '.' ) - break; - hash += 11 * ( ns[i] ); - hash *= 3; - } - return hash; - } + int nsDBHash( const string& ns ); + + bool nsDBEquals( const string& a, const string& b ); - inline bool nsDBEquals( const string& a, const string& b ) { - for ( size_t i = 0; i < a.size(); i++ ) { - - if ( a[i] == '.' ) { - // b has to either be done or a '.' - - if ( b.size() == i ) - return true; - - if ( b[i] == '.' ) - return true; - - return false; - } - - // a is another character - if ( b.size() == i ) - return false; - - if ( b[i] != a[i] ) - return false; - } - - // a is done - // make sure b is done - if ( b.size() == a.size() || - b[a.size()] == '.' ) - return true; - - return false; - } - struct NamespaceDBHash { int operator()( const string& ns ) const { return nsDBHash( ns ); @@ -227,5 +166,8 @@ namespace mongo { return nsDBEquals( a, b ); } }; - + } + + +#include "mongo/db/namespacestring-inl.h" diff --git a/src/mongo/db/namespacestring_test.cpp b/src/mongo/db/namespacestring_test.cpp index 817cf797e64..0a70af169a3 100644 --- a/src/mongo/db/namespacestring_test.cpp +++ b/src/mongo/db/namespacestring_test.cpp @@ -21,18 +21,52 @@ namespace mongo { + TEST( NamespaceStringTest, Normal ) { + ASSERT( NamespaceString::normal( "a" ) ); + ASSERT( NamespaceString::normal( "a.b" ) ); + ASSERT( NamespaceString::normal( "a.b.c" ) ); + + ASSERT( !NamespaceString::normal( "a.b.$c" ) ); + ASSERT( !NamespaceString::normal( "a.b.$.c" ) ); + + ASSERT( NamespaceString::normal( "local.oplog.$main" ) ); + ASSERT( NamespaceString::normal( "local.oplog.rs" ) ); + } + + TEST( NamespaceStringTest, Oplog ) { + ASSERT( !NamespaceString::oplog( "a" ) ); + ASSERT( !NamespaceString::oplog( "a.b" ) ); + + ASSERT( NamespaceString::oplog( "local.oplog.rs" ) ); + ASSERT( !NamespaceString::oplog( "local.oplog.foo" ) ); + ASSERT( NamespaceString::oplog( "local.oplog.$main" ) ); + ASSERT( !NamespaceString::oplog( "local.oplog.$foo" ) ); + } + + TEST( NamespaceStringTest, Special ) { + ASSERT( NamespaceString::special( "a.$.b" ) ); + ASSERT( NamespaceString::special( "a.system.foo" ) ); + ASSERT( !NamespaceString::special( "a.foo" ) ); + } TEST( NamespaceStringTest, DatabaseValidNames ) { ASSERT( NamespaceString::validDBName( "foo" ) ); ASSERT( !NamespaceString::validDBName( "foo/bar" ) ); ASSERT( !NamespaceString::validDBName( "foo bar" ) ); ASSERT( !NamespaceString::validDBName( "foo.bar" ) ); - + ASSERT( NamespaceString::normal( "asdads" ) ); ASSERT( !NamespaceString::normal( "asda$ds" ) ); ASSERT( NamespaceString::normal( "local.oplog.$main" ) ); } + TEST( NamespaceStringTest, CollectionValidNames ) { + ASSERT( NamespaceString::validCollectionName( "a.b" ) ); + ASSERT( NamespaceString::validCollectionName( "a.b" ) ); + ASSERT( !NamespaceString::validCollectionName( "a." ) ); + ASSERT( NamespaceString::validCollectionName( "a.b." ) ); // TODO: should this change? + } + TEST( NamespaceStringTest, DBHash ) { ASSERT_EQUALS( nsDBHash( "foo" ), nsDBHash( "foo" ) ); ASSERT_EQUALS( nsDBHash( "foo" ), nsDBHash( "foo.a" ) ); @@ -41,7 +75,7 @@ namespace mongo { ASSERT_EQUALS( nsDBHash( "" ), nsDBHash( "" ) ); ASSERT_EQUALS( nsDBHash( "" ), nsDBHash( ".a" ) ); ASSERT_EQUALS( nsDBHash( "" ), nsDBHash( "." ) ); - + ASSERT_NOT_EQUALS( nsDBHash( "foo" ), nsDBHash( "food" ) ); ASSERT_NOT_EQUALS( nsDBHash( "foo." ), nsDBHash( "food" ) ); ASSERT_NOT_EQUALS( nsDBHash( "foo.d" ), nsDBHash( "food" ) ); @@ -98,5 +132,30 @@ namespace mongo { } + + TEST( NamespaceStringTest, NamespaceStringParse1 ) { + NamespaceString ns( "a.b" ); + ASSERT_EQUALS( (string)"a", ns.db() ); + ASSERT_EQUALS( (string)"b", ns.coll() ); + } + + TEST( NamespaceStringTest, NamespaceStringParse2 ) { + NamespaceString ns( "a.b.c" ); + ASSERT_EQUALS( (string)"a", ns.db() ); + ASSERT_EQUALS( (string)"b.c", ns.coll() ); + } + + TEST( NamespaceStringTest, NamespaceStringParse3 ) { + NamespaceString ns( "abc" ); + ASSERT_EQUALS( (string)"", ns.db() ); + ASSERT_EQUALS( (string)"", ns.coll() ); + } + + TEST( NamespaceStringTest, NamespaceStringParse4 ) { + NamespaceString ns( "abc." ); + ASSERT_EQUALS( (string)"abc", ns.db() ); + ASSERT_EQUALS( (string)"", ns.coll() ); + } + } diff --git a/src/mongo/db/ops/update.cpp b/src/mongo/db/ops/update.cpp index ad3a90f6145..090cc8419ac 100644 --- a/src/mongo/db/ops/update.cpp +++ b/src/mongo/db/ops/update.cpp @@ -357,7 +357,7 @@ namespace mongo { // is of the form "db.collection". Therefore, the following expression must // always be valid. "system.users" updates must never be done in place, in // order to ensure that they are validated inside DataFileMgr::updateRecord(.). - bool isSystemUsersMod = (NamespaceString(ns).coll == "system.users"); + bool isSystemUsersMod = nsToCollectionSubstring(ns) == "system.users"; BSONObj newObj; if ( !mss->isUpdateIndexed() && mss->canApplyInPlace() && !isSystemUsersMod ) { diff --git a/src/mongo/db/pdfile.cpp b/src/mongo/db/pdfile.cpp index d8724037de9..a917ae7b91b 100644 --- a/src/mongo/db/pdfile.cpp +++ b/src/mongo/db/pdfile.cpp @@ -111,55 +111,6 @@ namespace mongo { } }; - SimpleMutex BackgroundOperation::m("bg"); - map<string, unsigned> BackgroundOperation::dbsInProg; - set<string> BackgroundOperation::nsInProg; - - bool BackgroundOperation::inProgForDb(const char *db) { - SimpleMutex::scoped_lock lk(m); - return dbsInProg[db] != 0; - } - - bool BackgroundOperation::inProgForNs(const char *ns) { - SimpleMutex::scoped_lock lk(m); - return nsInProg.count(ns) != 0; - } - - void BackgroundOperation::assertNoBgOpInProgForDb(const char *db) { - uassert(12586, "cannot perform operation: a background operation is currently running for this database", - !inProgForDb(db)); - } - - void BackgroundOperation::assertNoBgOpInProgForNs(const char *ns) { - uassert(12587, "cannot perform operation: a background operation is currently running for this collection", - !inProgForNs(ns)); - } - - BackgroundOperation::BackgroundOperation(const char *ns) : _ns(ns) { - SimpleMutex::scoped_lock lk(m); - dbsInProg[_ns.db]++; - nsInProg.insert(_ns.ns()); - } - - BackgroundOperation::~BackgroundOperation() { - SimpleMutex::scoped_lock lk(m); - dbsInProg[_ns.db]--; - nsInProg.erase(_ns.ns()); - } - - void BackgroundOperation::dump(stringstream& ss) { - SimpleMutex::scoped_lock lk(m); - if( nsInProg.size() ) { - ss << "\n<b>Background Jobs in Progress</b>\n"; - for( set<string>::iterator i = nsInProg.begin(); i != nsInProg.end(); i++ ) - ss << " " << *i << '\n'; - } - for( map<string,unsigned>::iterator i = dbsInProg.begin(); i != dbsInProg.end(); i++ ) { - if( i->second ) - ss << "database " << i->first << ": " << i->second << '\n'; - } - } - /* ----------------------------------------- */ #ifdef _WIN32 string dbpath = "\\data\\db\\"; @@ -190,7 +141,7 @@ namespace mongo { static void _ensureSystemIndexes(const char* ns) { NamespaceString nsstring(ns); - if (StringData(nsstring.coll).substr(0, 7) == "system.") { + if ( nsstring.coll().startsWith( "system." ) ) { authindex::createSystemIndexes(nsstring); } } @@ -990,9 +941,9 @@ namespace mongo { BackgroundOperation::assertNoBgOpInProgForNs(nsToDrop.c_str()); NamespaceString s(nsToDrop); - verify( s.db == cc().database()->name() ); + verify( s.db() == cc().database()->name() ); if( s.isSystem() ) { - if( s.coll == "system.profile" ) { + if( s.coll() == "system.profile" ) { uassert( 10087, "turn off profiling before dropping system.profile collection", cc().database()->getProfilingLevel() == 0 ); @@ -1082,7 +1033,7 @@ namespace mongo { { d->incrementStats( -1 * todelete->netLength(), -1 ); - if (NamespaceString(ns).coll == "system.indexes") { + if ( nsToCollectionSubstring(ns) == "system.indexes") { /* temp: if in system.indexes, don't reuse, and zero out: we want to be careful until validated more, as IndexDetails has pointers to this disk location. so an incorrectly done remove would cause @@ -1168,9 +1119,8 @@ namespace mongo { } NamespaceString nsstring(ns); - if (nsstring.coll == "system.users") { - uassertStatusOK(getGlobalAuthorizationManager()->checkValidPrivilegeDocument( - nsstring.db, objNew)); + if (nsstring.coll() == "system.users") { + uassertStatusOK(getGlobalAuthorizationManager()->checkValidPrivilegeDocument(nsstring.db(), objNew)); } uassert( 13596 , str::stream() << "cannot change _id of a document old:" << objOld << " new:" << objNew, @@ -1404,7 +1354,7 @@ namespace mongo { uassert( 10095 , "attempt to insert in reserved database name 'system'", sys != ns); if ( strstr(ns, ".system.") ) { // later:check for dba-type permissions here if have that at some point separate - if (NamespaceString(ns).coll == "system.indexes") + if (nsToCollectionSubstring(ns) == "system.indexes") wouldAddIndex = true; else if ( legalClientSystemNS( ns , true ) ) { if ( obuf && strstr( ns , ".system.users" ) ) { @@ -1449,7 +1399,7 @@ namespace mongo { bool mayInterrupt) { uassert(13143, "can't create index on system.indexes", - NamespaceString(tabletoidxns).coll != "system.indexes"); + nsToCollectionSubstring(tabletoidxns) != "system.indexes"); BSONObj info = loc.obj(); std::string idxName = info["name"].valuestr(); @@ -2051,7 +2001,7 @@ namespace mongo { string name = *i; LOG(2) << "DatabaseHolder::closeAll path:" << path << " name:" << name << endl; Client::Context ctx( name , path ); - if( !force && BackgroundOperation::inProgForDb(name.c_str()) ) { + if( !force && BackgroundOperation::inProgForDb(name) ) { log() << "WARNING: can't close database " << name << " because a bg job is in progress - try killOp command" << endl; nNotClosed++; } diff --git a/src/mongo/db/repl/rs_rollback.cpp b/src/mongo/db/repl/rs_rollback.cpp index 5453492b9e1..5e86e4f404b 100644 --- a/src/mongo/db/repl/rs_rollback.cpp +++ b/src/mongo/db/repl/rs_rollback.cpp @@ -144,19 +144,19 @@ namespace mongo { /* Create collection operation { ts: ..., h: ..., op: "c", ns: "foo.$cmd", o: { create: "abc", ... } } */ - string ns = s.db + '.' + o["create"].String(); // -> foo.abc + string ns = s.db().toString() + '.' + o["create"].String(); // -> foo.abc h.toDrop.insert(ns); return; } else if( cmdname == "drop" ) { - string ns = s.db + '.' + first.valuestr(); + string ns = s.db().toString() + '.' + first.valuestr(); h.collectionsToResync.insert(ns); return; } else if( cmdname == "dropIndexes" || cmdname == "deleteIndexes" ) { /* TODO: this is bad. we simply full resync the collection here, which could be very slow. */ log() << "replSet info rollback of dropIndexes is slow in this version of mongod" << rsLog; - string ns = s.db + '.' + first.valuestr(); + string ns = s.db().toString() + '.' + first.valuestr(); h.collectionsToResync.insert(ns); return; } diff --git a/src/mongo/db/repl/rs_sync.cpp b/src/mongo/db/repl/rs_sync.cpp index 65d81994847..65d0d232451 100644 --- a/src/mongo/db/repl/rs_sync.cpp +++ b/src/mongo/db/repl/rs_sync.cpp @@ -502,7 +502,8 @@ namespace replset { if ((op["op"].valuestrsafe()[0] == 'c') || // Index builds are acheived through the use of an insert op, not a command op. // The following line is the same as what the insert code uses to detect an index build. - (NamespaceString(op["ns"].valuestrsafe()).coll == "system.indexes")) { + nsToCollectionSubstring( op["ns"].valuestrsafe() ) == "system.indexes" ) { + if (ops->empty()) { // apply commands one-at-a-time ops->push_back(op); diff --git a/src/mongo/s/commands_public.cpp b/src/mongo/s/commands_public.cpp index 723fccd42de..c1f70e09e01 100644 --- a/src/mongo/s/commands_public.cpp +++ b/src/mongo/s/commands_public.cpp @@ -1867,7 +1867,7 @@ namespace mongo { // this function with any other collection name. uassert(16618, "Illegal attempt to run a command against a namespace other than $cmd.", - NamespaceString(ns).coll == "$cmd"); + nsToCollectionSubstring(ns) == "$cmd"); BSONElement e = jsobj.firstElement(); std::string commandName = e.fieldName(); diff --git a/src/mongo/s/config_upgrade_helpers.cpp b/src/mongo/s/config_upgrade_helpers.cpp index 3cdc40cef33..e586f5a1a06 100644 --- a/src/mongo/s/config_upgrade_helpers.cpp +++ b/src/mongo/s/config_upgrade_helpers.cpp @@ -70,7 +70,7 @@ namespace mongo { return Status::OK(); } - string _extractHashFor(const BSONObj& dbHashResult, const string& collName) { + string _extractHashFor(const BSONObj& dbHashResult, const StringData& collName) { if (dbHashResult["collections"].type() != Object || dbHashResult["collections"].Obj()[collName].type() != String) @@ -123,7 +123,7 @@ namespace mongo { try { ScopedDbConnection conn(configLoc, 30); - resultOk = conn->runCommand(nssA.db, BSON("dbHash" << true), result); + resultOk = conn->runCommand(nssA.db().toString(), BSON("dbHash" << true), result); conn.done(); } catch (const DBException& e) { @@ -132,11 +132,11 @@ namespace mongo { if (!resultOk) { return Status(ErrorCodes::UnknownError, - stream() << "could not run dbHash command on " << nssA.db << " db" + stream() << "could not run dbHash command on " << nssA.db() << " db" << causedBy(result.toString())); } - string hashResultA = _extractHashFor(result, nssA.coll); + string hashResultA = _extractHashFor(result, nssA.coll()); if (hashResultA == "") { return Status(ErrorCodes::RemoteValidationError, @@ -152,7 +152,7 @@ namespace mongo { try { ScopedDbConnection conn(configLoc, 30); - resultOk = conn->runCommand(nssB.db, BSON("dbHash" << true), result); + resultOk = conn->runCommand(nssB.db().toString(), BSON("dbHash" << true), result); conn.done(); } catch (const DBException& e) { @@ -161,11 +161,11 @@ namespace mongo { if (!resultOk) { return Status(ErrorCodes::UnknownError, - stream() << "could not run dbHash command on " << nssB.db << " db" + stream() << "could not run dbHash command on " << nssB.db() << " db" << causedBy(result.toString())); } - string hashResultB = _extractHashFor(result, nssB.coll); + string hashResultB = _extractHashFor(result, nssB.coll()); if (hashResultB == "") { return Status(ErrorCodes::RemoteValidationError, @@ -219,7 +219,7 @@ namespace mongo { verify(fromNSS.isValid()); // TODO: EnsureIndex at some point, if it becomes easier? - string indexesNS = fromNSS.db + ".system.indexes"; + string indexesNS = fromNSS.db().toString() + ".system.indexes"; scoped_ptr<DBClientCursor> cursor(_safeCursor(conn->query(indexesNS, BSON("ns" << fromNS)))); @@ -231,7 +231,7 @@ namespace mongo { newIndexDesc.append("ns", toNS); newIndexDesc.appendElementsUnique(next); - conn->insert(toNSS.db + ".system.indexes", newIndexDesc.done()); + conn->insert(toNSS.db().toString() + ".system.indexes", newIndexDesc.done()); _checkGLE(conn); } } @@ -304,8 +304,8 @@ namespace mongo { // Verify indices haven't changed Status indexStatus = checkIdsTheSame(configLoc, - fromNSS.db + ".system.indexes", - toNSS.db + ".system.indexes"); + fromNSS.db().toString() + ".system.indexes", + toNSS.db().toString() + ".system.indexes"); if (!indexStatus.isOK()) { return indexStatus; diff --git a/src/mongo/s/d_migrate.cpp b/src/mongo/s/d_migrate.cpp index cc3ac9939c0..ef97bf08fd6 100644 --- a/src/mongo/s/d_migrate.cpp +++ b/src/mongo/s/d_migrate.cpp @@ -1463,7 +1463,7 @@ namespace mongo { Client::WriteContext ctx( ns ); // Only copy if ns doesn't already exist if ( ! nsdetails( ns ) ) { - string system_namespaces = NamespaceString( ns ).db + ".system.namespaces"; + string system_namespaces = nsToDatabase(ns) + ".system.namespaces"; BSONObj entry = conn->findOne( system_namespaces, BSON( "name" << ns ) ); if ( entry["options"].isABSONObj() ) { string errmsg; diff --git a/src/mongo/s/grid.cpp b/src/mongo/s/grid.cpp index 62ea11f48b2..e3b0e7a6f94 100644 --- a/src/mongo/s/grid.cpp +++ b/src/mongo/s/grid.cpp @@ -38,12 +38,8 @@ namespace mongo { MONGO_FP_DECLARE(neverBalance); - DBConfigPtr Grid::getDBConfig( string database , bool create , const string& shardNameHint ) { - { - string::size_type i = database.find( "." ); - if ( i != string::npos ) - database = database.substr( 0 , i ); - } + DBConfigPtr Grid::getDBConfig( const StringData& ns , bool create , const string& shardNameHint ) { + string database = nsToDatabase( ns ); if ( database == "config" ) return configServerPtr; diff --git a/src/mongo/s/grid.h b/src/mongo/s/grid.h index 6d524fc9326..cfdb9f3647b 100644 --- a/src/mongo/s/grid.h +++ b/src/mongo/s/grid.h @@ -39,7 +39,7 @@ namespace mongo { * gets the config the db. * will return an empty DBConfig if not in db already */ - DBConfigPtr getDBConfig( string ns , bool create=true , const string& shardNameHint="" ); + DBConfigPtr getDBConfig( const StringData& ns , bool create=true , const string& shardNameHint="" ); /** * removes db entry. diff --git a/src/mongo/s/strategy_shard.cpp b/src/mongo/s/strategy_shard.cpp index 08c3511574c..e414b58c3c2 100644 --- a/src/mongo/s/strategy_shard.cpp +++ b/src/mongo/s/strategy_shard.cpp @@ -44,7 +44,7 @@ namespace mongo { class ShardStrategy : public Strategy { bool _isSystemIndexes( const char* ns ) { - return NamespaceString(ns).coll == "system.indexes"; + return nsToCollectionSubstring(ns) == "system.indexes"; } virtual void queryOp( Request& r ) { diff --git a/src/mongo/tools/dump.cpp b/src/mongo/tools/dump.cpp index 250dceee6ea..7db4ef776c6 100644 --- a/src/mongo/tools/dump.cpp +++ b/src/mongo/tools/dump.cpp @@ -218,7 +218,7 @@ public: continue; } - if (NamespaceString(name).coll == "system.indexes") { + if (nsToCollectionSubstring(name) == "system.indexes") { // Create system.indexes.bson for compatibility with pre 2.2 mongorestore const string filename = name.substr( db.size() + 1 ); writeCollectionFile( name.c_str() , outdir / ( filename + ".bson" ) ); diff --git a/src/mongo/tools/restore.cpp b/src/mongo/tools/restore.cpp index 4b98f8e7108..fead4ce1c57 100644 --- a/src/mongo/tools/restore.cpp +++ b/src/mongo/tools/restore.cpp @@ -360,8 +360,8 @@ public: } _curns = ns.c_str(); - _curdb = NamespaceString(_curns).db; - _curcoll = NamespaceString(_curns).coll; + _curdb = nsToDatabase(_curns); + _curcoll = nsToCollectionSubstring(_curns).toString(); // If drop is not used, warn if the collection exists. if (!_drop) { @@ -425,16 +425,19 @@ public: } } } - else if (NamespaceString(_curns).coll == "system.indexes") { + else if (nsToCollectionSubstring(_curns) == "system.indexes") { createIndex(obj, true); } - else if (_drop && endsWith(_curns.c_str(), ".system.users") && _users.count(obj["user"].String())) { + else if (_drop && + nsToCollectionSubstring(_curns) == ".system.users" && + _users.count(obj["user"].String())) { // Since system collections can't be dropped, we have to manually // replace the contents of the system.users collection BSONObj userMatch = BSON("user" << obj["user"].String()); conn().update(_curns, Query(userMatch), obj); _users.erase(obj["user"].String()); - } else { + } + else { conn().insert( _curns , obj ); // wait for insert to propagate to "w" nodes (doesn't warn if w used without replset) @@ -546,7 +549,7 @@ private: BSONElement e = i.next(); if (strcmp(e.fieldName(), "ns") == 0) { NamespaceString n(e.String()); - string s = _curdb + "." + (keepCollName ? n.coll : _curcoll); + string s = _curdb + "." + (keepCollName ? n.coll().toString() : _curcoll); bo.append("ns", s); } else if (strcmp(e.fieldName(), "v") != 0 || _keepIndexVersion) { // Remove index version number |