/// <summary> /// "All disks holding extents for a given volume must have the same sector size" /// </summary> public static int?GetBytesPerSector(List <DynamicColumn> columns) { foreach (DynamicColumn column in columns) { int?bytesPerSector = DynamicColumn.GetBytesPerSector(column.Extents); if (bytesPerSector.HasValue) { return(bytesPerSector.Value); } } return(null); }
public override void WriteSectors(long sectorIndex, byte[] data) { int sectorCount = data.Length / this.BytesPerSector; List <ArrayPosition> writePositions = TranslateSectors(sectorIndex, sectorCount); int bytesWritten = 0; foreach (ArrayPosition writePosition in writePositions) { byte[] stripeBytes = new byte[writePosition.SectorCount * this.BytesPerSector]; Array.Copy(data, bytesWritten, stripeBytes, 0, stripeBytes.Length); DynamicColumn column = m_columns[writePosition.DiskIndex]; column.WriteSectors(writePosition.SectorIndex, stripeBytes); bytesWritten += stripeBytes.Length; } }
public override byte[] ReadSectors(long sectorIndex, int sectorCount) { List <ArrayPosition> readPositions = TranslateSectors(sectorIndex, sectorCount); byte[] result = new byte[sectorCount * BytesPerSector]; int bytesRead = 0; foreach (ArrayPosition readPosition in readPositions) { DynamicColumn column = m_columns[readPosition.DiskIndex]; byte[] stripeBytes = column.ReadSectors(readPosition.SectorIndex, (int)readPosition.SectorCount); Array.Copy(stripeBytes, 0, result, bytesRead, stripeBytes.Length); bytesRead += stripeBytes.Length; } return(result); }
public override byte[] ReadSectors(long sectorIndex, int sectorCount) { CheckBoundaries(sectorIndex, sectorCount); List <ArrayPosition> readPositions = TranslateSectors(sectorIndex, sectorCount); byte[] result = new byte[sectorCount * BytesPerSector]; int bytesRead = 0; foreach (ArrayPosition readPosition in readPositions) { DynamicColumn column = m_columns[readPosition.DiskIndex]; byte[] stripeBytes; if (column.IsOperational) { stripeBytes = column.ReadSectors(readPosition.SectorIndex, readPosition.SectorCount); } else { stripeBytes = new byte[readPosition.SectorCount * BytesPerDynamicDiskSector]; for (int index = 0; index < m_columns.Count; index++) { if (index != readPosition.DiskIndex) { byte[] currentBytes = m_columns[index].ReadSectors(readPosition.SectorIndex, readPosition.SectorCount); stripeBytes = XOR(stripeBytes, currentBytes); } } } Array.Copy(stripeBytes, 0, result, bytesRead, stripeBytes.Length); bytesRead += stripeBytes.Length; } return(result); }
// We support degraded arrays public override void WriteSectors(long sectorIndex, byte[] data) { CheckBoundaries(sectorIndex, data.Length / this.BytesPerSector); int numberOfColumns = m_columns.Count; int sectorCount = data.Length / this.BytesPerSector; List <ArrayPosition> writePositions = TranslateSectors(sectorIndex, sectorCount); int bytesWritten = 0; foreach (ArrayPosition writePosition in writePositions) { DynamicColumn column = m_columns[writePosition.DiskIndex]; byte[] stripeBytes = new byte[writePosition.SectorCount * this.BytesPerSector]; Array.Copy(data, bytesWritten, stripeBytes, 0, stripeBytes.Length); // first we obtain the necessary data from the other columns long stripeIndexInColumn = writePosition.SectorIndex / m_sectorsPerStripe; int parityColumnIndex = (numberOfColumns - 1) - (int)(stripeIndexInColumn % numberOfColumns); List <byte[]> segment = new List <byte[]>(); for (int index = 0; index < numberOfColumns; index++) { if (m_columns[index].IsOperational) { byte[] bytes = m_columns[index].ReadSectors(writePosition.SectorIndex, writePosition.SectorCount); segment.Add(bytes); } else { segment.Add(null); } } int missingColumnIndex = segment.IndexOf(null); if (missingColumnIndex >= 0) { if (missingColumnIndex != parityColumnIndex && missingColumnIndex != writePosition.DiskIndex) { // let's calculate the missing data stripe byte[] missingBytes = segment[parityColumnIndex]; for (int index = 0; index < numberOfColumns; index++) { if (index != missingColumnIndex && index != parityColumnIndex) { missingBytes = XOR(missingBytes, segment[index]); } } segment[missingColumnIndex] = missingBytes; } } if (column.IsOperational) { column.WriteSectors(writePosition.SectorIndex, stripeBytes); } if (missingColumnIndex != parityColumnIndex) { // lets calculate the new parity disk segment[writePosition.DiskIndex] = stripeBytes; byte[] parityBytes = new byte[writePosition.SectorCount * this.BytesPerSector]; for (int index = 0; index < numberOfColumns; index++) { if (index != parityColumnIndex) { parityBytes = XOR(parityBytes, segment[index]); } } m_columns[parityColumnIndex].WriteSectors(writePosition.SectorIndex, parityBytes); } bytesWritten += stripeBytes.Length; } }
public SpannedVolume(DynamicColumn column, Guid volumeGuid, Guid diskGroupGuid) : base(volumeGuid, diskGroupGuid) { m_column = column; }