icons
[lttv.git] / ltt / branches / poly / lttv / textDump.c
CommitLineData
48f6f3c2 1/* The text dump facility needs to print headers before the trace set and
2 before each trace, to print each event, and to print statistics
3 after each trace. */
4
f60d7a47 5#include <ltt/type.h>
6#include <lttv/attribute.h>
7#include <lttv/hook.h>
8
48f6f3c2 9void init(int argc, char **argv)
10{
11 lttv_attributes *a;
12 lttv_hooks *before, *after;
13
14 a = lttv_global_attributes();
15 before = (lttv_hooks *)lttv_attributes_get_pointer_pathname(a,
16 "hooks/trace_set/before");
17 after = (lttv_hooks *)lttv_attributes_get_pointer_pathname(a,
18 "hooks/trace_set/after");
19 lttv_hooks_add(before, textDump_trace_set_before, NULL);
20 lttv_hooks_add(after, textDump_trace_set_after, NULL);
21}
22
23
24void destroy()
25{
26 lttv_attributes *a;
27 lttv_hooks *before, *after;
28
29 a = lttv_global_attributes();
30 before = (lttv_hooks *)lttv_attributes_get_pointer_pathname(a,
31 "hooks/trace_set/before");
32 after = (lttv_hooks *)lttv_attributes_get_pointer_pathname(a,
33 "hooks/trace_set/after");
34 lttv_hooks_remove(before, textDump_trace_set_before, NULL);
35 lttv_hooks_remove(after, textDump_trace_set_after, NULL);
36}
37
38/* Insert the hooks before and after each trace and tracefile, and for each
39 event. Print a global header. */
40
41typedef struct _trace_context {
42 g_string s;
43 FILE *fp;
44 bool mandatory_fields;
45 lttv_attributes *a;
46} trace_context;
47
48static bool textDump_trace_set_before(void *hook_data, void *call_data)
49{
50 FILE *fp;
51 int i, j, nb, nbtf;
52 lttv_trace_set *s;
53 lttv_attributes *a;
54 trace_context *c;
55
56 a = lttv_global_attributes();
57 s = (lttv_trace_set *)call_data
58
59 /* Get the file pointer */
60
61 fp = (FILE *)lttv_attributes_get_pointer_pathname(a, "textDump/file");
62
63 /* For each trace prepare the contexts and insert the hooks */
64
65 nb = lttv_trace_set_number(s);
66 for(i = 0 ; i < nb ; i++) {
67 c = g_new(trace_context);
68 a = lttv_trace_set_trace_attributes(s, i);
69
70 if(lttv_attributes_get_pointer_pathname(a, "textDump/context") != NULL) {
71 g_error("Recursive call to TextDump");
72 }
73
74 c->fp = fp;
75 c->mandatory_fields = TRUE;
76 c->s = g_string_new();
77 c->a = a;
78
79 lttv_attributes_set_pointer_pathname(a, "textDump/context", c);
80
81 h = lttv_attributes_get_hooks(a, "hooks/before");
82 lttv_hooks_add(h, textDump_trace_before, c);
83 h = lttv_attributes_get_hooks(a, "hooks/after");
84 lttv_hooks_add(h, textDump_trace_after, c);
85 h = lttv_attributes_get_hooks(a, "hooks/tacefile/before");
86 lttv_hooks_add(h, textDump_tracefile_before, c);
87 h = lttv_attributes_get_hooks(a, "hooks/tracefile/after");
88 lttv_hooks_add(h, textDump_tracefile_after, c);
89 h = lttv_attributes_get_hooks(a, "hooks/event/selected");
90 lttv_hooks_add(h, textDump_event, c);
91 }
92
93 /* Print the trace set header */
94 fprintf(fp,"Trace set contains %d traces\n\n", nb);
95
96 return TRUE;
97}
98
99
100/* Remove the hooks before and after each trace and tracefile, and for each
101 event. Print trace set level statistics. */
102
103static bool textDump_trace_set_after(void *hook_data, void *call_data)
104{
105 FILE *fp;
106 int i, j, nb, nbtf;
107 lttv_trace_set *s;
108 lttv_attributes *ga, *a;
109 trace_context *c;
110
111 ga = lttv_global_attributes();
112 s = (lttv_trace_set *)lttv_attributes_get_pointer_pathname(ga,
113 "trace_set/main");
114
115 /* Get the file pointer */
116
117 fp = (FILE *)lttv_attributes_get_pointer_pathname(ga, "textDump/file");
118
119 /* For each trace remove the hooks */
120
121 nb = lttv_trace_set_number(s);
122 for(i = 0 ; i < nb ; i++) {
123 a = lttv_trace_set_trace_attributes(s, i);
124 c = (trace_context *)lttv_attributes_get_pointer_pathname(a,
125 "textDump/context");
126 lttv_attributes_set_pointer_pathname(a, "textDump/context", NULL);
127 g_string_free(c->s);
128
129 h = lttv_attributes_get_hooks(a, "hooks/before");
130 lttv_hooks_remove(h, textDump_trace_before, c);
131 h = lttv_attributes_get_hooks(a, "hooks/after");
132 lttv_hooks_remove(h, textDump_trace_after, c);
133 h = lttv_attributes_get_hooks(a, "hooks/tacefile/before");
134 lttv_hooks_remove(h, textDump_tracefile_before, c);
135 h = lttv_attributes_get_hooks(a, "hooks/tracefile/after");
136 lttv_hooks_remove(h, textDump_tracefile_after, c);
137 h = lttv_attributes_get_hooks(a, "hooks/event/selected");
138 lttv_hooks_remove(h, textDump_event, c);
139 g_free(c);
140 }
141
142 /* Print the trace set statistics */
143
144 fprintf(fp,"Trace set contains %d traces\n\n", nb);
145
146 print_stats(fp, ga);
147
148 return TRUE;
149}
150
151
152/* Print a trace level header */
153
154static bool textDump_trace_before(void *hook_data, void *call_data)
155{
156 ltt_trace *t;
157 trace_context *c;
158
159 c = (trace_context *)hook_data;
160 t = (ltt_trace *)call_data;
161 fprintf(c->fp,"Start trace\n");
162 return TRUE;
163}
164
165
166/* Print trace level statistics */
167
168static bool textDump_trace_after(void *hook_data, void *call_data)
169{
170 ltt_trace *t;
171 trace_context *c;
172
173 c = (trace_context *)hook_data;
174 t = (ltt_trace *)call_data;
175 fprintf(c->fp,"End trace\n");
176 print_stats(c->fp,c->a);
177 return TRUE;
178}
179
180
181static bool textDump_tracefile_before(void *hook_data, void *call_data)
182{
183 ltt_tracefile *tf;
184 trace_context *c;
185
186 c = (trace_context *)hook_data;
187 tf = (ltt_tracefile *)call_data;
188 fprintf(c->fp,"Start tracefile\n");
189 return TRUE;
190}
191
192
193static bool textDump_tracefile_after(void *hook_data, void *call_data)
194{
195 ltt_tracefile *tf;
196 trace_context *c;
197
198 c = (trace_context *)hook_data;
199 tf = (ltt_tracefile *)call_data;
200 fprintf(c->fp,"End tracefile\n");
201 return TRUE;
202}
203
204
205/* Print the event content */
206
207static bool textDump_event(void *hook_data, void *call_data)
208{
209 ltt_event *e;
210 trace_context *c;
211
212 e = (ltt_event *)call_data;
213 c = (event_context *)hook_data;
214 lttv_event_to_string(e,c->s,c->mandatory_fields);
215 fputs(s, c->fd);
216 return TRUE;
217}
218
219
220static void print_stats(FILE *fp, lttv_attributes *a)
221{
222 int i, j, k, nb, nbc;
223
224 lttv_attributes *sa, *ra;
225 lttv_attribute *reports, *content;
226 lttv_key *key, *previous_key, null_key;
227
228 null_key = lttv_key_new_pathname("");
229 sa = (lttv_attributes *)lttv_attributes_get_pointer_pathname(a,"stats");
230 reports = lttv_attributes_array_get(sa);
231 nb= lttv_attributes_number(sa);
232
233 for(i = 0 ; i < nb ; i++) {
234 ra = (lttv_attributes *)reports[i].v.p;
235 key = reports[i].key;
236 g_assert(reports[i].t == LTTV_POINTER);
237
238 /* CHECK maybe have custom handlers registered for some specific reports */
239
240 print_key(fp,key);
241
242 content = lttv_attributes_array_get(ra);
243 nbc = lttv_attributes_number(ra);
244 lttv_attribute_array_sort_lexicographic(content, nbc, NULL, 0);
245 previous_key = nullKey;
246 for(j = 0 ; j < nbc ; j++) {
247 key = content[j].key;
248 for(k = 0 ; lttv_key_index(previous_key,k) == lttv_index(key,k) ; k++)
249 for(; k < lttv_key_number(key) ; k++) {
250 for(l = 0 ; l < k ; l++) fprintf(fp," ");
251 fprintf(fp, "%s", lttv_string_id_to_string(lttv_index(key,k)));
252 if(k == lttv_key_number(key)) {
253 switch(content[j].t) {
254 case LTTV_INTEGER:
255 fprintf(fp," %d\n", content[j].v.i);
256 break;
257 case LTTV_TIME:
258 fprintf(fp," %d.%09d\n", content[j].v.t.tv_sec,
259 content[j].v.t.tv_nsec);
260 break;
261 case LTTV_DOUBLE:
262 fprintf(fp," %g\n", content[j].v.d);
263 break;
264 case LTTV_POINTER:
265 fprintf(fp," pointer\n");
266 break;
267 }
268 }
269 else fprintf(fp,"\n");
270 }
271 }
272 lttv_attribute_array_destroy(content);
273 }
274 lttv_attribute_array_destroy(reports);
275 lttv_key_destroy(null_key);
276}
277
278
279void lttv_event_to_string(ltt_event *e, lttv_string *s, bool mandatory_fields)
280{
281 ltt_facility *facility;
282 ltt_eventtype *eventtype;
283 ltt_type *type;
284 ltt_field *field;
285 ltt_time time;
286
287 g_string_set_size(s,0);
288
289 facility = lttv_event_facility(e);
290 eventtype = ltt_event_eventtype(e);
291 field = ltt_event_field(e);
292
293 if(mandatory_fields) {
294 time = ltt_event_time(e);
295 g_string_append_printf(s,"%s.%s: %ld.%ld",ltt_facility_name(facility),
296 ltt_eventtype_name(eventtype), (long)time.tv_sec, time.tv_nsec);
297 }
298
299 print_field(e,f,s);
300}
301
302void print_field(ltt_event *e, ltt_field *f, lttv_string *s) {
303 ltt_type *type;
304 ltt_field *element;
305
306 int nb, i;
307
308 type = ltt_field_type(f);
309 switch(ltt_type_class(type)) {
310 case LTT_INT:
311 g_string_append_printf(s, " %ld", ltt_event_get_long_int(e,f));
312 break;
313
314 case LTT_UINT:
315 g_string_append_printf(s, " %lu", ltt_event_get_long_unsigned(e,f));
316 break;
317
318 case LTT_FLOAT:
319 g_string_append_printf(s, " %g", ltt_event_get_double(e,f));
320 break;
321
322 case LTT_STRING:
323 g_string_append_printf(s, " \"%s\"", ltt_event_get_string(e,f));
324 break;
325
326 case LTT_ENUM:
327 g_string_append_printf(s, " %s", ltt_enum_string_get(type,
328 event_get_unsigned(e,f));
329 break;
330
331 case LTT_ARRAY:
332 case LTT_SEQUENCE:
333 g_string_append_printf(s, " {");
334 nb = ltt_event_field_element_number(e,f);
335 element = ltt_field_element(f);
336 for(i = 0 ; i < nb ; i++) {
337 ltt_event_field_element_select(e,f,i);
338 print_field(e,element,s);
339 }
340 g_string_append_printf(s, " }");
341 break;
342
343 case LTT_STRUCT:
344 g_string_append_printf(s, " {");
345 nb = ltt_type_member_number(type);
346 for(i = 0 ; i < nb ; i++) {
347 element = ltt_field_member(f,i);
348 print_field(e,element,s);
349 }
350 g_string_append_printf(s, " }");
351 break;
352 }
353}
354
355
356
357
This page took 0.035342 seconds and 4 git commands to generate.