1 /*
2  * Copyright (C) by Argonne National Laboratory
3  *     See COPYRIGHT in top-level directory
4  */
5 
6 #include "trace_impl.h"
7 #include "rlog.h"
8 #ifdef HAVE_STDLIB_H
9 #include <stdlib.h>
10 #endif
11 #ifdef HAVE_CTYPE_H
12 #include <ctype.h>
13 #endif
14 #ifdef HAVE_STRING_H
15 #include <string.h>
16 #endif
17 #include "trace_API.h"
18 #include "mpir_mem.h"
19 
20 #define TRACEINPUT_SUCCESS 0
21 #define TRACEINPUT_FAIL    -1
22 
23 #define INVALID_EVENT -1
24 
25 typedef struct _trace_file {
26     RLOG_IOStruct *pInput;
27     RLOG_STATE state;
28     RLOG_ARROW arrow;
29     RLOG_BOOL bArrowAvail;
30     RLOG_EVENT **ppEvent;
31     RLOG_BOOL **ppEventAvail;
32 } _trace_file;
33 
PackQuadChar(char * str,int * length,char * base,int * pos,const int max)34 RLOG_BOOL PackQuadChar(char *str, int *length, char *base, int *pos, const int max)
35 {
36     /* Am I supposed to include the terminating NULL character? */
37     /* This function does not. */
38     if (*pos + (int) strlen(str) > max)
39         return FALSE;
40     *length = strlen(str);
41     memcpy(&base[*pos], str, *length);
42     *pos += *length;
43     return TRUE;
44 }
45 
PackQuadInt(int n1,int n2,int * length,int * base,int * pos,const int max)46 RLOG_BOOL PackQuadInt(int n1, int n2, int *length, int *base, int *pos, const int max)
47 {
48     if (*pos + 2 > max)
49         return FALSE;
50     *length = 2;
51     base[*pos] = n1;
52     base[*pos + 1] = n2;
53     *pos += 2;
54     return TRUE;
55 }
56 
PackQuadDouble(double d1,double d2,int * length,double * base,int * pos,const int max)57 RLOG_BOOL PackQuadDouble(double d1, double d2, int *length, double *base, int *pos, const int max)
58 {
59     if (*pos + 2 > max)
60         return FALSE;
61     *length = 2;
62     base[*pos] = d1;
63     base[*pos + 1] = d2;
64     *pos += 2;
65     return TRUE;
66 }
67 
TRACE_Open(const char filespec[],TRACE_file * fp)68 TRACE_EXPORT int TRACE_Open(const char filespec[], TRACE_file * fp)
69 {
70     int i, j;
71     RLOG_IOStruct *pInput;
72 
73     if (filespec == NULL || fp == NULL)
74         return TRACEINPUT_FAIL;
75 
76     if (strcmp(filespec, "-h") == 0) {
77         *fp = NULL;
78         return TRACEINPUT_SUCCESS;
79     }
80 
81     *fp = (_trace_file *) MPL_malloc(sizeof(_trace_file), MPL_MEM_DEBUG);
82     if (*fp == NULL)
83         return TRACEINPUT_FAIL;
84 
85     (*fp)->pInput = pInput = RLOG_CreateInputStruct(filespec);
86     if (pInput == NULL) {
87         MPL_free(*fp);
88         *fp = NULL;
89         return TRACEINPUT_FAIL;
90     }
91 
92     (*fp)->bArrowAvail = (RLOG_GetNextArrow(pInput, &(*fp)->arrow) == 0);
93     if (pInput->nNumRanks > 0) {
94         (*fp)->ppEvent =
95             (RLOG_EVENT **) MPL_malloc(sizeof(RLOG_EVENT *) * pInput->nNumRanks, MPL_MEM_DEBUG);
96         (*fp)->ppEventAvail = (int **) MPL_malloc(sizeof(int *) * pInput->nNumRanks, MPL_MEM_DEBUG);
97 
98         for (i = 0; i < pInput->nNumRanks; i++) {
99             if (pInput->pNumEventRecursions[i] > 0) {
100                 (*fp)->ppEvent[i] =
101                     (RLOG_EVENT *) MPL_malloc(sizeof(RLOG_EVENT) * pInput->pNumEventRecursions[i],
102                                               MPL_MEM_DEBUG);
103                 (*fp)->ppEventAvail[i] =
104                     (int *) MPL_malloc(sizeof(int) * pInput->pNumEventRecursions[i], MPL_MEM_DEBUG);
105             } else {
106                 (*fp)->ppEvent[i] = NULL;
107                 (*fp)->ppEventAvail[i] = NULL;
108             }
109         }
110     } else {
111         (*fp)->ppEvent = NULL;
112         (*fp)->ppEventAvail = NULL;
113     }
114     for (j = 0; j < pInput->nNumRanks; j++) {
115         for (i = 0; i < pInput->pNumEventRecursions[j]; i++) {
116             (*fp)->ppEventAvail[j][i] =
117                 (RLOG_GetNextEvent(pInput, j + pInput->header.nMinRank, i, &(*fp)->ppEvent[j][i]) ==
118                  0);
119         }
120     }
121     return TRACEINPUT_SUCCESS;
122 }
123 
TRACE_Close(TRACE_file * fp)124 TRACE_EXPORT int TRACE_Close(TRACE_file * fp)
125 {
126     int i;
127 
128     if (*fp == NULL)
129         return TRACEINPUT_SUCCESS;
130 
131     if ((*fp)->pInput) {
132         for (i = 0; i < (*fp)->pInput->nNumRanks; i++) {
133             MPL_free((*fp)->ppEvent[i]);
134             MPL_free((*fp)->ppEventAvail[i]);
135         }
136         RLOG_CloseInputStruct(&(*fp)->pInput);
137     }
138     MPL_free((*fp)->ppEvent);
139     MPL_free((*fp)->ppEventAvail);
140     MPL_free((*fp));
141     *fp = NULL;
142 
143     return TRACEINPUT_SUCCESS;
144 }
145 
TRACE_Peek_next_kind(const TRACE_file fp,TRACE_Rec_Kind_t * next_kind)146 TRACE_EXPORT int TRACE_Peek_next_kind(const TRACE_file fp, TRACE_Rec_Kind_t * next_kind)
147 {
148     int i, j;
149 
150     *next_kind = TRACE_EOF;
151     if (fp->pInput->nCurState < fp->pInput->nNumStates) {
152         *next_kind = TRACE_CATEGORY;
153         return TRACEINPUT_SUCCESS;
154     }
155 
156     for (j = 0; j < fp->pInput->nNumRanks; j++) {
157         for (i = 0; i < fp->pInput->pNumEventRecursions[j]; i++) {
158             if (fp->ppEventAvail[j][i]) {
159                 *next_kind = TRACE_PRIMITIVE_DRAWABLE;
160                 return TRACEINPUT_SUCCESS;
161             }
162         }
163     }
164     if (fp->bArrowAvail) {
165         *next_kind = TRACE_PRIMITIVE_DRAWABLE;
166         return TRACEINPUT_SUCCESS;
167     }
168 
169     return TRACEINPUT_SUCCESS;
170 }
171 
TRACE_Get_next_method(const TRACE_file fp,char method_name[],char method_extra[],int * methodID)172 TRACE_EXPORT int TRACE_Get_next_method(const TRACE_file fp,
173                                        char method_name[], char method_extra[], int *methodID)
174 {
175     return TRACEINPUT_FAIL;
176 }
177 
TRACE_Peek_next_category(const TRACE_file fp,int * n_legend,int * n_label,int * n_methodIDs)178 TRACE_EXPORT int TRACE_Peek_next_category(const TRACE_file fp,
179                                           int *n_legend, int *n_label, int *n_methodIDs)
180 {
181     if (fp->pInput->nCurState >= fp->pInput->nNumStates)
182         return TRACEINPUT_FAIL;
183 
184     if (RLOG_GetNextState(fp->pInput, &fp->state) != 0)
185         return TRACEINPUT_FAIL;
186     *n_legend = strlen(fp->state.description) + 1;
187     *n_label = 0;
188     *n_methodIDs = 0;
189 
190     return TRACEINPUT_SUCCESS;
191 }
192 
TRACE_Get_next_category(const TRACE_file fp,TRACE_Category_head_t * head,int * n_legend,char legend_base[],int * legend_pos,const int legend_max,int * n_label,char label_base[],int * label_pos,const int label_max,int * n_methodIDs,int methodID_base[],int * methodID_pos,const int methodID_max)193 TRACE_EXPORT int TRACE_Get_next_category(const TRACE_file fp,
194                                          TRACE_Category_head_t * head,
195                                          int *n_legend, char legend_base[],
196                                          int *legend_pos, const int legend_max,
197                                          int *n_label, char label_base[],
198                                          int *label_pos, const int label_max,
199                                          int *n_methodIDs, int methodID_base[],
200                                          int *methodID_pos, const int methodID_max)
201 {
202     char *pColorStr = fp->state.color;
203 
204     head->index = fp->state.event;
205     while (isspace(*pColorStr))
206         pColorStr++;
207     head->red = atoi(pColorStr);
208     while (!isspace(*pColorStr))
209         pColorStr++;
210     while (isspace(*pColorStr))
211         pColorStr++;
212     head->green = atoi(pColorStr);
213     while (!isspace(*pColorStr))
214         pColorStr++;
215     while (isspace(*pColorStr))
216         pColorStr++;
217     head->blue = atoi(pColorStr);
218     head->alpha = 255;
219     if (fp->state.event == RLOG_ARROW_EVENT_ID)
220         head->shape = TRACE_SHAPE_ARROW;
221     else
222         head->shape = TRACE_SHAPE_STATE;
223     head->width = 1;
224 
225     if (!PackQuadChar(fp->state.description, n_legend, legend_base, legend_pos, legend_max))
226         return TRACEINPUT_FAIL;
227 
228     *n_label = 0;
229     *n_methodIDs = 0;
230 
231     return TRACEINPUT_SUCCESS;
232 }
233 
TRACE_Peek_next_ycoordmap(TRACE_file fp,int * n_rows,int * n_columns,int * max_column_name,int * max_title_name,int * n_methodIDs)234 TRACE_EXPORT int TRACE_Peek_next_ycoordmap(TRACE_file fp,
235                                            int *n_rows, int *n_columns,
236                                            int *max_column_name,
237                                            int *max_title_name, int *n_methodIDs)
238 {
239     return TRACEINPUT_FAIL;
240 }
241 
TRACE_Get_next_ycoordmap(TRACE_file fp,char * title_name,char ** column_names,int * coordmap_sz,int coordmap_base[],int * coordmap_pos,const int coordmap_max,int * n_methodIDs,int methodID_base[],int * methodID_pos,const int methodID_max)242 TRACE_EXPORT int TRACE_Get_next_ycoordmap(TRACE_file fp,
243                                           char *title_name,
244                                           char **column_names,
245                                           int *coordmap_sz, int coordmap_base[],
246                                           int *coordmap_pos, const int coordmap_max,
247                                           int *n_methodIDs, int methodID_base[],
248                                           int *methodID_pos, const int methodID_max)
249 {
250     return TRACEINPUT_FAIL;
251 }
252 
TRACE_Peek_next_primitive(const TRACE_file fp,double * starttime,double * endtime,int * n_tcoords,int * n_ycoords,int * n_bytes)253 TRACE_EXPORT int TRACE_Peek_next_primitive(const TRACE_file fp,
254                                            double *starttime, double *endtime,
255                                            int *n_tcoords, int *n_ycoords, int *n_bytes)
256 {
257     int i, j, rank = -1, level = -1;
258     double dmin;
259     RLOG_BOOL done = FALSE;
260 
261     *n_tcoords = 2;
262     *n_ycoords = 2;
263     *n_bytes = 0;
264 
265     for (j = 0; j < fp->pInput->nNumRanks && !done; j++) {
266         for (i = 0; i < fp->pInput->pNumEventRecursions[j] && !done; i++) {
267             if (fp->ppEventAvail[j][i]) {
268                 level = i;
269                 rank = j;
270                 dmin = fp->ppEvent[j][i].end_time;
271                 done = TRUE;
272             }
273         }
274     }
275     if (level == -1) {
276         if (!fp->bArrowAvail)
277             return TRACEINPUT_FAIL;
278         *starttime = fp->arrow.start_time;
279         *endtime = fp->arrow.end_time;
280         return TRACEINPUT_SUCCESS;
281     }
282     for (j = 0; j < fp->pInput->nNumRanks; j++) {
283         for (i = 0; i < fp->pInput->pNumEventRecursions[j]; i++) {
284             if (fp->ppEventAvail[j][i]) {
285                 if (fp->ppEvent[j][i].end_time < dmin) {
286                     level = i;
287                     rank = j;
288                     dmin = fp->ppEvent[j][i].end_time;
289                 }
290             }
291         }
292     }
293     if (fp->bArrowAvail) {
294         if (fp->arrow.end_time < dmin) {
295             *starttime = fp->arrow.start_time;
296             *endtime = fp->arrow.end_time;
297             return TRACEINPUT_SUCCESS;
298         }
299     }
300     *starttime = fp->ppEvent[rank][level].start_time;
301     *endtime = fp->ppEvent[rank][level].end_time;
302 
303     return TRACEINPUT_SUCCESS;
304 }
305 
TRACE_Get_next_primitive(const TRACE_file fp,int * category_index,int * n_tcoords,double tcoord_base[],int * tcoord_pos,const int tcoord_max,int * n_ycoords,int ycoord_base[],int * ycoord_pos,const int ycoord_max,int * n_bytes,char byte_base[],int * byte_pos,const int byte_max)306 TRACE_EXPORT int TRACE_Get_next_primitive(const TRACE_file fp,
307                                           int *category_index,
308                                           int *n_tcoords, double tcoord_base[],
309                                           int *tcoord_pos, const int tcoord_max,
310                                           int *n_ycoords, int ycoord_base[],
311                                           int *ycoord_pos, const int ycoord_max,
312                                           int *n_bytes, char byte_base[],
313                                           int *byte_pos, const int byte_max)
314 {
315     int i, j, rank = 1, level = -1;
316     double dmin;
317     RLOG_BOOL done = FALSE;
318 
319     *n_bytes = 0;
320 
321     for (j = 0; j < fp->pInput->nNumRanks; j++) {
322         for (i = 0; i < fp->pInput->pNumEventRecursions[j]; i++) {
323             if (fp->ppEventAvail[j][i]) {
324                 level = i;
325                 rank = j;
326                 dmin = fp->ppEvent[j][i].end_time;
327                 break;
328             }
329         }
330     }
331     if (level == -1) {
332         if (!fp->bArrowAvail)
333             return TRACEINPUT_FAIL;
334         *category_index = RLOG_ARROW_EVENT_ID;
335         if (fp->arrow.leftright == RLOG_ARROW_RIGHT) {
336             PackQuadDouble(fp->arrow.start_time,
337                            fp->arrow.end_time, n_tcoords, tcoord_base, tcoord_pos, tcoord_max);
338         } else {
339             PackQuadDouble(fp->arrow.end_time,
340                            fp->arrow.start_time, n_tcoords, tcoord_base, tcoord_pos, tcoord_max);
341         }
342         PackQuadInt(fp->arrow.src, fp->arrow.dest, n_ycoords, ycoord_base, ycoord_pos, ycoord_max);
343         fp->bArrowAvail = (RLOG_GetNextArrow(fp->pInput, &fp->arrow) == 0);
344         return TRACEINPUT_SUCCESS;
345     }
346     for (j = 0; j < fp->pInput->nNumRanks; j++) {
347         for (i = 0; i < fp->pInput->pNumEventRecursions[j]; i++) {
348             if (fp->ppEventAvail[j][i]) {
349                 if (fp->ppEvent[j][i].end_time < dmin) {
350                     level = i;
351                     rank = j;
352                     dmin = fp->ppEvent[j][i].end_time;
353                 }
354             }
355         }
356     }
357     if (fp->bArrowAvail) {
358         if (fp->arrow.end_time < dmin) {
359             *category_index = RLOG_ARROW_EVENT_ID;
360             if (fp->arrow.leftright == RLOG_ARROW_RIGHT) {
361                 PackQuadDouble(fp->arrow.start_time,
362                                fp->arrow.end_time, n_tcoords, tcoord_base, tcoord_pos, tcoord_max);
363             } else {
364                 PackQuadDouble(fp->arrow.end_time,
365                                fp->arrow.start_time,
366                                n_tcoords, tcoord_base, tcoord_pos, tcoord_max);
367             }
368             PackQuadInt(fp->arrow.src,
369                         fp->arrow.dest, n_ycoords, ycoord_base, ycoord_pos, ycoord_max);
370             fp->bArrowAvail = (RLOG_GetNextArrow(fp->pInput, &fp->arrow) == 0);
371             return TRACEINPUT_SUCCESS;
372         }
373     }
374     *category_index = fp->ppEvent[rank][level].event;
375     PackQuadDouble(fp->ppEvent[rank][level].start_time,
376                    fp->ppEvent[rank][level].end_time,
377                    n_tcoords, tcoord_base, tcoord_pos, tcoord_max);
378     PackQuadInt(fp->ppEvent[rank][level].rank,
379                 fp->ppEvent[rank][level].rank, n_ycoords, ycoord_base, ycoord_pos, ycoord_max);
380     fp->ppEventAvail[rank][level] =
381         (RLOG_GetNextEvent(fp->pInput,
382                            rank + fp->pInput->header.nMinRank,
383                            level, &fp->ppEvent[rank][level]) == 0);
384 
385     return TRACEINPUT_SUCCESS;
386 }
387 
TRACE_Peek_next_composite(const TRACE_file fp,double * starttime,double * endtime,int * n_primitives,int * n_bytes)388 TRACE_EXPORT int TRACE_Peek_next_composite(const TRACE_file fp,
389                                            double *starttime, double *endtime,
390                                            int *n_primitives, int *n_bytes)
391 {
392     return TRACEINPUT_FAIL;
393 }
394 
TRACE_Get_next_composite(const TRACE_file fp,int * category_index,int * n_bytes,char byte_base[],int * byte_pos,const int byte_max)395 TRACE_EXPORT int TRACE_Get_next_composite(const TRACE_file fp,
396                                           int *category_index,
397                                           int *n_bytes, char byte_base[],
398                                           int *byte_pos, const int byte_max)
399 {
400     return TRACEINPUT_FAIL;
401 }
402 
403 
TRACE_Get_position(TRACE_file fp,TRACE_int64_t * offset)404 TRACE_EXPORT int TRACE_Get_position(TRACE_file fp, TRACE_int64_t * offset)
405 {
406     return TRACEINPUT_FAIL;
407 }
408 
TRACE_Set_position(TRACE_file fp,TRACE_int64_t offset)409 TRACE_EXPORT int TRACE_Set_position(TRACE_file fp, TRACE_int64_t offset)
410 {
411     return TRACEINPUT_FAIL;
412 }
413 
414 /* FIXME: Improve failure reporting */
TRACE_Get_err_string(int ierr)415 TRACE_EXPORT char *TRACE_Get_err_string(int ierr)
416 {
417     /* ierr == 0 returns the help string (see the documentation on this
418      * routine) */
419     switch (ierr) {
420         case 0:
421             return "Usage: executable_name ASCII_drawable_filename";
422         default:
423             return "failure";
424     }
425 }
426