예제 #1
0
expected<accept_handle> abstract_broker::add_tcp_doorman(network::native_socket fd) {
  CAF_LOG_TRACE(CAF_ARG(fd));
  return backend().add_tcp_doorman(this, fd);
}
예제 #2
0
expected<std::pair<accept_handle, uint16_t>>
abstract_broker::add_tcp_doorman(uint16_t port, const char* in,
                                 bool reuse_addr) {
  CAF_LOG_TRACE(CAF_ARG(port) << CAF_ARG(in) << CAF_ARG(reuse_addr));
  return backend().add_tcp_doorman(this, port, in, reuse_addr);
}
예제 #3
0
expected<void> abstract_broker::assign_tcp_doorman(accept_handle hdl) {
  CAF_LOG_TRACE(CAF_ARG(hdl));
  return backend().assign_tcp_doorman(this, hdl);
}
예제 #4
0
expected<void> abstract_broker::assign_tcp_scribe(connection_handle hdl) {
  CAF_LOG_TRACE(CAF_ARG(hdl));
  return backend().assign_tcp_scribe(this, hdl);
}
예제 #5
0
expected<connection_handle>
abstract_broker::add_tcp_scribe(network::native_socket fd) {
  CAF_LOG_TRACE(CAF_ARG(fd));
  return backend().add_tcp_scribe(this, fd);
}
예제 #6
0
 /// Enqueues a new job to the worker's queue from an internal
 /// source, i.e., a job that is currently executed by this worker.
 /// @warning Must not be called from other threads.
 void exec_later(job_ptr job) override {
   CAF_ASSERT(job != nullptr);
   CAF_LOG_TRACE(CAF_ARG(id()) << CAF_ARG(id_of(job)));
   policy_.internal_enqueue(this, job);
 }
예제 #7
0
expected<connection_handle> abstract_broker::add_tcp_scribe(const std::string& hostname,
                                                  uint16_t port) {
  CAF_LOG_TRACE(CAF_ARG(hostname) << ", " << CAF_ARG(port));
  return backend().add_tcp_scribe(this, hostname, port);
}
예제 #8
0
 outbound_stream_slot<output_type> add_outbound_path(const Handle& next) {
   CAF_LOG_TRACE(CAF_ARG(next));
   return this->add_unchecked_outbound_path<output_type>(next);
 }
예제 #9
0
 outbound_stream_slot<output_type, detail::strip_and_convert_t<Ts>...>
 add_outbound_path(const Handle& next, std::tuple<Ts...> xs) {
   CAF_LOG_TRACE(CAF_ARG(next) << CAF_ARG(xs));
   return this->add_unchecked_outbound_path<output_type>(next, std::move(xs));
 }
예제 #10
0
void basp_broker_state::deliver(const node_id& src_nid, actor_id src_aid,
                                strong_actor_ptr dest, message_id mid,
                                std::vector<strong_actor_ptr>& stages,
                                message& msg) {
  CAF_LOG_TRACE(CAF_ARG(src_nid) << CAF_ARG(src_aid) << CAF_ARG(dest)
                << CAF_ARG(msg) << CAF_ARG(mid));
  auto src = src_nid == this_node() ? system().registry().get(src_aid)
                                    : proxies().get_or_put(src_nid, src_aid);
  // Intercept link messages. Forwarding actor proxies signalize linking
  // by sending link_atom/unlink_atom message with src = dest.
  if (msg.type_token() == make_type_token<atom_value, strong_actor_ptr>()) {
    switch (static_cast<uint64_t>(msg.get_as<atom_value>(0))) {
      default:
        break;
      case link_atom::value.uint_value(): {
        if (src_nid != this_node()) {
          CAF_LOG_WARNING("received link message for an other node");
          return;
        }
        auto ptr = msg.get_as<strong_actor_ptr>(1);
        if (!ptr) {
          CAF_LOG_WARNING("received link message with invalid target");
          return;
        }
        if (!src) {
          CAF_LOG_DEBUG("received link for invalid actor, report error");
          anon_send(actor_cast<actor>(ptr),
                    make_error(sec::remote_linking_failed));
          return;
        }
        static_cast<actor_proxy*>(ptr->get())->local_link_to(src->get());
        return;
      }
      case unlink_atom::value.uint_value(): {
        if (src_nid != this_node()) {
          CAF_LOG_WARNING("received unlink message for an other node");
          return;
        }
        auto ptr = msg.get_as<strong_actor_ptr>(1);
        if (!ptr) {
          CAF_LOG_DEBUG("received unlink message with invalid target");
          return;
        }
        if (!src) {
          CAF_LOG_DEBUG("received unlink for invalid actor, report error");
          return;
        }
        static_cast<actor_proxy*>(ptr->get())->local_unlink_from(src->get());
        return;
      }
    }
  }
  if (!dest) {
    auto rsn = exit_reason::remote_link_unreachable;
    CAF_LOG_INFO("cannot deliver message, destination not found");
    self->parent().notify<hook::invalid_message_received>(src_nid, src,
                                                          invalid_actor_id,
                                                          mid, msg);
    if (mid.valid() && src) {
      detail::sync_request_bouncer srb{rsn};
      srb(src, mid);
    }
    return;
  }
  self->parent().notify<hook::message_received>(src_nid, src, dest, mid, msg);
  dest->enqueue(make_mailbox_element(std::move(src), mid, std::move(stages),
                                      std::move(msg)),
                nullptr);
}
예제 #11
0
bool monitorable_actor::remove_backlink(abstract_actor* x) {
  // Called in an exclusive critical section.
  CAF_LOG_TRACE(CAF_ARG(x));
  default_attachable::observe_token tk{x->address(), default_attachable::link};
  return detach_impl(tk, true) > 0;
}
예제 #12
0
void basp_broker_state::kill_proxy(const node_id& nid, actor_id aid,
                                   const error& rsn) {
  CAF_LOG_TRACE(CAF_ARG(nid) << CAF_ARG(aid) << CAF_ARG(rsn));
  proxies().erase(nid, aid, rsn);
}
예제 #13
0
void outbound_path::emit_regular_shutdown(local_actor* self) {
  CAF_LOG_TRACE(CAF_ARG(slots));
  unsafe_send_as(self, hdl,
                 make<downstream_msg::close>(slots, self->address()));
}
예제 #14
0
void outbound_path::emit_irregular_shutdown(local_actor* self, error reason) {
  CAF_LOG_TRACE(CAF_ARG(slots) << CAF_ARG(reason));
  unsafe_send_as(self, hdl,
                 make<downstream_msg::forced_close>(slots, self->address(),
                                                    std::move(reason)));
}
예제 #15
0
void abstract_broker::ack_writes(connection_handle hdl, bool enable) {
  CAF_LOG_TRACE(CAF_ARG(hdl) << CAF_ARG(enable));
  auto x = by_id(hdl);
  if (x)
    x->ack_writes(enable);
}
예제 #16
0
bool actor_pool::filter(upgrade_lock<detail::shared_spinlock>& guard,
                        const strong_actor_ptr& sender, message_id mid,
                        message_view& mv, execution_unit* eu) {
  auto& content = mv.content();
  CAF_LOG_TRACE(CAF_ARG(mid) << CAF_ARG(content));
  if (content.match_elements<exit_msg>()) {
    // acquire second mutex as well
    std::vector<actor> workers;
    auto em = content.get_as<exit_msg>(0).reason;
    if (cleanup(std::move(em), eu)) {
      auto tmp = mv.move_content_to_message();
      // send exit messages *always* to all workers and clear vector afterwards
      // but first swap workers_ out of the critical section
      upgrade_to_unique_lock<detail::shared_spinlock> unique_guard{guard};
      workers_.swap(workers);
      unique_guard.unlock();
      for (auto& w : workers)
        anon_send(w, tmp);
      is_registered(false);
    }
    return true;
  }
  if (content.match_elements<down_msg>()) {
    // remove failed worker from pool
    auto& dm = content.get_as<down_msg>(0);
    upgrade_to_unique_lock<detail::shared_spinlock> unique_guard{guard};
    auto last = workers_.end();
    auto i = std::find(workers_.begin(), workers_.end(), dm.source);
    CAF_LOG_DEBUG_IF(i == last, "received down message for an unknown worker");
    if (i != last)
      workers_.erase(i);
    if (workers_.empty()) {
      planned_reason_ = exit_reason::out_of_workers;
      unique_guard.unlock();
      quit(eu);
    }
    return true;
  }
  if (content.match_elements<sys_atom, put_atom, actor>()) {
    auto& worker = content.get_as<actor>(2);
    worker->attach(default_attachable::make_monitor(worker.address(),
                                                    address()));
    upgrade_to_unique_lock<detail::shared_spinlock> unique_guard{guard};
    workers_.push_back(worker);
    return true;
  }
  if (content.match_elements<sys_atom, delete_atom, actor>()) {
    upgrade_to_unique_lock<detail::shared_spinlock> unique_guard{guard};
    auto& what = content.get_as<actor>(2);
    auto last = workers_.end();
    auto i = std::find(workers_.begin(), last, what);
    if (i != last) {
      workers_.erase(i);
    }
    return true;
  }
  if (content.match_elements<sys_atom, get_atom>()) {
    auto cpy = workers_;
    guard.unlock();
    sender->enqueue(nullptr, mid.response_id(),
                    make_message(std::move(cpy)), eu);
    return true;
  }
  if (workers_.empty()) {
    guard.unlock();
    if (sender && mid.valid()) {
      // tell client we have ignored this sync message by sending
      // and empty message back
      sender->enqueue(nullptr, mid.response_id(), message{}, eu);
    }
    return true;
  }
  return false;
}
예제 #17
0
void acceptor::removed_from_loop(operation op) {
  CAF_LOG_TRACE(CAF_ARG2("fd", fd()) << CAF_ARG(op));
  if (op == operation::read)
    mgr_.reset();
}
예제 #18
0
 /// Enqueues a new job to the worker's queue from an external
 /// source, i.e., from any other thread.
 void external_enqueue(job_ptr job) {
   CAF_ASSERT(job != nullptr);
   CAF_LOG_TRACE(CAF_ARG(id()) << CAF_ARG(id_of(job)));
   policy_.external_enqueue(this, job);
 }