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