Example #1
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);
        }
Example #2
0
        public byte[] this[byte[] key]
        {
            get
            {
                byte[] value;
                if (TryGetValue(key, out value))
                {
                    return(value);
                }
                throw new KeyNotFoundException();
            }

            set
            {
                IndexEntry oldEntry;
                IndexNode  node;
                _rootNode.TotalSpaceAvailable = _rootNode.CalcSize() +
                                                _file.MftRecordFreeSpace(AttributeType.IndexRoot, _name);
                if (_rootNode.TryFindEntry(key, out oldEntry, out node))
                {
                    node.UpdateEntry(key, value);
                }
                else
                {
                    _rootNode.AddEntry(key, value);
                }
            }
        }
Example #3
0
        /// <summary>
        /// Only valid on non-root nodes, this method divides the node in two,
        /// adding the new node to the current parent.
        /// </summary>
        private void Divide()
        {
            int        midEntryIdx = _entries.Count / 2;
            IndexEntry midEntry    = _entries[midEntryIdx];

            // The terminating entry (aka end) for the new node
            IndexEntry newTerm = new IndexEntry(_index.IsFileIndex);

            newTerm.Flags |= IndexEntryFlags.End;

            // The set of entries in the new node
            List <IndexEntry> newEntries = new List <IndexEntry>(midEntryIdx + 1);

            for (int i = 0; i < midEntryIdx; ++i)
            {
                newEntries.Add(_entries[i]);
            }
            newEntries.Add(newTerm);

            // Copy the node pointer from the elected 'mid' entry to the new node
            if ((midEntry.Flags & IndexEntryFlags.Node) != 0)
            {
                newTerm.ChildrenVirtualCluster = midEntry.ChildrenVirtualCluster;
                newTerm.Flags |= IndexEntryFlags.Node;
            }

            // Set the new entries into the new node
            IndexBlock newBlock = _index.AllocateBlock(_parent, midEntry);

            newBlock.Node.SetEntries(newEntries, 0, newEntries.Count);

            // All of the nodes that used to be referenced by an entry that's just gone
            // into the new block, need to have their parent references updated to point
            // to the new block.
            foreach (var entry in newEntries)
            {
                if ((entry.Flags & IndexEntryFlags.Node) != 0)
                {
                    IndexBlock block = _index.GetSubBlockIfCached(entry);
                    if (block != null)
                    {
                        block.Node._parent = newBlock.Node;
                    }
                }
            }

            // Forget about the entries moved into the new node, and the entry about
            // to be promoted as the new node's pointer
            _entries.RemoveRange(0, midEntryIdx + 1);

            // Promote the old mid entry
            _parent.AddEntry(midEntry, true);
        }