Добавил:
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 - рутины
- •Планирование файлов
- •Память и сборка мусора

4.8. TSN 351
lock +name:5 e w "lock failed",!
Существуют также системы баз данных и СУБД, которые применяют компенсатор по таймауту автоматически, и при возникновении ситуации невозможности получить захват ресурса, автоматически откатывают транзакцию и повторяют ее действия снова. В случае если рестарт
транзакций поддерживается используемой MUMPS системой, это также
может быть использовано разработчиками.
При использовании рестарта транзакций может также возникнуть
ситуация, когда при выполнении N рестартов операцию выполнить все
равно не удалось. В этом случае разработчики на MUMPS должны использовать значение системной переменной $TRESTART, показывающей
число рестартов, чтобы процесс мог принять решение стоит ли продолжать операцию снова. Вообще говоря, если алгоритм допускает дедлоки,
то причина дедлоков не устраняется повторным запуском алгоритма, и
дедлоки могут возникать при каждом его выполнении.
4.8 TSN
При выполнении транзакций СУБД должна реализовать механизм различения записей в журнале транзакций, какие записи к какой транзакции относятся. Для этого используется так называемый номер последовательности транзакций, или Transaction Sequence Number (TSN).
Каждая транзакция должна получить собственный уникальный номер, и этот номер должен отличаться как для различных процессов одного экземпляра сервера СУБД, так и между процессами сервера до его
останова и после последующего старта. Второе условие необходимо для
корректного продолжения журнала транзакций и процедуры автоматического восстановления сервера при старте.
К наиболее распространенным и достаточно устойчивым механизмам
генерации номера транзакций относится алгоритм основанный на времени генерации с синтетическим номером выравнивания. В номер транзакции входит, таким образом, два числа - дата с временем и синтетическое
число. Общий алгоритм состоит в следующем:
1. Сервер ведет используемую дату и синтетический номер, эти данные используют процессы сервера для генерации нового значения
TSN.
2. При старте сервера сервер отыскивает в журнальных записях наибольший из последних номеров TSN и выделяет в нем дату и синтетический номер.

352 ГЛАВА 4. КОНКУРЕНТНЫЙ ДОСТУП
3. Если текущая дата больше последней использованной, то она становится используемой и синтетический номер обнуляется.
4. Если текущая дата меньше или равна используемой, то для генерации TSN используется используемая, а синтетический номер
увеличивается.
5. При переполнении синтетического номера используемая дата увеличивается на одну секунду и синтетический номер обнуляется.
При такой схеме генерации значения TSN поддерживается правило их непрерывного возрастания, что позволяет корректно использовать
журнальные записи, оставшиеся от предыдущего сеанса работы сервера.
Кроме того, механизм генерации основанный на добавлении к текущей дате синтетического номера застрахован от одинаковых значений
TSN, полученных при одинаковом значении времени для различных процессов.
Наиболее важным следствием и задачей алгоритма является устойчивость к переводу времени на компьютере как в течении сеанса работы
сервера, так и между сеансами. Такой перевод времени может выполняться как вручную для исправления ошибки хода часов, так и автоматически при смене летнего и зимнего отсчета времени.
Задачей синтетического дополнения TSN является ожидание даты,
когда текущая дата и время компьютера догонит используемое. В случае
переполнения синтетического числа к используемому времени автоматически добавляется секунда и синтетический довесок обнуляется. Таким
образом, если на компьютере был произведен перевод часов на N секунд
назад, то сервер СУБД в течении этих N секунд будет использовать для
вычисления TSN более позднее время, а когда время сравняется, начнет
использовать текущее.
В случае если в реализации СУБД содержится ошибка в отношении генерации очередного значения TSN, это может проявиться самым
различным образом. В первую очередь либо некорректным откатом транзакции, в течении которой был произведен перевод времени, либо некорректным процессом старта сервера. Если администратор системы сможет
определить ситуацию сбоя, то может выполнить перевод времени на компьютере соответственно либо между сеансами работы СУБД, либо во
время сеанса. В любом случае, механизм генерации TSN является строго внутренним для СУБД, и при обнаружении проблем в работе сервера
необходимо обращаться в техподдержку СУБД.

Глава 5
Обработка ошибок
5.1 Состояние ошибки
MUMPS системы относятся к средам исполнения со встроенными языковыми средствами обработки и генерации ошибок. Уже на уровне языка
присутствуют средства реагирования на нарушение обычного хода выполнения программы либо на невозможность его продолжения по какимлибо причинам.
Если сравнить с контекстом выполнения программы, не имеющей
языковых средств обработки ошибок, то это может быть, к примеру
язык С, в котором обработка отдельных типов ошибок выполняется поразному в зависимости от типа ошибки, операционной среды, и, возможно, процессора. Например, обработка прерывания Ctrl+C и переполнения
числа с плавающей точкой выполняются совершенно разными способами, как и описание желания программы реагировать на них.
В MUMPS системах к средствам обработки ошибок относится само
понятие состояния процесса при генерации ошибки, специальные команды и системные переменные и функции, используя которые разработчик
определяет поведение программы при возникновении ошибки. В MUMPS
системах обработка ошибок, последовательность ее выполнения, набор
средств обработки ошибок не зависят от типа ошибки.
Штатное выполнение программы проходит в состоянии отсутствия
ошибки и последовательность выполнения определяется набором указанных для выполнения команд и функций. При возникновении же ошибки
система выполнения должна прервать штатное выполнение программы
и, не продолжая его, выполнить обработку ошибок. Обычное течение
программы далее невозможно. Например, при выполнении деления на
ноль или при попытке записи в базу данных находящейся в состоянии
353

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

5.1. СОСТОЯНИЕ ОШИБКИ 355
устройство диагностического сообщения и процесс переходит к ожиданию ввода следующих команд. При этом система переводит процесс в
состояние отсутствия ошибки, но сохраняет информацию об ошибке в
специальных системных переменных. Формат диагностического сообщения для каждой из MUMPS системы свой и содержит порцию описания,
которую система может предоставить. Обычно по такому диагностическому сообщению понятно, что произошло, и зачастую где именно или
с какими переменными.
Исторически сложилось так, что, хотя стандарт предусматривал состояние ошибки, стандартизированные средства и определение их поведения стандарт языка MUMPS начал предусматривать лишь с редакции
1995-го года.
MUMPS системы, разработанные до этого года, вводили обработку
ошибок на свое усмотрение, и в существенной степени совместимо друг
с другом по принципам поведения. При этом отдельные нюансы поведения различных MUMPS систем отличаются. К таким отличиям относится множество сочетаний собственно обработчика ошибок с другими
компонентами MUMPS системы:
1. Соотношение обработчика ошибок и состояния транзакций.
2. Сочетания поведения достандартного обработчика и стандартного,
их приоритеты.
3. Возможность обработки ошибок возникших в самом обработчике
ошибок.
4. Поведение встроенных команд отладки, например BREAK, ZGOTO,
ZQUIT и др.
5. Наличие и содержание дополнительных системных переменных,
например $ZSTATUS, $ZERROR и др.
В случае если разработчики прикладной системы используют лишь
определенный стандартом обработчик ошибок, то такие программы переносимы. В случае если используется достандартный, то при переносе
программ разработчикам необходимо сверить поведение используемых
ими нюансов таких обработчиков.
В настоящее время разработчики прикладных программ обычно выбирают то, что им удобнее, или то к чему они привыкли, и, зачастую,
таким средством оказывается именно достандартный характер обработки
ошибок.

356 ГЛАВА 5. ОБРАБОТКА ОШИБОК
Поведение достандартных обработчиков ошибок в некоторых MUMPS
системах разрабатывалось зачастую с ориентацией на практичность их
применения в прикладных программах, наиболее подходящих для применения этих MUMPS систем. Конечно, поведение таких обработчиков
ошибок не было привязано к определенным прикладным программным
пакетам, и было достаточно универсально, но при реализации нюансов
производители MUMPS систем могли учесть наиболее предпочтительные умолчания, подходящие определенным программам.
Для тех программистов, кто ранее работал со строчно - ориентированными языками, принцип построения обработчиков ошибок в MUMPS
будет знаком. В частности, в языках BASIC группы до сих пор используется синтаксическая конструкция указания что делать системе исполнения при возникновении состояния ошибки:
On Error GoTo ОбработкаОшибок
для указания куда перейти для обработки ошибок и
On Error Goto 0
для отключения установленного ранее обработчика ошибок и перевода
процесса в состояние обработки ошибок по умолчанию.
После взведения такого указания процесс уже имеет инструкцию,
описывающую, что необходимо предпринять в случае возникновения
ошибки. При этом инструкция обработки ошибок распространяется в зависимости от особенностей языка либо на все дальнейшее выполнение,
либо на все выполнение на текущем уровне стека. При необходимости
ограничить действие обработчика ошибок нужно его взвести в соответствующее состояние.
Более поздние языки с поддержкой обработки ошибок на уровне языка также содержат средства ограничения области действия обработчика
ошибок путем синтаксического указания этой области, например, конструкции вида:
try - catch
try - except
try - finally
Что интересно, в старших версиях Cach´e при введении блочного синтаксиса с ограничением действия фигурными скобками также был введен
и обработчик ошибок с ограничением области его действия:

5.1. СОСТОЯНИЕ ОШИБКИ 357
TRY {
protected statements
} CATCH [ErrorHandle] {
error statements
}
further statements
В частности, обработчик деления на ноль в старших версиях Cach´e
синтаксически может быть описан с использованием нового расширенного синтаксиса в стиле блоков try - catch и команды throw так:
div(num,div) public {
TRY {
SET ans=num/div
} CATCH errobj {
IF errobj.Name="<DIVIDE>" { SET ans=0 }
ELSE { THROW }
}
QUIT ans
}
В языке MUMPS, определенном как строчно - ориентированном языке, вообще говоря, отсутствует такое синтаксическое понятие, как строки принадлежащие или не принадлежащие функции или процедуре. Поэтому в стандартном языке отсутствует как область действия обработчика ошибок, так и автоматическое прекращение его действия какими либо
синтаксическими элементами. Область действия определяется лишь состоянием стека. При этом программа может выполнять на одном и том
же уровне стека самые различные строки, в том числе принадлежащие
и различным рутинам.
Вообще говоря, обработка ошибок включает в себя в качестве составной части определенный алгоритм передачи управления, и этот механизм
может быть использован программой в качестве штатной составляющей
работы процесса. Процесс можно перевести в состояние ошибки программно, если процесс выполнит команду генерации ошибки. В этом
случае разработчики должны понимать, что они используют механизм
обработки непреодолимого состояния для возврата по стеку, который
можно выполнить обычными командами. Сложно сказать, может ли это
быть рекомендовано или не рекомендовано. В некоторых случаях это
действительно может существенно как упростить код, так и усложнить
его понимание и модернизацию.

358 ГЛАВА 5. ОБРАБОТКА ОШИБОК
5.2 ZTRAP
Механизм обработки ошибок, применявшийся в MUMPS системах до
введения единого стандартизированного определения, называется обобщенным термином ZTRAP, поскольку производители различных MUMPS
систем использовали именно этот термин.
В различных реализациях его определение и поведение различно,
хотя и сохраняет общие принципы обработки ошибок - он указывает
что необходимо выполнить в случае возникновения состояния ошибки и
документация на конкретную MUMPS систему описывает каким именно
образом он будет выполняться.
Для указания обработчика ошибок используется специальная системная переменная $ZTRAP, доступная на чтение и запись. В случае если
значение пусто, то это означает что система должна выполнять обработку ошибок по умолчанию. Иначе система должна использовать это
значение в качестве инструкции что необходимо предпринять.
Очень важно отметить, что различные реализации MUMPS систем
используют различные механизмы при обработке ошибок по ZTRAP,
поэтому далее будет описываться механизм с указанием MUMPS системы, для которой он приведен. Кроме того, что поведение обработчиков
ZTRAP в различных MUMPS системах отличается, также отличается
их поведение при комбинировании с обработчиком ETRAP и их одновременном использовании в одном процессе.
5.2.1 Cach´e
В системе Cach´e системной переменной $ZTRAP необходимо присвоить
имя метки. В случае возникновения ошибки процесс выполняет неявную
команду goto и переходит на эту метку. Пример:
proc ; k d proc^ZTRAP w
s $ztrap="err"
w "in proc, $st=",$st,!
w 1/0
w "exit proc, $st=",$st,!
q
err
w "in err, $st=",$st,!
q
При выполнении в терминале Cach´e получаем:
USER>k d proc^ZTRAP w
in proc, $st=1
in err, $st=1

5.2. ZTRAP 359
Здесь иллюстрируется, что обработчик ошибок выполнился, не дойдя
до отметки о выходе из подпрограммы, и данный обработчик выполнился
на том же уровне стека.
В Cach´e есть дополнительная особенность обработчика ZTRAP: перед именем метки может быть указан символ "*". Отсутствие этого символа означает, что система выполнения должна вернуться до того уровня
стека, на котором произошло присваивание $ZTRAP и вместо выполняемого кода выполнить неявную команду GOTO. В случае если происходит ошибка на более глубоком уровне стека, то процесс возвращается по
стеку и уже на именно том уровне, где было присваивание $ZTRAP, выполняет обработчик ошибки. Для иллюстрации модифицируем пример:
proc ; k d proc^ZTRAP w
s $ztrap="err"
w "in proc, $st=",$st,!
d trap
w "exit proc, $st=",$st,!
q
trap
w "in trap, $st=",$st,!
w 1/0
err
w "in err, $st=",$st,!
q
При выполнении получаем:
USER>k d proc^ZTRAP w
in proc, $st=1
in trap, $st=2
in err, $st=1
Здесь обработчик выполнился именно на том же уровне стека, где
был установлен, независимо от уровня стека, где произошла ошибка на том же или более глубоком.
В случае если перед именем метки ставится символ "*", то это служит процессу Cach´e инструкцией не выполнять развертывание стека до
того уровня где был установлен обработчик, а выполнить его на том
уровне стека где произошла ошибка. Проиллюстрируем еще раз модифицированным примером, указав уже символ "*" перед именем метки:
proc ; k d proc^ZTRAP w
s $ztrap="*err"
w "in proc, $st=",$st,!
d trap

360 ГЛАВА 5. ОБРАБОТКА ОШИБОК
w "exit proc, $st=",$st,!
q
trap
w "in trap, $st=",$st,!
w 1/0
err
w "in err, $st=",$st,!
q
При выполнении примера получаем:
USER>k d proc^ZTRAP w
in proc, $st=1
in trap, $st=2
in err, $st=2
exit proc, $st=1
Для того, чтобы продолжить выполнение программы с команды, следующей после вызвавшую ошибку, при использовании обработчика ZTRAP
в Cach´e нужно:
1. Внести код, который может вызвать ошибку, в аргумент команды
XECUTE.
2. Перед именем метки с обработчиком указать символ "*".
Проиллюстрируем это на примере:
proc ; k d proc^ZTRAP w
s $ztrap="*err"
w "in proc, $st=",$st,!
x "w 1/0"
w "exit proc, $st=",$st,!
q
err
w "in err, $st=",$st,!
q
При выполнении такого кода получаем:
USER>k d proc^ZTRAP w
in proc, $st=1
in err, $st=2
exit proc, $st=1
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
