void reactor_t::on_message(const std::shared_ptr<channel<io::socket<tcp>>>& channel_, const message_t& message) { slot_map_t::const_iterator slot = m_slots.find(message.id()); if(slot == m_slots.end()) { COCAINE_LOG_WARNING(m_log, "dropping an unknown type %d message", message.id()); return; } std::string response; try { response = (*slot->second)(message.args()); } catch(const std::exception& e) { COCAINE_LOG_ERROR( m_log, "unable to process type %d message - %s", message.id(), e.what() ); return; } if(!response.empty()) { channel_->wr->stream()->write(response.data(), response.size()); } }
void locator_t::on_message(const key_type& key, const message_t& message) { std::string uuid; std::tie(uuid, std::ignore, std::ignore) = key; switch(message.id()) { case event_traits<io::rpc::chunk>::id: { std::string chunk; message.as<io::rpc::chunk>(chunk); msgpack::unpacked unpacked; msgpack::unpack(&unpacked, chunk.data(), chunk.size()); auto dump = unpacked.get().as<synchronize_result_type>(); auto diff = m_router->update_remote(uuid, dump); for(auto it = diff.second.begin(); it != diff.second.end(); ++it) { m_gateway->cleanup(uuid, it->first); } for(auto it = diff.first.begin(); it != diff.first.end(); ++it) { m_gateway->consume(uuid, it->first, it->second); } } break; case event_traits<io::rpc::error>::id: case event_traits<io::rpc::choke>::id: { COCAINE_LOG_INFO(m_log, "node '%s' has been shut down", uuid); auto removed = m_router->remove_remote(uuid); for(auto it = removed.begin(); it != removed.end(); ++it) { m_gateway->cleanup(uuid, it->first); } // NOTE: It is dangerous to remove the channel while the message is still being // processed, so we defer it via reactor_t::post(). m_reactor.post(deferred_erase_action<decltype(m_remotes)> { m_remotes, key }); } break; default: COCAINE_LOG_ERROR(m_log, "dropped unknown type %d synchronization message", message.id()); } }
void engine_t::on_control(const message_t& message) { std::lock_guard<std::mutex> pool_guard(m_pool_mutex); switch(message.id()) { case event_traits<control::report>::id: { collector_t collector; Json::Value info(Json::objectValue); size_t active = std::count_if( m_pool.cbegin(), m_pool.cend(), std::bind<bool>(std::ref(collector), _1) ); info["load-median"] = static_cast<Json::LargestUInt>(collector.median()); info["queue"]["capacity"] = static_cast<Json::LargestUInt>(m_profile.queue_limit); info["queue"]["depth"] = static_cast<Json::LargestUInt>(m_queue.size()); info["sessions"]["pending"] = static_cast<Json::LargestUInt>(collector.sum()); info["slaves"]["active"] = static_cast<Json::LargestUInt>(active); info["slaves"]["capacity"] = static_cast<Json::LargestUInt>(m_profile.pool_limit); info["slaves"]["idle"] = static_cast<Json::LargestUInt>(m_pool.size() - active); info["state"] = describe[static_cast<int>(m_state)]; m_channel->wr->write<control::info>(0UL, info); } break; case event_traits<control::terminate>::id: { // Prepare for the shutdown. migrate(states::stopping); // NOTE: This message is needed to wake up the app's event loop, which is blocked // in order to allow the stream to flush the message queue. m_channel->wr->write<control::terminate>(0UL); } break; default: COCAINE_LOG_ERROR(m_log, "dropping unknown type %d control message", message.id()); } }