DynamicColumn.cs 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. /* Copyright (C) 2014 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
  2. *
  3. * You can redistribute this program and/or modify it under the terms of
  4. * the GNU Lesser Public License as published by the Free Software Foundation,
  5. * either version 3 of the License, or (at your option) any later version.
  6. */
  7. using System;
  8. using System.Collections.Generic;
  9. using System.Text;
  10. using Utilities;
  11. namespace DiskAccessLibrary.LogicalDiskManager
  12. {
  13. /// <summary>
  14. /// Column is a sequence of one or more (dynamic) disk extents, it's an abstraction of disk,
  15. /// Simple Volume uses a single column that has one extent,
  16. /// Spanned volume uses a single column to span data across multiple extents,
  17. /// Striped / RAID-5 write the data in stripes across multiple columns in an orderly fashion. (each column can contain more than one extent)
  18. /// </summary>
  19. public class DynamicColumn
  20. {
  21. List<DynamicDiskExtent> m_extents = new List<DynamicDiskExtent>();
  22. public DynamicColumn(DynamicDiskExtent extent)
  23. {
  24. m_extents.Add(extent);
  25. }
  26. public DynamicColumn(List<DynamicDiskExtent> extents)
  27. {
  28. m_extents = extents;
  29. }
  30. private List<ArrayPosition> TranslateSectors(long startSectorIndex, int sectorCount)
  31. {
  32. List<ArrayPosition> result = new List<ArrayPosition>();
  33. int numberOfDisks = m_extents.Count;
  34. int sectorsLeft = sectorCount;
  35. long currentSectorIndex = startSectorIndex;
  36. while (sectorsLeft > 0)
  37. {
  38. long extentStartSectorInColumn = 0;
  39. long nextExtentStartSectorInColumn = 0;
  40. for (int index = 0; index < m_extents.Count; index++)
  41. {
  42. DynamicDiskExtent extent = m_extents[index];
  43. extentStartSectorInColumn = nextExtentStartSectorInColumn;
  44. nextExtentStartSectorInColumn += extent.TotalSectors;
  45. if (currentSectorIndex >= extentStartSectorInColumn && currentSectorIndex < nextExtentStartSectorInColumn)
  46. {
  47. long sectorIndexInExtent = currentSectorIndex - extentStartSectorInColumn;
  48. int sectorCountInExtent = (int)Math.Min(extent.TotalSectors - sectorIndexInExtent, sectorsLeft);
  49. ArrayPosition position = new ArrayPosition(index, sectorIndexInExtent, sectorCountInExtent);
  50. result.Add(position);
  51. currentSectorIndex += sectorCountInExtent;
  52. sectorsLeft -= sectorCountInExtent;
  53. }
  54. }
  55. }
  56. return result;
  57. }
  58. public byte[] ReadSectors(long sectorIndex, int sectorCount)
  59. {
  60. List<ArrayPosition> readPositions = TranslateSectors(sectorIndex, sectorCount);
  61. byte[] result = new byte[sectorCount * DynamicVolume.BytesPerDynamicDiskSector];
  62. int bytesRead = 0;
  63. foreach (ArrayPosition readPosition in readPositions)
  64. {
  65. DynamicDiskExtent extent = m_extents[readPosition.DiskIndex];
  66. byte[] extentBytes = extent.ReadSectors(readPosition.SectorIndex, readPosition.SectorCount);
  67. Array.Copy(extentBytes, 0, result, bytesRead, extentBytes.Length);
  68. bytesRead += extentBytes.Length;
  69. }
  70. return result;
  71. }
  72. public void WriteSectors(long sectorIndex, byte[] data)
  73. {
  74. int sectorCount = data.Length / DynamicVolume.BytesPerDynamicDiskSector;
  75. List<ArrayPosition> writePositions = TranslateSectors(sectorIndex, sectorCount);
  76. int bytesWritten = 0;
  77. foreach (ArrayPosition writePosition in writePositions)
  78. {
  79. DynamicDiskExtent extent = m_extents[writePosition.DiskIndex];
  80. byte[] extentBytes = new byte[writePosition.SectorCount * DynamicVolume.BytesPerDynamicDiskSector];
  81. Array.Copy(data, bytesWritten, extentBytes, 0, extentBytes.Length);
  82. extent.WriteSectors(writePosition.SectorIndex, extentBytes);
  83. bytesWritten += extentBytes.Length;
  84. }
  85. }
  86. public List<DynamicDiskExtent> Extents
  87. {
  88. get
  89. {
  90. return m_extents;
  91. }
  92. }
  93. public long Size
  94. {
  95. get
  96. {
  97. long result = 0;
  98. foreach (DynamicDiskExtent extent in m_extents)
  99. {
  100. result += extent.Size;
  101. }
  102. return result;
  103. }
  104. }
  105. public bool IsOperational
  106. {
  107. get
  108. {
  109. foreach (DynamicDiskExtent extent in m_extents)
  110. {
  111. if (extent.Disk == null)
  112. {
  113. return false;
  114. }
  115. }
  116. return true;
  117. }
  118. }
  119. }
  120. }