sample/app/main.cpp

Пример приложения, позволяющего работать с SO SysConf 2 в интерактивном режиме.

//
// Главное приложение примера.
//
// Создает подсистему SO SysConf 2 и организует интерактивный
// диалог с оператором.
//
// Демонстрирует два способа журналирования состояния SO SysConf 2:
// - назначение подсистеме SO SysConf 2 журнализатора;
// - прослушивание сообщений
// so_sysconf_2::a_sysconf_t::msg_sysconf_info.
//

#include <iostream>
#include <memory>
#include <sstream>

// Загружаем средства поддержки многопоточности.
#include <ace/OS.h>
#include <ace/Thread_Manager.h>

// Загружаем необходимые заголовочные файлы SObjectizer.
#include <so_4/rt/h/rt.hpp>
#include <so_4/rt/h/msg_auto_ptr.hpp>
#include <so_4/api/h/api.hpp>

#include <so_4/timer_thread/simple/h/pub.hpp>
#include <so_4/disp/one_thread/h/pub.hpp>

// Загружаем описание агента a_sysconf_t для доступа
// к его сообщениям.
#include <so_sysconf_2/h/a_sysconf.hpp>

// Загружаем описание журнализатора в std::ostream
// для печати изменений состояния SO SysConf 2 на
// стандартный поток вывода.
#include <so_sysconf_2/h/ostream_sysconf_logger.hpp>

// Средства запуска SO SysConf 2.
#include <so_sysconf_2/h/pub.hpp>

//
// a_sysconf_listener_t
//

/*
  Агент, который будет слушать состояние sysconf.
  Для этого агент подписывается на сообщение
  so_sysconf_2::a_sysconf_t::msg_sysconf_info.

  Агент a_sysconf_listener будет создаваться до того,
  как будет запущена подсистема sysconf. Поэтому
  агент a_sysconf_listener должен подписываться
  на сообщение msg_sysconf_info только после
  запуска sysconf. Для этого агенту a_sysconf_listener
  после старта sysconf нужно отослать сообщение
  a_sysconf_listener_t::msg_subscr.
*/
class a_sysconf_listener_t :
  public so_4::rt::agent_t
{
  typedef so_4::rt::agent_t base_type_t;
  public :
    a_sysconf_listener_t();
    virtual ~a_sysconf_listener_t();

    const char *
    so_query_type() const;

    void
    so_on_subscription();

    // Имя единственного агента данного типа.
    static const std::string &
    agent_name();

    // Сообщение, дающее команду агенту подписаться
    // на сообщение msg_sysconf_info.
    struct  msg_subscr
    {
    };

    // Обработчик изменения состояния sysconf.
    void
    evt_sysconf_info(
      const so_4::rt::event_data_t & data,
      const so_sysconf_2::a_sysconf_t::msg_sysconf_info * cmd );

    // Подписка на сообщение msg_sysconf_info.
    void
    evt_subscr(
      const so_4::rt::event_data_t & data,
      const msg_subscr * cmd );

};

SOL4_CLASS_START( a_sysconf_listener_t )

  SOL4_MSG_START( msg_subscr,
    a_sysconf_listener_t::msg_subscr )
  SOL4_MSG_FINISH()

  SOL4_EVENT_WITH_INCIDENT_TYPE(
    evt_sysconf_info,
    so_sysconf_2::a_sysconf_t::msg_sysconf_info )
  SOL4_EVENT_WITH_INCIDENT_TYPE(
    evt_subscr,
    a_sysconf_listener_t::msg_subscr )

  SOL4_STATE_START( st_normal )
    SOL4_STATE_EVENT( evt_sysconf_info )
    SOL4_STATE_EVENT( evt_subscr )
  SOL4_STATE_FINISH()

SOL4_CLASS_FINISH()

a_sysconf_listener_t::a_sysconf_listener_t()
  :
    base_type_t( agent_name().c_str() )
{
}

a_sysconf_listener_t::~a_sysconf_listener_t()
{
}

void
a_sysconf_listener_t::so_on_subscription()
{
  // Сразу можно подписаться только на
  // собственное сообщение.
  SOL4_SUBSCR_EVENT_START( evt_subscr, 0 )
    SOL4_SUBSCR_EVENT_MSG_SELF(
      "msg_subscr" )
  SOL4_SUBSCR_EVENT_FINISH_CERR()
}

const std::string &
a_sysconf_listener_t::agent_name()
{
  static const std::string name( "a_sysconf_listener" );
  return name;
}

void
a_sysconf_listener_t::evt_sysconf_info(
  const so_4::rt::event_data_t & data,
  const so_sysconf_2::a_sysconf_t::msg_sysconf_info * cmd )
{
  std::ostringstream out;

  // Начинается распечатка текущего состояния.
  out << "*** sysconf info begin ***\n";

  // Просмотр всех загруженных sysconf-ом DLL.
  const so_sysconf_2::dll_info_set_t & dlls =
    cmd->m_info.query_dlls();
  for( so_sysconf_2::dll_info_set_t::const_iterator
      it_dll = dlls.begin(),
      it_dll_end = dlls.end();
    it_dll != it_dll_end;
    ++it_dll )
  {
    // То, что известно про DLL.
    out << it_dll->query_alias() << " (file_name: "
      << it_dll->query_file_name() << ", ref_count: "
      << it_dll->query_ref_count() << ")\n";

    // Просмотр всех коопераций, находящихся
    // в данной DLL.
    const so_sysconf_2::coop_info_set_t & coops =
      it_dll->query_coops();
    for( so_sysconf_2::coop_info_set_t::const_iterator
        it_coop = coops.begin(),
        it_coop_end = coops.end();
      it_coop != it_coop_end;
      ++it_coop )
    {
      // То, что известно про кооперацию.
      out << "\tcooperation: " << it_coop->query_coop_name();
      if( it_coop->is_reg() )
        out << ", registered";
      out << "\n";
    }

    // Просмотр всех фабрик, находящихся
    // в данной DLL.
    const so_sysconf_2::factory_info_set_t & factories =
      it_dll->query_factories();
    for( so_sysconf_2::factory_info_set_t::const_iterator
        it_factory = factories.begin(),
        it_factory_end = factories.end();
      it_factory != it_factory_end;
      ++it_factory )
    {
      // То, что известно про фабрику.
      out << "\tfactory: " << it_factory->query_factory_name()
        << "\n";
    }
  }

  out << "*** sysconf info end ***\n";

  // Распечатка текущего состояния завершена.

  std::cout << out.str() << std::endl;
}

void
a_sysconf_listener_t::evt_subscr(
  const so_4::rt::event_data_t & data,
  const msg_subscr * )
{
  SOL4_SUBSCR_EVENT_START( evt_sysconf_info, 0 )
    SOL4_SUBSCR_EVENT_MSG(
      so_sysconf_2::a_sysconf_t::agent_name(),
      "msg_sysconf_info" )
  SOL4_SUBSCR_EVENT_FINISH_CERR()
}


//
// Нить, на которой будет происходить запуск SObjectizer-а
//
ACE_THR_FUNC_RETURN
sobjectizer_thread( void * )
{
  // Используется простой таймер.
  std::auto_ptr< so_4::timer_thread::timer_thread_t >
    timer_ptr( so_4::timer_thread::simple::create_timer_thread() );

  // Используется простой диспетчер с одной рабочей нитью.
  std::auto_ptr< so_4::rt::dispatcher_t >
    disp_ptr( so_4::disp::one_thread::create_disp( *timer_ptr ) );

  // В стартовую кооперацию будет входить только слушатель
  // состояния подсистемы sysconf.
  a_sysconf_listener_t a_listener;
  so_4::rt::agent_coop_t coop( a_listener );

  so_4::ret_code_t rc = so_4::api::start( *disp_ptr, &coop );
  if( rc )
  {
    // Запуск SObjectizer не удался.
    std::cerr << "start: " << rc << std::endl;
  }

  return 0;
}

int
main( int argc, char ** argv )
{
  // Запускаем SObjectizer.
  ACE_Thread_Manager::instance()->spawn( &sobjectizer_thread );

  // Даем время SObjectizer для старта.
  ACE_OS::sleep( 1 );

  // Цикл интерактивного взаимодействия с оператором.
  bool is_continue = true;
  while( is_continue )
  {
    // Задержка для отладочных печатей.
    ACE_Time_Value pause( 0, 250000 );
    ACE_OS::sleep( pause );

    std::string choice;

    std::cout << "Choose action:\n"
      "\t0  - quit\n"
      "\t1  - create sysconf cooperation\n"
      "\t2  - parse config file\n"
      "\t3  - send msg_reg_coop\n"
      "\t4  - send msg_dereg_coop\n"
      "\t5  - send msg_load_dll\n"
      "\t6  - send msg_unload_dll\n"
      "\t7  - send msg_query_sysconf_info\n"
      "\t8  - send msg_make_coop\n"
      "\t9  - send msg_event\n"
      "\t10 - send msg_restart_coop\n"
      "\t11 - send msg_rereg_coop\n"

      << std::flush;

    std::cin >> choice;
    if( !std::cin )
      choice = "0";

    if( choice == "0" )
    {
      // Необходимо завершить работу примера.
      so_4::api::send_msg(
        so_4::rt::sobjectizer_agent_name(),
        "msg_normal_shutdown", 0,
        so_4::rt::sobjectizer_agent_name() );
      is_continue = false;
    }
    else if( choice == "1" )
    {
      // Стартуем подсистему sysconf.
      so_sysconf_2::register_coop(
        new so_sysconf_2::ostream_sysconf_logger_t() );
      // Указываем слушателю на необходимость
      // начать прослушивать состояние sysconf.
      so_4::api::send_msg(
        a_sysconf_listener_t::agent_name(),
        "msg_subscr", 0 );
    }
    else if( choice == "2" )
    {
      // Запрашиваем имя конфигурационного файла...
      std::string config_file_name;
      std::cout << "Enter config file name: "
        << std::flush;
      std::cin >> config_file_name;

      // ... и инициируем обработку этого файла.
      so_sysconf_2::run_script( config_file_name );
    }
    else if( choice == "3" )
    {
      // Подготавливаем сообщение-команду регистрации
      // кооперации.
      so_4::rt::msg_auto_ptr_t<
        so_sysconf_2::a_sysconf_t::msg_reg_coop >
        msg( new so_sysconf_2::a_sysconf_t::msg_reg_coop() );

      std::cout << "Enter coop_name: " << std::flush;
      std::cin >> msg->m_coop_name;
      std::cout << "Enter cfg_file: " << std::flush;
      std::cin >> msg->m_cfg_file;

      // Отдаем команду.
      msg.send( so_sysconf_2::a_sysconf_t::agent_name(),
        "msg_reg_coop" );
    }
    else if( choice == "4" )
    {
      // Подготавливаем сообщение-команду дерегистрации
      // кооперации.
      so_4::rt::msg_auto_ptr_t<
        so_sysconf_2::a_sysconf_t::msg_dereg_coop >
        msg( new so_sysconf_2::a_sysconf_t::
          msg_dereg_coop() );

      std::cout << "Enter coop_name: " << std::flush;
      std::cin >> msg->m_coop_name;

      // Отдаем команду.
      msg.send( so_sysconf_2::a_sysconf_t::agent_name(),
        "msg_dereg_coop" );
    }
    else if( choice == "5" )
    {
      // Подготавливаем сообщение-команду загрузки DLL.
      so_4::rt::msg_auto_ptr_t<
        so_sysconf_2::a_sysconf_t::msg_load_dll >
        msg( new so_sysconf_2::a_sysconf_t::msg_load_dll() );

      std::cout << "Enter dll_name: " << std::flush;
      std::cin >> msg->m_dll_name;
      std::cout << "Enter dll_alias: " << std::flush;
      std::cin >> msg->m_dll_alias;

      // Отдаем команду.
      msg.send( so_sysconf_2::a_sysconf_t::agent_name(),
        "msg_load_dll" );
    }
    else if( choice == "6" )
    {
      // Подготавливаем сообщение-команду выгрузки DLL.
      so_4::rt::msg_auto_ptr_t<
        so_sysconf_2::a_sysconf_t::msg_unload_dll >
        msg( new so_sysconf_2::a_sysconf_t::msg_unload_dll() );

      std::cout << "Enter dll_alias: " << std::flush;
      std::cin >> msg->m_dll_alias;

      // Отдаем команду.
      msg.send( so_sysconf_2::a_sysconf_t::agent_name(),
        "msg_unload_dll" );
    }
    else if( choice == "7" )
    {
      // Выдаем команду sysconf-у на информирование
      // о своем текущем состоянии.
      so_4::api::send_msg(
          so_sysconf_2::a_sysconf_t::agent_name(),
        "msg_query_sysconf_info", 0 );
    }
    else if( choice == "8" )
    {
      // Подготавливаем сообщение-команду создания
      // кооперации при помощи фабрики.
      so_4::rt::msg_auto_ptr_t<
        so_sysconf_2::a_sysconf_t::msg_make_coop >
        msg( new so_sysconf_2::a_sysconf_t::msg_make_coop() );

      std::cout << "Enter factory_name: " << std::flush;
      std::cin >> msg->m_factory_name;
      std::cout << "Enter coop_name: " << std::flush;
      std::cin >> msg->m_coop_name;
      std::cout << "Enter cfg_file: " << std::flush;
      std::cin >> msg->m_cfg_file;

      // Отдаем команду.
      msg.send( so_sysconf_2::a_sysconf_t::agent_name(),
        "msg_make_coop" );
    }
    else if( choice == "9" )
    {
      so_4::rt::msg_auto_ptr_t<
        so_sysconf_2::a_sysconf_t::msg_event >
        msg( new so_sysconf_2::a_sysconf_t::msg_event() );

      std::cout << "Enter event_name: " << std::flush;
      std::cin >> msg->m_event_name;

      // Отдаем команду.
      msg.send( so_sysconf_2::a_sysconf_t::agent_name(),
        "msg_event" );
    }
    else if( choice == "10" )
    {
      // Подготавливаем сообщение-команду перерегистрации
      // кооперации.
      so_4::rt::msg_auto_ptr_t<
        so_sysconf_2::a_sysconf_t::msg_restart_coop >
        msg( new so_sysconf_2::a_sysconf_t::
          msg_restart_coop() );

      std::cout << "Enter coop_name: " << std::flush;
      std::cin >> msg->m_coop_name;

      // Отдаем команду.
      msg.send( so_sysconf_2::a_sysconf_t::agent_name(),
        "msg_restart_coop" );
    }
    else if( choice == "11" )
    {
      // Подготавливаем сообщение-команду перерегистрации
      // кооперации с новым конфигом.
      so_4::rt::msg_auto_ptr_t<
        so_sysconf_2::a_sysconf_t::msg_rereg_coop >
        msg( new so_sysconf_2::a_sysconf_t::
          msg_rereg_coop() );

      std::cout << "Enter coop_name: " << std::flush;
      std::cin >> msg->m_coop_name;
      std::cout << "Enter cfg_file: " << std::flush;
      std::cin >> msg->m_cfg_file;

      // Отдаем команду.
      msg.send( so_sysconf_2::a_sysconf_t::agent_name(),
        "msg_rereg_coop" );
    }

  }

  // Ожидаем окончательного завершения работы SObjectizer.
  ACE_Thread_Manager::instance()->wait();

  return 0;
}


Документация по so_sysconf_2 v.2.4.0. Последние изменения: Wed Oct 31 18:55:07 2007. Создано системой  doxygen1.5.4 Intervale SourceForge.net Logo