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

/src/monitor/logic/Logic.cpp

https://gitlab.com/github-cloud-corporation/cynara
C++ | 193 lines | 140 code | 19 blank | 34 comment | 14 complexity | ffa5afe79f5705e4c3a7ba0b14718b50 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/monitor/logic/Logic.cpp
  18. * @author Aleksander Zdyb <a.zdyb@samsung.com>
  19. * @author Zofia Abramowska <z.abramowska@samsung.com>
  20. * @version 1.0
  21. * @brief This file contains implementation of Logic class -- main libcynara-monitor class
  22. */
  23. #include <mutex>
  24. #include <cynara-error.h>
  25. #include <log/log.h>
  26. #include <request/MonitorGetEntriesRequest.h>
  27. #include <request/MonitorGetFlushRequest.h>
  28. #include <types/MonitorEntry.h>
  29. #include "Logic.h"
  30. namespace {
  31. Cynara::ProtocolFrameSequenceNumber generateSequenceNumber(void) {
  32. static Cynara::ProtocolFrameSequenceNumber sequenceNumber = 0;
  33. return ++sequenceNumber;
  34. }
  35. /*
  36. * Made for scoped lock/unlock of mutex
  37. */
  38. class StatusChangeWrapper {
  39. public:
  40. StatusChangeWrapper(std::mutex &mutex, bool &status) : m_mutex(mutex), m_status(status) {
  41. std::lock_guard<std::mutex> lock(m_mutex);
  42. m_status = true;
  43. }
  44. ~StatusChangeWrapper() {
  45. std::lock_guard<std::mutex> lock(m_mutex);
  46. m_status = false;
  47. }
  48. private:
  49. std::mutex &m_mutex;
  50. bool &m_status;
  51. };
  52. /*
  53. * Made for scoped condition variable notify
  54. */
  55. class CVNotifyWrapper {
  56. public:
  57. CVNotifyWrapper(std::condition_variable &cv) : m_cv(cv) {
  58. }
  59. ~CVNotifyWrapper() {
  60. m_cv.notify_all();
  61. }
  62. private:
  63. std::condition_variable &m_cv;
  64. };
  65. } // namespace anonymous
  66. namespace Cynara {
  67. int Logic::init(void) {
  68. if (!m_notify.init()) {
  69. LOGE("Couldn't initialize notification object");
  70. return CYNARA_API_UNKNOWN_ERROR;
  71. }
  72. m_client.setNotifyFd(m_notify.getNotifyFd());
  73. return CYNARA_API_SUCCESS;
  74. }
  75. bool Logic::connect(void) {
  76. std::unique_lock<std::mutex> lock(m_mutexCond);
  77. CVNotifyWrapper cv(m_connectedCV);
  78. bool connectionEstablished = true;
  79. m_connectionResolved = true;
  80. if (!m_client.isConnected()) {
  81. connectionEstablished = m_client.connect();
  82. }
  83. if (!connectionEstablished) {
  84. LOGE("Cannot connect to Cynara service");
  85. }
  86. return connectionEstablished;
  87. }
  88. int Logic::sendAndFetch(std::vector<MonitorEntry> &entries) {
  89. StatusChangeWrapper status(m_mutexCond, m_isRunning);
  90. if (!connect()) {
  91. return CYNARA_API_SERVICE_NOT_AVAILABLE;
  92. }
  93. if (!m_client.sendRequest(MonitorGetEntriesRequest(m_conf.getBufferSize(),
  94. generateSequenceNumber()))) {
  95. LOGE("Failed sending request to Cynara");
  96. return CYNARA_API_UNKNOWN_ERROR;
  97. }
  98. MonitorSocketClient::Event event;
  99. if (!m_client.waitForEvent(event)) {
  100. LOGE("Waiting for event failed");
  101. return CYNARA_API_SERVICE_NOT_AVAILABLE;
  102. }
  103. switch(event) {
  104. case MonitorSocketClient::Event::FETCH_ENTRIES:
  105. {
  106. auto responsePtr = m_client.fetchEntries();
  107. if (!responsePtr) {
  108. LOGE("Error fetching response");
  109. return CYNARA_API_UNKNOWN_ERROR;
  110. }
  111. entries.assign(responsePtr->entries().begin(), responsePtr->entries().end());
  112. break;
  113. }
  114. case MonitorSocketClient::Event::NOTIFY_RETURN:
  115. LOGD("Got notification to stop working");
  116. break;
  117. }
  118. return CYNARA_API_SUCCESS;
  119. }
  120. int Logic::entriesGet(std::vector<MonitorEntry> &entries) {
  121. std::unique_lock<std::mutex> guard(m_reentrantGuard, std::defer_lock);
  122. if (!guard.try_lock()) {
  123. LOGE("Function is not reentrant");
  124. return CYNARA_API_OPERATION_NOT_ALLOWED;
  125. }
  126. // When sendAndFetch finishes, notify
  127. CVNotifyWrapper cv(m_finishedCV);
  128. int ret = sendAndFetch(entries);
  129. return ret;
  130. }
  131. bool Logic::waitForConnectionResolved(void) {
  132. std::unique_lock<std::mutex> lock(m_mutexCond);
  133. m_connectedCV.wait(lock, [&] { return m_connectionResolved; });
  134. if (!m_client.isConnected()) {
  135. LOGE("Cynara monitor is not connected to service.");
  136. return false;
  137. }
  138. return true;
  139. }
  140. int Logic::entriesFlush(void) {
  141. if (!isRunning()) {
  142. // If no entriesGet waiting, flush doesn't make sense
  143. return CYNARA_API_OPERATION_NOT_ALLOWED;
  144. }
  145. // Wait until entriesGet establishes connection
  146. if (!waitForConnectionResolved()) {
  147. return CYNARA_API_SERVICE_NOT_AVAILABLE;
  148. }
  149. if (!m_client.sendRequest(MonitorGetFlushRequest(generateSequenceNumber()))) {
  150. LOGE("Error sending request to Cynara");
  151. return CYNARA_API_UNKNOWN_ERROR;
  152. }
  153. return CYNARA_API_SUCCESS;
  154. }
  155. bool Logic::isRunning(void) {
  156. std::unique_lock<std::mutex> lock(m_mutexCond);
  157. bool isRunning = m_isRunning;
  158. return isRunning;
  159. }
  160. void Logic::notifyFinish(void) {
  161. if (!isRunning()) {
  162. // If no entriesGet waiting, no action required
  163. return;
  164. }
  165. // Notify entriesGet to unblock it and let it finish gracefully
  166. if (!m_notify.notify()) {
  167. LOGE("Failed to notify");
  168. return;
  169. }
  170. // Wait until entriesGet finished, only then object destruction is safe
  171. std::unique_lock<std::mutex> lock(m_mutexCond);
  172. m_finishedCV.wait(lock, [&] {return !m_isRunning;});
  173. }
  174. } // namespace Cynara