TEST( NamespaceStringTest, nsToDatabase1 ) { ASSERT_EQUALS( "foo", nsToDatabaseSubstring( "foo.bar" ) ); ASSERT_EQUALS( "foo", nsToDatabaseSubstring( "foo" ) ); ASSERT_EQUALS( "foo", nsToDatabase( "foo.bar" ) ); ASSERT_EQUALS( "foo", nsToDatabase( "foo" ) ); ASSERT_EQUALS( "foo", nsToDatabase( string("foo.bar") ) ); ASSERT_EQUALS( "foo", nsToDatabase( string("foo") ) ); }
void DBClientCursor::_assembleInit(Message& toSend) { // If we haven't gotten a cursorId yet, we need to issue a new query or command. if (!cursorId) { // HACK: // Unfortunately, this code is used by the shell to run commands, // so we need to allow the shell to send invalid options so that we can // test that the server rejects them. Thus, to allow generating commands with // invalid options, we validate them here, and fall back to generating an OP_QUERY // through assembleQueryRequest if the options are invalid. bool hasValidNToReturnForCommand = (nToReturn == 1 || nToReturn == -1); bool hasValidFlagsForCommand = !(opts & mongo::QueryOption_Exhaust); if (_isCommand && hasValidNToReturnForCommand && hasValidFlagsForCommand) { toSend = assembleCommandRequest(_client, nsToDatabaseSubstring(ns), opts, query); return; } assembleQueryRequest(ns, query, nextBatchSize(), nToSkip, fieldsToReturn, opts, toSend); return; } // Assemble a legacy getMore request. BufBuilder b; b.appendNum(opts); b.appendStr(ns); b.appendNum(nToReturn); b.appendNum(cursorId); toSend.setData(dbGetMore, b.buf(), b.len()); }
void Lock::DBWrite::lockDB(const string& ns) { fassert( 16253, !ns.empty() ); Acquiring a(this, *_lockState); _locked_W=false; _locked_w=false; _weLocked=0; massert(16186, "can't get a DBWrite while having a read lock", !_lockState->hasAnyReadLock()); if (_lockState->isW()) return; StringData db = nsToDatabaseSubstring( ns ); Nestable nested = n(db); if( nested == admin ) { // we can't nestedly lock both admin and local as implemented. so lock_W. qlk.lock_W(_lockState); _locked_W = true; return; } if( !nested ) lockOther(db); lockTop(); if( nested ) lockNestable(nested); }
void Lock::DBWrite::lockDB(const string& ns, const string &context) { fassert( 16253, !ns.empty() ); LockState& ls = lockState(); Acquiring a(this,ls); _locked_W=false; _locked_w=false; _weLocked=0; massert( 16186 , "can't get a DBWrite while having a read lock" , ! ls.hasAnyReadLock() ); if( ls.isW() ) return; if (DB_LEVEL_LOCKING_ENABLED) { StringData db = nsToDatabaseSubstring( ns ); Nestable nested = n(db); if( nested == admin ) { // we can't nestedly lock both admin and local as implemented. so lock_W. qlk.lock_W(); _locked_W = true; return; } if( !nested ) lockOther(db, context); lockTop(ls); if( nested ) lockNestable(nested, context); } else { qlk.lock_W(); _locked_w = true; } }
CollectionTemp* Database::getCollectionTemp( const StringData& ns ) { StringData dbName = nsToDatabaseSubstring( ns ); verify( dbName == _name); scoped_lock lk( _collectionLock ); string myns = ns.toString(); CollectionMap::const_iterator it = _collections.find( myns ); if ( it != _collections.end() ) { if ( it->second ) { //DEV { NamespaceDetails* details = _namespaceIndex.details( ns ); verify( details == it->second->_details ); //} return it->second; } } NamespaceDetails* details = _namespaceIndex.details( ns ); if ( !details ) { return NULL; } CollectionTemp* c = new CollectionTemp( ns, details, this ); _collections[myns] = c; return c; }
Status createIndexFromSpec(OperationContext* txn, const StringData& ns, const BSONObj& spec) { AutoGetOrCreateDb autoDb(txn, nsToDatabaseSubstring(ns), MODE_X); Collection* coll; { WriteUnitOfWork wunit(txn); coll = autoDb.getDb()->getOrCreateCollection(txn, ns); invariant(coll); wunit.commit(); } MultiIndexBlock indexer(txn, coll); Status status = indexer.init(spec); if (status == ErrorCodes::IndexAlreadyExists) { return Status::OK(); } if (!status.isOK()) { return status; } status = indexer.insertAllDocumentsInCollection(); if (!status.isOK()) { return status; } WriteUnitOfWork wunit(txn); indexer.commit(); wunit.commit(); return Status::OK(); }
void insertObjects(const char *ns, const vector<BSONObj> &objs, bool keepGoing, uint64_t flags, bool logop ) { StringData _ns(ns); if (NamespaceString::isSystem(_ns)) { massert(16748, "need transaction to run insertObjects", cc().txnStackSize() > 0); uassert(10095, "attempt to insert in reserved database name 'system'", nsToDatabaseSubstring(_ns) != "system"); massert(16750, "attempted to insert multiple objects into a system namspace at once", objs.size() == 1); // Trying to insert into a system collection. Fancy side-effects go here: if (nsToCollectionSubstring(ns) == "system.indexes") { BSONObj obj = stripDropDups(objs[0]); NamespaceDetails *d = getAndMaybeCreateNS(obj["ns"].Stringdata(), logop); bool ok = d->ensureIndex(obj); if (!ok) { // Already had that index return; } // Now we have to actually insert that document into system.indexes, we may have // modified it with stripDropDups. vector<BSONObj> newObjs; newObjs.push_back(obj); _insertObjects(ns, newObjs, keepGoing, flags, logop); return; } else if (!legalClientSystemNS(ns, true)) { uasserted(16459, str::stream() << "attempt to insert in system namespace '" << ns << "'"); } } _insertObjects(ns, objs, keepGoing, flags, logop); }
void NamespaceUUIDCache::evictNamespacesInDatabase(StringData dbname) { for (auto&& it = _cache.begin(); it != _cache.end();) { auto entry = it++; if (entry->first.empty() || nsToDatabaseSubstring(entry->first) == dbname) _cache.erase(entry); } }
bool LockerImpl::isAtLeastReadLocked(const StringData& ns) const { if (threadState() == 'R' || threadState() == 'W') { return true; // global } if (!isLocked()) { return false; } const StringData db = nsToDatabaseSubstring(ns); const newlm::ResourceId resIdDb(newlm::RESOURCE_DATABASE, db); // S on the database means we don't need to check further down the hierarchy if (isLockHeldForMode(resIdDb, newlm::MODE_S)) { return true; } if (!isLockHeldForMode(resIdDb, newlm::MODE_IS)) { return false; } if (nsIsFull(ns)) { const newlm::ResourceId resIdColl(newlm::RESOURCE_DATABASE, ns); return isLockHeldForMode(resIdColl, newlm::MODE_IS); } // We're just asking about a database, so IS on the db is enough. return true; }
AutoGetCollectionForRead::AutoGetCollectionForRead(OperationContext* txn, const std::string& ns) : _txn(txn), _transaction(txn, MODE_IS), _db(_txn, nsToDatabaseSubstring(ns), MODE_IS), _collLock(_txn->lockState(), ns, MODE_IS), _coll(NULL) { _init(ns, nsToCollectionSubstring(ns)); }
CountStageTest() : _txn(), _scopedXact(&_txn, MODE_IX), _dbLock(_txn.lockState(), nsToDatabaseSubstring(ns()), MODE_X), _ctx(&_txn, ns()), _coll(NULL) { }
string Command::parseNsFullyQualified(const string& dbname, const BSONObj& cmdObj) const { string s = cmdObj.firstElement().valuestr(); StringData dbstr = nsToDatabaseSubstring(s); // these are for security, do not remove: massert(15962, "need to specify namespace" , !dbstr.empty() ); massert(15966, str::stream() << "dbname not ok in Command::parseNsFullyQualified: " << dbname , dbname == dbstr || dbname == "admin" ); return s; }
void CollectionMap::drop() { Lock::assertWriteLocked(_database); init(); if (!allocated()) { return; } string errmsg; BSONObjBuilder result; // This implementation is inefficient and slightly messy, but it was easy. // Feel free to improve it as necessary: // - The getCursor call will grab a table lock on .system.namespaces. // - We'll look at the entire system.namespaces collection just for one database. // - Code is duplicated to handle dropping system system collections in stages. vector<string> sysIndexesEntries; const string systemNamespacesNs = getSisterNS(_database, "system.namespaces"); Collection *sysCl = getCollection(systemNamespacesNs); for (shared_ptr<Cursor> c(Cursor::make(sysCl)); c->ok(); c->advance()) { const BSONObj nsObj = c->current(); const StringData ns = nsObj["name"].Stringdata(); if (nsToDatabaseSubstring(ns) != _database) { // Not part of this database, skip. continue; } if (nsToCollectionSubstring(ns) == "system.indexes") { // Save .system.indexes collection for last, because drop() deletes from it. sysIndexesEntries.push_back(ns.toString()); } else { Collection *cl = getCollection(ns); if (cl != NULL) { cl->drop(errmsg, result, true); } } } if (sysCl != NULL) { // The .system.namespaces collection does not include itself. sysCl->drop(errmsg, result, true); } // Now drop the system.indexes entries. for (vector<string>::const_iterator it = sysIndexesEntries.begin(); it != sysIndexesEntries.end(); it++) { // Need to close any existing handle before drop. Collection *cl = getCollection(*it); if (cl != NULL) { cl->drop(errmsg, result, true); } } // Everything that was open should have been closed due to drop. verify(_collections.empty()); shared_ptr<storage::Dictionary> metadb = _metadb; _metadb.reset(); const int r = metadb->close(); if (r != 0) { storage::handle_ydb_error(r); } storage::db_remove(_metadname); }
void run() { ScopedTransaction transaction(&_txn, MODE_IX); Lock::DBLock lk(_txn.lockState(), nsToDatabaseSubstring(ns()), MODE_X); Client::Context ctx(&_txn, ns()); Database* db = ctx.db(); Collection* coll = db->getCollection(&_txn, ns()); if (!coll) { WriteUnitOfWork wuow(&_txn); coll = db->createCollection(&_txn, ns()); wuow.commit(); } WorkingSet ws; // Add an object to the DB. insert(BSON("foo" << 5)); set<DiskLoc> locs; getLocs(&locs, coll); ASSERT_EQUALS(size_t(1), locs.size()); // Create a mock stage that returns the WSM. auto_ptr<MockStage> mockStage(new MockStage(&ws)); // Mock data. { WorkingSetMember mockMember; mockMember.state = WorkingSetMember::LOC_AND_IDX; mockMember.loc = *locs.begin(); // State is loc and index, shouldn't be able to get the foo data inside. BSONElement elt; ASSERT_FALSE(mockMember.getFieldDotted("foo", &elt)); mockStage->pushBack(mockMember); } // Make the filter. BSONObj filterObj = BSON("foo" << 6); StatusWithMatchExpression swme = MatchExpressionParser::parse(filterObj); verify(swme.isOK()); auto_ptr<MatchExpression> filterExpr(swme.getValue()); // Matcher requires that foo==6 but we only have data with foo==5. auto_ptr<FetchStage> fetchStage( new FetchStage(&_txn, &ws, mockStage.release(), filterExpr.get(), coll)); // First call should return a fetch request as it's not in memory. WorkingSetID id = WorkingSet::INVALID_ID; PlanStage::StageState state; // Normally we'd return the object but we have a filter that prevents it. state = fetchStage->work(&id); ASSERT_EQUALS(PlanStage::NEED_TIME, state); // No more data to fetch, so, EOF. state = fetchStage->work(&id); ASSERT_EQUALS(PlanStage::IS_EOF, state); }
Collection* Database::getCollection( StringData ns ) const { invariant( _name == nsToDatabaseSubstring( ns ) ); CollectionMap::const_iterator it = _collections.find( ns ); if ( it != _collections.end() && it->second ) { return it->second; } return NULL; }
void Database::_clearCollectionCache_inlock( const StringData& fullns ) { verify( _name == nsToDatabaseSubstring( fullns ) ); CollectionMap::iterator it = _collections.find( fullns.toString() ); if ( it == _collections.end() ) return; delete it->second; _collections.erase( it ); }
bool fileIndexExceedsQuota( const char *ns, int fileIndex ) { return cmdLine.quota && fileIndex >= cmdLine.quotaFiles && // 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 ) && nsToDatabaseSubstring( ns ) != "local"; }
~IndexIteratorTests() { OperationContextImpl txn; Lock::DBLock lk(txn.lockState(), nsToDatabaseSubstring(_ns), MODE_X); Client::Context ctx(&txn, _ns); WriteUnitOfWork wuow(&txn); _db->dropCollection(&txn, _ns); wuow.commit(); }
bool LockerImpl<IsForMMAPV1>::isWriteLocked(const StringData& ns) const { if (isWriteLocked()) { return true; } const StringData db = nsToDatabaseSubstring(ns); const ResourceId resIdNs(RESOURCE_DATABASE, db); return isLockHeldForMode(resIdNs, MODE_X); }
bool LockerImpl::isAtLeastReadLocked(const StringData& ns) const { if (threadState() == 'R' || threadState() == 'W') return true; // global if (!isLocked()) return false; const StringData db = nsToDatabaseSubstring(ns); const newlm::ResourceId resIdNs(newlm::RESOURCE_DATABASE, db); return isLockHeldForMode(resIdNs, newlm::MODE_S); }
IndexIteratorTests() { OperationContextImpl txn; Lock::DBLock lk(txn.lockState(), nsToDatabaseSubstring(_ns), MODE_X); Client::Context ctx(&txn, _ns); WriteUnitOfWork wuow(&txn); _db = ctx.db(); _coll = _db->createCollection(&txn, _ns); _catalog = _coll->getIndexCatalog(); wuow.commit(); }
void Database::_clearCollectionCache(OperationContext* txn, StringData fullns ) { verify( _name == nsToDatabaseSubstring( fullns ) ); CollectionMap::const_iterator it = _collections.find( fullns.toString() ); if ( it == _collections.end() ) return; // Takes ownership of the collection txn->recoveryUnit()->registerChange(new RemoveCollectionChange(this, it->second)); it->second->_cursorManager.invalidateAll(false); _collections.erase( it ); }
Lock::CollectionLock::CollectionLock(Locker* lockState, StringData ns, LockMode mode) : _id(RESOURCE_COLLECTION, ns), _lockState(lockState) { massert(28538, "need a non-empty collection name", nsIsFull(ns)); dassert(_lockState->isDbLockedForMode(nsToDatabaseSubstring(ns), isSharedLockMode(mode) ? MODE_IS : MODE_IX)); if (supportsDocLocking()) { _lockState->lock(_id, mode); } else { _lockState->lock(_id, isSharedLockMode(mode) ? MODE_S : MODE_X); } }
LegacyRequest::LegacyRequest(const Message* message) : _message(std::move(message)), _dbMessage(*message), _queryMessage(_dbMessage) { _database = nsToDatabaseSubstring(_queryMessage.ns); uassert(ErrorCodes::InvalidNamespace, str::stream() << "Invalid database name: '" << _database << "'", NamespaceString::validDBName(_database)); std::tie(_upconvertedCommandArgs, _upconvertedMetadata) = uassertStatusOK(rpc::upconvertRequestMetadata(std::move(_queryMessage.query), std::move(_queryMessage.queryOptions))); }
Lock::CollectionLock::CollectionLock(Locker* lockState, const StringData& ns, LockMode mode) : _id(RESOURCE_COLLECTION, ns), _lockState(lockState) { const bool isRead = (mode == MODE_S || mode == MODE_IS); massert(28538, "need a non-empty collection name", nsIsFull(ns)); dassert(_lockState->isDbLockedForMode(nsToDatabaseSubstring(ns), isRead ? MODE_IS : MODE_IX)); if (supportsDocLocking()) { _lockState->lock(_id, mode); } else if (enableCollectionLocking) { _lockState->lock(_id, isRead ? MODE_S : MODE_X); } }
Lock::CollectionLock::CollectionLock(Locker* lockState, StringData ns, LockMode mode, Date_t deadline) : _id(RESOURCE_COLLECTION, ns), _result(LOCK_INVALID), _lockState(lockState) { massert(28538, "need a non-empty collection name", nsIsFull(ns)); dassert(_lockState->isDbLockedForMode(nsToDatabaseSubstring(ns), isSharedLockMode(mode) ? MODE_IS : MODE_IX)); LockMode actualLockMode = mode; if (!supportsDocLocking()) { actualLockMode = isSharedLockMode(mode) ? MODE_S : MODE_X; } _result = _lockState->lock(_id, actualLockMode, deadline); invariant(_result == LOCK_OK || deadline != Date_t::max()); }
void OldClientContext::_finishInit() { _db = dbHolder().get(_txn, _ns); if (_db) { _justCreated = false; } else { invariant(_txn->lockState()->isDbLockedForMode(nsToDatabaseSubstring(_ns), MODE_X)); _db = dbHolder().openDb(_txn, _ns, &_justCreated); invariant(_db); } if (_doVersion) { _checkNotStale(); } stdx::lock_guard<Client> lk(*_txn->getClient()); CurOp::get(_txn)->enter_inlock(_ns.c_str(), _db->getProfilingLevel()); }
void Lock::DBRead::unlockDB() { if (supportsDocLocking()) { if (nsIsFull(_ns)) { const newlm::ResourceId resIdCollection(newlm::RESOURCE_COLLECTION, _ns); _lockState->unlock(resIdCollection); } } const StringData db = nsToDatabaseSubstring(_ns); const newlm::ResourceId resIdDb(newlm::RESOURCE_DATABASE, db); _lockState->unlock(resIdDb); // The last release reports time the lock was held if (_lockState->unlockGlobal()) { recordTime(); } }
void Lock::DBRead::lockDB(const string& ns) { fassert( 16254, !ns.empty() ); Acquiring a(this, *_lockState); _locked_r=false; _weLocked=0; if (_lockState->isRW()) return; StringData db = nsToDatabaseSubstring(ns); Nestable nested = n(db); if( !nested ) lockOther(db); lockTop(); if( nested ) lockNestable(nested); }
Lock::CollectionLock::CollectionLock(Locker* lockState, const StringData& ns, newlm::LockMode mode) : _id(newlm::RESOURCE_COLLECTION, ns), _lockState(lockState) { const bool isRead = (mode == newlm::MODE_S || mode == newlm::MODE_IS); dassert(!ns.empty()); dassert(nsIsFull(ns)); dassert(_lockState->isLockHeldForMode(newlm::ResourceId(newlm::RESOURCE_DATABASE, nsToDatabaseSubstring(ns)), isRead ? newlm::MODE_IS : newlm::MODE_IX)); if (supportsDocLocking()) { _lockState->lock(_id, mode); } else { _lockState->lock(_id, isRead ? newlm::MODE_S : newlm::MODE_X); } }