Beispiel #1
0
 protected override void Read(byte[] buffer, int offset)
 {
     // Skip FixupRecord fields...
     _logSequenceNumber = Utilities.ToUInt64LittleEndian(buffer, offset + 0x08);
     _indexBlockVcn     = Utilities.ToUInt64LittleEndian(buffer, offset + 0x10);
     _node = new IndexNode(WriteToDisk, UpdateSequenceSize, _index, _isRoot, buffer, offset + FieldSize);
 }
Beispiel #2
0
        /// <summary>
        /// Removes redundant nodes (that contain only an 'End' entry).
        /// </summary>
        /// <param name="entryIndex">The index of the entry that may have a redundant child</param>
        /// <returns>An entry that needs to be promoted to the parent node (if any)</returns>
        private IndexEntry LiftNode(int entryIndex)
        {
            if ((_entries[entryIndex].Flags & IndexEntryFlags.Node) != 0)
            {
                IndexNode childNode = _index.GetSubBlock(_entries[entryIndex]).Node;
                if (childNode._entries.Count == 1)
                {
                    long freeBlock = _entries[entryIndex].ChildrenVirtualCluster;
                    _entries[entryIndex].Flags = (_entries[entryIndex].Flags & ~IndexEntryFlags.Node) | (childNode._entries[0].Flags & IndexEntryFlags.Node);
                    _entries[entryIndex].ChildrenVirtualCluster = childNode._entries[0].ChildrenVirtualCluster;

                    _index.FreeBlock(freeBlock);
                }

                if ((_entries[entryIndex].Flags & (IndexEntryFlags.Node | IndexEntryFlags.End)) == 0)
                {
                    IndexEntry entry = _entries[entryIndex];
                    _entries.RemoveAt(entryIndex);

                    IndexNode nextNode = _index.GetSubBlock(_entries[entryIndex]).Node;
                    return(nextNode.AddEntry(entry));
                }
            }

            return(null);
        }
Beispiel #3
0
        public bool TryFindEntry(byte[] key, out IndexEntry entry, out IndexNode node)
        {
            foreach (var focus in _entries)
            {
                if ((focus.Flags & IndexEntryFlags.End) != 0)
                {
                    if ((focus.Flags & IndexEntryFlags.Node) != 0)
                    {
                        IndexBlock subNode = _index.GetSubBlock(focus);
                        return(subNode.Node.TryFindEntry(key, out entry, out node));
                    }

                    break;
                }
                else
                {
                    int compVal = _index.Compare(key, focus.KeyBuffer);
                    if (compVal == 0)
                    {
                        entry = focus;
                        node  = this;
                        return(true);
                    }
                    else if (compVal < 0 && (focus.Flags & (IndexEntryFlags.End | IndexEntryFlags.Node)) != 0)
                    {
                        IndexBlock subNode = _index.GetSubBlock(focus);
                        return(subNode.Node.TryFindEntry(key, out entry, out node));
                    }
                }
            }

            entry = null;
            node  = null;
            return(false);
        }
Beispiel #4
0
        private IndexBlock(Index index, bool isRoot, long vcn, BiosParameterBlock bpb)
            : base("INDX", bpb.BytesPerSector, bpb.IndexBufferSize)
        {
            _index  = index;
            _isRoot = isRoot;

            _indexBlockVcn = (ulong)vcn;

            _streamPosition = vcn * bpb.BytesPerSector * bpb.SectorsPerCluster;

            _node = new IndexNode(WriteToDisk, UpdateSequenceSize, _index, isRoot, (uint)bpb.IndexBufferSize - FieldSize);

            WriteToDisk();
        }
Beispiel #5
0
        private IEnumerable <IndexEntry> FindAllIn(IComparable <byte[]> query, IndexNode node)
        {
            foreach (var focus in node.Entries)
            {
                bool searchChildren = true;
                bool matches        = false;
                bool keepIterating  = true;

                if ((focus.Flags & IndexEntryFlags.End) == 0)
                {
                    int compVal = query.CompareTo(focus.KeyBuffer);
                    if (compVal == 0)
                    {
                        matches = true;
                    }
                    else if (compVal > 0)
                    {
                        searchChildren = false;
                    }
                    else if (compVal < 0)
                    {
                        keepIterating = false;
                    }
                }

                if (searchChildren && (focus.Flags & IndexEntryFlags.Node) != 0)
                {
                    IndexBlock block = GetSubBlock(focus);
                    foreach (var entry in FindAllIn(query, block.Node))
                    {
                        yield return(entry);
                    }
                }

                if (matches)
                {
                    yield return(focus);
                }

                if (!keepIterating)
                {
                    yield break;
                }
            }
        }
Beispiel #6
0
        protected IEnumerable <IndexEntry> Enumerate(IndexNode node)
        {
            foreach (var focus in node.Entries)
            {
                if ((focus.Flags & IndexEntryFlags.Node) != 0)
                {
                    IndexBlock block = GetSubBlock(focus);
                    foreach (var subEntry in Enumerate(block.Node))
                    {
                        yield return(subEntry);
                    }
                }

                if ((focus.Flags & IndexEntryFlags.End) == 0)
                {
                    yield return(focus);
                }
            }
        }
Beispiel #7
0
        private void NodeAsString(TextWriter writer, string prefix, IndexNode node, string id)
        {
            writer.WriteLine(prefix + id + ":");
            foreach (var entry in node.Entries)
            {
                if ((entry.Flags & IndexEntryFlags.End) != 0)
                {
                    writer.WriteLine(prefix + "      E");
                }
                else
                {
                    writer.WriteLine(prefix + "      " + EntryAsString(entry, _file.BestName, _name));
                }

                if ((entry.Flags & IndexEntryFlags.Node) != 0)
                {
                    NodeAsString(writer, prefix + "        ", GetSubBlock(entry).Node, ":i" + entry.ChildrenVirtualCluster);
                }
            }
        }
Beispiel #8
0
        private Index(AttributeType attrType, AttributeCollationRule collationRule, File file, string name, BiosParameterBlock bpb, UpperCase upCase)
        {
            _file        = file;
            _name        = name;
            _bpb         = bpb;
            _isFileIndex = name == "$I30";

            _blockCache = new ObjectCache <long, IndexBlock>();

            _file.CreateStream(AttributeType.IndexRoot, _name);

            _root = new IndexRoot()
            {
                AttributeType             = (uint)attrType,
                CollationRule             = collationRule,
                IndexAllocationSize       = (uint)bpb.IndexBufferSize,
                RawClustersPerIndexRecord = bpb.RawIndexBufferSize
            };

            _comparer = _root.GetCollator(upCase);

            _rootNode = new IndexNode(WriteRootNodeToDisk, 0, this, true, 32);
        }
Beispiel #9
0
        public bool RemoveEntry(byte[] key, out IndexEntry newParentEntry)
        {
            bool       exactMatch;
            int        entryIndex = GetEntry(key, out exactMatch);
            IndexEntry entry      = _entries[entryIndex];

            if (exactMatch)
            {
                if ((entry.Flags & IndexEntryFlags.Node) != 0)
                {
                    IndexNode  childNode = _index.GetSubBlock(entry).Node;
                    IndexEntry rLeaf     = childNode.FindLargestLeaf();

                    byte[] newKey  = rLeaf.KeyBuffer;
                    byte[] newData = rLeaf.DataBuffer;

                    IndexEntry newEntry;
                    childNode.RemoveEntry(newKey, out newEntry);
                    entry.KeyBuffer  = newKey;
                    entry.DataBuffer = newData;

                    if (newEntry != null)
                    {
                        InsertEntryThisNode(newEntry);
                    }

                    newEntry = LiftNode(entryIndex);
                    if (newEntry != null)
                    {
                        InsertEntryThisNode(newEntry);
                    }

                    newEntry = PopulateEnd();
                    if (newEntry != null)
                    {
                        InsertEntryThisNode(newEntry);
                    }

                    // New entry could be larger than old, so may need
                    // to divide this node...
                    newParentEntry = EnsureNodeSize();
                }
                else
                {
                    _entries.RemoveAt(entryIndex);
                    newParentEntry = null;
                }

                _store();
                return(true);
            }
            else if ((entry.Flags & IndexEntryFlags.Node) != 0)
            {
                IndexNode  childNode = _index.GetSubBlock(entry).Node;
                IndexEntry newEntry;
                if (childNode.RemoveEntry(key, out newEntry))
                {
                    if (newEntry != null)
                    {
                        InsertEntryThisNode(newEntry);
                    }

                    newEntry = LiftNode(entryIndex);
                    if (newEntry != null)
                    {
                        InsertEntryThisNode(newEntry);
                    }

                    newEntry = PopulateEnd();
                    if (newEntry != null)
                    {
                        InsertEntryThisNode(newEntry);
                    }

                    // New entry could be larger than old, so may need
                    // to divide this node...
                    newParentEntry = EnsureNodeSize();

                    _store();
                    return(true);
                }
            }

            newParentEntry = null;
            return(false);
        }