Пример #1
0
Collection* Database::createCollection(OperationContext* txn,
                                       StringData ns,
                                       const CollectionOptions& options,
                                       bool createIdIndex) {
    massert(17399, "collection already exists", getCollection(ns) == NULL);
    massertNamespaceNotIndex(ns, "createCollection");
    invariant(txn->lockState()->isDbLockedForMode(name(), MODE_X));

    if (serverGlobalParams.clusterRole == ClusterRole::ConfigServer &&
        !(ns.startsWith("config.") || ns.startsWith("local.") || ns.startsWith("admin."))) {
        uasserted(14037, "can't create user databases on a --configsvr instance");
    }

    if (NamespaceString::normal(ns)) {
        // This check only applies for actual collections, not indexes or other types of ns.
        uassert(17381,
                str::stream() << "fully qualified namespace " << ns << " is too long "
                              << "(max is "
                              << NamespaceString::MaxNsCollectionLen
                              << " bytes)",
                ns.size() <= NamespaceString::MaxNsCollectionLen);
    }

    NamespaceString nss(ns);
    uassert(17316, "cannot create a blank collection", nss.coll() > 0);
    uassert(28838, "cannot create a non-capped oplog collection", options.capped || !nss.isOplog());

    audit::logCreateCollection(&cc(), ns);

    txn->recoveryUnit()->registerChange(new AddCollectionChange(txn, this, ns));

    Status status = _dbEntry->createCollection(txn, ns, options, true /*allocateDefaultSpace*/);
    massertNoTraceStatusOK(status);


    Collection* collection = _getOrCreateCollectionInstance(txn, ns);
    invariant(collection);
    _collections[ns] = collection;

    if (createIdIndex) {
        if (collection->requiresIdIndex()) {
            if (options.autoIndexId == CollectionOptions::YES ||
                options.autoIndexId == CollectionOptions::DEFAULT) {
                IndexCatalog* ic = collection->getIndexCatalog();
                uassertStatusOK(ic->createIndexOnEmptyCollection(txn, ic->getDefaultIdIndexSpec()));
            }
        }

        if (nss.isSystem()) {
            authindex::createSystemIndexes(txn, collection);
        }
    }

    auto opObserver = getGlobalServiceContext()->getOpObserver();
    if (opObserver)
        opObserver->onCreateCollection(txn, nss, options);

    return collection;
}
Пример #2
0
    Collection* Database::createCollection( OperationContext* txn,
                                            const StringData& ns,
                                            const CollectionOptions& options,
                                            bool allocateDefaultSpace,
                                            bool createIdIndex ) {
        massert( 17399, "collection already exists", getCollection( txn, ns ) == NULL );
        massertNamespaceNotIndex( ns, "createCollection" );

        if ( serverGlobalParams.configsvr &&
             !( ns.startsWith( "config." ) ||
                ns.startsWith( "local." ) ||
                ns.startsWith( "admin." ) ) ) {
            uasserted(14037, "can't create user databases on a --configsvr instance");
        }

        if (NamespaceString::normal(ns)) {
            // This check only applies for actual collections, not indexes or other types of ns.
            uassert(17381, str::stream() << "fully qualified namespace " << ns << " is too long "
                                         << "(max is " << NamespaceString::MaxNsCollectionLen << " bytes)",
                    ns.size() <= NamespaceString::MaxNsCollectionLen);
        }

        NamespaceString nss( ns );
        uassert( 17316, "cannot create a blank collection", nss.coll() > 0 );

        audit::logCreateCollection( currentClient.get(), ns );

        txn->recoveryUnit()->registerChange( new AddCollectionChange(this, ns) );

        Status status = _dbEntry->createCollection(txn, ns,
                                                options, allocateDefaultSpace);
        massertStatusOK(status);

        Collection* collection = getCollection(txn, ns);
        invariant(collection);

        if ( createIdIndex ) {
            if ( collection->requiresIdIndex() ) {
                if ( options.autoIndexId == CollectionOptions::YES ||
                     options.autoIndexId == CollectionOptions::DEFAULT ) {
                    IndexCatalog* ic = collection->getIndexCatalog();
                    uassertStatusOK(
                        ic->createIndexOnEmptyCollection(txn, ic->getDefaultIdIndexSpec()));
                }
            }

            if ( nss.isSystem() ) {
                authindex::createSystemIndexes( txn, collection );
            }

        }

        return collection;
    }
Пример #3
0
Status Database::dropCollectionEvenIfSystem(OperationContext* opCtx,
                                            const NamespaceString& fullns) {
    invariant(opCtx->lockState()->isDbLockedForMode(name(), MODE_X));

    LOG(1) << "dropCollection: " << fullns;

    Collection* collection = getCollection(fullns);
    if (!collection) {
        return Status::OK();  // Post condition already met.
    }

    massertNamespaceNotIndex(fullns.toString(), "dropCollection");

    BackgroundOperation::assertNoBgOpInProgForNs(fullns);

    audit::logDropCollection(&cc(), fullns.toString());

    Status s = collection->getIndexCatalog()->dropAllIndexes(opCtx, true);
    if (!s.isOK()) {
        warning() << "could not drop collection, trying to drop indexes" << fullns << " because of "
                  << redact(s.toString());
        return s;
    }

    verify(collection->_details->getTotalIndexCount(opCtx) == 0);
    LOG(1) << "\t dropIndexes done";

    Top::get(opCtx->getClient()->getServiceContext()).collectionDropped(fullns.toString());

    // We want to destroy the Collection object before telling the StorageEngine to destroy the
    // RecordStore.
    _clearCollectionCache(opCtx, fullns.toString(), "collection dropped");

    s = _dbEntry->dropCollection(opCtx, fullns.toString());

    if (!s.isOK())
        return s;

    DEV {
        // check all index collection entries are gone
        string nstocheck = fullns.toString() + ".$";
        for (CollectionMap::const_iterator i = _collections.begin(); i != _collections.end(); ++i) {
            string temp = i->first;
            if (temp.find(nstocheck) != 0)
                continue;
            log() << "after drop, bad cache entries for: " << fullns << " have " << temp;
            verify(0);
        }
    }

    getGlobalServiceContext()->getOpObserver()->onDropCollection(opCtx, fullns);

    return Status::OK();
}
Пример #4
0
void Database::_checkCanCreateCollection(const NamespaceString& nss,
                                         const CollectionOptions& options) {
    massert(17399, "collection already exists", getCollection(nss.ns()) == nullptr);
    massertNamespaceNotIndex(nss.ns(), "createCollection");

    uassert(14037,
            "can't create user databases on a --configsvr instance",
            serverGlobalParams.clusterRole != ClusterRole::ConfigServer || nss.isOnInternalDb());

    // This check only applies for actual collections, not indexes or other types of ns.
    uassert(17381,
            str::stream() << "fully qualified namespace " << nss.ns() << " is too long "
                          << "(max is "
                          << NamespaceString::MaxNsCollectionLen
                          << " bytes)",
            !nss.isNormal() || nss.size() <= NamespaceString::MaxNsCollectionLen);

    uassert(17316, "cannot create a blank collection", nss.coll() > 0);
    uassert(28838, "cannot create a non-capped oplog collection", options.capped || !nss.isOplog());
}
Пример #5
0
    Status Database::dropCollection( OperationContext* txn, StringData fullns ) {
        invariant(txn->lockState()->isDbLockedForMode(name(), MODE_X));

        LOG(1) << "dropCollection: " << fullns << endl;
        massertNamespaceNotIndex( fullns, "dropCollection" );

        Collection* collection = getCollection( fullns );
        if ( !collection ) {
            // collection doesn't exist
            return Status::OK();
        }

        {
            NamespaceString s( fullns );
            verify( s.db() == _name );

            if( s.isSystem() ) {
                if( s.coll() == "system.profile" ) {
                    if ( _profile != 0 )
                        return Status( ErrorCodes::IllegalOperation,
                                       "turn off profiling before dropping system.profile collection" );
                }
                else {
                    return Status( ErrorCodes::IllegalOperation, "can't drop system ns" );
                }
            }
        }

        BackgroundOperation::assertNoBgOpInProgForNs( fullns );

        audit::logDropCollection( currentClient.get(), fullns );

        Status s = collection->getIndexCatalog()->dropAllIndexes(txn, true);
        if ( !s.isOK() ) {
            warning() << "could not drop collection, trying to drop indexes"
                      << fullns << " because of " << s.toString();
            return s;
        }

        verify( collection->_details->getTotalIndexCount( txn ) == 0 );
        LOG(1) << "\t dropIndexes done" << endl;

        Top::global.collectionDropped( fullns );

        s = _dbEntry->dropCollection( txn, fullns );

        _clearCollectionCache( txn, fullns ); // we want to do this always

        if ( !s.isOK() )
            return s;

        DEV {
            // check all index collection entries are gone
            string nstocheck = fullns.toString() + ".$";
            for ( CollectionMap::const_iterator i = _collections.begin();
                  i != _collections.end();
                  ++i ) {
                string temp = i->first;
                if ( temp.find( nstocheck ) != 0 )
                    continue;
                log() << "after drop, bad cache entries for: "
                      << fullns << " have " << temp;
                verify(0);
            }
        }

        return Status::OK();
    }
Пример #6
0
Status Database::dropCollection(OperationContext* txn, StringData fullns) {
    invariant(txn->lockState()->isDbLockedForMode(name(), MODE_X));

    LOG(1) << "dropCollection: " << fullns;
    massertNamespaceNotIndex(fullns, "dropCollection");

    Collection* collection = getCollection(fullns);
    if (!collection) {
        // collection doesn't exist
        return Status::OK();
    }

    NamespaceString nss(fullns);
    {
        verify(nss.db() == _name);

        if (nss.isSystem()) {
            if (nss.isSystemDotProfile()) {
                if (_profile != 0)
                    return Status(ErrorCodes::IllegalOperation,
                                  "turn off profiling before dropping system.profile collection");
            } else if (nss.isSystemDotViews()) {
                if (serverGlobalParams.featureCompatibilityVersion.load() !=
                    ServerGlobalParams::FeatureCompatibilityVersion_32) {
                    return Status(ErrorCodes::IllegalOperation,
                                  "The featureCompatibilityVersion must be 3.2 to drop the "
                                  "system.views collection. See "
                                  "http://dochub.mongodb.org/core/3.4-feature-compatibility.");
                }
            } else {
                return Status(ErrorCodes::IllegalOperation, "can't drop system ns");
            }
        }
    }

    BackgroundOperation::assertNoBgOpInProgForNs(fullns);

    audit::logDropCollection(&cc(), fullns);

    Status s = collection->getIndexCatalog()->dropAllIndexes(txn, true);
    if (!s.isOK()) {
        warning() << "could not drop collection, trying to drop indexes" << fullns << " because of "
                  << redact(s.toString());
        return s;
    }

    verify(collection->_details->getTotalIndexCount(txn) == 0);
    LOG(1) << "\t dropIndexes done";

    Top::get(txn->getClient()->getServiceContext()).collectionDropped(fullns);

    s = _dbEntry->dropCollection(txn, fullns);

    // we want to do this always
    _clearCollectionCache(txn, fullns, "collection dropped");

    if (!s.isOK())
        return s;

    DEV {
        // check all index collection entries are gone
        string nstocheck = fullns.toString() + ".$";
        for (CollectionMap::const_iterator i = _collections.begin(); i != _collections.end(); ++i) {
            string temp = i->first;
            if (temp.find(nstocheck) != 0)
                continue;
            log() << "after drop, bad cache entries for: " << fullns << " have " << temp;
            verify(0);
        }
    }

    auto opObserver = getGlobalServiceContext()->getOpObserver();
    if (opObserver)
        opObserver->onDropCollection(txn, nss);

    return Status::OK();
}
Пример #7
0
    Status Database::dropCollection( OperationContext* txn, const StringData& fullns ) {
        LOG(1) << "dropCollection: " << fullns << endl;
        massertNamespaceNotIndex( fullns, "dropCollection" );

        Collection* collection = getCollection( txn, fullns );
        if ( !collection ) {
            // collection doesn't exist
            return Status::OK();
        }

        {
            NamespaceString s( fullns );
            verify( s.db() == _name );

            if( s.isSystem() ) {
                if( s.coll() == "system.profile" ) {
                    if ( _profile != 0 )
                        return Status( ErrorCodes::IllegalOperation,
                                       "turn off profiling before dropping system.profile collection" );
                }
                else {
                    return Status( ErrorCodes::IllegalOperation, "can't drop system ns" );
                }
            }
        }

        BackgroundOperation::assertNoBgOpInProgForNs( fullns );

        audit::logDropCollection( currentClient.get(), fullns );

        try {
            Status s = collection->getIndexCatalog()->dropAllIndexes(txn, true);
            if ( !s.isOK() ) {
                warning() << "could not drop collection, trying to drop indexes"
                          << fullns << " because of " << s.toString();
                return s;
            }
        }
        catch( DBException& e ) {
            stringstream ss;
            ss << "drop: dropIndexes for collection failed. cause: " << e.what();
            ss << ". See http://dochub.mongodb.org/core/data-recovery";
            warning() << ss.str() << endl;
            return Status( ErrorCodes::InternalError, ss.str() );
        }

        verify( collection->_details->getTotalIndexCount() == 0 );
        LOG(1) << "\t dropIndexes done" << endl;

        Top::global.collectionDropped( fullns );

        Status s = _dbEntry->dropCollection( txn, fullns );

        _clearCollectionCache( fullns ); // we want to do this always

        if ( !s.isOK() )
            return s;

        DEV {
            // check all index collection entries are gone
            string nstocheck = fullns.toString() + ".$";
            scoped_lock lk( _collectionLock );
            for ( CollectionMap::const_iterator i = _collections.begin();
                  i != _collections.end();
                  ++i ) {
                string temp = i->first;
                if ( temp.find( nstocheck ) != 0 )
                    continue;
                log() << "after drop, bad cache entries for: "
                      << fullns << " have " << temp;
                verify(0);
            }
        }

        return Status::OK();
    }
Пример #8
0
Status Database::dropCollection(OperationContext* txn, StringData fullns) {
    invariant(txn->lockState()->isDbLockedForMode(name(), MODE_X));

    LOG(1) << "dropCollection: " << fullns;
    massertNamespaceNotIndex(fullns, "dropCollection");

    Collection* collection = getCollection(fullns);
    if (!collection) {
        // collection doesn't exist
        return Status::OK();
    }

    NamespaceString nss(fullns);
    {
        verify(nss.db() == _name);

        if (nss.isSystem()) {
            if (nss.isSystemDotProfile()) {
                if (_profile != 0)
                    return Status(ErrorCodes::IllegalOperation,
                                  "turn off profiling before dropping system.profile collection");
            } else if (!nss.isSystemDotViews()) {
                return Status(ErrorCodes::IllegalOperation, "can't drop system ns");
            }
        }
    }

    BackgroundOperation::assertNoBgOpInProgForNs(fullns);

    audit::logDropCollection(&cc(), fullns);

    Status s = collection->getIndexCatalog()->dropAllIndexes(txn, true);
    if (!s.isOK()) {
        warning() << "could not drop collection, trying to drop indexes" << fullns << " because of "
                  << redact(s.toString());
        return s;
    }

    verify(collection->_details->getTotalIndexCount(txn) == 0);
    LOG(1) << "\t dropIndexes done";

    Top::get(txn->getClient()->getServiceContext()).collectionDropped(fullns);

    // We want to destroy the Collection object before telling the StorageEngine to destroy the
    // RecordStore.
    _clearCollectionCache(txn, fullns, "collection dropped");

    s = _dbEntry->dropCollection(txn, fullns);

    if (!s.isOK())
        return s;

    DEV {
        // check all index collection entries are gone
        string nstocheck = fullns.toString() + ".$";
        for (CollectionMap::const_iterator i = _collections.begin(); i != _collections.end(); ++i) {
            string temp = i->first;
            if (temp.find(nstocheck) != 0)
                continue;
            log() << "after drop, bad cache entries for: " << fullns << " have " << temp;
            verify(0);
        }
    }

    getGlobalServiceContext()->getOpObserver()->onDropCollection(txn, nss);

    return Status::OK();
}