public KeyValuePair <IndexNode[], int> GetMappedAncestors(int[] instanceNdxs, int maxLevel, out string error, ReferenceType refType = ReferenceType.Ancestors | ReferenceType.All)
        {
            error = null;
            try
            {
                IndexNode[] lst = new IndexNode[instanceNdxs.Length];

                int level = 0;

                int totalCount        = instanceNdxs.Length;
                Queue <IndexNode> que = new Queue <IndexNode>(instanceNdxs.Length);

                var offAccessor = GetMapReader((ReferenceType.Ancestors & refType) != 0 ? RefFile.BwdOffsets : RefFile.FwdOffsets);
                var refAccessor = GetMapReader((ReferenceType.Ancestors & refType) != 0 ? RefFile.BwdRefs : RefFile.FwdRefs);
                for (int i = 0, icnt = instanceNdxs.Length; i < icnt; ++i)
                {
                    int ndx = instanceNdxs[i];
                    (long offset, int count) = GetRefOffsetAndCount(offAccessor, ndx);
                    totalCount += count;
                    if (count == 0)
                    {
                        lst[i] = new IndexNode(ndx, level);
                        continue;
                    }
                    IndexNode[] refs = ReadReferences(refAccessor, offset, count, level + 1, que);
                    lst[i] = new IndexNode(ndx, level, refs);
                }
                ++level;
                if (maxLevel <= level)
                {
                    return(new KeyValuePair <IndexNode[], int>(lst, totalCount));
                }

                while (que.Count > 0)
                {
                    var node = que.Dequeue();
                    if (node.Level >= maxLevel)
                    {
                        continue;
                    }
                    int ndx = node.Index;
                    Debug.Assert(!node.HasReferences());
                    (long offset, int count) = GetRefOffsetAndCount(offAccessor, ndx);
                    totalCount += count;
                    if (count == 0)
                    {
                        continue;
                    }
                    IndexNode[] refs = ReadReferences(refAccessor, offset, count, node.Level + 1, que);
                    node.AddNodes(refs);
                }

                return(new KeyValuePair <IndexNode[], int>(lst, totalCount));
            }
            catch (Exception ex)
            {
                error = Utils.GetExceptionErrorString(ex);
                return(new KeyValuePair <IndexNode[], int>(null, 0));;
            }
        }
        public KeyValuePair <IndexNode, int> GetAncestors(int instanceNdx, int maxLevel, out string error, ReferenceType refType = ReferenceType.Ancestors | ReferenceType.All)
        {
            error = null;
            try
            {
                int level = 0;

                Queue <IndexNode> que = new Queue <IndexNode>(128);

                long[]       offsets = GetOffsets((ReferenceType.Ancestors & refType) != 0 ? RefFile.BwdOffsets : RefFile.FwdOffsets);
                BinaryReader br      = GetReader((ReferenceType.Ancestors & refType) != 0 ? RefFile.BwdRefs : RefFile.FwdRefs);
                long         offset  = offsets[instanceNdx];
                int          count   = ReferenceCount(offset, offsets[instanceNdx + 1]);
                if (count == 0)
                {
                    return(new KeyValuePair <IndexNode, int>(new IndexNode(instanceNdx, level), 1));
                }
                int           totalCount = count + 1;
                IndexNode[]   refs       = ReadReferences(br, offset, count, level + 1, que);
                var           rootNode   = new IndexNode(instanceNdx, level, refs);
                HashSet <int> set        = new HashSet <int>();
                set.Add(rootNode.Index);
                while (que.Count > 0)
                {
                    var node = que.Dequeue();
                    if (node.Level >= maxLevel)
                    {
                        continue;
                    }
                    if (!set.Add(node.Index))
                    {
                        continue;
                    }
                    int ndx = node.Index;
                    Debug.Assert(!node.HasReferences());
                    offset = offsets[ndx];
                    count  = ReferenceCount(offset, offsets[ndx + 1]);
                    if (count == 0)
                    {
                        continue;
                    }
                    totalCount += count;
                    refs        = ReadReferences(br, offset, count, node.Level + 1, que);
                    node.AddNodes(refs);
                }

                return(new KeyValuePair <IndexNode, int>(rootNode, totalCount));
            }
            catch (Exception ex)
            {
                error = Utils.GetExceptionErrorString(ex);
                return(new KeyValuePair <IndexNode, int>(null, 0));;
            }
        }
 private IndexNode[] ReadReferences(BinaryReader br, long offset, int count, int level, Queue <IndexNode> que)
 {
     IndexNode[] refs = new IndexNode[count];
     br.BaseStream.Seek(offset, SeekOrigin.Begin);
     for (int i = 0, icnt = count; i < icnt; ++i)
     {
         var ndx  = br.ReadInt32();
         var node = new IndexNode(ndx, level);
         refs[i] = node;
         que.Enqueue(node);
     }
     return(refs);
 }
 private IndexNode[] ReadReferences(MemoryMappedViewAccessor va, long offset, int count, int level, Queue <IndexNode> que)
 {
     IndexNode[] refs = new IndexNode[count];
     int[]       ndxs = new int[count];
     va.ReadArray <int>(offset, ndxs, 0, count);
     for (int i = 0, icnt = count; i < icnt; ++i)
     {
         var ndx  = ndxs[i];
         var node = new IndexNode(ndx, level);
         refs[i] = node;
         que.Enqueue(node);
     }
     return(refs);
 }
        public KeyValuePair <IndexNode, int>[] GetMappedReferenceNodes(int[] addrNdxs, int maxLevel, out string error, ReferenceType refType = ReferenceType.Ancestors | ReferenceType.All)
        {
            error = null;
            try
            {
                var results     = new List <KeyValuePair <IndexNode, int> >(addrNdxs.Length);
                var uniqueSet   = new HashSet <int>();
                var que         = new Queue <IndexNode>(256);
                var offAccessor = GetMapReader((ReferenceType.Ancestors & refType) != 0 ? RefFile.BwdOffsets : RefFile.FwdOffsets);
                var refAccessor = GetMapReader((ReferenceType.Ancestors & refType) != 0 ? RefFile.BwdRefs : RefFile.FwdRefs);
                for (int ndx = 0, ndxCnt = addrNdxs.Length; ndx < ndxCnt; ++ndx)
                {
                    uniqueSet.Clear();
                    que.Clear();
                    var addrNdx  = addrNdxs[ndx];
                    var rootNode = new IndexNode(addrNdx, 0); // we at level 0
                    que.Enqueue(rootNode);
                    uniqueSet.Add(addrNdx);
                    int nodeCount = 0; // do not count root node
                    while (que.Count > 0)
                    {
                        var curNode = que.Dequeue();
                        ++nodeCount;
                        if (curNode.Level >= maxLevel || nodeCount > MaxNodes)
                        {
                            continue;
                        }
                        int curndx = curNode.Index;

                        (long offset, int count) = GetRefOffsetAndCount(offAccessor, curndx);
                        if (count == 0)
                        {
                            continue;
                        }

                        var nodes = new IndexNode[count];
                        curNode.AddNodes(nodes);
                        var refs = ReadReferences(refAccessor, offset, count);
                        for (int i = 0; i < count; ++i)
                        {
                            var rNdx  = refs[i];
                            var cnode = new IndexNode(rNdx, curNode.Level + 1);
                            nodes[i] = cnode;
                            if (!uniqueSet.Add(rNdx))
                            {
                                ++nodeCount;
                                continue;
                            }
                            que.Enqueue(cnode);
                        }
                    }
                    results.Add(new KeyValuePair <IndexNode, int>(rootNode, nodeCount));
                }
                return(results.ToArray());
            }
            catch (Exception ex)
            {
                error = Utils.GetExceptionErrorString(ex);
                return(null);
            }
        }