Commit 625ff651 authored by Dominik Charousset's avatar Dominik Charousset

Remove unused stream multiplexers

parent 113bbae9
...@@ -55,7 +55,6 @@ set (LIBCAF_CORE_SRCS ...@@ -55,7 +55,6 @@ set (LIBCAF_CORE_SRCS
src/group.cpp src/group.cpp
src/group_manager.cpp src/group_manager.cpp
src/group_module.cpp src/group_module.cpp
src/incoming_stream_multiplexer.cpp
src/invoke_result_visitor.cpp src/invoke_result_visitor.cpp
src/local_actor.cpp src/local_actor.cpp
src/logger.cpp src/logger.cpp
...@@ -70,7 +69,6 @@ set (LIBCAF_CORE_SRCS ...@@ -70,7 +69,6 @@ set (LIBCAF_CORE_SRCS
src/message_view.cpp src/message_view.cpp
src/monitorable_actor.cpp src/monitorable_actor.cpp
src/node_id.cpp src/node_id.cpp
src/outgoing_stream_multiplexer.cpp
src/parse_ini.cpp src/parse_ini.cpp
src/pretty_type_name.cpp src/pretty_type_name.cpp
src/private_thread.cpp src/private_thread.cpp
...@@ -96,7 +94,6 @@ set (LIBCAF_CORE_SRCS ...@@ -96,7 +94,6 @@ set (LIBCAF_CORE_SRCS
src/stream_handler.cpp src/stream_handler.cpp
src/stream_id.cpp src/stream_id.cpp
src/stream_msg_visitor.cpp src/stream_msg_visitor.cpp
src/stream_multiplexer.cpp
src/stream_priority.cpp src/stream_priority.cpp
src/stream_sink.cpp src/stream_sink.cpp
src/stream_source.cpp src/stream_source.cpp
......
...@@ -129,7 +129,7 @@ public: ...@@ -129,7 +129,7 @@ public:
friend class abstract_actor; friend class abstract_actor;
/// The number of actors implictly spawned by the actor system on startup. /// The number of actors implictly spawned by the actor system on startup.
static constexpr size_t num_internal_actors = 3; static constexpr size_t num_internal_actors = 2;
/// Returns the ID of an internal actor by its name. /// Returns the ID of an internal actor by its name.
/// @pre x in {'SpawnServ', 'ConfigServ', 'StreamServ'} /// @pre x in {'SpawnServ', 'ConfigServ', 'StreamServ'}
...@@ -148,12 +148,6 @@ public: ...@@ -148,12 +148,6 @@ public:
return internal_actors_[internal_actor_id(atom("ConfigServ"))]; return internal_actors_[internal_actor_id(atom("ConfigServ"))];
} }
/// Returns the internal actor for managing streams that
/// cross network boundaries.
inline const strong_actor_ptr& stream_serv() const {
return internal_actors_[internal_actor_id(atom("StreamServ"))];
}
actor_system() = delete; actor_system() = delete;
actor_system(const actor_system&) = delete; actor_system(const actor_system&) = delete;
actor_system& operator=(const actor_system&) = delete; actor_system& operator=(const actor_system&) = delete;
...@@ -545,10 +539,6 @@ private: ...@@ -545,10 +539,6 @@ private:
internal_actors_[internal_actor_id(atom("ConfigServ"))] = std::move(x); internal_actors_[internal_actor_id(atom("ConfigServ"))] = std::move(x);
} }
/// Sets the internal actor for managing streams that
/// cross network boundaries. Called in middleman::start.
void stream_serv(strong_actor_ptr x);
std::atomic<size_t> ids_; std::atomic<size_t> ids_;
uniform_type_info_map types_; uniform_type_info_map types_;
node_id node_; node_id node_;
......
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2017 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#ifndef CAF_DETAIL_INCOMING_STREAM_MULTIPLEXER_HPP
#define CAF_DETAIL_INCOMING_STREAM_MULTIPLEXER_HPP
#include <deque>
#include <cstdint>
#include <algorithm>
#include <unordered_map>
#include "caf/actor.hpp"
#include "caf/error.hpp"
#include "caf/local_actor.hpp"
#include "caf/stream_msg.hpp"
#include "caf/detail/stream_multiplexer.hpp"
namespace caf {
namespace detail {
// Forwards messages from local actors to a remote stream_serv.
class incoming_stream_multiplexer : public stream_multiplexer {
public:
/// Allow `variant` to recognize this type as a visitor.
using result_type = void;
incoming_stream_multiplexer(local_actor* self, backend& service);
void operator()(stream_msg& x);
/// @pre `self_->current_sender() != nullptr && current_stream_state_valid()`
void operator()(stream_msg::open&);
/// @pre `self_->current_sender() != nullptr && current_stream_state_valid()`
void operator()(stream_msg::ack_open&);
/// @pre `self_->current_sender() != nullptr && current_stream_state_valid()`
void operator()(stream_msg::batch&);
/// @pre `self_->current_sender() != nullptr && current_stream_state_valid()`
void operator()(stream_msg::ack_batch&);
/// @pre `self_->current_sender() != nullptr && current_stream_state_valid()`
void operator()(stream_msg::close&);
/// @pre `self_->current_sender() != nullptr && current_stream_state_valid()`
void operator()(stream_msg::abort&);
/// @pre `self_->current_sender() != nullptr && current_stream_state_valid()`
void operator()(stream_msg::downstream_failed&);
/// @pre `self_->current_sender() != nullptr && current_stream_state_valid()`
void operator()(stream_msg::upstream_failed&);
private:
// Forwards the current stream_msg upstream.
// @pre `current_stream_msg != nullptr`
void forward_to_upstream();
// Forwards the current stream_msg downstream.
// @pre `current_stream_msg != nullptr`
void forward_to_downstream();
};
} // namespace detail
} // namespace caf
#endif // CAF_DETAIL_INCOMING_STREAM_MULTIPLEXER_HPP
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2017 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#ifndef CAF_DETAIL_STREAM_SERV_DOWNSTREAM_HPP
#define CAF_DETAIL_STREAM_SERV_DOWNSTREAM_HPP
#include <deque>
#include <cstdint>
#include <algorithm>
#include <unordered_map>
#include "caf/actor.hpp"
#include "caf/error.hpp"
#include "caf/stream_msg.hpp"
#include "caf/local_actor.hpp"
#include "caf/detail/stream_multiplexer.hpp"
namespace caf {
namespace detail {
// Forwards messages from local actors to a remote stream_serv.
class outgoing_stream_multiplexer : public stream_multiplexer {
public:
/// Allow `variant` to recognize this type as a visitor.
using result_type = void;
outgoing_stream_multiplexer(local_actor* self, backend& service);
void operator()(stream_msg& x);
/// @pre `self_->current_sender() != nullptr && current_stream_state_valid()`
void operator()(stream_msg::open&);
/// @pre `self_->current_sender() != nullptr && current_stream_state_valid()`
void operator()(stream_msg::ack_open&);
/// @pre `self_->current_sender() != nullptr && current_stream_state_valid()`
void operator()(stream_msg::batch&);
/// @pre `self_->current_sender() != nullptr && current_stream_state_valid()`
void operator()(stream_msg::ack_batch&);
/// @pre `self_->current_sender() != nullptr && current_stream_state_valid()`
void operator()(stream_msg::close&);
/// @pre `self_->current_sender() != nullptr && current_stream_state_valid()`
void operator()(stream_msg::abort&);
/// @pre `self_->current_sender() != nullptr && current_stream_state_valid()`
void operator()(stream_msg::downstream_failed&);
/// @pre `self_->current_sender() != nullptr && current_stream_state_valid()`
void operator()(stream_msg::upstream_failed&);
private:
// Forwards the current stream_msg upstream.
// @pre `current_stream_msg != nullptr`
void forward_to_upstream();
// Forwards the current stream_msg downstream.
// @pre `current_stream_msg != nullptr`
void forward_to_downstream();
};
} // namespace detail
} // namespace caf
#endif // CAF_DETAIL_STREAM_SERV_DOWNSTREAM_HPP
This diff is collapsed.
...@@ -32,7 +32,7 @@ class forwarding_actor_proxy : public actor_proxy { ...@@ -32,7 +32,7 @@ class forwarding_actor_proxy : public actor_proxy {
public: public:
using forwarding_stack = std::vector<strong_actor_ptr>; using forwarding_stack = std::vector<strong_actor_ptr>;
forwarding_actor_proxy(actor_config& cfg, actor dest, actor stream_serv1); forwarding_actor_proxy(actor_config& cfg, actor dest);
~forwarding_actor_proxy() override; ~forwarding_actor_proxy() override;
...@@ -50,7 +50,6 @@ private: ...@@ -50,7 +50,6 @@ private:
mutable detail::shared_spinlock mtx_; mutable detail::shared_spinlock mtx_;
actor broker_; actor broker_;
actor stream_serv_;
}; };
} // namespace caf } // namespace caf
......
...@@ -438,9 +438,4 @@ actor_system::dyn_spawn_impl(const std::string& name, message& args, ...@@ -438,9 +438,4 @@ actor_system::dyn_spawn_impl(const std::string& name, message& args,
return std::move(res.first); return std::move(res.first);
} }
void actor_system::stream_serv(strong_actor_ptr x) {
internal_actors_[internal_actor_id(atom("StreamServ"))] = std::move(x);
registry_.put(atom("StreamServ"), stream_serv());
}
} // namespace caf } // namespace caf
...@@ -29,11 +29,9 @@ ...@@ -29,11 +29,9 @@
namespace caf { namespace caf {
forwarding_actor_proxy::forwarding_actor_proxy(actor_config& cfg, actor dest, forwarding_actor_proxy::forwarding_actor_proxy(actor_config& cfg, actor dest)
actor stream_serv)
: actor_proxy(cfg), : actor_proxy(cfg),
broker_(std::move(dest)), broker_(std::move(dest)) {
stream_serv_(std::move(stream_serv)) {
// nop // nop
} }
...@@ -85,11 +83,10 @@ bool forwarding_actor_proxy::remove_backlink(abstract_actor* x) { ...@@ -85,11 +83,10 @@ bool forwarding_actor_proxy::remove_backlink(abstract_actor* x) {
void forwarding_actor_proxy::kill_proxy(execution_unit* ctx, error rsn) { void forwarding_actor_proxy::kill_proxy(execution_unit* ctx, error rsn) {
CAF_ASSERT(ctx != nullptr); CAF_ASSERT(ctx != nullptr);
actor tmp[2]; actor tmp;
{ // lifetime scope of guard { // lifetime scope of guard
std::unique_lock<detail::shared_spinlock> guard(mtx_); std::unique_lock<detail::shared_spinlock> guard(mtx_);
broker_.swap(tmp[0]); // manually break cycle broker_.swap(tmp); // manually break cycle
stream_serv_.swap(tmp[1]); // manually break cycle
} }
cleanup(std::move(rsn), ctx); cleanup(std::move(rsn), ctx);
} }
......
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2017 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#include "caf/detail/incoming_stream_multiplexer.hpp"
#include "caf/send.hpp"
#include "caf/variant.hpp"
#include "caf/to_string.hpp"
#include "caf/local_actor.hpp"
namespace caf {
namespace detail {
incoming_stream_multiplexer::incoming_stream_multiplexer(local_actor* self,
backend& service)
: stream_multiplexer(self, service) {
// nop
}
void incoming_stream_multiplexer::operator()(stream_msg& x) {
CAF_LOG_TRACE(CAF_ARG(x));
CAF_ASSERT(self_->current_mailbox_element() != nullptr);
dispatch(*this, x);
}
void incoming_stream_multiplexer::operator()(stream_msg::open& x) {
CAF_LOG_TRACE(CAF_ARG(x));
CAF_ASSERT(current_stream_msg_ != nullptr);
auto prev = std::move(x.prev_stage);
// Make sure we have a previous stage.
if (!prev) {
CAF_LOG_WARNING("received stream_msg::open without previous stage");
return fail(sec::invalid_upstream, nullptr);
}
// Make sure we have a next stage.
auto cme = self_->current_mailbox_element();
if (!cme || cme->stages.empty()) {
CAF_LOG_WARNING("received stream_msg::open without next stage");
return fail(sec::invalid_downstream, std::move(prev));
}
auto successor = cme->stages.back();
cme->stages.pop_back();
// Our prev always is the remote stream server proxy.
auto current_remote_path = remotes().emplace(prev->node(), prev).first;
current_stream_state_ = add_stream(std::move(prev), successor,
&current_remote_path->second);
// Rewrite handshake and forward it to the next stage.
x.prev_stage = self_->ctrl();
auto ptr = make_mailbox_element(
cme->sender, cme->mid, std::move(cme->stages),
make<stream_msg::open>(current_stream_msg_->sid, std::move(x.msg),
self_->ctrl(), x.original_stage, x.priority,
x.redeployable));
successor->enqueue(std::move(ptr), self_->context());
// Send out demand upstream.
manage_credit();
}
void incoming_stream_multiplexer::operator()(stream_msg::ack_open&) {
CAF_ASSERT(current_stream_msg_ != nullptr);
CAF_ASSERT(current_stream_state_valid());
forward_to_upstream();
}
void incoming_stream_multiplexer::operator()(stream_msg::batch&) {
CAF_ASSERT(current_stream_msg_ != nullptr);
CAF_ASSERT(current_stream_state_valid());
forward_to_downstream();
}
void incoming_stream_multiplexer::operator()(stream_msg::ack_batch&) {
CAF_ASSERT(current_stream_msg_ != nullptr);
CAF_ASSERT(current_stream_state_valid());
forward_to_upstream();
}
void incoming_stream_multiplexer::operator()(stream_msg::close&) {
CAF_ASSERT(current_stream_msg_ != nullptr);
CAF_ASSERT(current_stream_state_valid());
forward_to_downstream();
remove_current_stream();
}
void incoming_stream_multiplexer::operator()(stream_msg::abort& x) {
CAF_ASSERT(current_stream_msg_ != nullptr);
CAF_ASSERT(current_stream_state_valid());
if (current_stream_state_->second.prev_stage == self_->current_sender())
fail(x.reason, nullptr, current_stream_state_->second.next_stage);
else
fail(x.reason, current_stream_state_->second.prev_stage);
remove_current_stream();
}
void incoming_stream_multiplexer::operator()(stream_msg::downstream_failed&) {
CAF_ASSERT(current_stream_msg_ != nullptr);
CAF_ASSERT(current_stream_state_valid());
// TODO: implement me
}
void incoming_stream_multiplexer::operator()(stream_msg::upstream_failed&) {
CAF_ASSERT(current_stream_msg_ != nullptr);
CAF_ASSERT(current_stream_state_valid());
// TODO: implement me
}
void incoming_stream_multiplexer::forward_to_upstream() {
CAF_ASSERT(current_stream_msg_ != nullptr);
CAF_ASSERT(current_stream_state_valid());
send_remote(*current_stream_state_->second.rpath,
std::move(*current_stream_msg_));
}
void incoming_stream_multiplexer::forward_to_downstream() {
CAF_ASSERT(current_stream_msg_ != nullptr);
// When forwarding downstream, we also have to manage upstream credit.
manage_credit();
send_local(current_stream_state_->second.next_stage,
std::move(*current_stream_msg_));
}
} // namespace detail
} // namespace caf
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2017 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#include "caf/detail/outgoing_stream_multiplexer.hpp"
#include "caf/send.hpp"
#include "caf/variant.hpp"
#include "caf/to_string.hpp"
#include "caf/local_actor.hpp"
namespace caf {
namespace detail {
outgoing_stream_multiplexer::outgoing_stream_multiplexer(local_actor* self,
backend& service)
: stream_multiplexer(self, service) {
// nop
}
void outgoing_stream_multiplexer::operator()(stream_msg& x) {
CAF_LOG_TRACE(CAF_ARG(x));
CAF_ASSERT(self_->current_mailbox_element() != nullptr);
dispatch(*this, x);
}
void outgoing_stream_multiplexer::operator()(stream_msg::open& x) {
CAF_LOG_TRACE(CAF_ARG(x));
CAF_ASSERT(current_stream_msg_ != nullptr);
auto predecessor = std::move(x.prev_stage);
// Make sure we a previous stage.
if (!predecessor) {
CAF_LOG_WARNING("received stream_msg::open without previous stage");
return fail(sec::invalid_upstream, nullptr);
}
// Make sure we don't receive a handshake for an already open stream.
if (has_stream(current_stream_msg_->sid)) {
CAF_LOG_WARNING("received stream_msg::open twice");
return fail(sec::upstream_already_exists, std::move(predecessor));
}
// Make sure we have a next stage.
auto cme = self_->current_mailbox_element();
if (cme->stages.empty()) {
CAF_LOG_WARNING("received stream_msg::open without next stage");
return fail(sec::invalid_downstream, std::move(predecessor));
}
auto successor = cme->stages.back();
// Get a connection to the responsible stream server.
auto path = get_remote_or_try_connect(successor->node());
if (!path) {
CAF_LOG_WARNING("cannot connect to remote stream server");
return fail(sec::cannot_connect_to_node, std::move(predecessor));
}
// Update state and send handshake to remote stream_serv (via
// middleman/basp_broker).
add_stream(std::move(predecessor), path->hdl, &(*path));
// Send handshake to remote stream_serv (via middleman/basp_broker). We need
// to send this message as `current_sender`. We have do bypass the queue
// since `send_remote` always sends the message from `self_`.
auto ptr = make_mailbox_element(
cme->sender, message_id::make(), {}, forward_atom::value, cme->sender,
std::move(cme->stages), path->hdl, cme->mid,
make_message(make<stream_msg::open>(
current_stream_msg_->sid, std::move(x.msg), self_->ctrl(),
x.original_stage, x.priority, x.redeployable)));
basp()->enqueue(std::move(ptr), self_->context());
}
void outgoing_stream_multiplexer::operator()(stream_msg::ack_open&) {
CAF_ASSERT(current_stream_msg_ != nullptr);
CAF_ASSERT(current_stream_state_valid());
forward_to_upstream();
}
void outgoing_stream_multiplexer::operator()(stream_msg::batch&) {
CAF_ASSERT(current_stream_msg_ != nullptr);
CAF_ASSERT(current_stream_state_valid());
forward_to_downstream();
}
void outgoing_stream_multiplexer::operator()(stream_msg::ack_batch&) {
CAF_ASSERT(current_stream_msg_ != nullptr);
CAF_ASSERT(current_stream_state_valid());
forward_to_upstream();
}
void outgoing_stream_multiplexer::operator()(stream_msg::close&) {
CAF_ASSERT(current_stream_msg_ != nullptr);
CAF_ASSERT(current_stream_state_valid());
forward_to_downstream();
remove_current_stream();
}
void outgoing_stream_multiplexer::operator()(stream_msg::abort& x) {
CAF_ASSERT(current_stream_msg_ != nullptr);
CAF_ASSERT(current_stream_state_valid());
if (current_stream_state_->second.prev_stage == self_->current_sender())
fail(x.reason, nullptr, current_stream_state_->second.next_stage);
else
fail(x.reason, current_stream_state_->second.prev_stage);
remove_current_stream();
}
void outgoing_stream_multiplexer::operator()(stream_msg::downstream_failed&) {
CAF_ASSERT(current_stream_msg_ != nullptr);
CAF_ASSERT(current_stream_state_valid());
// TODO: implement me
}
void outgoing_stream_multiplexer::operator()(stream_msg::upstream_failed&) {
CAF_ASSERT(current_stream_msg_ != nullptr);
CAF_ASSERT(current_stream_state_valid());
// TODO: implement me
}
void outgoing_stream_multiplexer::forward_to_upstream() {
CAF_ASSERT(current_stream_msg_ != nullptr);
CAF_ASSERT(current_stream_state_valid());
manage_credit();
send_local(current_stream_state_->second.prev_stage,
std::move(*current_stream_msg_));
}
void outgoing_stream_multiplexer::forward_to_downstream() {
CAF_ASSERT(current_stream_msg_ != nullptr);
CAF_ASSERT(current_stream_state_valid());
send_remote(*current_stream_state_->second.rpath,
std::move(*current_stream_msg_));
}
} // namespace detail
} // namespace caf
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2017 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#include "caf/detail/stream_multiplexer.hpp"
#include "caf/send.hpp"
#include "caf/variant.hpp"
#include "caf/to_string.hpp"
#include "caf/local_actor.hpp"
#include "caf/stream_aborter.hpp"
namespace caf {
namespace detail {
stream_multiplexer::backend::backend(actor basp_ref) : basp_(basp_ref) {
// nop
}
stream_multiplexer::backend::~backend() {
// nop
}
void stream_multiplexer::backend::add_credit(const node_id& nid, int32_t x) {
auto i = remotes().find(nid);
if (i != remotes().end()) {
auto& path = i->second;
path.credit += x;
drain_buf(path);
}
}
void stream_multiplexer::backend::drain_buf(remote_path& path) {
CAF_LOG_TRACE(CAF_ARG(path));
auto n = std::min(path.credit, static_cast<int32_t>(path.buf.size()));
if (n > 0) {
auto b = path.buf.begin();
auto e = b + n;
for (auto i = b; i != e; ++i)
basp()->enqueue(std::move(*i), nullptr);
path.buf.erase(b, e);
path.credit -= static_cast<int32_t>(n);
}
}
stream_multiplexer::stream_multiplexer(local_actor* self, backend& service)
: self_(self),
service_(service) {
CAF_ASSERT(self_ != nullptr);
}
stream_multiplexer::stream_states::iterator
stream_multiplexer::add_stream(strong_actor_ptr prev, strong_actor_ptr next,
remote_path* path) {
CAF_LOG_TRACE(CAF_ARG(prev) << CAF_ARG(next) << CAF_ARG(path));
auto sid = current_stream_msg_->sid;
auto x = streams_.emplace(sid, stream_state{prev, next, path});
if (x.second) {
stream_aborter::add(prev, self_->address(), sid);
stream_aborter::add(next, self_->address(), sid);
}
return x.first;
}
void stream_multiplexer::remove_current_stream() {
auto& sid = current_stream_state_->first;
auto& st = current_stream_state_->second;
stream_aborter::del(st.prev_stage, self_->address(), sid);
stream_aborter::del(st.next_stage, self_->address(), sid);
streams_.erase(current_stream_state_);
}
optional<stream_multiplexer::remote_path&>
stream_multiplexer::get_remote_or_try_connect(const node_id& nid) {
auto i = remotes().find(nid);
if (i != remotes().end())
return i->second;
auto res = service_.remote_stream_serv(nid);
if (res)
return remotes().emplace(nid, std::move(res)).first->second;
return none;
}
optional<stream_multiplexer::stream_state&>
stream_multiplexer::state_for(const stream_id& sid) {
auto i = streams_.find(sid);
if (i != streams_.end())
return i->second;
return none;
}
void stream_multiplexer::manage_credit() {
auto& path = *current_stream_state_->second.rpath;
// todo: actual, adaptive credit management
if (--path.in_flight == 0) {
int32_t new_remote_credit = 5;
path.in_flight += new_remote_credit;
send_remote_ctrl(
path, make_message(sys_atom::value, ok_atom::value, new_remote_credit));
}
}
void stream_multiplexer::fail(error reason, strong_actor_ptr predecessor,
strong_actor_ptr successor) {
CAF_ASSERT(current_stream_msg_ != nullptr);
if (predecessor)
unsafe_send_as(self_, predecessor,
make<stream_msg::abort>(current_stream_msg_->sid, reason));
if (successor)
unsafe_send_as(self_, successor,
make<stream_msg::abort>(current_stream_msg_->sid, reason));
auto rp = self_->make_response_promise();
if (!rp.async())
rp.deliver(std::move(reason));
}
void stream_multiplexer::fail(error reason) {
CAF_ASSERT(current_stream_msg_ != nullptr);
auto i = streams_.find(current_stream_msg_->sid);
if (i != streams_.end()) {
fail(std::move(reason), std::move(i->second.prev_stage),
std::move(i->second.next_stage));
streams_.erase(i);
} else {
fail(std::move(reason), nullptr, nullptr);
}
}
void stream_multiplexer::send_local(strong_actor_ptr& dest, stream_msg&& x,
std::vector<strong_actor_ptr> stages,
message_id mid) {
CAF_ASSERT(dest != nullptr);
dest->enqueue(make_mailbox_element(self_->ctrl(), mid, std::move(stages),
std::move(x)),
self_->context());
}
} // namespace detail
} // namespace caf
This diff is collapsed.
This diff is collapsed.
...@@ -88,8 +88,7 @@ strong_actor_ptr basp_broker_state::make_proxy(node_id nid, actor_id aid) { ...@@ -88,8 +88,7 @@ strong_actor_ptr basp_broker_state::make_proxy(node_id nid, actor_id aid) {
auto mm = &system().middleman(); auto mm = &system().middleman();
actor_config cfg; actor_config cfg;
auto res = make_actor<forwarding_actor_proxy, strong_actor_ptr>( auto res = make_actor<forwarding_actor_proxy, strong_actor_ptr>(
aid, nid, &(self->home_system()), cfg, self, aid, nid, &(self->home_system()), cfg, self);
actor_cast<actor>(self->home_system().stream_serv()));
strong_actor_ptr selfptr{self->ctrl()}; strong_actor_ptr selfptr{self->ctrl()};
res->get()->attach_functor([=](const error& rsn) { res->get()->attach_functor([=](const error& rsn) {
mm->backend().post([=] { mm->backend().post([=] {
......
...@@ -56,8 +56,6 @@ ...@@ -56,8 +56,6 @@
#include "caf/detail/safe_equal.hpp" #include "caf/detail/safe_equal.hpp"
#include "caf/detail/get_root_uuid.hpp" #include "caf/detail/get_root_uuid.hpp"
#include "caf/detail/get_mac_addresses.hpp" #include "caf/detail/get_mac_addresses.hpp"
#include "caf/detail/incoming_stream_multiplexer.hpp"
#include "caf/detail/outgoing_stream_multiplexer.hpp"
#ifdef CAF_USE_ASIO #ifdef CAF_USE_ASIO
#include "caf/io/network/asio_multiplexer.hpp" #include "caf/io/network/asio_multiplexer.hpp"
...@@ -273,106 +271,10 @@ void middleman::start() { ...@@ -273,106 +271,10 @@ void middleman::start() {
}}; }};
backend().thread_id(thread_.get_id()); backend().thread_id(thread_.get_id());
} }
// Default implementation of the stream server.
class stream_serv : public raw_event_based_actor,
public detail::stream_multiplexer::backend {
public:
stream_serv(actor_config& cfg, actor basp_ref)
: raw_event_based_actor(cfg),
detail::stream_multiplexer::backend(std::move(basp_ref)),
incoming_(this, *this),
outgoing_(this, *this) {
// nop
}
const char* name() const override {
return "stream_serv";
}
behavior make_behavior() override {
return {
[=](stream_msg& x) -> delegated<message> {
CAF_LOG_TRACE(CAF_ARG(x));
// Dispatching depends on the direction of the message.
if (outgoing_.has_stream(x.sid)) {
outgoing_(x);
} else {
incoming_(x);
}
return {};
},
[=](sys_atom, stream_msg& x) -> delegated<message> {
CAF_LOG_TRACE(CAF_ARG(x));
// Stream message received from a proxy
outgoing_(x);
return {};
},
[=](sys_atom, ok_atom, int32_t credit) {
CAF_LOG_TRACE(CAF_ARG(credit));
CAF_ASSERT(current_mailbox_element() != nullptr);
auto cme = current_mailbox_element();
if (cme->sender != nullptr) {
auto& nid = cme->sender->node();
add_credit(nid, credit);
} else {
CAF_LOG_ERROR("Received credit from an anonmyous stream server.");
}
},
[=](exit_msg& x) {
CAF_LOG_TRACE(CAF_ARG(x));
if (x.reason)
quit(x.reason);
},
// Connects both incoming_ and outgoing_ to nid.
[=](connect_atom, const node_id& nid) {
CAF_LOG_TRACE(CAF_ARG(nid));
send(basp_, forward_atom::value, nid, atom("ConfigServ"),
make_message(get_atom::value, atom("StreamServ")));
},
// Assumes `ptr` is a remote spawn server.
[=](strong_actor_ptr& ptr) {
CAF_LOG_TRACE(CAF_ARG(ptr));
if (ptr) {
add_remote_path(ptr->node(), ptr);
}
}
};
}
strong_actor_ptr remote_stream_serv(const node_id& nid) override {
CAF_LOG_TRACE(CAF_ARG(nid));
strong_actor_ptr result;
// Ask remote config server for a handle to the remote spawn server.
scoped_actor self{system()};
self->send(basp_, forward_atom::value, nid, atom("ConfigServ"),
make_message(get_atom::value, atom("StreamServ")));
// Time out after 5 minutes.
self->receive(
[&](strong_actor_ptr& addr) {
result = std::move(addr);
},
after(std::chrono::minutes(5)) >> [] {
CAF_LOG_INFO("Accessing a remote spawn server timed out.");
}
);
return result;
}
void on_exit() override {
// Make sure to not keep references to remotes after shutdown.
remotes().clear();
}
private:
detail::incoming_stream_multiplexer incoming_;
detail::outgoing_stream_multiplexer outgoing_;
};
// Spawn utility actors. // Spawn utility actors.
auto basp = named_broker<basp_broker>(atom("BASP")); auto basp = named_broker<basp_broker>(atom("BASP"));
manager_ = make_middleman_actor(system(), basp); manager_ = make_middleman_actor(system(), basp);
auto hdl = actor_cast<actor>(basp); auto hdl = actor_cast<actor>(basp);
auto ssi = system().spawn<stream_serv, lazy_init + hidden>(std::move(hdl));
system().stream_serv(actor_cast<strong_actor_ptr>(std::move(ssi)));
} }
void middleman::stop() { void middleman::stop() {
......
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2017 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#include <string>
#include <numeric>
#include <fstream>
#include <iostream>
#include <iterator>
#define CAF_SUITE io_remote_streams
#include "caf/test/io_dsl.hpp"
#include "caf/io/middleman.hpp"
#include "caf/io/basp_broker.hpp"
#include "caf/io/network/test_multiplexer.hpp"
using std::cout;
using std::endl;
using std::string;
using namespace caf;
using namespace caf::io;
namespace {
class remoting_config : public actor_system_config {
public:
remoting_config() {
load<middleman, network::test_multiplexer>();
add_message_type<stream<int>>("stream<int>");
add_message_type<std::vector<int>>("vector<int>");
middleman_detach_utility_actors = false;
}
};
using sub_fixture = test_node_fixture_t<remoting_config>;
} // namespace <anonymous>
struct dsl_path_info {
sub_fixture& host;
actor receiver;
dsl_path_info(sub_fixture& x, actor y)
: host(x), receiver(std::move(y)) {
// nop
}
dsl_path_info(sub_fixture& x, strong_actor_ptr y)
: host(x), receiver(actor_cast<actor>(std::move(y))) {
// nop
}
};
#define expect_on_path(types, fields, ...) \
CAF_MESSAGE(">>> " << #types << " on path " << #__VA_ARGS__); \
{ \
std::vector<dsl_path_info> path{{__VA_ARGS__}}; \
for (auto x : path) { \
network_traffic(); \
expect_on(x.host, types, from(_).to(x.receiver).fields); \
} \
} \
CAF_MESSAGE("<<< path done")
CAF_TEST_FIXTURE_SCOPE(netstreams, point_to_point_fixture_t<remoting_config>)
CAF_TEST(stream_crossing_the_wire) {
// TODO: stream servers are currently disabled, because they break many
// possible setups by hiding remote actor handles. They must be
// re-implemented in a transparent fashion.
CAF_CHECK(true);
}
/*
CAF_TEST(stream_crossing_the_wire) {
CAF_MESSAGE("earth stream serv: " << to_string(earth.stream_serv));
CAF_MESSAGE("mars stream serv: " << to_string(mars.stream_serv));
// Connect the buffers of mars and earth to setup a pseudo-network.
mars.peer = &earth;
earth.peer = &mars;
// Setup: earth (streamer_without_result) streams to mars (drop_all).
CAF_MESSAGE("spawn drop_all sink on mars");
auto sink = mars.sys.spawn(drop_all);
// This test uses two fixtures for keeping state.
earth.conn = connection_handle::from_int(1);
mars.conn = connection_handle::from_int(2);
mars.acc = accept_handle::from_int(3);
// Run any initialization code.
exec_all();
// Prepare publish and remote_actor calls.
CAF_MESSAGE("prepare connections on earth and mars");
prepare_connection(mars, earth, "mars", 8080u);
// Publish sink on mars.
CAF_MESSAGE("publish sink on mars");
mars.publish(sink, 8080);
// Get a proxy on earth.
CAF_MESSAGE("connect from earth to mars");
auto proxy = earth.remote_actor("mars", 8080);
CAF_MESSAGE("got proxy: " << to_string(proxy) << ", spawn streamer on earth");
CAF_MESSAGE("establish remote stream paths");
// Establish remote paths between the two stream servers. This step is
// necessary to prevent a deadlock in `stream_serv::remote_stream_serv` due
// to blocking communication with the BASP broker.
anon_send(actor_cast<actor>(earth.stream_serv), connect_atom::value,
mars.stream_serv->node());
anon_send(actor_cast<actor>(mars.stream_serv), connect_atom::value,
earth.stream_serv->node());
exec_all();
CAF_MESSAGE("start streaming");
// Start streaming.
auto source = earth.sys.spawn(streamer_without_result, proxy);
earth.sched.run_once();
// source ----('sys', stream_msg::open)----> earth.stream_serv
expect_on(earth, (atom_value, stream_msg),
from(source).to(earth.stream_serv).with(sys_atom::value, _));
// --------------(stream_msg::open)-------------->
// earth.stream_serv -> mars.stream_serv -> sink
expect_on_path(
(stream_msg::open), with(_, _, _, _, _, false),
{mars, mars.stream_serv}, {mars, sink});
// mars.stream_serv --('sys', 'ok', 5)--> earth.stream_serv
network_traffic();
expect_on(earth, (atom_value, atom_value, int32_t),
from(_).to(earth.stream_serv)
.with(sys_atom::value, ok_atom::value, 5));
// -----------------(stream_msg::ack_open)------------------>
// sink -> mars.stream_serv -> earth.stream_serv -> source
expect_on_path(
(stream_msg::ack_open), with(_, 5, _, false),
{mars, mars.stream_serv}, {earth, earth.stream_serv}, {earth, source});
// earth.stream_serv --('sys', 'ok', 5)--> mars.stream_serv
network_traffic();
expect_on(mars, (atom_value, atom_value, int32_t),
from(_).to(mars.stream_serv)
.with(sys_atom::value, ok_atom::value, 5));
// -------------------(stream_msg::batch)------------------->
// source -> earth.stream_serv -> mars.stream_serv -> sink
expect_on_path(
(stream_msg::batch), with(5, std::vector<int>{1, 2, 3, 4, 5}, 0),
{earth, earth.stream_serv},
{mars, mars.stream_serv}, {mars, sink});
// -----------------(stream_msg::ack_batch)------------------>
// sink -> mars.stream_serv -> earth.stream_serv -> source
expect_on_path(
(stream_msg::ack_batch), with(5, 0),
{mars, mars.stream_serv}, {earth, earth.stream_serv}, {earth, source});
// -------------------(stream_msg::batch)------------------->
// source -> earth.stream_serv -> mars.stream_serv -> sink
expect_on_path(
(stream_msg::batch), with(4, std::vector<int>{6, 7, 8, 9}, 1),
{earth, earth.stream_serv},
{mars, mars.stream_serv}, {mars, sink});
// -----------------(stream_msg::ack_batch)------------------>
// sink -> mars.stream_serv -> earth.stream_serv -> source
expect_on_path(
(stream_msg::ack_batch), with(4, 1),
{mars, mars.stream_serv}, {earth, earth.stream_serv}, {earth, source});
// -------------------(stream_msg::close)------------------->
// source -> earth.stream_serv -> mars.stream_serv -> sink
expect_on_path(
(stream_msg::close), with(),
{earth, earth.stream_serv},
{mars, mars.stream_serv}, {mars, sink});
// sink ----(result: <empty>)---> source
network_traffic();
expect_on(earth, (void), from(proxy).to(source).with());
// sink --(void)--> source
anon_send_exit(sink, exit_reason::user_shutdown);
mars.sched.run();
anon_send_exit(source, exit_reason::user_shutdown);
earth.sched.run();
}
*/
CAF_TEST_FIXTURE_SCOPE_END()
...@@ -36,13 +36,11 @@ public: ...@@ -36,13 +36,11 @@ public:
caf::io::connection_handle conn; caf::io::connection_handle conn;
caf::io::accept_handle acc; caf::io::accept_handle acc;
test_node_fixture* peer = nullptr; test_node_fixture* peer = nullptr;
caf::strong_actor_ptr stream_serv;
test_node_fixture() test_node_fixture()
: mm(this->sys.middleman()), : mm(this->sys.middleman()),
mpx(dynamic_cast<caf::io::network::test_multiplexer&>(mm.backend())), mpx(dynamic_cast<caf::io::network::test_multiplexer&>(mm.backend())),
basp(get_basp_broker()), basp(get_basp_broker()) {
stream_serv(this->sys.stream_serv()) {
// nop // nop
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment