/// <summary> /// Remove Block from the Collection. /// NOTE: this is used by BTreeAlgorithm when deleting a node's and/or /// a node's item's data block(s) on disk. /// </summary> public bool Remove(Algorithm.Collection.ICollectionOnDisk parent, Sop.DataBlock block, bool clearBlock = true) { if (!parent.File.Server.HasTrashBin) { return(false); } // remove block and linked blocks from MRU Sop.DataBlock d = block; long contiguousBlockStartAddress = -1; long currentBlockAddress = -1; int contiguousBlockCount = 0; var deletedBlocks = ((CollectionOnDisk)parent).DeletedBlocks; IDictionary <long, Sop.DataBlock> blocks = ((CollectionOnDisk)parent).Blocks; if (!d.IsFolded) { d.Fold(); } if (d.IsFolded) { if (clearBlock && d.SizeOccupied > 0) { d.SizeOccupied = 0; } foreach (var segment in d.foldedDataAddresses) { if (deletedBlocks != null) { RegisterRemovedBlock((CollectionOnDisk)parent, segment.Address, segment.BlockCount * (int)parent.DataBlockSize); // add removed block to the recycle Store for reuse later on Add operation deletedBlocks.AddAvailableBlock(segment.Address, segment.BlockCount * (int)parent.DataBlockSize); } } } else { #region Legacy code for removing unfolded Blocks do { if (d.DataAddress >= 0) { blocks.Remove(d.DataAddress); } if (currentBlockAddress >= 0 && currentBlockAddress + (int)parent.DataBlockSize == d.DataAddress) { // if current block is part of a single contiguous block contiguousBlockCount++; currentBlockAddress = d.DataAddress; } else { if (currentBlockAddress != -1) { // recycle segment if (deletedBlocks != null) { RegisterRemovedBlock((CollectionOnDisk)parent, contiguousBlockStartAddress, contiguousBlockCount * (int)parent.DataBlockSize); // add removed block to the recycle Store for reuse later on Add operation deletedBlocks.AddAvailableBlock(contiguousBlockStartAddress, contiguousBlockCount * (int)parent.DataBlockSize); } } currentBlockAddress = d.DataAddress; contiguousBlockStartAddress = d.DataAddress; contiguousBlockCount = 1; } // clear block's data if (clearBlock && d.SizeOccupied > 0) { d.SizeOccupied = 0; } if (d.Next == null && d.NextItemAddress >= 0) { //load the next datablock to get its next block address... d.Next = ReadBlockFromDisk(parent, parent.FileStream.Position, true, true, CreateBlock(parent.DataBlockSize)); } d = d.Next; } while (d != null); // add to deleted blocks store any deleted block haven't added yet if (contiguousBlockStartAddress != -1) { if (deletedBlocks != null) { RegisterRemovedBlock((CollectionOnDisk)parent, contiguousBlockStartAddress, contiguousBlockCount * (int)parent.DataBlockSize); // add removed block to the recycle Store for reuse later on Add operation deletedBlocks.AddAvailableBlock(contiguousBlockStartAddress, contiguousBlockCount * (int)parent.DataBlockSize); } } #endregion } parent.RegisterChange(true); return(true); }