コード例 #1
0
        /// <summary>
        /// ibatrak очистка полей с количеством ссылок в заголовке записи
        /// </summary>
        public static void ClearItems(Stream stream, long offset)
        {
            //в заголовке проставляем 0 записей, сами ссылки не трогаем
            //ирбис так делает, проверено
            var ifpRecord = ReadLeader(stream, offset);
            //в записи со спец блоком зануляется только TotalLinkCount и оба поля во вложенных записях
            var special = ifpRecord.Special;

            if (!special)
            {
                ifpRecord.BlockLinkCount = 0;
            }
            ifpRecord.TotalLinkCount = 0;
            WriteLeader(stream, ifpRecord, offset);
            if (special)
            {
                //начитаем первую запись из спец блока, в ней ссылка на первую запись обыкновенного формата
                //остальные записи спец блока здесь не нужны

                var specBlock       = new SpecialPostingBlockEntry[ifpRecord.Capacity];
                var specBlockBuffer = new byte[ifpRecord.Capacity * SpecialPostingBlockEntry.RecordSize];
                var fileOffset      = stream.Position;
                if (stream.Read(specBlockBuffer, 0, specBlockBuffer.Length) != specBlockBuffer.Length)
                {
                    throw new IOException();
                }

                for (int i = 0; i < ifpRecord.Capacity; i++)
                {
                    var entry = SpecialPostingBlockEntry.Read(specBlockBuffer, i * SpecialPostingBlockEntry.RecordSize);
                    entry.FileOffset = fileOffset + i + SpecialPostingBlockEntry.RecordSize;
                    specBlock[i]     = entry;
                }

                var nonEmptyEntries = specBlock.Where(e => e.Offset > 0).Count();
                if (nonEmptyEntries != ifpRecord.BlockLinkCount)
                {
                    throw new InvalidOperationException("Ошибка чтения ifp offset=" + offset);
                }

                var nestedRecords = new IfpRecord[ifpRecord.BlockLinkCount];

                for (int i = 0; i < ifpRecord.BlockLinkCount; i++)
                {
                    if (specBlock[i].Offset <= 0 ||
                        (i > 0 && nestedRecords[i - 1].FullOffset != specBlock[i].Offset))
                    {
                        throw new InvalidOperationException("Ошибка чтения ifp offset=" + offset);
                    }
                    var nestedRecord = ReadLeader(stream, specBlock[i].Offset);
                    nestedRecord.BlockLinkCount = 0;
                    nestedRecord.TotalLinkCount = 0;
                    nestedRecords[i]            = nestedRecord;
                    WriteLeader(stream, ifpRecord, specBlock[i].Offset);
                }
            }
        }
コード例 #2
0
        public static IfpRecord Read
        (
            Stream stream,
            long offset
        )
        {
            //new ObjectDumper()
            //    .DumpStream(stream, offset, 100);

            //ibatrak чтение лидера вынесено отдельно
            //stream.Position = offset;

            //IfpRecord result = new IfpRecord
            //    {
            //        LowOffset = stream.ReadInt32Network(),
            //        HighOffset = stream.ReadInt32Network(),
            //        TotalLinkCount = stream.ReadInt32Network(),
            //        BlockLinkCount = stream.ReadInt32Network(),
            //        Capacity = stream.ReadInt32Network(),
            //        _FileOffset = offset
            //    };

            IfpRecord result = ReadLeader(stream, offset);

            //ibatrak чтение вложенных записей в спец блоке
            //Специальный формат записи .ifp
            //В этом случае первой записью является специальный блок,
            //который представляет собой заголовок (обыкновенного формата), в котором смещения имеют специальные значения = -1001, и набор вхождений следующего формата:
            //Число бит	Параметр	Описание
            //32	POSTING	1-я ссылка из записи обыкновенного формата
            //32	LOW	младшее слово смещения на следующую запись (если нет 0)
            //32	HIGH	старшее слово смещения на следующую запись (если нет 0)
            //Число вхождений кратно 4. Записи, на которые ссылается специальный блок связаны между собой как описано выше.
            //Общее количество ссылок для данного термина сохраняется только в специальном блоке.
            if (result.Special)
            {
                //irbis64.dll делает так

                //читает первые 24 байта блока спец ссылок
                //берет первую запись, адрес из нее в файле и читает записей IFP
                //по количеству result.BlockLinkCount

                //записи спец блока идут по количеству Capacity
                //каждая указывает на запись обычного формата
                //также в каждой записи обычного формата FullOffset указывает на следующую запись (кроме последней)
                //это должно соответствовать

                var specBlock       = new SpecialPostingBlockEntry[result.Capacity];
                var specBlockBuffer = new byte[result.Capacity * SpecialPostingBlockEntry.RecordSize];
                var fileOffset      = stream.Position;
                if (stream.Read(specBlockBuffer, 0, specBlockBuffer.Length) != specBlockBuffer.Length)
                {
                    throw new IOException();
                }

                for (int i = 0; i < result.Capacity; i++)
                {
                    var entry = SpecialPostingBlockEntry.Read(specBlockBuffer, i * SpecialPostingBlockEntry.RecordSize);
                    entry.FileOffset = fileOffset + i + SpecialPostingBlockEntry.RecordSize;
                    specBlock[i]     = entry;
                }

                //запомнить для редактирования
                result._SpecialBlock = specBlock;

                var nonEmptyEntries = specBlock.Where(e => e.Offset > 0).Count();
                if (nonEmptyEntries != result.BlockLinkCount)
                {
                    throw new InvalidOperationException("Ошибка чтения ifp offset=" + offset);
                }

                var nestedRecords = new IfpRecord[result.BlockLinkCount];
                for (int i = 0; i < result.BlockLinkCount; i++)
                {
                    if (specBlock[i].Offset <= 0 ||
                        (i > 0 && nestedRecords[i - 1].FullOffset != specBlock[i].Offset))
                    {
                        throw new InvalidOperationException("Ошибка чтения ifp offset=" + offset);
                    }
                    var nestedRecord = Read(stream, specBlock[i].Offset);
                    nestedRecords[i] = nestedRecord;
                }
                var links = nestedRecords.SelectMany(r => r.Links).ToArray();
                if (links.Length != result.TotalLinkCount)
                {
                    throw new InvalidOperationException("Ошибка чтения ifp offset=" + offset);
                }
                result.Links.AddRange(links);
                result._NestedRecordLeaders = nestedRecords.ToArray();
                foreach (var r in nestedRecords)
                {
                    r._links.Clear();
                }
                return(result);
            }
            //ibatrak до сюда

            //ibatrak читаем ссылки за раз, так быстрее
            var linkBuffer = new byte[result.BlockLinkCount * TermLink.RecordSize];

            if (stream.Read(linkBuffer, 0, linkBuffer.Length) != linkBuffer.Length)
            {
                throw new IOException();
            }

            for (int i = 0; i < result.BlockLinkCount; i++)
            {
                TermLink link = TermLink.Read(linkBuffer, i * TermLink.RecordSize);
                result.Links.Add(link);
            }

            //for (int i = 0; i < result.BlockLinkCount; i++)
            //{
            //    TermLink link = TermLink.Read(stream);
            //    result.Links.Add(link);
            //}

            return(result);
        }