Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:MUMPS СУБД. Практика применения и опыт программирования.pdf
X
- •Предисловие
- •Введение
- •Среда исполнения
- •Команды
- •Команды присваивания
- •Условные команды
- •Команды передачи управления
- •Команды ввода-вывода
- •Служебные команды
- •Постусловия
- •Операторы
- •Переменные
- •Числа и строки
- •Функции
- •$DATA
- •$GET
- •$ORDER
- •$NEXT
- •$QUERY
- •$NAME
- •$QLENGTH
- •$QSUBSCRIPT
- •$ASCII
- •$CHAR
- •$EXTRACT
- •$PIECE
- •$LENGTH
- •$REVERSE
- •$FIND
- •$TRANSLATE
- •$JUSTIFY
- •$FNUMBER
- •$TEXT
- •$RANDOM
- •$VIEW
- •$SELECT
- •$STACK
- •Списковые функции
- •Битовые функции
- •Модули
- •Рутины
- •Передача параметров
- •Неопределенные значения
- •Шаблоны
- •Косвенность
- •Косвенность имени
- •Косвенность индексов
- •Косвенность метки
- •Косвенность аргумента
- •Косвенность шаблона
- •Интерпретатор
- •Голая ссылка
- •Очередность выполнения
- •Очередность вычисления выражений
- •Очередность вычисления имен
- •Стекование $test
- •Комментарий
- •Стандарт и расширения
- •Глобалы
- •B-дерево
- •Кодирование индексов
- •Размер блока
- •Кеширование блоков
- •Структуры
- •Индексация
- •Группировка
- •Каноничность индексов
- •Маппинг
- •Индексация данных
- •Общие принципы
- •Механизм поддержки индекса
- •Простой индекс
- •Составной индекс
- •Покрывающий индекс
- •Кластерный индекс
- •Хеш-индекс
- •Битмап индекс (bitmap)
- •Битслайс индекс (bitslice)
- •Нормирование значений
- •Выборки по индексу
- •Многоиндексная выборка (zig-zag)
- •Дифференциальное индексирование
- •Индексация длинных атрибутов
- •Межтабличный индекс
- •Индекс с условием на вставку
- •Индекс на вычисляемый атрибут
- •Индекс поиска по фрагменту
- •Индексация для шаблона (like)
- •Индексация уникального атрибута
- •Массовое перестроение индексов
- •Операции с древовидными индексами
- •Операции с битовыми индексами
- •Сортировка по индексу
- •Статистики и кардинальность
- •Конкурентный доступ
- •Параллельность выполнения
- •Блокировки
- •Функция $INCREMENT
- •Транзакции
- •Блокировки в транзакциях
- •Функция $BIT
- •Дедлоки
- •Обработка ошибок
- •Состояние ошибки
- •ZTRAP
- •GT.M
- •MiniM
- •ETRAP
- •Определение
- •$ETRAP
- •$ECODE
- •$ESTACK
- •Ошибки в обработчике ошибок
- •$STACK()
- •Трассировка
- •BREAK
- •MiniM Debugger
- •Serenji Debugger
- •Внешний мир
- •Общие принципы
- •Терминальный интерфейс
- •Сокеты
- •HTTP клиент
- •Вебсервер на MUMPS
- •WebLink
- •Проблемы HTTP
- •Поверх HTTP
- •Подключаемые DLL (SO)
- •Файлы
- •Внешние процессы
- •Порты
- •Практика применения
- •Терминальный режим
- •Редакторы рутин
- •Экспорт и импорт
- •Препроцессор
- •Формат $HOROLOG
- •Опции устройств
- •$X и $Y
- •Возврат результатов
- •Возврат по значению ($$)
- •Возврат по ссылке
- •Запись в предопределенную переменную
- •Возврат значений косвенно
- •Итеративный возврат
- •Потоковый возврат
- •%Z - рутины
- •Планирование файлов
- •Память и сборка мусора

5.2. ZTRAP 361
В определение обработчика ошибок входит 3 пункта: 1) что делать со
стеком, 2) какой код нужно выполнить и 3) критерий окончания обработки. В случае использования обработчика ZTRAP в Cach´e третий пункт
выполняется автоматически, как только система выполнит переход на
обработчик ошибок по неявной команде GOTO.
К отличительной особенности перехода по GOTO относится возможность перейти на метку из различных точек выполняемого кода (строк),
на которые мы можем попасть в различном контексте вызова - с ожиданием возвращаемого значения или без. И, для того, чтобы обработчик
корректно отнесся к возврату при выполнении неявной команды GOTO,
нужно указать возврат в зависимости от значения системной переменной
$QUIT. Покажем, как может сработать обработчик, не учитывающий
контекст возврата:
proc() ; k w $$proc^ZTRAP() w
s $ztrap="err"
w "in proc, $st=",$st,!
w 1/0
w "exit proc, $st=",$st,!
q 11
err
w "in err, $st=",$st,!
q
Это тот же самый код, но предназначенный для вызова с возвратом
значения:
USER>k w $$proc^ZTRAP() w
in proc, $st=1
in err, $st=1
K W $$proc^ZTRAP() W
^
<COMMAND>
USER>
Здесь команда QUIT в обработчике ошибок вошла в конфликт по своей форме (безаргументной) с контекстом вызова с ожиданием возврата.
Чтобы исправить ситуацию и сделать обработчик ошибки более универсальным, модифицируем его, чтобы учитывалось значение $QUIT:
proc() ; k w $$proc^ZTRAP() w
s $ztrap="err"
w "in proc, $st=",$st,!
w 1/0

362 ГЛАВА 5. ОБРАБОТКА ОШИБОК
w "exit proc, $st=",$st,!
q 11
err
w "in err, $st=",$st,!
q:$Q "was error" q
И этот вариант уже корректно срабатывает в обоих случаях вызова:
USER>k w $$proc^ZTRAP() w
in proc, $st=1
in err, $st=1
was error
USER>d proc^ZTRAP
in proc, $st=1
in err, $st=1
В случае если в обработчике ошибки также происходит ошибка, то
при его срабатывании также вызывается обработчик ошибок. Если программист не изменил значение $ZTRAP, то при его выполнении программа зацикливается. Приведем модифицированный пример для иллюстрации:
proc() ; k w $$proc^ZTRAP() w
s count=0
s $ztrap="err"
w "in proc, $st=",$st,!
w 1/0
w "exit proc, $st=",$st,!
q 11
err
i count=1 w "already in err",! q:$Q "was error" q
s count=1
w "in err, $st=",$st,!
w 1/0
q:$Q "was error" q
При его выполнении получаем отчет о ходе обработки ошибки:
USER>k w $$proc^ZTRAP() w
in proc, $st=1
in err, $st=1
already in err
was error
count=1
USER>
Другим способом избежать зацикливание в обработчике ошибок является самостоятельная очистка текущего обработчика ошибок $ZTRAP
в самом обработчике:

5.2. ZTRAP 363
proc() ; k w $$proc^ZTRAP() w
s $ztrap="err"
w "in proc, $st=",$st,!
w 1/0
w "exit proc, $st=",$st,!
q 11
err
s $zt=""
w "in err, $st=",$st,!
w 1/0
q:$Q "was error" q
В этом случае процесс, попав в обработчик, в нем использует обработчик ошибок, установленный на более высоком уровне, или, если он
не был установлен, то переходит к обработке ошибки по умолчанию:
USER>k w $$proc^ZTRAP() w
in proc, $st=1
in err, $st=1
w 1/0
^
<DIVIDE>err+3^ZTRAP
USER 2e0>
При использовании системы Cach´e и обработчика в стиле ZTRAP
программисты чаще всего выбирают типовой способ его использования
с такими условиями:
1. Обработчик используется без указания символа "*", чтобы вне зависимости от глубины стека где произошла ошибка, управление
было передано на код, указанный программистом при установке
обработчика.
2. Обработчик устанавливается во всех функциях, где это важно, и с
самого верхнего уровня. Во вспомогательных функциях-утилитах
из разряда преобразований данных обработчик обычно не указывается.
3. В самом коде обработчика ошибок значение обработчика $ZTRAP
предварительно очищается во избежание зацикливания и чтобы
код мог перейти на обработку ошибки на более верхнем уровне
стека.

364 ГЛАВА 5. ОБРАБОТКА ОШИБОК
При этом нужно понимать, что выбор характера обработки ошибок в
каждом проекте может отличаться из-за различных методик или необходимости предпринимать какие-то особенные для прикладной программы
действия. Для этого изучаются требования к проекту, особенности работы обработчика ошибок в определенной MUMPS системе или даже ее
версии, и составляются правила его применения, чтобы группа программистов - участников проекта им далее следовала.
Старшие версии Cach´e также дополнительно проверяют синтаксис
значения $ZTRAP при присваивании и в случае недопустимого синтаксиса генерируют ошибку <SYNTAX>:
USER>s $zt="w w"
S $ZT="w w"
^
<SYNTAX>
5.2.2 MSM
В системе MSM поведение обработчика ZTRAP почти в точности аналогично его поведению в системе Cach´e, но с такими отличиями:
1. Не поддерживается символ "*" перед меткой обработчика ошибок
и MSM всегда передает управление на тот уровень стека, где он
был установлен последним.
2. Перед выполнением неявной команды GOTO для передачи управления на код обработчика ошибок значение обработчика $ZTRAP
автоматически сбрасывается в значение пустая строка.
И, также как и в Cach´e, в системе MSM критерием выхода процесса
из состояния ошибки является передача управления неявной командой
GOTO на метку обработчика.
Таким образом, для организации полностью совместимой между Cach´e
и MSM обработки ошибок с помощью ZTRAP нужно, чтобы програмисты не использовали символ "*" перед именем метки в значении $ZTRAP,
и в коде обработчика сбрасывали значение $ZTRAP в значение пустая
строка. И большинство программ, разрабатываемых как для MSM, так
и для Cach´e, действительно придерживается таких правил.

5.2. ZTRAP 365
5.2.3 DTM
В системе DTM (Data Tree MUMPS) обработчик ZTRAP также аналогичен по поведению системе MSM, но у программиста дополнительно есть
команда ZQUIT. Если код обработчика ошибок заканчивается командой
QUIT, то управление передается на тот уровень стека, на котором произошла ошибка, а если командой ZQUIT, то управление передается на
обработчик ошибок, установленный раньше по стеку.
5.2.4 M3
В MUMPS системе M3 (в настоящее время доступна реализация M3Lite) обработчик ZTRAP используется в зависимости от синтаксиса содержания системной переменной $ZTRAP.
Если значение $ZTRAP синтаксически соответствует имени метки,
то при обработке ошибки процесс выполняет возврат по стеку на уровень где было выполнено присваивание $ZTRAP и выполняет неявную
команду GOTO на указанную метку.
В случае если значение $ZTRAP синтаксически соответствует последовательности команд, то они выполняются вместо строки, на которой
произошла ошибка. В этом случае код команд должен выполнить передачу управления на иную строку командой GOTO или возврат командой
QUIT.
В случае если присваивается пустая строка, то обработчик на этом
уровне стека отменяется и далее процесс будет использовать обработчик,
указанный ранее по стеку.
5.2.5 GT.M
В системе GT.M обработчик ZTRAP устроен, видимо, наиболее сложным образом из современных MUMPS систем. Ключевая часть его функционала, видимо, и послужила прототипом для определения стандартного обработчика ошибок ETRAP.
К формальному определению $ZTRAP в системе GT.M можно отнести то, что эта системная переменная должна содержать последовательность команд, которые будут выполнены на манер команды XECUTE.
К дополнительным синтаксическим возможностям относится то, что она
может быть аргументом команды NEW и система GT.M различает, на
каком уровне стека был определен обработчик ошибок - если была применена команда NEW явно, то на этом же уровне стека, иначе присваивание системной переменной $ZTRAP изменяет значение на том уровне

366 ГЛАВА 5. ОБРАБОТКА ОШИБОК
стека где она была заведена ранее.
По умолчанию команда NEW, примененная к переменной $ZTRAP,
автоматически сбрасывает ее в значение пустая строка, поэтому обычно
следующей же командой идет присваивание $ZTRAP обработчика ошибок. В системе GT.M, в отличие от других, пустое значение не является
признаком обработчика по умолчанию. Если процесс попал в состояние ошибки при пустом $ZTRAP, то он завершает работу. В начальном состоянии процесса после его старта значение $ZTRAP равно "B",
что означает необходимость выполнить при ошибке команду BREAK, то
есть перейти в непосредственный режим управления процессом (Direct
Mode), и управление передается оператору для непосредственного ввода команд. При этом в системе GT.M имеется управление поведением
присваивания $ZTRAP через переменную окружения - если значение
переменной окружения gtm_ztrap_new вычисляется как TRUE, YES или
ненулевое число, то любое присваивание $ZTRAP приводит к неявному
выполнению команды NEW для $ZTRAP перед присваиванием. Применение NEW к переменной $ZTRAP позволяет сохранить предыдущие
определения обработчиков ошибок и автоматически восстановить предыдущее значение при возврате по стеку. В отличие от определения ZTRAP
в Cach´e, в GT.M обработчик ошибок всегда выполняется на том же
уровне стека где произошла ошибка, без автоматического возврата по
стеку к месту установки $ZTRAP.
Формально говоря, при возникновении ошибки в исполняемой строке, процесс GT.M переходит в состояние выполнения строки $ZTRAP
как если бы она была вместо исполняемой строки, или XECUTE без организации нового уровня стека. Критерий окончания состояния ошибки
- начало выполнения этой строки. При этом система GT.M различает, в
каком качестве и как использовать содержание переменной $ZTRAP.
В зависимости от значения переменной окружения gtm_ztrap_form,
процесс GT.M использует значение $ZTRAP следующими способами (по
умолчанию поведение GT.M соответствует значению code):
code Значение $ZTRAP используется как последо-
вательность команд, выполняемых при ошибке. Если управление не было передано командами GOTO, ZGOTO или QUIT какой-либо
другой строке кода, то после выполнения кода
$ZTRAP управление снова передается на начало строки, вызвавшей ошибку.

5.2. ZTRAP 367
entryref Значение $ZTRAP используется как имя мет-
ки для передачи управления неявной командой
GOTO.
adaptive Если значение $ZTRAP синтаксически являет-
ся последовательностью команд, то используется как было описано для "code", иначе используется как было описано для "entryref". В этом
случае процесс GT.M применяет распознавание
синтаксиса и действует адаптивно.
popentryref Процесс GT.M возвращается по стеку на уро-
вень, где было произведено последнее присваивание $ZTRAP и использует его значение как
имя метки для выполнения неявной команды
GOTO для передачи управления.
popadaptive Процесс GT.M возвращается по стеку на уро-
вень, где было произведено последнее присваивание $ZTRAP и использует его значение в
зависимости от синтаксиса - если это последовательность команд то они выполняются, если имя метки то на нее передается управления
неявной командой GOTO.
Кроме того, процесс GT.M использует еще одну переменную окружения процесса - переменную gtm_zyerror. Если ее значение синтаксически
соответствует имени метки, то при значениях переменной gtm_ztrap_form,
равным popentryref или popadaptive, процесс после возврата по стеку выполняет неявную команду DO для метки, указанной в переменной окружения gtm_zyerror, и лишь после возврата из нее передает управление
либо последовательности команд, либо метке, указанным в $ZTRAP.
В качестве иллюстрации поведения $ZTRAP приведем пример из
документации GT.M при присваивании переменной $ZTRAP последовательности команд:
GTM>ZPRINT ^EP6
EP6 WRITE !,"THIS IS "_$TEXT(+0)
BAD SET CB=CB+1 WRITE A SET CE=CE+1
NEW
NEW $ZTRAP SET $ZTRAP="DO ET"
SET (CB,CE)=0
WRITE !,"AFTER SUCCESSFUL EXECUTION OF BAD:",!
SET A="A IS NOT DEFINED"
ZWRITE
QUIT

368 ГЛАВА 5. ОБРАБОТКА ОШИБОК
ET W !,"CONTINUING WITH ERROR TRAP AFTER AN ERROR",!
GTM>do ^EP6
THIS IS EP6
CONTINUING WITH ERROR TRAP AFTER AN ERROR
CB=1
CE=0
A IS NOW DEFINED
AFTER SUCCESSFUL EXECUTION OF BAD:
A="A IS NOT DEFINED"
CB=2
CE=1
GTM>
ZWRITE
SET A="A IS NOW DEFINED"
Здесь при выполнении строки BAD генерируется ошибка неопределенного значения A, вызывается обработчик ошибок в виде последовательности команд
DO ET
в котором корректируется ошибка с определенностью переменной A.
Затем снова управление снова передается на строку BAD и в примере показывается, что оператор увеличения CB выполнился дважды, а
увеличения CE - единожды.
Тот же алгоритм обработки ошибки с использованием стандартного обработчика ETRAP, с возвратом управления на строку, вызвавшую
ошибку, выполняется таким способом:
GTM>ZPRINT ^EP6A
EP6A WRITE !,"THIS IS "_$TEXT(+0)
BAD SET CB=CB+1 WRITE A SET CE=CE+1
ET W !,"CONTINUING WITH ERROR TRAP AFTER AN ERROR",!
NEW
NEW $ETRAP SET $ETRAP="GOTO ET"
SET (CB,CE)=0
WRITE !,"AFTER SUCCESSFUL EXECUTION OF BAD:",!
ZWRITE
QUIT
ZWRITE
SET A="A IS NOW DEFINED"
SET RETRY=$STACK($STACK,"PLACE")
SET $ECODE=""

5.2. ZTRAP 369
GOTO @RETRY
GTM>DO ^EP6A
THIS IS EP6A
CONTINUING WITH ERROR TRAP AFTER AN ERROR
CB=1
CE=0
A IS NOW DEFINED
AFTER SUCCESSFUL EXECUTION OF BAD:
A="A IS NOW DEFINED"
CB=2
CE=1
RETRY="BAD^EP6A"
GTM>
Здесь для выполнения возврата на строку имя строки с ошибкой
вычисляется обращением к системной переменной $STACK и системной
функции $STACK. И в обработчике ошибок $ETRAP, и в конце кода
обработчика используются команды GOTO, сохраняющие уровни стека.
5.2.6 MiniM
В системе MiniM обработчик ZTRAP также выполнен с отличительными особенностями поведения, не совпадающими в точности с другими MUMPS системами. Вообще говоря, в системе MiniM отсутствует
отдельный механизм обработки ошибок ZTRAP как таковой, и присутствует только обработчик ETRAP. Системная переменная $ZTRAP
в MiniM используется исключительно для определенного уровня синтаксической совместимости с имеющимся кодом и при присваивании
$ZTRAP в действительности выполняется присваивание системной переменной $ETRAP в зависимости от содержания $ZTRAP.
В системе MiniM значение $ZTRAP сохраняется единственным для
всех уровней стека, вне зависимости от уровня на котором производилось присваивание.
При присваивании значения системной переменной $ZTRAP производится анализ его содержания и выполняются операции с присваиванием
и команда new с системными переменными $ESTACK и $ETRAP в зависимости от содержания $ZTRAP. В значении системной переменной
$ZTRAP допускается либо имя метки для перехода по команде goto,
либо метка и дополнительный символ "*" перед ней.

370 ГЛАВА 5. ОБРАБОТКА ОШИБОК
Если значение $ZTRAP при присваивании содержит только метку,
то при этом выполняется код эквивалентный коду:
new $estack
new $etrap
set $etrap="g:’$es "_$ztrap
Это соответствует раскручиванию стека выполнения до того уровня,
на котором был установлен обработчик, и переходу на обработчик по
команде goto.
Если значение $ZTRAP при присваивании содержит символ "*" перед
меткой, то при этом выполняется код, эквивалентный коду:
set $etrap="g "_$e($ztrap,2,$l($ztrap))
Это соответствует переходу на обработчик ошибок на уровень стека,
на котором возникла ошибка:
USER>s $zt="err^errhandler"
USER>w $et
g:’$es err^errhandler
USER>s $zt="*err^errhandler"
USER>w $et
g err^errhandler
В случае, если системной переменной $ZTRAP присваивается значение не соответствующее ни одной допустимой форме, то процесс MiniM
генерирует ошибку <SYNTAX>.
Поскольку в MiniM обработчик ZTRAP есть только переходник на
обработчик ETRAP, для выполнения кода совместимого по поведению с
другими MUMPS системами необходимо в коде обработчика очистить
значение системной переменной $ECODE. Эту очистку надо разместить
после того, как значение $ECODE было использовано, например, так:
n ec s ec=$ec s $ec=""
В этом случае обработка ошибки будет закончена выполнением кода
обработчика. Иначе, без очистки значения $ECODE при возврате из
обработчика, будет продолжена раскрутка стека до передачи управления
обработчику, установленному ранее.
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
