lttd/Makefile
ltt/Makefile
include/Makefile
- include/ltt/Makefile
ltt/convert/Makefile
include/lttv/Makefile])
AC_OUTPUT
-SUBDIRS = ltt lttv
+SUBDIRS = lttv
+++ /dev/null
-lttinclude_HEADERS = \
- event.h\
- facility.h\
- ltt.h\
- time.h\
- trace.h\
- type.h
+++ /dev/null
-/* This file is part of the Linux Trace Toolkit trace reading library
- * Copyright (C) 2003-2004 Michel Dagenais
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License Version 2.1 as published by the Free Software Foundation.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef EVENT_H
-#define EVENT_H
-
-#include <ltt/ltt.h>
-
-/* Events and their content, including the raw data, are only valid
- until reading another event from the same tracefile.
- Indeed, since event reading is critical to the performance,
- the memory associated with an event may be reused at each read. */
-
-
-/* Obtain the trace unique integer id associated with the type of
- this event */
-
-unsigned ltt_event_eventtype_id(LttEvent *e);
-
-
-/* Facility and type for the event */
-
-LttFacility *ltt_event_facility(LttEvent *e);
-
-LttEventType *ltt_event_eventtype(LttEvent *e);
-
-
-/* Root field for the event */
-
-LttField *ltt_event_field(LttEvent *e);
-
-
-/* Time and cycle count for the event */
-
-LttTime ltt_event_time(LttEvent *e);
-
-LttCycleCount ltt_event_cycle_count(LttEvent *e);
-
-
-/* Obtain the position of the event within the tracefile. This
- is used to seek back to this position later or to seek to another
- position, computed relative to this position. The event position
- structure is opaque and contains several fields, only two
- of which are user accessible: block number and event index
- within the block. */
-
-void ltt_event_position(LttEvent *e, LttEventPosition *ep);
-
-LttEventPosition * ltt_event_position_new();
-
-void ltt_event_position_get(LttEventPosition *ep,
- unsigned *block_number, unsigned *index_in_block, LttTracefile ** tf);
-
-void ltt_event_position_set(LttEventPosition *ep,
- unsigned block_number, unsigned index_in_block);
-
-
-/* CPU id of the event */
-
-unsigned ltt_event_cpu_id(LttEvent *e);
-
-
-/* Pointer to the raw data for the event. This should not be used directly
- unless prepared to do all the architecture specific conversions. */
-
-void *ltt_event_data(LttEvent *e);
-
-
-/* The number of elements in a sequence field is specific to each event
- instance. This function returns the number of elements for an array or
- sequence field in an event. */
-
-unsigned ltt_event_field_element_number(LttEvent *e, LttField *f);
-
-
-/* Set the currently selected element for a sequence or array field. */
-
-void ltt_event_field_element_select(LttEvent *e, LttField *f, unsigned i);
-
-
-/* A union is like a structure except that only a single member at a time
- is present depending on the specific event instance. This function tells
- the active member for a union field in an event. */
-
-unsigned ltt_event_field_union_member(LttEvent *e, LttField *f);
-
-
-/* These functions extract data from an event after architecture specific
- conversions. */
-
-unsigned ltt_event_get_unsigned(LttEvent *e, LttField *f);
-
-int ltt_event_get_int(LttEvent *e, LttField *f);
-
-unsigned long ltt_event_get_long_unsigned(LttEvent *e, LttField *f);
-
-long int ltt_event_get_long_int(LttEvent *e, LttField *f);
-
-float ltt_event_get_float(LttEvent *e, LttField *f);
-
-double ltt_event_get_double(LttEvent *e, LttField *f);
-
-
-/* The string obtained is only valid until the next read from
- the same tracefile. */
-
-char *ltt_event_get_string(LttEvent *e, LttField *f);
-
-#endif // EVENT_H
+++ /dev/null
-/* This file is part of the Linux Trace Toolkit trace reading library
- * Copyright (C) 2003-2004 Michel Dagenais
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License Version 2.1 as published by the Free Software Foundation.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef FACILITY_H
-#define FACILITY_H
-
-#include <ltt/ltt.h>
-
-/* Facilities are obtained from an opened trace. The structures associated
- with a facility are released when the trace is closed. Each facility
- is characterized by its name and checksum. */
-
-char *ltt_facility_name(LttFacility *f);
-
-LttChecksum ltt_facility_checksum(LttFacility *f);
-
-/* open facility */
-void ltt_facility_open(LttTrace * t, char * facility_name);
-
-/* Discover the event types within the facility. The event type integer id
- relative to the trace is from 0 to nb_event_types - 1. The event
- type id within the trace is the relative id + the facility base event
- id. */
-
-unsigned ltt_facility_base_id(LttFacility *f);
-
-unsigned ltt_facility_eventtype_number(LttFacility *f);
-
-LttEventType *ltt_facility_eventtype_get(LttFacility *f, unsigned i);
-
-LttEventType *ltt_facility_eventtype_get_by_name(LttFacility *f, char *name);
-
-#endif // FACILITY_H
-
+++ /dev/null
-/* This file is part of the Linux Trace Toolkit trace reading library
- * Copyright (C) 2003-2004 Michel Dagenais
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License Version 2.1 as published by the Free Software Foundation.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef LTT_H
-#define LTT_H
-
-#include <ltt/time.h>
-#include <glib.h>
-
-/* A trace is associated with a tracing session run on a single, possibly
- multi-cpu, system. It is defined as a pathname to a directory containing
- all the relevant trace files. All the tracefiles for a trace were
- generated in a single system for the same time period by the same
- trace daemon. They simply contain different events. Typically control
- tracefiles contain the important events (process creations and registering
- tracing facilities) for all CPUs, and one file for each CPU contains all
- the events for that CPU. All the tracefiles within the same trace directory
- then use the exact same id numbers for event types.
-
- A tracefile (LttTracefile) contains a list of events (LttEvent) sorted
- by time for each CPU; events from different CPUs may be slightly out of
- order, especially using the (possibly drifting) cycle counters as
- time unit.
-
- A facility is a list of event types (LttEventType), declared in a special
- eventdefs file. A corresponding checksum differentiates different
- facilities which would have the same name but a different content
- (e.g., different versions). The files are stored within the trace
- directory and are accessed automatically upon opening a trace.
- The list of facilities (and associated checksum) used in a trace
- must be known in order to properly decode the contained events. An event
- is stored in the "facilities" control tracefile to denote each different
- facility used.
-
- Event types (LttEventType) refer to data types (LttType) describing
- their content. The data types supported are integer and unsigned integer
- (of various length), enumerations (a special form of unsigned integer),
- floating point (of various length), fixed size arrays, sequence
- (variable sized arrays), structures and null terminated strings.
- The elements of arrays and sequences, and the data members for
- structures, may be of any nested data type (LttType).
-
- An LttField is a special object to denote a specific, possibly nested,
- field within an event type. Suppose an event type socket_connect is a
- structure containing two data members, source and destination, of type
- socket_address. Type socket_address contains two unsigned integer
- data members, ip and port. An LttField is different from a data type
- structure member since it can denote a specific nested field, like the
- source port, and store associated access information (byte offset within
- the event data). The LttField objects are trace specific since the
- contained information (byte offsets) may vary with the architecture
- associated to the trace. */
-
-typedef struct _LttTrace LttTrace;
-
-typedef struct _LttTracefile LttTracefile;
-
-typedef struct _LttFacility LttFacility;
-
-typedef struct _LttEventType LttEventType;
-
-typedef struct _LttType LttType;
-
-typedef struct _LttField LttField;
-
-typedef struct _LttEvent LttEvent;
-
-typedef struct _LttSystemDescription LttSystemDescription;
-
-/* Checksums are used to differentiate facilities which have the same name
- but differ. */
-
-typedef unsigned long LttChecksum;
-
-
-/* Events are usually stored with the easily obtained CPU clock cycle count,
- ltt_cycle_count. This can be converted to the real time value, LttTime,
- using linear interpolation between regularly sampled values (e.g. a few
- times per second) of the real time clock with their corresponding
- cycle count values. */
-
-
-typedef struct _TimeInterval{
- LttTime startTime;
- LttTime endTime;
-} TimeInterval;
-
-
-typedef guint64 LttCycleCount;
-
-
-/* Event positions are used to seek within a tracefile based on
- the block number and event position within the block. */
-
-typedef struct _LttEventPosition LttEventPosition;
-
-
-/* Differences between architectures include word sizes, endianess,
- alignment, floating point format and calling conventions. For a
- packed binary trace, endianess and size matter, assuming that the
- floating point format is standard (and is seldom used anyway). */
-
-typedef enum _LttArchSize
-{ LTT_LP32, LTT_ILP32, LTT_LP64, LTT_ILP64, LTT_UNKNOWN
-} LttArchSize;
-
-
-typedef enum _LttArchEndian
-{ LTT_LITTLE_ENDIAN, LTT_BIG_ENDIAN
-} LttArchEndian;
-
-typedef enum _LttTypeEnum
-{ LTT_INT, LTT_UINT, LTT_FLOAT, LTT_STRING, LTT_ENUM, LTT_ARRAY,
- LTT_SEQUENCE, LTT_STRUCT, LTT_UNION
-} LttTypeEnum;
-
-
-#endif // LTT_H
+++ /dev/null
-/* This file is part of the Linux Trace Toolkit trace reading library
- * Copyright (C) 2003-2004 Michel Dagenais
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License Version 2.1 as published by the Free Software Foundation.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef LTT_TIME_H
-#define LTT_TIME_H
-
-
-typedef struct _LttTime {
- unsigned long tv_sec;
- unsigned long tv_nsec;
-} LttTime;
-
-
-static const unsigned long NANOSECONDS_PER_SECOND = 1000000000;
-
-static const LttTime ltt_time_zero = { 0, 0};
-
-
-static inline LttTime ltt_time_sub(LttTime t1, LttTime t2)
-{
- LttTime res;
- res.tv_sec = t1.tv_sec - t2.tv_sec;
- if(t1.tv_nsec < t2.tv_nsec) {
- res.tv_sec--;
- res.tv_nsec = NANOSECONDS_PER_SECOND + t1.tv_nsec - t2.tv_nsec;
- }
- else {
- res.tv_nsec = t1.tv_nsec - t2.tv_nsec;
- }
- return res;
-}
-
-
-static inline LttTime ltt_time_add(LttTime t1, LttTime t2)
-{
- LttTime res;
- res.tv_sec = t1.tv_sec + t2.tv_sec;
- res.tv_nsec = t1.tv_nsec + t2.tv_nsec;
- if(res.tv_nsec >= NANOSECONDS_PER_SECOND) {
- res.tv_sec++;
- res.tv_nsec -= NANOSECONDS_PER_SECOND;
- }
- return res;
-}
-
-
-static inline LttTime ltt_time_mul(LttTime t1, float f)
-{
- LttTime res;
- float d;
- double sec;
-
- if(f == 0.0){
- res.tv_sec = 0;
- res.tv_nsec = 0;
- }else{
- d = 1.0/f;
- sec = t1.tv_sec / (double)d;
- res.tv_sec = sec;
- res.tv_nsec = t1.tv_nsec / (double)d + (sec - res.tv_sec) *
- NANOSECONDS_PER_SECOND;
- res.tv_sec += res.tv_nsec / NANOSECONDS_PER_SECOND;
- res.tv_nsec %= NANOSECONDS_PER_SECOND;
- }
- return res;
-}
-
-
-static inline LttTime ltt_time_div(LttTime t1, float f)
-{
- double sec;
- LttTime res;
-
- sec = t1.tv_sec / (double)f;
- res.tv_sec = sec;
- res.tv_nsec = t1.tv_nsec / (double)f + (sec - res.tv_sec) *
- NANOSECONDS_PER_SECOND;
- res.tv_sec += res.tv_nsec / NANOSECONDS_PER_SECOND;
- res.tv_nsec %= NANOSECONDS_PER_SECOND;
- return res;
-}
-
-
-static inline int ltt_time_compare(LttTime t1, LttTime t2)
-{
- if(t1.tv_sec > t2.tv_sec) return 1;
- if(t1.tv_sec < t2.tv_sec) return -1;
- if(t1.tv_nsec > t2.tv_nsec) return 1;
- if(t1.tv_nsec < t2.tv_nsec) return -1;
- return 0;
-}
-
-
-static inline double ltt_time_to_double(LttTime t1)
-{
- return (double)t1.tv_sec + (double)t1.tv_nsec / NANOSECONDS_PER_SECOND;
-}
-
-
-static inline LttTime ltt_time_from_double(double t1)
-{
- LttTime res;
- res.tv_sec = t1;
- res.tv_nsec = (t1 - res.tv_sec) * NANOSECONDS_PER_SECOND;
- return res;
-}
-
-#endif // LTT_TIME_H
+++ /dev/null
-/* This file is part of the Linux Trace Toolkit trace reading library
- * Copyright (C) 2003-2004 Michel Dagenais
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License Version 2.1 as published by the Free Software Foundation.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef TRACE_H
-#define TRACE_H
-
-#include <ltt/ltt.h>
-
-/* A trace is specified as a pathname to the directory containing all the
- associated data (control tracefiles, per cpu tracefiles, event
- descriptions...).
-
- When a trace is closed, all the associated facilities, types and fields
- are released as well. */
-
-LttTrace *ltt_trace_open(const char *pathname);
-
-/* copy reopens a trace */
-LttTrace *ltt_trace_copy(LttTrace *self);
-
-char * ltt_trace_name(LttTrace *t);
-
-void ltt_trace_close(LttTrace *t);
-
-
-LttSystemDescription *ltt_trace_system_description(LttTrace *t);
-
-
-/* Functions to discover the facilities in the trace. Once the number
- of facilities is known, they may be accessed by position. Multiple
- versions of a facility (same name, different checksum) have consecutive
- positions. */
-
-unsigned ltt_trace_facility_number(LttTrace *t);
-
-LttFacility *ltt_trace_facility_get(LttTrace *t, unsigned i);
-
-LttFacility * ltt_trace_facility_by_id(LttTrace * trace, unsigned id);
-
-/* Look for a facility by name. It returns the number of facilities found
- and sets the position argument to the first found. Returning 0, the named
- facility is unknown, returning 1, the named facility is at the specified
- position, returning n, the facilities are from position to
- position + n - 1. */
-
-unsigned ltt_trace_facility_find(LttTrace *t, char *name, unsigned *position);
-
-
-/* Functions to discover all the event types in the trace */
-
-unsigned ltt_trace_eventtype_number(LttTrace *t);
-
-LttEventType *ltt_trace_eventtype_get(LttTrace *t, unsigned i);
-
-
-/* There is one "per cpu" tracefile for each CPU, numbered from 0 to
- the maximum number of CPU in the system. When the number of CPU installed
- is less than the maximum, some positions are unused. There are also a
- number of "control" tracefiles (facilities, interrupts...). */
-
-unsigned ltt_trace_control_tracefile_number(LttTrace *t);
-
-unsigned ltt_trace_per_cpu_tracefile_number(LttTrace *t);
-
-
-/* It is possible to search for the tracefiles by name or by CPU position.
- The index within the tracefiles of the same type is returned if found
- and a negative value otherwise. */
-
-int ltt_trace_control_tracefile_find(LttTrace *t, char *name);
-
-int ltt_trace_per_cpu_tracefile_find(LttTrace *t, unsigned i);
-
-
-/* Get a specific tracefile */
-
-LttTracefile *ltt_trace_control_tracefile_get(LttTrace *t, unsigned i);
-
-LttTracefile *ltt_trace_per_cpu_tracefile_get(LttTrace *t, unsigned i);
-
-
-/* Get the start time and end time of the trace */
-
-void ltt_trace_time_span_get(LttTrace *t, LttTime *start, LttTime *end);
-
-
-/* Get the name of a tracefile */
-
-char *ltt_tracefile_name(LttTracefile *tf);
-
-
-/* Get the number of blocks in the tracefile */
-
-unsigned ltt_tracefile_block_number(LttTracefile *tf);
-
-
-/* Seek to the first event of the trace with time larger or equal to time */
-
-void ltt_tracefile_seek_time(LttTracefile *t, LttTime time);
-
-/* Seek to the first event with position equal or larger to ep */
-
-void ltt_tracefile_seek_position(LttTracefile *t,
- LttEventPosition *ep);
-
-/* Read the next event */
-
-LttEvent *ltt_tracefile_read(LttTracefile *t);
-
-/* open tracefile */
-
-LttTracefile * ltt_tracefile_open(LttTrace *t, char * tracefile_name);
-
-void ltt_tracefile_open_cpu(LttTrace *t, char * tracefile_name);
-
-void ltt_tracefile_open_control(LttTrace *t, char * control_name);
-
-
-/* obtain the time of an event */
-
-LttTime getEventTime(LttTracefile * tf);
-
-
-/* get the data type size and endian type of the local machine */
-
-void getDataEndianType(LttArchSize * size, LttArchEndian * endian);
-
-/* get an integer number */
-
-int getIntNumber(int size1, void *evD);
-
-
-/* get the node name of the system */
-
-char * ltt_trace_system_description_node_name (LttSystemDescription * s);
-
-
-/* get the domain name of the system */
-
-char * ltt_trace_system_description_domain_name (LttSystemDescription * s);
-
-
-/* get the description of the system */
-
-char * ltt_trace_system_description_description (LttSystemDescription * s);
-
-
-/* get the start time of the trace */
-
-LttTime ltt_trace_system_description_trace_start_time(LttSystemDescription *s);
-
-#endif // TRACE_H
+++ /dev/null
-/* This file is part of the Linux Trace Toolkit trace reading library
- * Copyright (C) 2003-2004 Michel Dagenais
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License Version 2.1 as published by the Free Software Foundation.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef TYPE_H
-#define TYPE_H
-
-
-/* Different types allowed */
-
-#include <ltt/ltt.h>
-
-
-/* All event types, data types and fields belong to their trace and
- are released at the same time. */
-
-/* Obtain the name, description, facility, facility relative id, global id,
- type and root field for an eventtype */
-
-char *ltt_eventtype_name(LttEventType *et);
-
-char *ltt_eventtype_description(LttEventType *et);
-
-LttFacility *ltt_eventtype_facility(LttEventType *et);
-
-unsigned ltt_eventtype_relative_id(LttEventType *et);
-
-unsigned ltt_eventtype_id(LttEventType *et);
-
-LttType *ltt_eventtype_type(LttEventType *et);
-
-LttField *ltt_eventtype_field(LttEventType *et);
-
-
-/* obtain the type name and size. The size is the number of bytes for
- primitive types (INT, UINT, FLOAT, ENUM), or the size for the unsigned
- integer length count for sequences. */
-
-char *ltt_type_name(LttType *t);
-
-LttTypeEnum ltt_type_class(LttType *t);
-
-unsigned ltt_type_size(LttTrace *trace, LttType *t);
-
-
-/* The type of nested elements for arrays and sequences. */
-
-LttType *ltt_type_element_type(LttType *t);
-
-
-/* The number of elements for arrays. */
-
-unsigned ltt_type_element_number(LttType *t);
-
-
-/* The number of data members for structures and unions. */
-
-unsigned ltt_type_member_number(LttType *t);
-
-
-/* The type of a data member in a structure. */
-
-LttType *ltt_type_member_type(LttType *t, unsigned i, char ** name);
-
-
-/* For enumerations, obtain the symbolic string associated with a value
- (0 to n - 1 for an enumeration of n elements). */
-
-char *ltt_enum_string_get(LttType *t, unsigned i);
-
-
-/* The fields form a tree representing a depth first search of the
- corresponding event type directed acyclic graph. Fields for arrays and
- sequences simply point to one nested field representing the currently
- selected element among all the (identically typed) elements. For structures,
- a nested field exists for each data member. Each field stores the
- platform/trace specific offset values (for efficient access) and
- points back to the corresponding LttType for the rest. */
-
-LttField *ltt_field_element(LttField *f);
-
-LttField *ltt_field_member(LttField *f, unsigned i);
-
-LttType *ltt_field_type(LttField *f);
-
-int ltt_field_size(LttField * f);
-
-#endif // TYPE_H
#include <glib-object.h>
#include <lttv/iattribute.h>
+#include <stdio.h>
#define LTTV_ATTRIBUTE_TYPE (lttv_attribute_get_type ())
#define LTTV_ATTRIBUTE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LTTV_ATTRIBUTE_TYPE, LttvAttribute))
void lttv_attribute_recursive_add(LttvAttribute *dest, LttvAttribute *src);
+void
+lttv_attribute_write_xml(LttvAttribute *self, FILE *fp, int pos, int indent);
+
+void lttv_attribute_read_xml(LttvAttribute *self, FILE *fp);
+
#endif // ATTRIBUTE_H
* MA 02111-1307, USA.
*/
+/*
+CHECK Rename to viewer.h
+
+Things that can happen to a viewer:
+
+update_time_window
+update_current_time
+update_traceset
+update_filter
+show_viewer
+update_dividor
+?? Reshape, damage ??
+
+Things that a viewer can do:
+
+update_status
+set_time_window
+set_current_time
+update_traceset?
+update_filter?
+show_viewer?
+set_focused_pane
+set_hpane_dividor
+*/
+
+
+
+
/*! \file gtktraceset.h
* \brief API used by the graphical viewers to interact with their top window.
*
void set_hpane_dividor(MainWindow *main_win, gint position);
+/*
+CHECK These functions really should not appear here. Directr calls would
+be OK unless there is a linker problem.
+*/
/**
* Function to process traceset. It will call lttv_process_trace,
* each view will call this api to get events.
void lttv_state_restore(LttvTraceState *self, LttvAttribute *container);
-void lttv_state_saved_state_free(LttvTraceState *self,
+void lttv_state_state_saved_free(LttvTraceState *self,
LttvAttribute *container);
gboolean lttv_stats_remove_event_hooks(LttvTracesetStats *self);
-void lttv_stats_save_statistics(LttvTracesetStats *self);
+void lttv_stats_sum_traceset(LttvTracesetStats *self);
-gboolean lttv_stats_load_statistics(LttvTracesetStats *self);
+void lttv_stats_sum_trace(LttvTraceStats *self);
/* The LttvTracesetStats, LttvTraceStats and LttvTracefileStats types
libtraceread_la_SOURCES = event.c facility.c parser.c tracefile.c type.c
noinst_HEADERS = parser.h ltt-private.h
+lttinclude_HEADERS = \
+ event.h\
+ facility.h\
+ ltt.h\
+ time.h\
+ trace.h\
+ type.h
EXTRA_DIST = crc32.tab
--- /dev/null
+/* This file is part of the Linux Trace Toolkit trace reading library
+ * Copyright (C) 2003-2004 Michel Dagenais
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License Version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef EVENT_H
+#define EVENT_H
+
+#include <ltt/ltt.h>
+
+/* Events and their content, including the raw data, are only valid
+ until reading another event from the same tracefile.
+ Indeed, since event reading is critical to the performance,
+ the memory associated with an event may be reused at each read. */
+
+
+/* Obtain the trace unique integer id associated with the type of
+ this event */
+
+unsigned ltt_event_eventtype_id(LttEvent *e);
+
+
+/* Facility and type for the event */
+
+LttFacility *ltt_event_facility(LttEvent *e);
+
+LttEventType *ltt_event_eventtype(LttEvent *e);
+
+
+/* Root field for the event */
+
+LttField *ltt_event_field(LttEvent *e);
+
+
+/* Time and cycle count for the event */
+
+LttTime ltt_event_time(LttEvent *e);
+
+LttCycleCount ltt_event_cycle_count(LttEvent *e);
+
+
+/* Obtain the position of the event within the tracefile. This
+ is used to seek back to this position later or to seek to another
+ position, computed relative to this position. The event position
+ structure is opaque and contains several fields, only two
+ of which are user accessible: block number and event index
+ within the block. */
+
+void ltt_event_position(LttEvent *e, LttEventPosition *ep);
+
+LttEventPosition * ltt_event_position_new();
+
+void ltt_event_position_get(LttEventPosition *ep,
+ unsigned *block_number, unsigned *index_in_block, LttTracefile ** tf);
+
+void ltt_event_position_set(LttEventPosition *ep,
+ unsigned block_number, unsigned index_in_block);
+
+
+/* CPU id of the event */
+
+unsigned ltt_event_cpu_id(LttEvent *e);
+
+
+/* Pointer to the raw data for the event. This should not be used directly
+ unless prepared to do all the architecture specific conversions. */
+
+void *ltt_event_data(LttEvent *e);
+
+
+/* The number of elements in a sequence field is specific to each event
+ instance. This function returns the number of elements for an array or
+ sequence field in an event. */
+
+unsigned ltt_event_field_element_number(LttEvent *e, LttField *f);
+
+
+/* Set the currently selected element for a sequence or array field. */
+
+void ltt_event_field_element_select(LttEvent *e, LttField *f, unsigned i);
+
+
+/* A union is like a structure except that only a single member at a time
+ is present depending on the specific event instance. This function tells
+ the active member for a union field in an event. */
+
+unsigned ltt_event_field_union_member(LttEvent *e, LttField *f);
+
+
+/* These functions extract data from an event after architecture specific
+ conversions. */
+
+unsigned ltt_event_get_unsigned(LttEvent *e, LttField *f);
+
+int ltt_event_get_int(LttEvent *e, LttField *f);
+
+unsigned long ltt_event_get_long_unsigned(LttEvent *e, LttField *f);
+
+long int ltt_event_get_long_int(LttEvent *e, LttField *f);
+
+float ltt_event_get_float(LttEvent *e, LttField *f);
+
+double ltt_event_get_double(LttEvent *e, LttField *f);
+
+
+/* The string obtained is only valid until the next read from
+ the same tracefile. */
+
+char *ltt_event_get_string(LttEvent *e, LttField *f);
+
+#endif // EVENT_H
--- /dev/null
+/* This file is part of the Linux Trace Toolkit trace reading library
+ * Copyright (C) 2003-2004 Michel Dagenais
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License Version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef FACILITY_H
+#define FACILITY_H
+
+#include <ltt/ltt.h>
+
+/* Facilities are obtained from an opened trace. The structures associated
+ with a facility are released when the trace is closed. Each facility
+ is characterized by its name and checksum. */
+
+char *ltt_facility_name(LttFacility *f);
+
+LttChecksum ltt_facility_checksum(LttFacility *f);
+
+/* open facility */
+void ltt_facility_open(LttTrace * t, char * facility_name);
+
+/* Discover the event types within the facility. The event type integer id
+ relative to the trace is from 0 to nb_event_types - 1. The event
+ type id within the trace is the relative id + the facility base event
+ id. */
+
+unsigned ltt_facility_base_id(LttFacility *f);
+
+unsigned ltt_facility_eventtype_number(LttFacility *f);
+
+LttEventType *ltt_facility_eventtype_get(LttFacility *f, unsigned i);
+
+LttEventType *ltt_facility_eventtype_get_by_name(LttFacility *f, char *name);
+
+#endif // FACILITY_H
+
--- /dev/null
+/* This file is part of the Linux Trace Toolkit trace reading library
+ * Copyright (C) 2003-2004 Michel Dagenais
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License Version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef LTT_H
+#define LTT_H
+
+#include <ltt/time.h>
+#include <glib.h>
+
+/* A trace is associated with a tracing session run on a single, possibly
+ multi-cpu, system. It is defined as a pathname to a directory containing
+ all the relevant trace files. All the tracefiles for a trace were
+ generated in a single system for the same time period by the same
+ trace daemon. They simply contain different events. Typically control
+ tracefiles contain the important events (process creations and registering
+ tracing facilities) for all CPUs, and one file for each CPU contains all
+ the events for that CPU. All the tracefiles within the same trace directory
+ then use the exact same id numbers for event types.
+
+ A tracefile (LttTracefile) contains a list of events (LttEvent) sorted
+ by time for each CPU; events from different CPUs may be slightly out of
+ order, especially using the (possibly drifting) cycle counters as
+ time unit.
+
+ A facility is a list of event types (LttEventType), declared in a special
+ eventdefs file. A corresponding checksum differentiates different
+ facilities which would have the same name but a different content
+ (e.g., different versions). The files are stored within the trace
+ directory and are accessed automatically upon opening a trace.
+ The list of facilities (and associated checksum) used in a trace
+ must be known in order to properly decode the contained events. An event
+ is stored in the "facilities" control tracefile to denote each different
+ facility used.
+
+ Event types (LttEventType) refer to data types (LttType) describing
+ their content. The data types supported are integer and unsigned integer
+ (of various length), enumerations (a special form of unsigned integer),
+ floating point (of various length), fixed size arrays, sequence
+ (variable sized arrays), structures and null terminated strings.
+ The elements of arrays and sequences, and the data members for
+ structures, may be of any nested data type (LttType).
+
+ An LttField is a special object to denote a specific, possibly nested,
+ field within an event type. Suppose an event type socket_connect is a
+ structure containing two data members, source and destination, of type
+ socket_address. Type socket_address contains two unsigned integer
+ data members, ip and port. An LttField is different from a data type
+ structure member since it can denote a specific nested field, like the
+ source port, and store associated access information (byte offset within
+ the event data). The LttField objects are trace specific since the
+ contained information (byte offsets) may vary with the architecture
+ associated to the trace. */
+
+typedef struct _LttTrace LttTrace;
+
+typedef struct _LttTracefile LttTracefile;
+
+typedef struct _LttFacility LttFacility;
+
+typedef struct _LttEventType LttEventType;
+
+typedef struct _LttType LttType;
+
+typedef struct _LttField LttField;
+
+typedef struct _LttEvent LttEvent;
+
+typedef struct _LttSystemDescription LttSystemDescription;
+
+/* Checksums are used to differentiate facilities which have the same name
+ but differ. */
+
+typedef unsigned long LttChecksum;
+
+
+/* Events are usually stored with the easily obtained CPU clock cycle count,
+ ltt_cycle_count. This can be converted to the real time value, LttTime,
+ using linear interpolation between regularly sampled values (e.g. a few
+ times per second) of the real time clock with their corresponding
+ cycle count values. */
+
+
+typedef struct _TimeInterval{
+ LttTime startTime;
+ LttTime endTime;
+} TimeInterval;
+
+
+typedef guint64 LttCycleCount;
+
+
+/* Event positions are used to seek within a tracefile based on
+ the block number and event position within the block. */
+
+typedef struct _LttEventPosition LttEventPosition;
+
+
+/* Differences between architectures include word sizes, endianess,
+ alignment, floating point format and calling conventions. For a
+ packed binary trace, endianess and size matter, assuming that the
+ floating point format is standard (and is seldom used anyway). */
+
+typedef enum _LttArchSize
+{ LTT_LP32, LTT_ILP32, LTT_LP64, LTT_ILP64, LTT_UNKNOWN
+} LttArchSize;
+
+
+typedef enum _LttArchEndian
+{ LTT_LITTLE_ENDIAN, LTT_BIG_ENDIAN
+} LttArchEndian;
+
+typedef enum _LttTypeEnum
+{ LTT_INT, LTT_UINT, LTT_FLOAT, LTT_STRING, LTT_ENUM, LTT_ARRAY,
+ LTT_SEQUENCE, LTT_STRUCT, LTT_UNION
+} LttTypeEnum;
+
+
+#endif // LTT_H
--- /dev/null
+/* This file is part of the Linux Trace Toolkit trace reading library
+ * Copyright (C) 2003-2004 Michel Dagenais
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License Version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef LTT_TIME_H
+#define LTT_TIME_H
+
+
+typedef struct _LttTime {
+ unsigned long tv_sec;
+ unsigned long tv_nsec;
+} LttTime;
+
+
+static const unsigned long NANOSECONDS_PER_SECOND = 1000000000;
+
+static const LttTime ltt_time_zero = { 0, 0};
+
+
+static inline LttTime ltt_time_sub(LttTime t1, LttTime t2)
+{
+ LttTime res;
+ res.tv_sec = t1.tv_sec - t2.tv_sec;
+ if(t1.tv_nsec < t2.tv_nsec) {
+ res.tv_sec--;
+ res.tv_nsec = NANOSECONDS_PER_SECOND + t1.tv_nsec - t2.tv_nsec;
+ }
+ else {
+ res.tv_nsec = t1.tv_nsec - t2.tv_nsec;
+ }
+ return res;
+}
+
+
+static inline LttTime ltt_time_add(LttTime t1, LttTime t2)
+{
+ LttTime res;
+ res.tv_sec = t1.tv_sec + t2.tv_sec;
+ res.tv_nsec = t1.tv_nsec + t2.tv_nsec;
+ if(res.tv_nsec >= NANOSECONDS_PER_SECOND) {
+ res.tv_sec++;
+ res.tv_nsec -= NANOSECONDS_PER_SECOND;
+ }
+ return res;
+}
+
+
+static inline LttTime ltt_time_mul(LttTime t1, float f)
+{
+ LttTime res;
+ float d;
+ double sec;
+
+ if(f == 0.0){
+ res.tv_sec = 0;
+ res.tv_nsec = 0;
+ }else{
+ d = 1.0/f;
+ sec = t1.tv_sec / (double)d;
+ res.tv_sec = sec;
+ res.tv_nsec = t1.tv_nsec / (double)d + (sec - res.tv_sec) *
+ NANOSECONDS_PER_SECOND;
+ res.tv_sec += res.tv_nsec / NANOSECONDS_PER_SECOND;
+ res.tv_nsec %= NANOSECONDS_PER_SECOND;
+ }
+ return res;
+}
+
+
+static inline LttTime ltt_time_div(LttTime t1, float f)
+{
+ double sec;
+ LttTime res;
+
+ sec = t1.tv_sec / (double)f;
+ res.tv_sec = sec;
+ res.tv_nsec = t1.tv_nsec / (double)f + (sec - res.tv_sec) *
+ NANOSECONDS_PER_SECOND;
+ res.tv_sec += res.tv_nsec / NANOSECONDS_PER_SECOND;
+ res.tv_nsec %= NANOSECONDS_PER_SECOND;
+ return res;
+}
+
+
+static inline int ltt_time_compare(LttTime t1, LttTime t2)
+{
+ if(t1.tv_sec > t2.tv_sec) return 1;
+ if(t1.tv_sec < t2.tv_sec) return -1;
+ if(t1.tv_nsec > t2.tv_nsec) return 1;
+ if(t1.tv_nsec < t2.tv_nsec) return -1;
+ return 0;
+}
+
+
+static inline double ltt_time_to_double(LttTime t1)
+{
+ return (double)t1.tv_sec + (double)t1.tv_nsec / NANOSECONDS_PER_SECOND;
+}
+
+
+static inline LttTime ltt_time_from_double(double t1)
+{
+ LttTime res;
+ res.tv_sec = t1;
+ res.tv_nsec = (t1 - res.tv_sec) * NANOSECONDS_PER_SECOND;
+ return res;
+}
+
+#endif // LTT_TIME_H
--- /dev/null
+/* This file is part of the Linux Trace Toolkit trace reading library
+ * Copyright (C) 2003-2004 Michel Dagenais
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License Version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef TRACE_H
+#define TRACE_H
+
+#include <ltt/ltt.h>
+
+/* A trace is specified as a pathname to the directory containing all the
+ associated data (control tracefiles, per cpu tracefiles, event
+ descriptions...).
+
+ When a trace is closed, all the associated facilities, types and fields
+ are released as well. */
+
+LttTrace *ltt_trace_open(const char *pathname);
+
+/* copy reopens a trace */
+LttTrace *ltt_trace_copy(LttTrace *self);
+
+char * ltt_trace_name(LttTrace *t);
+
+void ltt_trace_close(LttTrace *t);
+
+
+LttSystemDescription *ltt_trace_system_description(LttTrace *t);
+
+
+/* Functions to discover the facilities in the trace. Once the number
+ of facilities is known, they may be accessed by position. Multiple
+ versions of a facility (same name, different checksum) have consecutive
+ positions. */
+
+unsigned ltt_trace_facility_number(LttTrace *t);
+
+LttFacility *ltt_trace_facility_get(LttTrace *t, unsigned i);
+
+LttFacility * ltt_trace_facility_by_id(LttTrace * trace, unsigned id);
+
+/* Look for a facility by name. It returns the number of facilities found
+ and sets the position argument to the first found. Returning 0, the named
+ facility is unknown, returning 1, the named facility is at the specified
+ position, returning n, the facilities are from position to
+ position + n - 1. */
+
+unsigned ltt_trace_facility_find(LttTrace *t, char *name, unsigned *position);
+
+
+/* Functions to discover all the event types in the trace */
+
+unsigned ltt_trace_eventtype_number(LttTrace *t);
+
+LttEventType *ltt_trace_eventtype_get(LttTrace *t, unsigned i);
+
+
+/* There is one "per cpu" tracefile for each CPU, numbered from 0 to
+ the maximum number of CPU in the system. When the number of CPU installed
+ is less than the maximum, some positions are unused. There are also a
+ number of "control" tracefiles (facilities, interrupts...). */
+
+unsigned ltt_trace_control_tracefile_number(LttTrace *t);
+
+unsigned ltt_trace_per_cpu_tracefile_number(LttTrace *t);
+
+
+/* It is possible to search for the tracefiles by name or by CPU position.
+ The index within the tracefiles of the same type is returned if found
+ and a negative value otherwise. */
+
+int ltt_trace_control_tracefile_find(LttTrace *t, char *name);
+
+int ltt_trace_per_cpu_tracefile_find(LttTrace *t, unsigned i);
+
+
+/* Get a specific tracefile */
+
+LttTracefile *ltt_trace_control_tracefile_get(LttTrace *t, unsigned i);
+
+LttTracefile *ltt_trace_per_cpu_tracefile_get(LttTrace *t, unsigned i);
+
+
+/* Get the start time and end time of the trace */
+
+void ltt_trace_time_span_get(LttTrace *t, LttTime *start, LttTime *end);
+
+
+/* Get the name of a tracefile */
+
+char *ltt_tracefile_name(LttTracefile *tf);
+
+
+/* Get the number of blocks in the tracefile */
+
+unsigned ltt_tracefile_block_number(LttTracefile *tf);
+
+
+/* Seek to the first event of the trace with time larger or equal to time */
+
+void ltt_tracefile_seek_time(LttTracefile *t, LttTime time);
+
+/* Seek to the first event with position equal or larger to ep */
+
+void ltt_tracefile_seek_position(LttTracefile *t,
+ LttEventPosition *ep);
+
+/* Read the next event */
+
+LttEvent *ltt_tracefile_read(LttTracefile *t);
+
+/* open tracefile */
+
+LttTracefile * ltt_tracefile_open(LttTrace *t, char * tracefile_name);
+
+void ltt_tracefile_open_cpu(LttTrace *t, char * tracefile_name);
+
+void ltt_tracefile_open_control(LttTrace *t, char * control_name);
+
+
+/* obtain the time of an event */
+
+LttTime getEventTime(LttTracefile * tf);
+
+
+/* get the data type size and endian type of the local machine */
+
+void getDataEndianType(LttArchSize * size, LttArchEndian * endian);
+
+/* get an integer number */
+
+int getIntNumber(int size1, void *evD);
+
+
+/* get the node name of the system */
+
+char * ltt_trace_system_description_node_name (LttSystemDescription * s);
+
+
+/* get the domain name of the system */
+
+char * ltt_trace_system_description_domain_name (LttSystemDescription * s);
+
+
+/* get the description of the system */
+
+char * ltt_trace_system_description_description (LttSystemDescription * s);
+
+
+/* get the start time of the trace */
+
+LttTime ltt_trace_system_description_trace_start_time(LttSystemDescription *s);
+
+#endif // TRACE_H
--- /dev/null
+/* This file is part of the Linux Trace Toolkit trace reading library
+ * Copyright (C) 2003-2004 Michel Dagenais
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License Version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef TYPE_H
+#define TYPE_H
+
+
+/* Different types allowed */
+
+#include <ltt/ltt.h>
+
+
+/* All event types, data types and fields belong to their trace and
+ are released at the same time. */
+
+/* Obtain the name, description, facility, facility relative id, global id,
+ type and root field for an eventtype */
+
+char *ltt_eventtype_name(LttEventType *et);
+
+char *ltt_eventtype_description(LttEventType *et);
+
+LttFacility *ltt_eventtype_facility(LttEventType *et);
+
+unsigned ltt_eventtype_relative_id(LttEventType *et);
+
+unsigned ltt_eventtype_id(LttEventType *et);
+
+LttType *ltt_eventtype_type(LttEventType *et);
+
+LttField *ltt_eventtype_field(LttEventType *et);
+
+
+/* obtain the type name and size. The size is the number of bytes for
+ primitive types (INT, UINT, FLOAT, ENUM), or the size for the unsigned
+ integer length count for sequences. */
+
+char *ltt_type_name(LttType *t);
+
+LttTypeEnum ltt_type_class(LttType *t);
+
+unsigned ltt_type_size(LttTrace *trace, LttType *t);
+
+
+/* The type of nested elements for arrays and sequences. */
+
+LttType *ltt_type_element_type(LttType *t);
+
+
+/* The number of elements for arrays. */
+
+unsigned ltt_type_element_number(LttType *t);
+
+
+/* The number of data members for structures and unions. */
+
+unsigned ltt_type_member_number(LttType *t);
+
+
+/* The type of a data member in a structure. */
+
+LttType *ltt_type_member_type(LttType *t, unsigned i, char ** name);
+
+
+/* For enumerations, obtain the symbolic string associated with a value
+ (0 to n - 1 for an enumeration of n elements). */
+
+char *ltt_enum_string_get(LttType *t, unsigned i);
+
+
+/* The fields form a tree representing a depth first search of the
+ corresponding event type directed acyclic graph. Fields for arrays and
+ sequences simply point to one nested field representing the currently
+ selected element among all the (identically typed) elements. For structures,
+ a nested field exists for each data member. Each field stores the
+ platform/trace specific offset values (for efficient access) and
+ points back to the corresponding LttType for the rest. */
+
+LttField *ltt_field_element(LttField *f);
+
+LttField *ltt_field_member(LttField *f, unsigned i);
+
+LttType *ltt_field_type(LttField *f);
+
+int ltt_field_size(LttField * f);
+
+#endif // TYPE_H
}
+static void
+print_indent(FILE *fp, int pos)
+{
+ int i;
+
+ for(i = 0 ; i < pos ; i++) putc(' ', fp);
+}
+
+
+void
+lttv_attribute_write_xml(LttvAttribute *self, FILE *fp, int pos, int indent)
+{
+ int i, nb;
+
+ Attribute *a;
+
+ nb = self->attributes->len;
+
+ fprintf(fp,"<ATTRS>\n");
+ for(i = 0 ; i < nb ; i++) {
+ a = &g_array_index(self->attributes, Attribute, i);
+ print_indent(fp, pos);
+ fprintf(fp, "<ATTR NAME=\"%s\" ", a->name);
+ if(a->type == LTTV_GOBJECT && LTTV_IS_ATTRIBUTE(a->value.dv_gobject)) {
+ fprintf(fp, "TYPE=ATTRS>");
+ lttv_attribute_write_xml((LttvAttribute *)(a->value.dv_gobject), fp,
+ pos + indent, indent);
+ }
+ else {
+ switch(a->type) {
+ case LTTV_INT:
+ fprintf(fp, "TYPE=INT VALUE=%d/>\n", a->value.dv_int);
+ break;
+ case LTTV_UINT:
+ fprintf(fp, "TYPE=UINT VALUE=%u/>\n", a->value.dv_uint);
+ break;
+ case LTTV_LONG:
+ fprintf(fp, "TYPE=LONG VALUE=%ld/>\n", a->value.dv_long);
+ break;
+ case LTTV_ULONG:
+ fprintf(fp, "TYPE=ULONG VALUE=%lu/>\n", a->value.dv_ulong);
+ break;
+ case LTTV_FLOAT:
+ fprintf(fp, "TYPE=FLOAT VALUE=%f/>\n", a->value.dv_float);
+ break;
+ case LTTV_DOUBLE:
+ fprintf(fp, "TYPE=DOUBLE VALUE=%f/>\n", a->value.dv_double);
+ break;
+ case LTTV_TIME:
+ fprintf(fp, "TYPE=TIME SEC=%u NSEC=%u/>\n", a->value.dv_time.tv_sec,
+ a->value.dv_time.tv_nsec);
+ break;
+ case LTTV_POINTER:
+ fprintf(fp, "TYPE=POINTER VALUE=%p/>\n", a->value.dv_pointer);
+ break;
+ case LTTV_STRING:
+ fprintf(fp, "TYPE=STRING VALUE=\"%s\"/>\n", a->value.dv_string);
+ break;
+ case LTTV_GOBJECT:
+ fprintf(fp, "TYPE=GOBJECT VALUE=%p/>\n", a->value.dv_gobject);
+ break;
+ case LTTV_NONE:
+ fprintf(fp, "TYPE=NONE/>\n");
+ break;
+ }
+ }
+ }
+ print_indent(fp, pos);
+ fprintf(fp,"</ATTRS>\n");
+}
+
+
+void
+lttv_attribute_read_xml(LttvAttribute *self, FILE *fp)
+{
+ int i, nb, res;
+
+ Attribute *a;
+
+ char buffer[256], type[10];
+
+ LttvAttributeName name;
+
+ LttvAttributeValue value;
+
+ LttvAttribute *subtree;
+
+ fscanf(fp,"<ATTRS>");
+ while(1) {
+ res = fscanf(fp, "<ATTR NAME=\"%256[^\"]\" TYPE=%10[^ >]", buffer, type);
+ g_assert(res == 2);
+ name = g_quark_from_string(buffer);
+ if(strcmp(type, "ATTRS") == 0) {
+ fscanf(fp, ">");
+ subtree = lttv_attribute_find_subdir(self, name);
+ lttv_attribute_read_xml(subtree, fp);
+ }
+ else if(strcmp(type, "INT") == 0) {
+ value = lttv_attribute_add(self, name, LTTV_INT);
+ res = fscanf(fp, " VALUE=%d/>", value.v_int);
+ g_assert(res == 1);
+ }
+ else if(strcmp(type, "UINT") == 0) {
+ value = lttv_attribute_add(self, name, LTTV_UINT);
+ res = fscanf(fp, " VALUE=%u/>", value.v_uint);
+ g_assert(res == 1);
+ }
+ else if(strcmp(type, "LONG") == 0) {
+ value = lttv_attribute_add(self, name, LTTV_LONG);
+ res = fscanf(fp, " VALUE=%ld/>", value.v_long);
+ g_assert(res == 1);
+ }
+ else if(strcmp(type, "ULONG") == 0) {
+ value = lttv_attribute_add(self, name, LTTV_ULONG);
+ res = fscanf(fp, " VALUE=%lu/>", value.v_ulong);
+ g_assert(res == 1);
+ }
+ else if(strcmp(type, "FLOAT") == 0) {
+ float d;
+ value = lttv_attribute_add(self, name, LTTV_FLOAT);
+ res = fscanf(fp, " VALUE=%f/>", &d);
+ *(value.v_float) = d;
+ g_assert(res == 1);
+ }
+ else if(strcmp(type, "DOUBLE") == 0) {
+ value = lttv_attribute_add(self, name, LTTV_DOUBLE);
+ res = fscanf(fp, " VALUE=%f/>", value.v_double);
+ g_assert(res == 1);
+ }
+ else if(strcmp(type, "TIME") == 0) {
+ value = lttv_attribute_add(self, name, LTTV_TIME);
+ res = fscanf(fp, " SEC=%u NSEC=%u/>", &(value.v_time->tv_sec),
+ &(value.v_time->tv_nsec));
+ g_assert(res == 2);
+ }
+ else if(strcmp(type, "POINTER") == 0) {
+ value = lttv_attribute_add(self, name, LTTV_POINTER);
+ res = fscanf(fp, " VALUE=%p/>", value.v_pointer);
+ g_error("Cannot read a pointer");
+ }
+ else if(strcmp(type, "STRING") == 0) {
+ value = lttv_attribute_add(self, name, LTTV_STRING);
+ res = fscanf(fp, " VALUE=\"%256[^\"]\"/>", buffer);
+ *(value.v_string) = g_strdup(buffer);
+ g_assert(res == 1);
+ }
+ else if(strcmp(type, "GOBJECT") == 0) {
+ value = lttv_attribute_add(self, name, LTTV_GOBJECT);
+ res = fscanf(fp, " VALUE=%p/>", value.v_gobject);
+ g_error("Cannot read a pointer");
+ }
+ else if(strcmp(type, "NONE") == 0) {
+ value = lttv_attribute_add(self, name, LTTV_NONE);
+ fscanf(fp, "/>");
+ }
+ else g_error("Unknown type to read");
+ }
+ fscanf(fp,"</ATTRS>");
+}
+
+
static void
attribute_interface_init (gpointer g_iface, gpointer iface_data)
{
gint compare_tracefile(gconstpointer a, gconstpointer b)
{
- return ltt_time_compare(*((LttTime *)a), *((LttTime *)b));
+ gint comparison;
+
+ LttvTracefileContext *trace_a = (LttvTracefileContext *)a;
+
+ LttvTracefileContext *trace_b = (LttvTracefileContext *)b;
+
+ if(trace_a == trace_b) return 0;
+ comparison = ltt_time_compare(trace_a->timestamp, trace_b->timestamp);
+ if(comparison != 0) return comparison;
+ if(trace_a->index < trace_b->index) return -1;
+ else if(trace_a->index > trace_b->index) return 1;
+ if(trace_a->t_context->index < trace_b->t_context->index) return -1;
+ else if(trace_a->t_context->index > trace_b->t_context->index) return 1;
+ g_assert(FALSE);
}
if(tfc->timestamp.tv_sec < end.tv_sec ||
(tfc->timestamp.tv_sec == end.tv_sec &&
tfc->timestamp.tv_nsec <= end.tv_nsec)) {
- g_tree_insert(self->pqueue, &(tfc->timestamp), tfc);
+ g_tree_insert(self->pqueue, tfc, tfc);
}
}
}
or more tracefiles have events for the same time, hope that lookup
and remove are consistent. */
- tfc = g_tree_lookup(pqueue, &(tfc->timestamp));
- g_tree_remove(pqueue, &(tfc->timestamp));
+ g_tree_remove(pqueue, tfc);
count++;
if(!lttv_hooks_call(tfc->check_event, tfc)) {
tfc->timestamp = ltt_event_time(event);
if(tfc->timestamp.tv_sec < end.tv_sec ||
(tfc->timestamp.tv_sec == end.tv_sec && tfc->timestamp.tv_nsec <= end.tv_nsec))
- g_tree_insert(pqueue, &(tfc->timestamp), tfc);
+ g_tree_insert(pqueue, tfc, tfc);
}
}
}
#include <ltt/trace.h>
#include <ltt/event.h>
#include <ltt/type.h>
+#include <stdio.h>
LttvExecutionMode
LTTV_STATE_MODE_UNKNOWN,
LTTV_STATE_SAVED_STATES,
LTTV_STATE_SAVED_STATES_TIME,
LTTV_STATE_TIME,
- LTTV_STATE_HOOKS;
+ LTTV_STATE_HOOKS,
+ LTTV_STATE_NAME_TABLES,
+ LTTV_STATE_TRACE_STATE_USE_COUNT;
-static void fill_name_tables(LttvTraceState *tcs);
+static void create_max_time(LttvTraceState *tcs);
+
+static void get_max_time(LttvTraceState *tcs);
+
+static void free_max_time(LttvTraceState *tcs);
+
+static void create_name_tables(LttvTraceState *tcs);
+
+static void get_name_tables(LttvTraceState *tcs);
static void free_name_tables(LttvTraceState *tcs);
+static void free_saved_state(LttvTraceState *tcs);
+
static void lttv_state_free_process_table(GHashTable *processes);
}
-void lttv_state_saved_state_free(LttvTraceState *self,
+void lttv_state__state_saved_free(LttvTraceState *self,
LttvAttribute *container)
{
- LTTV_TRACE_STATE_GET_CLASS(self)->state_restore(self, container);
+ LTTV_TRACE_STATE_GET_CLASS(self)->state_saved_free(self, container);
}
tc = self->parent.traces[i];
tcs = (LttvTraceState *)tc;
tcs->save_interval = 50000;
- lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_SAVED_STATES_TIME,
- LTTV_POINTER, &v);
- if(*(v.v_pointer) == NULL) {
- *(v.v_pointer) = g_new(LttTime,1);
- *((LttTime *)*(v.v_pointer)) = time_zero;
- }
- tcs->max_time_state_recomputed_in_seek = (LttTime *)*(v.v_pointer);
+ lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_TRACE_STATE_USE_COUNT,
+ LTTV_UINT, &v);
+ (*v.v_uint)++;
- fill_name_tables(tcs);
+ if(*(v.v_uint) == 1) {
+ create_name_tables(tcs);
+ create_max_time(tcs);
+ }
+ get_name_tables(tcs);
+ get_max_time(tcs);
nb_tracefile = ltt_trace_control_tracefile_number(tc->t) +
ltt_trace_per_cpu_tracefile_number(tc->t);
LttvTracefileState *tfcs;
+ LttvAttributeValue v;
+
nb_trace = lttv_traceset_number(LTTV_TRACESET_CONTEXT(self)->ts);
for(i = 0 ; i < nb_trace ; i++) {
tcs = (LttvTraceState *)(LTTV_TRACESET_CONTEXT(self)->traces[i]);
+ lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_TRACE_STATE_USE_COUNT,
+ LTTV_UINT, &v);
+ (*v.v_uint)--;
+
+ g_assert(*(v.v_uint) >= 0);
+ if(*(v.v_uint) == 0) {
+ free_name_tables(tcs);
+ free_max_time(tcs);
+ free_saved_state(tcs);
+ }
lttv_state_free_process_table(tcs->processes);
tcs->processes = NULL;
- free_name_tables(tcs);
}
LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE))->
fini((LttvTracesetContext *)self);
process = (LttvProcessState *)value;
fprintf(fp,
-" <PROCESS PID=%u PPID=%u CTIME_S=%lu CTIME_NS=%lu NAME=\"%s\" CPU=\"%s\">\n",
- process->pid, process->ppid, process->creation_time.tv_sec,
+" <PROCESS CORE=%p PID=%u PPID=%u CTIME_S=%lu CTIME_NS=%lu NAME=\"%s\" CPU=\"%s\">\n",
+ process, process->pid, process->ppid, process->creation_time.tv_sec,
process->creation_time.tv_nsec, g_quark_to_string(process->name),
g_quark_to_string(process->last_cpu));
}
+static void free_saved_state(LttvTraceState *self)
+{
+ guint i, nb;
+
+ LttvAttributeType type;
+
+ LttvAttributeValue value;
+
+ LttvAttributeName name;
+
+ LttvAttribute *saved_states;
+
+ saved_states = lttv_attribute_find_subdir(self->parent.t_a,
+ LTTV_STATE_SAVED_STATES);
+
+ nb = lttv_attribute_get_number(saved_states);
+ for(i = 0 ; i < nb ; i++) {
+ type = lttv_attribute_get(saved_states, i, &name, &value);
+ g_assert(type == LTTV_GOBJECT);
+ state_saved_free(self, *((LttvAttribute **)value.v_gobject));
+ }
+
+ lttv_attribute_remove_by_name(self->parent.t_a, LTTV_STATE_SAVED_STATES);
+ lttv_attribute_recursive_free(saved_states);
+}
+
+
+static void
+create_max_time(LttvTraceState *tcs)
+{
+ LttvAttributeValue v;
+
+ lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_SAVED_STATES_TIME,
+ LTTV_POINTER, &v);
+ g_assert(*(v.v_pointer) == NULL);
+ *(v.v_pointer) = g_new(LttTime,1);
+ *((LttTime *)*(v.v_pointer)) = time_zero;
+}
+
+
+static void
+get_max_time(LttvTraceState *tcs)
+{
+ LttvAttributeValue v;
+
+ lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_SAVED_STATES_TIME,
+ LTTV_POINTER, &v);
+ g_assert(*(v.v_pointer) != NULL);
+ tcs->max_time_state_recomputed_in_seek = (LttTime *)*(v.v_pointer);
+}
+
+
+static void
+free_max_time(LttvTraceState *tcs)
+{
+ LttvAttributeValue v;
+
+ lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_SAVED_STATES_TIME,
+ LTTV_POINTER, &v);
+ g_free(*(v.v_pointer));
+ *(v.v_pointer) = NULL;
+}
+
+
+typedef struct _LttvNameTables {
+ GQuark *eventtype_names;
+ GQuark *syscall_names;
+ GQuark *trap_names;
+ GQuark *irq_names;
+} LttvNameTables;
+
+
static void
-fill_name_tables(LttvTraceState *tcs)
+create_name_tables(LttvTraceState *tcs)
{
int i, nb;
GString *fe_name = g_string_new("");
+ LttvNameTables *name_tables = g_new(LttvNameTables, 1);
+
+ LttvAttributeValue v;
+
+ lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_NAME_TABLES,
+ LTTV_POINTER, &v);
+ g_assert(*(v.v_pointer) == NULL);
+ *(v.v_pointer) = name_tables;
+
nb = ltt_trace_eventtype_number(tcs->parent.t);
- tcs->eventtype_names = g_new(GQuark, nb);
+ name_tables->eventtype_names = g_new(GQuark, nb);
for(i = 0 ; i < nb ; i++) {
et = ltt_trace_eventtype_get(tcs->parent.t, i);
e_name = ltt_eventtype_name(et);
f_name = ltt_facility_name(ltt_eventtype_facility(et));
g_string_printf(fe_name, "%s.%s", f_name, e_name);
- tcs->eventtype_names[i] = g_quark_from_string(fe_name->str);
+ name_tables->eventtype_names[i] = g_quark_from_string(fe_name->str);
}
lttv_trace_find_hook(tcs->parent.t, "core", "syscall_entry",
nb = ltt_type_element_number(t);
/* CHECK syscalls should be an emun but currently are not!
- tcs->syscall_names = g_new(GQuark, nb);
+ name_tables->syscall_names = g_new(GQuark, nb);
for(i = 0 ; i < nb ; i++) {
- tcs->syscall_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
+ name_tables->syscall_names[i] = g_quark_from_string(
+ ltt_enum_string_get(t, i));
}
*/
- tcs->syscall_names = g_new(GQuark, 256);
+ name_tables->syscall_names = g_new(GQuark, 256);
for(i = 0 ; i < 256 ; i++) {
g_string_printf(fe_name, "syscall %d", i);
- tcs->syscall_names[i] = g_quark_from_string(fe_name->str);
+ name_tables->syscall_names[i] = g_quark_from_string(fe_name->str);
}
lttv_trace_find_hook(tcs->parent.t, "core", "trap_entry",
nb = ltt_type_element_number(t);
/*
- tcs->trap_names = g_new(GQuark, nb);
+ name_tables->trap_names = g_new(GQuark, nb);
for(i = 0 ; i < nb ; i++) {
- tcs->trap_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
+ name_tables->trap_names[i] = g_quark_from_string(
+ ltt_enum_string_get(t, i));
}
*/
- tcs->trap_names = g_new(GQuark, 256);
+ name_tables->trap_names = g_new(GQuark, 256);
for(i = 0 ; i < 256 ; i++) {
g_string_printf(fe_name, "trap %d", i);
- tcs->trap_names[i] = g_quark_from_string(fe_name->str);
+ name_tables->trap_names[i] = g_quark_from_string(fe_name->str);
}
lttv_trace_find_hook(tcs->parent.t, "core", "irq_entry",
nb = ltt_type_element_number(t);
/*
- tcs->irq_names = g_new(GQuark, nb);
+ name_tables->irq_names = g_new(GQuark, nb);
for(i = 0 ; i < nb ; i++) {
- tcs->irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
+ name_tables->irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
}
*/
- tcs->irq_names = g_new(GQuark, 256);
+ name_tables->irq_names = g_new(GQuark, 256);
for(i = 0 ; i < 256 ; i++) {
g_string_printf(fe_name, "irq %d", i);
- tcs->irq_names[i] = g_quark_from_string(fe_name->str);
+ name_tables->irq_names[i] = g_quark_from_string(fe_name->str);
}
g_string_free(fe_name, TRUE);
}
+static void
+get_name_tables(LttvTraceState *tcs)
+{
+ LttvNameTables *name_tables;
+
+ LttvAttributeValue v;
+
+ lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_NAME_TABLES,
+ LTTV_POINTER, &v);
+ g_assert(*(v.v_pointer) != NULL);
+ name_tables = (LttvNameTables *)*(v.v_pointer);
+ tcs->eventtype_names = name_tables->eventtype_names;
+ tcs->syscall_names = name_tables->syscall_names;
+ tcs->trap_names = name_tables->trap_names;
+ tcs->irq_names = name_tables->irq_names;
+}
+
+
static void
free_name_tables(LttvTraceState *tcs)
{
- g_free(tcs->eventtype_names);
- g_free(tcs->syscall_names);
- g_free(tcs->trap_names);
- g_free(tcs->irq_names);
+ LttvNameTables *name_tables;
+
+ LttvAttributeValue v;
+
+ lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_NAME_TABLES,
+ LTTV_POINTER, &v);
+ name_tables = (LttvNameTables *)*(v.v_pointer);
+ *(v.v_pointer) = NULL;
+
+ g_free(name_tables->eventtype_names);
+ g_free(name_tables->syscall_names);
+ g_free(name_tables->trap_names);
+ g_free(name_tables->irq_names);
+ g_free(name_tables);
}
{
LttvProcessState *process = tfs->process;
- guint depth = process->execution_stack->len - 1;
+ guint depth = process->execution_stack->len;
if(process->state->t != t){
g_info("Different execution mode type (%d.%09d): ignore it\n",
return;
}
- if(depth == 0){
+ if(depth == 1){
g_info("Trying to pop last state on stack (%d.%09d): ignore it\n",
tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec);
return;
}
- g_array_remove_index(process->execution_stack, depth);
- depth--;
+ g_array_set_size(process->execution_stack, depth - 1);
process->state = &g_array_index(process->execution_stack, LttvExecutionState,
- depth);
+ depth - 2);
process->state->change = tfs->parent.timestamp;
}
char buffer[128];
- tcs = (LttvTraceState *)tc = tfs->parent.t_context;
+ tcs = ((LttvTraceState *)tc = tfs->parent.t_context);
process->pid = pid;
process->last_cpu = tfs->cpu_name;
+ g_warning("Process %u, core %p", process->pid, process);
g_hash_table_insert(tcs->processes, process, process);
if(parent) {
if(s->process != NULL) {
+ /* We could not know but it was not the idle process executing.
+ This should only happen at the beginning, before the first schedule
+ event, and when the initial information (current process for each CPU)
+ is missing. It is not obvious how we could, after the fact, compensate
+ the wrongly attributed statistics. */
+
+ if(s->process->pid != pid_out) {
+ g_assert(s->process->pid == 0);
+ }
+
if(state_out == 0) s->process->state->s = LTTV_STATE_WAIT_CPU;
else if(s->process->state->s == LTTV_STATE_EXIT)
exit_process(s, s->process);
else s->process->state->s = LTTV_STATE_WAIT;
- if(s->process->pid == 0)
- s->process->pid = pid_out;
-
s->process->state->change = s->parent.timestamp;
}
s->process = lttv_state_find_process_or_create(s, pid_in);
}
/* restore the closest earlier saved state */
- if(min_pos != -1) lttv_state_restore(tcs, closest_tree);
+ if(min_pos != -1) {
+ lttv_state_restore(tcs, closest_tree);
+ }
/* There is no saved state, yet we want to have it. Restart at T0 */
else {
LTTV_STATE_SAVED_STATES_TIME = g_quark_from_string("saved states time");
LTTV_STATE_TIME = g_quark_from_string("time");
LTTV_STATE_HOOKS = g_quark_from_string("saved state hooks");
+ LTTV_STATE_NAME_TABLES = g_quark_from_string("name tables");
+ LTTV_STATE_TRACE_STATE_USE_COUNT =
+ g_quark_from_string("trace_state_use_count");
}
static void module_destroy()
#include <lttv/module.h>
#include <lttv/stats.h>
#include <lttv/lttv.h>
+#include <lttv/attribute.h>
#include <ltt/facility.h>
#include <ltt/trace.h>
#include <ltt/event.h>
LTTV_STATS_CPU_TIME,
LTTV_STATS_ELAPSED_TIME,
LTTV_STATS_EVENTS,
- LTTV_STATS_EVENTS_COUNT;
+ LTTV_STATS_EVENTS_COUNT,
+ LTTV_STATS_USE_COUNT,
+ LTTV_STATS,
+ LTTV_STATS_TRACEFILES,
+ LTTV_STATS_SUMMED;
static GQuark
LTTV_STATS_BEFORE_HOOKS,
LttTime timestamp = {0,0};
+ LttvAttributeValue v;
+
+ LttvAttribute
+ *stats_tree,
+ *tracefiles_stats;
+
LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE))->
init((LttvTracesetContext *)self, ts);
- self->stats = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
+ self->stats =lttv_attribute_find_subdir(self->parent.parent.ts_a,LTTV_STATS);
+ lttv_attribute_find(self->parent.parent.ts_a, LTTV_STATS_USE_COUNT,
+ LTTV_UINT, &v);
+
+ *(v.v_uint)++;
+ if(*(v.v_uint) == 1) {
+ g_assert(lttv_attribute_get_number(self->stats) == 0);
+ }
+
nb_trace = lttv_traceset_number(ts);
for(i = 0 ; i < nb_trace ; i++) {
tcs = (LttvTraceStats *)tc = (LTTV_TRACESET_CONTEXT(self)->traces[i]);
- tcs->stats = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
+
+ tcs->stats = lttv_attribute_find_subdir(tcs->parent.parent.t_a,LTTV_STATS);
+ tracefiles_stats = lttv_attribute_find_subdir(tcs->parent.parent.t_a,
+ LTTV_STATS_TRACEFILES);
+ lttv_attribute_find(tcs->parent.parent.t_a, LTTV_STATS_USE_COUNT,
+ LTTV_UINT, &v);
+
+ *(v.v_uint)++;
+ if(*(v.v_uint) == 1) {
+ g_assert(lttv_attribute_get_number(tcs->stats) == 0);
+ }
nb_tracefile = ltt_trace_control_tracefile_number(tc->t) +
ltt_trace_per_cpu_tracefile_number(tc->t);
for(j = 0 ; j < nb_tracefile ; j++) {
tfcs = LTTV_TRACEFILE_STATS(tc->tracefiles[j]);
- tfcs->stats = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
+ tfcs->stats = lttv_attribute_find_subdir(tracefiles_stats,
+ tfcs->parent.cpu_name);
find_event_tree(tfcs, LTTV_STATS_PROCESS_UNKNOWN,
tfcs->parent.cpu_name, LTTV_STATE_MODE_UNKNOWN,
LTTV_STATE_SUBMODE_UNKNOWN, &tfcs->current_events_tree,
LttTime timestamp = {0,0};
- lttv_attribute_recursive_free(self->stats);
+ LttvAttributeValue v;
+
+ LttvAttribute *tracefiles_stats;
+
+ lttv_attribute_find(self->parent.parent.ts_a, LTTV_STATS_USE_COUNT,
+ LTTV_UINT, &v);
+ *(v.v_uint)--;
+
+ if(*(v.v_uint) == 0) {
+ lttv_attribute_remove_by_name(self->parent.parent.ts_a, LTTV_STATS);
+ lttv_attribute_recursive_free(self->stats);
+ }
+ self->stats = NULL;
+
ts = self->parent.parent.ts;
nb_trace = lttv_traceset_number(ts);
for(i = 0 ; i < nb_trace ; i++) {
- tcs = (LttvTraceStats *)tc = (LTTV_TRACESET_CONTEXT(self)->traces[i]);
- lttv_attribute_recursive_free(tcs->stats);
+ tcs = (LttvTraceStats *)(tc = (LTTV_TRACESET_CONTEXT(self)->traces[i]));
+
+ lttv_attribute_find(tcs->parent.parent.t_a, LTTV_STATS_USE_COUNT,
+ LTTV_UINT, &v);
+ *(v.v_uint)--;
+
+ if(*(v.v_uint) == 0) {
+ lttv_attribute_remove_by_name(tcs->parent.parent.t_a,LTTV_STATS);
+ lttv_attribute_recursive_free(tcs->stats);
+ tracefiles_stats = lttv_attribute_find_subdir(tcs->parent.parent.t_a,
+ LTTV_STATS_TRACEFILES);
+ lttv_attribute_remove_by_name(tcs->parent.parent.t_a,
+ LTTV_STATS_TRACEFILES);
+ lttv_attribute_recursive_free(tracefiles_stats);
+ }
+ tcs->stats = NULL;
nb_tracefile = ltt_trace_control_tracefile_number(tc->t) +
ltt_trace_per_cpu_tracefile_number(tc->t);
for(j = 0 ; j < nb_tracefile ; j++) {
- tfcs = (LttvTracefileStats *)tfc = tc->tracefiles[j];
- lttv_attribute_recursive_free(tfcs->stats);
+ tfcs = ((LttvTracefileStats *)tfc = tc->tracefiles[j]);
+ tfcs->stats = NULL;
tfcs->current_events_tree = NULL;
tfcs->current_event_types_tree = NULL;
}
}
-static gboolean
-sum_stats(void *hook_data, void *call_data)
+void
+lttv_stats_sum_trace(LttvTraceStats *self)
{
- LttvTracesetStats *tscs = (LttvTracesetStats *)call_data;
-
LttvTraceStats *tcs;
- LttvTraceset *traceset = tscs->parent.parent.ts;
-
LttvAttributeType type;
LttvAttributeValue value;
unsigned sum;
- int i, j, k, l, m, n, nb_trace, nb_process, nb_cpu, nb_mode_type, nb_submode,
+ int i, j, k, l, m, nb_process, nb_cpu, nb_mode_type, nb_submode,
nb_event_type;
LttvAttribute *main_tree, *processes_tree, *process_tree, *cpus_tree,
*cpu_tree, *mode_tree, *mode_types_tree, *submodes_tree,
*submode_tree, *event_types_tree, *mode_events_tree,
*cpu_events_tree, *process_modes_tree, *trace_cpu_tree,
- *trace_modes_tree, *traceset_modes_tree;
-
- traceset_modes_tree = lttv_attribute_find_subdir(tscs->stats,
- LTTV_STATS_MODES);
- nb_trace = lttv_traceset_number(traceset);
-
- for(i = 0 ; i < nb_trace ; i++) {
- tcs = (LttvTraceStats *)(tscs->parent.parent.traces[i]);
- main_tree = tcs->stats;
- processes_tree = lttv_attribute_find_subdir(main_tree,
- LTTV_STATS_PROCESSES);
- trace_modes_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_MODES);
- nb_process = lttv_attribute_get_number(processes_tree);
-
- for(j = 0 ; j < nb_process ; j++) {
- type = lttv_attribute_get(processes_tree, j, &name, &value);
- process_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
+ *trace_modes_tree;
+
+ main_tree = self->stats;
+
+ lttv_attribute_find(self->parent.parent.t_a, LTTV_STATS_SUMMED,
+ LTTV_UINT, &value);
+ if(*(value.v_uint) != 0) return;
+ *(value.v_uint) = 1;
+
+ processes_tree = lttv_attribute_find_subdir(main_tree,
+ LTTV_STATS_PROCESSES);
+ trace_modes_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_MODES);
+ nb_process = lttv_attribute_get_number(processes_tree);
+
+ for(i = 0 ; i < nb_process ; i++) {
+ type = lttv_attribute_get(processes_tree, i, &name, &value);
+ process_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
+
+ cpus_tree = lttv_attribute_find_subdir(process_tree, LTTV_STATS_CPU);
+ process_modes_tree = lttv_attribute_find_subdir(process_tree,
+ LTTV_STATS_MODES);
+ nb_cpu = lttv_attribute_get_number(cpus_tree);
+
+ for(j = 0 ; j < nb_cpu ; j++) {
+ type = lttv_attribute_get(cpus_tree, j, &name, &value);
+ cpu_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
+
+ mode_types_tree = lttv_attribute_find_subdir(cpu_tree,
+ LTTV_STATS_MODE_TYPES);
+ cpu_events_tree = lttv_attribute_find_subdir(cpu_tree,
+ LTTV_STATS_EVENTS);
+ trace_cpu_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_CPU);
+ trace_cpu_tree = lttv_attribute_find_subdir(trace_cpu_tree, name);
+ nb_mode_type = lttv_attribute_get_number(mode_types_tree);
+
+ for(k = 0 ; k < nb_mode_type ; k++) {
+ type = lttv_attribute_get(mode_types_tree, k, &name, &value);
+ mode_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
+
+ submodes_tree = lttv_attribute_find_subdir(mode_tree,
+ LTTV_STATS_SUBMODES);
+ mode_events_tree = lttv_attribute_find_subdir(mode_tree,
+ LTTV_STATS_EVENTS);
+ nb_submode = lttv_attribute_get_number(submodes_tree);
- cpus_tree = lttv_attribute_find_subdir(process_tree, LTTV_STATS_CPU);
- process_modes_tree = lttv_attribute_find_subdir(process_tree,
- LTTV_STATS_MODES);
- nb_cpu = lttv_attribute_get_number(cpus_tree);
+ for(l = 0 ; l < nb_submode ; l++) {
+ type = lttv_attribute_get(submodes_tree, l, &name, &value);
+ submode_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
- for(k = 0 ; k < nb_cpu ; k++) {
- type = lttv_attribute_get(cpus_tree, k, &name, &value);
- cpu_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
+ event_types_tree = lttv_attribute_find_subdir(submode_tree,
+ LTTV_STATS_EVENT_TYPES);
+ nb_event_type = lttv_attribute_get_number(event_types_tree);
- mode_types_tree = lttv_attribute_find_subdir(cpu_tree,
- LTTV_STATS_MODE_TYPES);
- cpu_events_tree = lttv_attribute_find_subdir(cpu_tree,
- LTTV_STATS_EVENTS);
- trace_cpu_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_CPU);
- trace_cpu_tree = lttv_attribute_find_subdir(trace_cpu_tree, name);
- nb_mode_type = lttv_attribute_get_number(mode_types_tree);
-
- for(l = 0 ; l < nb_mode_type ; l++) {
- type = lttv_attribute_get(mode_types_tree, l, &name, &value);
- mode_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
-
- submodes_tree = lttv_attribute_find_subdir(mode_tree,
- LTTV_STATS_SUBMODES);
- mode_events_tree = lttv_attribute_find_subdir(mode_tree,
- LTTV_STATS_EVENTS);
- nb_submode = lttv_attribute_get_number(submodes_tree);
-
- for(m = 0 ; m < nb_submode ; m++) {
- type = lttv_attribute_get(submodes_tree, m, &name, &value);
- submode_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
-
- event_types_tree = lttv_attribute_find_subdir(submode_tree,
- LTTV_STATS_EVENT_TYPES);
- nb_event_type = lttv_attribute_get_number(event_types_tree);
-
- sum = 0;
- for(n = 0 ; n < nb_event_type ; n++) {
- type = lttv_attribute_get(event_types_tree, n, &name, &value);
- sum += *(value.v_uint);
- }
- lttv_attribute_find(submode_tree, LTTV_STATS_EVENTS_COUNT,
- LTTV_UINT, &value);
- *(value.v_uint) = sum;
- lttv_attribute_recursive_add(mode_events_tree, submode_tree);
+ sum = 0;
+ for(m = 0 ; m < nb_event_type ; m++) {
+ type = lttv_attribute_get(event_types_tree, m, &name, &value);
+ sum += *(value.v_uint);
}
- lttv_attribute_recursive_add(cpu_events_tree, mode_events_tree);
+ lttv_attribute_find(submode_tree, LTTV_STATS_EVENTS_COUNT,
+ LTTV_UINT, &value);
+ *(value.v_uint) = sum;
+ lttv_attribute_recursive_add(mode_events_tree, submode_tree);
}
- lttv_attribute_recursive_add(process_modes_tree, cpu_tree);
- lttv_attribute_recursive_add(trace_cpu_tree, cpu_tree);
+ lttv_attribute_recursive_add(cpu_events_tree, mode_events_tree);
}
- lttv_attribute_recursive_add(trace_modes_tree, process_modes_tree);
+ lttv_attribute_recursive_add(process_modes_tree, cpu_tree);
+ lttv_attribute_recursive_add(trace_cpu_tree, cpu_tree);
}
+ lttv_attribute_recursive_add(trace_modes_tree, process_modes_tree);
+ }
+}
+
+
+void
+lttv_stats_sum_traceset(LttvTracesetStats *self)
+{
+ LttvTraceset *traceset = self->parent.parent.ts;
+
+ LttvTraceStats *tcs;
+
+ int i, nb_trace;
+
+ LttvAttribute *main_tree, *trace_modes_tree, *traceset_modes_tree;
+
+ LttvAttributeValue value;
+
+ lttv_attribute_find(self->parent.parent.ts_a, LTTV_STATS_SUMMED,
+ LTTV_UINT, &value);
+ if(*(value.v_uint) != 0) return;
+ *(value.v_uint) = 1;
+
+ traceset_modes_tree = lttv_attribute_find_subdir(self->stats,
+ LTTV_STATS_MODES);
+ nb_trace = lttv_traceset_number(traceset);
+
+ for(i = 0 ; i < nb_trace ; i++) {
+ tcs = (LttvTraceStats *)(self->parent.parent.traces[i]);
+ lttv_stats_sum_trace(tcs);
+ main_tree = tcs->stats;
+ trace_modes_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_MODES);
lttv_attribute_recursive_add(traceset_modes_tree, trace_modes_tree);
}
- return FALSE;
}
LTTV_POINTER, &val);
*(val.v_pointer) = after_hooks;
}
- lttv_hooks_add(self->parent.parent.after, sum_stats, NULL);
}
g_array_free(before_hooks, TRUE);
g_array_free(after_hooks, TRUE);
}
- lttv_hooks_remove_data(self->parent.parent.after, sum_stats, NULL);
-}
-
-
-void lttv_stats_save_attribute(LttvAttribute *attr, char *indent, FILE * fp)
-{
- LttvAttributeType type;
- LttvAttributeValue value;
- LttvAttributeName name;
- char type_value[BUF_SIZE];
- int i, nb_attr, flag;
-
- nb_attr = lttv_attribute_get_number(attr);
- for(i=0;i<nb_attr;i++){
- flag = 1;
- type = lttv_attribute_get(attr, i, &name, &value);
- switch(type) {
- case LTTV_INT:
- sprintf(type_value, "%d\0", *value.v_int);
- break;
- case LTTV_UINT:
- sprintf(type_value, "%u\0", *value.v_uint);
- break;
- case LTTV_LONG:
- sprintf(type_value, "%ld\0", *value.v_long);
- break;
- case LTTV_ULONG:
- sprintf(type_value, "%lu\0", *value.v_ulong);
- break;
- case LTTV_FLOAT:
- sprintf(type_value, "%f\0", (double)*value.v_float);
- break;
- case LTTV_DOUBLE:
- sprintf(type_value, "%f\0", *value.v_double);
- break;
- case LTTV_TIME:
- sprintf(type_value, "%10u.%09u\0", value.v_time->tv_sec,
- value.v_time->tv_nsec);
- break;
- case LTTV_POINTER:
- sprintf(type_value, "POINTER\0");
- break;
- case LTTV_STRING:
- sprintf(type_value, "%s\0", *value.v_string);
- break;
- default:
- flag = 0;
- break;
- }
- if(flag == 0) continue;
- fprintf(fp,"%s<VALUE type=\"%d\" name=\"%s\">",indent,type,g_quark_to_string(name));
- fprintf(fp,"%s",type_value);
- fprintf(fp,"</VALUE> \n");
- }
-
-}
-
-void lttv_stats_save_statistics(LttvTracesetStats *self)
-{
- LttvTracesetStats *tscs = self;
- LttvTraceStats *tcs;
- LttvTraceset *traceset = tscs->parent.parent.ts;
- LttvAttributeType type;
- LttvAttributeValue value;
- LttvAttributeName name;
-
- char filename[BUF_SIZE];
- FILE * fp;
- char indent[10][24]= {" ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " "
- };
-
-
- int i, j, k, l, m, n, nb_trace, nb_process, nb_cpu, nb_mode_type, nb_submode;
-
- LttvAttribute *main_tree, *processes_tree, *process_tree, *cpus_tree,
- *cpu_tree, *mode_tree, *mode_types_tree, *submodes_tree,
- *submode_tree, *event_types_tree;
-
- nb_trace = lttv_traceset_number(traceset);
-
- for(i = 0 ; i < nb_trace ; i++) {
- tcs = (LttvTraceStats *)(tscs->parent.parent.traces[i]);
-
- filename[0] = '\0';
- strcat(filename,ltt_trace_name(tcs->parent.parent.t));
- strcat(filename,"/statistics.xml");
- fp = fopen(filename,"w");
- if(!fp){
- g_warning("can not open the file %s for saving statistics\n", filename);
- exit(1);
- }
-
- main_tree = tcs->stats;
- processes_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_PROCESSES);
- nb_process = lttv_attribute_get_number(processes_tree);
-
- fprintf(fp, "<NODE name=\"%s\"> \n",g_quark_to_string(LTTV_STATS_PROCESSES)); //root NODE
-
- for(j = 0 ; j < nb_process ; j++) {
- type = lttv_attribute_get(processes_tree, j, &name, &value);
- process_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
-
- fprintf(fp,"%s<NODE name=\"%s\"> \n",indent[0],g_quark_to_string(name)); //process NODE
- lttv_stats_save_attribute(process_tree,indent[1], fp);
- fprintf(fp,"%s<NODE name=\"%s\"> \n", indent[1],g_quark_to_string(LTTV_STATS_CPU)); //cpus NODE
-
- cpus_tree = lttv_attribute_find_subdir(process_tree, LTTV_STATS_CPU);
- nb_cpu = lttv_attribute_get_number(cpus_tree);
-
- for(k = 0 ; k < nb_cpu ; k++) {
- type = lttv_attribute_get(cpus_tree, k, &name, &value);
- cpu_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
-
- fprintf(fp,"%s<NODE name=\"%s\"> \n",indent[2],g_quark_to_string(name)); //cpu NODE
- lttv_stats_save_attribute(cpu_tree,indent[3], fp);
- fprintf(fp,"%s<NODE name=\"%s\"> \n",indent[3],g_quark_to_string(LTTV_STATS_MODE_TYPES)); //mode_types NODE
-
- mode_types_tree = lttv_attribute_find_subdir(cpu_tree,LTTV_STATS_MODE_TYPES);
- nb_mode_type = lttv_attribute_get_number(mode_types_tree);
-
- for(l = 0 ; l < nb_mode_type ; l++) {
- type = lttv_attribute_get(mode_types_tree, l, &name, &value);
- mode_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
-
- fprintf(fp,"%s<NODE name=\"%s\"> \n",indent[4],g_quark_to_string(name)); //mode NODE
- lttv_stats_save_attribute(mode_tree,indent[5], fp);
- fprintf(fp,"%s<NODE name=\"%s\"> \n",indent[5],g_quark_to_string(LTTV_STATS_SUBMODES)); //sub_modes NODE
-
- submodes_tree = lttv_attribute_find_subdir(mode_tree,LTTV_STATS_SUBMODES);
- nb_submode = lttv_attribute_get_number(submodes_tree);
-
- for(m = 0 ; m < nb_submode ; m++) {
- type = lttv_attribute_get(submodes_tree, m, &name, &value);
- submode_tree = LTTV_ATTRIBUTE(*(value.v_gobject));
- fprintf(fp,"%s<NODE name=\"%s\"> \n",indent[6],g_quark_to_string(name)); //sub_mode NODE
- lttv_stats_save_attribute(submode_tree,indent[7], fp);
- fprintf(fp,"%s<NODE name=\"%s\"> \n",indent[7],g_quark_to_string(LTTV_STATS_EVENT_TYPES)); //event_types NODE
-
- event_types_tree = lttv_attribute_find_subdir(submode_tree, LTTV_STATS_EVENT_TYPES);
- lttv_stats_save_attribute(event_types_tree,indent[8], fp);
-
- fprintf(fp,"%s</NODE> \n",indent[7]); //event_types NODE
- fprintf(fp,"%s</NODE> \n",indent[6]); //sub_mode NODE
- }
- fprintf(fp,"%s</NODE> \n",indent[5]); //sub_modes NODE
- fprintf(fp,"%s</NODE> \n",indent[4]); //mode NODE
- }
- fprintf(fp,"%s</NODE> \n",indent[3]); //mode_type NODE
- fprintf(fp,"%s</NODE> \n",indent[2]); //cpu NODE
- }
- fprintf(fp,"%s</NODE> \n",indent[1]); //cpus NODE
- fprintf(fp,"%s</NODE> \n", indent[0]); //process NODE
- }
- fprintf(fp, "</NODE>\n"); //root NODE
- fclose(fp);
- }
-}
-
-
-/* Functions to parse statistic.xml file (using glib xml parser) */
-
-typedef struct _ParserStruct{
- GPtrArray * attribute;
- LttvAttributeType type;
- LttvAttributeName name;
-} ParserStruct;
-
-static void stats_parser_start_element (GMarkupParseContext *context,
- const gchar *element_name,
- const gchar **attribute_names,
- const gchar **attribute_values,
- gpointer user_data,
- GError **error)
-{
- ParserStruct * parser = (ParserStruct *)user_data;
- int len;
- LttvAttributeType type;
- LttvAttributeName name;
- LttvAttribute * parent_att, *new_att;
-
- len = parser->attribute->len;
- parent_att = (LttvAttribute *)g_ptr_array_index (parser->attribute, len-1);
-
- if(strcmp("NODE", element_name) == 0){
- type = LTTV_GOBJECT;
- name = g_quark_from_string(attribute_values[0]);
- new_att = lttv_attribute_find_subdir(parent_att,name);
- g_ptr_array_add(parser->attribute, (gpointer)new_att);
- }else if(strcmp("VALUE", element_name) == 0){
- parser->type = (LttvAttributeType) atoi(attribute_values[0]);
- parser->name = g_quark_from_string(attribute_values[1]);
- }else{
- g_warning("This is not statistics.xml file\n");
- exit(1);
- }
-}
-
-static void stats_parser_end_element (GMarkupParseContext *context,
- const gchar *element_name,
- gpointer user_data,
- GError **error)
-{
- ParserStruct * parser = (ParserStruct *)user_data;
- int len;
- LttvAttribute * parent_att;
-
- len = parser->attribute->len;
- parent_att = (LttvAttribute *)g_ptr_array_index (parser->attribute, len-1);
-
- if(strcmp("NODE", element_name) == 0){
- g_ptr_array_remove_index(parser->attribute, len-1);
- }else if(strcmp("VALUE", element_name) == 0){
- }else{
- g_warning("This is not statistics.xml file\n");
- exit(1);
- }
-
-}
-
-static void stats_parser_characters (GMarkupParseContext *context,
- const gchar *text,
- gsize text_len,
- gpointer user_data,
- GError **error)
-{
- ParserStruct * parser = (ParserStruct *)user_data;
- LttvAttributeValue value;
- int len;
- LttvAttribute * parent_att;
- char *pos;
-
- pos = (char*)text;
- for(len=0;len<text_len;len++){
- if(isspace(*pos)){
- pos++;
- continue;
- }
- break;
- }
- if(strlen(pos) == 0)return;
-
- len = parser->attribute->len;
- parent_att = (LttvAttribute *)g_ptr_array_index (parser->attribute, len-1);
- if(!lttv_attribute_find(parent_att,parser->name, parser->type, &value)){
- g_warning("can not find value\n");
- exit(1);
- }
-
- switch(parser->type) {
- case LTTV_INT:
- *value.v_int = atoi(text);
- break;
- case LTTV_UINT:
- *value.v_uint = (unsigned)atoi(text);
- break;
- case LTTV_LONG:
- *value.v_long = atol(text);
- break;
- case LTTV_ULONG:
- *value.v_ulong = (unsigned long)atol(text);
- break;
- case LTTV_FLOAT:
- *value.v_float = atof(text);
- break;
- case LTTV_DOUBLE:
- *value.v_float = atof(text);
- break;
- case LTTV_TIME:
- pos = strrchr(text,'.');
- if(pos){
- *pos = '\0';
- pos++;
- value.v_time->tv_sec = atol(text);
- value.v_time->tv_nsec = atol(pos);
- }else{
- g_warning("The time value format is wrong\n");
- exit(1);
- }
- break;
- case LTTV_POINTER:
- break;
- case LTTV_STRING:
- *value.v_string = g_strdup(text);
- break;
- default:
- break;
- }
-
-}
-
-gboolean lttv_stats_load_statistics(LttvTracesetStats *self)
-{
- FILE * fp;
- char buf[BUF_SIZE];
- LttvTracesetStats *tscs = self;
- LttvTraceStats *tcs;
- LttvTraceset *traceset = tscs->parent.parent.ts;
- char filename[BUF_SIZE];
-
- GMarkupParseContext * context;
- GError * error = NULL;
- GMarkupParser markup_parser =
- {
- stats_parser_start_element,
- stats_parser_end_element,
- stats_parser_characters,
- NULL, /* passthrough */
- NULL /* error */
- };
-
- int i, nb_trace;
- LttvAttribute *main_tree;
- ParserStruct a_parser_struct;
- a_parser_struct.attribute = g_ptr_array_new();
-
- nb_trace = lttv_traceset_number(traceset);
-
- for(i = 0 ; i < nb_trace ; i++) {
- tcs = (LttvTraceStats *)(tscs->parent.parent.traces[i]);
-
- filename[0] = '\0';
- strcat(filename,ltt_trace_name(tcs->parent.parent.t));
- strcat(filename,"/statistics.xml");
- fp = fopen(filename,"r");
- if(!fp){
- g_warning("can not open the file %s for reading statistics\n", filename);
- return FALSE;
- }
-
- main_tree = tcs->stats;
- g_ptr_array_add(a_parser_struct.attribute,(gpointer)main_tree);
-
- context = g_markup_parse_context_new(&markup_parser, 0, (gpointer)&a_parser_struct, NULL);
-
- while(fgets(buf,BUF_SIZE, fp) != NULL){
- if(!g_markup_parse_context_parse(context, buf, BUF_SIZE, &error)){
- g_warning("Can not parse xml file: \n%s\n", error->message);
- exit(1);
- }
- }
- fclose(fp);
- }
-
- sum_stats(NULL, (void *)self);
-
- return TRUE;
}
LTTV_STATS_EVENTS_COUNT = g_quark_from_string("events count");
LTTV_STATS_BEFORE_HOOKS = g_quark_from_string("saved stats before hooks");
LTTV_STATS_AFTER_HOOKS = g_quark_from_string("saved stats after hooks");
+ LTTV_STATS_USE_COUNT = g_quark_from_string("stats_use_count");
+ LTTV_STATS = g_quark_from_string("statistics");
+ LTTV_STATS_TRACEFILES = g_quark_from_string("tracefiles statistics");
+ LTTV_STATS_SUMMED = g_quark_from_string("statistics summed");
}
static void module_destroy()
LTTV_MODULE("stats", "Compute processes statistics", \
"Accumulate statistics for event types, processes and CPUs", \
module_init, module_destroy, "state");
+
+/* Change the places where stats are called (create/read/write stats)
+
+ Check for options in batchtest.c to reduce writing and see what tests are
+ best candidates for performance analysis. Once OK, commit, move to main
+ and run tests. Update the gui for statistics. */
&statistic_viewer_data->time_span);
if(statistic_viewer_data->calculate_stats){
- if(lttv_stats_load_statistics(statistic_viewer_data->stats))
- statistic_viewer_data->calculate_stats = FALSE;
+ //if(lttv_stats_load_statistics(statistic_viewer_data->stats))
+ // statistic_viewer_data->calculate_stats = FALSE;
}
if(statistic_viewer_data->calculate_stats == FALSE){
show_traceset_stats(statistic_viewer_data);
if(statistic_viewer_data->calculate_stats){
statistic_remove_context_hooks(statistic_viewer_data,tsc);
- lttv_stats_save_statistics((LttvTracesetStats*)tsc);
+ //lttv_stats_save_statistics((LttvTracesetStats*)tsc);
}
}
a_save_interval;
static gboolean
+ a_trace_event,
+ a_save_state_copy,
a_test1,
a_test2,
a_test3,
a_test7,
a_test_all;
+LttEventPosition *a_event_position;
+
typedef struct _save_state {
guint count;
FILE *fp;
{
double t0, t1;
+ int i;
+
lttv_traceset_context_add_hooks(&ts->parent,
before_traceset, after_traceset, NULL, before_trace, after_trace,
NULL, before_tracefile, after_tracefile, NULL, before_event, after_event);
+ for(i = 0 ; i < lttv_traceset_number(traceset) ; i++) {
+ ((LttvTraceState *)(ts->parent.traces[i]))->save_interval =a_save_interval;
+ }
+
t0 = get_time();
lttv_state_traceset_seek_time_closest(ts, start);
lttv_process_traceset(&ts->parent, end, G_MAXULONG);
}
+gboolean trace_event(void *hook_data, void *call_data)
+{
+ LttvTracefileState *tfs = (LttvTracefileState *)call_data;
+
+ guint nb_block, nb_event;
+
+ LttTracefile *tf;
+
+ ltt_event_position(tfs->parent.e, a_event_position);
+ ltt_event_position_get(a_event_position, &nb_block, &nb_event, &tf);
+ fprintf(stderr,"Event %s %lu.%09lu [%lu %lu]\n",
+ ltt_eventtype_name(ltt_event_eventtype(tfs->parent.e)),
+ tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec,
+ nb_block, nb_event);
+ return FALSE;
+}
+
+
gboolean count_event(void *hook_data, void *call_data)
{
guint *pcount = (guint *)hook_data;
}
+gboolean save_state_copy_event(void *hook_data, void *call_data)
+{
+ SaveState *save_state = (SaveState *)hook_data;
+
+ LttvTracefileState *tfs = (LttvTracefileState *)call_data;
+
+ LttvTraceState *ts = (LttvTraceState *)tfs->parent.t_context;
+
+ GString *filename;
+
+ FILE *fp;
+
+ if(ts->nb_event == 0 && strcmp(ltt_eventtype_name(
+ ltt_event_eventtype(tfs->parent.e)), "block_start") == 0) {
+ if(a_save_sample != NULL) {
+ filename = g_string_new("");
+ g_string_printf(filename, "%s.copy.%lu.%09lu.xml", a_save_sample,
+ tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec);
+ fp = fopen(filename->str, "w");
+ if(fp == NULL) g_error("Cannot open %s", filename->str);
+ g_string_free(filename, TRUE);
+ lttv_state_write(ts, tfs->parent.timestamp, fp);
+ fclose(fp);
+ } //else lttv_state_write(ts, tfs->parent.timestamp, save_state->fp);
+ }
+ return FALSE;
+}
+
+
gboolean save_state_event(void *hook_data, void *call_data)
{
SaveState *save_state = (SaveState *)hook_data;
g_string_free(filename, TRUE);
lttv_state_write(ts, tfs->parent.timestamp, fp);
fclose(fp);
- } else lttv_state_write(ts, tfs->parent.timestamp, save_state->fp);
+ } //else lttv_state_write(ts, tfs->parent.timestamp, save_state->fp);
save_state->write_time[save_state->position] = tfs->parent.timestamp;
save_state->position++;
LttTime start_time;
- LttEventPosition *event_position;
-
LttTime zero_time = ltt_time_zero;
LttTime max_time = { G_MAXULONG, G_MAXULONG };
+ a_event_position = ltt_event_position_new();
+
if(a_dump_tracefiles != NULL) {
- event_position = ltt_event_position_new();
for(i = 0 ; i < lttv_traceset_number(traceset) ; i++) {
trace = lttv_trace(lttv_traceset_get(traceset, i));
nb_control = ltt_trace_control_tracefile_number(trace);
event_type = ltt_event_eventtype(event);
time = ltt_event_time(event);
cycle_count = ltt_event_cycle_count(event);
- ltt_event_position(event, event_position);
- ltt_event_position_get(event_position, &nb_block, &nb_event, &tf);
+ ltt_event_position(event, a_event_position);
+ ltt_event_position_get(a_event_position, &nb_block, &nb_event, &tf);
fprintf(fp,"%s.%s: %llu %lu.%09lu position %u/%u\n",
ltt_facility_name(facility), ltt_eventtype_name(event_type),
cycle_count, (unsigned long)time.tv_sec,
fclose(fp);
}
}
- g_free(event_position);
}
tscs = g_object_new(LTTV_TRACESET_STATS_TYPE, NULL);
tc = &tscs->parent.parent;
lttv_context_init(tc, traceset);
- for(i = 0 ; i < lttv_traceset_number(traceset) ; i++) {
- ((LttvTraceState *)(tc->traces[i]))->save_interval = a_save_interval;
- }
/* For each case compute and print the elapsed time.
The first case is simply to run through all events with a
g_message("Memory summary after computing stats");
g_mem_profile();
}
+
+ lttv_stats_sum_traceset(tscs);
+
+ if(lttv_profile_memory) {
+ g_message("Memory summary after summing stats");
+ g_mem_profile();
+ }
+
+ lttv_context_fini(tc);
+ lttv_context_init(tc, traceset);
+
+ if(lttv_profile_memory) {
+ g_message("Memory summary after cleaning up the stats");
+ g_mem_profile();
+ }
}
/* Run through all events computing the state and stats. */
g_message("Memory summary after computing and state and stats");
g_mem_profile();
}
+
+ lttv_context_fini(tc);
+ lttv_context_init(tc, traceset);
+
+ if(lttv_profile_memory) {
+ g_message("Memory summary after cleaning up the stats");
+ g_mem_profile();
+ }
}
/* Run through all events computing and saving the state. */
+ if(a_trace_event) lttv_hooks_add(after_event, trace_event, NULL);
+
if(a_test6 || a_test_all) {
if(lttv_profile_memory) {
g_message("Memory summary before computing and saving state");
lttv_state_add_event_hooks(ts);
lttv_state_save_add_event_hooks(ts);
+ if(a_save_state_copy)
+ lttv_hooks_add(after_event, save_state_copy_event, &save_state);
t = run_one_test(ts, zero_time, max_time);
lttv_state_remove_event_hooks(ts);
lttv_state_save_remove_event_hooks(ts);
+ if(a_save_state_copy)
+ lttv_hooks_remove_data(after_event,save_state_copy_event, &save_state);
+
g_warning("Processing trace while updating/saving state (%g seconds)", t);
if(lttv_profile_memory) {
save_state.write_time[j], fp);
fclose(fp);
}
- else lttv_state_write((LttvTraceState *)tc->traces[0],
- save_state.write_time[j], save_state.fp);
+ //else lttv_state_write((LttvTraceState *)tc->traces[0],
+ // save_state.write_time[j], save_state.fp);
}
}
}
+ if(a_trace_event) lttv_hooks_remove_data(after_event, trace_event, NULL);
+
g_free(save_state.write_time);
+ g_free(a_event_position);
lttv_context_fini(tc);
g_object_unref(tscs);
+ if(lttv_profile_memory) {
+ g_message("Memory summary at the end of batchtest");
+ g_mem_profile();
+ }
+
g_info("BatchTest end process traceset");
}
"pathname of the directory containing the trace",
LTTV_OPT_STRING, &a_trace, lttv_trace_option, NULL);
+ a_trace_event = FALSE;
+
a_dump_tracefiles = NULL;
lttv_option_add("dump-tracefiles", 'D',
"Write event by event the content of tracefiles",
"basename for the files containing the state samples",
LTTV_OPT_STRING, &a_save_sample, NULL, NULL);
+ a_save_state_copy = FALSE;
+ lttv_option_add("save-state-copy", 'S', "Write the state saved for seeking",
+ "", LTTV_OPT_NONE, &a_save_state_copy, NULL, NULL);
+
a_save_interval = 100000;
lttv_option_add("save-interval", 'i',
"Interval between saving state",
lttv_option_remove("trace");
lttv_option_remove("dump-tracefiles");
lttv_option_remove("save-sample");
+ lttv_option_remove("save-state-copy");
lttv_option_remove("sample-interval");
lttv_option_remove("sample-number");
lttv_option_remove("save-interval");
fprintf(a_file,"End trace set\n\n");
if(LTTV_IS_TRACESET_STATS(tc)) {
+ lttv_stats_sum_traceset((LttvTracesetStats *)tc);
print_stats(a_file, (LttvTracesetStats *)tc);
}