hmbdc
simplify-high-performance-messaging-programming
RecvTransportEngine.hpp
1 #include "hmbdc/Copyright.hpp"
2 #pragma once
3 #include "hmbdc/tips/rmcast/Transport.hpp"
4 #include "hmbdc/tips/rmcast/McRecvTransport.hpp"
5 #include "hmbdc/tips/rmcast/BackupRecvSession.hpp"
6 #include "hmbdc/tips/rmcast/DefaultUserConfig.hpp"
7 #include "hmbdc/tips/reliable/AttBufferAdaptor.hpp"
8 #include "hmbdc/app/Logger.hpp"
9 #include "hmbdc/comm/inet/Hash.hpp"
10 
11 #include <boost/bind.hpp>
12 #include <boost/lexical_cast.hpp>
13 #include <boost/unordered_map.hpp>
14 
15 #include <memory>
16 #include <regex>
17 #include <type_traits>
18 #include <mutex>
19 
20 namespace hmbdc { namespace tips { namespace rmcast {
21 
22 /**
23  * @brief interface to power a multicast transport receiving functions
24  */
28  , cfg.resetSection("rx", false)))
29  {}
30 
31  virtual ~RecvTransport(){}
32 };
33 
34 namespace recvtransportengine_detail {
35 
36 /**
37  * @brief impl class
38  *
39  * @tparam OutputBuffer type of buffer to hold resulting network messages
40  * between different recv transport. By default, keeping all
41  */
42 template <typename OutputBuffer, typename AttachmentAllocator>
47 
48 /**
49  * @brief ctor
50  * @details io_service could be passed in by user, in this case NO more than two threads should
51  * power this io_service instance since that would violate the thread garantee of Client, which
52  * is no callbacks are called in parallel
53  *
54  * @param cfg specify the details of the rmcast transport
55  * @param outputBuffer holding the results
56  */
57  RecvTransportImpl(hmbdc::app::Config const& cfg, OutputBuffer& outputBuffer)
58  : RecvTransport(cfg)
59  , cmdBuffer_(std::max({sizeof(app::MessageWrap<TypeTagBackupSource>)})
60  , config_.getExt<uint16_t>("cmdBufferSizePower2"))
61  , outputBuffer_(outputBuffer)
62  , myBackupIp_(inet_addr(hmbdc::comm::inet::getLocalIpMatchMask(
63  config_.getExt<std::string>("tcpIfaceAddr") == std::string("ifaceAddr")
64  ?config_.getExt<std::string>("ifaceAddr"):config_.getExt<std::string>("tcpIfaceAddr")
65  ).c_str()))
66  , mcRecvTransport_(config_
67  , cmdBuffer_ //to store cmds
68  , subscriptions_
69  , ep2SessionDict_)
70  , loopback_(config_.getExt<bool>("loopback")) {
71  subscriptions_.addAll<std::tuple<app::StartMemorySegTrain, app::MemorySeg>>();
72  if (!config_.getExt<bool>("allowRecvWithinProcess")) {
73  myPid_ = getpid();
74  }
75  }
76 
77 
78 /**
79  * @brief start the show by schedule the mesage recv
80  */
81  void start() {
82  mcRecvTransport_.start();
83  }
84 
85  void runOnce() HMBDC_RESTRICT {
86  hmbdc::app::utils::EpollTask::instance().poll();
88  auto n = cmdBuffer_.peek(begin, end);
89  auto it = begin;
90  while (it != end) {
91  MD()(*this, *static_cast<hmbdc::app::MessageHead*>(*it++));
92  }
93  cmdBuffer_.wasteAfterPeek(begin, n);
94  mcRecvTransport_.runOnce();
95  for (auto it = recvSessions_.begin(); it != recvSessions_.end();) {
96  if (hmbdc_unlikely(!it->second->runOnce())) {
97  it->second->stop();
98  cancel(*it->second);
99  ep2SessionDict_.erase(it->second->sendFrom);
100  recvSessions_.erase(it++);
101  } else {
102  it++;
103  }
104  }
105  }
106 
107 /**
108  * @brief only used by MH
109  */
111  auto ip = inet_addr(t.ip);
112  //unless using loopback address, don't EVER listen to myself (own process)
113  if (ip == myBackupIp_
114  && (!loopback_)) {
115  return;
116  }
117  if (t.srcPid == myPid_ && ip == myBackupIp_) return;
118  auto key = std::make_pair(ip, t.port);
119  if (recvSessions_.find(key) == recvSessions_.end()) {
120  for (auto i = 0u; i < t.typeTagCountContained; ++i) {
121  if (subscriptions_.check(t.typeTags[i])) {
122  try {
123  typename Session::ptr sess {
124  new Session(
125  config_
126  , t.sendFrom
127  , subscriptions_
128  , outputBuffer_
129  , t.recvReportDelay
130  )
131  };
132  sess->start(ip, t.port);
133  recvSessions_[key] = sess;
134  ep2SessionDict_[t.sendFrom] = sess;
135  schedule(hmbdc::time::SysTime::now(), *sess);
136  } catch (std::exception const& e) {
137  HMBDC_LOG_C(e.what());
138  }
139  break;
140  }
141  }
142  } //else ignore
143  }
144 
145  /**
146  * @brief check how many other parties are sending to this engine
147  * @return recipient session count are still active
148  */
149  size_t sessionsRemainingActive() const {
150  return recvSessions_.size();
151  }
152 
153  template <MessageTupleC Messages, typename CcNode>
154  void subscribeFor(CcNode const& node, uint16_t mod, uint16_t res) {
155  subscriptions_.markSubsFor<Messages>(node, mod, res);
156  }
157 private:
159 
161  TypeTagSet subscriptions_;
162  OutputBuffer outputBuffer_;
163  in_addr_t myBackupIp_;
166  using Ep2SessionDict //sender's ip address port ->
167  = boost::unordered_map<sockaddr_in, typename Session::ptr
168  , endpointhash, endpointequal>;
169  Ep2SessionDict ep2SessionDict_;
170  boost::unordered_map<std::pair<uint64_t, uint16_t>
171  , typename Session::ptr> recvSessions_;
173  bool loopback_;
174  uint32_t myPid_ = 0;
175 };
176 
177 template <typename OutputBuffer, typename AttachmentAllocator>
179 : RecvTransportImpl<OutputBuffer, AttachmentAllocator>
180 , hmbdc::app::Client<RecvTransportEngine<OutputBuffer, AttachmentAllocator>> {
181 private:
183 
184 public:
186  , OutputBuffer& outputBuffer)
187  : Impl(cfg, outputBuffer) {
188  Impl::start();
189  }
190 
191  void rotate() {
192  if (runLock_.try_lock()) {
193  this->checkTimers(hmbdc::time::SysTime::now());
195  runLock_.unlock();
196  }
197  }
198 
199  /*virtual*/
200  void messageDispatchingStartedCb(size_t const*) override {
201  runLock_.lock();
202  };
203 
204  /*virtual*/
205  void invokedCb(size_t) HMBDC_RESTRICT override {
206  Impl::runOnce();
207  }
208 
209 /**
210  * @brief should not happen ever unless an exception thrown
211  *
212  * @param e exception thown
213  */
214  /*virtual*/
215  void stoppedCb(std::exception const& e) override {
216  HMBDC_LOG_C(e.what());
217  };
218 
219  using EngineTransport::hmbdcName;
220 
221  std::tuple<char const*, int> schedSpec() const {
222  return std::make_tuple(this->schedPolicy_.c_str(), this->schedPriority_);
223  }
224 
226  this->runLock_.unlock();
227  }
228 private:
229  std::mutex runLock_;
230 };
231 
232 } //recvtransportengine_detail
233 
234 template <typename OutputBuffer, typename AttachmentAllocator>
235 using RecvTransportEngine = recvtransportengine_detail::RecvTransportEngine<OutputBuffer
236  , AttachmentAllocator>;
237 }}}
T getExt(const path_type &param, bool throwIfMissing=true) const
get a value from the config
Definition: Config.hpp:238
Definition: MonoLockFreeBuffer.hpp:16
class to hold an hmbdc configuration
Definition: Config.hpp:44
void setAdditionalFallbackConfig(Config const &c)
set additional defaults
Definition: Config.hpp:153
Definition: Messages.hpp:90
impl class
Definition: McRecvTransport.hpp:26
Definition: TypedString.hpp:84
impl class
Definition: RecvTransportEngine.hpp:43
Definition: Timers.hpp:70
Config & resetSection(char const *section, bool sectionExists=true)
change section name
Definition: Config.hpp:176
Definition: Hash.hpp:32
void stoppedCb(std::exception const &e) override
should not happen ever unless an exception thrown
Definition: RecvTransportEngine.hpp:215
Definition: MessageDispacher.hpp:184
Definition: Message.hpp:212
RecvTransportImpl(hmbdc::app::Config const &cfg, OutputBuffer &outputBuffer)
ctor
Definition: RecvTransportEngine.hpp:57
Definition: Hash.hpp:20
void cancel(Timer &timer)
cancel a timer previously scheduled with the TimerManager
Definition: Timers.hpp:90
interface to power a multicast transport receiving functions
Definition: RecvTransportEngine.hpp:25
void invokedCb(size_t) HMBDC_RESTRICT override
this callback is called all the time (frequently) - the exact timing is after a batch of messages are...
Definition: RecvTransportEngine.hpp:205
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
size_t sessionsRemainingActive() const
check how many other parties are sending to this engine
Definition: RecvTransportEngine.hpp:149
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
void handleMessageCb(TypeTagBackupSource const &t)
only used by MH
Definition: RecvTransportEngine.hpp:110
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
void start()
start the show by schedule the mesage recv
Definition: RecvTransportEngine.hpp:81
Definition: LockFreeBufferMisc.hpp:89
void messageDispatchingStartedCb(size_t const *) override
called before any messages got dispatched - only once
Definition: RecvTransportEngine.hpp:200