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

6.3. СОКЕТЫ 421
Здесь на серверной стороне необходимо читать не на определенную
длину, а до договоренного разделителя (в данном случае перевод строки). Естественно, что в этом случае в передаваемых данных не должен
содержаться сам символ перевода строки.
По способу использования сокетов они также могут быть разделены
на две группы, хотя между ними и нет четко определенной границы:
1. Серверные.
2. Сервисные.
К серверным сокетам могут быть отнесены те, которые используются
скорее для выполнения одного запроса и этот запрос полностью решает
задачу, либо для выполнения в рамках одного соединения нескольких
запросов. В этом случае соединение удерживается для полного решения
задачи.
К сервисным сокетам могут быть отнесены те, которые используются
для только одного запроса, даже если он не решает задачу относительно
целиком.
В частности, отправка SMTP сообщения - это набор сообщений в
рамках одного соединения как от клиента серверу, так и ответы сервера клиенту. В случае же использования модели HTTP запросов один
запрос может и не решать поставленную задачу целиком, и получение
всей информации о странице может потребовать нескольких запросов,
например отдельно для самой страницы, для входящих в нее скриптов
Javascript, стилей, картинок. Поэтому в случае SMTP обмена протокол
по способу своего использования скорее серверный, а в случае HTTP
скорее сервисный.
Основным различием между способами использования - серверный
или сервисный является общее время выполнения задачи. В случае если
требуется установление нескольких соединений, то каждое из них требует собственные накладные расходы. Если задача может быть выполнена
в виде одного запроса объемом в 10 килобайт, или в виде 10-ти запросов
по 1 килобайт, то первый способ может работать в разы быстрее. Это
особенно заметно при снижении объемов передаваемых за один раз (за
одно соединение) данных.
Косвенно это также проявляется при использовании собственных
протоколов обмена MUMPS систем с клиентскими программами. Хотя соединение установлено один раз и данные передаются в пределах
одного соединения, возможна передача порций данных как по отдельности, так и единой строкой, например в виде строки с разделителями

422 ГЛАВА 6. ВНЕШНИЙ МИР
или в виде списка. Второй вариант показывает обычно намного лучшее
время, чем последовательные запросы на каждую из порций.
6.4 WEB
С появлением и распространением в сети Internet HTTP клиентов и
HTTP серверов MUMPS системы также стали использовать и для написания как клиентских, так и серверных частей приложений, для интеграции приложений и обмена данными по HTTP протоколу.
В настоящее время распространенность HTTP клиентов такова, то
многие пользователи именно запуск браузера считают синонимом слов
"войти в интернет".
В этом разделе опишем основные принципы и способы интеграции
сервера приложений с каналом связи по протоколу HTTP с точки зрения
программистов MUMPS систем.
Соединение клиента и сервера выполняется по сетевому протоколу
TCP/IP. Протокол HTTP это соглашение о передаче и формировании
HTTP запроса и получении и трактовке ответа. Обе части, и запрос
и ответ, состоят из двух частей - заголовок и тело. Заголовок формируется как набор строк. После заголовка следует одна пустая строка,
отделяющая заголовок от содержания. Далее следует само содержание.
В заголовках описывается, что запрашивается, что отвечается, в каком
кодировании, информационные поля.
Чтобы выполнить запрос, одна из сторон, называемая HTTP клиентом, открывает сокет, и в параметрах соединения указывает с каким
сервером и на какой порт следует соединиться. По умолчанию для HTTP
серверов используется порт номер 80. Далее, при установлении соединения, клиент отсылает запрос и ожидает ответ. В ответ сервер отсылает
набор заголовков, пустую строку и содержание ответа.
Полностью все соглашения о кодировании и передаче описваются в
соответствующих документах RFC.
Обе стороны взаимодействуют через сетевой протокол TCP/IP, и
неважно, какая программа работает с той стороны, на каком процессоре, на какой архитектуре, на какой операционной системе, и по каким
промежуточным каналам производится пересылка сетевых пакетов. По
сути, если среда разработки может получить программу, работающую
с сокетами TCP/IP, то ее можно использовать для написания модулей
интеграции не только для HTTP, но и для HTTPS, WAP, и других,
а также тех, которые еще появятся. Поверх этих протоколов работают
такие технологии, как SOAP, JSON, AJAX, RSS и другие, постоянно

6.4. WEB 423
находящиеся в наше время на слуху.
Заголовок запроса (ответа) состоит из набора строк, каждая из которых означает один из заголовков запроса (ответа). В начале строки
пишется имя заголовка, далее двоеточие с пробелом или пробел, далее
значение, далее после пробела с разделителями "," или ";" могут следовать детализирующие значения заголовка.
Например, запрос на получение страницы index.html, находящейся в
корне сайта, выглядит так:
GET /index.html HTTP/1.1
Здесь GET - это типа запроса, /index.html - это имя ресурса на сайте,
HTTP/1.1 - это уточнение версии протокола для запроса.
Вообще говоря, с точки зрения принципов построения HTTP взаимодействия для программистов, это и все. Остальное - это детали, описанные в справочниках RFC на протоколы и способы кодирования, в
документации на готовые WEB сервера и их версии и на готовые WEB
браузеры или другие HTTP клиенты и их версии. Строго говоря, детальный состав заголовков, их порядок и само и их наличие в запросе
- это все носит рекомендательный характер. В развитием Интернет появляются новые версии как браузеров, так и серверов, самостоятельно
вводящие практически полезные заголовки, которые далее могут быть
в точности поддержаны и другими производителями. Программисты народ пытливых умов, и они постоянно придумывают что-то новое.
Далее рассмотрим способы, как может быть организовано взаимодействие MUMPS системы с HTTP клиентом или HTTP сервером. MUMPS
процесс может быть как клиентом, запрашивающим данные у HTTP
сервера, так и сервером, отдающим данные HTTP клиенту. При этом
серверная сторона может быть выполнена намного более разнообразнее,
чем просто открытие сокета, запись - чтение и закрытие.
На серверной стороне требуется получить соединение, разобрать параметры, сформировать ответ, переслать ответ обратно. MUMPS система
может быть включена в этом процессе на произвольном этапе, и в зависимости от выбранной точки последовательности в этой цепочке может
отличаться способ ее применения.
Перечислим несколько из возможных и реализованных различными
проиводителями вариантов генерации HTTP ответа в контексте MUMPS
процесса:
1. MUMPS процесс может открыть серверный сокет TCP/IP, получить входящее соединение и сгенерировать ответ, отправив его обратно. Это вариант вебсервера, написанного на MUMPS.

424 ГЛАВА 6. ВНЕШНИЙ МИР
2. Готовый WEB сервер, используя соглашения CGI, можно настроить
на обработку запросов специального вида так, чтобы WEB сервер
запускал непосредственно MUMPS процесс. Это вариант прямого
вызова MUMPS процесса.
3. Промежуточная DLL для WEB сервера, поддерживающая протокол ISAPI или NSAPI, самостоятельно обращающаяся к MUMPS
системе по обычному для нее протоколу подключения. MUMPS
процессу при этом передаются параметры и контекст запроса (переменные окружения) в виде его локальных переменных. MUMPS
процесс при этом, используя обычные команды WRITE, генерирует
ответ. Сгенерированный ответ промежутоный DLL модуль возвращает WEB серверу, а тот уже возвращает его HTTP клиенту. При
этом могут быть использованы уже готовые модули промышленных WEB серверов, такие как шифрование по протоколу HTTPS,
компрессия ответа, трансформация параметров по определенным
правилам. В таком варианте выполнен модуль WebLink.
4. Промежуточный CGI модуль (фильтр файлов) может обрабатывать
специальный файл таким образом, чтобы специальные синтаксические конструкции в нем обрабатывались MUMPS процессом, а
остальное передавалось как есть. В таком варианте выполнен модуль MWA.
5. Промежуточный DLL или CGI модуль (фильтр файлов) может обрабатывать специальный файл таким образом, чтобы специальные
синтаксические конструкции в нем обрабатывались MUMPS процессом, так же как и в предыдущем варианте, но при первой обработке файла чтобы генерировалась специальная функционально
эквивалентная рутина. И далее модуль уже может вызывать сгенерированную рутину, чтобы она командами WRITE генерировала
содержание HTTP ответа. В таком варианте выполнен модуль CSP.
6.4.1 HTTP клиент
Интеграция MUMPS процесса в качестве HTTP клиента с WEB сервером для получения данных выглядит наиболее просто. Достаточно использовать поддерживаемые MUMPS системой устройства типа TCP и
соглашения протокола HTTP.
Приведем вариант простого HTTP запроса к одному из серверов но-
востей, отвечающих данными по RSS:

6.4. WEB 425
HTTPREAD ; HTTP client demo
q
RSS ; k d RSS^HTTPREAD w
n dev="|TCP|news.yandex.ru:80"
n header,rss,str
o dev:("rwt"):10 e w "failed to connect",! q
u dev
w "GET /index.rss HTTP/1.0",!
w "Host: news.yandex.ru:80",!!
n $et="g exit"
; skip headers
f r str q:str="" d
. s header($i(header))=str
; read entire content
f r str q:str="" d
. s rss($i(rss))=str
exit
u $p
w "exit",!
c dev s $ec=""
w
q
Этот пример приведен на языке MUMPS в диалекте MiniM.
Процесс открывает сокет в текстовом режиме, пишет в него два
HTTP заголовка, идентифицирующих запрос новостей RSS с дополнительной пустой строкой, далее переходит к чтению ответа. Полный ответ
состоит из двух частей - заголовок ответа (сохраняется в переменную
header) и собственно содержания (сохраняется в переменную rss).
Здесь не производится отслеживание длины содержания, передаваемой в поле Content-Type, и по окончании входных данных (WEB сервер
разрывает соединение) генерируется ошибка чтения. По ошибке чтения
сокет закрывается и выводятся значения как заголовков, так и содержания ответа.
Конечно, для более реалистичного варианта получения ответа необходимо обратить внимание как на значение самих заголовков, так и на
кодировку ответа, указываемую в самом ответе (RSS ответ возвращается
в формате XML).
6.4.2 Вебсервер на MUMPS
Для организации вебсервера на MUMPS необходимо открыть согласно
документации на используемую MUMPS систему серверный сокет, и,
дождавшись подключения, принять заголовки HTTP запроса. После них,

426 ГЛАВА 6. ВНЕШНИЙ МИР
в зависимости от типа запроса, могут быть данные запроса (например, в
запросах типа POST или PUT). Разобрав содержание заголовков, надо
сгенерировать заголовки ответа и содержание ответа.
Приведем простой вариант вебсервера, реагирующего на запросы мак-
симально примитивно, но уже демонстрирующего принципы работы:
RUN ; run http listener
n $es,$et="g:’$es exit",str
n dev="|TCP|:81"
o dev:("rwt"):2 e w "open failed",! g exit
rep
u dev:/ACCEPT
j responce:(:$io)
u $p w "responce was run",! g rep
q
exit
u $p c
q
responce
u $p:("rwt")
n str,header
f r str:10 q:str="" d
. s header($i(header))=str
n ans,crlf=$c(13,10)
s ans($i(ans))="<html><head>"_crlf
s ans($i(ans))="<title>Demo Http Responce</title>"_crlf
s ans($i(ans))="</head>"_crlf
s ans($i(ans))="<body>"_crlf
s ans($i(ans))="This is demo http responce.<p>"_crlf
s ans($i(ans))=$zcvt($zv,"o","xml")_"<p>"_crlf
s ans($i(ans))="Now: "_$h_"<p>"_crlf
s ans($i(ans))="Headers:<p>"_crlf
s i="" f s i=$o(header(i)) q:i="" d
. s ans($i(ans))=$zcvt(header(i),"o","xml")_"<p>"_crlf
s ans($i(ans))="</body></html>"_crlf
n len=0,i=""
f s i=$o(ans(i)) q:i="" s len=len+$l(ans(i))
w "HTTP/1.0 200 OK",!
w "Content-Type: text/html",!
w "Content-Length: ",len,!!
s i="" f s i=$o(ans(i)) q:i="" w ans(i)
h
Этот пример, как и предыдущий с HTTP клиентом, приведен на языке
MUMPS в диалекте MiniM.
Здесь процесс открывает серверный сокет, и ждет подключения к
нему извне. При подключении сокет просто передается дочернему процессу без дополнительных проверок.

6.4. WEB 427
Дочерний процесс переводит сокет в текстовый режим, чтобы операции и чтения и записи использовали стандартные соглашения о переводе
строки.
Далее процесс вычитывает все заголовки HTTP запроса в локальную
переменную header.
После чего генерирует ответ в локальную переменную ans, чтобы
иметь возможность по окончании полной генерации ответа получить его
общую длину в байтах. Вообще говоря, в протоколах HTTP предусмотрена возможность не передавать длину ответа, в этом случае клиент
должен получать все, что следует далее, но часть HTTP клиентов не
придерживаются этого правила.
По окончании генерации ответа процесс передает HTTP клиенту ответ, состоящий из заголовков и самого содержания ответа.
В таком исполнении программистам на MUMPS, в принципе, доступны как все возможности по генерации произвольного ответа с самыми
сложными правилами и нюансами, так и появляется необходимость дополнительной работы в случае если необходимо применять парные к
HTTP запросам темы - шифрование HTTPS, авторизация, компрессия,
кодирование, генерация графического содержимого.
Как именно относиться к параметрам запроса в таком вебсервере полностью определяет программист, например запрос
http://server/abc/def/klm?123&678
Может быть тактован так:
1. Использовать abc как имя базы данных, в которую необходимо
переключиться.
2. Использовать def как имя рутины.
3. Использовать klm как имя метки.
4. Использовать 123 и 678 как значения первого и второго параметров.
Или использовать иные произвольные и непротиворечивые соглаше-
ния.
При обращении к такому простому HTTP серверу браузером IE9 по-
лучаем ответ вида:
This is demo http responce.
MiniM for Windows 32 bit 1.14 release build
Now: 62697,72396

428 ГЛАВА 6. ВНЕШНИЙ МИР
Headers:
GET / HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
Accept-Language: ru-RU
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0;
Windows NT 6.1; WOW64; Trident/5.0)
Accept-Encoding: gzip, deflate
Host: localhost:81
DNT: 1
Connection: Keep-Alive
При обращении иным браузером заголовки могут быть другими, в
частности при запросе браузером Opera9 получаем:
This is demo http responce.
MiniM for Windows 32 bit 1.14 release build
Now: 62697,72389
Headers:
GET / HTTP/1.1
User-Agent: Opera/9.63 (Windows NT 6.1; U; en) Presto/2.1.1
Host: localhost:81
Accept: text/html, application/xml;q=0.9,
application/xhtml+xml, image/png, image/jpeg,
image/gif, image/x-xbitmap, */*;q=0.1
Accept-Language: ru-RU,ru;q=0.9,en;q=0.8
Accept-Charset: iso-8859-1, utf-8, utf-16, *;q=0.1
Accept-Encoding: deflate, gzip, x-gzip, identity, *;q=0
Connection: Keep-Alive, TE
TE: deflate, gzip, chunked, identity, trailers
Конечно, такой вариант вебсервера довольно трудоемок и требует написания специфических для HTTP протокола и способов кодирования
модулей, равно как и получение дополнительной информации о полученном подключении обращением к системным функциям. Реализация
грамотного WEB сервера на MUMPS это действительно трудоемкая задача, из-за обилия различных нюансов кодирований и трактовок параметров и заголовков HTTP запросов.
Все остальные варианты генерации HTTP ответа с использованием
MUMPS - это различного рода упрощения с получением параметров
запроса и характеристик соединения таким образом, что разработчику
остается все меньше работы либо таким образом, чтобы использовались
уже готовые модули кодирований и трансформации.
Применение готовых WEB серверов дает б´ольшую возможность в
независимой административной их настройке и подключении сложных
подсистем - шифрования, компрессии, подстановки правил, кеширования
и проксирования.

6.4. WEB 429
С одной стороны, возможность административно подключить или отключить, или перенастроить по справочной документации дополнительный модуль промышленного WEB сервера может оказаться существенным плюсом. С другой стороны, применение сторонних программных
комплексов по отношению к MUMPS системе также влечет и необходимость заниматься намного большим комплектом программного обеспечения - инсталлировать и обновлять версии, равно как и искать возможные проблемы работы в общей, интегральной схеме. Настройка большого комплекта программ с их собственными нюансами может оказаться
намного более разнообразной задачей, чем просто запуск MUMPS процесса при старте MUMPS системы.
6.4.3 CGI
Классический интерфейс CGI состоит в использовании программой стандартных каналов ввода вывода stdin + stdout. Вебсервер, получив запрос
от браузера, запускает указанный процесс и формирует ему необходимые
параметры окружения, через которые и передаются параметры запроса
из URL.
Обычно в каталог cgi-bin или функционально аналогичный ему не
размещаются исполняемые файлы серверов СУБД, поэтому в них размещают специальные командные файлы, в которых первой строкой указывают через шебанг что необходимо выполнить. В запросе вебсерверу
указывают уже этот командный файл. Например, организуем запрос к
файлу demo.m размещенном в каталоге cgi-bin:
http://localhost/cgi-bin/demo.m?param=123
Сам файл demo.m составим с указанием правила запуска MUMPS
процесса. Разумеется, тут могут быть использованы только те MUMPS
системы, которые поддерживают ввод и вывод данных через стандартные каналы stdin и stdout. В параметрах запуска нужно указать, что
необходимо выполнить. Параметры процесса у каждой MUMPS системы
отличаются и необходимо определить по документации правила их описания. Положим, что необходимо выполнить на сервере рутину DEMO,
тогда файл demo.m может выглядеть так:
#! serverdir\mumps -xecute "d ^DEMO"
Здесь точное значение параметров зависит от MUMPS системы.
Сама выполняемая рутина DEMO уже полностью формирует HTTP
ответ для вебсервера:

430 ГЛАВА 6. ВНЕШНИЙ МИР
WEB
w "Content-Type: text/html",$c(10,10)
w "<html>",!
w "<head><title>Web Demo Response</title></head>",!
w "<body>",!
w ....
w "</body>",!
w "</html>",!
q
Также, в зависимости от MUMPS системы, необходимо определить
по документации на нее, как получить переменные окружения.
Такой способ запуска, если он осуществим, прост и не требует настройки дополнительного программного обеспечения. Программист может программно генерировать произвольные вебстраницы, произвольного типа и полностью реализовывать сложные формы взаимодействия с
вебклиентом (браузером).
6.4.4 WebLink
WebLink это ISAPI модуль для промышленных WEB серверов. В выполнении запроса используется обращение к dll с передачей параметров, но
при разработке используются файлы asp. Хотя технически и используется расширение для файлов asp, но WebLink работает с такими файлами самостоятельно, без использования модулей Microsoft Active Server
Pages.
Файл WebLink содержит в качестве основного код в разметке HTML,
а специальные теги ASP обрабатываются компилятором приложений
WebLink. Результат обработки таких файлов получается в виде рутин
MUMPS системы. После первой обработки файла уже вызываются сгенерированые рутины, отдающие содержание вебсерверу. Все обращения (ссылки) к станицам asp, входящим в приложение, компилятором
WebLink автоматически заменяются на обращение к ISAPI модулю с
подстановкой необходимых параметров.
Кроме того, сгенерированные или иные рутины могут быть вызваны
непосредственно через DLL модуль.
Набор файлов и рутин объединяется в один пакет, называемый приложением. Все входящие в него элементы могут быть откомпилированы.
WebLink при компиляции файлов рассматривает специальные теги
<% %>
и символы подстановки
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
