session: add cli option to dump session elog
[vpp.git] / src / tools / perftool / c2cpel.c
1 /* 
2  *------------------------------------------------------------------
3  * Copyright (c) 2006-2016 Cisco and/or its affiliates.
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <netinet/in.h>
19 #include <string.h>
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <fcntl.h>
23 #include <sys/fcntl.h>
24 #include <sys/mman.h>
25 #include <unistd.h>
26 #include <ctype.h>
27 #include <vppinfra/clib.h>
28 #include <vppinfra/vec.h>
29 #include <vppinfra/hash.h>
30 #include <vppinfra/elog.h>
31 #include <vppinfra/mem.h>
32 #include <pwd.h>
33 #include <stdarg.h>
34 #include <time.h>
35 #include "cpel.h"
36 #include "cpel_util.h"
37
38 static elog_main_t elog_main;
39
40 /*
41  * convert_clib_file
42  */
43 void convert_clib_file(char *clib_file)
44 {
45     clib_error_t *error = 0;
46     int i;
47     elog_main_t *em = &elog_main;
48     double starttime, delta;
49
50     error = elog_read_file (&elog_main, clib_file);
51
52     if (error) {
53         clib_warning("%U", format_clib_error, error);
54         exit (1);
55     }
56
57     em = &elog_main;
58
59     starttime = em->events[0].time;
60
61     for (i = 0; i < vec_len (em->events); i++) {
62         elog_event_t *e;        /* clib event */
63         evt_t *ep;              /* xxx2cpel event */
64         u8 *s;
65         u64 timestamp;
66         elog_event_type_t *t;
67         u8 *brief_event_name;
68         u8 *track_name;
69         int j;
70
71         e = vec_elt_at_index(em->events, i);
72
73         /* Seconds since start of log */
74         delta = e->time - starttime;
75         
76         /* u64 nanoseconds since start of log */
77         timestamp = delta * 1e9;
78
79         s = format (0, "%U%c", format_elog_event, em, e, 0);
80
81         /* allocate an event instance */
82         vec_add2(the_events, ep, 1);
83         ep->timestamp = timestamp;
84         
85         /* convert string event code to a real number */
86         t = vec_elt_at_index (em->event_types, e->type);
87
88         /* 
89          * Construct a reasonable event name.
90          * Truncate the format string at the first whitespace break
91          * or printf format character.
92          */
93         brief_event_name = format (0, "%s", t->format);
94
95         for (j = 0; j < vec_len (brief_event_name); j++) {
96             if (brief_event_name[j] == ' ' ||
97                 brief_event_name[j] == '%' ||
98                 brief_event_name[j] == '(') {
99                 brief_event_name[j] = 0;
100                 break;
101             }
102         }
103         /* Throw away that much of the formatted event */
104         vec_delete (s, j+1, 0);
105
106         ep->event_id = find_or_add_event(brief_event_name, "%s");
107
108         track_name = format (0, "%U%c", format_elog_track_name, em, e, 0);
109
110         ep->track_id = find_or_add_track (track_name);
111
112         ep->datum = find_or_add_strtab(s);
113
114         vec_free (track_name);
115         vec_free(brief_event_name);
116         vec_free(s);
117     }
118 }
119
120 u8 *vec_basename (char *s)
121 {
122     u8 * rv;
123     char *cp = s;
124
125     while (*cp)
126         cp++;
127
128     cp--;
129
130     while (cp > s && *cp != '/')
131         cp--;
132
133     if (cp > s)
134         cp++;
135
136     rv = format (0, "%s", cp);
137     return rv;
138 }
139
140
141 int event_compare (const void *a0, const void *a1)
142 {
143     evt_t *e0 = (evt_t *)a0;
144     evt_t *e1 = (evt_t *)a1;
145
146     if (e0->timestamp < e1->timestamp)
147         return -1;
148     else if (e0->timestamp > e1->timestamp)
149         return 1;
150     return 0;
151 }
152
153 int main (int argc, char **argv)
154 {
155     int curarg=1;
156     char **inputfiles = 0;
157     char *outputfile = 0;
158     FILE *ofp;
159
160     clib_mem_init_thread_safe (0, 256 << 20);
161
162     if (argc < 3)
163         goto usage;
164
165     while (curarg < argc) {
166         if (!strncmp(argv[curarg], "--input-file", 3)) {
167             curarg++;
168             if (curarg < argc) {
169                 vec_add1 (inputfiles, argv[curarg]);
170                 curarg++;
171                 continue;
172             }
173             clib_warning("Missing filename after --input-file\n");
174             exit (1);
175         }
176
177         if (!strncmp(argv[curarg], "--output-file", 3)) {
178             curarg ++;
179             if (curarg < argc) {
180                 outputfile = argv[curarg];
181                 curarg ++;
182                 continue;
183             }
184             clib_warning("Missing filename after --output-file\n");
185             exit(1);
186         }
187         vec_add1 (inputfiles, argv[curarg]);
188         curarg++;
189         continue;
190
191     usage:
192         fformat(stderr, 
193                 "c2cpel [--input-file] <filename> --output-file <filename>\n");
194         exit(1);
195     }
196
197     if (vec_len(inputfiles) == 0 || outputfile == 0)
198         goto usage;
199         
200     if (vec_len(inputfiles) > 1)
201         goto usage;
202
203     clib_mem_init (0, ((uword)3<<30));
204
205     cpel_util_init();
206
207     convert_clib_file (inputfiles[0]);
208
209     ofp = fopen (outputfile, "w");
210     if (ofp == NULL) {
211         clib_unix_warning ("couldn't create %s", outputfile);
212         exit (1);
213     }
214     
215     alpha_sort_tracks();
216     fixup_event_tracks();
217
218     /*
219      * Four sections: string-table, event definitions, track defs, events. 
220      */
221     if (!write_cpel_header(ofp, 4)) {
222         clib_warning ("Error writing cpel header to %s...\n", outputfile);
223         unlink(outputfile);
224         exit(1);
225     }
226
227     if (!write_string_table(ofp)) {
228         clib_warning ("Error writing string table to %s...\n", outputfile);
229         unlink(outputfile);
230         exit(1);
231     }
232
233     if (!write_event_defs(ofp)) {
234         clib_warning ("Error writing event defs to %s...\n", outputfile);
235         unlink(outputfile);
236         exit(1);
237     }
238
239     if (!write_track_defs(ofp)) {
240         clib_warning ("Error writing track defs to %s...\n", outputfile);
241         unlink(outputfile);
242         exit(1);
243     }
244
245     if (!write_events(ofp, (u64) 1e9)) {
246         clib_warning ("Error writing events to %s...\n", outputfile);
247         unlink(outputfile);
248         exit(1);
249         
250     }
251     fclose(ofp);
252     exit (0);
253 }