void RecordStoreV1Base::deleteRecord( TransactionExperiment* txn, const DiskLoc& dl ) { Record* todelete = recordFor( dl ); /* remove ourself from the record next/prev chain */ { if ( todelete->prevOfs() != DiskLoc::NullOfs ) { DiskLoc prev = getPrevRecordInExtent( dl ); Record* prevRecord = recordFor( prev ); txn->writingInt( prevRecord->nextOfs() ) = todelete->nextOfs(); } if ( todelete->nextOfs() != DiskLoc::NullOfs ) { DiskLoc next = getNextRecord( dl ); Record* nextRecord = recordFor( next ); txn->writingInt( nextRecord->prevOfs() ) = todelete->prevOfs(); } } /* remove ourself from extent pointers */ { Extent *e = txn->writing( _getExtent( _getExtentLocForRecord( dl ) ) ); if ( e->firstRecord == dl ) { if ( todelete->nextOfs() == DiskLoc::NullOfs ) e->firstRecord.Null(); else e->firstRecord.set(dl.a(), todelete->nextOfs() ); } if ( e->lastRecord == dl ) { if ( todelete->prevOfs() == DiskLoc::NullOfs ) e->lastRecord.Null(); else e->lastRecord.set(dl.a(), todelete->prevOfs() ); } } /* add to the free list */ { _details->incrementStats( txn, -1 * todelete->netLength(), -1 ); if ( _isSystemIndexes ) { /* temp: if in system.indexes, don't reuse, and zero out: we want to be careful until validated more, as IndexDetails has pointers to this disk location. so an incorrectly done remove would cause a lot of problems. */ memset( txn->writingPtr(todelete, todelete->lengthWithHeaders() ), 0, todelete->lengthWithHeaders() ); } else { DEV { unsigned long long *p = reinterpret_cast<unsigned long long *>( todelete->data() ); *txn->writing(p) = 0; } addDeletedRec(txn, dl); } } }
void RecordStoreV1Base::_addRecordToRecListInExtent(OperationContext* txn, Record *r, DiskLoc loc) { dassert( recordFor(loc) == r ); Extent *e = _getExtent( _getExtentLocForRecord( loc ) ); if ( e->lastRecord.isNull() ) { *txn->recoveryUnit()->writing(&e->firstRecord) = loc; *txn->recoveryUnit()->writing(&e->lastRecord) = loc; r->prevOfs() = r->nextOfs() = DiskLoc::NullOfs; } else { Record *oldlast = recordFor(e->lastRecord); r->prevOfs() = e->lastRecord.getOfs(); r->nextOfs() = DiskLoc::NullOfs; txn->recoveryUnit()->writingInt(oldlast->nextOfs()) = loc.getOfs(); *txn->recoveryUnit()->writing(&e->lastRecord) = loc; } }
DiskLoc RecordStoreV1Base::getNextRecord( const DiskLoc& loc ) const { DiskLoc next = getNextRecordInExtent( loc ); if ( !next.isNull() ) return next; // now traverse extents Extent* e = _getExtent( _getExtentLocForRecord(loc) ); while ( 1 ) { if ( e->xnext.isNull() ) return DiskLoc(); // end of collection e = _getExtent( e->xnext ); if ( !e->firstRecord.isNull() ) break; // entire extent could be empty, keep looking } return e->firstRecord; }
DiskLoc RecordStoreV1Base::getPrevRecord(OperationContext* txn, const DiskLoc& loc) const { DiskLoc prev = getPrevRecordInExtent(txn, loc); if (!prev.isNull()) { return prev; } // now traverse extents Extent* e = _getExtent(txn, _getExtentLocForRecord(txn, loc)); while (1) { if (e->xprev.isNull()) return DiskLoc(); // end of collection e = _getExtent(txn, e->xprev); if (!e->firstRecord.isNull()) break; // entire extent could be empty, keep looking } return e->lastRecord; }