/// <summary> /// Delete the Collection for recycling /// </summary> public void Delete(Algorithm.Collection.ICollectionOnDisk parent) { if (HeaderData != null && HeaderData.OccupiedBlocksHead != null) { //** add deleted collection start and end block info to the deleted blocks collection of the File var dbi = new DeletedBlockInfo { StartBlockAddress = HeaderData.OccupiedBlocksHead.DataAddress, EndBlockAddress = HeaderData.EndAllocatableAddress }; bool oc = false; if (parent.File.DeletedCollections != null) { oc = ((Algorithm.BTree.IBTreeAlgorithm)parent.File.DeletedCollections).ChangeRegistry; ((Algorithm.BTree.IBTreeAlgorithm)parent.File.DeletedCollections).ChangeRegistry = ((Algorithm.BTree.IBTreeAlgorithm)parent).ChangeRegistry; parent.File.DeletedCollections.Add(dbi); } //** Reset count to 0 and save the header to disk HeaderData.Count = 0; if (!parent.IsTransactionStore) { parent.RegisterChange(true); } if (parent.File.DeletedCollections != null) { ((Algorithm.BTree.IBTreeAlgorithm)parent.File.DeletedCollections).ChangeRegistry = oc; } HeaderData.Clear(); } }
/// <summary> /// Remove Block from the Collection /// </summary> public void Remove(Algorithm.Collection.ICollectionOnDisk parent, Sop.DataBlock block, bool clearBlock = true) { if (!parent.File.Server.HasTrashBin) { return; } //** 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; 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) { 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) { deletedBlocks.AddAvailableBlock(contiguousBlockStartAddress, contiguousBlockCount * (int)parent.DataBlockSize); } } parent.RegisterChange(true); }
/// <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); }