bool compact(const string& ns, string &errmsg, bool validate, BSONObjBuilder& result, double pf, int pb) { massert( 14028, "bad ns", NamespaceString::normal(ns.c_str()) ); massert( 14027, "can't compact a system namespace", !str::contains(ns, ".system.") ); // items in system.indexes cannot be moved there are pointers to those disklocs in NamespaceDetails bool ok; { writelock lk; BackgroundOperation::assertNoBgOpInProgForNs(ns.c_str()); Client::Context ctx(ns); NamespaceDetails *d = nsdetails(ns.c_str()); massert( 13660, str::stream() << "namespace " << ns << " does not exist", d ); massert( 13661, "cannot compact capped collection", !d->capped ); log() << "compact " << ns << " begin" << endl; if( pf != 0 || pb != 0 ) { log() << "paddingFactor:" << pf << " paddingBytes:" << pb << endl; } try { ok = _compact(ns.c_str(), d, errmsg, validate, result, pf, pb); } catch(...) { log() << "compact " << ns << " end (with error)" << endl; throw; } log() << "compact " << ns << " end" << endl; } return ok; }
Command& CommandCache::alloc( NodePtr node, LocalNodePtr localNode, const uint64_t size ) { EQ_TS_THREAD( _thread ); const Cache which = (size > Packet::minSize) ? CACHE_BIG : CACHE_SMALL; _compact( which ); Command& command = _newCommand( which ); command._alloc( node, localNode, size ); return command; }
Command& CommandCache::alloc( NodePtr node, LocalNodePtr localNode, const uint64_t size ) { EQ_TS_THREAD( _thread ); EQASSERTINFO( size < EQ_BIT48, "Out-of-sync network stream: packet size " << size << "?" ); const Cache which = (size > Packet::minSize) ? CACHE_BIG : CACHE_SMALL; _compact( which ); Command& command = _newCommand( which ); command.alloc_( node, localNode, size ); return command; }
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; } string ns = db + '.' + coll; if ( ! NamespaceString::normal(ns.c_str()) ) { errmsg = "bad namespace name"; return false; } // parameter validation to avoid triggering assertions in compact() if ( str::contains(ns, ".system.") ) { errmsg = "can't compact a system namespace"; return false; } { Lock::DBWrite lk(ns); Client::Context ctx(ns); NamespaceDetails *d = nsdetails(ns); if( ! d ) { errmsg = "namespace does not exist"; return false; } if ( d->isCapped() ) { errmsg = "cannot compact a capped collection"; return false; } } double pf = 1.0; int pb = 0; // preservePadding trumps all other compact methods bool preservePadding = false; // useDefaultPadding is used to track whether or not a padding requirement was passed in // if it wasn't than UsePowerOf2Sizes will be maintained when compacting bool useDefaultPadding = true; if (cmdObj.hasElement("preservePadding")) { preservePadding = cmdObj["preservePadding"].trueValue(); useDefaultPadding = false; } if( cmdObj.hasElement("paddingFactor") ) { if (preservePadding == true) { errmsg = "preservePadding is incompatible with paddingFactor"; return false; } useDefaultPadding = false; pf = cmdObj["paddingFactor"].Number(); verify( pf >= 1.0 && pf <= 4.0 ); } if( cmdObj.hasElement("paddingBytes") ) { if (preservePadding == true) { errmsg = "preservePadding is incompatible with paddingBytes"; return false; } useDefaultPadding = false; pb = (int) cmdObj["paddingBytes"].Number(); verify( pb >= 0 && pb <= 1024 * 1024 ); } bool validate = !cmdObj.hasElement("validate") || cmdObj["validate"].trueValue(); // default is true at the moment massert( 14028, "bad ns", NamespaceString::normal(ns.c_str()) ); massert( 14027, "can't compact a system namespace", !str::contains(ns, ".system.") ); // items in system.indexes cannot be moved there are pointers to those disklocs in NamespaceDetails bool ok; { Lock::DBWrite lk(ns); BackgroundOperation::assertNoBgOpInProgForNs(ns.c_str()); Client::Context ctx(ns); NamespaceDetails *d = nsdetails(ns); massert( 13660, str::stream() << "namespace " << ns << " does not exist", d ); massert( 13661, "cannot compact capped collection", !d->isCapped() ); log() << "compact " << ns << " begin" << endl; std::vector<BSONObj> indexesInProg = stopIndexBuilds(db, cmdObj); if( pf != 0 || pb != 0 ) { log() << "paddingFactor:" << pf << " paddingBytes:" << pb << endl; } try { ok = _compact(ns.c_str(), d, errmsg, validate, result, pf, pb, useDefaultPadding, preservePadding); } catch(...) { log() << "compact " << ns << " end (with error)" << endl; throw; } log() << "compact " << ns << " end" << endl; IndexBuilder::restoreIndexes(indexesInProg); } return ok; }