diff options
author | Eliot Horowitz <eliot@10gen.com> | 2014-04-11 14:59:12 -0400 |
---|---|---|
committer | Eliot Horowitz <eliot@10gen.com> | 2014-04-14 00:23:08 -0400 |
commit | 78acc64523fbc05cd9a8c2f8980bbe51a0d957e7 (patch) | |
tree | f4662301863279c55717c2cdc13548ac9074f7c6 /src/mongo | |
parent | 12a2947ebd5ebbf5282e2d5e2c673eeae840f578 (diff) | |
download | mongo-78acc64523fbc05cd9a8c2f8980bbe51a0d957e7.tar.gz |
SERVER-13084: move compact details down into RecordStore layer
Diffstat (limited to 'src/mongo')
-rw-r--r-- | src/mongo/db/exec/oplogstart.cpp | 4 | ||||
-rw-r--r-- | src/mongo/db/storage/record.h | 2 | ||||
-rw-r--r-- | src/mongo/db/structure/collection_compact.cpp | 251 | ||||
-rw-r--r-- | src/mongo/db/structure/record_store.h | 22 | ||||
-rw-r--r-- | src/mongo/db/structure/record_store_v1_capped.cpp | 6 | ||||
-rw-r--r-- | src/mongo/db/structure/record_store_v1_capped.h | 8 | ||||
-rw-r--r-- | src/mongo/db/structure/record_store_v1_simple.cpp | 204 | ||||
-rw-r--r-- | src/mongo/db/structure/record_store_v1_simple.h | 13 |
8 files changed, 304 insertions, 206 deletions
diff --git a/src/mongo/db/exec/oplogstart.cpp b/src/mongo/db/exec/oplogstart.cpp index 7554548dac8..f6754d42670 100644 --- a/src/mongo/db/exec/oplogstart.cpp +++ b/src/mongo/db/exec/oplogstart.cpp @@ -114,7 +114,7 @@ namespace mongo { // Set up our extent hopping state. Get the start of the extent that we were collection // scanning. - Extent* e = _curloc.rec()->myExtent(_curloc).ext(); + Extent* e = _curloc.rec()->myExtentLoc(_curloc).ext(); if (!_nsd->capLooped() || (e->myLoc != _nsd->capExtent())) { _curloc = e->firstRecord; } @@ -187,7 +187,7 @@ namespace mongo { // static DiskLoc OplogStart::prevExtentFirstLoc(const NamespaceDetails* nsd, const DiskLoc& rec ) { - Extent *e = rec.rec()->myExtent( rec ).ext(); + Extent *e = rec.rec()->myExtentLoc( rec ).ext(); if (nsd->capLooped() ) { while( true ) { // Advance e to preceding extent (looping to lastExtent if necessary). diff --git a/src/mongo/db/storage/record.h b/src/mongo/db/storage/record.h index 8ac063f9e7d..db6a703b0ae 100644 --- a/src/mongo/db/storage/record.h +++ b/src/mongo/db/storage/record.h @@ -75,7 +75,7 @@ namespace mongo { /* use this when a record is deleted. basically a union with next/prev fields */ DeletedRecord& asDeleted() { return *((DeletedRecord*) this); } - DiskLoc myExtent(const DiskLoc& myLoc) const { return DiskLoc(myLoc.a(), extentOfs() ); } + DiskLoc myExtentLoc(const DiskLoc& myLoc) const { return DiskLoc(myLoc.a(), extentOfs() ); } struct NP { int nextOfs; diff --git a/src/mongo/db/structure/collection_compact.cpp b/src/mongo/db/structure/collection_compact.cpp index a59e232cfb4..92a0002567f 100644 --- a/src/mongo/db/structure/collection_compact.cpp +++ b/src/mongo/db/structure/collection_compact.cpp @@ -47,198 +47,71 @@ namespace mongo { - class CompactDocWriter : public DocWriter { - public: - /** - * param allocationSize - allocation size WITH header - */ - CompactDocWriter( const BSONObj& doc, size_t allocationSize ) - : _doc( doc ), _allocationSize( allocationSize ) { - } - - virtual ~CompactDocWriter() {} - - virtual void writeDocument( char* buf ) const { - memcpy( buf, _doc.objdata(), _doc.objsize() ); - } - - virtual size_t documentSize() const { - return _allocationSize - Record::HeaderSize; - } - - virtual bool addPadding() const { - return false; - } - - private: - BSONObj _doc; - size_t _allocationSize; - }; - - void Collection::_compactExtent(const DiskLoc diskloc, int extentNumber, - MultiIndexBlock& indexesToInsertTo, - const CompactOptions* compactOptions, CompactStats* stats ) { - - log() << "compact begin extent #" << extentNumber - << " for namespace " << _ns << " " << diskloc; - - unsigned oldObjSize = 0; // we'll report what the old padding was - unsigned oldObjSizeWithPadding = 0; - - Extent *e = getExtentManager()->getExtent( diskloc ); - e->assertOk(); - verify( e->validates(diskloc) ); - - { - // the next/prev pointers within the extent might not be in order so we first - // page the whole thing in sequentially - log() << "compact paging in len=" << e->length/1000000.0 << "MB" << endl; - Timer t; - size_t length = e->length; - - touch_pages( reinterpret_cast<const char*>(e), length ); - int ms = t.millis(); - if( ms > 1000 ) - log() << "compact end paging in " << ms << "ms " - << e->length/1000000.0/t.seconds() << "MB/sec" << endl; + namespace { + BSONObj _compactAdjustIndexSpec( const BSONObj& oldSpec ) { + BSONObjBuilder b; + BSONObj::iterator i( oldSpec ); + while( i.more() ) { + BSONElement e = i.next(); + if ( str::equals( e.fieldName(), "v" ) ) { + // Drop any preexisting index version spec. The default index version will + // be used instead for the new index. + continue; + } + if ( str::equals( e.fieldName(), "background" ) ) { + // Create the new index in the foreground. + continue; + } + // Pass the element through to the new index spec. + b.append(e); + } + return b.obj(); } - { - log() << "compact copying records" << endl; - long long datasize = 0; - long long nrecords = 0; - DiskLoc L = e->firstRecord; - if( !L.isNull() ) { - while( 1 ) { - Record *recOld = _recordStore->recordFor(L); - BSONObj objOld = docFor( L ); - L = getExtentManager()->getNextRecordInExtent(L); - - if ( compactOptions->validateDocuments && !objOld.valid() ) { - // object is corrupt! - log() << "compact skipping corrupt document!"; - stats->corruptDocuments++; - } - else { - unsigned docSize = objOld.objsize(); - - nrecords++; - oldObjSize += docSize; - oldObjSizeWithPadding += recOld->netLength(); - - unsigned lenWHdr = docSize + Record::HeaderSize; - unsigned lenWPadding = lenWHdr; - - switch( compactOptions->paddingMode ) { - case CompactOptions::NONE: - if ( details()->isUserFlagSet(NamespaceDetails::Flag_UsePowerOf2Sizes) ) - lenWPadding = details()->quantizePowerOf2AllocationSpace(lenWPadding); - break; - case CompactOptions::PRESERVE: - // if we are preserving the padding, the record should not change size - lenWPadding = recOld->lengthWithHeaders(); - break; - case CompactOptions::MANUAL: - lenWPadding = compactOptions->computeRecordSize(lenWPadding); - if (lenWPadding < lenWHdr || lenWPadding > BSONObjMaxUserSize / 2 ) { - lenWPadding = lenWHdr; - } - break; - } - - CompactDocWriter writer( objOld, lenWPadding ); - StatusWith<DiskLoc> status = _recordStore->insertRecord( &writer, 0 ); - uassertStatusOK( status.getStatus() ); - datasize += _recordStore->recordFor( status.getValue() )->netLength(); - - InsertDeleteOptions options; - options.logIfError = false; - options.dupsAllowed = true; // in compact we should be doing no checking - - indexesToInsertTo.insert( objOld, status.getValue(), options ); - } - - if( L.isNull() ) { - // we just did the very last record from the old extent. it's still pointed to - // by the old extent ext, but that will be fixed below after this loop - break; - } + class MyCompactAdaptor : public RecordStoreCompactAdaptor { + public: + MyCompactAdaptor( Collection* collection, + MultiIndexBlock* indexBlock ) + : _collection( collection ), + _multiIndexBlock( indexBlock ) { + } - // remove the old records (orphan them) periodically so our commit block doesn't get too large - bool stopping = false; - RARELY stopping = *killCurrentOp.checkForInterruptNoAssert() != 0; - if( stopping || getDur().isCommitNeeded() ) { - e->firstRecord.writing() = L; - Record *r = _recordStore->recordFor(L); - getDur().writingInt(r->prevOfs()) = DiskLoc::NullOfs; - getDur().commitIfNeeded(); - killCurrentOp.checkForInterrupt(); - } - } - } // if !L.isNull() + virtual bool isDataValid( Record* rec ) { + return BSONObj( rec->data() ).valid(); + } - verify( details()->firstExtent() == diskloc ); - verify( details()->lastExtent() != diskloc ); - DiskLoc newFirst = e->xnext; - details()->firstExtent().writing() = newFirst; - getExtentManager()->getExtent( newFirst )->xprev.writing().Null(); - getDur().writing(e)->markEmpty(); - getExtentManager()->freeExtents( diskloc, diskloc ); + virtual size_t dataSize( Record* rec ) { + return BSONObj( rec->data() ).objsize(); + } - getDur().commitIfNeeded(); + virtual void inserted( Record* rec, const DiskLoc& newLocation ) { + InsertDeleteOptions options; + options.logIfError = false; + options.dupsAllowed = true; // in compact we should be doing no checking - { - double op = 1.0; - if( oldObjSize ) - op = static_cast<double>(oldObjSizeWithPadding)/oldObjSize; - log() << "compact finished extent #" << extentNumber << " containing " << nrecords - << " documents (" << datasize/1000000.0 << "MB)" - << " oldPadding: " << op << ' ' << static_cast<unsigned>(op*100.0)/100; + _multiIndexBlock->insert( BSONObj( rec->data() ), newLocation, options ); } - } - } + private: + Collection* _collection; + MultiIndexBlock* _multiIndexBlock; + }; - BSONObj _compactAdjustIndexSpec( const BSONObj& oldSpec ) { - BSONObjBuilder b; - BSONObj::iterator i( oldSpec ); - while( i.more() ) { - BSONElement e = i.next(); - if ( str::equals( e.fieldName(), "v" ) ) { - // Drop any preexisting index version spec. The default index version will - // be used instead for the new index. - continue; - } - if ( str::equals( e.fieldName(), "background" ) ) { - // Create the new index in the foreground. - continue; - } - // Pass the element through to the new index spec. - b.append(e); - } - return b.obj(); } + StatusWith<CompactStats> Collection::compact( const CompactOptions* compactOptions ) { - if ( isCapped() ) + if ( !_recordStore->compactSupported() ) return StatusWith<CompactStats>( ErrorCodes::BadValue, - "cannot compact capped collection" ); + str::stream() << + "cannot compact collection with record store: " << + _recordStore->name() ); if ( _indexCatalog.numIndexesInProgress() ) return StatusWith<CompactStats>( ErrorCodes::BadValue, "cannot compact when indexes in progress" ); - // this is a big job, so might as well make things tidy before we start just to be nice. - getDur().commitIfNeeded(); - - list<DiskLoc> extents; - for( DiskLoc extLocation = _details->firstExtent(); - !extLocation.isNull(); - extLocation = getExtentManager()->getExtent( extLocation )->xnext ) { - extents.push_back( extLocation ); - } - log() << "compact " << extents.size() << " extents"; // same data, but might perform a little different after compact? _infoCache.reset(); @@ -263,17 +136,6 @@ namespace mongo { } } - log() << "compact orphan deleted lists" << endl; - _details->orphanDeletedList(); - - // Start over from scratch with our extent sizing and growth - _details->setLastExtentSize( 0 ); - - // before dropping indexes, at least make sure we can allocate one extent! - // this will allocate an extent and add to free list - // if it cannot, it will throw an exception - increaseStorageSize( _details->lastExtentSize(), true ); - // note that the drop indexes call also invalidates all clientcursors for the namespace, // which is important and wanted here log() << "compact dropping indexes" << endl; @@ -282,7 +144,6 @@ namespace mongo { return StatusWith<CompactStats>( status ); } - getDur().commitIfNeeded(); killCurrentOp.checkForInterrupt(); CompactStats stats; @@ -292,27 +153,11 @@ namespace mongo { if ( !status.isOK() ) return StatusWith<CompactStats>( status ); - // reset data size and record counts to 0 for this namespace - // as we're about to tally them up again for each new extent - _details->setStats( 0, 0 ); - - ProgressMeterHolder pm(cc().curop()->setMessage("compact extent", - "Extent Compacting Progress", - extents.size())); - - int extentNumber = 0; - for( list<DiskLoc>::iterator i = extents.begin(); i != extents.end(); i++ ) { - _compactExtent(*i, extentNumber++, multiIndexBlock, compactOptions, &stats ); - pm.hit(); - } - - invariant( getExtentManager()->getExtent( _details->firstExtent() )->xprev.isNull() ); + MyCompactAdaptor adaptor( this, &multiIndexBlock ); - // indexes will do their own progress meter - pm.finished(); + _recordStore->compact( &adaptor, compactOptions, &stats ); log() << "starting index commits"; - status = multiIndexBlock.commit(); if ( !status.isOK() ) return StatusWith<CompactStats>( status ); diff --git a/src/mongo/db/structure/record_store.h b/src/mongo/db/structure/record_store.h index e1ba247c581..2712bbc80d5 100644 --- a/src/mongo/db/structure/record_store.h +++ b/src/mongo/db/structure/record_store.h @@ -37,11 +37,15 @@ namespace mongo { class Collection; + struct CompactOptions; + struct CompactStats; class DocWriter; class ExtentManager; class MAdvise; class NamespaceDetails; class Record; + + class RecordStoreCompactAdaptor; class RecordStore; /** @@ -84,6 +88,11 @@ namespace mongo { RecordStore( const StringData& ns ); virtual ~RecordStore(); + // META + + // name of the RecordStore implementation + virtual const char* name() const = 0; + // CRUD related virtual Record* recordFor( const DiskLoc& loc ) const = 0; @@ -110,6 +119,12 @@ namespace mongo { */ virtual Status truncate() = 0; + // does this RecordStore support the compact operation + virtual bool compactSupported() const = 0; + virtual Status compact( RecordStoreCompactAdaptor* adaptor, + const CompactOptions* options, + CompactStats* stats ) = 0; + // TODO: this makes me sad, it shouldn't be in the interface // do not use this anymore virtual void increaseStorageSize( int size, int quotaMax ) = 0; @@ -121,4 +136,11 @@ namespace mongo { std::string _ns; }; + class RecordStoreCompactAdaptor { + public: + virtual ~RecordStoreCompactAdaptor(){} + virtual bool isDataValid( Record* rec ) = 0; + virtual size_t dataSize( Record* rec ) = 0; + virtual void inserted( Record* rec, const DiskLoc& newLocation ) = 0; + }; } diff --git a/src/mongo/db/structure/record_store_v1_capped.cpp b/src/mongo/db/structure/record_store_v1_capped.cpp index 5cd9e9cf240..728c388315d 100644 --- a/src/mongo/db/structure/record_store_v1_capped.cpp +++ b/src/mongo/db/structure/record_store_v1_capped.cpp @@ -583,4 +583,10 @@ namespace mongo { return new CappedRecordStoreV1Iterator( this, start, tailable, dir ); } + Status CappedRecordStoreV1::compact( RecordStoreCompactAdaptor* adaptor, + const CompactOptions* options, + CompactStats* stats ) { + invariant(false); + } + } diff --git a/src/mongo/db/structure/record_store_v1_capped.h b/src/mongo/db/structure/record_store_v1_capped.h index 961ed2aa584..77dabd10a5d 100644 --- a/src/mongo/db/structure/record_store_v1_capped.h +++ b/src/mongo/db/structure/record_store_v1_capped.h @@ -49,6 +49,8 @@ namespace mongo { virtual ~CappedRecordStoreV1(); + const char* name() const { return "CappedRecordStoreV1"; } + virtual Status truncate(); /** @@ -63,6 +65,12 @@ namespace mongo { virtual RecordIterator* getIterator( const DiskLoc& start, bool tailable, const CollectionScanParams::Direction& dir) const; + virtual bool compactSupported() const { return false; } + + virtual Status compact( RecordStoreCompactAdaptor* adaptor, + const CompactOptions* options, + CompactStats* stats ); + protected: virtual StatusWith<DiskLoc> allocRecord( int lengthWithHeaders, int quotaMax ); diff --git a/src/mongo/db/structure/record_store_v1_simple.cpp b/src/mongo/db/structure/record_store_v1_simple.cpp index c094ef46b60..227b7c5c51e 100644 --- a/src/mongo/db/structure/record_store_v1_simple.cpp +++ b/src/mongo/db/structure/record_store_v1_simple.cpp @@ -32,14 +32,19 @@ #include "mongo/base/counter.h" #include "mongo/db/catalog/collection.h" +#include "mongo/db/client.h" #include "mongo/db/commands/server_status.h" +#include "mongo/db/curop.h" #include "mongo/db/dur.h" +#include "mongo/db/kill_current_op.h" #include "mongo/db/storage/extent.h" #include "mongo/db/storage/extent_manager.h" #include "mongo/db/storage/record.h" #include "mongo/db/structure/catalog/namespace_details.h" #include "mongo/db/structure/record_store_v1_simple_iterator.h" #include "mongo/util/mmap.h" +#include "mongo/util/progress_meter.h" +#include "mongo/util/touch_pages.h" namespace mongo { @@ -267,4 +272,203 @@ namespace mongo { return new SimpleRecordStoreV1Iterator( this, start, dir ); } + class CompactDocWriter : public DocWriter { + public: + /** + * param allocationSize - allocation size WITH header + */ + CompactDocWriter( const Record* rec, unsigned dataSize, size_t allocationSize ) + : _rec( rec ), + _dataSize( dataSize ), + _allocationSize( allocationSize ) { + } + + virtual ~CompactDocWriter() {} + + virtual void writeDocument( char* buf ) const { + memcpy( buf, _rec->data(), _dataSize ); + } + + virtual size_t documentSize() const { + return _allocationSize - Record::HeaderSize; + } + + virtual bool addPadding() const { + return false; + } + + private: + const Record* _rec; + size_t _dataSize; + size_t _allocationSize; + }; + + void SimpleRecordStoreV1::_compactExtent(const DiskLoc diskloc, int extentNumber, + RecordStoreCompactAdaptor* adaptor, + const CompactOptions* compactOptions, + CompactStats* stats ) { + + log() << "compact begin extent #" << extentNumber + << " for namespace " << _ns << " " << diskloc; + + unsigned oldObjSize = 0; // we'll report what the old padding was + unsigned oldObjSizeWithPadding = 0; + + Extent *e = _extentManager->getExtent( diskloc ); + e->assertOk(); + fassert( 17437, e->validates(diskloc) ); + + { + // the next/prev pointers within the extent might not be in order so we first + // page the whole thing in sequentially + log() << "compact paging in len=" << e->length/1000000.0 << "MB" << endl; + Timer t; + size_t length = e->length; + + touch_pages( reinterpret_cast<const char*>(e), length ); + int ms = t.millis(); + if( ms > 1000 ) + log() << "compact end paging in " << ms << "ms " + << e->length/1000000.0/t.seconds() << "MB/sec" << endl; + } + + { + log() << "compact copying records" << endl; + long long datasize = 0; + long long nrecords = 0; + DiskLoc L = e->firstRecord; + if( !L.isNull() ) { + while( 1 ) { + Record *recOld = recordFor(L); + L = _extentManager->getNextRecordInExtent(L); + + if ( compactOptions->validateDocuments && !adaptor->isDataValid(recOld) ) { + // object is corrupt! + log() << "compact skipping corrupt document!"; + stats->corruptDocuments++; + } + else { + unsigned dataSize = adaptor->dataSize( recOld ); + unsigned docSize = dataSize; + + nrecords++; + oldObjSize += docSize; + oldObjSizeWithPadding += recOld->netLength(); + + unsigned lenWHdr = docSize + Record::HeaderSize; + unsigned lenWPadding = lenWHdr; + + switch( compactOptions->paddingMode ) { + case CompactOptions::NONE: + if ( _details->isUserFlagSet(NamespaceDetails::Flag_UsePowerOf2Sizes) ) + lenWPadding = _details->quantizePowerOf2AllocationSpace(lenWPadding); + break; + case CompactOptions::PRESERVE: + // if we are preserving the padding, the record should not change size + lenWPadding = recOld->lengthWithHeaders(); + break; + case CompactOptions::MANUAL: + lenWPadding = compactOptions->computeRecordSize(lenWPadding); + if (lenWPadding < lenWHdr || lenWPadding > BSONObjMaxUserSize / 2 ) { + lenWPadding = lenWHdr; + } + break; + } + + CompactDocWriter writer( recOld, dataSize, lenWPadding ); + StatusWith<DiskLoc> status = insertRecord( &writer, 0 ); + uassertStatusOK( status.getStatus() ); + datasize += recordFor( status.getValue() )->netLength(); + + adaptor->inserted( recordFor( status.getValue() ), status.getValue() ); + } + + if( L.isNull() ) { + // we just did the very last record from the old extent. it's still pointed to + // by the old extent ext, but that will be fixed below after this loop + break; + } + + // remove the old records (orphan them) periodically so our commit block doesn't get too large + bool stopping = false; + RARELY stopping = *killCurrentOp.checkForInterruptNoAssert() != 0; + if( stopping || getDur().isCommitNeeded() ) { + e->firstRecord.writing() = L; + Record *r = recordFor(L); + getDur().writingInt(r->prevOfs()) = DiskLoc::NullOfs; + getDur().commitIfNeeded(); + killCurrentOp.checkForInterrupt(); + } + } + } // if !L.isNull() + + invariant( _details->firstExtent() == diskloc ); + invariant( _details->lastExtent() != diskloc ); + DiskLoc newFirst = e->xnext; + _details->firstExtent().writing() = newFirst; + _extentManager->getExtent( newFirst )->xprev.writing().Null(); + getDur().writing(e)->markEmpty(); + _extentManager->freeExtents( diskloc, diskloc ); + + getDur().commitIfNeeded(); + + { + double op = 1.0; + if( oldObjSize ) + op = static_cast<double>(oldObjSizeWithPadding)/oldObjSize; + log() << "compact finished extent #" << extentNumber << " containing " << nrecords + << " documents (" << datasize/1000000.0 << "MB)" + << " oldPadding: " << op << ' ' << static_cast<unsigned>(op*100.0)/100; + } + } + + } + + Status SimpleRecordStoreV1::compact( RecordStoreCompactAdaptor* adaptor, + const CompactOptions* options, + CompactStats* stats ) { + + // this is a big job, so might as well make things tidy before we start just to be nice. + getDur().commitIfNeeded(); + + list<DiskLoc> extents; + for( DiskLoc extLocation = _details->firstExtent(); + !extLocation.isNull(); + extLocation = _extentManager->getExtent( extLocation )->xnext ) { + extents.push_back( extLocation ); + } + log() << "compact " << extents.size() << " extents"; + + log() << "compact orphan deleted lists" << endl; + _details->orphanDeletedList(); + + // Start over from scratch with our extent sizing and growth + _details->setLastExtentSize( 0 ); + + // create a new extent so new records go there + increaseStorageSize( _details->lastExtentSize(), true ); + + // reset data size and record counts to 0 for this namespace + // as we're about to tally them up again for each new extent + _details->setStats( 0, 0 ); + + ProgressMeterHolder pm(cc().curop()->setMessage("compact extent", + "Extent Compacting Progress", + extents.size())); + + int extentNumber = 0; + for( list<DiskLoc>::iterator i = extents.begin(); i != extents.end(); i++ ) { + _compactExtent(*i, extentNumber++, adaptor, options, stats ); + pm.hit(); + } + + invariant( _extentManager->getExtent( _details->firstExtent() )->xprev.isNull() ); + invariant( _extentManager->getExtent( _details->lastExtent() )->xnext.isNull() ); + + // indexes will do their own progress meter + pm.finished(); + + return Status::OK(); + } + } diff --git a/src/mongo/db/structure/record_store_v1_simple.h b/src/mongo/db/structure/record_store_v1_simple.h index 1af6f002767..bb808d3e4a7 100644 --- a/src/mongo/db/structure/record_store_v1_simple.h +++ b/src/mongo/db/structure/record_store_v1_simple.h @@ -47,10 +47,18 @@ namespace mongo { virtual ~SimpleRecordStoreV1(); + const char* name() const { return "SimpleRecordStoreV1"; } + virtual RecordIterator* getIterator( const DiskLoc& start, bool tailable, const CollectionScanParams::Direction& dir) const; virtual Status truncate(); + + virtual bool compactSupported() const { return true; } + virtual Status compact( RecordStoreCompactAdaptor* adaptor, + const CompactOptions* options, + CompactStats* stats ); + protected: virtual StatusWith<DiskLoc> allocRecord( int lengthWithHeaders, int quotaMax ); @@ -58,6 +66,11 @@ namespace mongo { private: DiskLoc _allocFromExistingExtents( int lengthWithHeaders ); + void _compactExtent(const DiskLoc diskloc, int extentNumber, + RecordStoreCompactAdaptor* adaptor, + const CompactOptions* compactOptions, + CompactStats* stats ); + bool _normalCollection; friend class SimpleRecordStoreV1Iterator; |