1
/* $Header: /tmp/hpctools/ga/tcgmsg/ipcv5.0/evlog.c,v 1.3 2003-06-27 13:53:12 manoj Exp $ */
3
/* Event logging routine with key driven varargs interface */
16
#if defined(ALLIANT) || defined(ENCORE) || defined(SEQUENT) || \
17
defined(CONVEX) || defined(ARDENT) || defined(ULTRIX) || \
18
defined(AIX) || defined(IPSC) || defined(NEXT) || defined(DECOSF)
19
extern char *strdup();
22
#if defined(ULTRIX) || defined(SGI) || defined(NEXT) || defined(KSR) || \
24
extern void *malloc();
26
extern char *malloc();
31
static double walltime();
33
/* If sprintf returns an integer instead of a character pointer
34
then define the flag INTSPRINTF */
36
#if defined(SGI) || defined(AIX) || defined(IPSC) || defined(CRAY) || \
37
defined(HPUX) || defined(ALLIANT) || defined(CONVEX) || defined(NEXT) || \
38
defined(KSR) || defined(DECOSF)
42
void evlog(int farg_key, ...)
44
The format of the argument list is as follows:
46
evlog([(int) key, [values, ...]], ..., EVKEY_LAST_ARG)
48
Arguments are read as keys with corresponding values. Recognised keys
49
are defined in evlog.h and are described in detail below.
51
Logging is enabled/disabled by calling evlog with one of EVKEY_ENABLE
52
or EVKEY_DISABLE specified. Note that EVKEY_ENABLE must be the
53
first key specified for it to be recognized and that all keys
54
in the argument list after EVKEY_DISABLE are ignored. By default
55
events are logged in the file events. This can be overridden with
56
the key EVKEY_FILENAME, which takes the filename as its value.
58
The model for logging events assumed by the post-analysis routines
59
assumes that upon logging an event:
61
a) no state chage occurs (EVKEY_EVENT). The event is just recorded.
63
b) the process changes state by pushing the event onto the state stack
66
c) the process changes state by popping an event off the state stack
67
(EVKEY_END). If the event or state popped off the stack does not
68
match the specified event then the post-analysis may get confused
69
but this does not interfere with the actual logging.
71
EVKEY_EVENT, EVKEY_BEGIN or EVKEY_END must be the first key specified other
72
than a possible EVKEY_ENABLE.
74
Internally an event is stored as a large character string to simplify
75
post-analysis. Users specify data for storage in addition to
76
that which is automatically stored (only the time and process) with
77
key, value combinations (EVKEY_STR_INT, EVKEY_STR_DBL, EVKEY_STR).
78
Many such key-value combinations as required may be specified.
79
Since the internal data format uses colons ':', double quotation
80
marks '"' and carriage returns users should avoid these in their
83
----------------------------
84
Sample calling sequence:
86
evlog(EVKEY_ENABLE, EVKEY_FILENAME, "events.log", EVKEY_LAST_ARG);
89
evlog(EVKEY_EVENT, "Finished startup code",
90
EVKEY_STR, "Now do some real work",
93
evlog(EVKEY_BEGIN, "Get Matrix", EVKEY_LAST_ARG);
96
evlog(EVKEY_END, "Get matrix",
97
EVKEY_STR_INT, "Size of matrix", (int) N,
98
EVKEY_STR_DBL, "Norm of matrix", (double) matrix_norm,
101
evlog(EVKEY_BEGIN, "Transform matrix",
102
EVKEY_STR_DBL, "Recomputed norm", (double) matrix_norm,
106
evlog(EVKEY_END, "Transform matrix",
107
EVKEY_STR_INT, "No. of iterations", (int) niters,
110
evlog(EVKEY_DUMP, EVKEY_DISABLE, EVKEY_LAST_ARG);
112
evlog(EVKEY_EVENT, "Logging is disabled ... this should not print",
113
EVKEY_DUMP, EVKEY_LAST_ARG);
115
----------------------------
118
Terminates list ... takes no value and must be present
120
EVKEY_EVENT, (char *) event
121
Simply log occurence of the event
123
EVKEY_BEGIN, (char *) event
124
Push event onto process state stack
126
EVKEY_END, (char *) event
127
Pop event off process state stack
129
EVKEY_MSG_LEN, (int) length
130
Value is (int) mesage length SND/RCV only
132
EVKEY_MSG_TO, (int) to
133
Value is (int) to process id SND/RCV only
135
EVKEY_MSG_FROM, (int) from
136
Value is (int) from process SND/RCV only
138
EVKEY_MSG_TYPE, (int) type
139
Value is (int) message type SND/RCV only
141
EVKEY_STR_INT, (char *) string, (int) data
144
EVKEY_STR_DBL, (char *) string, (double) data
145
User data value pair (char *), (double)
147
EVKEY_STR, (char *) string
148
User data value (char *)
157
Dump out the current buffer to disk
159
EVKEY_FILE, (char *) filename
160
Use specified file to capture events. Default is "events".
163
static int logging=0; /* Boolean flag for login enabled/disabled */
164
static int error=0; /* Boolean flag for error detected */
165
static int ncall=0; /* Need to do stuff on first entry */
166
static char *buffer; /* Logging buffer ... null terminated */
167
static char *bufpt; /* Pointer to next free char in buffer */
168
static int left; /* Amount of free space in buffer */
169
#define BUFLEN 262144 /* Size allocated for buffer ... biggish */
170
#define MAX_EV_LEN 1000 /* Assumed maximum size of single event record */
171
static FILE *file; /* File where events will be dumped */
172
static char *filename = "events"; /* Default name of events file */
174
va_list ap; /* For variable argument list */
175
int key; /* Hold key being processed */
176
int nchars; /* No. of chars printed by sprintf call */
177
char *temp; /* Temporary copy of bufpt */
178
char *string; /* Temporary */
179
int integer; /* Temporary */
180
double dbl; /* Temporary */
181
int valid; /* Temporary */
183
#define ERROR_RETURN error = 1; return;
185
#define DUMPBUF (void) fputs(buffer, file); \
186
(void) fflush(file);\
187
if(ferror(file)) {ERROR_RETURN} \
188
bufpt = buffer; left = BUFLEN;
190
sprintf is a disaster area!!!!
192
#define RECORD(A) nchars = (A); bufpt += nchars; left -= nchars
194
#define RECORD(A) nchars = strlen(A); bufpt += nchars; left -= nchars
197
#define RECORD(A) {A; nchars = strlen(bufpt); bufpt += nchars; left -= nchars;}
200
/* If an error was detected on a previous call don't even try to
203
if (error) {ERROR_RETURN}
205
/* First time in need to allocate the buffer, open the file etc */
209
if (!(bufpt = buffer = malloc((unsigned) BUFLEN))) {ERROR_RETURN}
212
if (!(file = fopen(filename, "w"))) {ERROR_RETURN}
215
/* Parse the arguments */
217
temp = bufpt; /* Save to check if anything has been logged */
218
valid = 0; /* One of BEGIN, END or EVENT must preceed most keys */
220
va_start(ap, farg_key);
222
while (key != EVKEY_LAST_ARG) {
224
if ( (!logging) && (key != EVKEY_ENABLE) )
239
if (!(filename = strdup(va_arg(ap, char *))))
241
if (!(file = freopen(filename, "w", file))) {ERROR_RETURN}
246
RECORD(sprintf(bufpt, ":BEGIN:%s", va_arg(ap, char *)));
247
RECORD(sprintf(bufpt, ":TIME:%.2f", walltime()));
252
RECORD(sprintf(bufpt, ":END:%s", va_arg(ap, char *)));
253
RECORD(sprintf(bufpt, ":TIME:%.2f", walltime()));
258
RECORD(sprintf(bufpt, ":EVENT:%s", va_arg(ap, char *)));
259
RECORD(sprintf(bufpt, ":TIME:%.2f", walltime()));
263
if (!valid) {ERROR_RETURN}
264
RECORD(sprintf(bufpt, ":MSG_LEN:%d", va_arg(ap, int)));
268
if (!valid) {ERROR_RETURN}
269
RECORD(sprintf(bufpt, ":MSG_TO:%d", va_arg(ap, int)));
273
if (!valid) {ERROR_RETURN}
274
RECORD(sprintf(bufpt, ":MSG_FROM:%d", va_arg(ap, int)));
278
if (!valid) {ERROR_RETURN}
279
RECORD(sprintf(bufpt, ":MSG_TYPE:%d", va_arg(ap, int)));
283
if (!valid) {ERROR_RETURN}
284
RECORD(sprintf(bufpt, ":MSG_SYNC:%d", va_arg(ap, int)));
288
if (!valid) {ERROR_RETURN}
289
string = va_arg(ap, char *);
290
integer = va_arg(ap, int);
291
RECORD(sprintf(bufpt, ":STR_INT:%s:%d", string, integer));
295
if (!valid) {ERROR_RETURN}
296
string = va_arg(ap, char *);
297
dbl = va_arg(ap, double);
298
RECORD(sprintf(bufpt, ":STR_DBL:%s:%g", string, dbl));
302
if (!valid) {ERROR_RETURN}
303
RECORD(sprintf(bufpt, ":STR:%s", va_arg(ap, char *)));
309
RECORD(sprintf(bufpt, "\n"));
318
key = va_arg(ap, int);
324
/* Put a linefeed on the end of the record if something is written */
327
RECORD(sprintf(bufpt, "\n"));
331
/* Should really check on every access to the buffer that there is
332
enough space ... however just assume a very large maximum size
333
for a single event log entry and check here */
338
if (left < MAX_EV_LEN)
344
static double walltime()
346
return the wall time in seconds as a double
349
return ((double) MTIME_()) * 0.01;
356
double matrix_norm = 99.1;
359
evlog(EVKEY_ENABLE, EVKEY_FILENAME, "events.log", EVKEY_LAST_ARG);
362
evlog(EVKEY_EVENT, "Finished startup code",
363
EVKEY_STR, "Now do some real work",
366
evlog(EVKEY_BEGIN, "Get Matrix", EVKEY_LAST_ARG);
369
evlog(EVKEY_END, "Get matrix",
370
EVKEY_STR_INT, "Size of matrix", (int) N,
371
EVKEY_STR_DBL, "Norm of matrix", (double) matrix_norm,
374
evlog(EVKEY_BEGIN, "Transform matrix",
375
EVKEY_STR_DBL, "Recomputed norm", (double) matrix_norm,
379
evlog(EVKEY_END, "Transform matrix",
380
EVKEY_STR_INT, "No. of iterations", (int) niters,
383
evlog(EVKEY_DUMP, EVKEY_LAST_ARG);
385
evlog(EVKEY_EVENT, "Logging is disabled ... this should not print",
386
EVKEY_DUMP, EVKEY_LAST_ARG);