Работа с записями


НАЧАЛО >> Нативный провайдер данных DP_Irbis64Native >> Работа с записями📄 Скачать в DOCX


Операции с записями выполняются через стандартные функции провайдера. В прикладном коде они выглядят так же, как при работе с другими провайдерами ИРБИС 128, но внутри DP_Irbis64Native читает и изменяет файлы базы напрямую.

1. Чтение записи

Для чтения используется MFN. Провайдер обращается к XRF, получает физический адрес записи в MST, читает тело записи и возвращает его в формате, ожидаемом ИРБИС 128.

Типовая последовательность:

  1. прикладной модуль передает имя базы и MFN;
  2. провайдер открывает или берет из кэша контекст базы;
  3. по XRF определяется положение записи;
  4. из MST читается актуальная версия;
  5. поля записи преобразуются в нужную кодировку;
  6. результат возвращается вызывающему модулю.

Если запись удалена, заблокирована или MFN выходит за допустимый диапазон, провайдер возвращает состояние ошибки через общий механизм ИРБИС 128.

2. Чтение с форматированием

Функции RecReadAndFormat, RecFormat, RecFormatMfn и RecFormatMfnRange читают записи и применяют PFT-форматы. Форматы ищутся через стандартные пути базы и окружения, а список доступных форматов может определяться настройкой PftOpt.

Форматирование выполняется после получения записи. Поэтому проблемы чтения MST/XRF и ошибки PFT диагностируются отдельно.

3. Сохранение записи

Сохранение выполняется через RecWrite и связанные обработчики. Перед фактической записью провайдер может выполнить несколько шагов:

  1. применить автоматический ввод;
  2. выполнить формально-логический контроль;
  3. обработать специальные действия сохранения;
  4. подготовить обновление MST и XRF;
  5. записать новую версию записи;
  6. отметить необходимость актуализации индекса;
  7. завершить транзакцию.

Если проверка ФЛК возвращает фатальный отказ, запись сохраняется как логически удаленная. Это сохраняет занятый MFN и соответствует пакетным сценариям ИРБИС64, где неуспешная по ФЛК запись остается в MST/XRF с признаком удаления.

4. Автоматический ввод

Автоматический ввод выполняется по GBL-файлу, заданному параметром AutoInFile. Он используется для заполнения служебных полей, дат, идентификаторов и других значений, которые должны добавляться при создании или изменении записи.

Автоввод выполняется до записи в MST, поэтому его результат попадает в сохраняемую версию записи и далее участвует в актуализации.

5. Блокировки

Для предотвращения одновременного изменения используются операции:

При редактировании запись должна быть заблокирована до сохранения или отмены изменений. Если блокировку получить нельзя, прикладной модуль должен предупредить пользователя и не выполнять запись.

6. Удаление

Операция DeleteRec присутствует в интерфейсе провайдера для совместимости, но в текущей реализации DP_Irbis64Native не выполняет фактическое изменение MST/XRF. Если сценарий требует удаления записи, нужно использовать реализованный штатный механизм обслуживания базы и после него актуализировать индекс.

7. Импорт и создание базы

Для пакетной загрузки и подготовки баз используются функции ImportFromFile, NewDb и Empty. Они применяются административными сценариями и должны выполняться только при корректно настроенных путях базы и достаточных правах на файловую систему.

ImportFromFile в DP_Irbis64Native поддерживает потоковый импорт ISO-2709, текстового формата irbistool и CSV. Файл читается последовательно по одной записи, без загрузки всего входного файла в память. Для ISO запись читается по 5-байтовой длине, для текстового формата - до разделителя *****, для CSV - по одной CSV-строке с поддержкой кавычек, "" и многострочных quoted values.

Текущий импорт сохраняет прежнюю совместимость вызовов Database/ImportFromFile: по умолчанию используется кодировка windows-1251, а старый результат остается числом импортированных записей. Для сценариев, совместимых с irbistool import без -win, нужно передавать Encoding=utf-8. При ReturnReport=true функция возвращает отчет с числом прочитанных, импортированных и ошибочных записей; параметр ErrorLimit ограничивает число подробных ошибок в отчете, чтобы сбой на большом файле не приводил к накоплению неограниченного массива в памяти.

Для append-import без FST, фильтра, ФЛК, merge PFT и PhysicalDeleted provider использует одну bulk-транзакцию на весь поток записей; режимы CheckCoding=true, UseAutoin=true и простой MergeGbl без NEWREC/NEWMFN/PUTLOG также могут работать в этой bulk-модели. Это снижает overhead журналирования на больших ISO/text/CSV-файлах; в отчете такой режим отмечается флагом bulkAppendTransaction=true. Режимы с побочными записями остаются в поштучной транзакционной модели до расширенного rollback-регламента.

FST-преобразование можно передать как текст FstContent или как имя FSTName. Преобразование выполняется для каждой записи перед сохранением и поддерживает конструкцию 0 0 '*' для переноса неизмененных полей, как путь RecReformat(..., true) в irbistool import. Если отдельная строка FST состоит из @filename, DP_Irbis64Native рекурсивно подставляет содержимое filename.fst; файл ищется через путь 10: сначала среди файлов БД, затем в Deposit.

Фильтр импорта передается параметром FormatFilter. Он соответствует irbistool import -flt: формат выполняется после чтения записи и FST-преобразования, но до записи в MST. Запись импортируется только если результат форматирования начинается с 1; остальные записи учитываются в отчете как filtered.

Параметр PhysicalDeleted=true соответствует irbistool import -pdel: для новых записей без MFN импорт последовательно ищет физически удаленные MFN в XRF и переиспользует их перед добавлением записей в конец БД. Сканирование выполняется последовательно и не хранит полный список удаленных MFN в памяти; число переиспользованных MFN возвращается в отчете как reusedPhysicalDeleted.

Параметр CheckCoding=true соответствует irbistool import -k: перед сохранением проверяются строки всех полей записи. Если хотя бы одно поле содержит невалидную UTF-8-последовательность, запись не сохраняется и учитывается в отчете как codingRejected.

Параметр flc=true соответствует irbistool import -c на уровне провайдера. Формат ФЛК берется из dbnflc.pft или из имени, заданного настройкой DbnFlc; для тестов и административных сценариев можно передать текст формата через FlcContent. Код результата 1 помечает импортируемую запись как логически удаленную и все равно записывает ее в MST/XRF, как делает irbistool; код 2 считается предупреждением и не запрещает запись. В отчете возвращаются flcRejected и flcWarnings.

Параметр autoin=true соответствует irbistool import -a на уровне провайдера. GBL автоматического ввода загружается из autoin.gbl или из имени, заданного настройкой Autoin; для тестов и административных сценариев можно передать текст GBL через AutoinContent. Автоматический ввод выполняется после чтения записи, FST и FormatFilter, но до ФЛК, проверки кодировки, выбора физически удаленного MFN и записи в MST/XRF. В отчете возвращаются autoin, autoinLoaded, autoinApplied и autoinCreatedRecords.

Параметр MergePft соответствует irbistool import -p на уровне провайдера. Значение @<MFN> выбирает явную запись-цель, а имя PFT загружается через файловые пути БД; для тестов можно передать текст формата через MergePftContent. Если результат PFT начинается с @, используется указанный MFN; иначе результат считается термом инверсного файла и берется первая ссылка терма. Импортируемая запись объединяется с найденной записью-целью, дублирующиеся поля не добавляются, неповторяющиеся поля по WSFDT заменяются, а при отсутствии изменений запись не сохраняется повторно. Если цель не найдена, запись импортируется как новая, как в irbistool.

Параметр MergeGbl соответствует базовому сценарию irbistool import -g на уровне провайдера. GBL загружается по имени через файловые пути БД или передается текстом через MergeGblContent. Подтвержденный scope включает GBL-коррекцию текущей импортируемой записи, NEWREC, NEWMFN '*'/текущая БД и NEWMFN в другую БД с созданием дополнительной записи: созданная запись сохраняется перед основной, как у irbistool, а для другой БД provider открывает целевой контекст внутри DP_Irbis64Native. Если MergeGbl используется вместе с autoin или flc, автоматический ввод и ФЛК применяются к побочным записям перед их записью, как в IrbisGblRec; основная импортируемая запись в ветке -g после GBL пишется напрямую. Если autoin для побочной записи создает дополнительную запись, подтвержденный сценарий записывает эту autoin-created запись до родительской побочной записи в той же транзакционной группе. Отчет ReturnReport=true содержит mergeGblCreatedRecordDetails: для сохраненных в отчете побочных записей фиксируются исходная импортируемая запись, тип created, целевая БД, MFN после записи, результат RecUpdate, а также признаки autoinApplied, autoinCreatedRecords, autoinCascadeCreatedRecords, flcRejected и flcWarning. Чтобы большой импорт не держал в памяти detail для каждой побочной записи, число хранимых элементов ограничивается параметром MergeGblCreatedRecordDetailsLimit (по умолчанию 1000), а полный объем отражается в mergeGblCreatedRecordDetailsTotal, mergeGblCreatedRecordDetailsOmitted и mergeGblCreatedRecordDetailsTruncated. Расширенная семантика IrbisGblRec с рекурсией/UpdList, сложными циклами autoin/GBL и полным runtime error-протоколом должна проверяться отдельными инкрементами.

Соответствие режимов PhysicalDeleted, CheckCoding, flc, autoin, MergeGbl и MergePft проверяется скриптом tools/DP_Irbis64NativeImportRecordsCompare.php. Он запускает irbistool.exe import -pdel, irbistool.exe import -k, irbistool.exe import -c, irbistool.exe import -a, irbistool.exe import -g, irbistool.exe import -g с NEWREC, irbistool.exe import -g -a -c с NEWREC, irbistool.exe import -g -a с NEWREC и каскадной autoin-created записью, irbistool.exe import -g с NEWMFN '*', irbistool.exe import -g с NEWMFN 'ARCH', irbistool.exe import -g -a -c с NEWMFN 'ARCH', а также набор irbistool.exe import -p для @MFN, PFT -> @MFN, PFT -> term, WSFDT-замены неповторяющегося поля, de-dup повторяющегося поля и случая, когда цель merge не найдена. Native-импорт выполняется на такой же изолированной копии; сравниваются MaxMfn, статусы MST/XRF и контрольные MFN после операции. Full-size benchmark ISO append-import, CheckCoding=true, UseAutoin=true, простой MergeGbl и MergeGbl NEWREC проверяется tools/DP_Irbis64NativeImportRecordsBenchmark.php; сценарий RPC merge-gbl-newrec импортировал 95899 записей, создал 95899 побочных записей, подтвердил порядок side -> main, дал irbistool=82.921497s, native 114.512541s, mergeGblCreatedRecords=95899, mergeGblCreatedRecordDetailsTotal=95899, mergeGblCreatedRecordDetailsOmitted=94899, errors=0, peak memory 12582912. Для простого MergeGbl без побочных записей последний full-size прогон дал irbistool=17.579352s, native 17.735132s, bulkAppendTransaction=true, mergeGblApplied=95899, errors=0.

Для текстового импорта параметр Guid=true сохраняет служебное поле 2147483647; без него поле пропускается. Параметр Header=true учитывает строку #0: для новой записи с MFN, равным текущему MaxMfn, запись создается с этим MFN.

Provider-level MergeGbl, MergePft и autoin реализованы и сверяются с irbistool в ограниченных сценариях. Окно Database/ImportRecordsWindow передает эти режимы через Database::ImportFromFile только после обязательного подтверждения backup; лимит подробного отчета побочных записей задается там же параметром MergeGblCreatedRecordDetailsLimit, без прямого обращения UI или action-кода к provider context. Для MergeGbl уже покрыты простая коррекция, NEWREC, NEWMFN '*' в той же БД и NEWMFN в другую БД на изолированном стенде IBIS -> ARCH; отчет побочных записей проверяет DB/MFN/result. Сценарии -g NEWREC -a -c и -g NEWMFN 'ARCH' -a -c дополнительно подтверждают, что побочная запись перед сохранением получает autoin.gbl целевой БД, затем ФЛК целевой БД может пометить ее логически удаленной, а основная импортируемая запись в этой ветке не получает autoin. Сценарий -g NEWREC -a с autoin-created записью подтверждает порядок cascade -> side -> main по MFN. Если GBL создает побочные записи, provider записывает побочные и основную запись в одной транзакционной группе по задействованным native-БД. При ошибке основной записи уже записанные побочные записи откатываются, сохраненные detail-элементы помечаются rolledBack=true, а отчет содержит mergeGblRollbacks и mergeGblRollbackDetails со списком БД; это проверено и для пары cascade+side внутри одной БД. Структурные ошибки GBL, например отсутствующий include, не приводят к записи импортируемой записи и возвращаются в mergeGblErrorDetails; общий отчет также увеличивает счетчик errors. Это не заменяет пользовательский backup перед импортом. Для больших NEWREC-сценариев детальный отчет ограничивается summary-полями, но performance gap по записи побочных записей остается и должен учитываться при планировании запуска. Общая рекурсия/UpdList, сложные циклы autoin/GBL и полная совместимость error-протокола IrbisGblRec остаются отдельным ограничением.

8. План слияния БД

Метод MergeDbDryRun реализует первую, недеструктивную стадию подготовки аналога irbistool mergedb. Он не переносит MST/XRF, embedded FT и словари, а только строит preflight-отчет для будущей destructive-операции.

Входные данные: БД-приемник (DbName) и список исходных БД (SourceDbNames). Список может быть массивом или строкой, разделенной пробелами, запятыми или точками с запятой. Provider нормализует имена, убирает повторы и отказывает, если destination входит в source-list.

Для каждой БД метод открывает native-space только read-only, получает MaxMfn, проверяет наличие embedded FT, рассчитывает mfnShift/ftMfnShift, собирает известные файлы MST, XRF, CNT, N01, N02, L01, L02, IFP, ANY и .par, а также оценивает объем backup и рабочих файлов. Для стандартных .par, которые указывают на каталог БД, discovery учитывает файлы вида <DB>/<DB>.mst, <DB>/<DB>.xrf, <DB>/<DB>.ifp и их варианты с верхним регистром расширения.

Отчет содержит защитные признаки dryRun=true, writePerformed=false, implemented=false, requiresBackupBeforeMerge=true, requiresExclusiveDestinationLock=true и список диагностик, которые должны выполняться после будущего merge: diagmfn, diagmstxrf, diagrec, diaglnk, diagrecft. Эти признаки нужны, чтобы вызывающий код не воспринимал dry-run как готовую операцию слияния.

Для будущей стадии словарей dry-run возвращает dictionaryPlan. Это только план: рабочий каталог внутри irbistool-mergedb не создается, .lk1/JSONL/manifest-файлы не пишутся и loaddict не запускается. В плане фиксируются catalog-стадии export-destination, export-sources, shift-source-postings, external-sort-merge, load-destination, diaglnk, имена будущих work-файлов и отдельная FT-ветка, если destination или source имеют embedded FT. Такой отчет нужен, чтобы destructive dictionary merge проектировался как отдельная commit/rollback-стадия, а не скрывался внутри MST/XRF prototype.

Метод MergeDbDictionaryDryRun реализует первый материализованный, но недеструктивный кусок словарной стадии. Он создает workdir, формирует catalog terms для destination и source-БД через потоковый terms pipeline, применяет cumulative MFN-shift к source postings и строит общий terms-sorted.jsonl. Метод не загружает словарь в destination, не меняет N01/L01/IFP, возвращает writePerformed=false и destructiveLoadPerformed=false. Самопроверка ARCH <- CMPL,RQST с диагностическим лимитом 5 записей на БД подтвердил ненулевой поток 352 term rows / 381 postings и shifted ranges CMPL: 62..66, RQST: 387..393. Это подготовка для будущего loaddict/diaglnk, а не готовая словарная commit-стадия.

Отдельный isolated load-gate проверяет, что такой stream можно загрузить после MST/XRF append: tools/DP_Irbis64NativeMergeDbMstXrfPrototypeSelfTest.php ... CMPL SPRAV 5 строит MergeDbDictionaryDryRun до полного merge, затем выполняет полный MST/XRF prototype. Перед успешной загрузкой тест отменяет LoadIndexTermsCatalog через progress callback после начала stage-записи и проверяет, что committed N01/L01/IFP сохранили SHA1 baseline. Затем штатная загрузка получает dictTerms=5019 и dictPostings=20936, проверяет catalog-only DiagLnk, а после проверки N01/L01/IFP восстанавливаются по SHA1 baseline. Более поздние gates уже покрывают integrated catalog/FT dictionary, multi-source compare и internal Queue rollback/success; пользовательский UI и backup-confirmation design остаются отдельной production-стадией.

Сценарий сравнения tools/DP_Irbis64NativeMergeDbCompare.php поддерживает дополнительный флаг --with-dictionary-load. В этом режиме native dictionary stream строится до MST/XRF append, загружается после append на временной destination, затем выполняется native catalog-only DiagLnk и сканируются postings. Контроль CMPL,RQST -> SPRAV прошел с dictTerms=5975, dictPostings=22451, native diaglnk=ok; postings на физически или логически удаленные записи не найдены. Тот же fixture выявляет дефект текущего irbistool.exe: утилита завершает mergedb с exit code 0, но пишет sorting error ... length=260, а созданный ей L01 не проходит DiagLnk (error in file L01). Это не является целевым поведением provider-реализации.

Опция MergeCatalogDictionary=true включает ту же catalog dictionary load-стадию внутрь MergeDbMstXrfPrototype. Provider строит stream до MST/XRF append, загружает его после append, включает DiagLnk в post-merge diagnostics и использует общий backup-manifest для rollback после словарного сбоя. Самопроверка проверяет InjectFailureAfterDictionaryLoad=true: rollback срабатывает после уже записанных записей и index-файлов. Успешный integrated path возвращает mergedCatalogDictionary=true, requiresCatalogDictionaryRebuild=false и ненулевые счетчики dictionaryLoad; агрегированный requiresDictionaryRebuild остается для совместимости. Для частичного merge с MaxRecords > 0 эта опция запрещена, потому что словарь должен соответствовать полному MST/XRF состоянию. Сочетание MergeCatalogDictionary=true и MergeFullText=true разрешено только для полного исследовательского прогона MaxRecords=0: после raw append FT-записей provider перестраивает embedded FT dictionary через RecreateIndexFullText() в рамках того же backup-manifest и снимает requiresFullTextDictionaryRebuild.

Метод MergeDbMstXrfPrototype реализует следующий ограниченный backend-инкремент. Он требует AllowPrototypeWrite=true, по умолчанию требует пустую destination-БД, перед записью создает backup-manifest destination-файлов, читает source-записи последовательно и записывает их в destination raw append-путем без декодирования полей. Физически удаленные source-записи не копируются как обычные записи, но занимают физически удаленный MFN в destination, чтобы сохранить MFN-shift и не создавать поисковые postings. При ошибке после начала записи provider закрывает native handles и восстанавливает файлы из backup. Это сохраняет MST/XRF ближе к IrbisMergeMstXrf. Текущий irbistool.exe mergedb на проверенном real-FT fixture не переносит embedded FT-записи, поэтому native prototype по умолчанию также не переносит FT. Для отдельного исследовательского режима можно явно передать MergeFullText=true: если source и destination имеют открытые embedded FT-пространства и основной merge не ограничен MaxRecords, prototype переносит FT-записи отдельным raw append-потоком и возвращает mergedFullText, fullTextCopied, fullTextSources и fullTextMappings. При частичном основном merge FT не переносится, чтобы не получить несогласованное состояние основной БД и FT. После успешной записи по умолчанию выполняются post-merge проверки diagmfn, diagmstxrf, diagrec и, при наличии FT-пространства, проверка FT-записей; результат возвращается в postMergeDiagnostics и postMergeDiagnosticsOk. diaglnk в этом prototype помечается как пропущенный до стадии словарей, потому что словари не сливаются и индекс не актуализируется. Отчет содержит requiresDictionaryRebuild=true, mergedDictionaries=false.

Продуктовое решение по FT-copy: MergeFullText=true остается внутренним исследовательским флагом и не должен выводиться отдельной пользовательской опцией в первом UI слияния. Пользовательский режим должен по умолчанию следовать текущей семантике irbistool.exe на проверенном fixture, то есть не переносить embedded FT отдельно от обычного MST/XRF merge. Вывод FT-copy в UI возможен только после отдельного продуктового решения.

Проверка dry-run выполняется скриптом tools/DP_Irbis64NativeMergeDbDryRunSelfTest.php. Контрольный запуск ARCH <- IBIS на локальном стенде подтвердил расчет mfnShift=61, records=7228, requiredFreeBytes=168656996, отказ при включении destination в source-list и наличие dictionaryPlan без создания его workDir. Тот же self-test принимает source-строку через запятую; сценарий ARCH <- CMPL,RQST подтверждает cumulative mfnShift для второго source. Проверка MST/XRF prototype выполняется tools/DP_Irbis64NativeMergeDbMstXrfPrototypeSelfTest.php: на временных копиях CMPL -> SPRAV с лимитом 5 записей подтверждены отказ без AllowPrototypeWrite, отказ при недостатке свободного места до создания backup, rollback после искусственного сбоя InjectFailureAfterRecords=2, запись 5 записей, finalMaxMfn=6, успешные DiagMfn/DiagMstXrf/DiagRec, наличие post-merge diagnostics в отчете и совпадение первой raw-записи после ожидаемой переписи leader. Тот же self-test создает synthetic embedded FT-пространства во временных копиях: при явном MergeFullText=true он подтверждает fullTextCopied=2 и успешную post-merge проверку FT-записей, а при искусственном сбое InjectFailureAfterFullTextRecords=1 проверяет rollback после уже записанных main-записей и первой FT-записи с восстановлением main/FT snapshot destination.

Следующие стадии mergedb должны реализовываться отдельно: полноразмерное и производительное покрытие, реальные fragmented/фикстуры старых версий или явная внешняя fixture-зависимость, и пользовательский интерфейс и подтверждение резервного копирования. Решение по FT-copy уже зафиксировано: отдельная пользовательская опция не выводится в первом UI.

Backup-manifest для prototype merge дополнительно хранит снимки каталогов, в которых есть резервируемые destination-файлы. При rollback provider не только возвращает файлы из backup, но и удаляет новые extra-файлы, появившиеся в этих каталогах после создания backup; счетчик таких удалений возвращается как rollback.removedExtra. Самопроверка проверяет этот сценарий через InjectExtraFileBeforeRollback=true вместе со сбоем после FT dictionary load.

Проверка восстановления через Queue tools/DatabaseMergeDbQueueRestoreTest.php проверяет этот путь на временных копиях: повторный прогон создал rollback task 517275, который завершился ожидаемой ошибкой после injected dictionary load и восстановил destination snapshot из 38 файлов; затем task 517276 без injected failure завершился state=2, перенес 323 записи, записал 4308 dictionary terms / 7195 postings, прошел DiagLnk и вернул postMergeDiagnosticsOk=true. MergeDbMstXrfPrototype передает stage-level ProgressCallback для preflight, backup, records, dictionary-load, dictionary-load-ft, diagnostics и complete; action отображает эти события как queue progress/heartbeat.

Полноразмерное сравнение RPC -> SPRAV подтвердил raw MST/XRF append на 95899 записях без словарной загрузки: irbistool=24.588030 с, native 4.232021 с, MaxMfn=95900, структурное сравнение всех записей прошло. Для устойчивого повторного открытия таких результатов XrfFile::SetIsNewXrf() очищает chunk cache при переключении формата, а MstSpace::Open() проверяет расширенный набор MFN при autodetect 8/12-байтового XRF.

Среднее сравнение IBIS -> SPRAV --with-dictionary-load подтвердил интегрированный путь загрузки каталожного словаря на реальной БД: native DiagLnk проходит, dictTerms=14950, dictPostings=102887, физически удаленные MFN не получают postings. Raw append дополнительно переносит публичные статусные биты из source MST leader в destination XRF (BIT_NOTACT_REC, BIT_LOCK_REC, BIT_NOTACT_FULLTEXT_REC), чтобы not-actualized/lock state не терялся при копировании старых или смешанных XRF/MST вариантов. irbistool.exe на этом fixture повреждает словарь (result -401, invalid N01), поэтому это поведение документируется как дефект утилиты.

9. Восстановление после сбоя

Если операция записи была прервана, журнал транзакций позволяет восстановить согласованное состояние файлов при следующем открытии базы. Это не заменяет резервное копирование, но защищает от частично записанных MST, XRF, словаря или обратного индекса.

Для массового импорта журнал транзакций не является пользовательским механизмом отмены операции и не заменяет snapshot или файловую копию БД перед опасным запуском. Откат после ошибочного импорта должен планироваться как восстановление подготовленной копии БД, особенно при PhysicalDeleted, Header, flc, autoin, MergePft или MergeGbl, потому что операция может занимать MFN, менять MST/XRF, оставлять записи неактуализированными и изменять уже существующие записи.