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;
}
Beispiel #2
0
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
  }
}
Beispiel #5
0
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;
}
Beispiel #6
0
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);
}