public void CreateNewBlock(Guid id, ulong blockCount) { if (blockCount > UInt32.MaxValue) { throw new Exception("VirtualBlocks larger than 2^32-1 are not yet supported!"); } using(_configurationLock.EnterWriteLock()) { if (_blocks.ContainsKey(id)) { throw new Exception("Block already exists!"); } if (blockCount > uint.MaxValue) { throw new NotImplementedException("More than 2^32-1 blocks not yet supported at create-time!"); } MetaGroupHeader xGroupHeader = null; foreach (var xMetaGroup in _metaHeaders) { if (xMetaGroup.Parts.Length < _metaGroupItemsPerVirtualBlock) { xGroupHeader = xMetaGroup; break; } } if (xGroupHeader == null) { throw new Exception("No GroupHeader found with a free slot!"); } var xNextPostValues = (from item in _metaHeaders where item.Parts.Length > 0 select (from subItem in item.Parts select subItem.FirstDataBlockNumber + subItem.BlockCount).Max()).ToArray(); ulong xNextPos; if (xNextPostValues.Any()) { xNextPos = xNextPostValues.Max(); } else { xNextPos = (from item in _metaHeaders select item.BlockId + 1).Max(); } if ((((xNextPos + blockCount) * _virtualBlockSize) / _blockStore.BlockSize) > _blockStore.BlockCount) { throw new Exception("No free space found!"); } var xNewPartsList = new List<VirtualBlockPart>(xGroupHeader.Parts); var xNewPart = new VirtualBlockPart { BlockCount = (uint)blockCount, FirstDataBlockNumber = xNextPos, PartIndex = 0, TotalPartCount = 1 }; var xVBlock = new VirtualBlockConfig { Identifier = id, Parts = new List<VirtualBlockPart> { xNewPart }, TotalLength = blockCount }; xNewPart.VirtualBlock = xVBlock; xNewPartsList.Add(xNewPart); xGroupHeader.Parts = xNewPartsList.ToArray(); _blocks.Add(id, xVBlock); } using(_openBlocksLock.EnterWriteLock()) { _openBlocks.Add(id, new List<VBlockContentStore>()); } }
private void LoadConfiguration() { using(_configurationLock.EnterWriteLock()) { var xBuff = new byte[_virtualBlockSize]; var xBuffSeg = new ArraySegment<byte>(xBuff); var xNextMetaGroupBlock = 0UL; do { RetrieveVirtualBlock(xNextMetaGroupBlock, xBuffSeg); var xMetaGroupHeader = new MetaGroupHeader { BlockId = xNextMetaGroupBlock }; var xStartOffset = 0; if (xNextMetaGroupBlock == 0) { xStartOffset = 8; } xNextMetaGroupBlock = ByteConverter.ReadUInt64(xBuff, xStartOffset); xStartOffset = 32; var xParts = new List<VirtualBlockPart>((int)_metaGroupItemsPerVirtualBlock); for (uint i = 0; i < _metaGroupItemsPerVirtualBlock; i++) { var xVBlockId = ByteConverter.ReadGuid(xBuff, xStartOffset); if (xVBlockId != Guid.Empty) { var xVBlockPart = new VirtualBlockPart { TotalPartCount = ByteConverter.ReadUInt16(xBuff, xStartOffset + 16), PartIndex = ByteConverter.ReadUInt16(xBuff, xStartOffset + 18), FirstDataBlockNumber = ByteConverter.ReadUInt64(xBuff, xStartOffset + 20), BlockCount = ByteConverter.ReadUInt32(xBuff, xStartOffset + 28) }; VirtualBlockConfig xBlockConfig; if(!_blocks.TryGetValue(xVBlockId, out xBlockConfig)) { xBlockConfig = new VirtualBlockConfig(); xBlockConfig.Identifier = xVBlockId; xBlockConfig.Parts=new List<VirtualBlockPart>(4); _blocks.Add(xVBlockId, xBlockConfig); } xBlockConfig.Parts.Add(xVBlockPart); } xStartOffset += 32; } xMetaGroupHeader.Parts = xParts.ToArray(); _metaHeaders.Add(xMetaGroupHeader); } while (xNextMetaGroupBlock != 0); if (_blocks.Count > 0) { using (_openBlocksLock.EnterWriteLock()) { foreach (var xItem in _blocks) { xItem.Value.TotalLength = (from item in xItem.Value.Parts select (ulong)item.BlockCount).Sum(); _openBlocks.Add(xItem.Key, new List<VBlockContentStore>()); } } } } }