示例#1
0
        // Perform a lookup in the b-tree
        private static TreeNode LookupTreeNode(TreeIntermediate parent, UInt64 key, Action <TreeIntermediate> readDeferred)
        {
            if (parent.ReadDeferred)
            {
                if (readDeferred != null)
                {
                    readDeferred(parent);
                }
                else
                {
                    throw new Exception("Deferred index found, but no reader supplied");
                }
            }

            TreeIntermediate next = null;

            foreach (var n in parent.Children)
            {
                if (key > n.Key)
                {
                    next = n as TreeIntermediate;
                }
                else if (key < n.Key)
                {
                    if (next != null)
                    {
                        return(LookupTreeNode(next, key, readDeferred));
                    }
                    else
                    {
                        return(null); // Key does not exist
                    }
                }
                else // key matches
                {
                    if (n is TreeIntermediate)
                    {
                        return(LookupTreeNode((TreeIntermediate)n, key, readDeferred));
                    }
                    else
                    {
                        return(n);
                    }
                }
            }
            if (next != null)
            {
                return(LookupTreeNode(next, key, readDeferred));
            }
            else
            {
                return(null); // Key does not exist
            }
        }
示例#2
0
        // When a data block has a subnode, it can be a simple node, or a two-level tree
        // This reads a sub node and builds suitable data structures, so that we can later access data held in it
        private void ReadSubNodeBtreeUnicode(FileStream fs, UInt64 subDataBid, TreeIntermediate parent)
        {
            var rb = LookupDataBlock(subDataBid);

            if (rb == null)
            {
                throw new XstException("SubNode data block does not exist");
            }

            int read;

            byte[] buffer = ReadAndDecompress(fs, rb, out read);
            var    sl     = Map.MapType <SLBLOCKUnicode>(buffer);

            if (sl.cLevel > 0)
            {
                var rgbid = Map.MapArray <SIENTRYUnicode>(buffer, Marshal.SizeOf(typeof(SLBLOCKUnicode)), sl.cEnt);

                foreach (var sie in rgbid)
                {
                    var inter = new TreeIntermediate {
                        Key = (sie.nid & 0xffffffff)
                    };
                    parent.Children.Add(inter);

                    // Read child nodes in tree
                    ReadSubNodeBtreeUnicode(fs, sie.bid, inter);
                }
            }
            else
            {
                var rgbid = Map.MapArray <SLENTRYUnicode>(buffer, Marshal.SizeOf(typeof(SLBLOCKUnicode)), sl.cEnt);

                foreach (var sle in rgbid)
                {
                    // Only use low order dword of nid
                    var nb = new Node {
                        Key = (sle.nid & 0xffffffff), DataBid = sle.bidData, SubDataBid = sle.bidSub
                    };
                    parent.Children.Add(nb);
                }
            }
        }
示例#3
0
        // A callback to be used when searching a tree to read part of the index whose loading has been deferred
        private void ReadDeferredIndex(TreeIntermediate inter)
        {
            using (var fs = GetReadStream())
            {
                if (IsUnicode4K)
                {
                    ReadBTPageUnicode4K(fs, (ulong)inter.fileOffset, inter);
                }
                else if (IsUnicode)
                {
                    ReadBTPageUnicode(fs, (ulong)inter.fileOffset, inter);
                }
                else
                {
                    ReadBTPageANSI(fs, (ulong)inter.fileOffset, inter);
                }

                // Don't read it again
                inter.fileOffset = null;
            }
        }
示例#4
0
        private void ReadBTPageANSI(FileStream fs, ulong fileOffset, TreeIntermediate parent)
        {
            fs.Seek((long)fileOffset, SeekOrigin.Begin);
            var p = Map.ReadType <BTPAGEANSI>(fs);

            // read entries
            for (int i = 0; i < p.cEnt; i++)
            {
                if (p.cLevel > 0)
                {
                    BTENTRYANSI e;
                    unsafe
                    {
                        e = Map.MapType <BTENTRYANSI>(p.rgentries, LayoutsA.BTPAGEEntryBytes, i * p.cbEnt, p.cbEnt);
                    }
                    var inter = new TreeIntermediate {
                        Key = e.btkey
                    };
                    parent.Children.Add(inter);

                    if (deferReadingNodes)
                    {
                        inter.fileOffset = e.BREF.ib;
                    }
                    else
                    {
                        // Read child nodes in tree
                        ReadBTPageANSI(fs, e.BREF.ib, inter);
                        inter.fileOffset = null;
                    }
                }
                else
                {
                    if (p.pageTrailer.ptype == Eptype.ptypeNBT)
                    {
                        unsafe
                        {
                            var e  = Map.MapType <NBTENTRYANSI>(p.rgentries, LayoutsA.BTPAGEEntryBytes, i * p.cbEnt, p.cbEnt);
                            var nb = new Node {
                                Key = e.nid.dwValue, Type = e.nid.nidType, DataBid = e.bidData, SubDataBid = e.bidSub, Parent = e.nidParent
                            };
                            parent.Children.Add(nb);
                        }
                    }
                    else if (p.pageTrailer.ptype == Eptype.ptypeBBT)
                    {
                        unsafe
                        {
                            var e = Map.MapType <BBTENTRYANSI>(p.rgentries, LayoutsA.BTPAGEEntryBytes, i * p.cbEnt, p.cbEnt);
                            parent.Children.Add(new DataRef {
                                Key = e.BREF.bid, Offset = e.BREF.ib, Length = e.cb
                            });
                        }
                    }
                    else
                    {
                        throw new XstException("Unexpected page entry type");
                    }
                }
            }
        }