From 3ca4e091af04713e811357c1c6e05ecd922edabc Mon Sep 17 00:00:00 2001 From: Maxim Sharabayko Date: Thu, 14 Jan 2021 11:18:08 +0100 Subject: [PATCH] [core] Main-backup: added QualifyMemberStates function (#1739) and moved corresponding code there (behavior untouched) --- srtcore/group.cpp | 139 +++++++++++++++++++++++++--------------------- srtcore/group.h | 15 +++++ 2 files changed, 90 insertions(+), 64 deletions(-) diff --git a/srtcore/group.cpp b/srtcore/group.cpp index edc204d10..1f6378335 100644 --- a/srtcore/group.cpp +++ b/srtcore/group.cpp @@ -2894,6 +2894,79 @@ bool CUDTGroup::send_CheckIdle(const gli_t d, vector& w_wipeme, vecto return true; } +void CUDTGroup::sendBackup_QualifyMemberStates(const steady_clock::time_point& currtime, + vector& w_wipeme, + vector& w_idlers, + vector& w_pending, + vector& w_unstable, + vector& w_sendable) +{ + // First, check status of every link - no matter if idle or active. + for (gli_t d = m_Group.begin(); d != m_Group.end(); ++d) + { + if (d->sndstate != SRT_GST_BROKEN) + { + // Check the socket state prematurely in order not to uselessly + // send over a socket that is broken. + CUDT* const pu = (d->ps) + ? &d->ps->core() + : NULL; + + if (!pu || pu->m_bBroken) + { + HLOGC(gslog.Debug, log << "grp/sendBackup: socket @" << d->id << " detected +Broken - transit to BROKEN"); + d->sndstate = SRT_GST_BROKEN; + d->rcvstate = SRT_GST_BROKEN; + } + } + + // Check socket sndstate before sending + if (d->sndstate == SRT_GST_BROKEN) + { + HLOGC(gslog.Debug, + log << "grp/sendBackup: socket in BROKEN state: @" << d->id + << ", sockstatus=" << SockStatusStr(d->ps ? d->ps->getStatus() : SRTS_NONEXIST)); + w_wipeme.push_back(d->id); + continue; + } + + if (d->sndstate == SRT_GST_IDLE) + { + if (!send_CheckIdle(d, (w_wipeme), (w_pending))) + continue; + + HLOGC(gslog.Debug, + log << "grp/sendBackup: socket in IDLE state: @" << d->id << " - will activate it IF NEEDED"); + // This is idle, we'll take care of them next time + // Might be that: + // - this socket is idle, while some NEXT socket is running + // - we need at least one running socket to work BEFORE activating the idle one. + // - if ALL SOCKETS ARE IDLE, then we simply activate the first from the list, + // and all others will be activated using the ISN from the first one. + w_idlers.push_back(d); + sendBackup_CheckIdleTime(d); + continue; + } + + if (d->sndstate == SRT_GST_RUNNING) + { + if (!sendBackup_CheckRunningStability(d, (currtime))) + { + insert_uniq((w_unstable), d); + } + // Unstable links should still be used for sending. + w_sendable.push_back(d); + continue; + } + + HLOGC(gslog.Debug, + log << "grp/sendBackup: socket @" << d->id << " not ready, state: " << StateStr(d->sndstate) << "(" + << int(d->sndstate) << ") - NOT sending, SET AS PENDING"); + + w_pending.push_back(d->id); + } +} + // [[using locked(this->m_GroupLock)]] void CUDTGroup::sendBackup_CheckIdleTime(gli_t w_d) { @@ -3824,70 +3897,8 @@ int CUDTGroup::sendBackup(const char* buf, int len, SRT_MSGCTRL& w_mc) sendable.reserve(m_Group.size()); - // First, check status of every link - no matter if idle or active. - for (gli_t d = m_Group.begin(); d != m_Group.end(); ++d) - { - if (d->sndstate != SRT_GST_BROKEN) - { - // Check the socket state prematurely in order not to uselessly - // send over a socket that is broken. - CUDT* const pu = (d->ps) - ? &d->ps->core() - : NULL; - - if (!pu || pu->m_bBroken) - { - HLOGC(gslog.Debug, log << "grp/sendBackup: socket @" << d->id << " detected +Broken - transit to BROKEN"); - d->sndstate = SRT_GST_BROKEN; - d->rcvstate = SRT_GST_BROKEN; - } - } - - // Check socket sndstate before sending - if (d->sndstate == SRT_GST_BROKEN) - { - HLOGC(gslog.Debug, - log << "grp/sendBackup: socket in BROKEN state: @" << d->id - << ", sockstatus=" << SockStatusStr(d->ps ? d->ps->getStatus() : SRTS_NONEXIST)); - wipeme.push_back(d->id); - continue; - } - - if (d->sndstate == SRT_GST_IDLE) - { - if (!send_CheckIdle(d, (wipeme), (pending))) - continue; - - HLOGC(gslog.Debug, - log << "grp/sendBackup: socket in IDLE state: @" << d->id << " - will activate it IF NEEDED"); - // This is idle, we'll take care of them next time - // Might be that: - // - this socket is idle, while some NEXT socket is running - // - we need at least one running socket to work BEFORE activating the idle one. - // - if ALL SOCKETS ARE IDLE, then we simply activate the first from the list, - // and all others will be activated using the ISN from the first one. - idlers.push_back(d); - sendBackup_CheckIdleTime(d); - continue; - } - - if (d->sndstate == SRT_GST_RUNNING) - { - if (!sendBackup_CheckRunningStability(d, (currtime))) - { - insert_uniq((unstable), d); - } - // Unstable links should still be used for sending. - sendable.push_back(d); - continue; - } - - HLOGC(gslog.Debug, - log << "grp/sendBackup: socket @" << d->id << " not ready, state: " << StateStr(d->sndstate) << "(" - << int(d->sndstate) << ") - NOT sending, SET AS PENDING"); - - pending.push_back(d->id); - } + // Qualify states of member links + sendBackup_QualifyMemberStates(currtime, (wipeme), (idlers), (pending), (unstable), (sendable)); // Sort the idle sockets by priority so the highest priority idle links are checked first. sort(idlers.begin(), idlers.end(), FPriorityOrder()); diff --git a/srtcore/group.h b/srtcore/group.h index 9606c56e1..58eb76c8f 100644 --- a/srtcore/group.h +++ b/srtcore/group.h @@ -233,6 +233,21 @@ class CUDTGroup // Support functions for sendBackup and sendBroadcast bool send_CheckIdle(const gli_t d, std::vector& w_wipeme, std::vector& w_pending); void sendBackup_CheckIdleTime(gli_t w_d); + + /// Qualify states of member links. + /// [[using locked(this->m_GroupLock, m_pGlobal->m_GlobControlLock)]] + /// @param[in] currtime current timestamp + /// @param[out] w_wipeme broken links or links about to be closed + /// @param[out] w_idlers idle links + /// @param[out] w_pending links pending to be connected + /// @param[out] w_unstable member links qualified as unstable + /// @param[out] w_sendable all running member links, including unstable + void sendBackup_QualifyMemberStates(const steady_clock::time_point& currtime, + std::vector& w_wipeme, + std::vector& w_idlers, + std::vector& w_pending, + std::vector& w_unstable, + std::vector& w_sendable); /// Check if a running link is stable. /// @retval true running link is stable