Status _findAllCollections(const ConnectionString& configLoc,
                               bool optionalEpochs,
                               OwnedPointerMap<string, CollectionType>* collections)
    {
        scoped_ptr<ScopedDbConnection> connPtr;

        try {
            connPtr.reset(ScopedDbConnection::getInternalScopedDbConnection(configLoc, 30));

            ScopedDbConnection& conn = *connPtr;
            scoped_ptr<DBClientCursor> cursor(_safeCursor(conn->query(CollectionType::ConfigNS,
                                                                      Query())));

            while (cursor->more()) {

                BSONObj collDoc = cursor->nextSafe();

                CollectionType* coll = new CollectionType();
                string errMsg;
                coll->parseBSON(collDoc, &errMsg);

                // Needed for the v3 to v4 upgrade
                bool epochNotSet = !coll->isEpochSet() || !coll->getEpoch().isSet();
                if (optionalEpochs && epochNotSet) {
                    // Set our epoch to something here, just to allow
                    coll->setEpoch(OID::gen());
                }

                if (errMsg != "" || !coll->isValid(&errMsg)) {
                    return Status(ErrorCodes::UnsupportedFormat,
                                  stream() << "invalid collection " << collDoc
                                           << " read from the config server" << causedBy(errMsg));
                }

                if (coll->isDroppedSet() && coll->getDropped()) {
                    continue;
                }

                if (optionalEpochs && epochNotSet) {
                    coll->setEpoch(OID());
                }

                collections->mutableMap().insert(make_pair(coll->getNS(), coll));
            }
        }
        catch (const DBException& e) {
            return e.toStatus();
        }

        connPtr->done();
        return Status::OK();
    }
Esempio n. 2
0
CollectionInfo::CollectionInfo(OperationContext* txn,
                               const CollectionType& coll,
                               repl::OpTime opTime)
    : _configOpTime(std::move(opTime)) {
    _dropped = coll.getDropped();

    // Do this *first* so we're invisible to everyone else
    std::unique_ptr<ChunkManager> manager(stdx::make_unique<ChunkManager>(coll));
    manager->loadExistingRanges(txn, nullptr);

    // Collections with no chunks are unsharded, no matter what the collections entry says. This
    // helps prevent errors when dropping in a different process.
    if (manager->numChunks() != 0) {
        useChunkManager(std::move(manager));
    } else {
        warning() << "no chunks found for collection " << manager->getns()
                  << ", assuming unsharded";
        unshard();
    }

    _dirty = false;
}
Esempio n. 3
0
    Status MetadataLoader::_initCollection(CatalogManager* catalogManager,
                                           const string& ns,
                                           const string& shard,
                                           CollectionMetadata* metadata) const {

        auto coll = catalogManager->getCollection(ns);
        if (!coll.isOK()) {
            return coll.getStatus();
        }

        CollectionType collInfo = coll.getValue();
        if (collInfo.getDropped()) {
            return Status(ErrorCodes::NamespaceNotFound,
                          str::stream() << "could not load metadata, collection "
                                        << ns << " was dropped");
        }

        metadata->_keyPattern = collInfo.getKeyPattern().toBSON();
        metadata->fillKeyPatternFields();
        metadata->_shardVersion = ChunkVersion(0, 0, collInfo.getEpoch());
        metadata->_collVersion = ChunkVersion(0, 0, collInfo.getEpoch());

        return Status::OK();
    }
Esempio n. 4
0
    Status MetadataLoader::initCollection( const string& ns,
                                           const string& shard,
                                           CollectionMetadata* metadata ) const
    {
        //
        // Bring collection entry from the config server.
        //

        BSONObj collDoc;
        {
            try {
                ScopedDbConnection conn( _configLoc.toString(), 30 );
                collDoc = conn->findOne( CollectionType::ConfigNS, QUERY(CollectionType::ns()<<ns));
                conn.done();
            }
            catch ( const DBException& e ) {
                string errMsg = str::stream() << "could not query collection metadata"
                                              << causedBy( e );

                // We deliberately do not return conn to the pool, since it was involved
                // with the error here.

                return Status( ErrorCodes::HostUnreachable, errMsg );
            }
        }

        string errMsg;
        if ( collDoc.isEmpty() ) {

            errMsg = str::stream() << "could not load metadata, collection " << ns << " not found";
            warning() << errMsg << endl;

            return Status( ErrorCodes::NamespaceNotFound, errMsg );
        }

        CollectionType collInfo;
        if ( !collInfo.parseBSON( collDoc, &errMsg ) || !collInfo.isValid( &errMsg ) ) {

            errMsg = str::stream() << "could not parse metadata for collection " << ns
                                   << causedBy( errMsg );
            warning() << errMsg << endl;

            return Status( ErrorCodes::FailedToParse, errMsg );
        }

        if ( collInfo.isDroppedSet() && collInfo.getDropped() ) {

            errMsg = str::stream() << "could not load metadata, collection " << ns
                                   << " was dropped";
            warning() << errMsg << endl;

            return Status( ErrorCodes::NamespaceNotFound, errMsg );
        }

        if ( collInfo.isKeyPatternSet() && !collInfo.getKeyPattern().isEmpty() ) {

            // Sharded collection, need to load chunks

            metadata->_keyPattern = collInfo.getKeyPattern();
            metadata->_shardVersion = ChunkVersion( 0, 0, collInfo.getEpoch() );
            metadata->_collVersion = ChunkVersion( 0, 0, collInfo.getEpoch() );

            return Status::OK();
        }
        else if ( collInfo.isPrimarySet() && collInfo.getPrimary() == shard ) {

            // A collection with a non-default primary

            // Empty primary field not allowed if set
            dassert( collInfo.getPrimary() != "" );

            metadata->_keyPattern = BSONObj();
            metadata->_shardVersion = ChunkVersion( 1, 0, collInfo.getEpoch() );
            metadata->_collVersion = metadata->_shardVersion;

            return Status::OK();
        }
        else {

            // A collection with a primary that doesn't match this shard or is empty, the primary
            // may have changed before we loaded.

            errMsg = // br
                    str::stream() << "collection " << ns << " does not have a shard key "
                                  << "and primary "
                                  << ( collInfo.isPrimarySet() ? collInfo.getPrimary() : "" )
                                  << " does not match this shard " << shard;

            warning() << errMsg << endl;

            metadata->_collVersion = ChunkVersion( 0, 0, OID() );

            return Status( ErrorCodes::RemoteChangeDetected, errMsg );
        }
    }