multicast_t::multicast_t(context_t& context, interface& locator, const std::string& name, const dynamic_t& args): category_type(context, locator, name, args), m_context(context), m_log(context.log(name)), m_locator(locator), m_cfg(args.to<multicast_cfg_t>()), m_socket(locator.asio()), m_timer(locator.asio()) { m_socket.open(m_cfg.endpoint.protocol()); m_socket.set_option(socket_base::reuse_address(true)); if(m_cfg.endpoint.address().is_v4()) { m_socket.bind(udp::endpoint(address_v4::any(), m_cfg.endpoint.port())); } else { m_socket.bind(udp::endpoint(address_v6::any(), m_cfg.endpoint.port())); } if(args.as_object().count("interface")) { auto interface = args.as_object().at("interface"); if(m_cfg.endpoint.address().is_v4()) { m_socket.set_option(multicast::outbound_interface(interface.to<ip::address>().to_v4())); } else { m_socket.set_option(multicast::outbound_interface(interface.as_uint())); } } m_socket.set_option(multicast::enable_loopback(args.as_object().at("loopback", false).as_bool())); m_socket.set_option(multicast::hops(args.as_object().at("hops", 1u).as_uint())); COCAINE_LOG_INFO(m_log, "joining multicast group '%s'", m_cfg.endpoint)( "uuid", m_locator.uuid() ); m_socket.set_option(multicast::join_group(m_cfg.endpoint.address())); const auto announce = std::make_shared<announce_t>(); m_socket.async_receive_from(buffer(announce->buffer.data(), announce->buffer.size()), announce->endpoint, std::bind(&multicast_t::on_receive, this, ph::_1, ph::_2, announce) ); m_signals = std::make_shared<dispatch<context_tag>>(name); m_signals->on<context::prepared>(std::bind(&multicast_t::on_publish, this, std::error_code())); context.listen(m_signals, m_locator.asio()); }
node_t::node_t(context_t& context, asio::io_service& asio, const std::string& name, const dynamic_t& args): category_type(context, asio, name, args), dispatch<io::node_tag>(name), context(context), log(context.log(name)) { on<io::node::start_app>(std::bind(&node_t::start_app, this, ph::_1, ph::_2)); on<io::node::pause_app>(std::bind(&node_t::pause_app, this, ph::_1)); on<io::node::list> (std::bind(&node_t::list, this)); on<io::node::info> (std::bind(&node_t::info, this, ph::_1, ph::_2)); // Context signal/slot. signal = std::make_shared<dispatch<io::context_tag>>(name); signal->on<io::context::shutdown>(std::bind(&node_t::on_context_shutdown, this)); const auto runname = args.as_object().at("runlist", "").as_string(); if(runname.empty()) { context.listen(signal, asio); return; } COCAINE_LOG_INFO(log, "reading '%s' runlist", runname); typedef std::map<std::string, std::string> runlist_t; runlist_t runlist; const auto storage = api::storage(context, "core"); try { // TODO: Perform request to a special service, like "storage->runlist(runname)". runlist = storage->get<runlist_t>("runlists", runname); } catch(const std::system_error& err) { COCAINE_LOG_WARNING(log, "unable to read '%s' runlist: %s", runname, err.what()); } if(runlist.empty()) { context.listen(signal, asio); return; } COCAINE_LOG_INFO(log, "starting %d app(s)", runlist.size()); std::vector<std::string> errored; for(auto it = runlist.begin(); it != runlist.end(); ++it) { blackhole::scoped_attributes_t scope(*log, {{ "app", it->first }}); try { start_app(it->first, it->second); } catch(const std::exception& e) { COCAINE_LOG_WARNING(log, "unable to initialize app: %s", e.what()); errored.push_back(it->first); } } if(!errored.empty()) { std::ostringstream stream; std::ostream_iterator<char> builder(stream); boost::spirit::karma::generate(builder, boost::spirit::karma::string % ", ", errored); COCAINE_LOG_WARNING(log, "couldn't start %d app(s): %s", errored.size(), stream.str()); } context.listen(signal, asio); }