StatusWith<RecordData> KVRecordStore::updateWithDamages( OperationContext* txn, const RecordId& id, const RecordData& oldRec, const char* damageSource, const mutablebson::DamageVector& damages ) { const KeyString key(id); const Slice oldValue(oldRec.data(), oldRec.size()); const KVUpdateWithDamagesMessage message(damageSource, damages); // updateWithDamages can't change the number or size of records, so we don't need to update // stats. const Status s = _db->update(txn, Slice::of(key), oldValue, message); if (!s.isOK()) { return StatusWith<RecordData>(s); } // We also need to reach in and screw with the old doc's data so that the update system gets // the new image, because the update system is assuming mmapv1's behavior. Sigh. for (mutablebson::DamageVector::const_iterator it = damages.begin(); it != damages.end(); it++) { const mutablebson::DamageEvent &event = *it; invariant(event.targetOffset + event.size < static_cast<uint32_t>(oldRec.size())); std::copy(damageSource + event.sourceOffset, damageSource + event.sourceOffset + event.size, /* eek */ const_cast<char *>(oldRec.data()) + event.targetOffset); } return StatusWith<RecordData>(oldRec); }
Status HeapRecordStore::updateWithDamages( OperationContext* txn, const DiskLoc& loc, const RecordData& oldRec, const char* damageSource, const mutablebson::DamageVector& damages ) { HeapRecord* oldRecord = recordFor( loc ); const int len = oldRecord->size; HeapRecord newRecord(len); memcpy(newRecord.data.get(), oldRecord->data.get(), len); txn->recoveryUnit()->registerChange(new RemoveChange(_data, loc, *oldRecord)); *oldRecord = newRecord; cappedDeleteAsNeeded(txn); char* root = newRecord.data.get(); mutablebson::DamageVector::const_iterator where = damages.begin(); const mutablebson::DamageVector::const_iterator end = damages.end(); for( ; where != end; ++where ) { const char* sourcePtr = damageSource + where->sourceOffset; char* targetPtr = root + where->targetOffset; std::memcpy(targetPtr, sourcePtr, where->size); } *oldRecord = newRecord; return Status::OK(); }
StatusWith<RecordData> EphemeralForTestRecordStore::updateWithDamages( OperationContext* opCtx, const RecordId& loc, const RecordData& oldRec, const char* damageSource, const mutablebson::DamageVector& damages) { stdx::lock_guard<stdx::recursive_mutex> lock(_data->recordsMutex); EphemeralForTestRecord* oldRecord = recordFor(loc); const int len = oldRecord->size; EphemeralForTestRecord newRecord(len); memcpy(newRecord.data.get(), oldRecord->data.get(), len); opCtx->recoveryUnit()->registerChange(new RemoveChange(opCtx, _data, loc, *oldRecord)); *oldRecord = newRecord; cappedDeleteAsNeeded_inlock(opCtx); char* root = newRecord.data.get(); mutablebson::DamageVector::const_iterator where = damages.begin(); const mutablebson::DamageVector::const_iterator end = damages.end(); for (; where != end; ++where) { const char* sourcePtr = damageSource + where->sourceOffset; char* targetPtr = root + where->targetOffset; std::memcpy(targetPtr, sourcePtr, where->size); } *oldRecord = newRecord; return newRecord.toRecordData(); }
Status HeapRecordStore::updateWithDamages( OperationContext* txn, const DiskLoc& loc, const char* damangeSource, const mutablebson::DamageVector& damages ) { HeapRecord* rec = recordFor( loc ); char* root = rec->data(); // All updates were in place. Apply them via durability and writing pointer. mutablebson::DamageVector::const_iterator where = damages.begin(); const mutablebson::DamageVector::const_iterator end = damages.end(); for( ; where != end; ++where ) { const char* sourcePtr = damangeSource + where->sourceOffset; char* targetPtr = root + where->targetOffset; std::memcpy(targetPtr, sourcePtr, where->size); } return Status::OK(); }
StatusWith<RecordData> RecordStoreV1Base::updateWithDamages( OperationContext* txn, const RecordId& loc, const RecordData& oldRec, const char* damageSource, const mutablebson::DamageVector& damages) { MmapV1RecordHeader* rec = recordFor(DiskLoc::fromRecordId(loc)); char* root = rec->data(); // All updates were in place. Apply them via durability and writing pointer. mutablebson::DamageVector::const_iterator where = damages.begin(); const mutablebson::DamageVector::const_iterator end = damages.end(); for (; where != end; ++where) { const char* sourcePtr = damageSource + where->sourceOffset; void* targetPtr = txn->recoveryUnit()->writingPtr(root + where->targetOffset, where->size); std::memcpy(targetPtr, sourcePtr, where->size); } return rec->toRecordData(); }