protected override long GetWritePositionLocked(OperationHint hint, int length) { var contentHint = hint as OptimizedOperation ?? throw new ArgumentException(nameof(hint)); var retv = -1L; lock (_blocksLockObject) { if (!TryGetAvailableBlock(length, out var block)) { retv = CurrentPosition; } else { contentHint.IsExistingBlockUsed = true; retv = block.Position; if (block.Length <= length) { return(retv); } var generatedBlock = new DriveBlock { Length = block.Length - length, Position = block.Position + length }; AddAvailableBlock(generatedBlock); contentHint.GeneratedAvailableBlock = generatedBlock; } } return(retv); }
public IEnumerable <DriveBlock> AllocateSpace(int dataLength) { lock (_allocateLock) { var dataLeft = dataLength; while (dataLeft > 0) { if (!TryGetAvailableBlock(dataLength, out var block)) { CurrentPosition = InitialPosition + Length; block = new DriveBlock { Length = dataLength, Position = CurrentPosition }; CurrentPosition += block.Length; Length += block.Length; } yield return(block); dataLeft -= block.Length; } } }
public void RemoveAvailableBlock(DriveBlock block) { lock (_blocksLockObject) { var queue = _availableBlocks[block.Length]; var list = queue.ToList(); list.Remove(block); if (!list.Any()) { _availableBlocks.Remove(block.Length); return; } _availableBlocks[block.Length] = new Queue <DriveBlock>(list); } }
protected override bool HandleAddedAvailableBlock(DriveBlock block) { //min entry length = 42 if (block.Length < 42) { return(false); } var blockLengthBytes = BitConverter.GetBytes(block.Length); var bytesList = new List <byte>(blockLengthBytes) { (byte)ServiceMarks.Proceed }; var operation = new FileTableOperation(drive => drive.Write(block.Position, bytesList.ToArray()), block.Position); Synchronizer.EnqueueOperation(operation); return(true); }
public void AddAvailableBlock(DriveBlock block) { if (block == null) { throw new ArgumentNullException(nameof(block)); } if (!HandleAddedAvailableBlock(block)) { return; } lock (_blocksLockObject) { if (!_availableBlocks.ContainsKey(block.Length)) { _availableBlocks[block.Length] = new Queue <DriveBlock>(); } _availableBlocks[block.Length].Enqueue(block); } }
protected virtual bool TryGetAvailableBlock(int length, out DriveBlock block) { lock (_blocksLockObject) { block = null; if (!_availableBlocks.TryGetValue(length, out var queue) || _availableBlocks.Keys.All(x => x < length)) { return(false); } if (queue == null) { var key = _availableBlocks.Keys.FirstOrDefault(x => x > length); queue = _availableBlocks[key]; } block = queue.Dequeue(); if (block.Length > length) { var generatedBlock = new DriveBlock { Length = block.Length - length, Position = block.Position + length }; AddAvailableBlock(generatedBlock); } if (!queue.Any()) { _availableBlocks.Remove(length); } return(true); } }
protected virtual bool HandleAddedAvailableBlock(DriveBlock block) { return(true); }
protected override bool TryGetAvailableBlock(int length, out DriveBlock block) { return(base.TryGetAvailableBlock(length, out block) && block.Length >= 42); }
public DriveBlock(DriveBlock block) { Position = block.Position; Length = block.Length; }