Ассоциация ЭБНИТ    ИРБИС-корпорация    Вики-Ирбис    Online/CHM справка Ирбис   
Опыт и разработки пользователей ИРБИС :  ИРБИС Irbis
 
Ошибка сохранения записи при возврате результата из плагина
Пользователь: S-presso (IP-адрес скрыт)
Дата: 14, January, 2013 13:16

У меня возникла такая проблема. Пишу в этот раздел, поскольку речь идёт о разработке собственного приложения для Ирбис64, расширяемого с помощью внешних плагинов. Те же самые плагины должны по идее работать и из АРМ Каталогизатор (их формат принимаемых и возвращаемых данных соответствует документации), но на практике этого не происходит либо они срабатывают редко. Однако сейчас речь не об этом. Мне удалось заставить своё приложение обновлять текущую запись путём вызова плагинов, используя библиотеку irbis64_client.dll, но эту запись удаётся успешно сохранить командой IC_update, только если перед этим не была вызвана команда IC_changemfn (т.е. сама запись добавляется в конец БД). Если же я хочу сохранить её с текущим MFN, функция IC_update возвращает код ошибки -608 (при записи обнаружено несоответствие версий). Пытаясь найти выход из этой ситуации, я стал при выходе из плагинов с кодом возврата 1 вызывать после IC_changemfn ещё IC_ifupdate, но это не решило проблему полностью. При сохранении оглавлений журналов после этого терялись все данные об издании - в строке краткого описания остаётся только текст (Введено оглавление). Также при показе таких сохранённых записей в оптимизированном формате в моём приложении отображается мусор, хотя в Каталогизаторе всё отображается нормально (за исключением отдельных номеров журналов).

Демо-версию самого приложения скоро выложу здесь.

Re: Ошибка сохранения записи при возврате результата из плагина
Пользователь: Gena (IP-адрес скрыт)
Дата: 14, January, 2013 13:35

Еще раз и медленно:

Вы пишите модуль, которые вызывается из АРМа Каталогизатор с панели и модифицирует ТЕКУЩУЮ запись? В таком случае вы или должны ограничится работой в рамках этого метода (тоесть, передавать данные с кодом возврата, обозначающим модиыикацию), или должны делать это автономно, не вызывая запись в Каталогизаторе. На самом деле вы получили не одну проблему ,а две:

1. Если вы передаете слишком большой пакет данных, то Ирбис их обрезает по размеру своего буффера. Я не помню какой именно размер буффера в Каталогизаторе, но в Книговыдаче 2012 его можно регулировать в самом ини-файле. У меня похожая проблема была при передачи фотографий в запись. решилась увеличением буффера. Но это касается Книговыдачи. Вам надо написать Александру Иосифовичу, возможно он согласится сделать буффер для Каталогизатора таким же параметрируемым, как и для Книговыдачи.

2. Сообщение о несоответствии. Когда вы используете клиентскую библиотеку для доступа к БД Ирбиса, вы фактически создаете другой АРМ, который работает с данными. И вот у вас ситуация, при которой ДВА РАЗНЫХ АРМА работают с ОДНОЙ записью. И это естественно, что если один из них внесет изменения и сохранит, то другой начнет паниковать: ведь он на редактуру взял запись в одном виде, а когда пытался сохранить, то выяснил что эта запись уже кем-то модифицирована.

Re: Ошибка сохранения записи при возврате результата из плагина
Пользователь: S-presso (IP-адрес скрыт)
Дата: 14, January, 2013 14:09

Цитата:
Gena
Вы пишите модуль, которые вызывается из АРМа Каталогизатор с панели и модифицирует ТЕКУЩУЮ запись?

Нет, я сейчас пишу своеобразную замену для Каталогизатора (АРМ "АльтерВвод") с некоторым минимальным набором функций, но с поддержкой плагинов, которые точно так же вызываются кнопкой с панели. Один из этих плагинов предназначен для автоматизации ввода оглавления. Вот в нём для добавления оглавления к текущей записи (передаваемой как первый параметр buf1) используются функции клиентской библиотеки.

Цитата:
И это естественно, что если один из них внесет изменения и сохранит, то другой начнет паниковать: ведь он на редактуру взял запись в одном виде, а когда пытался сохранить, то выяснил что эта запись уже кем-то модифицирована.

Мой плагин не сохраняет изменения в записи в БД, а просто передаёт её обратно в виде второго параметра (buf2). АРМ "АльтерВвод" подхватывает эту запись (присваивает её текущей: record = buf2), отображает изменения в рабочем листе и последовательно меняет её MFN (иначе при сохранении запись попадает в конец) и актуализирует её с помощью функции IC_ifupdate (иначе при сохранении возникает ошибка о несоответствии версий). В принципе жить можно, поскольку в нужной позиции ЭК уже сохранены обработанные данные, но, как я говорил, для журналов при этом теряется вся информация о номере (её потом приходится вручную копировать из других записей в Каталогизаторе). Для книжных изданий вроде ничего не теряется, но поскольку в оптимизированном формате мой АРМ показывает для такой записи "мусор", очевидно, что-то здесь не так.

Re: Ошибка сохранения записи при возврате результата из плагина
Пользователь: Gena (IP-адрес скрыт)
Дата: 14, January, 2013 14:18

Эм... Что-то вы перемудрили:

Для чтения и записи хватает:

//Создали буффер для записи
GetMem(AnswerZap,buffer);

//Прочитали запись с МФН - Amfn
retval := IC_read('RDR',Amfn,1,AnswerZap,buffer);

//Модифицируем буффер с записью - AnswerZap

//Записываем модифицированную запись в открытую ранее
retval := IC_update('RDR',0,1,AnswerZap,buffer);

//Освободили буффер записи
FreeMem(AnswerZap);

Re: Ошибка сохранения записи при возврате результата из плагина
Пользователь: S-presso (IP-адрес скрыт)
Дата: 14, January, 2013 14:39

Возможно, и перемудрил, но я делал именно так, как вы написали, и у меня не работало (IC_update возвращала код -608). Точнее, работало раньше, когда все модификации с записью производилось в рамках одной программы. Теперь же оглавление добавляется к записи во внешнем плагине, а при возврате из него старой записи просто присваивается адрес новой. И возникают описанные мной проблемы. А то, что я использовал в качестве 3-го параметра IC_read 0, а не 1, имеет какое-то значение?

Re: Ошибка сохранения записи при возврате результата из плагина
Пользователь: Gena (IP-адрес скрыт)
Дата: 14, January, 2013 14:56

тертий параметр - это как бы подстраховка от ситуации, когда вы начали редактировать запись и кто-то еще в нее зашел и изменил ее завершения редакции записи вами.

Все равно не понимаю проблему. передавайте во внешнюю процедуру буффер с вашей записью, а потом при отработки комманды IC_update подавайте модифицированный буффер ей на сохранение. Скиньте мне на емейл кусок кода, который отвечает за чтение, модификацию и сохранение

Re: Ошибка сохранения записи при возврате результата из плагина
Пользователь: S-presso (IP-адрес скрыт)
Дата: 14, January, 2013 15:23

Ну, я вообще пишу сейчас на C++ Builder, возможно, из-за этого делаю что-то не так. Кстати, не сразу удалось выяснить, что вместо GetMem(AnswerZap,buffer) и FreeMem(AnswerZap) здесь нужно использовать PChar AnswerZap = (PChar)malloc(buffer); и free(AnswerZap). Так же есть нюанс в описании заголовка функции плагина, вызываемой из АРМа: не

int function(char* buf1, char* buf2, int bufsize); как это описано в документации, а

int function(char* buf1, PChar& buf2, int bufsize); или
int function(PChar buf1, PChar& buf2, int bufsize);

иначе не передаётся обратно значение второго параметра.

Геннадий, ещё такой вопрос: можно ли с помощью ЯФ передать в плагин только отмеченные галочкой в Каталогизаторе поля записи? Например, если я хочу сразу напечатать карточки на некоторые из статей, имеющихся в оглавлении сборника.

Re: Ошибка сохранения записи при возврате результата из плагина
Пользователь: Gena (IP-адрес скрыт)
Дата: 14, January, 2013 15:46

C C++ не знаком, не смогу прокомментировать вызов функций. Мне кажется, что передавать только отмеченные средствами ЯФ невозможно. Сделайте по другому: передали все нужные поля, вывели в начале форму с галочками напротив всех полей и кнопку выполнения действий с отмеченными.

Re: Ошибка сохранения записи при возврате результата из плагина
Пользователь: S-presso (IP-адрес скрыт)
Дата: 14, January, 2013 15:57

А у вас все плагины всегда срабатывают из Каталогизатора? У меня вот нет - достаточно попробовать подключить к Каталогизатору те 2 DLL'ки, что я создавал здесь в теме про экспорт из Лани. Я даже переписал плагин для анализа библиографического описания на C++ Builder, но он по-прежнему нестабильно срабатывает. К моему собственному АРМу всё как-то получше пристыковывается (хотя у меня на ноутбуке сейчас при загрузке плагина для оглавления всплывает ошибка, но это, видимо, из-за различных версий .NET Framework).

Re: Ошибка сохранения записи при возврате результата из плагина
Пользователь: Gena (IP-адрес скрыт)
Дата: 14, January, 2013 16:02

У меня никаких проблем с модулями нет - срабатывают штатно. Есть случаи и с двумя ДЛЛ.

Re: Ошибка сохранения записи при возврате результата из плагина
Пользователь: S-presso (IP-адрес скрыт)
Дата: 23, January, 2013 10:36

Разобрался с описанной проблемой. Всё работает так, как писал Gena, в том случае, если я перед вызовом функции из DLL плагина присваиваю её первому параметру адрес текущей записи: buf1 = dbAccess.record;
Проблема возникала из-за того, что я задавал этому параметру не просто значение текущей записи, а применял для этой записи форматирование - в соответствии с документацией, используя значение UMPFTn - имя формата, в соответствии с которым осуществляется передача входных данных в функцию плагина. Для этого использовалась функция IC_record_sformat. Так вот, полученная с её помощью запись всегда имеет версию 0 (т.е. 0#0 в строке вида 0#<версия записи>), в то время как исходная запись могла иметь большую версию. Из-за этого и возникала ошибка несоответствия версий -608, когда я присваивал dbAccess.record адрес записи buf2, возвращаемой функцией плагина (которая в свою очередь содержит изменённое значение buf1) и пытался потом сохранить эту запись. Не найдя в библиотеке irbis64_client.dll функции для модификации версии записи (IC_ifupdate здесь не подходит), я стал править значение версии buf2 после 0# ручками (применяя методы для работы со строками из разработанного мной класса NETString - т.е. класса для операций со строками, как в .NET), приводя его в соответствие с версией текущей записи dbAccess.record, а затем сохраняя новое значение записи с помощью StrLCopy() и, наконец, присваиваю адрес этой записи текущей записи: dbAccess.record = buf2;

Таким образом сохранение срабатывает, и я могу добавлять к записи оглавление, возвращаемое из вызванного плагина. Кстати, чтобы привести запись к нормальному виду после форматирования с помощью IC_record_sformat, всё-таки мне, кроме изменения её версии, приходится ещё применять к ней функцию IC_changemfn и удалять вписанную в запись строку форматирования. Что же до простого способа, описанного Геннадием, то я использую его для тех случаев, когда форматирование с помощью IC_record_sformat не удалось (например, файл форматирования не найден):

PChar buf1 = dbAccess.formatRecord("@" + dllInfo [num].PFT);
if (String(buf1) == "")
buf1 = dbAccess.record;

В общем, не знаю, как всё это реализовано у самих разработчиков Ирбиса, но, не считая описанной заморочки с версиями записей, моя программа сейчас работает с внешними плагинами лучше, чем АРМ Каталогизатор :)

Re: Ошибка сохранения записи при возврате результата из плагина
Пользователь: Alio (IP-адрес скрыт)
Дата: 23, January, 2013 11:17

Что за странная идея вызывать запись для корректировки с помощью функции IC_record_sformat
Для этого существует функция
IC_read

Re: Ошибка сохранения записи при возврате результата из плагина
Пользователь: S-presso (IP-адрес скрыт)
Дата: 23, January, 2013 13:38

Так это только для передачи записи во внешний плагин я вызываю IC_record_sformat. Ведь там присутствует такой параметр, как имя файла форматирования (UMPFTn=<имя файла> в файле irbisc.ini). Для него-то у меня и вызывается функция IC_record_sformat. Собственно, для своих плагинов я мог бы этого и не делать, поскольку у меня там передаётся вся запись целиком (без форматирования), просто я думал о том, как бы сделать свою программу совместимой с Каталогизатором (в т.ч. в отношении формата плагинов).



Извините, только зарегистрированные пользователи могут писать в этом форуме.
This forum powered by Phorum.