hmbdc
simplify-high-performance-messaging-programming
RecvTransportEngine.hpp
1 #include "hmbdc/Copyright.hpp"
2 #pragma once
3 #include "hmbdc/tips/tcpcast/Transport.hpp"
4 #include "hmbdc/tips/tcpcast/RecvSession.hpp"
5 #include "hmbdc/tips/tcpcast/Messages.hpp"
6 #include "hmbdc/tips/tcpcast/DefaultUserConfig.hpp"
7 #include "hmbdc/tips/udpcast/RecvTransportEngine.hpp"
8 #include "hmbdc/app/Logger.hpp"
9 
10 #include <boost/bind.hpp>
11 #include <boost/lexical_cast.hpp>
12 #include <boost/unordered_map.hpp>
13 #include <mutex>
14 #include <regex>
15 
16 #include <memory>
17 
18 namespace hmbdc { namespace tips { namespace tcpcast {
19 
20 /**
21  * @brief interface to power a tcpcast transport receiving functions
22  */
24 : Transport {
25  using Transport::Transport;
26  virtual ~RecvTransport(){}
27 };
28 
29 namespace recvtransportengine_detail {
30 template <typename OutputBuffer, typename AttachmentAllocator>
35 , hmbdc::app::Client<RecvTransportEngine<OutputBuffer, AttachmentAllocator>> {
37 
38 /**
39  * @brief ctor
40  * @details io_service could be passed in by user, in this case NO more than two threads should
41  * power this io_service instance since that would violate the thread garantee of Client, which
42  * is no callbacks are called in parallel
43  *
44  * @param cfg specify the details of the tcpcast transport
45  * @param outputBuffer holding the results
46  */
48  , OutputBuffer& outputBuffer)
49  : RecvTransport(((cfg.setAdditionalFallbackConfig(hmbdc::app::Config(DefaultUserConfig))
50  , cfg.resetSection("rx", false))))
51  , hmbdc::time::ReoccuringTimer(hmbdc::time::Duration::seconds(cfg.getExt<size_t>("heartbeatPeriodSeconds")))
52  , config_(cfg)
53  , mcConfig_(config_)
54  , buffer_(std::max({sizeof(app::MessageWrap<TypeTagSource>)})
55  , config_.getExt<uint16_t>("cmdBufferSizePower2"))
56  , outputBuffer_(outputBuffer)
57  , maxItemSize_(outputBuffer.maxItemSize())
58  , myIp_(inet_addr(hmbdc::comm::inet::getLocalIpMatchMask(
59  config_.getExt<std::string>("ifaceAddr")).c_str())) {
60  if (!config_.getExt<bool>("allowRecvWithinProcess")) {
61  myPid_ = getpid();
62  }
63  if (outputBuffer.maxItemSize() < sizeof(SessionStarted)
64  || outputBuffer.maxItemSize() < sizeof(SessionDropped)) {
65  HMBDC_THROW(std::out_of_range
66  , "buffer is too small for notification: SessionStarted and SessionDropped");
67  }
68  mcConfig_.put("outBufferSizePower2", 3u);
69  mcReceiver_.emplace(mcConfig_, buffer_);
70  mcReceiver_->template subscribe<TypeTagSource>();
71 
72  setCallback(
73  [this](hmbdc::time::TimerManager& tm, hmbdc::time::SysTime const& now) {
74  for (auto& s : recvSessions_) {
75  s.second->heartbeat();
76  }
77  }
78  );
79 
80  schedule(hmbdc::time::SysTime::now(), *this);
81  }
82 
83  void rotate() {
84  this->checkTimers(hmbdc::time::SysTime::now());
86  }
87 
88  using Transport::hmbdcName;
89  using Transport::schedSpec;
90 
91 /**
92  * @brief should not htipsen ever unless an exception thrown
93  *
94  * @param e exception thown
95  */
96  /*virtual*/
97  void stoppedCb(std::exception const& e) override {
98  HMBDC_LOG_C(e.what());
99  };
100 
101 /**
102  * @brief power the io_service and other things
103  *
104  */
105  /*virtual*/
106  void invokedCb(size_t) HMBDC_RESTRICT override {
107  for (auto it = recvSessions_.begin(); it != recvSessions_.end();) {
108  if (hmbdc_unlikely(!(*it).second->runOnce())) {
109  (*it).second->stop();
110  recvSessions_.erase(it++);
111  } else {
112  it++;
113  }
114  }
116  auto n = buffer_.peek(begin, end);
117  auto it = begin;
118  while (it != end) {
119  MD()(*this, *static_cast<app::MessageHead*>(*it++));
120  }
121  buffer_.wasteAfterPeek(begin, n);
122 
123  mcReceiver_->runOnce(true);
124  }
125 
126  /**
127  * @brief check how many other parties are sending to this engine
128  * @return recipient session count are still active
129  */
130  size_t sessionsRemainingActive() const {
131  return recvSessions_.size();
132  }
133 
134  template <MessageTupleC Messages, typename CcNode>
135  void subscribeFor(CcNode const& node, uint16_t mod, uint16_t res) {
136  subscriptions_.markSubsFor<Messages>(node, mod, res);
137  }
138 
139 /**
140  * @brief only used by MD
141  */
143  auto ip = inet_addr(t.ip);
144  if (ip == myIp_
145  && !t.loopback) {
146  return;
147  }
148 
149  if (t.srcPid == myPid_ && ip == myIp_) return;
150  auto key = std::make_pair(ip, t.port);
151  if (recvSessions_.find(key) == recvSessions_.end()) {
152  for (auto i = 0u; i < t.typeTagCountContained; ++i) {
153  if (subscriptions_.check(t.typeTags[i])) {
154  try {
155  auto sess = new Session(
156  config_
157  , subscriptions_
158  , outputBuffer_
159  );
160  sess->start(ip, t.port);
161  recvSessions_[key] = typename Session::ptr(sess);
162  } catch (std::exception const& e) {
163  HMBDC_LOG_C(e.what());
164  }
165  break;
166  }
167  }
168  } //else ignore
169  }
170 
171 private:
173 
174  hmbdc::app::Config config_, mcConfig_;
176  OutputBuffer& outputBuffer_;
177  size_t maxItemSize_;
178  std::optional<udpcast::RecvTransportImpl<decltype(buffer_)>> mcReceiver_;
179 
180  TypeTagSet subscriptions_;
181  boost::unordered_map<std::pair<uint64_t, uint16_t>
182  , typename Session::ptr> recvSessions_;
183  uint32_t myIp_;
184  uint32_t myPid_ = 0;
185 };
186 
187 } //recvtransportengine_detail
188 template <typename OutputBuffer, typename AttachmentAllocator>
189 using RecvTransportEngine = recvtransportengine_detail::RecvTransportEngine<OutputBuffer, AttachmentAllocator>;
190 }}}
T getExt(const path_type &param, bool throwIfMissing=true) const
get a value from the config
Definition: Config.hpp:238
Definition: MonoLockFreeBuffer.hpp:16
interface to power a tcpcast transport receiving functions
Definition: RecvTransportEngine.hpp:23
class to hold an hmbdc configuration
Definition: Config.hpp:44
void invokedCb(size_t) HMBDC_RESTRICT override
power the io_service and other things
Definition: RecvTransportEngine.hpp:106
Definition: TypedString.hpp:84
Definition: Timers.hpp:70
void handleMessageCb(TypeTagSource const &t)
only used by MD
Definition: RecvTransportEngine.hpp:142
Definition: Transport.hpp:65
this message tipsears in the receiver&#39;s buffer indicating a previously connected source is dropped ...
Definition: Messages.hpp:120
RecvTransportEngine(hmbdc::app::Config cfg, OutputBuffer &outputBuffer)
ctor
Definition: RecvTransportEngine.hpp:47
Definition: MessageDispacher.hpp:184
void stoppedCb(std::exception const &e) override
should not htipsen ever unless an exception thrown
Definition: RecvTransportEngine.hpp:97
Definition: Message.hpp:212
Definition: Messages.hpp:57
Definition: Time.hpp:14
void schedule(SysTime fireAt, Timer &timer)
schedule the timer to start at a specific time
Definition: Timers.hpp:79
Definition: TypeTagSet.hpp:138
Definition: Message.hpp:263
Config & put(Args &&... args)
forward the call to ptree&#39;s put but return Configure
Definition: Config.hpp:194
A Client represents a thread of execution/a task. The execution is managed by a Context. a Client object could participate in message dispatching as the receiver of specifed message types.
Definition: Client.hpp:128
Definition: Base.hpp:12
void wasteAfterPeek(iterator, size_t, bool=false)
if size not matching - please refer to the impl for details
Definition: MonoLockFreeBuffer.hpp:160
Definition: Timers.hpp:117
this message tipsears in the receiver&#39;s buffer indicating a new source is connected ...
Definition: Messages.hpp:106
size_t sessionsRemainingActive() const
check how many other parties are sending to this engine
Definition: RecvTransportEngine.hpp:130
Definition: LockFreeBufferMisc.hpp:89