Есть многое в природе, друг Горацио, Что и не снилось нашим мудрецам.(с) Вильям Шекспир


Более 6-ти лет занимаюсь разработкой под IBM i (бывшая AS/400). В основном, конечно, это работа с БД и разная бизнес-логика, но иногда приходится и что-то низкоуровневое писать.

Не так давно занимался разработкой удобного и простого в использовании API для работы с User Queue (есть на АС-ке такой системный объект - очередь *USRQ). И в заголовке извлекаемого из очереди сообщения есть такой параметр - message enqueue time (время размещения сообщения в очереди). Который описан как _MI_Time. Которое, в свою очередь, определено как

    /* The standard definition for time in the MI library:           */
    typedef char _MI_Time[8];

MI в данном случае - это Machine Instructions. То, что на АС-ке вместо ассемблера (на верхнем уровне). Набор низкоуровневых команд для различных операций. Для многих MI в С-шной библиотеке есть соответствующие врапперы. В частности, этот самый _MI_Time можно получить функцией

    /* Materialize Time of Day   */
    void mattod  ( _MI_Time );           /* Time-of-day template       */

Или более универсальной (и, как ни странно, более быстрой)

   /* Materialize Machine Data  */
   void matmdata ( _SPCPTR,             /* Machine data template  @A3C*/
                   short );             /* Options                    */

с соответствующим флагом в поле Options.

Но вот вопрос - а что это такое и что с ним делать? Как получить из этого какое-то осмысленное время?

Есть, конечно, несколько системных API, конвертирующих это время во что-то более удобоваримое, но они не слишком производительны (когда, к примеру, вызываешь их 1 000 000 и более раз). Ну и любопытно же...

Документация от IBM это вам не MSDN где все полочкам и с примерами... Тут вдумчивость нужна. И творческий подход.

В конечном итоге удалось установить, что в документации это называется Standard Time и представляет из себя количество микросекунд (да-да-да, именно микросекунд) от некоего начала эпохи. И никакой это не char[8], а вполне себе нормальный uint64.

А вот начало эпохи... Попробуйте угадать :-)

Hidden text

23/08/1928 12:03:06.314752

На всякий случай прописью - 23-е августа 1928-го года, 12 часов, 3 минуты, 6 секунд и еще 314752 микросекунды...

Как говорится, "что курили?"

И нет там никакой "проблемы 2038" как в остальном мире.

Hidden text

Зато есть проблема 08/06/2062 16:27:16.974591

Истину вам говорю - 8-го июня 2062-го года, ровно в 16 часов, 27 минут, 16 секунд и 974591 микросекунду Земля налетит на небесную ось...

Правда, если попытаться все-таки найти хоть какую-то логику, то внезапно становится понятно, что "эпоха" тут привязана не к началу или концу, а к середине. Ибо значение 0x8000000000000000 тут соответствует началу тысячелетия - 01/01/2000 00:00:00.000000

Ну и еще одна тонкость - для хранения собственно времени используется только 52 старших бита. А 12 младших - это т.н. "биты уникальности" которые используются (по задумке IBM) для создания уникальных меток с привязкой ко времени (с точностью до микросекунды). Т.е. "дергая" несколько раз это самое время даже в течении микросекунды, вы каждый раз будете получать уникальное значение, содержащее время и "сиквенс" - номер "внутри" микросекунды. В целом - красивое решение (если где-то потребуется).

К слову сказать, для matmdata определено несколько опций, возвращающих это самое время - локальное или UTC, с битами уникальности или без (всегда нули)

     #define _MDATA_CLOCK                 0x0000
     #define _MDATA_CLOCK_UTC             0x0004  /*              @A3A*/
     #define _MDATA_CLOCK_NOT_UNIQUE      0x0007  /*              @A6A*/
     #define _MDATA_CLOCK_UTC_NOT_UNIQUE  0x0008  /*              @A6A*/

(там есть еще набор опций, но ко времени они не относятся).

Теперь становится понятно что это такое и как из всего этого извлечь какую-то пользу. Например, перевести в привычный UNIXTIME.

Магическим числом тут будет 0x4A2FEC4C82000000 - значение _MI_Time, соответствующее началу UNIX эпохи - 01/01/1970 00:00:00.000000. А дальше просто:

#define IBM_EPOCH 0x4A2FEC4C82000000ULL
#define MKSECS    1000000ULL

  unsigned long long tod;
  unsigned           sec, usec;

  matmdata(&tod, _MDATA_CLOCK_UTC_NOT_UNIQUE);
  
  // приводим к UTC
  tod -= IBM_EPOCH;
  // убираем биты уникальности
  tod >>= 12;

  sec  = (unsigned)(tod / MKSECS);
  usec = (unsigned)(tod % MKSECS);

Получаем результат, идентичный тому, что возвращает gettimeofday() Но быстрее - 100 000 последовательных вызовов gettimeofday занимает 0.301682 сек, а тот же результат при помощи matmdata - 0.011416 сек в одних и тех же условиях.

Воистину - на AS/400 все не как у людей...

Комментарии (29)


  1. dyadyaSerezha
    04.05.2024 10:59

    Это все хорошо, но менять внешние/common переменные внутри функции, это прям какой-то 19 век) Не кошерно ни разу, тем более, что все прекрасно решается через параметры или возвращаемое значение.


    1. SpiderEkb Автор
      04.05.2024 10:59

      Не совсем понятно о каких внешних переменных речь?


      1. Kotofay
        04.05.2024 10:59

        Скорее всего претензии к некошерности mattod, где массив передаётся по неявной неконстантной ссылке, вместо того что бы вернуть его по значению.

        По видимому, "кошерно" выделить память внутри ф-ии и вернуть её по значению, ведь это будет "гораздо эффективнее" и "проще для студентов(-индусов) в поддержке".


        1. SpiderEkb Автор
          04.05.2024 10:59
          +4

          На самом деле, все MI работают с _SPCPTR - space pointer - указатель на область данных. mattod и проч - это не функции, а обертки над MI - достаточно низкоуровневая штука. Это вместо ассемблера (который на уровне обычного разработчика недоступен - так сделано для абстракции от конкретного железа).

          Есть еще _SYSPTR - это указатель на системный объект. Любая MI, работающая с системными объектами (той же очередью *USRQ) на вход получает этот самый системный указатель. Который нужно сначала получить (один раз) по имени и типу объекта. Примерно так:

            #pragma exception_handler(UsrQExeptHandler, 0, _C1_ALL, _C2_ALL, _CTLA_HANDLE_NO_MSG)
              pSP = rslvsp(_Usrq, UsrQName, UsrQLib, _AUTH_ALL);
            #pragma disable_handler 

          _Usrq - тип объекта (системная константа), дальше имя и расположение ("библиотека" - это то, что тут вместо папок) ну и права авторизации к объекту.

          А вот дальше уже везде будет этот самый системный указатель работать

            #pragma exception_handler(UsrQExeptHandler, 0, _C1_ALL, _C2_ALL, _CTLA_HANDLE_NO_MSG)        
              matqat(&mat_template, spQueue);
            #pragma disable_handler

          Получение свойств очереди ("материализация очереди"), mat_template - структура куда все это будет укладываться, spQueue - тот самый системный указатель.

          Ну и так далее...


      1. dyadyaSerezha
        04.05.2024 10:59

        Ой, это я съел чего-то! Сейчас посмотрел - все норм (или уже поменяли?). Но тогда лучше всё оформить в отдельную функцию, я про последний кусок кода.


  1. Sly_tom_cat
    04.05.2024 10:59

    Тоже имел дело с AS-400.... и тоже убедился что там все через ж не как у людей.
    Причем в прикладном ПО тред продолжается (DB2 и т.п.)


  1. suahr
    04.05.2024 10:59

    Согласен с @dyadyaSerezha — если вы меняете внешние переменные внутри функции, это может создать проблемы с предсказуемостью и поддерживаемостью кода. Лучше передавать все через параметры или возвращаемые значения. @SpiderEkb, внешние переменные — это переменные, объявленные за пределами функции, но используемые внутри неё. @Sly_tom_cat, с AS-400 встречался мало, но судя по вашим словам, лучше обойти эту систему стороной, если есть выбор.


    1. SpiderEkb Автор
      04.05.2024 10:59
      +3

      но судя по вашим словам, лучше обойти эту систему стороной, если есть выбор

      На самом деле нет. Там многое непривычно, но это достаточно мощная и очень богатая возможностями система. И если сейчас уйти куда-то в "обычный мир", то... нет, слишком много чего будет нехватать.

      Что касается данного случая - чем это хуже той же memcpy, к примеру? С предсказуемостью и поддерживаемостью там никаких проблем нет - вы передаете указатель на область памяти, которая там внутри заполняется нужным значением. Если не то передадите - получите системное исключение.

      Та же matmdata на самом деле обертка над https://www.ibm.com/docs/en/i/7.4?topic=instructions-materialize-machine-data-matmdata


    1. RedEyedAnonymous
      04.05.2024 10:59

      Вспоминается TurboPascal и Delphi (а заодно и Win32 API), где изменение внешних переменных из функции было штатной фичей.


      1. SpiderEkb Автор
        04.05.2024 10:59

        Ну вообще в "чистом" С это тоже нормальная практика.

        Но MI, повторюсь, ближе к ассемблеру. Там если указатель, то или _SYSPTR или _SPCPTR

        На АС-ке все компиляторы сначала транслируют код в набор MI а потом уже в исполняемый. Более того, MI код также хранится в бинарнике и при переносе на другую платформу система это видит и при первом запуске автоматом перегенерирует исполняемый код.

        Это как если у вас программа под x86, а вы ее переносите на ARM. А система при первом запуске вжух! и перегенерировала бинарь. И вы имеете ту же программу, но оптимизированную под тот проч, на котором ее запустили


        1. RedEyedAnonymous
          04.05.2024 10:59

          Ну вообще в "чистом" С это тоже нормальная практика.

          В чистом С вроде же всё-таки передаётся указатель в явном виде?
          А в паскалях тех оно слегка под капот зарыто, в виде var и out параметров. Т.е. null pointer или указатель на освобождённую память таки можно извернуться и передать, но именно что слегка изворачиваться придется.


          1. SpiderEkb Автор
            04.05.2024 10:59

            Ну тут тоже указатель же. _MI_Time определен как char[8] - имя есть указатель на начало массива.

            А в matmdata вообще _SPCPTR т.к. там если не время заказываешь, там другие структуры сосем. В зависимости от значения параметра option.


          1. SpiderEkb Автор
            04.05.2024 10:59

            Ну в RPG (это для работы с БД и бизнес-логики язык, на нем в основном на АСке пишут - более 80% кода) это тоже зарыто.

            По умолчанию параметр в процедуру передается по ссылке. Если в прототипе это параметр не указан как value. Тогда по значению. Можно еще указать const - тогда тоже по ссылке, но ссылка будет не на саму переменную, а на ее временную копию (ну и компилятор ругнется если попробуешь его изменить внутри).

            null pointer можно передать или если тип переменной явно указан как pointer value, или указав в прототипе для этого аргумента options(*omit) и передавая вместо переменной спецзначение *omit - это и есть передача null вместо указателя на переменную.

            Это тонкости в которые вникаешь когда используешь возможности ILE и вызываешь что-то, написанное на С с чем-то, написанном на RPG (т.е. сама программа на RPG, но кусок ее написан на С (потому что так удобнее) - один исходник на RPG, второй на С. Все это компилится в "модули" (аналог объектного файла) соответствующими компилерами и потом линкуется (bind здесь) в один программный объект. Тут надо понимать как правильно прототипы прописать (как типы переменных стыкуются между собой).


        1. RedEyedAnonymous
          04.05.2024 10:59

          На АС-ке все компиляторы сначала транслируют код в набор MI а потом уже в исполняемый.

          Т.е. байткод, то, что потом было передрано жабой, С# и прочими?


          1. SpiderEkb Автор
            04.05.2024 10:59

            Не совсем. Там нормальный исполняемый код + TIMI ( Technology Independent Machine Instructions) который нужен для перегенерации исполняемого кода при первом запуске на ином, от того под который изначально было сгенерировано, процессоре.

            У нас когда-то сервера были на Power7, потом перешли на Power8. Сейчас Power9. И всегда все программы система при первом после переноса запуске перегенерирует автоматически чтобы исполняемый код был оптимален под тот проц, на котором оно работает.


      1. salnicoff
        04.05.2024 10:59

        Дык это от ассемблеров и машинных кодов тянется, там выбора нет — есть регистр длиной сколько-то бит, и либо весь возврат из функции в них укладывается, либо надо пользовать память. А раз память — то ссылка на адрес, по которому функция будет менять байты.


        1. SpiderEkb Автор
          04.05.2024 10:59
          +1

          На AS-ке есть т.н. SLIC - System Licensed Internal Code. Это то, что написано под конкретное железо. Но обычному пользователю (разработчику) туда нет доступа. Для разработчика доступно все, что выше него. Доступ к SLIC обеспечивается вот этими самыми MI. Т.е. какое бы та ни было железо, SLIC будет разный, а MI одинаковые.

          А поверх MI уже системные API идут. Т.е. MI тут выполняет роль ассемблера (который сам по себе доступен только в SLIC, но не выше).

          Они, конечно, уже не с регистрами работают, но достаточно примитивны - указатель на объект, указатель на область памяти, литерал...

          Вот пример вызова одной программы из другой с выводом результата на экрвн

          DCL SPCPTR .ARG1 INIT(ARG1);
          DCL DD      ARG1 CHAR(10);
          
          DCL SPCPTR .ARG2 INIT(ARG2);
          DCL DD      ARG2 CHAR(10);
          
          DCL OL      MICPGM2 (.ARG1, .ARG2) ARG;
          DCL SYSPTR .MICPGM2;
          
          DCL DD RESOLVE CHAR(34);
              DCL DD RESOLVE-TYPE CHAR( 2) DEF(RESOLVE) POS( 1);
              DCL DD RESOLVE-NAME CHAR(30) DEF(RESOLVE) POS( 3);
              DCL DD RESOLVE-AUTH CHAR( 2) DEF(RESOLVE) POS(33);
          
          ENTRY * EXT;
          RESOLVE-TO-PGM:
              CPYBLA      RESOLVE-TYPE, X'0201';
              CPYBLAP     RESOLVE-NAME, "MICPGM2" , " ";
              RSLVSP     .MICPGM2, RESOLVE, *, *;
          
          LOAD-ARGUMENTS-AND-CALL:
              CPYBLAP     ARG1, "ARG1", " ";
              CPYBLAP     ARG2, "ARG2", " ";
              CALLX      .MICPGM2, MICPGM2, *;
          
          BACK-FROM-CALL:
              CAT         MSG-TEXT, ARG1, ARG2;
              CALLI       SHOW-MESSAGE, *, .SHOW-MESSAGE;
          
          RETURN:
              RTX        *;
          
          %INCLUDE SHOWMSG

          Это еще в старых версиях - там можно было писать чисто на MI (был компилятор). Сейчас убрали, только использовать С-шные "обертки" можно.

          Там еще есть пять уровней защиты системы. От 10-го уровня (отсутствие защиты), до 50-го - защита по сертификату С2 правительства США. Так вот, на уровнях 40 и 50 не все MI доступны пользователью. Есть ограничения. Например, на этих уровнях работа с объектами в домене *SYSTEM через MI запрещена. Только через системные API (более высокий уровень абстракции и интеграции). А через MI можно работать только с объектами в домене *USER.

          Я когда с очередями (Data Queue и User Queue) разбирался (думаю, про это отдельно можно будет написать), то столкнулся с этим. Для работы с *DTAQ есть системные API, для *USRQ - нет (только создание и удаление). Но с *DATQ можно работать точно также через MI - те же enq, deq, matqat... Весь код на 99.999% тот же - вся разница в том, что при получении системного указателя на объект (rslvsp) тип объекта не _Usrq, а _Dtaq

          Но проблема в том, что *DTAQ может быть создан только в домене *SYSTEM (*USRQ - по выбору, можно в *SYSTEM, можно в *USER). И тут наступает облом - мы работаем на 40-м уровне защиты

          При уровне 40 пользователь AS/400 также должен быть зарегистрирован, должен знать правильный пароль для входа в систему и иметь права на доступ к системным ресурсам. Впрочем, пользователи с ограниченными возможностями при этом уровне защиты тоже поддерживаются.   

          В отличие от уровней 10 — 30, при уровне защиты 40 доступ к нестандартным интерфейсам блокирован. Пользователю теперь доступны далеко не все команды MI, а лишь их разрешенный набор, включая сотни API, разработанных для ISV. Остальные же команды блокированы, то есть система не будет исполнять их в пользовательской программе.   

          Тем не менее, команды из блокированного набора по-прежнему доступны OS/400. Для различия программ OS/400 и пользовательских, были введены понятия системного и пользовательского состояния, к которым можно отнести любой процесс на AS/ 400. Использование заблокированных команд и доступ, таким образом, к некоторым объектам системы разрешены только в системном состоянии.

          цитата из Ф.Солтис "Основы AS/400"

          В результате системный указатель-то на объект *DTAQ мне дали, но вот что-то с ним сделать уже нет - любая попытка обратится к объекту по этому указателю приводит к системному исключению ACHTUNG! VERBOTEN!


          1. salnicoff
            04.05.2024 10:59

            Получается, что-то типа Java-машины, только реализованной в железе?


            1. SpiderEkb Автор
              04.05.2024 10:59
              +1

              В том и дело, что нет. Там есть нормальный исполняемый код (не байт-код). Который генерируется системой из TIMI кода. Но поскольку исполняемый код завязан на конкретное железо, то, чтобы не перекомпилировать руками программу для переноса ее на другую машину (на другом железе, но той же ОС), в программе хранится и TIMI код, позволяющей системе сделать это за вас автоматически (там всегда есть метка под какое железо и версию ОС был сгенерирован исполняемый код).

              Т.е. здесь не требуется постоянного присутсвия JVM (или ее аналога) просто чтобы программа работала. Только проверка при запуске - а оно вообще под этот проц скомпилировано?

              Вообще, все это достаточно объемно и сложно не только для комментария, но и даже для статьи. Тем более, что все это описано (и переведено) у Солтиса (один из отцов-основателей этой системы) в книге "Основы AS/400"

              Из авторского предисловия:

              Менее года назад я был в Буэнос-Айресе на встрече с группой пользователей этой системы. По окончании встречи молодой репортер газеты «La Nacion» спросил меня: «Сформулируйте, пожалуйста, коротко причины того, почему в AS/400 столь много новшеств?». И я ответил: «Потому что никто из ее создателей не заканчивал MIT.»

              Заинтригованный моим ответом, репортер попросил разъяснений. Я сказал, что не собирался критиковать MIT, а лишь имел в виду то, что разработчики AS/400 имели совершенно иной опыт, нежели выпускники MIT. Так как всегда было трудно заставить кого-либо переехать с восточного побережья в 70-тысячный миннесотский городок, в лаборатории IBM в Рочестере практически не оказалось выпускников университетов, расположенных на востоке США. И создатели AS/400 — представители «школ» Среднего Запада — не были так сильно привязаны к проектным решениям, используемым другими компаниями.

              И еще из предисловия

              IBM AS/400 — одна из самых интересных по инженерным решениям и эффективных коммерчески компьютерных архитектур. Задолго до того, как термин «объектно-ориентированный» широко распространился, машинный интерфейс высокого уровня AS/400, появившийся в предшествовавшей ей System/38, предоставил разработчикам приложений набор объектов (таких как очереди, индексы и файлы базы данных), которые при создании программы можно было использовать в качестве строительных блоков. Объекты придали высоким функциональным возможностям системы согласованную и простую в работе форму. Унифицированный объектный интерфейс скрывает от программистов AS/400 детали, благодаря чему они могут игнорировать сложные управляющие блоки и системные процедуры, относящиеся к внутренним процессам операционной системы (ОС). Более того, с помощью набора заранее определенных операций ОС ограничивает доступ к объектам. Это обеспечивает приложениям дополнительную защиту при исполнении.

              Это система, целиком и полностью построенная на единой концепции "все есть объект". Тут даже нет файлов и папок - есть объекты - имя, тип, атрибуты. И для каждого типа системой определен допустимый набор операций. Если в иных системах вы можете открыть программу в hex редакторе и поправить какие-то байты в исполняемом коде, то тут это физически невозможно - такая операция не определена системой для объекта типа *PGM.


              1. Kotofay
                04.05.2024 10:59

                Объект типа *PGM нельзя прочитать системными средствами как набор данных?
                А изменить тип можно?


                1. SpiderEkb Автор
                  04.05.2024 10:59

                  Нет. Тип указывается при создании объекта и не может быть изменен.

                  Можно изменить имя, текстовое описание, права доступа пользователей (или групп пользователей). Но не тип или атрибуты (для некоторых типов есть еще атрибуты внутри типа).


          1. SpiderEkb Автор
            04.05.2024 10:59

            Тут, кстати, появляется ловушка - мы можем создать (системным API) *USRQ в домене *SYSTEM, но на уровне 40+ ничего с ней с делать не сможем т.к. вся работа с ней только через MI, которые в данном случае будут запрещены.

            Поэтому в своем USRQ API я жестко зафиксировал создание *USRQ только в *USER.


  1. qark
    04.05.2024 10:59
    +9

    Ибо значение 0x8000000000000000 тут соответствует началу тысячелетия - 01/01/2000 00:00:00.000000

    Но... это же не начало тысячелетия.


  1. vlad_msk_ru
    04.05.2024 10:59
    +1

    Как интересно, я на AS/400 работал, программировал, преподавал и отвечал за продажи в ИБМ. И даже автор редбука по кластерным технологиям. Но чтобы в MI лазить - не, такого не было), не думаю, что это IBM way. Честно говоря, удивлен, что эта платформа еще где-то используется.


  1. SpiderEkb Автор
    04.05.2024 10:59
    +4

    Но чтобы в MI лазить - не, такого не было), не думаю, что это IBM way.

    Ну так скажем - более 80% кода там пишется на RPG (это тема для отдельной статьи)

    Но С/С++ там есть (правда, старенькие - 11-й год).

    Некоторые вещи без MI не сделать. Тот же самый USRQ - есть API для создания и удаления. И все. Читать-писать и все остальное - только через MI. А вещь полезная и удобная. Я для наших задач делал USRQ API (можно использовать из С/С++ или RPG, есть CL команды, есть SQL UDF/UDTF - например, посмотреть скулем содержимое очереди

    CL

    DSPUSRQ USRQ(TSTQUE)

    SQL

    select *
      from table(ALIBVPN.USER_QUEUE_ENTRIES('TSTQUE'));

    Ядро всего этого написано на С в модели памяти TERASPACE с 64-бит указателями. Оформлено в виде SVRPGM. Ну а пользоваться уже откуда угодно можно.

    Когда-то в системе был MI компилятор - видел MI код от Leif Svalgaard, Junlei Li - ну почти ассемблер...

    Потом убрали, оставили только С-врапперы для ряда MI.

    Честно говоря, удивлен, что эта платформа еще где-то используется.

    У нас - как минимум Альфа, Росбанк, Райф, может еще где есть. Были еще машинки в РЖД и ПФР (как сейчас - не знаю).

    В мире - Top Companies Using IBM i

    Ну и ресурсов хватает. Система, конечно, нишевая, но вполне себе используется и развивается - раз в 2-3 года новая версия (сейчас 7.5 самая свежая), 2-3 раза в год - свежий TR (Technology Refresh - минорное обновление системы). Ну и железо - мы на Power9 сидим (IBM Power E980, 120 ядер Power9, RAM 12Тб, 400Тб на SSD, IBM i 7.4), сейчас уже Power10 есть.

    Так что рано хоронить :-)


  1. qw1
    04.05.2024 10:59
    +1

    Эх, а сделали бы 10 "бит уникальности" вместо 12, хватило бы на 250 лет.


    1. GidraVydra
      04.05.2024 10:59
      +1

      Наверное разрабы IBM больше верили в ускорение выполнения операций на 3-4 порядка к 2050-м, чем в существование IBM (или хотя бы их продуктовой линейки 200-летней давности) к 2200-м.


  1. klvov
    04.05.2024 10:59

    нда, прямо как действительно про другой мир рассказываете, зазеркалье какое-то, технологии Древних из мира Фоллаута. Ооочень интересно. Я из IBM-овских машин лично видел какую-то бандуру из z серии, не ней в качестве ОС был какой-то AIX, и там тоже был терминал с зелеными буквами, но нужна она была только для того, чтоб запустить на ней Oracle DB, а над Ораклом - учетную систему банка. Это был примерно 2005 год.
    Понять и проникнуться духом, что это было такое, как оно устроено, и как с этим правильно работать, я тогда не успел - обстоятельства менялись, мне пришлось переезжать в другой город, ну а потом вжух-вжух и вот уже внезапно наступил 2024, и все строят свои инфраструктуры на linux, docker, kuber, kafka, rabbit, postgres, mongo, JVM based solutions и много других новых слов.


  1. SpiderEkb Автор
    04.05.2024 10:59

    IBM-овских машин лично видел какую-то бандуру из z серии, не ней в качестве ОС был какой-то AIX

    Это мейнфреймы. IBM z - потомок Sysyem/390. AIX - более традиционная, UNIX-подобная ОС.

    IBM i - переименованная AS/400 - потомок System/38. Поменьше машинки. Middleware - сначала позиционировались как серверы для малого и среднего бизнеса. Но получилась настолько мощной и масштабируемой что пошла и крупный бизнес. Но ОС там вообще ни на что не похожа принципиально.

    и там тоже был терминал с зелеными буквами

    Скорее всего IBM 3270 У нас тоже "с зелеными буквами". В простонародье "гринскрин". Но другой - IBM 5250. Сейчас, конечно, уже не терминал, а софтовый эмулятор. Мы используем Access Client Solutions (бесплатный пакет от IBM - там много чего кроме терминала для работы с сервером).

    нужна она была только для того, чтоб запустить на ней Oracle DB, а над Ораклом - учетную систему банка

    Аналогично. Только БД тут интегрирована в систему, DB2. И да, тоже крутится АБС банка.

    все строят свои инфраструктуры на linux, docker, kuber, kafka, rabbit, postgres, mongo, JVM based solutions и много других новых слов

    Это другие решения. Они дешевле (там много бесплатного и опенсорсного). Но это белее универсальное. А тут - платформа специализированная именно под бизнес-логику в первую очередь. Это изначально "многопользовательская" система. Каждый процесс в своем изолированном от остальных задании (job) работает. Т.е. контейнеры как бы и не нужны. БД, компиляторы, все средства администрирования - все интегрировано в систему. Отдельно ставили только очередь (IBM MQ, сейчас вот еще кафку прикрутили), но это для общения с внешним миром (тут еще куча "внешних систем", они на других платформах работают - там и RHEL и SLES есть и еще много чего). Для локальных задач есть системные объекты-очереди, более легкие, простые и быстрые (на эту тему будет отдельная статья). Основной язык - RPG Весьма быстр, удобен и эффективен для работы с БД и бизнес-логики т.к. там никаких внешних зависимостей не нужно. В языке есть все для работы с БД (хоть SQL в код встраивай когда нужно) и работы со строками, датой, временем, фиксированной точкой (практически все типы данных, что есть в БД поддерживаются в языке).

    Один минус - это достаточно дорогое решение. Ну и один раз подсев, уже не соскочишь... И разработчиков в стране не так много - Альфа, Райф, Росбанк на этой системе сидят. Ну вендоры есть, кто может под нее что-то делать - BTC, Cinimex, RMS-Lab...

    Действительно, такой себе параллельный мир.