A problem is that ntfd will queue alarm notifications forever if don't have any notifications arrive. The fix is adding periodic checking and writing alarm notifications in a queue --- src/ntf/ntfd/NtfAdmin.cc | 33 ++++++++++++++++++++++++++ src/ntf/ntfd/NtfAdmin.h | 2 ++ src/ntf/ntfd/NtfLogger.cc | 50 +++++++++++++++++++-------------------- src/ntf/ntfd/NtfLogger.h | 4 ++++ src/ntf/ntfd/ntfs_com.h | 2 ++ src/ntf/ntfd/ntfs_main.c | 23 +++++++++++++++++- 6 files changed, 88 insertions(+), 26 deletions(-)
diff --git a/src/ntf/ntfd/NtfAdmin.cc b/src/ntf/ntfd/NtfAdmin.cc index 8bbee69c5..7a74e336b 100644 --- a/src/ntf/ntfd/NtfAdmin.cc +++ b/src/ntf/ntfd/NtfAdmin.cc @@ -31,8 +31,10 @@ #include "base/logtrace.h" #include "base/osaf_utility.h" #include "ntf/common/ntfsv_mem.h" +#include "base/time.h" NtfAdmin *NtfAdmin::theNtfAdmin = NULL; +static const unsigned kTimeoutMs = 5000; /** * This is the constructor. The cluster-wide unique counter for @@ -743,6 +745,26 @@ void NtfAdmin::checkNotificationList() { TRACE_LEAVE(); } +/** + * Calculate timeout periodic checking + */ +int NtfAdmin::GeneratePollTimeout(struct timespec last) { + if (logger.Empty() || !activeController()) return -1; + struct timespec passed_time; + struct timespec current = base::ReadMonotonicClock(); + osaf_timespec_subtract(¤t, &last, &passed_time); + auto passed_time_ms = osaf_timespec_to_millis(&passed_time); + return (passed_time_ms < kTimeoutMs) ? (kTimeoutMs - passed_time_ms) : 0; +} + +/** + * Periodic logging alarm notification when queue available + */ +void NtfAdmin::PeriodicCheck() { + if (logger.Empty() || !activeController()) return; + logger.DequeueLoggerBuffer(); +} + /** * Check if a certain client exists. * @@ -1265,6 +1287,17 @@ void discardedClear(unsigned int clientId, return NtfAdmin::theNtfAdmin->discardedClear(clientId, subscriptionId); } +void PeriodicCheck() { + osafassert(NtfAdmin::theNtfAdmin != NULL); + return NtfAdmin::theNtfAdmin->PeriodicCheck(); +} + +int GeneratePollTimeout(struct timespec last) { + if (!activeController()) return -1; + osafassert(NtfAdmin::theNtfAdmin != NULL); + return NtfAdmin::theNtfAdmin->GeneratePollTimeout(last); +} + /************************C Wrappers related to CLM Integration * **************************/ void add_member_node(NODE_ID node_id) { diff --git a/src/ntf/ntfd/NtfAdmin.h b/src/ntf/ntfd/NtfAdmin.h index 4808ca94d..a75e389e7 100644 --- a/src/ntf/ntfd/NtfAdmin.h +++ b/src/ntf/ntfd/NtfAdmin.h @@ -109,6 +109,8 @@ class NtfAdmin { uint32_t send_cluster_membership_msg_to_clients( SaClmClusterChangesT cluster_change, NODE_ID node_id); bool is_stale_client(unsigned int clientId); + void PeriodicCheck(); + int GeneratePollTimeout(struct timespec last); private: void processNotification(unsigned int clientId, diff --git a/src/ntf/ntfd/NtfLogger.cc b/src/ntf/ntfd/NtfLogger.cc index f272a9a5a..06e6444df 100644 --- a/src/ntf/ntfd/NtfLogger.cc +++ b/src/ntf/ntfd/NtfLogger.cc @@ -108,7 +108,7 @@ void saLogStreamOpenCallback(SaInvocationT invocation, void saLogWriteLogCallback(SaInvocationT invocation, SaAisErrorT error) { TRACE_ENTER2("Callback for notificationId %llu", invocation); - + NtfAdmin::theNtfAdmin->logger.SetErrorCb(error); if (SA_AIS_OK != error) { NtfSmartPtr notification; @@ -142,30 +142,9 @@ void NtfLogger::log(NtfSmartPtr& newNotification) { TRACE_ENTER2("Notification Id=%llu received in logger. Logger buffer size %d", newNotification->getNotificationId(), static_cast<int>(queuedNotificationList.size())); - uint32_t is_buffer_full = isLoggerBufferFull(); - - // Check if there are not logged notifications in logger buffer - while (queuedNotificationList.empty() == false) { - NtfSmartPtr notification = queuedNotificationList.front(); - queuedNotificationList.pop_front(); - TRACE_2("Log queued notification: %llu", notification->getNotificationId()); - if (SA_AIS_OK != this->logNotification(notification)) { - TRACE_2("Push back queued notification: %llu", - notification->getNotificationId()); - queuedNotificationList.push_front(notification); // Keep order - queueNotifcation(newNotification); - TRACE_LEAVE(); - return; - } - } - - // The new notification should be only logged if the buffer is not full - // and the type of notification is alarm. - if ((is_buffer_full == false) && - (isAlarmNotification(newNotification) == true)) { - if (logNotification(newNotification) != SA_AIS_OK) - queueNotifcation(newNotification); - } + if (!isLoggerBufferFull() && isAlarmNotification(newNotification)) + queueNotifcation(newNotification); + DequeueLoggerBuffer(); TRACE_LEAVE(); } @@ -402,3 +381,24 @@ bool NtfLogger::isAlarmNotification(NtfSmartPtr& notif) { else return false; } + +void NtfLogger::DequeueLoggerBuffer() { + TRACE_ENTER(); + // Check if there are not logged notifications in logger buffer + while (!Empty()) { + NtfSmartPtr notification = queuedNotificationList.front(); + queuedNotificationList.pop_front(); + TRACE_2("Log queued notification: %llu", + notification->getNotificationId()); + if (SA_AIS_OK != this->logNotification(notification)) { + TRACE_2("Push back queued notification: %llu", + notification->getNotificationId()); + queuedNotificationList.push_front(notification); // Keep order + break; + } + if (cb_error != SA_AIS_OK) { + break; + } + } + TRACE_LEAVE(); +} diff --git a/src/ntf/ntfd/NtfLogger.h b/src/ntf/ntfd/NtfLogger.h index cd4053e2f..44fe8fe30 100644 --- a/src/ntf/ntfd/NtfLogger.h +++ b/src/ntf/ntfd/NtfLogger.h @@ -69,6 +69,9 @@ class NtfLogger { bool isAlarmNotification(NtfSmartPtr& notif); void resetLoggerBufferFullFlag(); + void DequeueLoggerBuffer(); + bool Empty() { return queuedNotificationList.empty(); } + void SetErrorCb(SaAisErrorT error) { cb_error = error; } private: SaAisErrorT initLog(); @@ -79,6 +82,7 @@ class NtfLogger { QueuedNotificationsList queuedNotificationList; uint32_t logger_buffer_capacity; + SaAisErrorT cb_error; // The flag if logger buffer is full. This is set when checking the logger // buffer size and is reset if the write callback return with SA_AIS_OK diff --git a/src/ntf/ntfd/ntfs_com.h b/src/ntf/ntfd/ntfs_com.h index b9e37da09..61ef4c627 100644 --- a/src/ntf/ntfd/ntfs_com.h +++ b/src/ntf/ntfd/ntfs_com.h @@ -204,6 +204,8 @@ uint32_t count_member_nodes(); bool is_client_clm_member(NODE_ID node_id, SaVersionT *client_ver); bool is_clm_init(); bool is_stale_client(unsigned int clientId); +void PeriodicCheck(); +int GeneratePollTimeout(struct timespec last); #ifdef __cplusplus } diff --git a/src/ntf/ntfd/ntfs_main.c b/src/ntf/ntfd/ntfs_main.c index d74ddc926..176ceef01 100644 --- a/src/ntf/ntfd/ntfs_main.c +++ b/src/ntf/ntfd/ntfs_main.c @@ -35,6 +35,8 @@ #include "base/daemon.h" #include "nid/agent/nid_api.h" #include "base/ncs_main_papi.h" +#include "base/osaf_time.h" +#include "ntf/ntfd/ntfs_com.h" #include "ntfs.h" #include "ntfs_imcnutil.h" @@ -304,6 +306,10 @@ int main(int argc, char *argv[]) int term_fd; TRACE_ENTER(); + struct timespec last; + osaf_clock_gettime(CLOCK_MONOTONIC, &last); + const int kMaxEvent = 50; + int num_events = 0; daemonize(argc, argv); @@ -334,7 +340,8 @@ int main(int argc, char *argv[]) fds[FD_CLM].fd = ntfs_cb->clmSelectionObject; fds[FD_CLM].events = POLLIN; - int ret = poll(fds, SIZE_FDS, -1); + int timeout = GeneratePollTimeout(last); + int ret = poll(fds, SIZE_FDS, timeout); if (ret == -1) { if (errno == EINTR) continue; @@ -343,6 +350,13 @@ int main(int argc, char *argv[]) break; } + if (ret == 0) { + PeriodicCheck(); + osaf_clock_gettime(CLOCK_MONOTONIC, &last); + num_events = 0; + continue; + } + if (fds[FD_TERM].revents & POLLIN) { TRACE("Exit via FD_TERM calling stop_ntfimcn()"); (void)stop_ntfimcn(); @@ -406,6 +420,13 @@ int main(int argc, char *argv[]) /* process all the log callbacks */ if (fds[FD_LOG].revents & POLLIN) logEvent(); + + num_events++; + if (num_events >= kMaxEvent) { + PeriodicCheck(); + num_events = 0; + osaf_clock_gettime(CLOCK_MONOTONIC, &last); + } } done: -- 2.25.1 _______________________________________________ Opensaf-devel mailing list Opensaf-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/opensaf-devel