Одно из ключевых направлений развития платформы данных InterSystems IRIS — открытость. Открытость во взаимодействии с языками программирования, технологиями и протоколами. Поддержка языков программирования двусторонняя — возможен как вызов кода из InterSystems IRIS, так и предоставляется API для работы с InterSystems IRIS извне. В этой статье речь пойдёт о первом варианте — вызове кода из InterSystems IRIS. Целью этого небольшого повествования является демонстрация того, как просто и удобно можно это сделать. Я не буду сравнивать различные языки программирования (хотя в конце есть таблица по скорости работы различных имплементаций), всё зависит от решаемых вами задач и требований, предъявляемых к результату разработки. В этой статье я продемонстрирую несколько различных подходов к вызовам сторонних библиотек, а реализовывать мы будем одну и ту же функциональность — вызов функции DELFATE из библиотеки zlib.
Недавно я прочитал вот эту статью. Речь там идет как раз о вызове функции DELFATE на NodeJS из платформы InterSystems IRIS, и эта статья натолкнула меня на мысль описать вызов кода и на других языках.
Итак, начнем с NodeJS. Я беру код почти целиком из статьи Бернда, за исключением того, что в нем не используются файлы, а прямое http-соединение для передачи данных. В целом лучше передавать данные в теле запроса, и кодировать как запрос, так и ответ в виде base64. Тем не менее, вот код:
//zlibserver.js
const express = require('express');
const zlib = require('zlib');
var app = express();
app.get('/zlibapi/:text', function(req, res) {
res.type('application/json');
var text=req.params.text;
try {
zlib.deflate(text, (err, buffer) => {
if (!err) {
res.status(200).send(buffer.toString('binary'));
} else {
res.status(500).json( { "error" : err.message});
// handle error
}
});
}
catch(err) {
res.status(500).json({ "error" : err.message});
return;
}
});
app.listen(3000, function(){
console.log("zlibserver started");
});
Чтобы запустить сервер, выполните в терминале ОС (должны быть установлены node
и npm
):
cd <repo>node
npm install
node ./zlibserver.js
Что здесь происходит? Слушаем порт 3000
, сжимаем DEFLATE тело запроса и возвращаем сжатые данные в ответ. На стороне InterSystems IRIS используется http запрос для взаимодействия с данным API:
/// NodeJS implementation
/// do ##class(isc.zlib.Test).node()
ClassMethod node(text As %String = "Hello World", Output response As %String) As %Status
{
kill response
set req = ##class(%Net.HttpRequest).%New()
set req.Server = "localhost"
set req.Port = 3000
set req.Location = "/zlibapi/" _ text
set sc = req.Get(,,$$$NO)
quit:$$$ISERR(sc) sc
set response = req.HttpResponse.Data.Read($$$MaxStringLength)
quit sc
}
Обратите внимание, что я устанавливаю третий аргумент set sc = req.Get(,,$$$NO)
— reset
равным нулю. Если вы пишете интерфейс для внешнего http(s) сервера, то лучше всего повторно использовать один объект запроса и просто модифицировать его по мере необходимости для выполнения новых запросов.
Java Gateway позволяет вызывать произвольный Java-код. Недавно я писал про него более подробно. Стандартная библиотека Java включает класс Deflater
, который делает именно то, что нам нужно:
package isc.zlib;
import java.util.Arrays;
import java.util.zip.Deflater;
public abstract class Java {
public static byte[] compress(String inputString) {
byte[] output = new byte[inputString.length()*3];
try {
// Encode a String into bytes
byte[] input = inputString.getBytes("UTF-8");
// Compress the bytes
Deflater compresser = new Deflater();
compresser.setInput(input);
compresser.finish();
int compressedDataLength = compresser.deflate(output);
compresser.end();
output = Arrays.copyOfRange(output, 0, compressedDataLength);
} catch (java.io.UnsupportedEncodingException ex) {
// handle
}
return output;
}
}
Особенность этой имплементации заключается в том, что она возвращает массив byte[]
, который становится потоком на стороне InterSystems IRIS. Я пытался вернуть строку, но не смог найти, как сформировать бинарную строку из byte[]
. Если у вас есть какие-то идеи, пожалуйста, оставьте комментарий.
Чтобы запустить код, поместите jar из релизов в папку <instance>/bin
, загрузите код в свой инстанс InterSystems IRIS и выполните:
write $System.Status.GetErrorText(##class(isc.zlib.Utils).createGateway())
write $System.Status.GetErrorText(##class(isc.zlib.Utils).updateJar())
Проверьте метод createGateway
перед запуском. Второй аргумент javaHome
предполагает что переменная окружения JAVA_HOME
установлена. Если это не так, вручную передайте путь до Java 1.8 JRE. Для сжатия строки text
выполните этот код:
set gateway = ##class(isc.zlib.Utils).connect()
set response = ##class(isc.zlib.Java).compress(gateway, text)
Библиотека InterSystems Callout это динамическая библиотека, предоставляющая функции, которые вы можете вызвать из InterSystems IRIS.
Вот наша библиотека:
#define ZF_DLL
// Ugly Windows hack
#ifndef ulong
typedef unsigned long ulong;
#endif
#include "string.h"
#include "stdio.h"
#include "stdlib.h"
#include "zlib.h"
#include <cdzf.h>
int Compress(char* istream, CACHE_EXSTRP retval)
{
ulong srcLen = strlen(istream)+1; // +1 for the trailing ``
ulong destLen = compressBound(srcLen); // estimate size needed for the buffer
char* ostream = malloc(destLen);
int res = compress(ostream, &destLen, istream, srcLen);
CACHEEXSTRKILL(retval);
if (!CACHEEXSTRNEW(retval,destLen)) {return ZF_FAILURE;}
memcpy(retval->str.ch,ostream,destLen); // copy to retval->str.ch
return ZF_SUCCESS;
}
ZFBEGIN
ZFENTRY("Compress","cJ",Compress)
ZFEND
Для запуска загрузите dll
или so
со страницы релизов в папку <instance>/bin
. В репозитории есть также скрипты для сборки вашей собственной версии библиотеки.
Перед сборкой установите:
apt install build-essential zlib1g zlib1g-devel
Для работы с Callout библиотекой выполните:
set path = ##class(isc.zlib.Test).getLibPath() //get path to library file
set response = $ZF(-3, path, "Compress", text) // execute function
do $ZF(-3, "") //unload library
Используя Python Gateway вызовем данный код:
import zlib
zlib.compress(b'text')
Из InterSystems IRIS: set out = ##class(isc.py.Callout).SimpleString("import zlib" _ $$$NL _ "x = zlib.compress(b'" _ text _ "')", "x")
Net Gateway позволяет вызывать произвольный код на языке C#. Недавно я писал про него более подробно.
Реализация на C# также возвращает поток, а не строку:
using System;
using System.IO;
using System.IO.Compression;
namespace isc.zlib
{
public class Net
{
public static byte[] compress(String str)
{
using (MemoryStream output = new MemoryStream())
{
using (DeflateStream gzip = new DeflateStream(output, CompressionMode.Compress))
{
using (StreamWriter writer = new StreamWriter(gzip, System.Text.Encoding.UTF8))
{
writer.Write(str);
}
}
return output.ToArray();
}
}
}
}
Для запуска загрузите zlibnet.dll
со страницы релизов в папку <instance>/bin
.
write $System.Status.GetErrorText(##class(isc.zlib.Utils).createNetGateway())
write $System.Status.GetErrorText(##class(isc.zlib.Utils).updateNet())
Для сжатия строки text
выполните этот код:
set gateway = ##class(isc.zlib.Utils).connect()
set response = ##class(isc.zlib.Net).compress(gateway, text)
Несколько неожиданно в статье о механизмах вызова кода на других языках, но в ObjectScript также есть встроенная функция Compress (и парная функция Decompress). Вызывается так: set response = $extract($SYSTEM.Util.Compress(text), 2, *-1)
Помните, что поиск в документации или вопрос на Developers Community может сэкономить вам некоторое время.
Я запустил простой тест (1Kb text, 1 000 000 итераций) на Linux (VPS) и Windows (Ноутбук) и получил следующие результаты.
Windows:
Linux:
Для запуска тестов загрузите код и вызовите: do ##class(isc.zlib.Test).test(textLength, iterations)
С платформой InterSystems IRIS вы легко можете использовать существующий код на ряде популярных языков. Однако выбор реализации не всегда прост: необходимо учитывать несколько метрик, таких как скорость разработки, производительность, кроссплатформенность и простота сопровождения. Ответы на эти вопросы помогут вам определиться с оптимальным планом разработки.
Центр управления связью общего пользования (ЦМУ ССОП) Роскомнадзора рекомендовал компаниям из реестра провайдеров ограничить доступ поисковых ботов к информации на российских сайтах.…
Apple возобновила переговоры с OpenAI о возможности внедрения ИИ-технологий в iOS 18, на основе данной операционной системы будут работать новые…
Конкурсный управляющий российской «дочки» Google подготовил 23 иска к участникам рекламного рынка. Общая сумма исков составляет 16 млрд рублей –…
Google завершил обновление основного алгоритма March 2024 Core Update. Раскатка обновлений была завершена 19 апреля, но сообщил об этом поисковик…
У частных продавцов на Авито появилась возможность составлять текст объявлений с помощью нейросети. Новый функционал доступен в категории «Обувь, одежда,…
24 апреля 2024 года в Москве состоялась церемония вручения наград международного конкурса Workspace Digital Awards. В этом году участниками стали…