group_backup.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. /*
  2. * SRT - Secure, Reliable, Transport
  3. * Copyright (c) 2021 Haivision Systems Inc.
  4. *
  5. * This Source Code Form is subject to the terms of the Mozilla Public
  6. * License, v. 2.0. If a copy of the MPL was not distributed with this
  7. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  8. *
  9. */
  10. /*****************************************************************************
  11. Written by
  12. Haivision Systems Inc.
  13. *****************************************************************************/
  14. #include "platform_sys.h"
  15. #include <algorithm>
  16. #include <sstream>
  17. #include "group_backup.h"
  18. namespace srt
  19. {
  20. namespace groups
  21. {
  22. using namespace std;
  23. using namespace srt_logging;
  24. const char* stateToStr(BackupMemberState state)
  25. {
  26. switch (state)
  27. {
  28. case srt::groups::BKUPST_UNKNOWN:
  29. return "UNKNOWN";
  30. case srt::groups::BKUPST_PENDING:
  31. return "PENDING";
  32. case srt::groups::BKUPST_STANDBY:
  33. return "STANDBY";
  34. case srt::groups::BKUPST_ACTIVE_FRESH:
  35. return "ACTIVE_FRESH";
  36. case srt::groups::BKUPST_ACTIVE_STABLE:
  37. return "ACTIVE_STABLE";
  38. case srt::groups::BKUPST_ACTIVE_UNSTABLE:
  39. return "ACTIVE_UNSTABLE";
  40. case srt::groups::BKUPST_ACTIVE_UNSTABLE_WARY:
  41. return "ACTIVE_UNSTABLE_WARY";
  42. case srt::groups::BKUPST_BROKEN:
  43. return "BROKEN";
  44. default:
  45. break;
  46. }
  47. return "WRONG_STATE";
  48. }
  49. /// @brief Compares group members by their weight (higher weight comes first), then state.
  50. /// Higher weight comes first, same weight: stable, then fresh active.
  51. struct FCompareByWeight
  52. {
  53. /// @returns true if the first argument is less than (i.e. is ordered before) the second.
  54. bool operator()(const BackupMemberStateEntry& a, const BackupMemberStateEntry& b)
  55. {
  56. if (a.pSocketData != NULL && b.pSocketData != NULL
  57. && (a.pSocketData->weight != b.pSocketData->weight))
  58. return a.pSocketData->weight > b.pSocketData->weight;
  59. if (a.state != b.state)
  60. {
  61. SRT_STATIC_ASSERT(BKUPST_ACTIVE_STABLE > BKUPST_ACTIVE_FRESH, "Wrong ordering");
  62. return a.state > b.state;
  63. }
  64. // the order does not matter, but comparator must return a different value for not equal a and b
  65. return a.socketID < b.socketID;
  66. }
  67. };
  68. void SendBackupCtx::recordMemberState(SocketData* pSockData, BackupMemberState st)
  69. {
  70. m_memberStates.push_back(BackupMemberStateEntry(pSockData, st));
  71. ++m_stateCounter[st];
  72. if (st == BKUPST_STANDBY)
  73. {
  74. m_standbyMaxWeight = max(m_standbyMaxWeight, pSockData->weight);
  75. }
  76. else if (isStateActive(st))
  77. {
  78. m_activeMaxWeight = max(m_activeMaxWeight, pSockData->weight);
  79. }
  80. }
  81. void SendBackupCtx::updateMemberState(const SocketData* pSockData, BackupMemberState st)
  82. {
  83. typedef vector<BackupMemberStateEntry>::iterator iter_t;
  84. for (iter_t i = m_memberStates.begin(); i != m_memberStates.end(); ++i)
  85. {
  86. if (i->pSocketData == NULL)
  87. continue;
  88. if (i->pSocketData != pSockData)
  89. continue;
  90. if (i->state == st)
  91. return;
  92. --m_stateCounter[i->state];
  93. ++m_stateCounter[st];
  94. i->state = st;
  95. return;
  96. }
  97. LOGC(gslog.Error,
  98. log << "IPE: SendBackupCtx::updateMemberState failed to locate member");
  99. }
  100. void SendBackupCtx::sortByWeightAndState()
  101. {
  102. sort(m_memberStates.begin(), m_memberStates.end(), FCompareByWeight());
  103. }
  104. BackupMemberState SendBackupCtx::getMemberState(const SocketData* pSockData) const
  105. {
  106. typedef vector<BackupMemberStateEntry>::const_iterator const_iter_t;
  107. for (const_iter_t i = m_memberStates.begin(); i != m_memberStates.end(); ++i)
  108. {
  109. if (i->pSocketData != pSockData)
  110. continue;
  111. return i->state;
  112. }
  113. // The entry was not found
  114. // TODO: Maybe throw an exception here?
  115. return BKUPST_UNKNOWN;
  116. }
  117. unsigned SendBackupCtx::countMembersByState(BackupMemberState st) const
  118. {
  119. return m_stateCounter[st];
  120. }
  121. std::string SendBackupCtx::printMembers() const
  122. {
  123. stringstream ss;
  124. typedef vector<BackupMemberStateEntry>::const_iterator const_iter_t;
  125. for (const_iter_t i = m_memberStates.begin(); i != m_memberStates.end(); ++i)
  126. {
  127. ss << "@" << i->socketID << " w " << i->pSocketData->weight << " state " << stateToStr(i->state) << ", ";
  128. }
  129. return ss.str();
  130. }
  131. } // namespace groups
  132. } // namespace srt