int node_id::compare(const node_id& other) const { if (this == &other || data_ == other.data_) return 0; // shortcut for comparing to self or identical instances if (!data_ != !other.data_) return data_ ? 1 : -1; // invalid instances are always smaller // use mismatch instead of strncmp because the // latter bails out on the first 0-byte auto last = host_id().end(); auto ipair = std::mismatch(host_id().begin(), last, other.host_id().begin()); if (ipair.first == last) return static_cast<int>(process_id())-static_cast<int>(other.process_id()); else if (*ipair.first < *ipair.second) return -1; else return 1; }
int node_id::compare(const node_id& other) const { int tmp = strncmp(reinterpret_cast<const char*>(host_id().data()), reinterpret_cast<const char*>(other.host_id().data()), host_id_size); if (tmp == 0) { if (m_process_id < other.process_id()) return -1; else if (m_process_id == other.process_id()) return 0; return 1; } return tmp; }
int node_id::compare(const node_id& other) const { if (this == &other || data_ == other.data_) return 0; // shortcut for comparing to self or identical instances if (! data_ != ! other.data_) return data_ ? 1 : -1; // invalid instances are always smaller int tmp = strncmp(reinterpret_cast<const char*>(host_id().data()), reinterpret_cast<const char*>(other.host_id().data()), host_id_size); return tmp != 0 ? tmp : (process_id() < other.process_id() ? -1 : (process_id() == other.process_id() ? 0 : 1)); }
void actor_namespace::write(serializer* sink, const actor_addr& addr) { CAF_ASSERT(sink != nullptr); if (! addr) { node_id::host_id_type zero; std::fill(zero.begin(), zero.end(), 0); sink->write_value(static_cast<actor_id>(0)); // actor id sink->write_raw(node_id::host_id_size, zero.data()); // host id sink->write_value(static_cast<uint32_t>(0)); // process id } else { // register locally running actors to be able to deserialize them later if (! addr.is_remote()) { auto reg = detail::singletons::get_actor_registry(); reg->put(addr.id(), actor_cast<abstract_actor_ptr>(addr)); } auto pinf = addr.node(); sink->write_value(addr.id()); // actor id sink->write_raw(node_id::host_id_size, pinf.host_id().data()); // host id sink->write_value(pinf.process_id()); // process id } }
int node_id::compare(const node_id& other) const { if (this == &other) { return 0; // shortcut for comparing to self } if (m_data == other.m_data) { return 0; // shortcut for identical instances } if ((m_data != nullptr) != (other.m_data != nullptr)) { return m_data ? 1 : -1; // invalid instances are always smaller } int tmp = strncmp(reinterpret_cast<const char*>(host_id().data()), reinterpret_cast<const char*>(other.host_id().data()), host_id_size); if (tmp == 0) { if (process_id() < other.process_id()) { return -1; } else if (process_id() == other.process_id()) { return 0; } return 1; } return tmp; }
abstract_actor_ptr remote_actor_impl(stream_ptr_pair io, string_set expected) { CPPA_LOGF_TRACE("io{" << io.first.get() << ", " << io.second.get() << "}"); auto mm = get_middleman(); auto pinf = mm->node(); std::uint32_t process_id = pinf->process_id(); // throws on error io.second->write(&process_id, sizeof(std::uint32_t)); io.second->write(pinf->host_id().data(), pinf->host_id().size()); // deserialize: actor id, process id, node id, interface actor_id remote_aid; std::uint32_t peer_pid; node_id::host_id_type peer_node_id; std::uint32_t iface_size; std::set<std::string> iface; auto& in = io.first; // -> actor id in->read(&remote_aid, sizeof(actor_id)); // -> process id in->read(&peer_pid, sizeof(std::uint32_t)); // -> node id in->read(peer_node_id.data(), peer_node_id.size()); // -> interface in->read(&iface_size, sizeof(std::uint32_t)); if (iface_size > max_iface_size) { throw std::invalid_argument("Remote actor claims to have more than" +std::to_string(max_iface_size)+ " message types? Someone is trying" " something nasty!"); } std::vector<char> strbuf; for (std::uint32_t i = 0; i < iface_size; ++i) { std::uint32_t str_size; in->read(&str_size, sizeof(std::uint32_t)); if (str_size > max_iface_clause_size) { throw std::invalid_argument("Remote actor claims to have a" " reply_to<...>::with<...> clause with" " more than" +std::to_string(max_iface_clause_size)+ " characters? Someone is" " trying something nasty!"); } strbuf.reserve(str_size + 1); strbuf.resize(str_size); in->read(strbuf.data(), str_size); strbuf.push_back('\0'); iface.insert(std::string{strbuf.data()}); } // deserialization done, check interface if (iface != expected) { auto tostr = [](const std::set<std::string>& what) -> std::string { if (what.empty()) return "actor"; std::string tmp; tmp = "typed_actor<"; auto i = what.begin(); auto e = what.end(); tmp += *i++; while (i != e) tmp += *i++; tmp += ">"; return tmp; }; auto iface_str = tostr(iface); auto expected_str = tostr(expected); if (expected.empty()) { throw std::invalid_argument("expected remote actor to be a " "dynamically typed actor but found " "a strongly typed actor of type " + iface_str); } if (iface.empty()) { throw std::invalid_argument("expected remote actor to be a " "strongly typed actor of type " + expected_str + " but found a dynamically typed actor"); } throw std::invalid_argument("expected remote actor to be a " "strongly typed actor of type " + expected_str + " but found a strongly typed actor of type " + iface_str); } auto pinfptr = make_counted<node_id>(peer_pid, peer_node_id); if (*pinf == *pinfptr) { // this is a local actor, not a remote actor CPPA_LOGF_INFO("remote_actor() called to access a local actor"); auto ptr = get_actor_registry()->get(remote_aid); return ptr; } struct remote_actor_result { remote_actor_result* next; actor value; }; std::mutex qmtx; std::condition_variable qcv; intrusive::single_reader_queue<remote_actor_result> q; mm->run_later([mm, io, pinfptr, remote_aid, &q, &qmtx, &qcv] { CPPA_LOGC_TRACE("cppa", "remote_actor$create_connection", ""); auto pp = mm->get_peer(*pinfptr); CPPA_LOGF_INFO_IF(pp, "connection already exists (re-use old one)"); if (!pp) mm->new_peer(io.first, io.second, pinfptr); auto res = mm->get_namespace().get_or_put(pinfptr, remote_aid); q.synchronized_enqueue(qmtx, qcv, new remote_actor_result{0, res}); }); std::unique_ptr<remote_actor_result> result(q.synchronized_pop(qmtx, qcv)); CPPA_LOGF_DEBUG(CPPA_MARG(result, get)); return raw_access::get(result->value); }