// Open the dictionary. Creates it if necessary. bool IndexDetails::open(const bool may_create) { const string dname = indexNamespace(); if (may_create) { addNewNamespaceToCatalog(dname); } TOKULOG(1) << "Opening IndexDetails " << dname << endl; try { _db.reset(new storage::Dictionary(dname, _info, *_descriptor, may_create, _info["background"].trueValue())); return true; } catch (storage::Dictionary::NeedsCreate) { if (cc().upgradingSystemUsers() && isSystemUsersCollection(parentNS()) && keyPattern() == oldSystemUsersKeyPattern) { // We're upgrading the system.users collection, and we are missing the old index. // That's ok, we'll signal the caller about this by returning a NULL pointer from // IndexDetails::make. See #673 return false; } // Unlike for NamespaceIndex, this dictionary must exist on disk if we think it should // exist. This error only gets thrown if may_create is false, which happens when we're // trying to open a collection for which we have serialized info. Therefore, this is a // fatal non-user error. msgasserted(16988, mongoutils::str::stream() << "dictionary " << dname << " should exist, but we got ENOENT"); } }
Status Database::_renameSingleNamespace( const StringData& fromNS, const StringData& toNS, bool stayTemp ) { // TODO: make it so we dont't need to do this string fromNSString = fromNS.toString(); string toNSString = toNS.toString(); // some sanity checking NamespaceDetails* fromDetails = _namespaceIndex.details( fromNS ); if ( !fromDetails ) return Status( ErrorCodes::BadValue, "from namespace doesn't exist" ); if ( _namespaceIndex.details( toNS ) ) return Status( ErrorCodes::BadValue, "to namespace already exists" ); // remove anything cached { scoped_lock lk( _collectionLock ); _collections.erase( fromNSString ); _collections.erase( toNSString ); } ClientCursor::invalidate( fromNSString.c_str() ); ClientCursor::invalidate( toNSString.c_str() ); NamespaceDetailsTransient::eraseCollection( fromNSString ); // XXX NamespaceDetailsTransient::eraseCollection( toNSString ); // XXX // at this point, we haven't done anything destructive yet // ---- // actually start moving // ---- // this could throw, but if it does we're ok _namespaceIndex.add_ns( toNS, fromDetails ); NamespaceDetails* toDetails = _namespaceIndex.details( toNS ); try { toDetails->copyingFrom(toNSString.c_str(), fromDetails); // fixes extraOffset } catch( DBException& ) { // could end up here if .ns is full - if so try to clean up / roll back a little _namespaceIndex.kill_ns(toNSString.c_str()); throw; } // at this point, code .ns stuff moved _namespaceIndex.kill_ns( fromNSString.c_str() ); fromDetails = NULL; // fix system.namespaces BSONObj newSpec; { BSONObj oldSpec; if ( !Helpers::findOne( _namespacesName, BSON( "name" << fromNS ), oldSpec ) ) return Status( ErrorCodes::InternalError, "can't find system.namespaces entry" ); BSONObjBuilder b; BSONObjIterator i( oldSpec.getObjectField( "options" ) ); while( i.more() ) { BSONElement e = i.next(); if ( strcmp( e.fieldName(), "create" ) != 0 ) { if (stayTemp || (strcmp(e.fieldName(), "temp") != 0)) b.append( e ); } else { b << "create" << toNS; } } newSpec = b.obj(); } addNewNamespaceToCatalog( toNSString.c_str(), newSpec.isEmpty() ? 0 : &newSpec ); deleteObjects( _namespacesName.c_str(), BSON( "name" << fromNS ), false, false, true ); return Status::OK(); }