public static void MoveExtentDataRight(Volume volume, DiskExtent sourceExtent, DiskExtent relocatedExtent, MoveExtentOperationBootRecord resumeRecord, ref long bytesCopied) { // we make sure no data will be overwritten too soon: long distanceLBA = (long)(resumeRecord.NewStartSector - resumeRecord.OldStartSector); bool bufferedMode = false; if (distanceLBA < BufferedModeThresholdLBA) { bufferedMode = true; } int transferSizeLBA; if (bufferedMode) { transferSizeLBA = (int)resumeRecord.BackupBufferSizeLBA; } else { transferSizeLBA = (int)Math.Min(Settings.MaximumTransferSizeLBA, distanceLBA); } // move the data for (long readCount = (long)resumeRecord.NumberOfCommittedSectors; readCount < relocatedExtent.TotalSectors; readCount += transferSizeLBA) { // we read (and write) from the end of the extent and progress to the left long sectorsLeft = relocatedExtent.TotalSectors - readCount; int sectorsToRead = (int)Math.Min(transferSizeLBA, sectorsLeft); long sectorIndex = relocatedExtent.TotalSectors - readCount - sectorsToRead; byte[] data = sourceExtent.ReadSectors(sectorIndex, sectorsToRead); if (bufferedMode) { // we write the data to the buffer for recovery purposes relocatedExtent.Disk.WriteSectors((long)resumeRecord.BackupBufferStartSector, data); resumeRecord.RestoreFromBuffer = true; // Note: if the extent we move is the first in the volume, we will write the resume record to // the source extent, which is the one that the database is still referring to volume.WriteSectors(0, resumeRecord.GetBytes()); } relocatedExtent.WriteSectors(sectorIndex, data); // update the resume record resumeRecord.RestoreFromBuffer = false; resumeRecord.NumberOfCommittedSectors += (ulong)sectorsToRead; volume.WriteSectors(0, resumeRecord.GetBytes()); bytesCopied = (long)resumeRecord.NumberOfCommittedSectors * sourceExtent.BytesPerSector; } }
public static void MoveExtentDataLeft(Volume volume, DiskExtent sourceExtent, DiskExtent relocatedExtent, MoveExtentOperationBootRecord resumeRecord, ref long bytesCopied) { // we make sure no data will be overwritten too soon: long distanceLBA = (long)(resumeRecord.OldStartSector - resumeRecord.NewStartSector); bool bufferedMode = false; if (distanceLBA < BufferedModeThresholdLBA) { bufferedMode = true; } int transferSizeLBA; if (bufferedMode) { transferSizeLBA = (int)resumeRecord.BackupBufferSizeLBA;; } else { transferSizeLBA = (int)Math.Min(Settings.MaximumTransferSizeLBA, distanceLBA); } // move the data for (long sectorIndex = (long)resumeRecord.NumberOfCommittedSectors; sectorIndex < relocatedExtent.TotalSectors; sectorIndex += transferSizeLBA) { long sectorsLeft = relocatedExtent.TotalSectors - sectorIndex; int sectorsToRead = (int)Math.Min(transferSizeLBA, sectorsLeft); byte[] data = sourceExtent.ReadSectors(sectorIndex, sectorsToRead); if (bufferedMode) { // we write the data to the buffer for recovery purposes relocatedExtent.Disk.WriteSectors((long)resumeRecord.BackupBufferStartSector, data); resumeRecord.RestoreFromBuffer = true; relocatedExtent.WriteSectors(0, resumeRecord.GetBytes()); } relocatedExtent.WriteSectors(sectorIndex, data); // update the resume record resumeRecord.RestoreFromBuffer = false; resumeRecord.NumberOfCommittedSectors += (ulong)sectorsToRead; volume.WriteSectors(0, resumeRecord.GetBytes()); bytesCopied = (long)resumeRecord.NumberOfCommittedSectors * sourceExtent.BytesPerSector; } }