/// <summary> /// Reads this instance. /// </summary> /// <returns></returns> public unsafe byte[] Read(ulong size) { // We prepare variables. byte[] data = new byte[size]; ulong i = 0; // Begin loop. for (ulong addr = blocks[0]; addr != 0;) { uint seq; ulong next; // Read header first. Block headerBlock = service.Read(BlockType.BigObjectData, addr); fixed(byte *p = headerBlock.Data) { BlockLinkHeader *header = (BlockLinkHeader *)p; next = header->NextBlock; seq = header->Sequential; } // First block special. for (uint j = (uint)sizeof(BlockLinkHeader); j < headerBlock.Data.Length && i < size; i++, j++) { data[i] = headerBlock.Data[j]; } // All sequential blocks. for (uint k = 1; k < seq; k++) { Block dataBlock = service.Read(BlockType.BigObjectData, addr + k); for (uint z = 0; z < dataBlock.Data.Length && i < size; i++, z++) { data[i] = dataBlock.Data[z]; } } // Next iteration. addr = next; } return(data); }
/// <summary> /// Deallocates this instance. /// </summary> public unsafe void Deallocate() { if (!CanWrite) { throw new ArgumentException("Cannot deallocate."); } IService writeService = service as IService; // We deallocate link. ulong addr = this.blocks[0]; for (; addr != 0;) { // We read the link. Block block = writeService.Read(BlockType.BigObjectData, addr); uint lenght; ulong next; // We extract header. fixed(byte *p = block.Data) { BlockLinkHeader *header = (BlockLinkHeader *)p; next = header->NextBlock; lenght = header->Sequential; } // We free all. for (uint i = 0; i < lenght; i++) { writeService.DeAllocate(addr + i); } // We proceed to next. addr = next; } }
/// <summary> /// Writes the specified data. /// </summary> /// <param name="data">The data.</param> public unsafe void Write(byte[] data) { if (!CanWrite) { throw new ArgumentException("Cannot write."); } IService writeService = service as IService; // We first organize blocks into logican units. ulong prev = 0; LogicalBlockUnit processingLink = new LogicalBlockUnit(0); List <LogicalBlockUnit> links = new List <LogicalBlockUnit>(); foreach (ulong block in blocks) { if (block == prev + 1) { processingLink.Count++; } else { links.Add(processingLink); processingLink = new LogicalBlockUnit(block); } prev = block; } links.Add(processingLink); // We have organised units, we can now actually write. We begin // at 1 because the first link is always an empty link. ulong dataOffset = 0; for (uint i = 1; i < (uint)links.Count; i++) { // We extract logical unit and next. LogicalBlockUnit link = links[(int)i]; ulong next = i == links.Count - 1 ? 0 : links[(int)(i + 1)].First; // We write to it, header first. Block block = new Block(service.BlockSize); fixed(byte *p = block.Data) { BlockLinkHeader *header = (BlockLinkHeader *)p; header->Sequential = link.Count; header->NextBlock = next; } // TODO: use ulong(s) in future for copying, not bytes. // We copy to header block (make sure we do not acces out of it). ulong maxWrite = service.BlockSize - (ulong)sizeof(BlockLinkHeader); if (maxWrite > (ulong)data.LongLength - dataOffset) { maxWrite = (ulong)data.LongLength - dataOffset; } for (uint k = 0; k < maxWrite; k++) { block.Data[k + (uint)sizeof(BlockLinkHeader)] = data[dataOffset++]; } writeService.Write(BlockType.BigObjectData, link.First, block); // And the rest of it. for (uint j = 1; j < link.Count; j++) { maxWrite = service.BlockSize; if (maxWrite > (ulong)data.LongLength - dataOffset) { maxWrite = (ulong)data.LongLength - dataOffset; } for (uint l = 0; l < maxWrite; l++) { block.Data[l] = data[dataOffset++]; } writeService.Write(BlockType.BigObjectData, link.First + j, block); } } }