OpenMPI  0.1.1
notifier_event_calls.h
1 /*
2  * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
3  * University Research and Technology
4  * Corporation. All rights reserved.
5  * Copyright (c) 2004-2005 The University of Tennessee and The University
6  * of Tennessee Research Foundation. All rights
7  * reserved.
8  * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
9  * University of Stuttgart. All rights reserved.
10  * Copyright (c) 2004-2005 The Regents of the University of California.
11  * All rights reserved.
12  * Copyright (c) 2009 Bull SAS. All rights reserved.
13  * $COPYRIGHT$
14  *
15  * Additional copyrights may follow
16  *
17  * $HEADER$
18  */
19 
20 #ifndef ORTE_NOTIFIER_EVENTS_CALLS_H
21 #define ORTE_NOTIFIER_EVENTS_CALLS_H
22 
23 #include "orte_config.h"
24 
25 #ifdef HAVE_STDIO_H
26 #include <stdio.h>
27 #endif /* HAVE_STDIO_H */
28 #ifdef HAVE_SYS_TIME_H
29 #include <sys/time.h>
30 #endif /* HAVE_SYS_TIME_H */
31 
32 #include "opal/class/opal_object.h"
33 
34 BEGIN_C_DECLS
35 
36 
37 
38 #define ORTE_NOTIFIER_LOG_0 0 /* Initial log format needed (no delay) */
39 #define ORTE_NOTIFIER_LOG_1 1 /* Intermediate log format needed (delay) */
40 #define ORTE_NOTIFIER_LOG_2 2 /* Final log format needed (at finalize) */
41 
42 ORTE_DECLSPEC bool notifier_log_event_enabled(void);
43 ORTE_DECLSPEC void notifier_event_store(orte_notifier_event_t *);
44 ORTE_DECLSPEC void notifier_trace_event(int, int, int32_t, time_t, time_t,
45  const char *);
46 
47 
48 /*
49  * Do not use this function directly: use ORTE_NOTIFIER_DEFINE_EVENT() instead
50  */
51 static inline orte_notifier_event_t *notifier_alloc_event(int ev_id,
52  const char *msg)
53 {
55 
56  ev = OBJ_NEW(orte_notifier_event_t);
57  if (NULL == ev) {
58  return NULL;
59  }
60  asprintf(&ev->ev_msg, msg);
61  if (NULL == ev->ev_msg) {
62  OBJ_RELEASE(ev);
63  return NULL;
64  }
65  ev->ev_id = ev_id;
66  /*
67  * Store the allocated event into a list to be able to manage the
68  * unconditional event tracing and freeing during finalize.
69  */
70  notifier_event_store(ev);
71  return ev;
72 }
73 
74 
75 static inline void notifier_count_and_log_event(orte_notifier_event_t *ev,
76  int ev_id,
77  int cnt_thresh,
78  int time_thresh)
79 {
80  time_t now, delay;
81  int32_t count;
82 
83  opal_atomic_add_32(&ev->ev_cnt, 1);
84  if (ev->ev_cnt <= cnt_thresh) {
85  return;
86  }
87 
88  count = ev->ev_cnt;
89  now = time(NULL);
90  if (ev->ev_already_traced) {
91  if (now > ev->ev_time_trc + time_thresh) {
92  delay = now - ev->ev_time_trc;
93  ev->ev_cnt = 0;
94  ev->ev_time_trc = now;
95  notifier_trace_event(ORTE_NOTIFIER_LOG_1, ev_id, count, now, delay,
96  ev->ev_msg);
97  }
98  } else {
99  ev->ev_already_traced = 1;
100  ev->ev_cnt = 0;
101  ev->ev_time_trc = now;
102  /* We don't care about the delay for the very 1st trace */
103  notifier_trace_event(ORTE_NOTIFIER_LOG_0, ev_id, count, now, now,
104  ev->ev_msg);
105  }
106 }
107 
108 
109 #define notifier_event_fn_prefix(i) notifier_log_event_ ## i
110 
111 /*
112  * This macro should be called each time a new event will be traced.
113  * It expands to a static inline function suffixed by the event number.
114  */
115 #define ORTE_NOTIFIER_DEFINE_EVENT(i, m) \
116  static inline void notifier_event_fn_prefix(i) (int c_thr, int t_thr) \
117  { \
118  static orte_notifier_event_t *prefix_ ## i = NULL; \
119  if (!notifier_log_event_enabled()) { \
120  return; \
121  } \
122  if (NULL == prefix_ ## i) { \
123  prefix_ ## i = notifier_alloc_event(i, m); \
124  if (NULL == prefix_ ## i) { \
125  return; \
126  } \
127  } \
128  notifier_count_and_log_event(prefix_ ## i, i, c_thr, t_thr); \
129  }
130 
131 /*
132  * This is the log interface that should be called whenever an unsual event
133  * should be warned about.
134  * The event should have been defined before, using
135  * ORTE_NOTIFIER_DEFINE_EVENT():
136  *
137  * (1) Event definition:
138  *
139  * Typically in a header file call the following:
140  * ORTE_NOTIFIER_DEFINE_EVENT(0, "message 0")
141  * This macro expands to
142  * static inline void notifier_log_event_0(int c_thr, int t_thr)
143  * {
144  * static orte_notifier_event_t *prefix_0 = NULL;
145  * if (!notifier_log_event_enabled()) {
146  * return;
147  * }
148  * if (NULL == prefix_0) {
149  * prefix_0 = notifier_alloc_event(0, "message 0");
150  * if (NULL == prefix_0) {
151  * return;
152  * }
153  * }
154  * notifier_count_and_log_event(prefix_0, 0, c_thr, t_thr);
155  * }
156  *
157  * (2) Event accounting and tracing:
158  *
159  * Whenever you want to trace the unusual event whose id is 0, just call:
160  * ORTE_NOTIFIER_LOG_EVENT(0, 100, 1);
161  * 100 and 1 are respectively the counter and time thresholds.
162  * This actually expands to
163  * notifier_log_event_0(100, 1);
164  */
165 #define ORTE_NOTIFIER_LOG_EVENT(i, c, t) notifier_event_fn_prefix(i) (c, t)
166 
167 
168 END_C_DECLS
169 
170 #endif /* ORTE_NOTIFIER_EVENT_CALLS_H */
#define OBJ_RELEASE(object)
Release an object (by decrementing its reference count).
Definition: opal_object.h:324
Definition: notifier_event_types.h:36
A simple C-language object-oriented system with single inheritance and ownership-based memory managem...