示例#1
0
        public void EndSavingChanges()
        {
            CommitChanges();

            AllocationHelper.ValidateAllocationMap(this);
            m_isSavingChanges = false;
        }
        /// <summary>
        /// The caller must update its reference to point to the new root
        /// </summary>
        public virtual void SaveChanges()
        {
            foreach (ulong blockID in m_blocksToWrite)
            {
                Block block  = m_blockBuffer[blockID];
                long  offset = AllocationHelper.AllocateSpaceForBlock(m_file, block.TotalLength);
                block.WriteToStream(m_file.BaseStream, offset);
                m_file.BlockBTree.InsertBlockEntry(block.BlockID, offset, block.DataLength);
            }

            foreach (ulong blockID in m_blocksToFree)
            {
                BlockBTreeEntry entry = m_file.FindBlockEntryByBlockID(blockID);
                entry.cRef--;
                // Any leaf BBT entry that points to a BID holds a reference count to it.
                if (entry.cRef == 1)
                {
                    // we can mark the allocation to be freed and delete the entry,
                    // We should not free the allocation until the BBT is committed.
                    m_file.MarkAllocationToBeFreed(entry.BREF.ib, Block.GetTotalBlockLength(entry.cb));
                    m_file.BlockBTree.DeleteBlockEntry(entry.BREF.bid);
                }
                else
                {
                    m_file.BlockBTree.UpdateBlockEntry(entry.BREF.bid, entry.cRef);
                }
            }

            m_blocksToWrite.Clear();
            m_blocksToFree.Clear();
        }
示例#3
0
        public void SaveChanges()
        {
            List <BTreePage> pages = new List <BTreePage>();

            foreach (BTreePage page in m_pageBuffer.Values)
            {
                if (m_pagesToWrite.Contains(page.BlockID.Value))
                {
                    pages.Add(page);
                }
            }
            SortByCLevel(pages, false);

            // we now have the pages in ascending cLevel order (i.e. leaves first)
            // we need them this way because we need to update the offset from old pages to new pages
            // so we must write children first

            // for new blocks:
            Dictionary <ulong, long> blockToOffset = new Dictionary <ulong, long>();

            foreach (BTreePage page in pages)
            {
                if (page is BTreeIndexPage) // page.cLevel > 0
                {
                    // parent page, we may need to update references
                    BTreeIndexPage indexPage = (BTreeIndexPage)page;
                    for (int index = 0; index < indexPage.IndexEntryList.Count; index++)
                    {
                        ulong childBlockID = indexPage.IndexEntryList[index].BREF.bid.Value;

                        if (indexPage.IndexEntryList[index].BREF.ib == 0) // reference to a new / updated block
                        {
                            long blockOffset = blockToOffset[childBlockID];
                            indexPage.IndexEntryList[index].BREF.ib = (ulong)blockOffset;
                        }
                    }
                }

                long newPageAllocationOffset = AllocationHelper.AllocateSpaceForPage(m_file);
                blockToOffset.Add(page.BlockID.Value, newPageAllocationOffset);
                page.Offset = (ulong)newPageAllocationOffset; // we may need this later
                byte[] pageBytes = page.GetBytes((ulong)newPageAllocationOffset);
                m_file.BaseStream.Seek(newPageAllocationOffset, SeekOrigin.Begin);
                m_file.BaseStream.Write(pageBytes, 0, pageBytes.Length);
            }

            // free all the marked pages
            foreach (ulong offset in m_offsetsToFree)
            {
                AllocationHelper.FreePageAllocation(m_file, (long)offset);
            }

            m_pagesToWrite.Clear();
            m_offsetsToFree.Clear();
        }
示例#4
0
        public void BeginSavingChanges()
        {
            if (!Header.root.IsAllocationMapValid)
            {
                throw new InvalidAllocationMapException();
            }

            // We want to make sure outlook will rebuild the allocation map if the operation does not complete successfully
            AllocationHelper.InvalidateAllocationMap(this);
            m_isSavingChanges = true;
        }
示例#5
0
        public void CommitChanges()
        {
            // We must save changes to the SMQ before committing the BBT / NBT
            if (m_searchManagementQueue != null)
            {
                m_searchManagementQueue.SaveChanges();
            }

            this.BlockBTree.SaveChanges();
            this.NodeBTree.SaveChanges();

            // Only after we saved changes to the BBT, we may free blocks,
            // this is to prevent blocks that are referenced by the BBT to be freed prematurely (before changes are committed)
            foreach (KeyValuePair <ulong, int> offsetToFree in m_offsetsToFree)
            {
                ulong offset = offsetToFree.Key;
                int   length = offsetToFree.Value;
                AllocationHelper.FreeAllocation(this, (long)offset, length);
            }
            m_offsetsToFree.Clear();

            UpdateBlockBTreeRootReference();
            UpdateNodeBTreeRootReference();
        }