Добавил:
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.4. $STACK() 391
или дополнительный код состояния стека
$STACK(level,"ETRAP")
чтобы можно было определить, что строка команд не принадлежит рутине, а задана в обработчике ошибок, выполняющегося в этот момент, в
$ETRAP.
Этот пример показывает отличие системной переменной $STACK и
максимально доступного для анализа уровня $STACK(-1). Показано, что
в состоянии ошибки система удерживает максимально доступную для
анализа ошибки информацию о стеке.
При этом выполнение обработчика ошибки
d show
в состоянии стека не отображается, хотя при его выполнении производится изменение состояния стека.
Этот нюанс очень важен, поскольку именно обработчик ошибки, строка команд указанная в $ETRAP, выполняется вместо строки, вызвавшей
ошибку, и, если бы $STACK() возвращала информацию о стеке как он
исполняется, то информация о собственно месте происхождения ошибки
была бы утрачена.
К ключевой проблеме функции $STACK(), как видно из ее определения и поведения, можно отнести то, что она возвращает данные в
зависимости от того, находится ли процесс в состоянии ошибки или нет.
Технически, в процессе могут возникнуть также ошибки в обработчике ошибок, сам обработчик ошибок может использовать и перезаписывать фреймы стека и использовать большие уровни, чем сохраняется для
функции $STACK() в момент ошибки.
Выглядит более разумным такое определение функции $STACK(),
чтобы ее поведение было точным и однозначным. Например, для того,
чтобы $STACK() возвращала реальное состояние стека как он исполняется на текущий момент, а дополнительная функция $ESTACK() возвращала бы состояния стека в зависимости от заданного первым параметром номера ошибки. В этом случае программисты могут получить точные состояния стека для каждой из последовательности произошедших
ошибок, пока процесс не выйдет из состояния ошибки присваиванием:
set $ecode=""

392 ГЛАВА 5. ОБРАБОТКА ОШИБОК
5.5 Трассировка
Трассировка, и как механизм, и как методика, относится к простейшим и
общедоступным отладочным средствам. В некоторой степени трассировка является намного более детализированным вариантом логгирования
работы программы.
В книге часто применяется трассирование выполнения программ для
иллюстрирования их работы. В своей основе трассировка программ есть
внедрение в программу команд вывода информации, необходимой и понятной для разработчика, а логгирование это внедрение в программу
команд вывода информации, необходимой для администратора.
По логгированию обычно видна работы программы в сильно укрупненном виде, например операция старта или останова, как именно они
закончились, происходили ли критические ошибки.
По трассировке программ видна последовательность их выполнения,
значения необходимых для анализа величин - локальных, глобальных и
системных переменных, вычисленные параметры оценки работы, например общее время или количество чего-то.
В отличие от логгирования, команды трассировки удаляются из готовой программы и, наоборот, добавляются для проведения отладки.
При локализации ошибки общий прицип поиска ошибок состоит в
объединении следующих пунктов:
1. Составление контрольного теста для воспроизведения проблемы.
2. Определение критерия момента перехода программы в некорректное состояние.
3. Установка контрольных меток трассировки с выводом индикатора
корректности.
4. Найдя моменты, между которыми возникает проблемное состояние,
этот участок кода детализируется более подробно.
Последовательность таких шагов локализует место происхождения
проблемы, последовательно сужая интервал между найденными состояниями "до ошибки" и "после ошибки".
В MUMPS системах зачастую в комплект инсталляции входит рутина
или набор рутин для проведения трассировки состояния виртуальной
машины исполнения. Обычно такие рутины именуются с префиксами,
производными от Error Trapping:

5.5. ТРАССИРОВКА 393
^%ET
^%ETN
^%ETL
Рутины трассировки состояния виртуальной машины обычно имеют
две точки входа - трассирование с завершением состояния обработки
ошибок и трассирование без завершения состояния обработки ошибок.
В этом случае их можно использовать в зависимости от необходимости.
При этом рутины трассировки по умолчанию производят сохранение
состояния процесса в относительно универсальном виде, включая, например, все значения локальных переменных. В реальных прикладных
системах сама такая информация может быть недостаточно информативной для анализа ошибки и многие прикладные системы содержат собственные средства трассировки состояния процесса и его отображения. В
этом случае разработчики могут вывести более информативно состояние
контекста процесса, например, кроме идентификатора текущего пользователя его более осмысленное описание, прочитанное из глобалов, а
также состояние критичных для анализа глобалов.
Как вариант трассировки состояния виртуальной машины можно посмотреть пример вывода состояния стека с использованием функции
$STACK().
Собственно сам вывод информации о состоянии процесса в осмысленном виде может занять большой объем, поскольку в него могут
включаться значения $STACK(), системных переменных, локальных переменных, обращение к различного рода системно-зависимым функциям
$VIEW() и командам VIEW, критичные для понимания работы программы записи в глобалах.
В большинстве случаев вывод данных производится не совсем так,
как приведено в книге (в виде простого вывода на экран), хотя во многих
случаях для локализации проблем и такого варианта может быть достаточно. Трассировка зачастую выполняется либо в файл, либо в глобал.
После чего можно просмотреть состояние файла или глобала или применить к глобалу специальные средства поиска.
В некоторых случаях отладочная информация о выполнении программы может занимать мегабайты относительно одинаковых строк, в которых необходимо что-то найти или сопоставить. Поэтому, в тех случаях,
когда по характеристикам выполнения программы ожидается очень большой вывод, разработчики чаще применяют вывод в текстовые файлы, а
когда небольшой - в глобалы.
При выводе в текстовый файл (и вообще при любой трассировке)
разработчики должны понимать, то функция трассировки должна изменить контекст выполнения процесса наименьшим образом, и необходимо

394 ГЛАВА 5. ОБРАБОТКА ОШИБОК
сохранять и восстанавливать значения системных переменных, которые
могут быть критичны для выполнения процесса. К таким в первую очередь относятся:
1. Текущее устройство ввода-вывода, значение $IO.
2. В случае если значение $PRINCIPAL может быть изменено, то его
также надо восстанавливать.
3. Значение последней глобальной ссылки (naked indicator), значение
$REFERENCE или $ZREFERENCE.
4. Значение системной переменной $TEST.
5. Все используемые функцией трассировки локальные переменные не
должны сохраниться после выхода из трассировки и, желательно,
не должны измениться критические для работы процесса локальные переменные.
При многопользовательской работе необходимо также различать различные трассировки, выполненные разными процессами, запущенные
разными пользователями. В этом случае разработчики при выводе в
файл получают следующий номер файла, либо при выводе в глобал,
получают следующий индекс глобала, например, системной функцией
$INCREMENT(), и используя в имени индекса или глобала что-то идентифицирующее или пользователя, запустившего процесс, или компьютер
с которого подключились к MUMPS системе. В этом случае в общем
списке имеющихся трассировок можно относительно просто найти интересующую.
При работе функции трассировки могут возникнуть проблемы, которые она может быть неспособна преодолеть и функция должна корректно
отнестись к ситуации невозможности выполнить трассировку. К таким
условиям относится работа в состоянии нехватки ресурсов.
Нехватка ресурсов может наступить как до срабатывания трассировки (работа в контексте обработчика ошибки, возникшей из-за нехватки
ресурса), так и во время (программа работает на пределе доступных
ресурсов).
В практической работе автор сталкивался с такими ситуациями, когда программа исчерпывает доступный ей ресурс, переходит к обработке
ошибок, но обработчик ошибок сам не может выполниться корректно,
поскольку ему также необходимы какие-то ресурсы. Обычно такая ситуация характеризуется тем, что одновременно и программа не работает

5.5. ТРАССИРОВКА 395
корректно и, при этом, нет и не может появиться никаких диагностических сообщений.
В такую ситуацию могут попасть не только программы на MUMPS,
но и любые другие, которые в обработчике ошибок полагают, что все
необходимые им ресурсы доступны. Как раз при исчерпании таких ресурсов эти обработчики не могут выполниться корректно.
Те случаи, когда программа не выполняет необходимые действия и не
сообщает об этом, хотя имеет такую возможность, относятся к ошибкам
программистов. В частности, если утилита копирования файлов может
ничего не сообщить на экран о неудаче копирования файла в случае
полного исчерпания места на диске.
В MUMPS системах к типовым ситуациям нехватки ресурсов в контексте работы функций трассировки состояния относятся:
1. Исчерпание памяти для локальных переменных (ошибка STORE в
системах Cach´e и MiniM).
2. Исчерпание доступного места в базе данных и невозможность его
расширения из-за административного ограничения.
3. Исчерпание доступного места в базе данных и невозможность его
расширения из-за исчерпания дискового пространства.
4. Исчерпание лимита на число одновременно открытых устройств
ввода-вывода.
5. Исчерпание таблицы блокировок, если они используются при трассировке.
При правильном проектировании функции трассировки и обработчика ошибок такие ситуации должны определяться программно и, при
невозможности выполнить трассировку обычными средствами, должны
использоваться аварийные средства логгирования, не расходующие ресурсы MUMPS системы.
К таким могут быть отнесены встроенные в MUMPS системы средства логгирования в текущий лог самой MUMPS системы или средства
логгирования, предоставляемые операционной системой. В Windows системах, в частности, к таким средствам могут быть отнесены средства
Event Logging.
И, к числу проблем, специфических для трассировки в контексте
СУБД, относится работа трассировки с сохранением информации в глобал в контексте транзакции. В случае, если после функции трассировки

396 ГЛАВА 5. ОБРАБОТКА ОШИБОК
процесс вызывает откат транзакции, могут быть также отменены и все
записи, сделанные в глобал трассирования. В этом случае разработчики должны выбрать подходящее решение, поддерживаемое используемой
MUMPS системой:
1. Трассирование в глобал, на который не распространяется откат
транзакции.
2. Трассирование в глобал в базе данных, на которую не распространяется откат транзакции.
3. На время трассировки отключать режим журналирования для процесса.
Разумеется, что при использовании отключения режима журналирования он, после выполнения трассировки, также должен быть восстановлен в предыдущее состояние.
Несмотря на то, что общий принцип трассировки выполнения процесса и состояния процесса на первый взгляд очень простой, реальное
и полноценное его исполнение может потребовать достаточно больших
усилий из-за необходимости учитывать множество нюансов и самой разрабатываемой прикладной системы, и используемой MUMPS системы, и
операционной системы.
5.6 BREAK
Команда BREAK относится к встроенным отладочным средствам. Команда декларирована в стандарте языка, но ее реальное поведение, параметры и использование никак не определены и отводятся на усмотрение
реализации MUMPS системы.
Общий принцип работы команды BREAK состоит в применении терминального или консольного режима, интерактивном вызове команды
для выполнения отладочных операций и организации ввода-вывода в
консоли непосредственно оператором, разработчиком или администратором.
К отладочным операциям, выполняемым командой BREAK, относятся установка и снятие точек или условий останова, либо для явного
перехода в режим интерактивной отладки.
В каждой из MUMPS систем реализация команды BREAK выполнена по-своему. MUMPS системы сохраняют общий стиль и назначение

5.6. BREAK 397
команды BREAK, поэтому у различных реализаций могут быть и совпадающие нюансы этой команды.
Принцип использования BREAK состоит в расстановке в нужных
программисту местах точек останова либо задании таких точек выполнением команды BREAK. В зависимости от параметров команды процесс либо продолжает выполнение, либо останавливается в нужном месте и переходит в интерактивный режим. Программист может вывести
на экран значения переменных, вызвать системные функции $VIEW()
и команду VIEW для определения состоянияи продолжить выполнение
программы либо по одной команде либо далее целиком как есть, либо
прервать полностью.
Синтаксис применения BREAK в MUMPS системе Cach´e:
BREAK:pc status
BREAK:pc "extend"
В первой форме команда отключает либо включает прерывания по
комбинации Ctrl+C, а во второй форме устанавливает тип останова для
перехода в интеративный режим.
В зависимости от значения параметра "extend" процесс может перейти в режим исполнения по одной команде, по одной строке команд, либо
отключить остановы по команде BREAK и далее продолжить выполнение программы. В состоянии ожидания ввода программиста система
поддерживает безаргументную форму команды GOTO для продолжения
выполнения программы.
Положим, что есть программа для демонстрации BREAK:
STEPS
B "S+"
N I
F I=1:1:3 W I,!
Q
При ее выполнении получаем пошаговое прохождение ее выполнения,
фрагмент работы программы:
USER>d STEPS^BREAK
B "S+"
^
<BREAK>STEPS+1^BREAK
USER 2d0>g
N I

398 ГЛАВА 5. ОБРАБОТКА ОШИБОК
^
<BREAK>STEPS+2^BREAK
USER 2d0>g
F I=1:1:3 W I,!
^
<BREAK>STEPS+3^BREAK
USER 2d1>g
F I=1:1:3 W I,!
<BREAK>STEPS+3^BREAK
USER 3f2>g
1
F I=1:1:3 W I,!
<BREAK>STEPS+3^BREAK
USER 3f2>
^
^
При этом MUMPS система Cach´e дополнительно предлагает расширенную и намного более мощную по своим возможностям команду
ZBREAK, которая работает также в контексте терминального режима:
ZBreak location[:action:condition:execute_code]
Значения параметров команды:
location Задает место останова в виде метки или,
если начинается с символа "*", задает имя
локальной переменной для останова при
изменении этой локальной переменной.
action Задает режим перехода в отладочное со-
стояние с ожиданием ввода от программиста, аналог параметра "extend" для команды BREAK.
condition Задает условие срабатывания точки оста-
нова, выражение на языке MUMPS. Если параметр опущен, то условие считается
истинным по умолчанию.
execute_code Строка команд, которую надо выполнить
при переходе в режим останова.
Например, задание точки останова для переменной A и с проверяемым условием останова:

5.6. BREAK 399
ZBreak *A::"’$D(A)"
Эта точка останова срабатывает при таком изменении локальной пе-
ременной A, после которого значение выражения
’$D(A)
становится истинным, например:
%SYS>K A
K A
^
<BREAK>
%SYS 1s0>
Еще несколько примеров установки точек отладки из документации
по Cach´e:
Установить точку останова при переходе на строку TAGˆROU с пере-
ходом в режим построчного прохождения:
ZBreak TAG^ROU:"L"
Установить точку останова при переходе на строку TAGˆROU, но не
останавливаться (action="N"), и если выполняется условие X < 1, то
записать в переменную FLAG значение переменной X:
ZBreak TAG^ROU:"N":"X<1":"S FLAG=X"
Полный перечень параметров и опций команд BREAK и ZBREAK
приведен в документации на MUMPS систему Cach´e. При использовании команд отладки также необходимо изучить способы продолжения
выполнения программы, команды GOTO, QUIT и ZQUIT, зависимые от
реализации и версии системы.
В MUMPS системе GT.M команда BREAK задает останов выполнения программы и выполнение указанной строки команд перед переходом
в интерактивный режим отладки:
B[REAK][:tvexpr] [expr[:tvexpr][,...]]
Если выполнение программы доходит до команды BREAK, то проверяется ее постусловие, и, если оно выполняется, то процесс переходит
в интерактивный режим. При этом выполняются задаваемые строки команд.
Выдержка из документации на команду BREAK в системе GT.M:

400 ГЛАВА 5. ОБРАБОТКА ОШИБОК
GTM>ZPRINT ^br
br;
kill
for i=1:1:3 do break;
quit
break;
write "Iteration ",i,?15,"x=",$get(x,"<UNDEF>"),!
break:$data(x) "write ""OK"",!":x,"write ""Wrong again"",!":’x
set x=$increment(x,$data(x))
quit
GTM>DO ^br
Iteration 1 x=<UNDEF>
Iteration 2 x=0
%GTM-I-BREAK, Break instruction encountered
GTM>ZCONTINUE
Wrong again
%GTM-I-BREAK, Break instruction encountered
GTM>ZCONTINUE
Iteration 3 x=1
OK
%GTM-I-BREAK, Break instruction encountered
GTM>ZCONTINUE
%GTM-I-BREAK, Break instruction encountered
At M source location break+2^br
At M source location break+2^br
At M source location break+2^br
At M source location break+2^br
GTM>ZCONTINUE
GTM>
Здесь при выполнении кода процесс переходит в интерактиный режим отладки и сообщает о причине останова, а продолжение выполнения
процесса происходит по команде ZCONTINUE.
Кроме команды BREAK MUMPS система GT.M предлагает также
более мощную расширенную команду ZBREAK, имеющую больше возможностей, чем команда BREAK:
ZB[REAK][:tvexpr] [-]entryref[:[expr][:intexpr]][,...]
Команда ZBREAK может установить и снять точку останова на указанной строке, проверить выполняется ли выражение и назначить счетчик на срабатывание точки останова, чтобы пропустить первые N остановов.
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
