SObjectizer  5.1
so_sysconf_4: Описание подсистемы

Оглавление

Краткое описание библиотеки so_sysconf_4.

Введение

Подсистема SO SysConf 4 (SObjectier System Configurator – сокращенно Sysconf), является приемником 2-го и 3-го (не публиковалась) поколения библиотеки Sysconf.

Sysconf предоставляет приложениям следующие возможности:

Типичное Sysconf-приложение представляет собой небольшой загрузчик и набор DLL с реализацией специфической прикладной логики. Причем зачастую большинство таких DLL – это вспомогательные и повторно используемые из других проектов (например, so_sysconf_log_3, so_sysconf_gemont_layer и т.п. ). А загрузчик представляет из себя небольшую программу, которая стартует SObjectizer Environment и подсистему Sysconf, после чего указывает Sysconf имя конфигурационного файла с описанием состава приложения и ожидает завершения работы SObjectizer. Основную часть работы по формированию приложения выполняет Sysconf во время разбора и обработки конфигурационного файла.

Кроме того Sysconf в своем составе предоставляет штатные приложения-загрузчики (so_sysconf_4: Штатные загрузчики).

По своей функциональности Sysconf является аналогом фреймворка System Configurator из состава библиотеки ACE. Но Sysconf появилась гораздо раньше, чем ACE начал использоваться в SObjectizer, и делалась с учетом особенностей SObjectizer. Поэтому Sysconf никак не использует System Configurator и является самостоятельной подсистемой.

Обоснование

Необходимость в подсистеме sysconf возникла из-за того, что одни и те же функции в разных случаях должны выполняться с помощью различных средств. Например, для установления SSL соединения можно использовать OpenSSL, GnuTLS или какую-либо коммерческую библиотеку. Для идентификации пользователя нужно либо спросить пароль, либо предложить составить изображение из предложенных фрагментов. Отправку уведомлений можно осуществлять либо через e-mail, либо через SMS. И т.д.

Если в приложении необходимо поддерживать несколько альтернативных возможностей, то возникает вопрос о том, как это сделать. Наиболее простой вариант заключается в том, чтобы на этапе трансляции и линковки исполнительного модуля собрать в единое приложение все необходимые библиотеки (как статические, так и динамические). Но этот способ имеет два важных недостатка:

Более сложный вариант состоит в том, чтобы разделить интерфейс и реализацию какой-либо функций на уровне используемых DLL-библиотек. Например, сделать интерфейс по поддержке SSL-соединений общим для различных реализаций. А сами реализации для OpenSSL и GnuTLS вынести в отдельные DLL. При этом исполнимый модуль не линкуется к реализациям вообще. Вместо этого при своем старте исполнимый модуль определяет, какую реализацию ему нужно использовать в конкретном случае (предположим, по конфигурационному файлу) и самостоятельно, вручную, загружает соответствующую DLL. Как только DLL с реализацией SSL-соединения окажется загруженной, конкретная реализация должна автоматически стать доступной для исполнимого модуля.

При реализации варианта с ручной загрузкой DLL так же существуют сложности. В основном, технического характера. Часть из них преодолевается достаточно просто (например, наличие различных API для работы с DLL в различных операционных системах). Наибольшую сложность вызывает, как правило, то, что после загрузки DLL реализация какой-либо функции должна стать доступной исполнимому модулю. Обычно это достигается использованием какой-либо таблицей доступных реализаций в исполнимом модуле. DLL либо сами прописывают себя в эту таблицу при загрузке (для чего могут использоваться либо глобальные переменные, либо точки входа/выхода в DLL). Либо исполнимый модуль сам определяет адрес какой-то интерфейсной функции в загруженной DLL.

В контексте SObjectizer-приложений Sysconf предполагает размещение средств создания коопераций и дополнительных слоев в различные DLL. Управление загрузкой/выгрузкой DLL и регистрацией/дерегистрацией коопераций средствами этих DLL и установкой слоев является задачей Sysconf. Это значит, что Sysconf берет на себя выполнения рутинных действий связанных с развертывание SObjectizer-инфраструктуры приложения.

Основная схема работы sysconf

Основным интерфейсом подсистемы so_sysconf_4 является слой so_sysconf_layer_t. Вызывая методы этого слоя, можно загружать/выгружать DLL библиотеки, регистрировать и дерегистрировать находящиеся в них кооперации, добавлять и регистрировать в системе SO дополнительные слои.

Предназначенные для использовани с sysconf DLL-библиотеки должны содержать в себе экспортируемую функцию следующего вида:

extern "C" {

  CPP_UTIL_2_EXPORT_FUNC_SPEC( so_sysconf_4::module_description_t * )
    SYSCONF_MODULE_CALLING_CONVENTION so_sysconf_4_module_description()
    {

    std::unique_ptr< so_sysconf_4::std_module_description_t >
      module_desc_name( new so_sysconf_4::std_module_description_t );

    module_desc_name->add_coop_handler(...);
    module_desc_name->add_coop_factory(...);
    module_desc_name->add_named_event(...);
    module_desc_name->add_layer_handler(...);

    return module_desc_name.release();
  }
}

Для упрощения работы с экспортируемой функцией so_sysconf_4 содержит ряд вспомогательных макросов. При их использовании пример выше примет следующий вид:

SYSCONF_4_MODULE_DESCRIPTION_START_STD()

  SYSCONF_4_MODULE_DESCRIPTION_ADD_HANDLER_STD(...)
  SYSCONF_4_MODULE_DESCRIPTION_ADD_FACTORY_STD(...)
  SYSCONF_4_MODULE_DESCRIPTION_ADD_EVENT_STD(...)
  SYSCONF_4_MODULE_DESCRIPTION_ADD_LAYER_HANDLER_STD(...)

SYSCONF_4_MODULE_DESCRIPTION_FINISH_STD()

В качестве аргуметов макросам должны передаваться указатели на динамически созданные объекты классов-регистраторов коопераций, производные от coop_handler_t, coop_factory_t, средства добавления слоев – layer_handler_t, и именованные события – named_event_t. Т.е. на этапе разработки DLL необходимо определить, какие кооперации, именованные события и слои будут находиться в этой DLL. Поскольку в текущей версии sysconf нельзя в динамике изменить состав доступных sysconf коопераций в DLL.

Когда sysconf получает команду на загрузку DLL, указанная DLL загружается в память, и so_sysconf_4 получает список доступных регистраторов.

Все регистраторы коопераций и слоев ,а также именованные события во всех DLL должны иметь уникальные имена. Если при загрузке DLL вясняется, что в ней есть конфликтное имя, то загрузки DLL не происходит, а сообщение об ошибке пишется в журнал Sysconf.

Для регистрации/дерегистрации кооперации подсистеме sysconf выдаются специальные команды. Если регистрация кооперации прошла успешно, то sysconf увеличивает счетчик ссылок на DLL. Sysconf не позволяет выгрузить DLL с ненулевым счетчиком ссылок. При дерегистрации кооперации счетчик ссылок уменьшается.

Особенность регистрации/дерегистрации кооперации.
При регистрации кооперации происходит вызов coop_handler_t::reg(). Если этот метод возращает true, то кооперация считается зарегистрированной и счетчик ссылок на DLL увеличивается. Подразумевается, что метод coop_handler_t::reg() обращается к методу so_5::rt::so_environment_t::register_coop(), и возврат из register_coop() осуществляется только тогда, когда кооперация реально зарегистрирована. При дерегистрации кооперации происходит вызов coop_handler_t::dereg(). Но возврат из этого метода еще не означает, что кооперация окончательно дерегистрирована. Момент окончания дерегистрации определяется после подтверждения от слушателя кооперации о том, что кооперация дерегистрирована. И только после этого счетчик ссылок на DLL уменьшается. Так же это справедливо для coop_factory_t и layer_handler_t

Начиная с версии 4.0.0 в so_sysconf введена функциональность по добавлению дополнительных слоев SObjectizer. За добавление слоя отвечает класс layer_handler_t, в методе которого layer_handler_t::add() необходимо размещать код по добавлению дополнительных слоев.

Заметки
Добавленный слой остается в системе до конца работы, и извлечь его нет возможности. Кроме того DLL в которой находится описание этого слоя не может быть выгружена до момента остановки cлоя и остановки SObjectizer (см. Дополнительные слои).

Использование конфигурационного файла

Управлять подсистемой sysconf с помощью методов слоя so_sysconf_layer_t. Однако этот вариант не всегда слишком удобен из-за необходимости вызовов методов слоя в теле прикладной программы, а значи при необходимости изменения вызовов придется выполнять перекомпиляцию программы. К тому же, в большинстве случаев, нужно в начале работы по конфигурационному файлу определить, из чего будет состоять приложение, один раз загрузить все необходимые DLL и начать работу.

Для облегчения этой задачи sysconf поддерживает работу с конфигурационными файлами специального формата. Функция so_sysconf_layer_t::run_script() запускает на обработку указанный конфигурационный файл.

Формат конфигурационного файла

{sysconf-script
  [{load-dll <str-dll-file-name>
    {os-name-convert <"simple" or "none">}
  }]*

  [{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>}]
  }]*

  [{add-layer <str-layer-name>
  }]
}

Пример конфигурационного файла

Вот пример реального конфигурационного файла для подсистемы sysconf.

{sysconf-script

  {load-dll "so_sysconf.breakflag_handler"
    {os-name-convert "simple"}
  }

  {reg-coop "so_sysconf_4::breakflag_handler::user_break_handler"
  }

  {reg-coop "so_sysconf_4::breakflag_handler::system_break_handler"
  }

  ||
  || COOP_HANDLER
  ||

  {load-dll "sample.so_sysconf_4.dll.coop_handler"
    {os-name-convert "simple"}
    {mandatory}
  }

  {reg-coop "coop_handler_sample::coop_handler"
  }

  {dereg-coop "coop_handler_sample::coop_handler"
  }

  {unload-dll "sample.so_sysconf_4.dll.coop_handler"
    {os-name-convert "simple"}
  }

  ||
  || COOP_FACTORY
  ||

  {load-dll "sample.so_sysconf_4.dll.coop_factory"
    {os-name-convert "simple"}
  }

  {make-coop
    {factory "coop_factory_sample::coop_factory"}
    {coop "unit_factory_1"}
  }

  {make-coop
    {factory "coop_factory_sample::coop_factory"}
    {coop "unit_factory_2"}
  }

  {make-coop
    {factory "coop_factory_sample::coop_factory"}
    {coop "unit_factory_3"}
  }

  {pause 3000
    {comment "before dereg coop"}
  }

  {dereg-coop "unit_factory_1"
  }
  {dereg-coop "unit_factory_2"
  }
  {dereg-coop "unit_factory_3"
  }

  {unload-dll "sample.so_sysconf_4.dll.coop_factory"
    {os-name-convert "simple"}
  }

  ||
  || NAMED_EVENT
  ||

  {load-dll "sample.so_sysconf_4.dll.with_named_event"
    {os-name-convert "simple"}
  }

  {reg-coop "named_event_sample::coop_handler"
  }

  {wait-for "waiting_event"
    {timeout 3000}
    {comment "this one must succeed"}
  }

  {wait-for "never_event"
    {timeout 2000}
    {comment "this one must fail"}
  }

  {dereg-coop "named_event_sample::coop_handler"
  }

  {unload-dll "sample.so_sysconf_4.dll.with_named_event"
    {os-name-convert "simple"}
  }

  ||
  || META_ACTION
  ||

  {load-dll "sample.so_sysconf_4.dll.with_meta_action"
    {os-name-convert "simple"}
  }

  {reg-coop "meta_action_sample::coop_handler"
  }


  {make-coop
    {factory "meta_action_sample::coop_factory"}
    {coop "meta_action_sample::coop_factory"}
  }

}

Завершение работы SObjectizer и sysconf

При использовании sysconf можно завершать работу SObjectizer вызовом метода so_5::rt::so_environment_t::stop() среды SO. Но sysconf предоставляет более развитые средства завершения работы SObjectizer Environment.

Иногда перед завершением работы приложения необходимо выполнить ряд сложных действий. Которые требуют времени и активного циркулирования сообщений в SObjectizer Environment. Например, при закрытии SMPP-соединения нужно выдать специальную команду unbind PDU и получить в ответ unbind_resp PDU. Что требует взаимодействия с агентами связи по TCP/IP. В этом случае нельзя начинать закрытие SMPP-соединения при получении so_5::rt::so_environment_t::stop(). Т.к. в этом случае работа SObjectizer Environment уже фактически завершена.

Слой sysconf содержит функциональность, задачей которой является управление процессом завершения работы SObjectizer Environment.

Каждый агент, который нуждается в специальных процедурах завершения работы должен зарегистрироваться в слое so_sysconf_layer посредством вызова метода so_sysconf_layer_t::subscribe_to_shutdown().

Для завершения работы SObjectizer необходимо вызвать метод so_sysconf_layer_t::stop(). После этого, всем агентам, зарегистрировавшихся в слое so_sysconf_layer отсылается сообщение msg_shutdown. Получив его, агентам нужно начать процедуру завершения своей работы. Когда эта процедура завершится агент должен вызвать метод слоя so_sysconf_layer_t::unsubscribe_from_shutdown().

Когда все зарегистрировавшиеся агенты отпишутся от оповещения о завершении работы, подсистема sysconf начнет завершение работы SObjectizer Environment посредством вызова so_5::rt::so_environment_t::stop().

Определение состояния sysconf

Подсистема sysconf является "черным ящиком" – все управление осуществляется сообщениями. Снаружи sysconf сложно понять, что сейчас загружено и что зарегистрировано. Для получения информации о своем текущем состоянии sysconf предоставляет два механизма.

Первый состоит в том, что при изменении своего состояние sysconf рассылает сообщение so_sysconf_4::msg_sysconf_info, в котором перечисляются все загруженные в данный момент DLL и доступные кооперации со своим статусом. Запросить эту же информацию можно в любой момент, вызвав метод so_sysconf_layer_t::query_sysconf_info().

Второй механизм состоит в том, что подсистеме sysconf при старте может быть назначен специальный объект-журнализатор – объект производного от sysconf_logger_t типа. В этом случае при выполнении своих действий sysconf будет обращаться к журнализатору сообщая неформальное описание выполненого действия.

Механизм объекта-журнализатора может применяться для журналирования событий, происходящих с sysconf в подходящих для приложения хранилищах (текстовых файлах, базах данных, системых журналах Windows NT и т.д.).


Документация по SObjectizer v.5.1 'Джимара'. Последние изменения: Ср 15 Май 2013 12:56:21. Создано системой  doxygen1.8.3.1 Intervale SourceForge.net Logo