/* * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana * University Research and Technology * Corporation. All rights reserved. * Copyright (c) 2004-2005 The University of Tennessee and The University * of Tennessee Research Foundation. All rights * reserved. * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, * University of Stuttgart. All rights reserved. * Copyright (c) 2004-2005 The Regents of the University of California. * All rights reserved. * Copyright (c) 2009 Bull SAS. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow * * $HEADER$ */ #ifndef ORTE_NOTIFIER_EVENTS_CALLS_H #define ORTE_NOTIFIER_EVENTS_CALLS_H #include "orte_config.h" #ifdef HAVE_STDIO_H #include #endif /* HAVE_STDIO_H */ #ifdef HAVE_SYS_TIME_H #include #endif /* HAVE_SYS_TIME_H */ #include "opal/class/opal_object.h" BEGIN_C_DECLS #define ORTE_NOTIFIER_LOG_0 0 /* Initial log format needed (no delay) */ #define ORTE_NOTIFIER_LOG_1 1 /* Intermediate log format needed (delay) */ #define ORTE_NOTIFIER_LOG_2 2 /* Final log format needed (at finalize) */ ORTE_DECLSPEC bool notifier_log_event_enabled(void); ORTE_DECLSPEC void notifier_event_store(orte_notifier_event_t *); ORTE_DECLSPEC void notifier_trace_event(int, int, int32_t, time_t, time_t, const char *); /* * Do not use this function directly: use ORTE_NOTIFIER_DEFINE_EVENT() instead */ static inline orte_notifier_event_t *notifier_alloc_event(int ev_id, const char *msg) { orte_notifier_event_t *ev; ev = OBJ_NEW(orte_notifier_event_t); if (NULL == ev) { return NULL; } asprintf(&ev->ev_msg, msg); if (NULL == ev->ev_msg) { OBJ_RELEASE(ev); return NULL; } ev->ev_id = ev_id; /* * Store the allocated event into a list to be able to manage the * unconditional event tracing and freeing during finalize. */ notifier_event_store(ev); return ev; } static inline void notifier_count_and_log_event(orte_notifier_event_t *ev, int ev_id, int cnt_thresh, int time_thresh) { time_t now, delay; int32_t count; opal_atomic_add_32(&ev->ev_cnt, 1); if (ev->ev_cnt <= cnt_thresh) { return; } count = ev->ev_cnt; now = time(NULL); if (ev->ev_already_traced) { if (now > ev->ev_time_trc + time_thresh) { delay = now - ev->ev_time_trc; ev->ev_cnt = 0; ev->ev_time_trc = now; notifier_trace_event(ORTE_NOTIFIER_LOG_1, ev_id, count, now, delay, ev->ev_msg); } } else { ev->ev_already_traced = 1; ev->ev_cnt = 0; ev->ev_time_trc = now; /* We don't care about the delay for the very 1st trace */ notifier_trace_event(ORTE_NOTIFIER_LOG_0, ev_id, count, now, now, ev->ev_msg); } } #define notifier_event_fn_prefix(i) notifier_log_event_ ## i /* * This macro should be called each time a new event will be traced. * It expands to a static inline function suffixed by the event number. */ #define ORTE_NOTIFIER_DEFINE_EVENT(i, m) \ static inline void notifier_event_fn_prefix(i) (int c_thr, int t_thr) \ { \ static orte_notifier_event_t *prefix_ ## i = NULL; \ if (!notifier_log_event_enabled()) { \ return; \ } \ if (NULL == prefix_ ## i) { \ prefix_ ## i = notifier_alloc_event(i, m); \ if (NULL == prefix_ ## i) { \ return; \ } \ } \ notifier_count_and_log_event(prefix_ ## i, i, c_thr, t_thr); \ } /* * This is the log interface that should be called whenever an unsual event * should be warned about. * The event should have been defined before, using * ORTE_NOTIFIER_DEFINE_EVENT(): * * (1) Event definition: * * Typically in a header file call the following: * ORTE_NOTIFIER_DEFINE_EVENT(0, "message 0") * This macro expands to * static inline void notifier_log_event_0(int c_thr, int t_thr) * { * static orte_notifier_event_t *prefix_0 = NULL; * if (!notifier_log_event_enabled()) { * return; * } * if (NULL == prefix_0) { * prefix_0 = notifier_alloc_event(0, "message 0"); * if (NULL == prefix_0) { * return; * } * } * notifier_count_and_log_event(prefix_0, 0, c_thr, t_thr); * } * * (2) Event accounting and tracing: * * Whenever you want to trace the unusual event whose id is 0, just call: * ORTE_NOTIFIER_LOG_EVENT(0, 100, 1); * 100 and 1 are respectively the counter and time thresholds. * This actually expands to * notifier_log_event_0(100, 1); */ #define ORTE_NOTIFIER_LOG_EVENT(i, c, t) notifier_event_fn_prefix(i) (c, t) END_C_DECLS #endif /* ORTE_NOTIFIER_EVENT_CALLS_H */