コード例 #1
0
        public static BTreePage ReadFromStream(Stream stream, BlockRef blockRef)
        {
            long offset = (long)blockRef.ib;

            stream.Seek(offset, SeekOrigin.Begin);
            byte[] buffer = new byte[Length];
            stream.Read(buffer, 0, Length);
            PageTypeName ptype = (PageTypeName)buffer[PageTrailer.OffsetFromPageStart + 0];
            BTreePage    page;
            byte         cLevel = buffer[491];

            if (cLevel > 0)
            {
                // If cLevel is greater than 0, then each entry in the array is of type BTENTRY.
                page = new BTreeIndexPage(buffer);
            }
            else
            {
                // If cLevel is 0, then each entry is either of type BBTENTRY or NBTENTRY, depending on the ptype of the page.
                if (ptype == PageTypeName.ptypeBBT)
                {
                    page = new BlockBTreeLeafPage(buffer);
                }
                else if (ptype == PageTypeName.ptypeNBT)
                {
                    page = new NodeBTreeLeafPage(buffer);
                }
                else
                {
                    throw new ArgumentException("BTreePage has incorrect ptype");
                }
            }
            page.Offset = (ulong)blockRef.ib;
            if (blockRef.bid.Value != page.BlockID.Value)
            {
                throw new InvalidBlockIDException();
            }
            uint crc = PSTCRCCalculation.ComputeCRC(buffer, PageTrailer.OffsetFromPageStart);

            if (page.pageTrailer.dwCRC != crc)
            {
                throw new InvalidChecksumException();
            }

            uint signature = BlockTrailer.ComputeSignature(blockRef.ib, blockRef.bid.Value);

            if (page.pageTrailer.wSig != signature)
            {
                throw new InvalidChecksumException();
            }
            return(page);
        }
コード例 #2
0
ファイル: BTree.cs プロジェクト: wang-xinhong/PSTFileFormat
        public void CreateNewRoot()
        {
            BTreeIndexPage newRoot = BTreeIndexPage.GetEmptyIndexPage(m_bTreeRootPage.pageTrailer.ptype, m_bTreeRootPage.cLevel + 1);

            BTreeIndexEntry rootIndexEntry = new BTreeIndexEntry();

            // We make sure the old root page has been updated (to prevent the BlockID from changing during update)
            UpdatePage(m_bTreeRootPage);

            rootIndexEntry.btkey    = m_bTreeRootPage.PageKey;
            rootIndexEntry.BREF.bid = m_bTreeRootPage.BlockID;
            rootIndexEntry.BREF.ib  = 0; // this will tell BufferedBTreePageStore that the block hasn't been written yet
            newRoot.IndexEntryList.Add(rootIndexEntry);
            AddPage(newRoot);
            m_bTreeRootPage.ParentPage = newRoot;
            m_bTreeRootPage            = newRoot;
        }
コード例 #3
0
ファイル: BTree.cs プロジェクト: wang-xinhong/PSTFileFormat
 /// <param name="blockID">BlockID of the child page with the new key</param>
 protected void UpdateIndexEntry(BTreeIndexPage indexPage, BlockID blockIDOfChild, ulong newKeyOfChild)
 {
     for (int index = 0; index < indexPage.IndexEntryList.Count; index++)
     {
         BTreeIndexEntry entry = indexPage.IndexEntryList[index];
         if (entry.BREF.bid.Value == blockIDOfChild.Value)
         {
             entry.btkey = newKeyOfChild;
             UpdatePageAndReferences(indexPage); // parents will now refer to the new blockID
             if (index == 0 && indexPage.ParentPage != null)
             {
                 // page key has been modified, we must update the parent as well
                 UpdateIndexEntry(indexPage.ParentPage, indexPage.BlockID, indexPage.PageKey);
             }
         }
     }
 }
コード例 #4
0
ファイル: BTree.cs プロジェクト: wang-xinhong/PSTFileFormat
        private void CascadeUpReferenceUpdate(BTreeIndexPage indexPage, ulong oldBlockID, ulong newBlockID)
        {
            int index = indexPage.GetIndexOfBlockID(oldBlockID);

            if (index >= 0)
            {
                BTreeIndexEntry entry = indexPage.IndexEntryList[index];
                entry.BREF.bid = new BlockID(newBlockID);
                entry.BREF.ib  = 0; // this will tell BufferedBTreePageStore that the block hasn't been written yet
                ulong currentBlockID = indexPage.BlockID.Value;
                UpdatePage(indexPage);
                if (currentBlockID != indexPage.BlockID.Value &&
                    indexPage.ParentPage != null)
                {
                    CascadeUpReferenceUpdate(indexPage.ParentPage, currentBlockID, indexPage.BlockID.Value);
                }
            }
        }
コード例 #5
0
        public BTreeIndexPage Split()
        {
            int            newNodeStartIndex = IndexEntryList.Count / 2;
            BTreeIndexPage newPage           = new BTreeIndexPage();

            // blockID will be given when the page will be added
            newPage.cEntMax           = cEntMax;
            newPage.cbEnt             = cbEnt;
            newPage.cLevel            = cLevel;
            newPage.pageTrailer.ptype = pageTrailer.ptype;
            for (int index = newNodeStartIndex; index < IndexEntryList.Count; index++)
            {
                newPage.IndexEntryList.Add(IndexEntryList[index]);
            }

            IndexEntryList.RemoveRange(newNodeStartIndex, IndexEntryList.Count - newNodeStartIndex);
            return(newPage);
        }
コード例 #6
0
ファイル: BTree.cs プロジェクト: wang-xinhong/PSTFileFormat
        protected void InsertIndexEntry(BTreeIndexPage indexPage, BTreeIndexEntry entryToInsert)
        {
            if (indexPage.IndexEntryList.Count < BTreeIndexPage.MaximumNumberOfEntries)
            {
                int insertIndex = indexPage.InsertSorted(entryToInsert);
                UpdatePageAndReferences(indexPage);
                if (insertIndex == 0 && indexPage.ParentPage != null)
                {
                    // page key has been modified, we must update the parent
                    UpdateIndexEntry(indexPage.ParentPage, indexPage.BlockID, indexPage.PageKey);
                }
            }
            else
            {
                // The tree node is full, we have to split it
                BTreeIndexPage newPage = indexPage.Split();
                if (newPage.PageKey < entryToInsert.btkey)
                {
                    newPage.InsertSorted(entryToInsert);
                }
                else
                {
                    int insertIndex = indexPage.InsertSorted(entryToInsert);
                    if (insertIndex == 0 && indexPage.ParentPage != null)
                    {
                        // page key has been modified, we must update the parent
                        UpdateIndexEntry(indexPage.ParentPage, indexPage.BlockID, indexPage.PageKey);
                    }
                }
                UpdatePageAndReferences(indexPage);
                AddPage(newPage);

                if (indexPage.ParentPage == null)
                {
                    // this is a root page and it's full, we have to create a new root
                    CreateNewRoot();
                }

                // We made sure we have a parent to add our new page to
                InsertIndexEntry(indexPage.ParentPage, newPage.PageKey, newPage.BlockID);
            }
        }