Пример #1
0
        private KeyValuePairList <int, IndexRecord> FindRemovalPath(byte[] key, out int indexOfEntryToRemove)
        {
            bool isParentNode         = true;
            List <IndexEntry> entries = m_rootRecord.IndexEntries;
            KeyValuePairList <int, IndexRecord> path = new KeyValuePairList <int, IndexRecord>();

            while (isParentNode)
            {
                int index = CollationHelper.FindIndexInParentNode(entries, key, m_rootRecord.CollationRule);
                if (!entries[index].IsLastEntry && CollationHelper.Compare(entries[index].Key, key, m_rootRecord.CollationRule) == 0)
                {
                    indexOfEntryToRemove = index;
                    return(path);
                }
                long        subnodeVBN  = entries[index].SubnodeVBN;
                IndexRecord indexRecord = ReadIndexRecord(subnodeVBN);
                isParentNode = indexRecord.IsParentNode;
                entries      = indexRecord.IndexEntries;
                path.Add(index, indexRecord);
            }

            indexOfEntryToRemove = CollationHelper.FindIndexInLeafNode(entries, key, m_rootRecord.CollationRule);
            if (indexOfEntryToRemove >= 0)
            {
                return(path);
            }
            else
            {
                return(null);
            }
        }
Пример #2
0
        public KeyValuePair <MftSegmentReference, byte[]>?FindEntry(byte[] key)
        {
            if (!m_rootRecord.IsParentNode)
            {
                int index = CollationHelper.FindIndexInLeafNode(m_rootRecord.IndexEntries, key, m_rootRecord.CollationRule);
                if (index >= 0)
                {
                    IndexEntry entry = m_rootRecord.IndexEntries[index];
                    return(new KeyValuePair <MftSegmentReference, byte[]>(entry.FileReference, entry.Key));
                }
                else
                {
                    return(null);
                }
            }
            else
            {
                bool isParentNode         = true;
                List <IndexEntry> entries = m_rootRecord.IndexEntries;
                int index;
                while (isParentNode)
                {
                    index = CollationHelper.FindIndexInParentNode(entries, key, m_rootRecord.CollationRule);
                    IndexEntry entry = entries[index];
                    if (!entry.IsLastEntry && CollationHelper.Compare(entry.Key, key, m_rootRecord.CollationRule) == 0)
                    {
                        return(new KeyValuePair <MftSegmentReference, byte[]>(entry.FileReference, entry.Key));
                    }
                    else
                    {
                        long        subnodeVBN  = entry.SubnodeVBN;
                        IndexRecord indexRecord = ReadIndexRecord(subnodeVBN);
                        isParentNode = indexRecord.IsParentNode;
                        entries      = indexRecord.IndexEntries;
                    }
                }

                index = CollationHelper.FindIndexInLeafNode(entries, key, m_rootRecord.CollationRule);
                if (index >= 0)
                {
                    IndexEntry entry = entries[index];
                    return(new KeyValuePair <MftSegmentReference, byte[]>(entry.FileReference, entry.Key));
                }
                else
                {
                    return(null);
                }
            }
        }
Пример #3
0
        private KeyValuePairList <int, IndexRecord> FindInsertPath(byte[] key)
        {
            bool isParentNode         = true;
            List <IndexEntry> entries = m_rootRecord.IndexEntries;
            KeyValuePairList <int, IndexRecord> path = new KeyValuePairList <int, IndexRecord>();

            while (isParentNode)
            {
                int         index       = CollationHelper.FindIndexInParentNode(entries, key, m_rootRecord.CollationRule);
                long        subnodeVBN  = entries[index].SubnodeVBN;
                IndexRecord indexRecord = ReadIndexRecord(subnodeVBN);
                isParentNode = indexRecord.IsParentNode;
                entries      = indexRecord.IndexEntries;
                path.Add(index, indexRecord);
            }
            return(path);
        }
Пример #4
0
        public void AddEntry(MftSegmentReference fileReference, byte[] key)
        {
            IndexEntry entry = new IndexEntry();

            entry.FileReference = fileReference;
            entry.Key           = key;
            if (!m_rootRecord.IsParentNode)
            {
                int insertIndex = CollationHelper.FindIndexForSortedInsert(m_rootRecord.IndexEntries, key, m_rootRecord.CollationRule);
                m_rootRecord.IndexEntries.Insert(insertIndex, entry);
                if (m_rootRecord.RecordLength >= m_volume.AttributeRecordLengthToMakeNonResident)
                {
                    if (m_indexAllocationRecord == null)
                    {
                        m_indexAllocationRecord = (IndexAllocationRecord)m_fileRecord.CreateAttributeRecord(AttributeType.IndexAllocation, m_indexName);
                        m_indexAllocationData   = new NonResidentAttributeData(m_volume, m_fileRecord, m_indexAllocationRecord);
                        m_bitmapRecord          = m_fileRecord.CreateAttributeRecord(AttributeType.Bitmap, m_indexName);
                        m_bitmapData            = new BitmapData(m_volume, m_fileRecord, m_bitmapRecord, 0);
                    }
                    SplitRootIndexRecord();
                }
                else
                {
                    m_volume.UpdateFileRecord(m_fileRecord);
                }
            }
            else
            {
                KeyValuePairList <int, IndexRecord> path = FindInsertPath(key);
                IndexRecord leafRecord    = path[path.Count - 1].Value;
                long        leafRecordVBN = leafRecord.RecordVBN;
                int         insertIndex   = CollationHelper.FindIndexForSortedInsert(leafRecord.IndexEntries, key, m_rootRecord.CollationRule);
                leafRecord.IndexEntries.Insert(insertIndex, entry);
                long leafRecordIndex = ConvertToRecordIndex(leafRecordVBN);
                if (leafRecord.DoesFit((int)m_rootRecord.BytesPerIndexRecord))
                {
                    WriteIndexRecord(leafRecordIndex, leafRecord);
                }
                else
                {
                    // Split index record
                    SplitIndexRecord(path);
                }
            }
        }
Пример #5
0
        public void RemoveEntry(byte[] key)
        {
            if (!m_rootRecord.IsParentNode)
            {
                int index = CollationHelper.FindIndexInLeafNode(m_rootRecord.IndexEntries, key, m_rootRecord.CollationRule);
                if (index >= 0)
                {
                    m_rootRecord.IndexEntries.RemoveAt(index);
                }
                m_volume.UpdateFileRecord(m_fileRecord);
            }
            else
            {
                int indexOfEntryToRemove;
                KeyValuePairList <int, IndexRecord> path = FindRemovalPath(key, out indexOfEntryToRemove);
                if (path == null)
                {
                    return;
                }

                if ((path.Count > 0 && path[path.Count - 1].Value.IsParentNode) || path.Count == 0)
                {
                    // We find the rightmost leaf entry in the left branch and put it instead.
                    // Note: Excluding the root of the branch, the rightmost leaf entry in the branch collates last.
                    KeyValuePairList <int, IndexRecord> pathToLeaf = FindPathToRightmostLeaf(path, indexOfEntryToRemove);
                    IndexRecord leaf = pathToLeaf[pathToLeaf.Count - 1].Value;
                    IndexEntry  entryToRemoveFromLeaf = leaf.IndexEntries[leaf.IndexEntries.Count - 1];
                    leaf.IndexEntries.RemoveAt(leaf.IndexEntries.Count - 1);
                    long leafRecordIndex = ConvertToRecordIndex(leaf.RecordVBN);
                    // Note: CHKDSK does not accept an empty IndexRecord, however, we must not call RemovePointer just yet because it might affect the parent as well.
                    WriteIndexRecord(leafRecordIndex, leaf);

                    if (path.Count == 0)
                    {
                        m_rootRecord.IndexEntries[indexOfEntryToRemove].FileReference = entryToRemoveFromLeaf.FileReference;
                        m_rootRecord.IndexEntries[indexOfEntryToRemove].Key           = entryToRemoveFromLeaf.Key;
                        m_volume.UpdateFileRecord(m_fileRecord);
                    }
                    else
                    {
                        path[path.Count - 1].Value.IndexEntries[indexOfEntryToRemove].FileReference = entryToRemoveFromLeaf.FileReference;
                        path[path.Count - 1].Value.IndexEntries[indexOfEntryToRemove].Key           = entryToRemoveFromLeaf.Key;
                        long recordIndex = ConvertToRecordIndex(path[path.Count - 1].Value.RecordVBN);
                        WriteIndexRecord(recordIndex, path[path.Count - 1].Value);
                    }

                    if (leaf.IndexEntries.Count == 0)
                    {
                        int indexOfLeafPointer = pathToLeaf[pathToLeaf.Count - 1].Key;
                        RemovePointer(pathToLeaf.GetRange(0, pathToLeaf.Count - 1), indexOfLeafPointer);
                        DeallocateIndexRecord(leafRecordIndex);
                    }
                }
                else
                {
                    int         indexInParentRecord = path[path.Count - 1].Key;
                    IndexRecord leaf = path[path.Count - 1].Value;

                    leaf.IndexEntries.RemoveAt(indexOfEntryToRemove);
                    long recordIndex = ConvertToRecordIndex(leaf.RecordVBN);
                    if (leaf.IndexEntries.Count > 0)
                    {
                        WriteIndexRecord(recordIndex, leaf);
                    }
                    else
                    {
                        path.RemoveAt(path.Count - 1);
                        RemovePointer(path, indexInParentRecord);
                        DeallocateIndexRecord(recordIndex);
                    }
                }
            }
        }
Пример #6
0
        public bool UpdateFileNameRecord(FileNameRecord fileNameRecord)
        {
            byte[] key = fileNameRecord.GetBytes();
            if (!m_rootRecord.IsParentNode)
            {
                int index = CollationHelper.FindIndexInLeafNode(m_rootRecord.IndexEntries, key, m_rootRecord.CollationRule);
                if (index >= 0)
                {
                    m_rootRecord.IndexEntries[index].Key = key;
                    m_volume.UpdateFileRecord(m_fileRecord);
                    return(true);
                }
            }
            else
            {
                IndexRecord       indexRecord  = null;
                bool              isParentNode = true;
                List <IndexEntry> entries      = m_rootRecord.IndexEntries;
                int index;
                while (isParentNode)
                {
                    index = CollationHelper.FindIndexInParentNode(entries, key, m_rootRecord.CollationRule);
                    IndexEntry entry = entries[index];
                    if (!entry.IsLastEntry && CollationHelper.Compare(entry.Key, key, m_rootRecord.CollationRule) == 0)
                    {
                        entries[index].Key = key;
                        if (indexRecord == null)
                        {
                            m_volume.UpdateFileRecord(m_fileRecord);
                        }
                        else
                        {
                            long recordIndex = ConvertToRecordIndex(indexRecord.RecordVBN);
                            WriteIndexRecord(recordIndex, indexRecord);
                        }
                        return(true);
                    }
                    else
                    {
                        long subnodeVBN = entry.SubnodeVBN;
                        indexRecord  = ReadIndexRecord(subnodeVBN);
                        isParentNode = indexRecord.IsParentNode;
                        entries      = indexRecord.IndexEntries;
                    }
                }

                index = CollationHelper.FindIndexInLeafNode(entries, key, m_rootRecord.CollationRule);
                if (index >= 0)
                {
                    entries[index].Key = key;
                    if (indexRecord == null)
                    {
                        m_volume.UpdateFileRecord(m_fileRecord);
                    }
                    else
                    {
                        long recordIndex = ConvertToRecordIndex(indexRecord.RecordVBN);
                        WriteIndexRecord(recordIndex, indexRecord);
                    }
                    return(true);
                }
            }

            return(false);
        }