PageRenderTime 15ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/llmessage/llmessagethrottle.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 176 lines | 107 code | 23 blank | 46 comment | 14 complexity | 9dd384d2426cc8a447b3cc6d9ae6266d MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llmessagethrottle.cpp
  3. * @brief LLMessageThrottle class used for throttling messages.
  4. *
  5. * $LicenseInfo:firstyear=2004&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #include "linden_common.h"
  27. #include "llhash.h"
  28. #include "llmessagethrottle.h"
  29. #include "llframetimer.h"
  30. // This is used for the stl search_n function.
  31. #if _MSC_VER >= 1500 // VC9 has a bug in search_n
  32. struct eq_message_throttle_entry : public std::binary_function< LLMessageThrottleEntry, LLMessageThrottleEntry, bool >
  33. {
  34. bool operator()(const LLMessageThrottleEntry& a, const LLMessageThrottleEntry& b) const
  35. {
  36. return a.getHash() == b.getHash();
  37. }
  38. };
  39. #else
  40. bool eq_message_throttle_entry(LLMessageThrottleEntry a, LLMessageThrottleEntry b)
  41. { return a.getHash() == b.getHash(); }
  42. #endif
  43. const U64 SEC_TO_USEC = 1000000;
  44. // How long (in microseconds) each type of message stays in its throttle list.
  45. const U64 MAX_MESSAGE_AGE[MTC_EOF] =
  46. {
  47. 10 * SEC_TO_USEC, // MTC_VIEWER_ALERT
  48. 10 * SEC_TO_USEC // MTC_AGENT_ALERT
  49. };
  50. LLMessageThrottle::LLMessageThrottle()
  51. {
  52. }
  53. LLMessageThrottle::~LLMessageThrottle()
  54. {
  55. }
  56. void LLMessageThrottle::pruneEntries()
  57. {
  58. // Go through each message category, and prune entries older than max age.
  59. S32 cat;
  60. for (cat = 0; cat < MTC_EOF; cat++)
  61. {
  62. message_list_t* message_list = &(mMessageList[cat]);
  63. // Use a reverse iterator, since entries on the back will be the oldest.
  64. message_list_reverse_iterator_t r_iterator = message_list->rbegin();
  65. message_list_reverse_iterator_t r_last = message_list->rend();
  66. // Look for the first entry younger than the maximum age.
  67. F32 max_age = (F32)MAX_MESSAGE_AGE[cat];
  68. BOOL found = FALSE;
  69. while (r_iterator != r_last && !found)
  70. {
  71. if ( LLFrameTimer::getTotalTime() - (*r_iterator).getEntryTime() < max_age )
  72. {
  73. // We found a young enough entry.
  74. found = TRUE;
  75. // Did we find at least one entry to remove?
  76. if (r_iterator != message_list->rbegin())
  77. {
  78. // Yes, remove it.
  79. message_list->erase(r_iterator.base(), message_list->end());
  80. }
  81. }
  82. else
  83. {
  84. r_iterator++;
  85. }
  86. }
  87. // If we didn't find any entries young enough to keep, remove them all.
  88. if (!found)
  89. {
  90. message_list->clear();
  91. }
  92. }
  93. }
  94. BOOL LLMessageThrottle::addViewerAlert(const LLUUID& to, const std::string& mesg)
  95. {
  96. message_list_t* message_list = &(mMessageList[MTC_VIEWER_ALERT]);
  97. // Concatenate from,to,mesg into one string.
  98. std::ostringstream full_mesg;
  99. full_mesg << to << mesg;
  100. // Create an entry for this message.
  101. size_t hash = llhash(full_mesg.str().c_str());
  102. LLMessageThrottleEntry entry(hash, LLFrameTimer::getTotalTime());
  103. // Check if this message is already in the list.
  104. #if _MSC_VER >= 1500 // VC9 has a bug in search_n
  105. // SJB: This *should* work but has not been tested yet *TODO: Test!
  106. message_list_iterator_t found = std::find_if(message_list->begin(), message_list->end(),
  107. std::bind2nd(eq_message_throttle_entry(), entry));
  108. #else
  109. message_list_iterator_t found = std::search_n(message_list->begin(), message_list->end(),
  110. 1, entry, eq_message_throttle_entry);
  111. #endif
  112. if (found == message_list->end())
  113. {
  114. // This message was not found. Add it to the list.
  115. message_list->push_front(entry);
  116. return TRUE;
  117. }
  118. else
  119. {
  120. // This message was already in the list.
  121. return FALSE;
  122. }
  123. }
  124. BOOL LLMessageThrottle::addAgentAlert(const LLUUID& agent, const LLUUID& task, const std::string& mesg)
  125. {
  126. message_list_t* message_list = &(mMessageList[MTC_AGENT_ALERT]);
  127. // Concatenate from,to,mesg into one string.
  128. std::ostringstream full_mesg;
  129. full_mesg << agent << task << mesg;
  130. // Create an entry for this message.
  131. size_t hash = llhash(full_mesg.str().c_str());
  132. LLMessageThrottleEntry entry(hash, LLFrameTimer::getTotalTime());
  133. // Check if this message is already in the list.
  134. #if _MSC_VER >= 1500 // VC9 has a bug in search_n
  135. // SJB: This *should* work but has not been tested yet *TODO: Test!
  136. message_list_iterator_t found = std::find_if(message_list->begin(), message_list->end(),
  137. std::bind2nd(eq_message_throttle_entry(), entry));
  138. #else
  139. message_list_iterator_t found = std::search_n(message_list->begin(), message_list->end(),
  140. 1, entry, eq_message_throttle_entry);
  141. #endif
  142. if (found == message_list->end())
  143. {
  144. // This message was not found. Add it to the list.
  145. message_list->push_front(entry);
  146. return TRUE;
  147. }
  148. else
  149. {
  150. // This message was already in the list.
  151. return FALSE;
  152. }
  153. }