f4c0acae6c939f6f488a31cbc6c9fd40d908c1fd
[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 if(generated) break; /* use the first good match */
139 }
140 else {
141 g_warning("facility token was expected in file %s", in.name);
142 ret = 1;
143 goto parse_error;
144 }
145 }
146
147 parse_error:
148 fclose(in.fp);
149 open_error:
150
151 if(!generated) {
152 g_warning("Cannot find facility %s, checksum 0x%X",
153 g_quark_to_string(f->name), f->checksum);
154 ret = 1;
155 }
156
157 return ret;
158 }
159
160
161 /*****************************************************************************
162 *Function name
163 * generateFacility : generate facility, internal function
164 *Input params
165 * facility : LttFacilty structure
166 * fac : facility structure
167 * checksum : checksum of the facility
168 ****************************************************************************/
169
170 void generateFacility(LttFacility *f, facility_t *fac, guint32 checksum)
171 {
172 char * facilityName = fac->name;
173 sequence_t * events = &fac->events;
174 int i;
175 //LttEventType * evType;
176 LttEventType * event_type;
177 LttField * field;
178 LttType * type;
179
180 g_assert(f->name == g_quark_from_string(facilityName));
181 g_assert(f->checksum == checksum);
182
183 //f->event_number = events->position;
184
185 //initialize inner structures
186 f->events = g_array_sized_new (FALSE, TRUE, sizeof(LttEventType),
187 events->position);
188 //f->events = g_new(LttEventType*,f->event_number);
189 f->events = g_array_set_size(f->events, events->position);
190
191 g_datalist_init(&f->events_by_name);
192 g_datalist_init(&f->named_types);
193
194 //f->named_types_number = fac->named_types.keys.position;
195 //f->named_types = g_array_sized_new (FALSE, TRUE, sizeof(LttType),
196 // fac->named_types.keys.position);
197 //f->named_types = g_new(LttType*, fac->named_types.keys.position);
198 //f->named_types = g_array_set_size(f->named_types,
199 // fac->named_types.keys.position);
200
201 //for each event, construct field tree and type graph
202 for(i=0;i<events->position;i++){
203 event_type = &g_array_index(f->events, LttEventType, i);
204 //evType = g_new(LttEventType,1);
205 //f->events[i] = evType;
206
207 event_type->name =
208 g_quark_from_string(((event_t*)(events->array[i]))->name);
209
210 g_datalist_id_set_data(&f->events_by_name, event_type->name,
211 event_type);
212
213 event_type->description =
214 g_strdup(((event_t*)(events->array[i]))->description);
215
216 field = g_new(LttField, 1);
217 event_type->root_field = field;
218 event_type->facility = f;
219 event_type->index = i;
220
221 if(((event_t*)(events->array[i]))->type != NULL){
222 // field->field_pos = 0;
223 type = lookup_named_type(f,((event_t*)(events->array[i]))->type);
224 field->field_type = type;
225 field->offset_root = 0;
226 field->fixed_root = FIELD_UNKNOWN;
227 field->offset_parent = 0;
228 field->fixed_parent = FIELD_UNKNOWN;
229 // field->base_address = NULL;
230 field->field_size = 0;
231 field->fixed_size = FIELD_UNKNOWN;
232 field->parent = NULL;
233 field->child = NULL;
234 field->current_element = 0;
235
236 //construct field tree and type graph
237 construct_types_and_fields(f,((event_t*)(events->array[i]))->type,field);
238 }else{
239 event_type->root_field = NULL;
240 g_free(field);
241 }
242 }
243 }
244
245
246 /*****************************************************************************
247 *Function name
248 * construct_types_and_fields : construct field tree and type graph,
249 * internal recursion function
250 *Input params
251 * fac : facility struct
252 * td : type descriptor
253 * root_field : root field of the event
254 ****************************************************************************/
255
256
257 void construct_types_and_fields(LttFacility * fac, type_descriptor_t * td,
258 LttField * fld)
259 {
260 int i;
261 type_descriptor_t * tmpTd;
262
263 switch(td->type) {
264 case INT:
265 case UINT:
266 case FLOAT:
267 fld->field_type->size = td->size;
268 break;
269 case POINTER:
270 case LONG:
271 case ULONG:
272 case SIZE_T:
273 case SSIZE_T:
274 case OFF_T:
275 fld->field_type->size = 0;
276 break;
277 case STRING:
278 fld->field_type->size = 0;
279 break;
280 case ENUM:
281 fld->field_type->element_number = td->labels.position;
282 fld->field_type->enum_strings = g_new(GQuark,td->labels.position);
283 for(i=0;i<td->labels.position;i++){
284 fld->field_type->enum_strings[i]
285 = g_quark_from_string(((char*)(td->labels.array[i])));
286 }
287 fld->field_type->size = td->size;
288 break;
289
290 case ARRAY:
291 fld->field_type->element_number = (unsigned)td->size;
292 case SEQUENCE:
293 fld->field_type->element_type = g_new(LttType*,1);
294 tmpTd = td->nested_type;
295 fld->field_type->element_type[0] = lookup_named_type(fac, tmpTd);
296 fld->child = g_new(LttField*, 1);
297 fld->child[0] = g_new(LttField, 1);
298
299 fld->child[0]->field_type = fld->field_type->element_type[0];
300 fld->child[0]->offset_root = 0;
301 fld->child[0]->fixed_root = FIELD_UNKNOWN;
302 fld->child[0]->offset_parent = 0;
303 fld->child[0]->fixed_parent = FIELD_UNKNOWN;
304 fld->child[0]->field_size = 0;
305 fld->child[0]->fixed_size = FIELD_UNKNOWN;
306 fld->child[0]->parent = fld;
307 fld->child[0]->child = NULL;
308 fld->child[0]->current_element = 0;
309 construct_types_and_fields(fac, tmpTd, fld->child[0]);
310 break;
311
312 case STRUCT:
313 case UNION:
314 fld->field_type->element_number = td->fields.position;
315
316 g_assert(fld->field_type->element_type == NULL);
317 fld->field_type->element_type = g_new(LttType*, td->fields.position);
318
319 fld->child = g_new(LttField*, td->fields.position);
320 for(i=0;i<td->fields.position;i++){
321 tmpTd = ((field_t*)(td->fields.array[i]))->type;
322
323 fld->field_type->element_type[i] = lookup_named_type(fac, tmpTd);
324 fld->child[i] = g_new(LttField,1);
325
326 // fld->child[i]->field_pos = i;
327 fld->child[i]->field_type = fld->field_type->element_type[i];
328
329 fld->child[i]->field_type->element_name
330 = g_quark_from_string(((field_t*)(td->fields.array[i]))->name);
331
332 fld->child[i]->offset_root = 0;
333 fld->child[i]->fixed_root = FIELD_UNKNOWN;
334 fld->child[i]->offset_parent = 0;
335 fld->child[i]->fixed_parent = FIELD_UNKNOWN;
336 fld->child[i]->field_size = 0;
337 fld->child[i]->fixed_size = FIELD_UNKNOWN;
338 fld->child[i]->parent = fld;
339 fld->child[i]->child = NULL;
340 fld->child[i]->current_element = 0;
341 construct_types_and_fields(fac, tmpTd, fld->child[i]);
342 }
343 break;
344
345 default:
346 g_error("construct_types_and_fields : unknown type");
347 }
348
349
350 }
351
352
353
354 #if 0
355 void construct_types_and_fields(LttFacility * fac, type_descriptor * td,
356 LttField * fld)
357 {
358 int i, flag;
359 type_descriptor * tmpTd;
360
361 // if(td->type == LTT_STRING || td->type == LTT_SEQUENCE)
362 // fld->field_size = 0;
363 // else fld->field_size = -1;
364
365 if(td->type == LTT_ENUM){
366 fld->field_type->element_number = td->labels.position;
367 fld->field_type->enum_strings = g_new(GQuark,td->labels.position);
368 for(i=0;i<td->labels.position;i++){
369 fld->field_type->enum_strings[i]
370 = g_quark_from_string(((char*)(td->labels.array[i])));
371 }
372 }else if(td->type == LTT_ARRAY || td->type == LTT_SEQUENCE){
373 if(td->type == LTT_ARRAY)
374 fld->field_type->element_number = (unsigned)td->size;
375 fld->field_type->element_type = g_new(LttType*,1);
376 tmpTd = td->nested_type;
377 fld->field_type->element_type[0] = lookup_named_type(fac, tmpTd);
378 fld->child = g_new(LttField*, 1);
379 fld->child[0] = g_new(LttField, 1);
380
381 // fld->child[0]->field_pos = 0;
382 fld->child[0]->field_type = fld->field_type->element_type[0];
383 fld->child[0]->offset_root = fld->offset_root;
384 fld->child[0]->fixed_root = fld->fixed_root;
385 fld->child[0]->offset_parent = 0;
386 fld->child[0]->fixed_parent = 1;
387 // fld->child[0]->base_address = NULL;
388 fld->child[0]->field_size = 0;
389 fld->child[0]->field_fixed = -1;
390 fld->child[0]->parent = fld;
391 fld->child[0]->child = NULL;
392 fld->child[0]->current_element = 0;
393 construct_types_and_fields(fac, tmpTd, fld->child[0]);
394 }else if(td->type == LTT_STRUCT){
395 fld->field_type->element_number = td->fields.position;
396
397 if(fld->field_type->element_type == NULL){
398 fld->field_type->element_type = g_new(LttType*, td->fields.position);
399 flag = 1;
400 }else{
401 flag = 0;
402 }
403
404 fld->child = g_new(LttField*, td->fields.position);
405 for(i=0;i<td->fields.position;i++){
406 tmpTd = ((type_fields*)(td->fields.array[i]))->type;
407
408 if(flag)
409 fld->field_type->element_type[i] = lookup_named_type(fac, tmpTd);
410 fld->child[i] = g_new(LttField,1);
411
412 fld->child[i]->field_pos = i;
413 fld->child[i]->field_type = fld->field_type->element_type[i];
414
415 if(flag){
416 fld->child[i]->field_type->element_name
417 = g_quark_from_string(((type_fields*)(td->fields.array[i]))->name);
418 }
419
420 fld->child[i]->offset_root = -1;
421 fld->child[i]->fixed_root = -1;
422 fld->child[i]->offset_parent = -1;
423 fld->child[i]->fixed_parent = -1;
424 // fld->child[i]->base_address = NULL;
425 fld->child[i]->field_size = 0;
426 fld->child[i]->field_fixed = -1;
427 fld->child[i]->parent = fld;
428 fld->child[i]->child = NULL;
429 fld->child[i]->current_element = 0;
430 construct_types_and_fields(fac, tmpTd, fld->child[i]);
431 }
432 }
433 }
434 #endif //0
435
436 /*****************************************************************************
437 *Function name
438 * lookup_named_type: search named type in the table
439 * internal function
440 *Input params
441 * fac : facility struct
442 * td : type descriptor
443 *Return value
444 * : either find the named type, or create a new LttType
445 ****************************************************************************/
446
447 LttType * lookup_named_type(LttFacility *fac, type_descriptor_t * td)
448 {
449 LttType *type = NULL;
450 GQuark name = 0;
451
452 if(td->type_name != NULL) {
453 /* Named type */
454 name = g_quark_from_string(td->type_name);
455
456 type = g_datalist_id_get_data(&fac->named_types, name);
457 }
458
459 if(type == NULL){
460 /* Create the type */
461 type = g_new(LttType,1);
462 type->type_name = name;
463 type->type_class = td->type;
464 if(td->fmt) type->fmt = g_strdup(td->fmt);
465 else type->fmt = NULL;
466 type->size = td->size;
467 type->enum_strings = NULL;
468 type->element_type = NULL;
469 type->element_number = 0;
470
471 if(td->type_name != NULL)
472 g_datalist_id_set_data_full(&fac->named_types, name,
473 type, (GDestroyNotify)freeLttNamedType);
474 }
475 return type;
476 }
477
478
479 /*****************************************************************************
480 *Function name
481 * ltt_facility_close : close a facility, decrease its usage count,
482 * if usage count = 0, release the memory
483 *Input params
484 * f : facility that will be closed
485 ****************************************************************************/
486
487 void ltt_facility_close(LttFacility *f)
488 {
489 //release the memory it occupied
490 freeFacility(f);
491 }
492
493 /*****************************************************************************
494 * Functions to release the memory occupied by the facility
495 ****************************************************************************/
496
497 void freeFacility(LttFacility * fac)
498 {
499 guint i;
500 LttEventType *et;
501
502 for(i=0; i<fac->events->len; i++) {
503 et = &g_array_index (fac->events, LttEventType, i);
504 freeEventtype(et);
505 }
506 g_array_free(fac->events, TRUE);
507
508 g_datalist_clear(&fac->named_types);
509
510 }
511
512 void freeEventtype(LttEventType * evType)
513 {
514 LttType * root_type;
515 if(evType->description)
516 g_free(evType->description);
517 if(evType->root_field){
518 root_type = evType->root_field->field_type;
519 freeLttField(evType->root_field);
520 freeLttType(&root_type);
521 }
522 }
523
524 void freeLttNamedType(LttType * type)
525 {
526 freeLttType(&type);
527 }
528
529 void freeLttType(LttType ** type)
530 {
531 unsigned int i;
532 if(*type == NULL) return;
533 if((*type)->type_name != 0) return; //this is a named type.
534 //if((*type)->type_name){
535 // return; //this is a named type
536 //}
537 if((*type)->fmt)
538 g_free((*type)->fmt);
539 if((*type)->enum_strings){
540 g_free((*type)->enum_strings);
541 }
542
543 if((*type)->element_type){
544 for(i=0;i<(*type)->element_number;i++)
545 freeLttType(&((*type)->element_type[i]));
546 g_free((*type)->element_type);
547 }
548 g_free(*type);
549 *type = NULL;
550 }
551
552 void freeLttField(LttField * fld)
553 {
554 int i;
555 int size = 0;
556
557 if(fld->field_type){
558 if(fld->field_type->type_class == LTT_ARRAY ||
559 fld->field_type->type_class == LTT_SEQUENCE){
560 size = 1;
561 }else if(fld->field_type->type_class == LTT_STRUCT){
562 size = fld->field_type->element_number;
563 }
564 }
565
566 if(fld->child){
567 for(i=0; i<size; i++){
568 if(fld->child[i])freeLttField(fld->child[i]);
569 }
570 g_free(fld->child);
571 }
572 g_free(fld);
573 }
574
575 /*****************************************************************************
576 *Function name
577 * ltt_facility_name : obtain the facility's name
578 *Input params
579 * f : the facility
580 *Return value
581 * GQuark : the facility's name
582 ****************************************************************************/
583
584 GQuark ltt_facility_name(LttFacility *f)
585 {
586 return f->name;
587 }
588
589 /*****************************************************************************
590 *Function name
591 * ltt_facility_checksum : obtain the facility's checksum
592 *Input params
593 * f : the facility
594 *Return value
595 * : the checksum of the facility
596 ****************************************************************************/
597
598 guint32 ltt_facility_checksum(LttFacility *f)
599 {
600 return f->checksum;
601 }
602
603 /*****************************************************************************
604 *Function name
605 * ltt_facility_base_id : obtain the facility base id
606 *Input params
607 * f : the facility
608 *Return value
609 * : the base id of the facility
610 ****************************************************************************/
611
612 guint ltt_facility_id(LttFacility *f)
613 {
614 return f->id;
615 }
616
617 /*****************************************************************************
618 *Function name
619 * ltt_facility_eventtype_number: obtain the number of the event types
620 *Input params
621 * f : the facility that will be closed
622 *Return value
623 * : the number of the event types
624 ****************************************************************************/
625
626 guint8 ltt_facility_eventtype_number(LttFacility *f)
627 {
628 return (f->events->len);
629 }
630
631 /*****************************************************************************
632 *Function name
633 * ltt_facility_eventtype_get: obtain the event type according to event id
634 * from 0 to event_number - 1
635 *Input params
636 * f : the facility that will be closed
637 *Return value
638 * LttEventType * : the event type required
639 ****************************************************************************/
640
641 LttEventType *ltt_facility_eventtype_get(LttFacility *f, guint8 i)
642 {
643 if(!f->exists) return NULL;
644
645 g_assert(i < f->events->len);
646 return &g_array_index(f->events, LttEventType, i);
647 }
648
649 /*****************************************************************************
650 *Function name
651 * ltt_facility_eventtype_get_by_name
652 * : obtain the event type according to event name
653 * event name is unique in the facility
654 *Input params
655 * f : the facility
656 * name : the name of the event
657 *Return value
658 * LttEventType * : the event type required
659 ****************************************************************************/
660
661 LttEventType *ltt_facility_eventtype_get_by_name(LttFacility *f, GQuark name)
662 {
663 LttEventType *et = g_datalist_id_get_data(&f->events_by_name, name);
664 return et;
665 }
666
This page took 0.044967 seconds and 3 git commands to generate.