make LTTV support the facility.xml in eventdefs : multiple facilities found by checksum
[lttv.git] / ltt / branches / poly / ltt / facility.c
1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Xiangxiu Yang
3 * 2005 Mathieu Desnoyers
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License Version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
17 * MA 02111-1307, USA.
18 */
19
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23
24 #include <stdlib.h>
25 #include <string.h>
26 #include <stdio.h>
27 #include <glib.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <fcntl.h>
31
32
33
34 #include "parser.h"
35 #include <ltt/ltt.h>
36 #include "ltt-private.h"
37 #include <ltt/facility.h>
38
39 #ifndef g_open
40 #define g_open open
41 #endif
42
43 #define g_close close
44
45 /* search for the (named) type in the table, if it does not exist
46 create a new one */
47 LttType * lookup_named_type(LttFacility *fac, type_descriptor_t * td);
48
49 /* construct directed acyclic graph for types, and tree for fields */
50 void construct_types_and_fields(LttFacility * fac, type_descriptor_t * td,
51 LttField * fld);
52
53 /* generate the facility according to the events belongin to it */
54 void generateFacility(LttFacility * f, facility_t * fac,
55 guint32 checksum);
56
57 /* functions to release the memory occupied by a facility */
58 void freeFacility(LttFacility * facility);
59 void freeEventtype(LttEventType * evType);
60 void freeLttType(LttType ** type);
61 void freeLttField(LttField * fld);
62 void freeLttNamedType(LttType * type);
63
64
65 /*****************************************************************************
66 *Function name
67 * ltt_facility_open : open facilities
68 *Input params
69 * t : the trace containing the facilities
70 * pathname : the path name of the facility
71 *
72 * Open the facility corresponding to the right checksum.
73 *
74 *returns 0 on success, 1 on error.
75 ****************************************************************************/
76
77 int ltt_facility_open(LttFacility *f, LttTrace * t, gchar * pathname)
78 {
79 int ret = 0;
80 gchar *token;
81 parse_file_t in;
82 facility_t * fac;
83 unsigned long checksum;
84 gchar buffer[BUFFER_SIZE];
85 gboolean generated = FALSE;
86
87 in.buffer = &(buffer[0]);
88 in.lineno = 0;
89 in.error = error_callback;
90 in.name = pathname;
91 in.unget = 0;
92
93 in.fp = fopen(in.name, "r");
94 if(in.fp == NULL) {
95 g_warning("cannot open facility description file %s",
96 in.name);
97 ret = 1;
98 goto open_error;
99 }
100
101 while(1){
102 token = getToken(&in);
103 if(in.type == ENDFILE) break;
104
105 if(g_ascii_strcasecmp(token, "<")) in.error(&in,"not a facility file");
106 token = getName(&in);
107
108 if(g_ascii_strcasecmp("facility",token) == 0) {
109 fac = g_new(facility_t, 1);
110 fac->name = NULL;
111 fac->description = NULL;
112 sequence_init(&(fac->events));
113 table_init(&(fac->named_types));
114 sequence_init(&(fac->unnamed_types));
115
116 parseFacility(&in, fac);
117
118 //check if any namedType is not defined
119 checkNamedTypesImplemented(&fac->named_types);
120
121 generateChecksum(fac->name, &checksum, &fac->events);
122
123 if(checksum == f->checksum) {
124 generateFacility(f, fac, checksum);
125 generated = TRUE;
126 }
127
128 g_free(fac->name);
129 free(fac->capname);
130 g_free(fac->description);
131 freeEvents(&fac->events);
132 sequence_dispose(&fac->events);
133 freeNamedType(&fac->named_types);
134 table_dispose(&fac->named_types);
135 freeTypes(&fac->unnamed_types);
136 sequence_dispose(&fac->unnamed_types);
137 g_free(fac);
138 }
139 else {
140 g_warning("facility token was expected in file %s", in.name);
141 ret = 1;
142 goto parse_error;
143 }
144 }
145
146 parse_error:
147 fclose(in.fp);
148 open_error:
149
150 if(!generated)
151 g_warning("Cannot find facility %s, checksum 0x%X", f->name, f->checksum);
152
153 return ret;
154 }
155
156
157 /*****************************************************************************
158 *Function name
159 * generateFacility : generate facility, internal function
160 *Input params
161 * facility : LttFacilty structure
162 * fac : facility structure
163 * checksum : checksum of the facility
164 ****************************************************************************/
165
166 void generateFacility(LttFacility *f, facility_t *fac, guint32 checksum)
167 {
168 char * facilityName = fac->name;
169 sequence_t * events = &fac->events;
170 int i;
171 //LttEventType * evType;
172 LttEventType * event_type;
173 LttField * field;
174 LttType * type;
175
176 g_assert(f->name == g_quark_from_string(facilityName));
177 g_assert(f->checksum == checksum);
178
179 //f->event_number = events->position;
180
181 //initialize inner structures
182 f->events = g_array_sized_new (FALSE, TRUE, sizeof(LttEventType),
183 events->position);
184 //f->events = g_new(LttEventType*,f->event_number);
185 f->events = g_array_set_size(f->events, events->position);
186
187 g_datalist_init(&f->events_by_name);
188 g_datalist_init(&f->named_types);
189
190 //f->named_types_number = fac->named_types.keys.position;
191 //f->named_types = g_array_sized_new (FALSE, TRUE, sizeof(LttType),
192 // fac->named_types.keys.position);
193 //f->named_types = g_new(LttType*, fac->named_types.keys.position);
194 //f->named_types = g_array_set_size(f->named_types,
195 // fac->named_types.keys.position);
196
197 //for each event, construct field tree and type graph
198 for(i=0;i<events->position;i++){
199 event_type = &g_array_index(f->events, LttEventType, i);
200 //evType = g_new(LttEventType,1);
201 //f->events[i] = evType;
202
203 event_type->name =
204 g_quark_from_string(((event_t*)(events->array[i]))->name);
205
206 g_datalist_id_set_data(&f->events_by_name, event_type->name,
207 event_type);
208
209 event_type->description =
210 g_strdup(((event_t*)(events->array[i]))->description);
211
212 field = g_new(LttField, 1);
213 event_type->root_field = field;
214 event_type->facility = f;
215 event_type->index = i;
216
217 if(((event_t*)(events->array[i]))->type != NULL){
218 // field->field_pos = 0;
219 type = lookup_named_type(f,((event_t*)(events->array[i]))->type);
220 field->field_type = type;
221 field->offset_root = 0;
222 field->fixed_root = FIELD_UNKNOWN;
223 field->offset_parent = 0;
224 field->fixed_parent = FIELD_UNKNOWN;
225 // field->base_address = NULL;
226 field->field_size = 0;
227 field->fixed_size = FIELD_UNKNOWN;
228 field->parent = NULL;
229 field->child = NULL;
230 field->current_element = 0;
231
232 //construct field tree and type graph
233 construct_types_and_fields(f,((event_t*)(events->array[i]))->type,field);
234 }else{
235 event_type->root_field = NULL;
236 g_free(field);
237 }
238 }
239 }
240
241
242 /*****************************************************************************
243 *Function name
244 * construct_types_and_fields : construct field tree and type graph,
245 * internal recursion function
246 *Input params
247 * fac : facility struct
248 * td : type descriptor
249 * root_field : root field of the event
250 ****************************************************************************/
251
252
253 void construct_types_and_fields(LttFacility * fac, type_descriptor_t * td,
254 LttField * fld)
255 {
256 int i;
257 type_descriptor_t * tmpTd;
258
259 switch(td->type) {
260 case INT:
261 case UINT:
262 case FLOAT:
263 fld->field_type->size = td->size;
264 break;
265 case POINTER:
266 case LONG:
267 case ULONG:
268 case SIZE_T:
269 case SSIZE_T:
270 case OFF_T:
271 fld->field_type->size = 0;
272 break;
273 case STRING:
274 fld->field_type->size = 0;
275 break;
276 case ENUM:
277 fld->field_type->element_number = td->labels.position;
278 fld->field_type->enum_strings = g_new(GQuark,td->labels.position);
279 for(i=0;i<td->labels.position;i++){
280 fld->field_type->enum_strings[i]
281 = g_quark_from_string(((char*)(td->labels.array[i])));
282 }
283 fld->field_type->size = td->size;
284 break;
285
286 case ARRAY:
287 fld->field_type->element_number = (unsigned)td->size;
288 case SEQUENCE:
289 fld->field_type->element_type = g_new(LttType*,1);
290 tmpTd = td->nested_type;
291 fld->field_type->element_type[0] = lookup_named_type(fac, tmpTd);
292 fld->child = g_new(LttField*, 1);
293 fld->child[0] = g_new(LttField, 1);
294
295 fld->child[0]->field_type = fld->field_type->element_type[0];
296 fld->child[0]->offset_root = 0;
297 fld->child[0]->fixed_root = FIELD_UNKNOWN;
298 fld->child[0]->offset_parent = 0;
299 fld->child[0]->fixed_parent = FIELD_UNKNOWN;
300 fld->child[0]->field_size = 0;
301 fld->child[0]->fixed_size = FIELD_UNKNOWN;
302 fld->child[0]->parent = fld;
303 fld->child[0]->child = NULL;
304 fld->child[0]->current_element = 0;
305 construct_types_and_fields(fac, tmpTd, fld->child[0]);
306 break;
307
308 case STRUCT:
309 case UNION:
310 fld->field_type->element_number = td->fields.position;
311
312 g_assert(fld->field_type->element_type == NULL);
313 fld->field_type->element_type = g_new(LttType*, td->fields.position);
314
315 fld->child = g_new(LttField*, td->fields.position);
316 for(i=0;i<td->fields.position;i++){
317 tmpTd = ((field_t*)(td->fields.array[i]))->type;
318
319 fld->field_type->element_type[i] = lookup_named_type(fac, tmpTd);
320 fld->child[i] = g_new(LttField,1);
321
322 // fld->child[i]->field_pos = i;
323 fld->child[i]->field_type = fld->field_type->element_type[i];
324
325 fld->child[i]->field_type->element_name
326 = g_quark_from_string(((field_t*)(td->fields.array[i]))->name);
327
328 fld->child[i]->offset_root = 0;
329 fld->child[i]->fixed_root = FIELD_UNKNOWN;
330 fld->child[i]->offset_parent = 0;
331 fld->child[i]->fixed_parent = FIELD_UNKNOWN;
332 fld->child[i]->field_size = 0;
333 fld->child[i]->fixed_size = FIELD_UNKNOWN;
334 fld->child[i]->parent = fld;
335 fld->child[i]->child = NULL;
336 fld->child[i]->current_element = 0;
337 construct_types_and_fields(fac, tmpTd, fld->child[i]);
338 }
339 break;
340
341 default:
342 g_error("construct_types_and_fields : unknown type");
343 }
344
345
346 }
347
348
349
350 #if 0
351 void construct_types_and_fields(LttFacility * fac, type_descriptor * td,
352 LttField * fld)
353 {
354 int i, flag;
355 type_descriptor * tmpTd;
356
357 // if(td->type == LTT_STRING || td->type == LTT_SEQUENCE)
358 // fld->field_size = 0;
359 // else fld->field_size = -1;
360
361 if(td->type == LTT_ENUM){
362 fld->field_type->element_number = td->labels.position;
363 fld->field_type->enum_strings = g_new(GQuark,td->labels.position);
364 for(i=0;i<td->labels.position;i++){
365 fld->field_type->enum_strings[i]
366 = g_quark_from_string(((char*)(td->labels.array[i])));
367 }
368 }else if(td->type == LTT_ARRAY || td->type == LTT_SEQUENCE){
369 if(td->type == LTT_ARRAY)
370 fld->field_type->element_number = (unsigned)td->size;
371 fld->field_type->element_type = g_new(LttType*,1);
372 tmpTd = td->nested_type;
373 fld->field_type->element_type[0] = lookup_named_type(fac, tmpTd);
374 fld->child = g_new(LttField*, 1);
375 fld->child[0] = g_new(LttField, 1);
376
377 // fld->child[0]->field_pos = 0;
378 fld->child[0]->field_type = fld->field_type->element_type[0];
379 fld->child[0]->offset_root = fld->offset_root;
380 fld->child[0]->fixed_root = fld->fixed_root;
381 fld->child[0]->offset_parent = 0;
382 fld->child[0]->fixed_parent = 1;
383 // fld->child[0]->base_address = NULL;
384 fld->child[0]->field_size = 0;
385 fld->child[0]->field_fixed = -1;
386 fld->child[0]->parent = fld;
387 fld->child[0]->child = NULL;
388 fld->child[0]->current_element = 0;
389 construct_types_and_fields(fac, tmpTd, fld->child[0]);
390 }else if(td->type == LTT_STRUCT){
391 fld->field_type->element_number = td->fields.position;
392
393 if(fld->field_type->element_type == NULL){
394 fld->field_type->element_type = g_new(LttType*, td->fields.position);
395 flag = 1;
396 }else{
397 flag = 0;
398 }
399
400 fld->child = g_new(LttField*, td->fields.position);
401 for(i=0;i<td->fields.position;i++){
402 tmpTd = ((type_fields*)(td->fields.array[i]))->type;
403
404 if(flag)
405 fld->field_type->element_type[i] = lookup_named_type(fac, tmpTd);
406 fld->child[i] = g_new(LttField,1);
407
408 fld->child[i]->field_pos = i;
409 fld->child[i]->field_type = fld->field_type->element_type[i];
410
411 if(flag){
412 fld->child[i]->field_type->element_name
413 = g_quark_from_string(((type_fields*)(td->fields.array[i]))->name);
414 }
415
416 fld->child[i]->offset_root = -1;
417 fld->child[i]->fixed_root = -1;
418 fld->child[i]->offset_parent = -1;
419 fld->child[i]->fixed_parent = -1;
420 // fld->child[i]->base_address = NULL;
421 fld->child[i]->field_size = 0;
422 fld->child[i]->field_fixed = -1;
423 fld->child[i]->parent = fld;
424 fld->child[i]->child = NULL;
425 fld->child[i]->current_element = 0;
426 construct_types_and_fields(fac, tmpTd, fld->child[i]);
427 }
428 }
429 }
430 #endif //0
431
432 /*****************************************************************************
433 *Function name
434 * lookup_named_type: search named type in the table
435 * internal function
436 *Input params
437 * fac : facility struct
438 * td : type descriptor
439 *Return value
440 * : either find the named type, or create a new LttType
441 ****************************************************************************/
442
443 LttType * lookup_named_type(LttFacility *fac, type_descriptor_t * td)
444 {
445 LttType *type = NULL;
446 GQuark name = 0;
447
448 if(td->type_name != NULL) {
449 /* Named type */
450 name = g_quark_from_string(td->type_name);
451
452 type = g_datalist_id_get_data(&fac->named_types, name);
453 }
454
455 if(type == NULL){
456 /* Create the type */
457 type = g_new(LttType,1);
458 type->type_name = name;
459 type->type_class = td->type;
460 if(td->fmt) type->fmt = g_strdup(td->fmt);
461 else type->fmt = NULL;
462 type->size = td->size;
463 type->enum_strings = NULL;
464 type->element_type = NULL;
465 type->element_number = 0;
466
467 if(td->type_name != NULL)
468 g_datalist_id_set_data_full(&fac->named_types, name,
469 type, (GDestroyNotify)freeLttNamedType);
470 }
471 return type;
472 }
473
474
475 /*****************************************************************************
476 *Function name
477 * ltt_facility_close : close a facility, decrease its usage count,
478 * if usage count = 0, release the memory
479 *Input params
480 * f : facility that will be closed
481 ****************************************************************************/
482
483 void ltt_facility_close(LttFacility *f)
484 {
485 //release the memory it occupied
486 freeFacility(f);
487 }
488
489 /*****************************************************************************
490 * Functions to release the memory occupied by the facility
491 ****************************************************************************/
492
493 void freeFacility(LttFacility * fac)
494 {
495 guint i;
496 LttEventType *et;
497
498 for(i=0; i<fac->events->len; i++) {
499 et = &g_array_index (fac->events, LttEventType, i);
500 freeEventtype(et);
501 }
502 g_array_free(fac->events, TRUE);
503
504 g_datalist_clear(&fac->named_types);
505
506 }
507
508 void freeEventtype(LttEventType * evType)
509 {
510 LttType * root_type;
511 if(evType->description)
512 g_free(evType->description);
513 if(evType->root_field){
514 root_type = evType->root_field->field_type;
515 freeLttField(evType->root_field);
516 freeLttType(&root_type);
517 }
518 }
519
520 void freeLttNamedType(LttType * type)
521 {
522 freeLttType(&type);
523 }
524
525 void freeLttType(LttType ** type)
526 {
527 unsigned int i;
528 if(*type == NULL) return;
529 if((*type)->type_name != 0) return; //this is a named type.
530 //if((*type)->type_name){
531 // return; //this is a named type
532 //}
533 if((*type)->fmt)
534 g_free((*type)->fmt);
535 if((*type)->enum_strings){
536 g_free((*type)->enum_strings);
537 }
538
539 if((*type)->element_type){
540 for(i=0;i<(*type)->element_number;i++)
541 freeLttType(&((*type)->element_type[i]));
542 g_free((*type)->element_type);
543 }
544 g_free(*type);
545 *type = NULL;
546 }
547
548 void freeLttField(LttField * fld)
549 {
550 int i;
551 int size = 0;
552
553 if(fld->field_type){
554 if(fld->field_type->type_class == LTT_ARRAY ||
555 fld->field_type->type_class == LTT_SEQUENCE){
556 size = 1;
557 }else if(fld->field_type->type_class == LTT_STRUCT){
558 size = fld->field_type->element_number;
559 }
560 }
561
562 if(fld->child){
563 for(i=0; i<size; i++){
564 if(fld->child[i])freeLttField(fld->child[i]);
565 }
566 g_free(fld->child);
567 }
568 g_free(fld);
569 }
570
571 /*****************************************************************************
572 *Function name
573 * ltt_facility_name : obtain the facility's name
574 *Input params
575 * f : the facility
576 *Return value
577 * GQuark : the facility's name
578 ****************************************************************************/
579
580 GQuark ltt_facility_name(LttFacility *f)
581 {
582 return f->name;
583 }
584
585 /*****************************************************************************
586 *Function name
587 * ltt_facility_checksum : obtain the facility's checksum
588 *Input params
589 * f : the facility
590 *Return value
591 * : the checksum of the facility
592 ****************************************************************************/
593
594 guint32 ltt_facility_checksum(LttFacility *f)
595 {
596 return f->checksum;
597 }
598
599 /*****************************************************************************
600 *Function name
601 * ltt_facility_base_id : obtain the facility base id
602 *Input params
603 * f : the facility
604 *Return value
605 * : the base id of the facility
606 ****************************************************************************/
607
608 guint ltt_facility_id(LttFacility *f)
609 {
610 return f->id;
611 }
612
613 /*****************************************************************************
614 *Function name
615 * ltt_facility_eventtype_number: obtain the number of the event types
616 *Input params
617 * f : the facility that will be closed
618 *Return value
619 * : the number of the event types
620 ****************************************************************************/
621
622 guint8 ltt_facility_eventtype_number(LttFacility *f)
623 {
624 return (f->events->len);
625 }
626
627 /*****************************************************************************
628 *Function name
629 * ltt_facility_eventtype_get: obtain the event type according to event id
630 * from 0 to event_number - 1
631 *Input params
632 * f : the facility that will be closed
633 *Return value
634 * LttEventType * : the event type required
635 ****************************************************************************/
636
637 LttEventType *ltt_facility_eventtype_get(LttFacility *f, guint8 i)
638 {
639 if(!f->exists) return NULL;
640
641 g_assert(i < f->events->len);
642 return &g_array_index(f->events, LttEventType, i);
643 }
644
645 /*****************************************************************************
646 *Function name
647 * ltt_facility_eventtype_get_by_name
648 * : obtain the event type according to event name
649 * event name is unique in the facility
650 *Input params
651 * f : the facility
652 * name : the name of the event
653 *Return value
654 * LttEventType * : the event type required
655 ****************************************************************************/
656
657 LttEventType *ltt_facility_eventtype_get_by_name(LttFacility *f, GQuark name)
658 {
659 LttEventType *et = g_datalist_id_get_data(&f->events_by_name, name);
660 return et;
661 }
662
This page took 0.044732 seconds and 5 git commands to generate.