Beispiel #1
0
    virtual bool run(OperationContext* txn,
                     const string& db,
                     BSONObj& cmdObj,
                     int,
                     string& errmsg,
                     BSONObjBuilder& result) {
        const std::string nsToCompact = parseNsCollectionRequired(db, cmdObj);

        repl::ReplicationCoordinator* replCoord = repl::getGlobalReplicationCoordinator();
        if (replCoord->getMemberState().primary() && !cmdObj["force"].trueValue()) {
            errmsg =
                "will not run compact on an active replica set primary as this is a slow blocking "
                "operation. use force:true to force";
            return false;
        }

        NamespaceString nss(nsToCompact);
        if (!nss.isNormal()) {
            errmsg = "bad namespace name";
            return false;
        }

        if (nss.isSystem()) {
            // items in system.* cannot be moved as there might be pointers to them
            // i.e. system.indexes entries are pointed to from NamespaceDetails
            errmsg = "can't compact a system namespace";
            return false;
        }

        CompactOptions compactOptions;

        if (cmdObj["preservePadding"].trueValue()) {
            compactOptions.paddingMode = CompactOptions::PRESERVE;
            if (cmdObj.hasElement("paddingFactor") || cmdObj.hasElement("paddingBytes")) {
                errmsg = "cannot mix preservePadding and paddingFactor|paddingBytes";
                return false;
            }
        } else if (cmdObj.hasElement("paddingFactor") || cmdObj.hasElement("paddingBytes")) {
            compactOptions.paddingMode = CompactOptions::MANUAL;
            if (cmdObj.hasElement("paddingFactor")) {
                compactOptions.paddingFactor = cmdObj["paddingFactor"].Number();
                if (compactOptions.paddingFactor < 1 || compactOptions.paddingFactor > 4) {
                    errmsg = "invalid padding factor";
                    return false;
                }
            }
            if (cmdObj.hasElement("paddingBytes")) {
                compactOptions.paddingBytes = cmdObj["paddingBytes"].numberInt();
                if (compactOptions.paddingBytes < 0 ||
                    compactOptions.paddingBytes > (1024 * 1024)) {
                    errmsg = "invalid padding bytes";
                    return false;
                }
            }
        }

        if (cmdObj.hasElement("validate"))
            compactOptions.validateDocuments = cmdObj["validate"].trueValue();


        ScopedTransaction transaction(txn, MODE_IX);
        AutoGetDb autoDb(txn, db, MODE_X);
        Database* const collDB = autoDb.getDb();
        Collection* collection = collDB ? collDB->getCollection(nss) : NULL;

        // If db/collection does not exist, short circuit and return.
        if (!collDB || !collection) {
            errmsg = "namespace does not exist";
            return false;
        }

        OldClientContext ctx(txn, nss.ns());
        BackgroundOperation::assertNoBgOpInProgForNs(nss.ns());

        log() << "compact " << nss.ns() << " begin, options: " << compactOptions.toString();

        StatusWith<CompactStats> status = collection->compact(txn, &compactOptions);
        if (!status.isOK())
            return appendCommandStatus(result, status.getStatus());

        if (status.getValue().corruptDocuments > 0)
            result.append("invalidObjects", status.getValue().corruptDocuments);

        log() << "compact " << nss.ns() << " end";

        return true;
    }
Beispiel #2
0
        virtual bool run(const string& db, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
            string coll = cmdObj.firstElement().valuestr();
            if( coll.empty() || db.empty() ) {
                errmsg = "no collection name specified";
                return false;
            }

            if( isCurrentlyAReplSetPrimary() && !cmdObj["force"].trueValue() ) {
                errmsg = "will not run compact on an active replica set primary as this is a slow blocking operation. use force:true to force";
                return false;
            }

            NamespaceString ns(db,coll);
            if ( !ns.isNormal() ) {
                errmsg = "bad namespace name";
                return false;
            }

            if ( ns.isSystem() ) {
                // items in system.* cannot be moved as there might be pointers to them
                // i.e. system.indexes entries are pointed to from NamespaceDetails
                errmsg = "can't compact a system namespace";
                return false;
            }

            CompactOptions compactOptions;

            if ( cmdObj["preservePadding"].trueValue() ) {
                compactOptions.paddingMode = CompactOptions::PRESERVE;
                if ( cmdObj.hasElement( "paddingFactor" ) ||
                     cmdObj.hasElement( "paddingBytes" ) ) {
                    errmsg = "cannot mix preservePadding and paddingFactor|paddingBytes";
                    return false;
                }
            }
            else if ( cmdObj.hasElement( "paddingFactor" ) || cmdObj.hasElement( "paddingBytes" ) ) {
                compactOptions.paddingMode = CompactOptions::MANUAL;
                if ( cmdObj.hasElement("paddingFactor") ) {
                    compactOptions.paddingFactor = cmdObj["paddingFactor"].Number();
                    if ( compactOptions.paddingFactor < 1 ||
                         compactOptions.paddingFactor > 4 ){
                        errmsg = "invalid padding factor";
                        return false;
                    }
                }
                if ( cmdObj.hasElement("paddingBytes") ) {
                    compactOptions.paddingBytes = cmdObj["paddingBytes"].numberInt();
                    if ( compactOptions.paddingBytes < 0 ||
                         compactOptions.paddingBytes > ( 1024 * 1024 ) ) {
                        errmsg = "invalid padding bytes";
                        return false;
                    }
                }
            }

            if ( cmdObj.hasElement("validate") )
                compactOptions.validateDocuments = cmdObj["validate"].trueValue();


            Lock::DBWrite lk(ns.ns());
            BackgroundOperation::assertNoBgOpInProgForNs(ns.ns());
            Client::Context ctx(ns);

            Collection* collection = ctx.db()->getCollection(ns.ns());
            if( ! collection ) {
                errmsg = "namespace does not exist";
                return false;
            }

            if ( collection->isCapped() ) {
                errmsg = "cannot compact a capped collection";
                return false;
            }

            log() << "compact " << ns << " begin, options: " << compactOptions.toString();

            std::vector<BSONObj> indexesInProg = stopIndexBuilds(db, cmdObj);

            StatusWith<CompactStats> status = collection->compact( &compactOptions );
            if ( !status.isOK() )
                return appendCommandStatus( result, status.getStatus() );

            if ( status.getValue().corruptDocuments > 0 )
                result.append("invalidObjects", status.getValue().corruptDocuments );

            log() << "compact " << ns << " end";

            IndexBuilder::restoreIndexes(indexesInProg);

            return true;
        }