Пример #1
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);
                }
            }
        }
Пример #2
0
        /// <param name="path">Key is index in parent node</param>
        private void SplitIndexRecord(KeyValuePairList <int, IndexRecord> path)
        {
            int indexInParentRecord = path[path.Count - 1].Key;
            // We will treat the record we want to split as the right node, and create a left node
            IndexRecord       rightNode        = path[path.Count - 1].Value;
            long              rightNodeVBN     = rightNode.RecordVBN;
            long              rightNodeIndex   = ConvertToRecordIndex(rightNodeVBN);
            List <IndexEntry> rightNodeEntries = rightNode.IndexEntries;
            int         splitIndex             = rightNodeEntries.Count / 2;
            IndexEntry  middleEntry            = rightNodeEntries[splitIndex];
            IndexRecord leftNode = new IndexRecord();

            leftNode.IsParentNode = rightNode.IsParentNode;
            leftNode.IndexEntries = rightNodeEntries.GetRange(0, splitIndex);
            rightNodeEntries.RemoveRange(0, splitIndex + 1);
            if (rightNode.IsParentNode)
            {
                // A parent node has n keys and points to (n + 1) subnodes,
                // When splitting it to two nodes we will take the pointer from the entry we wish to push to the parent node,
                // and use it as the last pointer in the left node.
                IndexEntry leftNodeLastEntry = new IndexEntry();
                leftNodeLastEntry.ParentNodeForm = true;
                leftNodeLastEntry.IsLastEntry    = true;
                leftNodeLastEntry.SubnodeVBN     = middleEntry.SubnodeVBN;
                leftNode.IndexEntries.Add(leftNodeLastEntry);
            }
            long leftNodeIndex = AllocateIndexRecord();

            leftNode.RecordVBN = ConvertToVirtualBlockNumber(leftNodeIndex);
            IndexEntry newParentEntry = new IndexEntry(middleEntry.FileReference, middleEntry.Key);

            newParentEntry.ParentNodeForm = true;
            newParentEntry.SubnodeVBN     = leftNode.RecordVBN;
            WriteIndexRecord(rightNodeIndex, rightNode);
            WriteIndexRecord(leftNodeIndex, leftNode);
            if (path.Count > 1)
            {
                IndexRecord       parentRecord      = path[path.Count - 2].Value;
                long              parentRecordIndex = ConvertToRecordIndex(parentRecord.RecordVBN);
                List <IndexEntry> parentEntries     = parentRecord.IndexEntries;
                parentEntries.Insert(indexInParentRecord, newParentEntry);
                if (parentRecord.DoesFit((int)m_rootRecord.BytesPerIndexRecord))
                {
                    WriteIndexRecord(parentRecordIndex, parentRecord);
                }
                else
                {
                    // Split parent index record
                    path.RemoveAt(path.Count - 1);
                    SplitIndexRecord(path);
                }
            }
            else
            {
                m_rootRecord.IndexEntries.Insert(indexInParentRecord, newParentEntry);
                if (m_rootRecord.RecordLength >= m_volume.AttributeRecordLengthToMakeNonResident)
                {
                    SplitRootIndexRecord();
                }
                else
                {
                    m_volume.UpdateFileRecord(m_fileRecord);
                }
            }
        }