private void AllocateGrains(int grainTable, int grain, int count) { // Calculate start pos for new grain long grainStartPos = (long)_serverHeader.FreeSector * Sizes.Sector; // Copy-on-write semantics, read the bytes from parent and write them out to this extent. _parentDiskStream.Position = _diskOffset + (grain + _header.NumGTEsPerGT * grainTable) * _header.GrainSize * Sizes.Sector; byte[] content = StreamUtilities.ReadExact(_parentDiskStream, (int)(_header.GrainSize * Sizes.Sector * count)); _fileStream.Position = grainStartPos; _fileStream.Write(content, 0, content.Length); // Update next-free-sector in disk header _serverHeader.FreeSector += (uint)MathUtilities.Ceil(content.Length, Sizes.Sector); byte[] headerBytes = _serverHeader.GetBytes(); _fileStream.Position = 0; _fileStream.Write(headerBytes, 0, headerBytes.Length); LoadGrainTable(grainTable); for (int i = 0; i < count; ++i) { SetGrainTableEntry(grain + i, (uint)(grainStartPos / Sizes.Sector + _header.GrainSize * i)); } WriteGrainTable(); }
private static void CreateExtent(Stream extentStream, long size, ExtentType type, long descriptorLength, out long descriptorStart) { if (type == ExtentType.Flat || type == ExtentType.Vmfs) { extentStream.SetLength(size); descriptorStart = 0; return; } if (type == ExtentType.Sparse) { CreateSparseExtent(extentStream, size, descriptorLength, out descriptorStart); return; } else if (type == ExtentType.VmfsSparse) { ServerSparseExtentHeader header = CreateServerSparseExtentHeader(size); extentStream.Position = 0; extentStream.Write(header.GetBytes(), 0, 4 * Sizes.Sector); byte[] blankGlobalDirectory = new byte[header.NumGdEntries * 4]; extentStream.Write(blankGlobalDirectory, 0, blankGlobalDirectory.Length); descriptorStart = 0; return; } else { throw new NotImplementedException("Extent type not implemented"); } }
internal override List <BuilderExtent> FixExtents(out long totalLength) { List <BuilderExtent> extents = new List <BuilderExtent>(); ServerSparseExtentHeader header = DiskImageFile.CreateServerSparseExtentHeader(_content.Length); GlobalDirectoryExtent gdExtent = new GlobalDirectoryExtent(header); long grainTableStart = (header.GdOffset * Sizes.Sector) + gdExtent.Length; long grainTableCoverage = header.NumGTEsPerGT * header.GrainSize * Sizes.Sector; foreach (var grainTableRange in StreamExtent.Blocks(_content.Extents, grainTableCoverage)) { for (int i = 0; i < grainTableRange.Count; ++i) { long grainTable = grainTableRange.Offset + i; long dataStart = grainTable * grainTableCoverage; GrainTableExtent gtExtent = new GrainTableExtent(grainTableStart, new SubStream(_content, dataStart, Math.Min(grainTableCoverage, _content.Length - dataStart)), header); extents.Add(gtExtent); gdExtent.SetEntry((int)grainTable, (uint)(grainTableStart / Sizes.Sector)); grainTableStart += gtExtent.Length; } } extents.Insert(0, gdExtent); header.FreeSector = (uint)(grainTableStart / Sizes.Sector); byte[] buffer = header.GetBytes(); extents.Insert(0, new BuilderBufferExtent(0, buffer)); totalLength = grainTableStart; return(extents); }