Использование конфигурационного файла
Формат конфигурационного файла
Пример конфигурационного файла
Завершение работы SObjectizer и sysconf
Необходимость в подсистеме sysconf возникла из-за того, что одни и те же функции в разных случаях должны выполняться с помощью различных средств. Например, для установления SSL соединения можно использовать OpenSSL, GnuTLS или какую-либо коммерческую библиотеку. Для идентификации пользователя нужно либо спросить пароль, либо предложить составить изображение из предложенных фрагментов. Отправку уведомлений можно осуществлять либо через e-mail, либо через SMS. И т.д.
Если в приложении необходимо поддерживать несколько альтернативных возможностей, то возникает вопрос о том, как это сделать. Наиболее простой вариант заключается в том, чтобы на этапе трансляции и линковки исполнительного модуля собрать в единое приложение все необходимые библиотеки (как статические, так и динамические). Но этот способ имеет два важных недостатка:
Более сложный вариант состоит в том, чтобы разделить интерфейс и реализацию какой-либо функций на уровне используемых DLL-библиотек. Например, сделать интерфейс по поддержке SSL-соединений общим для различных реализаций. А сами реализации для OpenSSL и GnuTLS вынести в отдельные DLL. При этом исполнимый модуль не линкуется к реализациям вообще. Вместо этого при своем старте исполнимый модуль определяет, какую реализацию ему нужно использовать в конкретном случае (предположим, по конфигурационному файлу) и самостоятельно, вручную, загружает соответствующую DLL. Как только DLL с реализацией SSL-соединения окажется загруженной, конкретная реализация должна автоматически стать доступной для исполнимого модуля.
При реализации варианта с ручной загрузкой DLL так же существуют сложности. В основном, технического характера. Часть из них преодолевается достаточно просто (например, наличие различных API для работы с DLL в различных операционных системах). Наибольшую сложность вызывает, как правило, то, что после загрузки DLL реализация какой-либо функции должна стать доступной исполнимому модулю. Обычно это достигается использованием какой-либо таблицей доступных реализаций в исполнимом модуле. DLL либо сами прописывают себя в эту таблицу при загрузке (для чего могут использоваться либо глобальные переменные, либо точки входа/выхода в DLL). Либо исполнимый модуль сам определяет адрес какой-то интерфейсной функции в загруженной DLL.
В случае с SObjectizer разделение на интерфейс и реализацию осуществляется созданием одного агента (иногда глобального), который служит только владельцем сообщений. Фактически интерфейсом. Для реализации функции создаются агенты, которые подписываются и рассылают сообщения агента-интерфейса. Агенты-реализации должны быть зарегистрированны в SObjectizer run-time. Для этого они должны входить в конкретную кооперацию с уникальным именем.
Sysconf использует это разделение для того, чтобы разместить различные кооперации-реализация в различные DLL. Управление загрузкой/выгрузкой DLL и регистрацией/дерегистрацией находящихся в DLL коопереаций является задачей sysconf.
Основным интерфейсным агентом подсистемы sysconf является глобальный агент типа so_sysconf_2::a_sysconf_t, имеющий имя so_sysconf_2::a_sysconf_t::agent_name(). Осуществляя широковещательную рассылку сообщений этого агента можно загружать/выгружать DLL библиотеки, регистрировать и дерегистрировать находящиеся в них кооперации.
Предназначенные для использования с sysconf DLL-библиотеки должны содержать в себе по одной глобальной переменной на каждую из находящихся в DLL коопераций. Эта переменная должна принадлежать к типу, производному от so_sysconf_2::coop_handler_t. Т.е. на этапе разработки DLL необходимо определить, какие кооперации будут находиться в этой DLL. Поскольку в текущей версии sysconf нельзя в динамике изменить состав доступных sysconf коопераций в DLL.
Когда sysconf получает команду на загрузку DLL, указанная DLL загружается в ОП. При этом запускаются конструкторы глобальных переменных coop_handler. Конструктор базового класса so_sysconf_2::coop_handler_t информирует sysconf о появлении очередной доступной кооперации. Т.о. подсистема sysconf формирует список загруженных DLL и доступных коопераций.
Все кооперации во всех DLL должны иметь уникальные имена.
Для идентификации DLL sysconf требует, чтобы каждой DLL так же был назначен уникальный идентификатор. Он необходим для того, чтобы не использовать в качестве идентификатора имя файла DLL (т.к. имена файлов DLL сильно зависят от операционной системы). При загрузке DLL идентификатор указывается в команде загрузки. Глобальные же переменные coop_handler в DLL должны уже знать идентификатор DLL. Т.е. идентификатор DLL должен быть определен на этапе разработки DLL.
Для регистрации/дерегистрации кооперации подсистеме sysconf выдаются специальные команды. Если регистрация кооперации прошла успешно, то sysconf увеличивает счетчик ссылок на DLL. Sysconf не позволяет выгрузить DLL с ненулевым счетчиком ссылок. При дерегистрации кооперации счетчик ссылок уменьшается.
Для облегчения этой задачи sysconf поддерживает работу с конфигурационными файлами специального формата. Функция so_sysconf_2::run_script() запускает на обработку указанный конфигурационный файл.
{sysconf-script [{load-dll <str-dll-file-name> {alias <str-dll-alias> } }]* [{reg-coop <str-coop-name> [{cfg-file <coop-cfg-file-name> }] }]* [{make-coop {factory <str-factory-name>} {coop <str-coop-name>} [{cfg-file <str-coop-cfg-file-name>}] }]* }
Подробнее о make-coop см. Новое в версии 2.1.0.
|| || Скрипт начальной инициализации AGGREGATE || {sysconf-script |# Загрузка и инициализация подсистемы сохранения истории отправленных SMS в CURL-подобных файлах. #| {load-dll "smsg_2.3.0.subsys.sms_hist_cls.dll" {alias "smsg_2::subsys::sms_hist_cls"} } {reg-coop "smsg_2::subsys::sms_hist_cls" {cfg-file "etc/safe_sms_history.cfg"} } |# Загрузка подсистемы мобильного оператора БиЛайн. Содержит кооперации: smsg_2::subsys::bee_line::moscow smsg_2::subsys::bee_line::region #| {load-dll "smsg.subsys.bee_line.2.3.0.dll" {alias "smsg_2::subsys::bee_line"} } || Инициализация Московского SMSC БиЛайна. {reg-coop "smsg_2::subsys::bee_line::moscow" {cfg-file "etc/bee_line/moscow.cfg"} } || Инициализация регионального SMSC БиЛайна. {reg-coop "smsg_2::subsys::bee_line::region" {cfg-file "etc/bee_line/region.cfg"} } |# Загрузка подсистемы мобильного оператора МТС. Содержит кооперации: smsg_2::subsys::mts::moscow #| {load-dll "smsg.subsys.mts.2.3.0.dll" {alias "smsg_2::subsys::mts"} } || Инициализация Московского SMSC МТС. {reg-coop "smsg_2::subsys::mts::moscow" {cfg-file "etc/mts/moscow.cfg"} } |# Загрузка подсистемы мобильного оператора Мегафон. Содержит кооперации: smsg_2::subsys::megafon::moscow #| {load-dll "smsg.subsys.megafon.2.3.0.dll" {alias "smsg_2::subsys::megafon"} } || Инициализация Московского SMSC Соник Доу. {reg-coop "smsg_2::subsys::megafon::moscow" {cfg-file "etc/megafon/moscow.cfg"} } |# Загрузка подсистемы AGGREGATE. Содержит кооперации: aggregate_1::main::main #| {load-dll "aggregate.main.1.3.dll" {alias "aggregate_1::main"} } || Инициализация AGGREGATE. {reg-coop "aggregate_1::main::main" {cfg-file "etc/aggregate/main.cfg"} } |# Имитация SMSC #| || В данный момент не используется. |# {load-dll "test_smsc_imit.dll" {alias "smsc_imit"} } {reg-coop "smsc_imit::bee_line_moscow" } #| }
Иногда перед завершением работы приложения необходимо выполнить ряд сложных действий. Которые требуют времени и активного циркулирования сообщений в SObjectizer run-time. Например, при закрытии SMPP-соединения нужно выдать специальную команду unbind PDU и получить в ответ unbind_resp PDU. Что требует взаимодействия с агентами связи по TCP/IP. В этом случае нельзя начинать закрытие SMPP-соединения при получении so_4::rt::msg_normal_shutdown. Т.к. в этом случае работа SObjectizer run-time уже фактически завершена.
В sysconf входит интерфейсный агент so_sysconf_2::a_shutdowner_t. Его задачей является управление процессом завершения работы SObjectizer run-time.
Каждый агент, который нуждается в специальных процедурах завершения работы должен зарегистрироваться в a_shutdowner_t посредством отсылки сообщения so_sysconf_2::a_shutdowner_t::msg_register.
Для завершения работы SObjectizer run-time необходимо широковещательно отослать сообщение so_sysconf_2::a_shutdowner_t::msg_shutdown. После этого, всем агентам, зарегистрировавшихся в a_shutdowner_t отсылается сообщение so_sysconf_2::a_shutdowner_t::msg_shutdown_started. Получив его агентам нужно начать процедуру завершения своей работы. Когда эта процедура завершится агент должен отослать сообщение so_sysconf_2::a_shutdowner_t::msg_deregister.
Когда все зарегистрировавшиеся агенты пришлют сообщение so_sysconf_2::a_shutdowner_t::msg_deregister подсистема sysconf начнет завершение работы SObjectizer run-time посредством so_4::rt::msg_normal_shutdown.
Первый состоит в том, что при изменении своего состояние sysconf рассылает сообщение so_sysconf_2::a_sysconf_t::msg_sysconf_info, в котором перечисляются все загруженные в данный момент DLL и доступные кооперации со своим статусом. Запросить эту же информацию можно в любой момент отослав сообщение so_sysconf_2::a_sysconf_t::msg_query_sysconf_info.
Используя тот факт, что агент so_sysconf_2::a_sysconf_t является глобальным, определения состояния sysconf возможно и через специальные внешние программы, взаимодействующие с приложение через SOP.
Второй механизм состоит в том, что подсистеме sysconf при старте может быть назначен специальный объект-журнализатор -- объект производного от so_sysconf_2::sysconf_logger_t типа. В этом случае при выполнении своих действий sysconf будет обращаться к журнализатору сообщая неформальное описание выполненого действия.
Механизм объекта-журнализатора может применяться для журналирования событий, происходящих с sysconf в подходящих для приложения хранилищах (текстовых файлах, базах данных, системых журналах Windows NT и т.д.).
Документация по so_sysconf_2 v.2.4.0. Последние изменения: Wed Oct 31 18:55:07 2007. Создано системой 1.5.4 |