1 #include "hmbdc/Copyright.hpp" 3 #include "hmbdc/tips/reliable/TcpEpollFd.hpp" 4 #include "hmbdc/tips/TypeTagSet.hpp" 5 #include "hmbdc/app/Logger.hpp" 6 #include "hmbdc/time/Time.hpp" 7 #include "hmbdc/time/Rater.hpp" 8 #include "hmbdc/pattern/LockFreeBufferT.hpp" 9 #include "hmbdc/comm/inet/Misc.hpp" 11 #include <boost/circular_buffer.hpp> 12 #include <unordered_set> 16 #include <netinet/tcp.h> 18 namespace hmbdc {
namespace tips {
namespace reliable {
20 using ToCleanupAttQueue = boost::circular_buffer<std::tuple<
22 , app::hasMemoryAttachment*
23 , app::hasMemoryAttachment::AfterConsumedCleanupFunc
27 namespace backupsendservert_detail {
28 template <
typename TypeTagBackupSource,
typename BackupSendSession>
33 , serverAddr_(serverFd_.localAddr) {
34 if (listen(serverFd_.fd, 10) < 0) {
35 HMBDC_THROW(std::runtime_error,
"failed to listen, errno=" << errno);
37 hmbdc::app::utils::EpollTask::instance().add(
38 hmbdc::app::utils::EpollTask::EPOLLIN
39 | hmbdc::app::utils::EpollTask::EPOLLET, serverFd_);
43 decltype(advertisingMessages_) newAds;
44 tts.exportTo([&](uint16_t tag,
auto&& subCount) {
45 if (newAds.size() == 0
46 || !newAds.rbegin()->addTypeTag(tag)) {
47 newAds.emplace_back(serverFd_.localIp
49 , time::Duration::microseconds(config_.
getExt<uint32_t>(
"recvReportDelayMicrosec"))
50 , config_.
getExt<
bool>(
"loopback"));
51 newAds.rbegin()->addTypeTag(tag);
54 std::swap(advertisingMessages_, newAds);
55 for (
auto& m : advertisingMessages_) {
56 HMBDC_LOG_N(
"adverise at ", m);
60 auto const& advertisingMessages()
const {
61 return advertisingMessages_;
67 sockaddr_in& serverAddr_;
68 std::vector<TypeTagBackupSource> advertisingMessages_;
72 template <
typename TypeTagBackupSource,
typename BackupSendSession>
75 using Buffer =
typename BackupSendSession::Buffer;
79 , ToCleanupAttQueue& toCleanupAttQueue
84 , maxSendBatch_(cfg.
getExt<uint32_t>(
"maxSendBatch"))
85 , toCleanupAttQueue_(toCleanupAttQueue)
86 , replayHistoryForNewRecv_(cfg.
getExt<
size_t>(
"replayHistoryForNewRecv"))
87 , outboundSubscriptions_(outboundSubscriptions) {
88 leastIt_.seq_ = std::numeric_limits<HMBDC_SEQ_TYPE>::max();
93 void runOnce() HMBDC_RESTRICT {
97 auto newSeq_= buffer_.readSeq(0);
98 for (
auto it = sessions_.begin(); it != sessions_.end();) {
99 if (hmbdc_unlikely(!(*it)->runOnce())) {
101 sessions_.erase(it++);
103 if (newSeq_ > (*it)->bufItNext_.seq_) {
104 newSeq_ = (*it)->bufItNext_.seq_;
109 if (hmbdc_likely(replayHistoryForNewRecv_ < newSeq_)) {
110 newSeq_ -= replayHistoryForNewRecv_;
114 if (leastIt_.seq_ != newSeq_) {
115 while (toCleanupAttQueue_.size()) {
116 auto it = toCleanupAttQueue_.begin();
117 if (newSeq_ > std::get<0>(*it)) {
118 auto f = std::get<2>(*it);
119 if (f) f(std::get<1>(*it));
120 toCleanupAttQueue_.pop_front();
125 buffer_.catchUpTo(1, newSeq_);
127 leastIt_.seq_ = newSeq_;
131 while (toCleanupAttQueue_.size()) {
132 auto it = toCleanupAttQueue_.begin();
133 auto f = std::get<2>(*it);
134 if (f) f(std::get<1>(*it));
135 toCleanupAttQueue_.pop_front();
139 size_t sessionCount()
const {
140 return sessions_.size();
143 size_t readySessionCount() HMBDC_RESTRICT
const {
145 for (
auto const& s : sessions_) {
146 if (s->ready()) res++;
151 void killSlowestSession() {
152 if (sessions_.size() == 0) {
156 auto it = sessions_.begin();
157 auto leastSessIt = it;
159 for (; it != sessions_.end(); it++) {
160 if ((*it)->bufItNext_ < leastIt) {
161 leastIt = (*it)->bufItNext_;
165 HMBDC_LOG_C((*leastSessIt)->id(),
" too slow, dropping");
166 (*leastSessIt)->stop();
167 sessions_.erase(leastSessIt);
171 void doAccept() HMBDC_RESTRICT {
172 auto& serverFd_ = this->serverFd_;
173 auto& serverAddr_ = this->serverAddr_;
174 if (hmbdc_unlikely(serverFd_.isFdReady())) {
175 auto addrlen =
sizeof(serverAddr_);
176 auto conn = accept(serverFd_.fd, (
struct sockaddr *)&serverAddr_, (socklen_t*)&addrlen);
178 if (!serverFd_.checkErr()) {
179 HMBDC_LOG_C(
"accept failure, errno=", errno);
183 auto sz = this->config_.template getExt<int>(
"tcpSendBufferBytes");
185 if (setsockopt(conn, SOL_SOCKET, SO_SNDBUF, &sz,
sizeof(sz)) < 0) {
186 HMBDC_LOG_C(
"failed to set send buffer size=", sz,
" errno=", errno);
189 int flag = this->config_.template getExt<bool>(
"nagling")?0:1;
190 if (setsockopt(conn, IPPROTO_TCP, TCP_NODELAY, (
char*) &flag,
sizeof(flag)) < 0) {
191 HMBDC_LOG_C(
"failed to set TCP_NODELAY, errno=", errno);
195 buffer_.peek(1, it, it, 0);
196 auto s = std::make_shared<BackupSendSession>(conn
201 , outboundSubscriptions_);
204 }
catch (std::exception
const& e) {
205 HMBDC_LOG_C(e.what());
210 using Sessions = std::unordered_set<typename BackupSendSession::ptr>;
212 Buffer& HMBDC_RESTRICT buffer_;
215 size_t maxSendBatch_;
216 ToCleanupAttQueue& toCleanupAttQueue_;
217 size_t replayHistoryForNewRecv_;
223 template <
typename TypeTagBackupSource,
typename BackupSendSession>
T getExt(const path_type ¶m, bool throwIfMissing=true) const
get a value from the config
Definition: Config.hpp:238
Definition: TcpEpollFd.hpp:14
class to hold an hmbdc configuration
Definition: Config.hpp:44
Definition: BackupSendServerT.hpp:29
Definition: BackupSendServerT.hpp:73
Definition: LockFreeBufferMisc.hpp:89