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

/src/service/monitor/EntriesQueue.cpp

https://gitlab.com/admin-github-cloud/cynara
C++ | 147 lines | 108 code | 17 blank | 22 comment | 10 complexity | f3fa8c401e755b27fa8986d3f7168959 MD5 | raw file
  1. /*
  2. * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /**
  17. * @file src/service/monitor/EntriesQueue.cpp
  18. * @author Zofia Abramowska <z.abramowska@samsung.com>
  19. * @version 1.0
  20. * @brief This file implements class for storing monitor entries
  21. */
  22. #include <algorithm>
  23. #include "EntriesQueue.h"
  24. #include <log/log.h>
  25. namespace Cynara {
  26. EntriesQueue::EntriesQueue(int maxQueueSize, int maxBucketSize)
  27. : m_firstBucketId(0), m_lastBucketId(0), m_size(0), m_maxQueueSize(maxQueueSize),
  28. m_maxBucketSize(maxBucketSize)
  29. {
  30. clear();
  31. }
  32. bool EntriesQueue::push(const MonitorEntry &entry) {
  33. auto &lastBucket = m_entries[m_lastBucketId];
  34. lastBucket.entries.push_back(entry);
  35. if (static_cast<int>(lastBucket.entries.size()) == m_maxBucketSize) {
  36. m_lastBucketId = nextBucketId(m_lastBucketId);
  37. createBucket(m_lastBucketId);
  38. }
  39. m_size++;
  40. return checkSize();
  41. }
  42. bool EntriesQueue::checkSize(void) {
  43. if (m_size <= m_maxQueueSize) {
  44. return false;
  45. }
  46. LOGW("Maximum capacity reached. Removing least recently pushed entry.");
  47. auto &firstBucket = m_entries[m_firstBucketId];
  48. firstBucket.offset++;
  49. m_size--;
  50. if (firstBucket.offset >= m_maxBucketSize) {
  51. eraseBucket(m_firstBucketId);
  52. m_firstBucketId = nextBucketId(m_firstBucketId);
  53. }
  54. return true;
  55. }
  56. EntriesQueue::EntryId EntriesQueue::fetch(EntriesQueue::EntryId fromEntryId, int amount,
  57. std::vector<MonitorEntry> &entries) const {
  58. if (sizeFrom(fromEntryId) < amount) {
  59. LOGE("Not enough entries stored to fetch [" << amount << "]");
  60. return -1;
  61. }
  62. int startBucketId = countBucketId(fromEntryId);
  63. int startBucketOffset = countBucketOffset(fromEntryId);
  64. copyEntries(startBucketId, startBucketOffset, amount, entries);
  65. return (fromEntryId + amount) % (m_entries.size() * m_maxBucketSize);
  66. }
  67. void EntriesQueue::popUntil(EntryId entryId) {
  68. int endBucketId = countBucketId(entryId);
  69. int endBucketOffset = countBucketOffset(entryId);
  70. removeEntries(endBucketId, endBucketOffset);
  71. }
  72. void EntriesQueue::clear(void) {
  73. m_lastBucketId = m_firstBucketId = 0;
  74. m_entries.clear();
  75. m_entries.resize(m_maxQueueSize/m_maxBucketSize + 1);
  76. m_size = 0;
  77. }
  78. int EntriesQueue::sizeFrom(EntryId fromEntryId) const {
  79. int frontId = getFrontEntryId();
  80. int backId = getBackEntryId();
  81. if (fromEntryId < frontId) {
  82. return backId - fromEntryId;
  83. } else {
  84. return m_size - (fromEntryId - frontId);
  85. }
  86. }
  87. void EntriesQueue::createBucket(int bucketId) {
  88. m_entries[bucketId].offset = 0;
  89. m_entries[bucketId].entries.reserve(m_maxBucketSize);
  90. }
  91. void EntriesQueue::eraseBucket(int bucketId) {
  92. // Trick for forcing vector to free its memory
  93. m_size -= m_entries[bucketId].entries.size() - m_entries[bucketId].offset;
  94. std::vector<MonitorEntry>().swap(m_entries[bucketId].entries);
  95. m_entries[bucketId].offset = 0;
  96. }
  97. int EntriesQueue::countBucketId(EntryId entryId) const {
  98. return entryId / m_maxBucketSize;
  99. }
  100. int EntriesQueue::countBucketOffset(EntryId entryId) const {
  101. return entryId % m_maxBucketSize;
  102. }
  103. int EntriesQueue::nextBucketId(int bucketId) const {
  104. return (bucketId + 1) % m_entries.size();
  105. }
  106. void EntriesQueue::copyEntries(int bucketId, int offset, int amount,
  107. std::vector<MonitorEntry> &entries) const {
  108. int toFetch = amount;
  109. while (entries.size() < static_cast<unsigned int>(amount)) {
  110. auto &bucket = m_entries[bucketId];
  111. int bucketAmount = std::min(offset + toFetch,
  112. static_cast<int>(bucket.entries.size()));
  113. entries.insert(entries.end(), bucket.entries.begin() + offset,
  114. bucket.entries.begin() + bucketAmount);
  115. bucketId = nextBucketId(bucketId);
  116. toFetch -= (bucketAmount - offset);
  117. offset = 0;
  118. }
  119. }
  120. void EntriesQueue::removeEntries(int endBucketId, int endOffset) {
  121. int bucketId = m_firstBucketId;
  122. while (bucketId != endBucketId) {
  123. eraseBucket(bucketId);
  124. bucketId = nextBucketId(bucketId);
  125. }
  126. m_size -= endOffset - m_entries[bucketId].offset;
  127. m_entries[bucketId].offset = endOffset;
  128. m_firstBucketId = bucketId;
  129. }
  130. } /* namespace Cynara */