Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
MUMPS СУБД. Практика применения и опыт программирования.pdf
Скачиваний:
0
Добавлен:
07.09.2026
Размер:
2 Мб
Скачать
6.4. WEB 441
И, если веб странице для работы необходимо строго работать только с авторизованным пользователем либо со связанным с ним контекстом, во всех страницах необходимо это предусматривать. Например, пере­направлять на страницу авторизации, либо возвращать содержание по умолчанию.
Очевидно, что и вторая и третья проблема протокола HTTP не от­носятся напрямую к MUMPS системам, и тут могут быть использованы точно такие же типовые решения проблем, как и при использовании других веб технологий.

6.4.8 Поверх HTTP

На основе протокола HTTP строится множество дополнительных тех­нологий взаимодействия веб клиентов и сервера. В них используется тот факт, что если административно настроен канал взаимодействия по TCP/IP с прохождением HTTP запросов, то поверх HTTP протокола также строится набор дополнений по передаче параметров и получению результата и используется в точности та же самая инфраструктура.
К таким технологиям относятся AJAX, SOAP, JSON, XML-RPC и другие, зачастую не получающие отдельного названия. По сути, все они построены на том, что создается дополнительный объект HTTP запроса, через который передаются параметры и полученное содержание анализи­руется в зависимости от вида технологии. AJAX и SOAP обмениваются данными в формате XML. Если AJAX передает произвольный XML, то SOAP дополнительно использует определенную схему определения пе­редаваемого XML, выделяя в ответе определенные теги самостоятельно как ответ. В определенной мере SOAP можно рассматривать как один из вариантов, или аналог взаимодействия XML-RPC.
Взаимодействие JSON основано на том, что в качестве ответа сервер возвращает код на JavaScript, который выполняется непосредственно, и по правилам JavaScript автоматически создается объект JavaScript. Вызывающий код уже обращается к его свойствам - атомарным, или массивам, или спискам.
Пример SOAP-запроса на сервер интернет-магазина:
<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<getProductDetails
xmlns="http://warehouse.example.com/ws"> <productID>12345</productID>
</getProductDetails>
442 ГЛАВА 6. ВНЕШНИЙ МИР
</soap:Body>
</soap:Envelope>
Пример ответа:
<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<getProductDetailsResponse
xmlns="http://warehouse.example.com/ws"> <getProductDetailsResult>
<productID>12345</productID> <productName>Стакан граненый</productName> <description>Стакан граненый. 250 мл.</description> <price>9.95</price> <currency>
<code>840</code> <alpha3>USD</alpha3> <sign>$</sign> <name>US dollar</name>
<accuracy>2</accuracy> </currency> <inStock>true</inStock>
</getProductDetailsResult>
</getProductDetailsResponse>
</soap:Body>
</soap:Envelope>
Для протокола SOAP при его разработке были изначально допол­нительно определены средства прототипирования и в нем присутствует две отдельные части: 1) URL для получения прототипа функции с пере­числением параметров и структуры возвращаемого значения и 2) URL для собственно вызова функции. Наличие прототипов позволяет строить визуальные средства с возможностью выбора функции и с автоматиче­скими генераторами SOAP запросов, включая парсинг ответа.
Пример JSON ответа:
{
"firstName": "Иван",
"lastName": "Иванов",
"address": {
"streetAddress":
"Московское ш., 101, кв.101", "city": "Ленинград", "postalCode": 101101
}, "phoneNumbers": [
6.4. WEB 443
"812 123-1234", "916 123-4567"
]
}
Для языка JavaScript такой ответ синтаксически является представ­лением JavaScript объекта с объявлением и одновременно инициализа­цией полей. В этом примере поля firstName и lastName специфицирова­ны как атомарные строковые, поле address как также объект со своими полями, и поле phoneNumbers как массив.
В своей технологической основе все эти способы построены на том, что по HTTP передается набор параметров и принимается ответ, но ответ отдается парсеру ответа для выделения его фрагментов. В случае AJAX / SOAP / XML-RPC ответ парсится как XML, а в случае JSON ответ парсится как JavaScript. Что интересно, для обмена данными по таким соглашениям уже не суть важно, какой именно из передающе - принима­ющих протоколов будет использован - будет это HTTP, или SMTP или другой.
Несложно также построить такой запрос, чтобы не только вебсервер отвечал на языке вебклиента, но и чтобы вебклиент отсылал вебсерверу данные в характерном для него формате. В частности, в SOAP содер­жание передается как XML. Но вебклиент может также сформировать содержание HTTP запроса и как JavaScript, и на языке MUMPS, напри­мер передавать данные в виде
data(78) Berlin~Germany~Europe
в теле запроса типа POST или PUT.
Такое содержание на стороне MUMPS процесса может рассматри­ваться как просто перечисление пар ключ - значение, и расходы на пар­синг данных фактически отсутствуют из-за встроенных в язык возмож­ностей косвенности.
Разумеется, при применении такого метода передачи данных сохра­няется опасность уязвимости при приеме данных от неавторизованного источника. Если серверный код примет, например, такие данные:
a($h) 123
и строку с ключем будет использовать как есть, то рискует выполнить системные функции как побочный эффект конструирования имени.
444 ГЛАВА 6. ВНЕШНИЙ МИР
Конечно, для страховки от такой возможности необходимо поставить простейшую проверку на допустимость полученного ключа. Например, применить функции $QS - $QL для проверки синтаксической допусти­мости имени и не является ли имя глобалом.
Весьма привлекательным выглядит вариант обмена данными в фор­мате, наиболее удобном для принимающей стороны - вебсервер отвечает вебклиенту на языке JavaScript, как в протоколе JSON, а вебклиент отправляет данные вебсерверу на языке MUMPS. В этом случае на при­нимающей стороне не используются громоздкие сторонние библиотеки парсинга абстрактных форматов данных, а используются встроенные в язык средства косвенности и использования данных динамически, как кода или фрагментов выражений. Теоретически, и для вебклиента на JavaScript, и для вебсервера на MUMPS (или на другой NoSQL СУБД) передача данных в виде просто пар ключ - значение выглядит более практичным форматом, чем громоздкая XML разметка.
При передаче, например, онлайн магазину запроса он мог бы выгля­деть например так:
function getProductDetails productID 12345
Или так:
function("name") getProductDetails param("productID") 12345

6.5 Подключаемые DLL (SO)

Большинство современных MUMPS систем, а из промышленно исполь­зуемых все, допускают подключение и использование внешних динами­ческих библиотек. Это DLL в системах Windows и SO в Linux.
Сама библиотека получается компилирующими трансляторами, обыч­но это C / C++ / Pascal / ASM. Каждая из MUMPS систем деклариру­ет правила, которым должна соответствовать такая библиотека и какой программный интерфейс она должна предоставить. У каждой из MUM­PS систем такие правила собственные и они не входят в стандартные соглашения.
6.5. ПОДКЛЮЧАЕМЫЕ DLL (SO) 445
Вызов DLL начинается с вызова специальной или набора специаль­ных расширенных функций MUMPS системы на языке MUMPS, в каж­дой из систем такой набор собственный, хотя по общей структуре ха­рактер вызовов в целом отвечает одним и тем же целям.
На стороне DLL она должна предоставить одну или несколько функ­ций (экспортировать) в соглашениях и в прототипе, объявленном MU­MPS системой. При необходимости вызова внешней DLL система опре­деляет, в какой файле находятся необходимые функции, загружает его динамически и отыскивает в экспортированных функциях специальную, которая объявляет наличие и способ вызова внутренних функций этой DLL. Далее отыскивается необходимая, имя которой было указано в M­UMPS коде, и она вызывается с передачей ей аргументов и получением возвращаемого значения.
В зависимости от типа применяемой MUMPS системы начальная функция DLL, объявляющая поддерживаемые ей функции, может воз­вращать как набор указателей на функции, так и набор имен экспор­тированных функций. Для каждой из таких поддерживаемых внешних функций DLL также должна объявить прототип, количество и, при необ­ходимости, характер передачи аргументов.
Перед вызовом внешней функции MUMPS система преобразует при необходимости передаваемые функции значения из своего внутреннего представления в формат для передачи, формирует стек вызова и передает управление вызываемой функции.
Укрупненно, и в абстрактных обозначениях, это может выглядеть так:
1. MUMPS система выполняет код
$zcalldll("filename","funcname",param1,param2)
2. MUMPS система по параметру filename отыскивает файл DLL и динамически загружает его.
3. В списке экспорта отыскивается оговоренная этой MUMPS систе­мой специальная функция декларирования поддерживаемых этой DLL внешних функций, пусть например это будет функция DEC­LARED.
4. Для такой функции определяется прототип, согласно которому M­UMPS система может получить список внешних функций этой DLL с их прототипами. Пусть для примера эта функция возвращает список определений для функций "transform", "add" и "remove".
446 ГЛАВА 6. ВНЕШНИЙ МИР
5. MUMPS система просматривает этот список объявлений и находит необходимую, например, "transform".
6. По объявленному прототипу функции готовит значения параметров и формирует стек вызова. Значения param1 и param2 переводятся при необходимости из внутреннего представления в передаваемое внешней функции. Это может быть строка завершающаяся нулем, число, структура, или иное.
7. Внешняя функция вызывается и принимается значение возврата. Это значение преобразуется к внутреннему представлению, исполь­зуемому MUMPS системой и возвращается как возврат функции $zcalldll на уровне исполнения языка.
Обычно предоставляется набор вариантов вызова внешней функции:
1. Загрузить DLL, вызвать функцию, выгрузить DLL.
2. Отдельно операции загрузки DLL, возможность вызова функций у уже загруженной DLL, и операция выгрузки DLL.
3. Загрузка DLL, вызов функции с оставлением DLL загруженной, с отдельной операцией выгрузки DLL.
Вариант с возможностью оставить DLL загруженной между различ­ными вызовами функций в ней дает возможность разработчикам ис­пользовать внутренние данные такой DLL, ее собственное состояние, многократно обращаться к ее внутренним объектам.
На основе внешних DLL обычно выполняются модули, написание ко­торых на языке MUMPS очень трудоемко, либо для использования уже написанных модулей, либо для использования специальных API опера­ционных систем, не доступных готовыми для использования в MUMPS вариантами. Также это могут быть функции, для которых критична ско­рость выполнения, например компрессоры данных, парсеры специальных форматов данных, или интерпретаторы других языков.
К неудобствам таких внешних функций можно отнести то, что в случае смены как MUMPS системы, так и операционной системы та­кие модули необходимо перекомпилировать под другую MUMPS- или операционную систему (выполнить портирование). К большим плюсам внешних DLL относится то, что в прикладной системе можно использо­вать произвольный функционал и расход ресурсов на вызов функции в DLL обычно значительно меньше, чем на вызов иных внешних средств.
6.6. ФАЙЛЫ 447
К интересным возможностям вызова внешних функций в DLL мож­но отнести не только то, что в таких функциях разработчик ничем не ограничен по возможностям, но и то, что большинство MUMPS систем также предоставляют интерфейс обратного вызова процесса на языке MUMPS из контекста вызванной DLL. При этом разработчик может в таком обратном вызове выполнить набор команд или вычислить значение выражения. При выполнении кода на MUMPS, в свою очередь, также возможен вызов DLL, и так далее. Используя возможности обратного вызова, разработик может, например, вернуть из DLL большое количе­ство данных, записав их в локальную или глобальную переменную или запросить дополнительные значения в зависимости от переданных аргу­ментов.
В практическом применении чаще встречаются внешние DLL с функ­циями, которых не хватает в самой используемой MUMPS системе с точ­ки зрения разработчиков прикладных систем, либо выполняющие слож­ные преобразования, либо предоставляющие доступ к специфическому функционалу операционных систем. В частности, это функции кодиро­вания данных в специальных форматах, функции криптографических модулей, модулей регулярных выражений, модулей компрессии данных, дополнительное управление аппаратным обеспечением сервера.
Также отдельно необходимо отметить, что именно внешние DLL ис­пользуются для интеграции MUMPS систем с другими СУБД, как ис­пользуя обобщенные драйверы (ODBC, OLEDB, BDE), так и специали­зированные DLL для определенных СУБД.

6.6 Файлы

Доступ к файлам поддерживается во всех MUMPS системах. Файл во многих системах рассматривается как основное средство передачи дан­ных, как больших, так и малых объемов, как в простых, так и в сложных форматах.
Файл доступен MUMPS процессу как устройство. При открытии фай­ла поддерживаются опции его открытия - нужно ли открыть только имеющийся, или создать новый, какой должен использоваться доступ
- текстовый или бинарный, какой должен использоваться терминатор. Операции чтения и записи автоматически смещают текущую позицию в файле на количество прочитанных или записанных байт, при записи после последней позиции файл автоматически увеличивается в размере. И так далее. Не будет ошибкой сказать, что в целом MUMPS системы поддерживают практически все операции с файлами, характерные для
448 ГЛАВА 6. ВНЕШНИЙ МИР
работы с файлами в других программных средах.
Способ открытия файла на чтение и ли на запись в каждой из ис­пользуемых MUMPS систем отличается в силу того, что стандарт не специфицирует в точности все необходимые опции. Это может быть от­крытие файла по номеру устройства с указанием в опции имени файла, или указание в качестве имени устройства самого имени файла, или совмещение в имени устройства и типа устройства и имени файла.
Набор поддерживаемых опций, их имена и значения также могут отличаться в разных MUMPS системах. Поэтому для написания пере­носимого кода такие операции необходимо выносить в отдельный код.
Несмотря на некоторое расхождение в способе поддержки файлов в виде устройств языка, общие правила у различных MUMPS систем совпадают. Для того, чтобы процесс имел доступ к файлу, используется команда OPEN, чтобы больше не использовать файл - команда CLOSE, чтение выполняется командой READ, запись командой WRITE, а смена опций использования командой USE. Чтобы выполнить портирование кода на иную MUMPS систему, необходимо проверить по документации на нее либо работу с этими командами, либо отдельное описание типа устройства, где указываются поддерживаемые опции команд при работе с файлами.
К особенностям применения файлов в практике можно отнести два пункта: 1) работа в текстовом или бинарном режиме и 2) обработка достижения конца файла.
Для текстового и бинарного режима различаются команды записи
write !
и чтения строки.
При записи символа перевода строки в Windows-based системах про­изводится вывод последовательности
$C(13,10)
а в UNIX-like системах выводится последовательность
$C(10)
При чтении строки система также различает что является символом окончания строки в зависимости от операционной системы. Для UNIX­like систем символ $C(13), предшествующий символу $C(10), считается частью строки, хотя он и относится к непечатным, а в Windows-based
6.6. ФАЙЛЫ 449
системах, если он присутствует, то отбрасывается и в строку не вклю­чается. Но это относится только к последнему символу $C (13) - если перед ним есть еще такие же, то они уже включаются в строку.
При работе в текстовом и бинарном режиме (если MUMPS система поддерживает их различение) символ перевода строки рассматривается описанным выше способом, в зависимости от типа операционной систе­мы. В бинарном режиме выводится символ $C(10) вне зависимости от типа операционной системы. Также для бинарного режима необходимо задавать терминатор чтения. Иначе система будет читать строку на мак­симально доступную длину, например 32 килобайт.
Естественно, что если в файле находится строка с длиной превы­шающей максимальную длину строки MUMPS системы, то она прочи­тает строку на доступную длину и последующие чтения строки будут производиться далее, из той же самой строки находящейся в файле. Та­ким образом, программа получит разбиение исходной длинной строки на несколько строк. Если применяются файлы с такими данными, то раз­работчикам необходимо учитывать фактор максимальной длины строки. И, возможно, в зависимости от применяемой MUMPS системы.
Для текстового и бинарного режима могут отличаться также поведе­ние команд табулирования
write ?NN
В этом случае MUMPS система может как вести отсчет текущей позиции в строке и корректно вывести в файл нужное число пробелов для табулированного дополнения, так и не вести такой отсчет, и даже игнорировать такую команду. Для каждой из MUMPS систем при необ­ходимости применения такой команды по отношению к файлу необходи­мо отдельно проверить, какие операции система выполняет. Кроме того, если выводящий код оперирует системными переменными $X и $Y при работе с текущим устройством, то также необходимо проверить, какие значения возвращаются для файла, как в текстовом, так и в бинарном режиме.
Основной режим доступа к файлам в MUMPS предполагается через модель последовательных устройств - текущий указатель автоматиче­ски смещается на количество прочитанных или записанных байт. Но при работе со многими форматами файлов необходимо явно позициони­роваться в файле. Для этого практически все системы поддерживают опции команды USE, чтобы задать, как именно необходимо установить текущую позицию в файле. Либо этот же функционал доступен через специальные расширенные системные функции.
450 ГЛАВА 6. ВНЕШНИЙ МИР
К такой же операции, использующей позицию и длину, относится операция явной блокировки участка файла на чтение или на запись. Та­кие операции уже могут поддерживаться м´еньшим числом MUMPS си­стем, и характерны скорее для файл-серверных систем, чем для клиент­серверных.
Многие MUMPS системы поддерживают отдельную опцию, задаю­щую длину строки для чтения без указания терминатора чтения. С тем, чтобы команда чтения строки всегда выполняла чтение строго указанной порции байт. Таким образом, доступ к файлу из последовательного пре­вращается в некоторым образом блочный. В любом случае, даже если применяемая MUMPS система не поддерживает такой режим, у програм­мистов есть опция команды чтения строки READ, указывающая длину чтения.
Обработка конца файла по умолчанию определена во всех системах как генерация ошибки. В стандарт входит именно такое поведение, и все MUMPS системы его поддерживают, но стандарт не описывает код такой ошибки, и в разных системах содержание ошибки может отличаться.
При выполнении команды чтения (как строки, так и одного симво­ла) MUMPS система проверяет, есть ли в файле еще какие-то байты. Если есть, то выполняет чтение на доступную длину. Например, если программа запрашивает чтение данных на 100 байт, а в файле только 40, то команда вернет только 40 байт. Если же на момент выполне­ния команды чтения в файле нет доступных байт (предыдущие команды чтения его исчерпали), то команда не возвращает пустую строку (ина­че команды чтения зациклились бы), а генерирует ошибку достижения конца файла.
Нужно отметить, что многие современные MUMPS системы поддер­живают отдельный режим процесса для обработки конца файла. Ис­пользуя системную функцию, можно переключить работу процесса так, чтобы явно указать - будет ли генерироваться ошибка достижения конца файла или будет взводиться определенная расширенная системная пере­менная. Многие MUMPS системы используют для такой переменной имя
$ZEOF
При переводе процесса в такой режим программа должна реагировать не на генерирующуюся ошибку, а на значение этой системной перемен­ной.
В практическом применении файлы используются для экспорта и им­порта данных, рутин, как в стандартных для MUMPS систем форма­тах, так и в сторонних форматах (XML, DBF, INI, CSV, и другие), а