Beispiel #1
0
        /// <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();
            }
        }
Beispiel #2
0
        public object Clone()
        {
            DeletedBlockInfo r = new DeletedBlockInfo();

            r.Count             = Count;
            r.StartBlockAddress = StartBlockAddress;
            r.IsDirty           = IsDirty;
            r.HintSizeOnDisk    = HintSizeOnDisk;
            r.EndBlockAddress   = EndBlockAddress;
            if (DiskBuffer != null)
            {
                r.DiskBuffer = (Sop.DataBlock)DiskBuffer.Clone();
            }
            return(r);
        }
Beispiel #3
0
        internal bool ResurfaceDeletedBlockNextSegment(CollectionOnDisk parent,
                                                       DeletedBlockInfo dbi, long segmentEnd)
        {
            //** read next segment of deleted collection
            Sop.DataBlock db      = CreateBlock(parent.DataBlockSize);
            long          address = segmentEnd - (int)parent.DataBlockSize;

            db = ReadBlockFromDisk(parent, address, true, true, db);
            if (db.InternalNextBlockAddress >= 0)
            {
                dbi.StartBlockAddress = db.InternalNextBlockAddress;
                if (parent.File.DeletedCollections != null)
                {
                    parent.File.DeletedCollections.SetTop(dbi);
                }
                return(true);
            }
            return(false);
        }
Beispiel #4
0
        /// <summary>
        /// Allocate next available block on disk.
        /// Returns true if all blocks had been allocated, false otherwise.
        /// </summary>
        /// <param name="parent"></param>
        /// <param name="block"></param>
        /// <param name="isHead"></param>
        /// <param name="isCollectionBlock"></param>
        /// <param name="addToMru"> </param>
        /// <returns></returns>
        private bool AllocateNextBlock(Algorithm.Collection.ICollectionOnDisk parent, Sop.DataBlock block,
                                       bool isHead, bool isCollectionBlock, bool addToMru)
        {
            bool       isBlockLocallyRecycled = false;
            HeaderData hd = HeaderData;

            if (hd == null && parent.Parent is CollectionOnDisk)
            {
                hd = ((CollectionOnDisk)parent.Parent).HeaderData;
            }

            bool willRecycle = hd != null && hd.RecycledSegment != null && hd.RecycledSegment.Count > 0;

            if (!willRecycle && hd.NextAllocatableAddress + block.Length <= hd.EndAllocatableAddress)
            {
                AllocateAvailableBlock((CollectionOnDisk)parent, hd, block);
            }
            else
            {
                if (parent.File.Server.HasTrashBin && !willRecycle)
                {
                    if (isCollectionBlock)
                    {
                        willRecycle = parent.File.DeletedCollections != null &&
                                      parent.File.DeletedCollections.Count > 0;
                    }
                    //** prioritize block recycling if there are plenty of deleted blocks
                    if (!willRecycle && ((CollectionOnDisk)parent).DeletedBlocks != null)
                    {
                        willRecycle = ((CollectionOnDisk)parent).DeletedBlocks.Count > 0 ||
                                      parent.File.DeletedCollections.Count > 0;
                    }
                    if (!willRecycle && isHead)
                    {
                        willRecycle = parent.File.DeletedCollections != null &&
                                      parent.File.DeletedCollections.Count > 0;
                    }
                }

                DeletedBlockInfo dbi = null;

                if (willRecycle)
                {
                    int  totalBlockSize;
                    bool fromCollection;
                    if (isCollectionBlock)
                    {
                        if (parent.File.DeletedCollections != null && parent.File.DeletedCollections.Count > 0)
                        {
                            dbi = RecycleBlock(parent, block, true, out totalBlockSize, out fromCollection);
                        }
                    }
                    if (
                        dbi != null ||
                        ((((CollectionOnDisk)parent).DeletedBlocksCount) > 0 &&
                         (dbi =
                              RecycleBlock(parent, block, isCollectionBlock, out totalBlockSize, out fromCollection)) !=
                         null)
                        )
                    {
                        #region Recycle Deleted Block
                        if (dbi.IsContiguousBlock)
                        {
                            #region Contiguous blocks can only be from Collection.DeletedBlocks
                            if (block.DataAddress == -1)
                            {
                                long          address     = dbi.StartBlockAddress;
                                Sop.DataBlock db          = block;
                                int           blockLength = (int)parent.DataBlockSize;
                                while (db != null)
                                {
                                    dbi.Count--;
                                    db.DataAddress = address;
                                    address       += blockLength;
                                    db             = db.Next;
                                }
                            }
                            isBlockLocallyRecycled = true;
                            #endregion
                        }
                        else
                        {
                            #region Recycled block is from a deleted collection of the File
                            int growthSizeInNob = parent.File.StoreGrowthSizeInNob;
                            block.DataAddress          = dbi.StartBlockAddress;
                            hd.StartAllocatableAddress = dbi.StartBlockAddress;
                            hd.EndAllocatableAddress   = hd.StartAllocatableAddress +
                                                         (short)parent.File.DataBlockSize * growthSizeInNob;

                            Log.Logger.Instance.Log(Log.LogLevels.Verbose,
                                                    "Recycled region {0}, Size {1} from {2} DeletedCollections",
                                                    dbi.StartBlockAddress, hd.EndAllocatableAddress - hd.StartAllocatableAddress,
                                                    parent.File.Filename);

                            if (parent.Transaction != null)
                            {
                                ((Transaction.TransactionBase)parent.Transaction).Register(
                                    Sop.Transaction.ActionType.RecycleCollection,
                                    (CollectionOnDisk)parent, dbi.StartBlockAddress,
                                    hd.EndAllocatableAddress - hd.StartAllocatableAddress);
                            }

                            if (dbi.EndBlockAddress == hd.EndAllocatableAddress)
                            {
                                if (parent.File.DeletedCollections != null)
                                {
                                    parent.File.DeletedCollections.RemoveTop();
                                }
                            }
                            else
                            {
                                //** read next segment of deleted collection
                                if (
                                    !ResurfaceDeletedBlockNextSegment((CollectionOnDisk)parent, dbi,
                                                                      hd.EndAllocatableAddress))
                                {
                                    if (parent.File.DeletedCollections != null)
                                    {
                                        parent.File.DeletedCollections.Remove(dbi.StartBlockAddress);
                                    }
                                }
                            }
                            hd.NextAllocatableAddress  = hd.StartAllocatableAddress + block.Length;
                            hd.DiskBuffer.IsDirty      = true;
                            hd.IsModifiedInTransaction = true;
                            #endregion
                        }
                        #endregion
                    }
                }
                if (dbi == null)
                {
                    if (hd.NextAllocatableAddress + block.Length <= hd.EndAllocatableAddress)
                    {
                        AllocateAvailableBlock((CollectionOnDisk)parent, hd, block);
                    }
                    else
                    {
                        AllocateOnNextSegment((CollectionOnDisk)parent, hd, block);
                    }
                }
            }

            #region Add Block to MRU

            if (hd.OccupiedBlocksHead == null)
            {
                hd.OccupiedBlocksHead             = CreateBlock((DataBlockSize)block.Length);
                hd.OccupiedBlocksHead.DataAddress = block.DataAddress;
                if (hd.OccupiedBlocksTail == null)
                {
                    hd.OccupiedBlocksTail = CreateBlock((DataBlockSize)block.Length);
                }
            }
            else if (isBlockLocallyRecycled)
            {
                //** reload & update the InternalNextBlockAddress to keep ("low-level") segments' link intact...
                Sop.DataBlock db = block;
                while (db != null)
                {
                    if ((db.DataAddress + (int)parent.DataBlockSize) %
                        (parent.File.Profile.StoreGrowthSizeInNob * (int)parent.DataBlockSize) == 0)
                    {
                        Sop.DataBlock db2 = CreateBlock(parent.DataBlockSize);
                        db2 = ReadBlockFromDisk(parent, db.DataAddress, true, true, db2);
                        db.InternalNextBlockAddress = db2.InternalNextBlockAddress;
                    }
                    db = db.Next;
                }
                //** add to MRU cache if requested...



                return(true);
            }
            else
            {
                if ((hd.OccupiedBlocksTail.DataAddress + (int)parent.DataBlockSize) %
                    (parent.File.Profile.StoreGrowthSizeInNob * (int)parent.DataBlockSize) == 0)
                {
                    Sop.DataBlock db = ReadBlockFromDisk(parent, hd.OccupiedBlocksTail.DataAddress, false);
                    db.InternalNextBlockAddress = block.DataAddress;
                    this.SetDiskAddress(parent, db, addToMru);
                    long dbId = GetId(db);
                    ((CollectionOnDisk)parent).Blocks[dbId] = db;
                }
            }
            hd.OccupiedBlocksTail.DataAddress = block.DataAddress;

            #endregion

            return(false);
        }