AC_SUBST(lttlibdir)
-top_includedir="\$(top_srcdir)/include"
-AC_SUBST(top_includedir)
+top_guidir="\$(top_srcdir)/lttv/modules/gui"
+AC_SUBST(top_guidir)
-DEFAULT_INCLUDES="-I\$(top_includedir) -I\$(top_srcdir)"
+DEFAULT_INCLUDES="-I\$(top_guidir) -I\$(top_srcdir)"
AC_SUBST(DEFAULT_INCLUDES)
#CPPFLAGS="${GLIB_CFLAGS}"
#AC_SUBST(CPPFLAGS)
+lttincludedir="${includedir}/ltt"
+AC_SUBST(lttincludedir)
+
lttvincludedir="${includedir}/lttv"
AC_SUBST(lttvincludedir)
-lttincludedir="${includedir}/ltt"
-AC_SUBST(lttincludedir)
+lttvguiincludedir="${includedir}/lttvgui"
+AC_SUBST(lttvguiincludedir)
AC_CONFIG_FILES([Makefile
lttv/Makefile
- lttv/main/Makefile
+ lttv/lttv/Makefile
lttv/modules/Makefile
lttv/modules/text/Makefile
lttv/modules/gui/Makefile
- lttv/modules/gui/mainlib/Makefile
+ lttv/modules/gui/lttvgui/Makefile
lttv/modules/gui/main/Makefile
lttv/modules/gui/main/src/Makefile
lttv/modules/gui/main/pixmaps/Makefile
lttv/modules/gui/statistics/Makefile
lttd/Makefile
ltt/Makefile
- include/Makefile
- ltt/convert/Makefile
- include/lttv/Makefile])
+ ltt/convert/Makefile])
AC_OUTPUT
+++ /dev/null
-SUBDIRS = lttv
+++ /dev/null
-lttvinclude_HEADERS = \
- attribute.h\
- batchAnalysis.h\
- common.h\
- filter.h\
- gtktraceset.h\
- gtkmultivpaned.h\
- hook.h\
- iattribute.h\
- lttv.h\
- mainwindow.h\
- menu.h\
- module.h\
- option.h\
- processTrace.h\
- state.h\
- stats.h\
- textDump.h\
- toolbar.h\
- traceset.h\
- lttvfilter.h
+++ /dev/null
-/* This file is part of the Linux Trace Toolkit viewer
- * Copyright (C) 2003-2004 Michel Dagenais
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License Version 2 as
- * published by the Free Software Foundation;
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA.
- */
-
-#ifndef ATTRIBUTE_H
-#define ATTRIBUTE_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))
-#define LTTV_ATTRIBUTE_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST ((vtable), LTTV_ATTRIBUTE_TYPE, LttvAttributeClass))
-#define LTTV_IS_ATTRIBUTE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LTTV_ATTRIBUTE_TYPE))
-#define LTTV_IS_ATTRIBUTE_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), LTTV_ATTRIBUTE_TYPE))
-#define LTTV_ATTRIBUTE_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), LTTV_ATTRIBUTE_TYPE, LttvAttributeClass))
-
-
-typedef struct _LttvAttribute LttvAttribute;
-typedef struct _LttvAttributeClass LttvAttributeClass;
-
-struct _LttvAttribute {
- GObject parent;
-
- /* private members */
- GHashTable *names;
- GArray *attributes;
-};
-
-struct _LttvAttributeClass {
- GObjectClass parent;
-};
-
-GType lttv_attribute_get_type (void);
-
-
-/* The functions exported in the IAttribute interface are also available
- directly. */
-
-
-/* Total number of attributes */
-
-unsigned int lttv_attribute_get_number(LttvAttribute *self);
-
-
-/* Container type. Named (fields in struct or elements in a hash table)
- or unnamed (elements in an array) attributes, homogeneous type or not. */
-
-gboolean lttv_attribute_named(LttvAttribute *self, gboolean *homogeneous);
-
-
-/* Get the i th attribute along with its type and a pointer to its value. */
-
-LttvAttributeType lttv_attribute_get(LttvAttribute *self, unsigned i,
- LttvAttributeName *name, LttvAttributeValue *v);
-
-
-/* Get the named attribute in the table along with its type and a pointer to
- its value. If the named attribute does not exist, the type is LTTV_NONE. */
-
-LttvAttributeType lttv_attribute_get_by_name(LttvAttribute *self,
- LttvAttributeName name, LttvAttributeValue *v);
-
-
-/* Add an attribute, which must not exist. The name is an empty string for
- containers with unnamed attributes. */
-
-LttvAttributeValue lttv_attribute_add(LttvAttribute *self,
- LttvAttributeName name, LttvAttributeType t);
-
-
-/* Remove an attribute */
-
-void lttv_attribute_remove(LttvAttribute *self, unsigned i);
-
-void lttv_attribute_remove_by_name(LttvAttribute *self,
- LttvAttributeName name);
-
-
-/* Create an empty iattribute object and add it as an attribute under the
- specified name, or return an existing iattribute attribute. If an
- attribute of that name already exists but is not a GObject supporting the
- iattribute interface, return NULL. */
-
-LttvAttribute* lttv_attribute_find_subdir(LttvAttribute *self,
- LttvAttributeName name);
-
-gboolean lttv_attribute_find(LttvAttribute *self, LttvAttributeName name,
- LttvAttributeType t, LttvAttributeValue *v);
-
-
-/* Free recursively a tree of attributes. All contained gobject of type
- LttvAttribute are freed (unreferenced) recursively. */
-
-void lttv_attribute_recursive_free(LttvAttribute *self);
-
-/* Add items from a tree of attributes to another tree. */
-
-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
+++ /dev/null
-/* This file is part of the Linux Trace Toolkit viewer
- * Copyright (C) 2003-2004 Michel Dagenais
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License Version 2 as
- * published by the Free Software Foundation;
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA.
- */
-
-#ifndef BATCH_ANALYSIS_H
-#define BATCH_ANALYSIS_H
-
-/* The batch analysis module defines a main traceset and command line options
- to specify the traces in the main traceset. It then processes that
- traceset calling hooks lists at various stages of the analysis.
-
- The hooks lists are defined in the global attributes for these various
- stages of the analysis. Loaded modules may add hooks to these lists.
- Thus, by requesting that a certain module be loaded, the analysis may
- produce additional information as the module adds hooks and these hooks
- are called during the analysis.
-
- The hooks lists defined are as follows. These may be split in more
- specific lists eventually to select the hooks applicable to state update,
- incremental or batch processing...
-
- /hooks/traceset/before
- Before analyzing a traceset.
-
- /hooks/traceset/after
- After analyzing a traceset.
-
- /hooks/trace/before
- Before each trace.
-
- /hooks/trace/after
- After each trace.
-
- /hooks/tracefile/before
- Before each tracefile.
-
- /hooks/tracefile/after
- After each tracefile.
-
- /hooks/event/before
- Before each event.
-
- /hooks/event/after
- After each event.
-
-*/
-
-#endif // BATCH_ANALYSIS_H
+++ /dev/null
-/* This file is part of the Linux Trace Toolkit viewer
- * Copyright (C) 2003-2004 Xiangxiu Yang
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License Version 2 as
- * published by the Free Software Foundation;
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA.
- */
-
-#ifndef COMMON_H
-#define COMMON_H
-
-#include <stdio.h>
-#include <ltt/ltt.h>
-#include <gtk/gtk.h>
-#include <lttv/lttvfilter.h>
-
-#define MAX_NUMBER_EVENT "MAX_NUMBER_EVENT"
-#define TRACESET_TIME_SPAN "TRACESET_TIME_SPAN"
-
-typedef struct _MainWindow MainWindow;
-typedef struct _Tab Tab;
-
-/* constructor of the viewer */
-typedef GtkWidget * (*lttv_constructor)(MainWindow * main_window,
- LttvTracesetSelector * s, char *key);
-typedef lttv_constructor view_constructor;
-
-typedef struct _TimeWindow {
- LttTime start_time;
- LttTime time_width;
-} TimeWindow;
-
-#endif // COMMON_H
+++ /dev/null
-/* This file is part of the Linux Trace Toolkit viewer
- * Copyright (C) 2003-2004 Michel Dagenais
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License Version 2 as
- * published by the Free Software Foundation;
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA.
- */
-
-#ifndef FILTER_H
-#define FILTER_H
-
-/* A filter expression consists in nested AND, OR and NOT expressions
- involving boolean relation (>, >=, =, !=, <, <=) between event fields and
- specific values. It is compiled into an efficient data structure which
- is used in functions to check if a given event or tracefile satisfies the
- filter.
-
- The grammar for filters is:
-
- filter = expression
-
- expression = "(" expression ")" | "!" expression |
- expression "&&" expression | expression "||" expression |
- simpleExpression
-
- simpleExpression = fieldPath op value
-
- fieldPath = fieldComponent [ "." fieldPath ]
-
- fieldComponent = name [ "[" integer "]" ]
-
- value = integer | double | string
-
-*/
-
-
-typedef struct _lttv_filter lttv_filter;
-
-
-/* Compile the filter expression into an efficient data structure */
-
-lttv_filter *lttv_filter_new(char *expression, lttv_trace *t);
-
-
-/* Check if the tracefile or event satisfies the filter. The arguments are
- declared as void * to allow these functions to be used as hooks. */
-
-bool lttv_filter_tracefile(void *filter, void *tracefile);
-
-bool lttv_filter_event(void *filter, void *event);
-
-#endif // FILTER_H
-
+++ /dev/null
-/* This file is part of the Linux Trace Toolkit viewer
- * Copyright (C) 2003-2004 Xiangxiu Yang
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License Version 2 as
- * published by the Free Software Foundation;
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA.
- */
-
-
-#ifndef __GTK_DIR_SEL_H__
-#define __GTK_DIR_SEL_H__
-
-
-#include <gdk/gdk.h>
-#include <gtk/gtkdialog.h>
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-
-#define GTK_TYPE_DIR_SELECTION (gtk_dir_selection_get_type ())
-#define GTK_DIR_SELECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_DIR_SELECTION, GtkDirSelection))
-#define GTK_DIR_SELECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_DIR_SELECTION, GtkDirSelectionClass))
-#define GTK_IS_DIR_SELECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_DIR_SELECTION))
-#define GTK_IS_DIR_SELECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_DIR_SELECTION))
-#define GTK_DIR_SELECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_DIR_SELECTION, GtkDirSelectionClass))
-
-
-typedef struct _GtkDirSelection GtkDirSelection;
-typedef struct _GtkDirSelectionClass GtkDirSelectionClass;
-
-struct _GtkDirSelection
-{
- GtkDialog parent_instance;
-
- GtkWidget *dir_list;
- GtkWidget *file_list;
- GtkWidget *selection_entry;
- GtkWidget *selection_text;
- GtkWidget *main_vbox;
- GtkWidget *ok_button;
- GtkWidget *cancel_button;
- GtkWidget *help_button;
- GtkWidget *history_pulldown;
- GtkWidget *history_menu;
- GList *history_list;
- GtkWidget *fileop_dialog;
- GtkWidget *fileop_entry;
- gchar *fileop_file;
- gpointer cmpl_state;
-
- GtkWidget *fileop_c_dir;
- GtkWidget *fileop_del_file;
- GtkWidget *fileop_ren_file;
-
- GtkWidget *button_area;
- GtkWidget *action_area;
-
- GPtrArray *selected_names;
- gchar *last_selected;
-};
-
-struct _GtkDirSelectionClass
-{
- GtkDialogClass parent_class;
-
- /* Padding for future expansion */
- void (*_gtk_reserved1) (void);
- void (*_gtk_reserved2) (void);
- void (*_gtk_reserved3) (void);
- void (*_gtk_reserved4) (void);
-};
-
-
-GType gtk_dir_selection_get_type (void) G_GNUC_CONST;
-GtkWidget* gtk_dir_selection_new (const gchar *title);
-void gtk_dir_selection_set_filename (GtkDirSelection *filesel,
- const gchar *filename);
-/* This function returns the selected filename in the C runtime's
- * multibyte string encoding, which may or may not be the same as that
- * used by GDK (UTF-8). To convert to UTF-8, call g_filename_to_utf8().
- * The returned string points to a statically allocated buffer and
- * should be copied away.
- */
-G_CONST_RETURN gchar* gtk_dir_selection_get_filename (GtkDirSelection *filesel);
-
-void gtk_dir_selection_complete (GtkDirSelection *filesel,
- const gchar *pattern);
-void gtk_dir_selection_show_fileop_buttons (GtkDirSelection *filesel);
-void gtk_dir_selection_hide_fileop_buttons (GtkDirSelection *filesel);
-
-gchar** gtk_dir_selection_get_selections (GtkDirSelection *filesel);
-const gchar * gtk_dir_selection_get_dir (GtkDirSelection *filesel);
-void gtk_dir_selection_set_select_multiple (GtkDirSelection *filesel,
- gboolean select_multiple);
-gboolean gtk_dir_selection_get_select_multiple (GtkDirSelection *filesel);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-
-#endif /* __GTK_DIR_SEL_H__ */
+++ /dev/null
-
-/* This file is part of the Linux Trace Toolkit viewer
- * Copyright (C) 2003-2004 Xiangxiu Yang
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License Version 2 as
- * published by the Free Software Foundation;
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA.
- */
-
-#ifndef __GTK_MULTI_VPANED_H__
-#define __GTK_MULTI_VPANED_H__
-
-
-#include <glib.h>
-#include <glib-object.h>
-#include <gdk/gdk.h>
-#include <gtk/gtkcontainer.h>
-#include <lttv/common.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-
-#define GTK_TYPE_MULTI_VPANED (gtk_multi_vpaned_get_type ())
-#define GTK_MULTI_VPANED(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_MULTI_VPANED, GtkMultiVPaned))
-#define GTK_MULTI_VPANED_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_MULTI_VPANED, GtkMultiVPanedClass))
-#define GTK_IS_MULTI_VPANED(obj ) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_MULTI_VPANED))
-#define GTK_IS_MULTI_VPANED_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_MULTI_VPANED))
-#define GTK_MULTI_VPANED_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_MULTI_VPANED, GtkMultiVPanedClass))
-
-
-typedef struct _GtkMultiVPaned GtkMultiVPaned;
-typedef struct _GtkMultiVPanedClass GtkMultiVPanedClass;
-
-struct _GtkMultiVPaned
-{
- GtkPaned container;
-
- /*< public >*/
- GtkPaned * first_pane;
- GtkPaned * last_pane;
- GtkPaned * focused_pane;
- GtkPaned * iter;
- guint num_children;
-
- GtkWidget * vbox;
- // GtkWidget * scrollWindow;
- // GtkWidget * viewport;
- GtkWidget * hscrollbar;
- GtkAdjustment *hadjust;
- MainWindow * mw;
-};
-
-struct _GtkMultiVPanedClass
-{
- GtkPanedClass parent_class;
-};
-
-
-GType gtk_multi_vpaned_get_type (void) G_GNUC_CONST;
-GtkWidget* gtk_multi_vpaned_new (void);
-
-void gtk_multi_vpaned_set_focus (GtkWidget * widget, gpointer user_data);
-void gtk_multi_vpaned_widget_add(GtkMultiVPaned * multi_vpaned, GtkWidget * widget1);
-void gtk_multi_vpaned_widget_delete(GtkMultiVPaned * multi_vpaned);
-void gtk_multi_vpaned_widget_move_up(GtkMultiVPaned * multi_vpaned);
-void gtk_multi_vpaned_widget_move_down(GtkMultiVPaned * multi_vpaned);
-void gtk_multi_vpaned_set_adjust(GtkMultiVPaned * multi_vpaned, gboolean first_time);
-void gtk_multi_vpaned_set_data(GtkMultiVPaned * multi_vpaned, char * key, gpointer value);
-gpointer gtk_multi_vpaned_get_data(GtkMultiVPaned * multi_vpaned, char * key);
-GtkWidget * gtk_multi_vpaned_get_widget(GtkMultiVPaned * multi_vpaned);
-GtkWidget * gtk_multi_vpaned_get_first_widget(GtkMultiVPaned * multi_vpaned);
-GtkWidget * gtk_multi_vpaned_get_next_widget(GtkMultiVPaned * multi_vpaned);
-void gtk_multi_vpaned_set_scroll_value(GtkMultiVPaned * multi_vpaned, double value);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-
-#endif /* __GTK_MULTI_VPANED_H__ */
+++ /dev/null
-/* This file is part of the Linux Trace Toolkit viewer
- * Copyright (C) 2003-2004 Xiangxiu Yang
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License Version 2 as
- * published by the Free Software Foundation;
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * 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.
- *
- * Main window (gui module) is the place to contain and display viewers.
- * Viewers (lttv plugins) interacte with main window through this API and
- * events sent by gtk.
- * This header file should be included in each graphic module.
- * This library is used by graphical modules to interact with the
- * tracesetWindow.
- *
- */
-
-#include <gtk/gtk.h>
-#include <ltt/ltt.h>
-#include <lttv/hook.h>
-#include <lttv/common.h>
-#include <lttv/stats.h>
-
-/**
- * Function to register a view constructor so that main window can generate
- * a toolbar item for the viewer in order to generate a new instance easily.
- * It will be called by init function of the module.
- * @param ButtonPixmap image shown on the toolbar item.
- * @param tooltip tooltip of the toolbar item.
- * @param view_constructor constructor of the viewer.
- */
-
-void toolbar_item_reg(char ** pixmap, char *tooltip, lttv_constructor view_constructor);
-
-
-/**
- * Function to unregister the viewer's constructor, release the space
- * occupied by pixmap, tooltip and constructor of the viewer.
- * It will be called when a module is unloaded.
- * @param view_constructor constructor of the viewer which is used as
- * a reference to find out where the pixmap and tooltip are.
- */
-
-void toolbar_item_unreg(lttv_constructor view_constructor);
-
-
-/**
- * Function to register a view constructor so that main window can generate
- * a menu item for the viewer in order to generate a new instance easily.
- * It will be called by init function of the module.
- * @param menu_path path of the menu item.
- * @param menu_text text of the menu item.
- * @param view_constructor constructor of the viewer.
- */
-
-void menu_item_reg(char *menu_path, char *menu_text, lttv_constructor view_constructor);
-
-
-/**
- * Function to unregister the viewer's constructor, release the space
- * occupied by menu_path, menu_text and constructor of the viewer.
- * It will be called when a module is unloaded.
- * @param view_constructor constructor of the viewer which is used as
- * a reference to find out where the menu_path and menu_text are.
- */
-
-void menu_item_unreg(lttv_constructor view_constructor);
-
-
-/**
- * Update the status bar whenever something changed in the viewer.
- * @param main_win the main window the viewer belongs to.
- * @param info the message which will be shown in the status bar.
- */
-
-void update_status(MainWindow *main_win, char *info);
-
-
-/**
- * Function to get the current time window of the current tab.
- * It will be called by a viewer's hook function to update the
- * time window of the viewer and also be called by the constructor
- * of the viewer.
- * @param main_win the main window the viewer belongs to.
- * @param time_interval a pointer where time interval will be stored.
- */
-
-void get_time_window(MainWindow *main_win, TimeWindow *time_window);
-
-
-/**
- * Function to set the time interval of the current tab.
- * It will be called by a viewer's signal handle associated with
- * the move_slider signal
- * @param main_win the main window the viewer belongs to.
- * @param time_interval a pointer where time interval is stored.
- */
-
-void set_time_window(MainWindow *main_win, TimeWindow *time_window);
-
-/**
- * Function to get the current time/event of the current tab.
- * It will be called by a viewer's hook function to update the
- * current time/event of the viewer.
- * @param main_win the main window the viewer belongs to.
- * @param time a pointer where time will be stored.
- */
-
-void get_current_time(MainWindow *main_win, LttTime *time);
-
-
-/**
- * Function to set the current time/event of the current tab.
- * It will be called by a viewer's signal handle associated with
- * the button-release-event signal
- * @param main_win the main window the viewer belongs to.
- * @param time a pointer where time is stored.
- */
-
-void set_current_time(MainWindow *main_win, LttTime *time);
-
-
-/**
- * Function to get the traceset from the current tab.
- * It will be called by the constructor of the viewer and also be
- * called by a hook funtion of the viewer to update its traceset.
- * @param main_win the main window the viewer belongs to.
- * @param traceset a pointer to a traceset.
- */
-
-//void get_traceset(MainWindow *main_win, Traceset *traceset);
-
-
-/**
- * Function to get the filter of the current tab.
- * It will be called by the constructor of the viewer and also be
- * called by a hook funtion of the viewer to update its filter.
- * @param main_win, the main window the viewer belongs to.
- * @param filter, a pointer to a filter.
- */
-
-//void get_filter(MainWindow *main_win, Filter *filter);
-
-
-/**
- * Function to register a hook function for a viewer to set/update its
- * time interval.
- * It will be called by the constructor of the viewer.
- * @param hook hook function of the viewer. Takes a TimeInterval* as call_data.
- * @param hook_data hook data associated with the hook function.
- * @param main_win the main window the viewer belongs to.
- */
-
-void reg_update_time_window(LttvHook hook, gpointer hook_data,
- MainWindow * main_win);
-
-
-/**
- * Function to unregister a viewer's hook function which is used to
- * set/update the time interval of the viewer.
- * It will be called by the destructor of the viewer.
- * @param hook hook function of the viewer. Takes a TimeInterval as call_data.
- * @param hook_data hook data associated with the hook function.
- * @param main_win the main window the viewer belongs to.
- */
-
-void unreg_update_time_window(LttvHook hook, gpointer hook_data,
- MainWindow * main_win);
-
-
-/**
- * Function to register a hook function for a viewer to set/update its
- * traceset.
- * It will be called by the constructor of the viewer.
- * @param hook hook function of the viewer.
- * @param hook_data hook data associated with the hook function.
- * @param main_win the main window the viewer belongs to.
- */
-
-void reg_update_traceset(LttvHook hook, gpointer hook_data,
- MainWindow * main_win);
-
-
-/**
- * Function to unregister a viewer's hook function which is used to
- * set/update the traceset of the viewer.
- * It will be called by the destructor of the viewer.
- * @param hook hook function of the viewer.
- * @param hook_data hook data associated with the hook function.
- * @param main_win the main window the viewer belongs to.
- */
-
-void unreg_update_traceset(LttvHook hook, gpointer hook_data,
- MainWindow * main_win);
-
-
-/**
- * Function to redraw each viewer belonging to the current tab
- * @param main_win the main window the viewer belongs to.
- */
-
-void update_traceset(MainWindow * main_win);
-
-
-/**
- * Function to register a hook function for a viewer to set/update its
- * filter.
- * It will be called by the constructor of the viewer.
- * @param hook hook function of the viewer.
- * @param hook_data hook data associated with the hook function.
- * @param main_win the main window the viewer belongs to.
- */
-
-void reg_update_filter(LttvHook hook, gpointer hook_data,
- MainWindow *main_win);
-
-
-/**
- * Function to unregister a viewer's hook function which is used to
- * set/update the filter of the viewer.
- * It will be called by the destructor of the viewer.
- * @param hook hook function of the viewer.
- * @param hook_data hook data associated with the hook function.
- * @param main_win the main window the viewer belongs to.
- */
-
-void unreg_update_filter(LttvHook hook, gpointer hook_data,
- MainWindow * main_win);
-
-
-/**
- * Function to register a hook function for a viewer to set/update its
- * current time.
- * It will be called by the constructor of the viewer.
- * @param hook hook function of the viewer.
- * @param hook_data hook data associated with the hook function.
- * @param main_win the main window the viewer belongs to.
- */
-
-void reg_update_current_time(LttvHook hook, gpointer hook_data,
- MainWindow *main_win);
-
-
-/**
- * Function to unregister a viewer's hook function which is used to
- * set/update the current time of the viewer.
- * It will be called by the destructor of the viewer.
- * @param hook hook function of the viewer.
- * @param hook_data hook data associated with the hook function.
- * @param main_win the main window the viewer belongs to.
- */
-
-void unreg_update_current_time(LttvHook hook, gpointer hook_data,
- MainWindow * main_win);
-
-
-/**
- * Function to register a hook function for a viewer to show
- *the content of the viewer.
- * It will be called by the constructor of the viewer.
- * @param hook hook function of the viewer.
- * @param hook_data hook data associated with the hook function.
- * @param main_win the main window the viewer belongs to.
- */
-
-void reg_show_viewer(LttvHook hook, gpointer hook_data,
- MainWindow *main_win);
-
-
-/**
- * Function to unregister a viewer's hook function which is used to
- * show the content of the viewer..
- * It will be called by the destructor of the viewer.
- * @param hook hook function of the viewer.
- * @param hook_data hook data associated with the hook function.
- * @param main_win the main window the viewer belongs to.
- */
-
-void unreg_show_viewer(LttvHook hook, gpointer hook_data,
- MainWindow * main_win);
-
-
-/**
- * Function to show each viewer in the current tab.
- * It will be called by main window after it called process_traceset
- * @param main_win the main window the viewer belongs to.
- */
-
-void show_viewer(MainWindow *main_win);
-
-
-/**
- * Function to set the focused pane (viewer).
- * It will be called by a viewer's signal handle associated with
- * the grab_focus signal
- * @param main_win the main window the viewer belongs to.
- * @param paned a pointer to a pane where the viewer is contained.
- */
-
-void set_focused_pane(MainWindow *main_win, gpointer paned);
-
-
-/**
- * Function to register a hook function for a viewer to set/update the
- * dividor of the hpane.
- * It will be called by the constructor of the viewer.
- * @param hook hook function of the viewer.
- * @param hook_data hook data associated with the hook function.
- * @param main_win the main window the viewer belongs to.
- */
-
-void reg_update_dividor(LttvHook hook, gpointer hook_data,
- MainWindow *main_win);
-
-
-/**
- * Function to unregister a viewer's hook function which is used to
- * set/update hpane's dividor of the viewer.
- * It will be called by the destructor of the viewer.
- * @param hook hook function of the viewer.
- * @param hook_data hook data associated with the hook function.
- * @param main_win the main window the viewer belongs to.
- */
-
-void unreg_update_dividor(LttvHook hook, gpointer hook_data,
- MainWindow *main_win);
-
-
-/**
- * Function to set the position of the hpane's dividor (viewer).
- * It will be called by a viewer's signal handle associated with
- * the motion_notify_event event/signal
- * @param main_win the main window the viewer belongs to.
- * @param position position of the hpane's dividor.
- */
-
-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.
- * @param main_win the main window the viewer belongs to.
- * @param start the start time of the first event to be processed.
- * @param end the end time of the last event to be processed.
- */
-
-void process_traceset_api(MainWindow *main_win, LttTime start,
- LttTime end, unsigned maxNumEvents);
-
-
-/**
- * Function to add hooks into the context of a traceset,
- * before reading events from traceset, viewer will call this api to
- * register hooks
- * @param main_win the main window the viewer belongs to.
- * @param LttvHooks hooks to be registered.
- */
-
-void context_add_hooks_api(MainWindow *main_win ,
- LttvHooks *before_traceset,
- LttvHooks *after_traceset,
- LttvHooks *check_trace,
- LttvHooks *before_trace,
- LttvHooks *after_trace,
- LttvHooks *check_tracefile,
- LttvHooks *before_tracefile,
- LttvHooks *after_tracefile,
- LttvHooks *check_event,
- LttvHooks *before_event,
- LttvHooks *after_event);
-
-
-/**
- * Function to remove hooks from the context of a traceset,
- * before reading events from traceset, viewer will call this api to
- * unregister hooks
- * @param main_win the main window the viewer belongs to.
- * @param LttvHooks hooks to be registered.
- */
-
-void context_remove_hooks_api(MainWindow *main_win ,
- LttvHooks *before_traceset,
- LttvHooks *after_traceset,
- LttvHooks *check_trace,
- LttvHooks *before_trace,
- LttvHooks *after_trace,
- LttvHooks *check_tracefile,
- LttvHooks *before_tracefile,
- LttvHooks *after_tracefile,
- LttvHooks *check_event,
- LttvHooks *before_event,
- LttvHooks *after_event);
-
-
-/**
- * Function to get the life span of the traceset
- * @param main_win the main window the viewer belongs to.
- * @param start start time of the traceset.
- * @param end end time of the traceset.
- */
-
-void get_traceset_time_span(MainWindow *main_win, TimeInterval *time_span);
-
-
-/**
- * Function to add/remove event hooks for state
- * @param main_win the main window the viewer belongs to.
- */
-
-void state_add_event_hooks_api(MainWindow *main_win );
-void state_remove_event_hooks_api(MainWindow *main_win );
-
-
-/**
- * Function to add/remove event hooks for stats
- * @param main_win the main window the viewer belongs to.
- */
-
-void stats_add_event_hooks_api(MainWindow *main_win );
-void stats_remove_event_hooks_api(MainWindow *main_win );
-
-
-/**
- * Function to get the stats of the traceset
- * @param main_win the main window the viewer belongs to.
- */
-
-LttvTracesetStats* get_traceset_stats_api(MainWindow *main_win);
-
-LttvTracesetContext* get_traceset_context(MainWindow *main_win);
+++ /dev/null
-/* This file is part of the Linux Trace Toolkit viewer
- * Copyright (C) 2003-2004 Michel Dagenais
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License Version 2 as
- * published by the Free Software Foundation;
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA.
- */
-
-#ifndef HOOK_H
-#define HOOK_H
-
-#include <glib.h>
-
-/* A hook is a function to call with the supplied hook data, and with
- call site specific data (e.g., hooks for events are called with a
- pointer to the current event). */
-
-typedef gboolean (*LttvHook)(void *hook_data, void *call_data);
-
-
-/* A list of hooks allows registering hooks to be called later. */
-
-typedef GArray LttvHooks;
-
-
-/* Create and destroy a list of hooks */
-
-LttvHooks *lttv_hooks_new();
-
-void lttv_hooks_destroy(LttvHooks *h);
-
-
-/* Add a hook and its hook data to the list */
-
-void lttv_hooks_add(LttvHooks *h, LttvHook f, void *hook_data);
-
-
-/* Add a list of hooks to the list h */
-
-void lttv_hooks_add_list(LttvHooks *h, LttvHooks *list);
-
-
-/* Remove a hook from the list. Return the hook data. */
-
-void *lttv_hooks_remove(LttvHooks *h, LttvHook f);
-
-
-/* Remove a hook from the list checking that the hook data match. */
-
-void lttv_hooks_remove_data(LttvHooks *h, LttvHook f, void *hook_data);
-
-
-/* Remove a list of hooks from the hooks list in h. */
-
-void lttv_hooks_remove_data_list(LttvHooks *h, LttvHook *list);
-
-
-/* Return the number of hooks in the list */
-
-unsigned lttv_hooks_number(LttvHooks *h);
-
-
-/* Return the hook at the specified position in the list */
-
-void lttv_hooks_get(LttvHooks *h, unsigned i, LttvHook *f, void **hook_data);
-
-
-/* Remove the specified hook. The position of the following hooks may change */
-
-void lttv_hooks_remove_by_position(LttvHooks *h, unsigned i);
-
-
-/* Call all the hooks in the list, each with its hook data,
- with the specified call data. Return TRUE if one hook returned TRUE. */
-
-gboolean lttv_hooks_call(LttvHooks *h, void *call_data);
-
-
-/* Call the hooks in the list until one returns true, in which case TRUE is
- returned. */
-
-gboolean lttv_hooks_call_check(LttvHooks *h, void *call_data);
-
-
-/* Sometimes different hooks need to be called based on the case. The
- case is represented by an unsigned integer id */
-
-typedef GPtrArray LttvHooksById;
-
-
-/* Create and destroy a hooks by id list */
-
-LttvHooksById *lttv_hooks_by_id_new();
-
-void lttv_hooks_by_id_destroy(LttvHooksById *h);
-
-
-/* Obtain the hooks for a given id, creating a list if needed */
-
-LttvHooks *lttv_hooks_by_id_find(LttvHooksById *h, unsigned id);
-
-
-/* Return an id larger than any for which a list exists. */
-
-unsigned lttv_hooks_by_id_max_id(LttvHooksById *h);
-
-
-/* Get the list of hooks for an id, NULL if none exists */
-
-LttvHooks *lttv_hooks_by_id_get(LttvHooksById *h, unsigned id);
-
-
-/* Remove the list of hooks associated with an id */
-
-void lttv_hooks_by_id_remove(LttvHooksById *h, unsigned id);
-
-#endif // HOOK_H
+++ /dev/null
-/* This file is part of the Linux Trace Toolkit viewer
- * Copyright (C) 2003-2004 Michel Dagenais
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License Version 2 as
- * published by the Free Software Foundation;
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA.
- */
-
-#ifndef IATTRIBUTE_H
-#define IATTRIBUTE_H
-
-
-#include <glib-object.h>
-#include <ltt/time.h>
-
-/* The content of a data structure may be seen as an array of pairs of
- attribute name and value. This simple model allows generic navigation
- and access functions over a wide range of structures. The names are
- represented by unique integer identifiers, GQuarks. */
-
-typedef GQuark LttvAttributeName;
-
-typedef enum _LttvAttributeType {
- LTTV_INT, LTTV_UINT, LTTV_LONG, LTTV_ULONG, LTTV_FLOAT, LTTV_DOUBLE,
- LTTV_TIME, LTTV_POINTER, LTTV_STRING, LTTV_GOBJECT, LTTV_NONE
-} LttvAttributeType;
-
-typedef union LttvAttributeValue {
- int *v_int;
- unsigned *v_uint;
- long *v_long;
- unsigned long *v_ulong;
- float *v_float;
- double *v_double;
- LttTime *v_time;
- gpointer *v_pointer;
- char **v_string;
- GObject **v_gobject;
-} LttvAttributeValue;
-
-
-/* GObject interface type macros */
-
-#define LTTV_IATTRIBUTE_TYPE (lttv_iattribute_get_type ())
-#define LTTV_IATTRIBUTE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LTTV_IATTRIBUTE_TYPE, LttvIAttribute))
-#define LTTV_IATTRIBUTE_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST ((vtable), LTTV_IATTRIBUTE_TYPE, LttvIAttributeClass))
-#define LTTV_IS_IATTRIBUTE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LTTV_IATTRIBUTE_TYPE))
-#define LTTV_IS_IATTRIBUTE_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), LTTV_IATTRIBUTE_TYPE))
-#define LTTV_IATTRIBUTE_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), LTTV_IATTRIBUTE_TYPE, LttvIAttributeClass))
-
-
-typedef struct _LttvIattribute LttvIAttribute; /* dummy object */
-typedef struct _LttvIAttributeClass LttvIAttributeClass;
-
-
-struct _LttvIAttributeClass {
- GTypeInterface parent;
-
- unsigned int (*get_number) (LttvIAttribute *self);
-
- gboolean (*named) (LttvIAttribute *self, gboolean *homogeneous);
-
- LttvAttributeType (*get) (LttvIAttribute *self, unsigned i,
- LttvAttributeName *name, LttvAttributeValue *v);
-
- LttvAttributeType (*get_by_name) (LttvIAttribute *self,
- LttvAttributeName name, LttvAttributeValue *v);
-
- LttvAttributeValue (*add) (LttvIAttribute *self, LttvAttributeName name,
- LttvAttributeType t);
-
- void (*remove) (LttvIAttribute *self, unsigned i);
-
- void (*remove_by_name) (LttvIAttribute *self,
- LttvAttributeName name);
-
- LttvIAttribute* (*find_subdir) (LttvIAttribute *self,
- LttvAttributeName name);
-};
-
-
-GType lttv_iattribute_get_type(void);
-
-
-/* Total number of attributes */
-
-unsigned int lttv_iattribute_get_number(LttvIAttribute *self);
-
-
-/* Container type. Named (fields in struct or elements in a hash table)
- or unnamed (elements in an array) attributes, homogeneous type or not. */
-
-gboolean lttv_iattribute_named(LttvIAttribute *self, gboolean *homogeneous);
-
-
-/* Get the i th attribute along with its type and a pointer to its value. */
-
-LttvAttributeType lttv_iattribute_get(LttvIAttribute *self, unsigned i,
- LttvAttributeName *name, LttvAttributeValue *v);
-
-
-/* Get the named attribute in the table along with its type and a pointer to
- its value. If the named attribute does not exist, the type is LTTV_NONE. */
-
-LttvAttributeType lttv_iattribute_get_by_name(LttvIAttribute *self,
- LttvAttributeName name, LttvAttributeValue *v);
-
-
-/* Add an attribute, which must not exist. The name is an empty string for
- containers with unnamed attributes. Its value is initialized to 0 or NULL
- and its pointer returned. */
-
-LttvAttributeValue lttv_iattribute_add(LttvIAttribute *self,
- LttvAttributeName name, LttvAttributeType t);
-
-
-/* Remove an attribute */
-
-void lttv_iattribute_remove(LttvIAttribute *self, unsigned i);
-
-void lttv_iattribute_remove_by_name(LttvIAttribute *self,
- LttvAttributeName name);
-
-
-/* Create an empty iattribute object and add it as an attribute under the
- specified name, or return an existing iattribute attribute. If an
- attribute of that name already exists but is not a GObject supporting the
- iattribute interface, return NULL. */
-
-LttvIAttribute* lttv_iattribute_find_subdir(LttvIAttribute *self,
- LttvAttributeName name);
-
-
-/* The remaining utility functions are not part of the LttvIAttribute
- interface but operate on objects implementing it. */
-
-/* Find the named attribute in the table, which must be of the specified type.
- If it does not exist, it is created with a default value of 0 (NULL for
- pointer types). Since the address of the value is obtained, it may be
- changed easily afterwards. The function returns false when the attribute
- exists but is of incorrect type. */
-
-gboolean lttv_iattribute_find(LttvIAttribute *self, LttvAttributeName name,
- LttvAttributeType t, LttvAttributeValue *v);
-
-
-/* Trees of attribute tables may be accessed using a hierarchical path with
- components separated by /, like in filesystems */
-
-gboolean lttv_iattribute_find_by_path(LttvIAttribute *self, char *path,
- LttvAttributeType t, LttvAttributeValue *v);
-
-
-/* Shallow and deep copies */
-
-void lttv_iattribute_copy_value(LttvAttributeType t, LttvAttributeValue dest,
- LttvAttributeValue src);
-
-LttvIAttribute *lttv_iattribute_shallow_copy(LttvIAttribute *self);
-
-LttvIAttribute *lttv_iattribute_deep_copy(LttvIAttribute *self);
-
-#endif // IATTRIBUTE_H
+++ /dev/null
-/* This file is part of the Linux Trace Toolkit viewer
- * Copyright (C) 2003-2004 Michel Dagenais
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License Version 2 as
- * published by the Free Software Foundation;
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA.
- */
-
-#ifndef LTTV_H
-#define LTTV_H
-
-#include <lttv/attribute.h>
-
-/* The modules in the visualizer communicate with the main module and
- with each other through attributes. There is a global set of attributes */
-
-LttvAttribute *lttv_global_attributes();
-
-extern gboolean lttv_profile_memory;
-
-extern int lttv_argc;
-
-extern char **lttv_argv;
-
-/* A number of global attributes are initialized before modules are
- loaded, for example hooks lists. More global attributes are defined
- in individual mudules to store information or to communicate with other
- modules (GUI windows, menus...).
-
- The hooks lists (lttv_hooks) are initialized in the main module and may be
- used by other modules. Each corresponds to a specific location in the main
- module processing loop. The attribute key and typical usage for each
- is indicated.
-
- /hooks/options/before
- Good place to define new command line options to be parsed.
-
- /hooks/options/after
- Read the values set by the command line options.
-
- /hooks/main/before
-
- /hooks/main/after
-
-*/
-
-#define g_info(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, format)
-#define g_debug(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, format)
-
-#endif // LTTV_H
+++ /dev/null
-/* This file is part of the Linux Trace Toolkit viewer
- * Copyright (C) 2003-2004 Xiangxiu Yang
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License Version 2 as
- * published by the Free Software Foundation;
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA.
- */
-
-#ifndef LTTV_FILTER_H
-#define LTTV_FILTER_H
-
-#include <ltt/ltt.h>
-
-
-typedef struct _LttvTracesetSelector LttvTracesetSelector;
-typedef struct _LttvTraceSelector LttvTraceSelector;
-typedef struct _LttvTracefileSelector LttvTracefileSelector;
-typedef struct _LttvEventtypeSelector LttvEventtypeSelector;
-
-
-LttvTracesetSelector *lttv_traceset_selector_new(char * name);
-LttvTraceSelector *lttv_trace_selector_new(LttTrace *t);
-LttvTracefileSelector *lttv_tracefile_selector_new(LttTracefile *t);
-LttvEventtypeSelector *lttv_eventtype_selector_new(LttEventType * et);
-void lttv_traceset_selector_destroy(LttvTracesetSelector *s);
-void lttv_trace_selector_destroy(LttvTraceSelector *t);
-void lttv_tracefile_selector_destroy(LttvTracefileSelector *t);
-void lttv_eventtype_selector_destroy(LttvEventtypeSelector *t);
-
-
-void lttv_traceset_selector_trace_add(LttvTracesetSelector *s,
- LttvTraceSelector *t);
-unsigned lttv_traceset_selector_trace_number(LttvTracesetSelector *s);
-LttvTraceSelector *lttv_traceset_selector_trace_get(LttvTracesetSelector *s,
- unsigned i);
-void lttv_traceset_selector_trace_remove(LttvTracesetSelector *s,
- unsigned i);
-
-
-void lttv_trace_selector_tracefile_add(LttvTraceSelector *s,
- LttvTracefileSelector *t);
-unsigned lttv_trace_selector_tracefile_number(LttvTraceSelector *s);
-LttvTracefileSelector *lttv_trace_selector_tracefile_get(LttvTraceSelector *s,
- unsigned i);
-void lttv_trace_selector_tracefile_remove(LttvTraceSelector *s, unsigned i);
-
-void lttv_trace_selector_eventtype_add(LttvTraceSelector *s,
- LttvEventtypeSelector *et);
-unsigned lttv_trace_selector_eventtype_number(LttvTraceSelector *s);
-LttvEventtypeSelector *lttv_trace_selector_eventtype_get(LttvTraceSelector *s,
- unsigned i);
-void lttv_trace_selector_eventtype_remove(LttvTraceSelector *s, unsigned i);
-
-
-void lttv_tracefile_selector_eventtype_add(LttvTracefileSelector *s,
- LttvEventtypeSelector *et);
-unsigned lttv_tracefile_selector_eventtype_number(LttvTracefileSelector *s);
-LttvEventtypeSelector *lttv_tracefile_selector_eventtype_get(LttvTracefileSelector *s,
- unsigned i);
-void lttv_tracefile_selector_eventtype_remove(LttvTracefileSelector *s, unsigned i);
-
-
-void lttv_trace_selector_set_selected(LttvTraceSelector *s, gboolean g);
-void lttv_tracefile_selector_set_selected(LttvTracefileSelector *s, gboolean g);
-void lttv_eventtype_selector_set_selected(LttvEventtypeSelector *s, gboolean g);
-gboolean lttv_trace_selector_get_selected(LttvTraceSelector *s);
-gboolean lttv_tracefile_selector_get_selected(LttvTracefileSelector *s);
-gboolean lttv_eventtype_selector_get_selected(LttvEventtypeSelector *s);
-char * lttv_traceset_selector_get_name(LttvTracesetSelector *s);
-char * lttv_trace_selector_get_name(LttvTraceSelector *s);
-char * lttv_tracefile_selector_get_name(LttvTracefileSelector *s);
-char * lttv_eventtype_selector_get_name(LttvEventtypeSelector *s);
-
-LttvEventtypeSelector * lttv_eventtype_selector_clone(LttvEventtypeSelector * s);
-void lttv_eventtype_selector_copy(LttvTraceSelector *s, LttvTracefileSelector *d);
-
-
-#endif // LTTV_FILTER_H
-
+++ /dev/null
-/* This file is part of the Linux Trace Toolkit viewer
- * Copyright (C) 2003-2004 Xiangxiu Yang
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License Version 2 as
- * published by the Free Software Foundation;
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA.
- */
-
-#ifndef _MAIN_WINDOW_
-#define _MAIN_WINDOW_
-
-#include <gtk/gtk.h>
-
-#include <ltt/ltt.h>
-#include <lttv/attribute.h>
-#include <lttv/traceset.h>
-#include <lttv/processTrace.h>
-
-#include <lttv/common.h>
-#include <lttv/gtkmultivpaned.h>
-#include <lttv/hook.h>
-#include <lttv/stats.h>
-
-typedef struct _TracesetInfo {
- //FIXME? TracesetContext and stats in same or different variable ?
- LttvTracesetStats * traceset_context;
- LttvTraceset * traceset;
-} TracesetInfo ;
-
-
-struct _MainWindow{
- GtkWidget* mwindow; /* Main Window */
- int window_width;
-
- /* Status bar information */
- // guint MainSBarContextID; /* Context ID of main status bar */
- // guint BegTimeSBarContextID; /* Context ID of BegTime status bar */
- // guint EndTimeSBarContextID; /* Context ID of EndTime status bar */
-
- /* Child windows */
- //openTracesetWindow* OpenTracesetWindow;/* Window to get prof and proc file*/
- //viewTimeFrameWindow* ViewTimeFrameWindow;/*Window to select time frame */
- //gotoEventWindow* GotoEventWindow; /*search for event description*/
- //openFilterWindow* OpenFilterWindow; /* Open a filter selection window */
- GtkWidget* help_contents;/* Window to display help contents */
- GtkWidget* about_box; /* Window about information */
-
- // lttv_trace_filter * filter; /* trace filter associated with the window */
-
- /* Attributes for trace reading hooks local to the main window */
- LttvIAttribute * attributes;
-
- Tab * tab;
- Tab * current_tab;
-
- GHashTable * hash_menu_item;
- GHashTable * hash_toolbar_item;
-};
-
-
-struct _Tab{
- GtkWidget * label;
- GtkMultiVPaned * multi_vpaned;
-
- // startTime is the left of the visible area. Corresponds to the scrollbar
- // value.
- // Time_Width is a zoom dependant value (corresponding to page size)
- TimeWindow time_window;
-
- // The current time is the time selected in the visible area by the user,
- // not the scrollbar value.
- LttTime current_time;
- LttvIAttribute * attributes;
-
- struct _Tab * next;
- MainWindow * mw;
-
- /* Traceset related information */
- TracesetInfo * traceset_info;
-};
-
-/**
- * Remove menu and toolbar item when a module unloaded
- */
-void main_window_remove_menu_item(lttv_constructor view_constructor);
-void main_window_remove_toolbar_item(lttv_constructor view_constructor);
-
-#endif /* _MAIN_WINDOW_ */
-
-
+++ /dev/null
-/* This file is part of the Linux Trace Toolkit viewer
- * Copyright (C) 2003-2004 Xiangxiu Yang
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License Version 2 as
- * published by the Free Software Foundation;
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA.
- */
-
-#ifndef MENU_H
-#define MENU_H
-
-#include <lttv/common.h>
-
-/* constructor of the viewer */
-//typedef GtkWidget* (*lttv_constructor)(void * main_window);
-
-
-typedef GArray LttvMenus;
-
-typedef struct _lttv_menu_closure {
- lttv_constructor con;
- char * menuPath;
- char * menuText;
-} lttv_menu_closure;
-
-
-LttvMenus *lttv_menus_new();
-
-void lttv_menus_destroy(LttvMenus *h);
-
-void lttv_menus_add(LttvMenus *h, lttv_constructor f, char* menuPath, char * menuText);
-
-gboolean lttv_menus_remove(LttvMenus *h, lttv_constructor f);
-
-unsigned lttv_menus_number(LttvMenus *h);
-
-#endif // MENU_H
+++ /dev/null
-/* This file is part of the Linux Trace Toolkit viewer
- * Copyright (C) 2003-2004 Michel Dagenais
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License Version 2 as
- * published by the Free Software Foundation;
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA.
- */
-
-#ifndef MODULES_H
-#define MODULES_H
-
-#include <glib.h>
-
-/* A module contains some functionality which becomes available atfer it is
- initialized and before it is destroyed. A module is characterized by a name,
- a description (short and long), a list of names of other modules on which
- it depends, and an initialization and a destruction function.
-
- A library contains one or more modules and may be loaded dynamically.
- The modules contained in a library are automatically registered through
- constructors which are called when the library is loaded. For modules
- directly linked with the main program (builtin), the constructors are
- called before the main program starts. (However, neither malloc nor glib
- functions are used during the registration process).
-
- The library loading path is a set of directories, where requested
- libraries and modules are searched for.
-*/
-
-typedef struct _LttvModule LttvModule;
-
-typedef struct _LttvLibrary LttvLibrary;
-
-typedef void (*LttvModuleInit)();
-
-typedef void (*LttvModuleDestroy)();
-
-typedef struct _LttvModuleInfo
-{
- char *name;
- char *short_description;
- char *description;
- LttvModuleInit init;
- LttvModuleDestroy destroy;
- LttvLibrary *library;
- unsigned require_count;
- unsigned use_count;
- unsigned prerequisites_number;
-} LttvModuleInfo;
-
-
-typedef struct _LttvLibraryInfo
-{
- char *name;
- char *path;
- unsigned load_count;
-} LttvLibraryInfo;
-
-
-typedef enum _LttvModuleError
-{
- LTTV_MODULE_NOT_FOUND,
- LTTV_MODULE_NO_INIT
-} LttvModuleError;
-
-
-/* Insure that a module is loaded and initialized. Require count
- (number of times the module was required) and use count
- (number of times required or used as prerequisite) serve to
- insure that a module is destroyed only after it has been released
- as many times as it was required (and prerequired).
-
- The module is searched among the modules currently loaded, then as a
- similarly named library to load which should contain the named module.
- If the module cannot be found or loaded, NULL is returned and an
- explanation is provided in error. */
-
-LttvModule *lttv_module_require(char *name, GError **error);
-
-void lttv_module_release(LttvModule *m);
-
-
-/* Obtain information about the module, including the containing library */
-
-void lttv_module_info(LttvModule *m, LttvModuleInfo *info);
-
-
-/* List the modules on which this module depends */
-
-unsigned lttv_module_prerequisite_number(LttvModule *m);
-
-LttvModule *lttv_module_prerequisite_get(LttvModule *m, unsigned i);
-
-
-/* Insure that a library is loaded. A load count insures that a library
- is unloaded only after it has been asked to unload as
- many times as it was loaded, and its modules are not in use. The library
- is searched along the library path if name is a relative pathname.
- If the library cannot be found or loaded, NULL is returned and an
- explanation is provided in error. */
-
-LttvLibrary *lttv_library_load(char *name, GError **error);
-
-void lttv_library_unload(LttvLibrary *l);
-
-
-/* Obtain information about the library */
-
-void lttv_library_info(LttvLibrary *l, LttvLibraryInfo *info);
-
-
-/* List the modules contained in a library */
-
-unsigned lttv_library_module_number(LttvLibrary *l);
-
-LttvModule *lttv_library_module_get(LttvLibrary *l, unsigned i);
-
-
-/* List the currently loaded libraries */
-
-unsigned lttv_library_number();
-
-LttvLibrary *lttv_library_get(unsigned i);
-
-
-
-/* Add or remove directory names to the library search path */
-
-void lttv_library_path_add(char *name);
-
-void lttv_library_path_remove(char *name);
-
-
-/* List the directory names in the library search path */
-
-unsigned lttv_library_path_number();
-
-char *lttv_library_path_get(unsigned i);
-
-
-/* To define a module, simply call the LTTV_MODULE macro with the needed
- arguments: single word name, one line short description, larger
- description, initialization function, destruction function, and
- list of names for required modules (e.g., "moduleA", "moduleB").
- This will insure that the module is registered at library load time.
-
- Example:
-
- LTTV_MODULE("option", "Command line options processing", "...", \
- init, destroy, "moduleA", "moduleB")
-*/
-
-#define LTTV_MODULE(name, short_desc, desc, init, destroy, ...) \
- \
- static void _LTTV_MODULE_REGISTER(__LINE__)() \
- __attribute__((constructor)); \
- \
- static void _LTTV_MODULE_REGISTER(__LINE__)() \
- { \
- static char *module_prerequisites[] = { __VA_ARGS__ }; \
- \
- static struct _LttvModuleDescription module = { \
- name, short_desc, desc, init, destroy, \
- sizeof(module_prerequisites) / sizeof(char *), \
- module_prerequisites, NULL}; \
- \
- lttv_module_register(&module); \
- }
-
-
-/* Internal structure and function used to register modules, called by
- LTTV_MODULE */
-
-#define __LTTV_MODULE_REGISTER(line) _lttv_module_register_ ## line
-#define _LTTV_MODULE_REGISTER(line) __LTTV_MODULE_REGISTER(line)
-
-struct _LttvModuleDescription
-{
- char *name;
- char *short_description;
- char *description;
- LttvModuleInit init;
- LttvModuleDestroy destroy;
- unsigned prerequisites_number;
- char **prerequisites;
- struct _LttvModuleDescription *next;
-};
-
-void lttv_module_register(struct _LttvModuleDescription *d);
-
-#endif // MODULES_H
-
-
-
-
-
-
+++ /dev/null
-/* This file is part of the Linux Trace Toolkit viewer
- * Copyright (C) 2003-2004 Michel Dagenais
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License Version 2 as
- * published by the Free Software Foundation;
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA.
- */
-
-#ifndef OPTION_H
-#define OPTION_H
-
-/* Define a new option with a long name (--long_name), a short
- one character name (-c), a descriptive text, the argument type, and a
- pointer to where the argument value will be stored. For an option of
- type LTTV_OPT_NONE, the argument is a boolean value set to true when the
- option is present. The option hook is called if non NULL. */
-
-typedef enum _LttvOptionType
-{LTTV_OPT_NONE, LTTV_OPT_STRING, LTTV_OPT_INT, LTTV_OPT_LONG }
-LttvOptionType;
-
-typedef void (*LttvOptionHook)(void *hook_data);
-
-void lttv_option_add(const char *long_name, const char char_name,
- const char *description, const char *arg_description,
- const LttvOptionType t, void *p,
- const LttvOptionHook h, void *hook_data);
-
-
-/* Remove an option */
-
-void lttv_option_remove(const char *long_name);
-
-
-/* Parse command line options. It is possible to add options (through the
- hooks being called) while the parsing is done. The new options will be
- used for subsequent command line arguments. */
-
-void lttv_option_parse(int argc, char **argv);
-
-void lttv_option_show_help(void);
-
-#endif // OPTION_H
+++ /dev/null
-/* This file is part of the Linux Trace Toolkit viewer
- * Copyright (C) 2003-2004 Michel Dagenais
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License Version 2 as
- * published by the Free Software Foundation;
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA.
- */
-
-#ifndef PROCESSTRACE_H
-#define PROCESSTRACE_H
-
-#include <lttv/traceset.h>
-#include <lttv/attribute.h>
-#include <lttv/hook.h>
-#include <ltt/ltt.h>
-
-/* This is the generic part of trace processing. All events within a
- certain time interval are accessed and processing hooks are called for
- each. The events are examined in monotonically increasing time to more
- closely follow the traced system behavior.
-
- Hooks are called at several different places during the processing:
- before traceset, after traceset, check trace, before trace, after trace,
- check tracefile, before tracefile, after tracefile,
- check_event, before_event, before_event_by_id,
- after_event, after_event_by_id.
-
- In each case the "check" hooks are called first to determine if further
- processing of the trace, tracefile or event is wanted. Then, the before
- hooks and the after hooks are called. The before hooks for a traceset
- are called before those for the contained traces, which are called before
- those for the contained tracefiles. The after hooks are called in reverse
- order. The event hooks are called after all the before_tracefile hooks
- and before all the after_tracefile hooks.
-
- The hooks receive two arguments, the hook_data and call_data. The hook_data
- is specified when the hook is registered and typically links to the
- object registering the hook (e.g. a graphical events viewer). The call_data
- must contain all the context related to the call. The traceset hooks receive
- the LttvTracesetContext provided by the caller. The trace hooks receive
- the LttvTraceContext from the traces array in the LttvTracesetContext.
- The tracefile and event hooks receive the LttvTracefileContext from
- the tracefiles array in the LttvTraceContext. The LttEvent and LttTime
- fields in the tracefile context are set to the current event and current
- event time before calling the event hooks. No other context field is
- modified.
-
- The contexts in the traces and tracefiles arrays must be allocated by
- the caller, either before the call or during the before hooks of the
- enclosing traceset or trace. The order in the traces array must
- correspond to the lttv_traceset_get function. The order in the tracefiles
- arrays must correspond to the ltt_trace_control_tracefile_get and
- ltt_trace_per_cpu_tracefile_get functions. The traceset, trace and
- tracefile contexts may be subtyped as needed. Indeed, both the contexts
- and the hooks are defined by the caller. */
-
-
-typedef struct _LttvTracesetContext LttvTracesetContext;
-typedef struct _LttvTracesetContextClass LttvTracesetContextClass;
-
-typedef struct _LttvTraceContext LttvTraceContext;
-typedef struct _LttvTraceContextClass LttvTraceContextClass;
-
-typedef struct _LttvTracefileContext LttvTracefileContext;
-typedef struct _LttvTracefileContextClass LttvTracefileContextClass;
-
-#define LTTV_TRACESET_CONTEXT_TYPE (lttv_traceset_context_get_type ())
-#define LTTV_TRACESET_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LTTV_TRACESET_CONTEXT_TYPE, LttvTracesetContext))
-#define LTTV_TRACESET_CONTEXT_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST ((vtable), LTTV_TRACESET_CONTEXT_TYPE, LttvTracesetContextClass))
-#define LTTV_IS_TRACESET_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LTTV_TRACESET_CONTEXT_TYPE))
-#define LTTV_IS_TRACESET_CONTEXT_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), LTTV_TRACESET_CONTEXT_TYPE))
-#define LTTV_TRACESET_CONTEXT_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), LTTV_TRACESET_CONTEXT_TYPE, LttvTracesetContextClass))
-
-struct _LttvTracesetContext {
- GObject parent;
-
- LttvTraceset *ts;
- LttvHooks *before;
- LttvHooks *after;
- LttvTraceContext **traces;
- LttvAttribute *a;
- LttvAttribute *ts_a;
- TimeInterval *Time_Span;
- GTree *pqueue;
-};
-
-struct _LttvTracesetContextClass {
- GObjectClass parent;
-
- void (*init) (LttvTracesetContext *self, LttvTraceset *ts);
- void (*fini) (LttvTracesetContext *self);
- LttvTracesetContext* (*new_traceset_context) (LttvTracesetContext *self);
- LttvTraceContext* (*new_trace_context) (LttvTracesetContext *self);
- LttvTracefileContext* (*new_tracefile_context) (LttvTracesetContext *self);
-};
-
-GType lttv_traceset_context_get_type (void);
-
-void lttv_context_init(LttvTracesetContext *self, LttvTraceset *ts);
-
-void lttv_context_fini(LttvTracesetContext *self);
-
-LttvTracesetContext *
-lttv_context_new_traceset_context(LttvTracesetContext *self);
-
-LttvTraceContext *
-lttv_context_new_trace_context(LttvTracesetContext *self);
-
-LttvTracefileContext *
-lttv_context_new_tracefile_context(LttvTracesetContext *self);
-
-
-#define LTTV_TRACE_CONTEXT_TYPE (lttv_trace_context_get_type ())
-#define LTTV_TRACE_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LTTV_TRACE_CONTEXT_TYPE, LttvTraceContext))
-#define LTTV_TRACE_CONTEXT_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST ((vtable), LTTV_TRACE_CONTEXT_TYPE, LttvTraceContextClass))
-#define LTTV_IS_TRACE_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LTTV_TRACE_CONTEXT_TYPE))
-#define LTTV_IS_TRACE_CONTEXT_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), LTTV_TRACE_CONTEXT_TYPE))
-#define LTTV_TRACE_CONTEXT_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), LTTV_TRACE_CONTEXT_TYPE, LttvTraceContextClass))
-
-struct _LttvTraceContext {
- GObject parent;
-
- LttvTracesetContext *ts_context;
- guint index; /* in ts_context->traces */
- LttTrace *t;
- LttvTrace *vt;
- LttvHooks *check;
- LttvHooks *before;
- LttvHooks *after;
- LttvTracefileContext **tracefiles;
- LttvAttribute *a;
- LttvAttribute *t_a;
-};
-
-struct _LttvTraceContextClass {
- GObjectClass parent;
-};
-
-GType lttv_trace_context_get_type (void);
-
-#define LTTV_TRACEFILE_CONTEXT_TYPE (lttv_tracefile_context_get_type ())
-#define LTTV_TRACEFILE_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LTTV_TRACEFILE_CONTEXT_TYPE, LttvTracefileContext))
-#define LTTV_TRACEFILE_CONTEXT_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST ((vtable), LTTV_TRACEFILE_CONTEXT_TYPE, LttvTracefileContextClass))
-#define LTTV_IS_TRACEFILE_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LTTV_TRACEFILE_CONTEXT_TYPE))
-#define LTTV_IS_TRACEFILE_CONTEXT_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), LTTV_TRACEFILE_CONTEXT_TYPE))
-#define LTTV_TRACEFILE_CONTEXT_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), LTTV_TRACEFILE_CONTEXT_TYPE, LttvTracefileContextClass))
-
-struct _LttvTracefileContext {
- GObject parent;
-
- LttvTraceContext *t_context;
- gboolean control;
- guint index; /* in ts_context->tracefiles */
- LttTracefile *tf;
- LttvHooks *check;
- LttvHooks *before;
- LttvHooks *after;
- LttEvent *e;
- LttvHooks *check_event;
- LttvHooks *before_event;
- LttvHooksById *before_event_by_id;
- LttvHooks *after_event;
- LttvHooksById *after_event_by_id;
- LttTime timestamp;
- LttvAttribute *a;
-};
-
-struct _LttvTracefileContextClass {
- GObjectClass parent;
-};
-
-GType lttv_tracefile_context_get_type (void);
-
-/* Run through the events in a traceset in sorted order calling all the
- hooks appropriately. It starts at the current time and runs until end or
- nb_events are processed. */
-
-void lttv_process_traceset(LttvTracesetContext *self, LttTime end,
- unsigned nb_events);
-
-/* Process traceset can also be done in smaller pieces calling begin, middle
- repeatedly, and end. The middle function return the number of events
- processed. It may be larger than nb_events if several events have the
- same timestamp. It will be smaller than nb_events if the end time
- is reached. */
-
-void lttv_process_traceset_begin(LttvTracesetContext *self, LttTime end);
-
-guint lttv_process_traceset_middle(LttvTracesetContext *self, LttTime end,
- unsigned nb_events);
-
-void lttv_process_traceset_end(LttvTracesetContext *self);
-
-
-void lttv_process_traceset_seek_time(LttvTracesetContext *self, LttTime start);
-
-void lttv_process_trace_seek_time(LttvTraceContext *self, LttTime start);
-
-void lttv_traceset_context_add_hooks(LttvTracesetContext *self,
- LttvHooks *before_traceset,
- LttvHooks *after_traceset,
- LttvHooks *check_trace,
- LttvHooks *before_trace,
- LttvHooks *after_trace,
- LttvHooks *check_tracefile,
- LttvHooks *before_tracefile,
- LttvHooks *after_tracefile,
- LttvHooks *check_event,
- LttvHooks *before_event,
- LttvHooks *after_event);
-
-void lttv_traceset_context_remove_hooks(LttvTracesetContext *self,
- LttvHooks *before_traceset,
- LttvHooks *after_traceset,
- LttvHooks *check_trace,
- LttvHooks *before_trace,
- LttvHooks *after_trace,
- LttvHooks *check_tracefile,
- LttvHooks *before_tracefile,
- LttvHooks *after_tracefile,
- LttvHooks *check_event,
- LttvHooks *before_event,
- LttvHooks *after_event);
-
-void lttv_trace_context_add_hooks(LttvTraceContext *self,
- LttvHooks *check_trace,
- LttvHooks *before_trace,
- LttvHooks *after_trace);
-
-void lttv_trace_context_remove_hooks(LttvTraceContext *self,
- LttvHooks *check_trace,
- LttvHooks *before_trace,
- LttvHooks *after_trace);
-
-void lttv_tracefile_context_add_hooks(LttvTracefileContext *self,
- LttvHooks *check_tracefile,
- LttvHooks *before_tracefile,
- LttvHooks *after_tracefile,
- LttvHooks *check_event,
- LttvHooks *before_event,
- LttvHooks *after_event);
-
-void lttv_tracefile_context_remove_hooks(LttvTracefileContext *self,
- LttvHooks *check_tracefile,
- LttvHooks *before_tracefile,
- LttvHooks *after_tracefile,
- LttvHooks *check_event,
- LttvHooks *before_event,
- LttvHooks *after_event);
-
-void lttv_tracefile_context_add_hooks_by_id(LttvTracefileContext *self,
- unsigned i,
- LttvHooks *before_event_by_id,
- LttvHooks *after_event_by_id);
-
-void lttv_tracefile_context_remove_hooks_by_id(LttvTracefileContext *self,
- unsigned i);
-
-typedef struct _LttvTraceHook {
- LttvHook h;
- guint id;
- LttField *f1;
- LttField *f2;
- LttField *f3;
-} LttvTraceHook;
-
-
-/* Search in the trace for the id of the named event type within the named
- facility. Then, find the three (if non null) named fields. All that
- information is then used to fill the LttvTraceHook structure. This
- is useful to find the specific id for an event within a trace, for
- registering a hook using this structure as event data;
- it already contains the (up to three) needed fields handles. */
-
-void lttv_trace_find_hook(LttTrace *t, char *facility, char *event_type,
- char *field1, char *field2, char *field3, LttvHook h, LttvTraceHook *th);
-
-#endif // PROCESSTRACE_H
+++ /dev/null
-/* This file is part of the Linux Trace Toolkit viewer
- * Copyright (C) 2003-2004 Michel Dagenais
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License Version 2 as
- * published by the Free Software Foundation;
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA.
- */
-
-#ifndef STATE_H
-#define STATE_H
-
-#include <glib.h>
-#include <lttv/processTrace.h>
-#include <stdio.h>
-
-/* The operating system state, kept during the trace analysis,
- contains a subset of the real operating system state,
- sufficient for the analysis, and possibly organized quite differently.
-
- The state information is added to LttvTracesetContext, LttvTraceContext
- and LttvTracefileContext objects, used by processTrace, through
- subtyping. The context objects already reflect the multiple tracefiles
- (one per cpu) per trace and multiple traces per trace set. The state
- objects defined here simply add fields to the relevant context objects.
-
- There is no traceset specific state yet. It may eventually contains such
- things as clock differences over time.
-
- The trace state currently consists in a process table.
-
- The tracefile level state relates to the associated cpu. It contains the
- position of the current event in the tracefile (since the state depends on
- which events have been processed) and a pointer to the current process,
- in the process table, being run on that cpu.
-
- For each process in the process table, various informations such as exec
- file name, pid, ppid and creation time are stored. Each process state also
- contains an execution mode stack (e.g. irq within system call, called
- from user mode). */
-
-typedef struct _LttvTracesetState LttvTracesetState;
-typedef struct _LttvTracesetStateClass LttvTracesetStateClass;
-
-typedef struct _LttvTraceState LttvTraceState;
-typedef struct _LttvTraceStateClass LttvTraceStateClass;
-
-typedef struct _LttvTracefileState LttvTracefileState;
-typedef struct _LttvTracefileStateClass LttvTracefileStateClass;
-
-void lttv_state_add_event_hooks(LttvTracesetState *self);
-
-void lttv_state_remove_event_hooks(LttvTracesetState *self);
-
-void lttv_state_save_add_event_hooks(LttvTracesetState *self);
-
-void lttv_state_save_remove_event_hooks(LttvTracesetState *self);
-
-void lttv_state_traceset_seek_time_closest(LttvTracesetState *self, LttTime t);
-
-/* The LttvProcessState structure defines the current state for each process.
- A process can make system calls (in some rare cases nested) and receive
- interrupts/faults. For instance, a process may issue a system call,
- generate a page fault while reading an argument from user space, and
- get caught by an interrupt. To represent these nested states, an
- execution mode stack is maintained. The stack bottom is normal user mode
- and the top of stack is the current execution mode.
-
- The execution mode stack tells about the process status, execution mode and
- submode (interrupt, system call or IRQ number). All these could be
- defined as enumerations but may need extensions (e.g. new process state).
- GQuark are thus used. They are as easy to manipulate as integers but have
- a string associated, just like enumerations.
-
- The execution mode is one of "user mode", "kernel thread", "system call",
- "interrupt request", "fault". */
-
-typedef GQuark LttvExecutionMode;
-
-extern LttvExecutionMode
- LTTV_STATE_USER_MODE,
- LTTV_STATE_SYSCALL,
- LTTV_STATE_TRAP,
- LTTV_STATE_IRQ,
- LTTV_STATE_MODE_UNKNOWN;
-
-
-/* The submode number depends on the execution mode. For user mode or kernel
- thread, which are the normal mode (execution mode stack bottom),
- it is set to "none". For interrupt requests, faults and system calls,
- it is set respectively to the interrupt name (e.g. "timer"), fault name
- (e.g. "page fault"), and system call name (e.g. "select"). */
-
-typedef GQuark LttvExecutionSubmode;
-
-extern LttvExecutionSubmode
- LTTV_STATE_SUBMODE_NONE,
- LTTV_STATE_SUBMODE_UNKNOWN;
-
-/* The process status is one of "running", "wait-cpu" (runnable), or "wait-*"
- where "*" describes the resource waited for (e.g. timer, process,
- disk...). */
-
-typedef GQuark LttvProcessStatus;
-
-extern LttvProcessStatus
- LTTV_STATE_UNNAMED,
- LTTV_STATE_WAIT_FORK,
- LTTV_STATE_WAIT_CPU,
- LTTV_STATE_EXIT,
- LTTV_STATE_WAIT,
- LTTV_STATE_RUN;
-
-
-typedef struct _LttvExecutionState {
- LttvExecutionMode t;
- LttvExecutionSubmode n;
- LttTime entry;
- LttTime change;
- LttvProcessStatus s;
-} LttvExecutionState;
-
-
-typedef struct _LttvProcessState {
- guint pid;
- guint ppid;
- LttTime creation_time;
- LttTime insertion_time;
- GQuark name;
- GQuark pid_time;
- GArray *execution_stack; /* Array of LttvExecutionState */
- LttvExecutionState *state; /* Top of interrupt stack */
- GQuark last_cpu; /* Last CPU where process was scheduled */
- /* opened file descriptors, address map?... */
-} LttvProcessState;
-
-
-LttvProcessState *
-lttv_state_find_process(LttvTracefileState *tfs, guint pid);
-
-LttvProcessState *
-lttv_state_find_process_from_trace(LttvTraceState *ts, GQuark cpu, guint pid);
-
-LttvProcessState *
-lttv_state_find_process_or_create(LttvTracefileState *tfs, guint pid);
-
-LttvProcessState *
-lttv_state_create_process(LttvTracefileState *tfs, LttvProcessState *parent,
- guint pid);
-
-void lttv_state_write(LttvTraceState *self, LttTime t, FILE *fp);
-
-/* The LttvTracesetState, LttvTraceState and LttvTracefileState types
- inherit from the corresponding Context objects defined in processTrace. */
-
-#define LTTV_TRACESET_STATE_TYPE (lttv_traceset_state_get_type ())
-#define LTTV_TRACESET_STATE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LTTV_TRACESET_STATE_TYPE, LttvTracesetState))
-#define LTTV_TRACESET_STATE_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST ((vtable), LTTV_TRACESET_STATE_TYPE, LttvTracesetStateClass))
-#define LTTV_IS_TRACESET_STATE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LTTV_TRACESET_STATE_TYPE))
-#define LTTV_IS_TRACESET_STATE_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), LTTV_TRACESET_STATE_TYPE))
-#define LTTV_TRACESET_STATE_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), LTTV_TRACESET_STATE_TYPE, LttvTracesetStateClass))
-
-struct _LttvTracesetState {
- LttvTracesetContext parent;
-};
-
-struct _LttvTracesetStateClass {
- LttvTracesetContextClass parent;
-};
-
-GType lttv_traceset_state_get_type (void);
-
-
-#define LTTV_TRACE_STATE_TYPE (lttv_trace_state_get_type ())
-#define LTTV_TRACE_STATE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LTTV_TRACE_STATE_TYPE, LttvTraceState))
-#define LTTV_TRACE_STATE_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST ((vtable), LTTV_TRACE_STATE_TYPE, LttvTraceStateClass))
-#define LTTV_IS_TRACE_STATE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LTTV_TRACE_STATE_TYPE))
-#define LTTV_IS_TRACE_STATE_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), LTTV_TRACE_STATE_TYPE))
-#define LTTV_TRACE_STATE_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), LTTV_TRACE_STATE_TYPE, LttvTraceStateClass))
-
-struct _LttvTraceState {
- LttvTraceContext parent;
-
- GHashTable *processes; /* LttvProcessState objects indexed by pid */
- guint nb_event, save_interval;
- /* Block/char devices, locks, memory pages... */
- GQuark *eventtype_names;
- GQuark *syscall_names;
- GQuark *trap_names;
- GQuark *irq_names;
- LttTime *max_time_state_recomputed_in_seek;
-};
-
-struct _LttvTraceStateClass {
- LttvTraceContextClass parent;
-
- void (*state_save) (LttvTraceState *self, LttvAttribute *container);
- void (*state_restore) (LttvTraceState *self, LttvAttribute *container);
- void (*state_saved_free) (LttvTraceState *self, LttvAttribute *container);
-};
-
-GType lttv_trace_state_get_type (void);
-
-void lttv_state_save(LttvTraceState *self, LttvAttribute *container);
-
-void lttv_state_restore(LttvTraceState *self, LttvAttribute *container);
-
-void lttv_state_state_saved_free(LttvTraceState *self,
- LttvAttribute *container);
-
-
-#define LTTV_TRACEFILE_STATE_TYPE (lttv_tracefile_state_get_type ())
-#define LTTV_TRACEFILE_STATE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LTTV_TRACEFILE_STATE_TYPE, LttvTracefileState))
-#define LTTV_TRACEFILE_STATE_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST ((vtable), LTTV_TRACEFILE_STATE_TYPE, LttvTracefileStateClass))
-#define LTTV_IS_TRACEFILE_STATE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LTTV_TRACEFILE_STATE_TYPE))
-#define LTTV_IS_TRACEFILE_STATE_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), LTTV_TRACEFILE_STATE_TYPE))
-#define LTTV_TRACEFILE_STATE_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), LTTV_TRACEFILE_STATE_TYPE, LttvTracefileStateClass))
-
-struct _LttvTracefileState {
- LttvTracefileContext parent;
-
- LttvProcessState *process;
- GQuark cpu_name;
- guint saved_position;
-};
-
-struct _LttvTracefileStateClass {
- LttvTracefileContextClass parent;
-};
-
-GType lttv_tracefile_state_get_type (void);
-
-
-#endif // STATE_H
+++ /dev/null
-/* This file is part of the Linux Trace Toolkit viewer
- * Copyright (C) 2003-2004 Michel Dagenais
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License Version 2 as
- * published by the Free Software Foundation;
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA.
- */
-
-#ifndef STATS_H
-#define STATS_H
-
-#include <glib.h>
-#include <lttv/state.h>
-
-/* The statistics are for a complete time interval. These structures differ
- from the system state since they relate to static components of the
- system (all processes which existed instead of just the currently
- existing processes).
-
- The basic attributes tree to gather for several different execution modes
- (e.g., user mode, syscall, irq), thereafter called the "events tree",
- contains the following attributes: the number of events of each type,
- the total number of events, the number of bytes written, the time spent
- executing, waiting for a resource, waiting for a cpu, and possibly many
- others. The name "facility-event_type" below is to be replaced
- by specific event types (e.g., core-schedchange, code-syscall_entry...).
-
- event_types/
- "facility-event_type"
- events_count
- cpu_time
- elapsed_time
- wait_time
- bytes_written
- packets_sent
- ...
-
- The events for several different execution modes are joined together to
- form the "execution modes tree". The name "execution mode" is to be replaced
- by "system call", "trap", "irq", "user mode" or "kernel thread".
- The name "submode" is to be replaced by the specific system call, trap or
- irq name. The "submode" is an empty string if none is applicable, which is
- the case for "user mode" and "kernel thread".
-
- An "events tree" for each "execution mode" contains the sum for all its
- different submodes. An "events tree" in the "execution modes tree" contains
- the sum for all its different execution modes.
-
- mode_types/
- "execution mode"/
- submodes/
- "submode"/
- Events Tree
- events/
- Event Tree
- events/
- Events Tree
-
- Each trace set contains an "execution modes tree". While the traces
- come from possibly different systems, which may differ in their system
- calls..., most of the system calls will have the same name, even if their
- actual internal numeric id differs. Categories such as cpu id and process
- id are not kept since these are specific to each system. When several
- traces are taken from the same system, these categories may make sense and
- could eventually be considered.
-
- Each trace contains a global "execution modes tree", one for each
- cpu and process, and one for each process/cpu combination. The name
- "cpu number" stands for the cpu identifier, and "process_id-start_time"
- is a unique process identifier composed of the process id
- (unique at any given time but which may be reused over time) concatenated
- with the process start time.
-
- modes/
- Execution Modes Tree
- cpu/
- "cpu number"/
- Execution Modes Tree
- processes/
- "process_id-start_time"/
- exec_file_name
- parent
- start_time
- end_time
- modes/
- Execution Modes Tree
- cpu/
- "cpu number"/
- Execution Modes Tree
-
- All the events and derived values (cpu, elapsed and wait time) are
- added during the trace analysis in the relevant
- trace / processes / * / cpu / * / mode_types / * /submodes / *
- "events tree". To achieve this efficiently, each tracefile context
- contains a pointer to the current relevant "events tree" and "event_types"
- tree within it.
-
- Once all the events are processed, the total number of events is computed
- within each trace / processes / * / cpu / * / mode_types / * / submodes / *.
- Then, the "events tree" are summed for all submodes within each mode type
- and for all mode types within a processes / * / cpu / *
- "execution modes tree".
-
- Finally, the "execution modes trees" for all cpu within a process,
- for all processes, and for all traces are computed. Separately,
- the "execution modes tree" for each cpu but for all processes within a
- trace are summed in the trace / cpu / * subtrees.
-
- */
-
-
-/* The various statistics branch names are GQuarks. They are pre-computed for
- easy and efficient access */
-
-extern GQuark
- LTTV_STATS_PROCESS_UNKNOWN,
- LTTV_STATS_PROCESSES,
- LTTV_STATS_CPU,
- LTTV_STATS_MODE_TYPES,
- LTTV_STATS_SUBMODES,
- LTTV_STATS_EVENT_TYPES,
- LTTV_STATS_CPU_TIME,
- LTTV_STATS_ELAPSED_TIME,
- LTTV_STATS_EVENTS,
- LTTV_STATS_EVENTS_COUNT,
- LTTV_STATS_BEFORE_HOOKS,
- LTTV_STATS_AFTER_HOOKS;
-
-
-typedef struct _LttvTracesetStats LttvTracesetStats;
-typedef struct _LttvTracesetStatsClass LttvTracesetStatsClass;
-
-typedef struct _LttvTraceStats LttvTraceStats;
-typedef struct _LttvTraceStatsClass LttvTraceStatsClass;
-
-typedef struct _LttvTracefileStats LttvTracefileStats;
-typedef struct _LttvTracefileStatsClass LttvTracefileStatsClass;
-
-gboolean lttv_stats_add_event_hooks(LttvTracesetStats *self);
-
-gboolean lttv_stats_remove_event_hooks(LttvTracesetStats *self);
-
-void lttv_stats_sum_traceset(LttvTracesetStats *self);
-
-void lttv_stats_sum_trace(LttvTraceStats *self);
-
-
-/* The LttvTracesetStats, LttvTraceStats and LttvTracefileStats types
- inherit from the corresponding State objects defined in state.h.. */
-
-#define LTTV_TRACESET_STATS_TYPE (lttv_traceset_stats_get_type ())
-#define LTTV_TRACESET_STATS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LTTV_TRACESET_STATS_TYPE, LttvTracesetStats))
-#define LTTV_TRACESET_STATS_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST ((vtable), LTTV_TRACESET_STATS_TYPE, LttvTracesetStatsClass))
-#define LTTV_IS_TRACESET_STATS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LTTV_TRACESET_STATS_TYPE))
-#define LTTV_IS_TRACESET_STATS_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), LTTV_TRACESET_STATS_TYPE))
-#define LTTV_TRACESET_STATS_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), LTTV_TRACESET_STATS_TYPE, LttvTracesetStatsClass))
-
-struct _LttvTracesetStats {
- LttvTracesetState parent;
-
- LttvAttribute *stats;
-};
-
-struct _LttvTracesetStatsClass {
- LttvTracesetStateClass parent;
-};
-
-GType lttv_traceset_stats_get_type (void);
-
-
-#define LTTV_TRACE_STATS_TYPE (lttv_trace_stats_get_type ())
-#define LTTV_TRACE_STATS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LTTV_TRACE_STATS_TYPE, LttvTraceStats))
-#define LTTV_TRACE_STATS_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST ((vtable), LTTV_TRACE_STATS_TYPE, LttvTraceStatsClass))
-#define LTTV_IS_TRACE_STATS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LTTV_TRACE_STATS_TYPE))
-#define LTTV_IS_TRACE_STATS_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), LTTV_TRACE_STATS_TYPE))
-#define LTTV_TRACE_STATS_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), LTTV_TRACE_STATS_TYPE, LttvTraceStatsClass))
-
-struct _LttvTraceStats {
- LttvTraceState parent;
-
- LttvAttribute *stats;
-};
-
-struct _LttvTraceStatsClass {
- LttvTraceStateClass parent;
-};
-
-GType lttv_trace_stats_get_type (void);
-
-
-#define LTTV_TRACEFILE_STATS_TYPE (lttv_tracefile_stats_get_type ())
-#define LTTV_TRACEFILE_STATS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LTTV_TRACEFILE_STATS_TYPE, LttvTracefileStats))
-#define LTTV_TRACEFILE_STATS_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST ((vtable), LTTV_TRACEFILE_STATS_TYPE, LttvTracefileStatsClass))
-#define LTTV_IS_TRACEFILE_STATS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LTTV_TRACEFILE_STATS_TYPE))
-#define LTTV_IS_TRACEFILE_STATS_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), LTTV_TRACEFILE_STATS_TYPE))
-#define LTTV_TRACEFILE_STATS_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), LTTV_TRACEFILE_STATS_TYPE, LttvTracefileStatsClass))
-
-struct _LttvTracefileStats {
- LttvTracefileState parent;
-
- LttvAttribute *stats;
- LttvAttribute *current_events_tree;
- LttvAttribute *current_event_types_tree;
-};
-
-struct _LttvTracefileStatsClass {
- LttvTracefileStateClass parent;
-};
-
-GType lttv_tracefile_stats_get_type (void);
-
-
-#endif // STATS_H
+++ /dev/null
-/* This file is part of the Linux Trace Toolkit viewer
- * Copyright (C) 2003-2004 Xiangxiu Yang
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License Version 2 as
- * published by the Free Software Foundation;
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA.
- */
-
-#ifndef TOOLBAR_H
-#define TOOLBAR_H
-
-#include <lttv/common.h>
-
-/* constructor of the viewer */
-//typedef GtkWidget* (*lttv_constructor)(void * main_window);
-
-
-typedef GArray LttvToolbars;
-
-typedef struct _lttv_toolbar_closure {
- lttv_constructor con;
- char * tooltip;
- char ** pixmap;
-} lttv_toolbar_closure;
-
-LttvToolbars *lttv_toolbars_new();
-
-void lttv_toolbars_destroy(LttvToolbars *h);
-
-void lttv_toolbars_add(LttvToolbars *h, lttv_constructor f, char* tooltip, char ** pixmap);
-
-gboolean lttv_toolbars_remove(LttvToolbars *h, lttv_constructor f);
-
-unsigned lttv_toolbars_number(LttvToolbars *h);
-
-#endif // TOOLBAR_H
+++ /dev/null
-/* This file is part of the Linux Trace Toolkit viewer
- * Copyright (C) 2003-2004 Michel Dagenais
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License Version 2 as
- * published by the Free Software Foundation;
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA.
- */
-
-#ifndef TRACESET_H
-#define TRACESET_H
-
-#include <lttv/attribute.h>
-#include <lttv/hook.h>
-#include <ltt/ltt.h>
-
-/* A traceset is a set of traces to be analyzed together. */
-
-typedef struct _LttvTraceset LttvTraceset;
-
-typedef struct _LttvTrace LttvTrace;
-
-/* Tracesets may be added to, removed from and their content listed. */
-
-LttvTraceset *lttv_traceset_new();
-
-char * lttv_traceset_name(LttvTraceset * s);
-
-LttvTrace *lttv_trace_new(LttTrace *t);
-
-LttvTraceset *lttv_traceset_copy(LttvTraceset *s_orig);
-
-LttvTraceset *lttv_traceset_load(const gchar *filename);
-
-gint lttv_traceset_save(LttvTraceset *s);
-
-void lttv_traceset_destroy(LttvTraceset *s);
-
-void lttv_trace_destroy(LttvTrace *t);
-
-void lttv_traceset_add(LttvTraceset *s, LttvTrace *t);
-
-unsigned lttv_traceset_number(LttvTraceset *s);
-
-LttvTrace *lttv_traceset_get(LttvTraceset *s, unsigned i);
-
-void lttv_traceset_remove(LttvTraceset *s, unsigned i);
-
-/* An attributes table is attached to the set and to each trace in the set. */
-
-LttvAttribute *lttv_traceset_attribute(LttvTraceset *s);
-
-LttvAttribute *lttv_trace_attribute(LttvTrace *t);
-
-LttTrace *lttv_trace(LttvTrace *t);
-
-guint lttv_trace_get_ref_number(LttvTrace * t);
-
-#endif // TRACESET_H
-
--- /dev/null
+AM_CFLAGS = $(GLIB_CFLAGS)
+LIBS += $(GLIB_LIBS) -lgobject-2.0 -L$(top_srcdir)/ltt -ltraceread
+
+bin_PROGRAMS = lttv
+
+INCLUDES = \
+ -DPACKAGE_PLUGIN_DIR=\""$(lttvplugindir)"\" \
+ @PACKAGE_CFLAGS@ \
+ $(DEFAULT_INCLUDES)
+
+libdir = ${lttvplugindir}
+
+lttvinclude_HEADERS = \
+ attribute.h\
+ hook.h\
+ iattribute.h\
+ lttv.h\
+ module.h\
+ option.h\
+ state.h\
+ stats.h\
+ tracecontext.h\
+ traceset.h
+
+noinst_HEADERS = \
+ filter.h
+
+lttv_SOURCES = batchtest.c main.c module.c option.c \
+ hook.c attribute.c \
+ iattribute.c state.c stats.c \
+ processTrace.c traceset.c
+
--- /dev/null
+/* This file is part of the Linux Trace Toolkit viewer
+ * Copyright (C) 2003-2004 Michel Dagenais
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+#include <lttv/attribute.h>
+#include <ltt/ltt.h>
+
+typedef union _AttributeValue {
+ int dv_int;
+ unsigned dv_uint;
+ long dv_long;
+ unsigned long dv_ulong;
+ float dv_float;
+ double dv_double;
+ LttTime dv_time;
+ gpointer dv_pointer;
+ char *dv_string;
+ GObject *dv_gobject;
+} AttributeValue;
+
+
+typedef struct _Attribute {
+ LttvAttributeName name;
+ LttvAttributeType type;
+ AttributeValue value;
+} Attribute;
+
+
+LttvAttributeValue address_of_value(LttvAttributeType t, AttributeValue *v)
+{
+ LttvAttributeValue va;
+
+ switch(t) {
+ case LTTV_INT: va.v_int = &v->dv_int; break;
+ case LTTV_UINT: va.v_uint = &v->dv_uint; break;
+ case LTTV_LONG: va.v_long = &v->dv_long; break;
+ case LTTV_ULONG: va.v_ulong = &v->dv_ulong; break;
+ case LTTV_FLOAT: va.v_float = &v->dv_float; break;
+ case LTTV_DOUBLE: va.v_double = &v->dv_double; break;
+ case LTTV_TIME: va.v_time = &v->dv_time; break;
+ case LTTV_POINTER: va.v_pointer = &v->dv_pointer; break;
+ case LTTV_STRING: va.v_string = &v->dv_string; break;
+ case LTTV_GOBJECT: va.v_gobject = &v->dv_gobject; break;
+ }
+ return va;
+}
+
+
+AttributeValue init_value(LttvAttributeType t)
+{
+ AttributeValue v;
+
+ switch(t) {
+ case LTTV_INT: v.dv_int = 0; break;
+ case LTTV_UINT: v.dv_uint = 0; break;
+ case LTTV_LONG: v.dv_long = 0; break;
+ case LTTV_ULONG: v.dv_ulong = 0; break;
+ case LTTV_FLOAT: v.dv_float = 0; break;
+ case LTTV_DOUBLE: v.dv_double = 0; break;
+ case LTTV_TIME: v.dv_time.tv_sec = 0; v.dv_time.tv_nsec = 0; break;
+ case LTTV_POINTER: v.dv_pointer = NULL; break;
+ case LTTV_STRING: v.dv_string = NULL; break;
+ case LTTV_GOBJECT: v.dv_gobject = NULL; break;
+ }
+ return v;
+}
+
+
+unsigned int
+lttv_attribute_get_number(LttvAttribute *self)
+{
+ return self->attributes->len;
+}
+
+
+gboolean
+lttv_attribute_named(LttvAttribute *self, gboolean *homogeneous)
+{
+ *homogeneous = FALSE;
+ return TRUE;
+}
+
+
+LttvAttributeType
+lttv_attribute_get(LttvAttribute *self, unsigned i, LttvAttributeName *name,
+ LttvAttributeValue *v)
+{
+ Attribute *a;
+
+ a = &g_array_index(self->attributes, Attribute, i);
+ *name = a->name;
+ *v = address_of_value(a->type, &(a->value));
+ return a->type;
+}
+
+
+LttvAttributeType
+lttv_attribute_get_by_name(LttvAttribute *self, LttvAttributeName name,
+ LttvAttributeValue *v)
+{
+ Attribute *a;
+
+ unsigned i;
+
+ gpointer p;
+
+ p = g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
+ if(p == NULL) return LTTV_NONE;
+
+ i = GPOINTER_TO_UINT(p);
+ i--;
+ a = &g_array_index(self->attributes, Attribute, i);
+ *v = address_of_value(a->type, &(a->value));
+ return a->type;
+}
+
+
+LttvAttributeValue
+lttv_attribute_add(LttvAttribute *self, LttvAttributeName name,
+ LttvAttributeType t)
+{
+ unsigned i;
+
+ Attribute a, *pa;
+
+ i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
+ if(i != 0) g_error("duplicate entry in attribute table");
+
+ a.name = name;
+ a.type = t;
+ a.value = init_value(t);
+ g_array_append_val(self->attributes, a);
+ i = self->attributes->len - 1;
+ pa = &g_array_index(self->attributes, Attribute, i);
+ g_hash_table_insert(self->names, GUINT_TO_POINTER(name),
+ GUINT_TO_POINTER(i + 1));
+ return address_of_value(t, &(pa->value));
+}
+
+
+/* Remove an attribute */
+
+void
+lttv_attribute_remove(LttvAttribute *self, unsigned i)
+{
+ Attribute *a;
+
+ a = &g_array_index(self->attributes, Attribute, i);
+
+ /* Remove the array element and its entry in the name index */
+
+ g_hash_table_remove(self->names, GUINT_TO_POINTER(a->name));
+ g_array_remove_index_fast(self->attributes, i);
+
+ /* The element used to replace the removed element has its index entry
+ all wrong now. Reinsert it with its new position. */
+
+ if(self->attributes->len != i){
+ g_hash_table_remove(self->names, GUINT_TO_POINTER(a->name));
+ g_hash_table_insert(self->names, GUINT_TO_POINTER(a->name), GUINT_TO_POINTER(i + 1));
+ }
+}
+
+void
+lttv_attribute_remove_by_name(LttvAttribute *self, LttvAttributeName name)
+{
+ unsigned i;
+
+ i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
+ if(i == 0) g_error("remove by name non existent attribute");
+
+ lttv_attribute_remove(self, i - 1);
+}
+
+/* Create an empty iattribute object and add it as an attribute under the
+ specified name, or return an existing iattribute attribute. If an
+ attribute of that name already exists but is not a GObject supporting the
+ iattribute interface, return NULL. */
+
+/*CHECK*/LttvAttribute*
+lttv_attribute_find_subdir(LttvAttribute *self, LttvAttributeName name)
+{
+ unsigned i;
+
+ Attribute a;
+
+ LttvAttribute *new;
+
+ i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
+ if(i != 0) {
+ a = g_array_index(self->attributes, Attribute, i - 1);
+ if(a.type == LTTV_GOBJECT && LTTV_IS_IATTRIBUTE(a.value.dv_gobject)) {
+ return LTTV_ATTRIBUTE(a.value.dv_gobject);
+ }
+ else return NULL;
+ }
+ new = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
+ *(lttv_attribute_add(self, name, LTTV_GOBJECT).v_gobject) = G_OBJECT(new);
+ return (LttvAttribute *)new;
+}
+
+gboolean
+lttv_attribute_find(LttvAttribute *self, LttvAttributeName name,
+ LttvAttributeType t, LttvAttributeValue *v)
+{
+ unsigned i;
+
+ Attribute *a;
+
+ i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
+ if(i != 0) {
+ a = &g_array_index(self->attributes, Attribute, i - 1);
+ if(a->type != t) return FALSE;
+ *v = address_of_value(t, &(a->value));
+ return TRUE;
+ }
+
+ *v = lttv_attribute_add(self, name, t);
+ return TRUE;
+}
+
+
+void lttv_attribute_recursive_free(LttvAttribute *self)
+{
+ int i, nb;
+
+ Attribute *a;
+
+ nb = self->attributes->len;
+
+ for(i = 0 ; i < nb ; i++) {
+ a = &g_array_index(self->attributes, Attribute, i);
+ if(a->type == LTTV_GOBJECT && LTTV_IS_ATTRIBUTE(a->value.dv_gobject)) {
+ lttv_attribute_recursive_free((LttvAttribute *)(a->value.dv_gobject));
+ }
+ }
+ g_object_unref(self);
+}
+
+
+void lttv_attribute_recursive_add(LttvAttribute *dest, LttvAttribute *src)
+{
+ int i, nb;
+
+ Attribute *a;
+
+ LttvAttributeValue value;
+
+ nb = src->attributes->len;
+
+ for(i = 0 ; i < nb ; i++) {
+ a = &g_array_index(src->attributes, Attribute, i);
+ if(a->type == LTTV_GOBJECT && LTTV_IS_ATTRIBUTE(a->value.dv_gobject)) {
+ lttv_attribute_recursive_add(
+ /*CHECK*/(LttvAttribute *)lttv_attribute_find_subdir(dest, a->name),
+ (LttvAttribute *)(a->value.dv_gobject));
+ }
+ else {
+ g_assert(lttv_attribute_find(dest, a->name, a->type, &value));
+ switch(a->type) {
+ case LTTV_INT:
+ *value.v_int += a->value.dv_int;
+ break;
+ case LTTV_UINT:
+ *value.v_uint += a->value.dv_uint;
+ break;
+ case LTTV_LONG:
+ *value.v_long += a->value.dv_long;
+ break;
+ case LTTV_ULONG:
+ *value.v_ulong += a->value.dv_ulong;
+ break;
+ case LTTV_FLOAT:
+ *value.v_float += a->value.dv_float;
+ break;
+ case LTTV_DOUBLE:
+ *value.v_double += a->value.dv_double;
+ break;
+ case LTTV_TIME:
+ *value.v_time = ltt_time_add(*value.v_time, a->value.dv_time);
+ break;
+ case LTTV_POINTER:
+ break;
+ case LTTV_STRING:
+ break;
+ case LTTV_GOBJECT:
+ break;
+ case LTTV_NONE:
+ break;
+ }
+ }
+ }
+}
+
+
+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)
+{
+ LttvIAttributeClass *klass = (LttvIAttributeClass *)g_iface;
+
+ klass->get_number = (unsigned int (*) (LttvIAttribute *self))
+ lttv_attribute_get_number;
+
+ klass->named = (gboolean (*) (LttvIAttribute *self, gboolean *homogeneous))
+ lttv_attribute_named;
+
+ klass->get = (LttvAttributeType (*) (LttvIAttribute *self, unsigned i,
+ LttvAttributeName *name, LttvAttributeValue *v)) lttv_attribute_get;
+
+ klass->get_by_name = (LttvAttributeType (*) (LttvIAttribute *self,
+ LttvAttributeName name, LttvAttributeValue *v))
+ lttv_attribute_get_by_name;
+
+ klass->add = (LttvAttributeValue (*) (LttvIAttribute *self,
+ LttvAttributeName name, LttvAttributeType t)) lttv_attribute_add;
+
+ klass->remove = (void (*) (LttvIAttribute *self, unsigned i))
+ lttv_attribute_remove;
+
+ klass->remove_by_name = (void (*) (LttvIAttribute *self,
+ LttvAttributeName name)) lttv_attribute_remove_by_name;
+
+ klass->find_subdir = (LttvIAttribute* (*) (LttvIAttribute *self,
+ LttvAttributeName name)) lttv_attribute_find_subdir;
+}
+
+
+static void
+attribute_instance_init (GTypeInstance *instance, gpointer g_class)
+{
+ LttvAttribute *self = (LttvAttribute *)instance;
+ self->names = g_hash_table_new(g_direct_hash, g_direct_equal);
+ self->attributes = g_array_new(FALSE, FALSE, sizeof(Attribute));
+}
+
+
+static void
+attribute_finalize (LttvAttribute *self)
+{
+ g_hash_table_destroy(self->names);
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "attribute_finalize()");
+ g_array_free(self->attributes, TRUE);
+ G_OBJECT_CLASS(g_type_class_peek_parent(
+ g_type_class_peek(LTTV_ATTRIBUTE_TYPE)))->finalize(G_OBJECT(self));
+}
+
+
+static void
+attribute_class_init (LttvAttributeClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
+
+ gobject_class->finalize = (void (*)(GObject *self))attribute_finalize;
+}
+
+GType
+lttv_attribute_get_type (void)
+{
+ static GType type = 0;
+ if (type == 0) {
+ static const GTypeInfo info = {
+ sizeof (LttvAttributeClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) attribute_class_init, /* class_init */
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (LttvAttribute),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) attribute_instance_init /* instance_init */
+ };
+
+ static const GInterfaceInfo iattribute_info = {
+ (GInterfaceInitFunc) attribute_interface_init, /* interface_init */
+ NULL, /* interface_finalize */
+ NULL /* interface_data */
+ };
+
+ type = g_type_register_static (G_TYPE_OBJECT, "LttvAttributeType", &info,
+ 0);
+ g_type_add_interface_static (type, LTTV_IATTRIBUTE_TYPE, &iattribute_info);
+ }
+ return type;
+}
+
+
--- /dev/null
+/* This file is part of the Linux Trace Toolkit viewer
+ * Copyright (C) 2003-2004 Michel Dagenais
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+#ifndef ATTRIBUTE_H
+#define ATTRIBUTE_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))
+#define LTTV_ATTRIBUTE_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST ((vtable), LTTV_ATTRIBUTE_TYPE, LttvAttributeClass))
+#define LTTV_IS_ATTRIBUTE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LTTV_ATTRIBUTE_TYPE))
+#define LTTV_IS_ATTRIBUTE_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), LTTV_ATTRIBUTE_TYPE))
+#define LTTV_ATTRIBUTE_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), LTTV_ATTRIBUTE_TYPE, LttvAttributeClass))
+
+
+typedef struct _LttvAttribute LttvAttribute;
+typedef struct _LttvAttributeClass LttvAttributeClass;
+
+struct _LttvAttribute {
+ GObject parent;
+
+ /* private members */
+ GHashTable *names;
+ GArray *attributes;
+};
+
+struct _LttvAttributeClass {
+ GObjectClass parent;
+};
+
+GType lttv_attribute_get_type (void);
+
+
+/* The functions exported in the IAttribute interface are also available
+ directly. */
+
+
+/* Total number of attributes */
+
+unsigned int lttv_attribute_get_number(LttvAttribute *self);
+
+
+/* Container type. Named (fields in struct or elements in a hash table)
+ or unnamed (elements in an array) attributes, homogeneous type or not. */
+
+gboolean lttv_attribute_named(LttvAttribute *self, gboolean *homogeneous);
+
+
+/* Get the i th attribute along with its type and a pointer to its value. */
+
+LttvAttributeType lttv_attribute_get(LttvAttribute *self, unsigned i,
+ LttvAttributeName *name, LttvAttributeValue *v);
+
+
+/* Get the named attribute in the table along with its type and a pointer to
+ its value. If the named attribute does not exist, the type is LTTV_NONE. */
+
+LttvAttributeType lttv_attribute_get_by_name(LttvAttribute *self,
+ LttvAttributeName name, LttvAttributeValue *v);
+
+
+/* Add an attribute, which must not exist. The name is an empty string for
+ containers with unnamed attributes. */
+
+LttvAttributeValue lttv_attribute_add(LttvAttribute *self,
+ LttvAttributeName name, LttvAttributeType t);
+
+
+/* Remove an attribute */
+
+void lttv_attribute_remove(LttvAttribute *self, unsigned i);
+
+void lttv_attribute_remove_by_name(LttvAttribute *self,
+ LttvAttributeName name);
+
+
+/* Create an empty iattribute object and add it as an attribute under the
+ specified name, or return an existing iattribute attribute. If an
+ attribute of that name already exists but is not a GObject supporting the
+ iattribute interface, return NULL. */
+
+LttvAttribute* lttv_attribute_find_subdir(LttvAttribute *self,
+ LttvAttributeName name);
+
+gboolean lttv_attribute_find(LttvAttribute *self, LttvAttributeName name,
+ LttvAttributeType t, LttvAttributeValue *v);
+
+
+/* Free recursively a tree of attributes. All contained gobject of type
+ LttvAttribute are freed (unreferenced) recursively. */
+
+void lttv_attribute_recursive_free(LttvAttribute *self);
+
+/* Add items from a tree of attributes to another tree. */
+
+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
--- /dev/null
+/* This file is part of the Linux Trace Toolkit viewer
+ * Copyright (C) 2003-2004 Michel Dagenais
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+/* This module inserts a hook in the program main loop. This hook processes
+ all the events in the main tracefile while testing the speed and
+ functionality of the state and stats computations. */
+
+
+#include <lttv/lttv.h>
+#include <lttv/attribute.h>
+#include <lttv/hook.h>
+#include <lttv/option.h>
+#include <lttv/module.h>
+#include <lttv/tracecontext.h>
+#include <lttv/state.h>
+#include <lttv/stats.h>
+#include <ltt/trace.h>
+#include <ltt/event.h>
+#include <ltt/type.h>
+
+static LttvTraceset *traceset;
+
+static LttvHooks
+ *before_traceset,
+ *after_traceset,
+ *before_trace,
+ *after_trace,
+ *before_tracefile,
+ *after_tracefile,
+ *before_event,
+ *after_event,
+ *main_hooks;
+
+static char *a_trace;
+
+static char *a_dump_tracefiles;
+
+static char *a_save_sample;
+
+static int
+ a_sample_interval,
+ a_sample_number,
+ a_save_interval;
+
+static gboolean
+ a_trace_event,
+ a_save_state_copy,
+ a_test1,
+ a_test2,
+ a_test3,
+ a_test4,
+ a_test5,
+ a_test6,
+ a_test7,
+ a_test_all;
+
+LttEventPosition *a_event_position;
+
+typedef struct _save_state {
+ guint count;
+ FILE *fp;
+ guint interval;
+ guint position;
+ guint size;
+ LttTime *write_time;
+ guint version;
+} SaveState;
+
+
+static void lttv_trace_option(void *hook_data)
+{
+ LttTrace *trace;
+
+ trace = ltt_trace_open(a_trace);
+ if(trace == NULL) g_critical("cannot open trace %s", a_trace);
+ lttv_traceset_add(traceset, lttv_trace_new(trace));
+}
+
+static double get_time()
+{
+ GTimeVal gt;
+
+ g_get_current_time(>);
+ return gt.tv_sec + (double)gt.tv_usec / (double)1000000.0;
+}
+
+static double run_one_test(LttvTracesetState *ts, LttTime start, LttTime end)
+{
+ 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);
+ t1 = get_time();
+
+ lttv_traceset_context_remove_hooks(&ts->parent,
+ before_traceset, after_traceset, NULL, before_trace, after_trace,
+ NULL, before_tracefile, after_tracefile, NULL, before_event, after_event);
+
+ return t1 - t0;
+}
+
+
+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;
+
+ (*pcount)++;
+ return FALSE;
+}
+
+
+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;
+
+ LttvTracefileState *tfs = (LttvTracefileState *)call_data;
+
+ LttvTraceState *ts = (LttvTraceState *)tfs->parent.t_context;
+
+ GString *filename;
+
+ FILE *fp;
+
+ (save_state->count)++;
+ if(save_state->count % save_state->interval == 0 &&
+ save_state->position < save_state->size) {
+ if(a_save_sample != NULL) {
+ filename = g_string_new("");
+ g_string_printf(filename, "%s.%u.xml.%u", a_save_sample,
+ save_state->position, save_state->version);
+ 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);
+
+ save_state->write_time[save_state->position] = tfs->parent.timestamp;
+ save_state->position++;
+ }
+ return FALSE;
+}
+
+
+static gboolean process_traceset(void *hook_data, void *call_data)
+{
+ LttvTracesetStats *tscs;
+
+ LttvTracesetState *ts;
+
+ LttvTracesetContext *tc;
+
+ GString *filename;
+
+ FILE *fp;
+
+ double t;
+
+ guint i, j, count, nb_control, nb_tracefile, nb_block, nb_event, nb_equal;
+
+ LttTrace *trace;
+
+ LttTracefile *tracefile, *tf;
+
+ LttEvent *event;
+
+ LttFacility *facility;
+
+ LttType *type;
+
+ LttEventType *event_type;
+
+ LttTime time, previous_time;
+
+ long long unsigned cycle_count, start_count, delta_cycle;
+
+ long long unsigned start_nsec, end_nsec, delta_nsec, added_nsec, added_nsec2;
+
+ double cycle_per_nsec, nsec_per_cycle;
+
+ long long interpolated_nsec, interpolated_nsec2, end_nsec_sec, end_nsec_nsec;
+
+ LttTime start_time;
+
+ 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) {
+ 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);
+ nb_tracefile = nb_control + ltt_trace_per_cpu_tracefile_number(trace);
+ for(j = 0 ; j < nb_tracefile ; j++) {
+ if(j < nb_control) {
+ tracefile = ltt_trace_control_tracefile_get(trace,j);
+ }
+ else {
+ tracefile = ltt_trace_per_cpu_tracefile_get(trace,j - nb_control);
+ }
+
+ filename = g_string_new("");
+ g_string_printf(filename, "%s.%u.%u.trace", a_dump_tracefiles, i, j);
+ fp = fopen(filename->str, "w");
+ if(fp == NULL) g_error("Cannot open %s", filename->str);
+ g_string_free(filename, TRUE);
+ ltt_tracefile_seek_time(tracefile, zero_time);
+ previous_time = zero_time;
+ nb_equal = 0;
+ while((event = ltt_tracefile_read(tracefile)) != NULL) {
+ facility = ltt_event_facility(event);
+ event_type = ltt_event_eventtype(event);
+ time = ltt_event_time(event);
+ cycle_count = ltt_event_cycle_count(event);
+ 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,
+ (unsigned long)time.tv_nsec,
+ nb_block, nb_event);
+
+ if(ltt_time_compare(time, previous_time) < 0) {
+ g_warning("Time decreasing trace %d tracefile %d position %u/%u",
+ i, j, nb_block, nb_event);
+ }
+
+ if(strcmp(ltt_eventtype_name(event_type),"block_start") == 0) {
+ start_count = cycle_count;
+ start_time = time;
+ }
+ else if(strcmp(ltt_eventtype_name(event_type),"block_end") == 0) {
+ delta_cycle = cycle_count - start_count;
+ end_nsec_sec = (long long unsigned)time.tv_sec * (long long unsigned)1000000000;
+ end_nsec_nsec = time.tv_nsec;
+ end_nsec = end_nsec_sec + end_nsec_nsec;
+ start_nsec = (long long unsigned)start_time.tv_sec * (long long unsigned)1000000000 + (long long unsigned)start_time.tv_nsec;
+ delta_nsec = end_nsec - start_nsec;
+ cycle_per_nsec = (double)delta_cycle / (double)delta_nsec;
+ nsec_per_cycle = (double)delta_nsec / (double)delta_cycle;
+ added_nsec = (double)delta_cycle * nsec_per_cycle;
+ interpolated_nsec = start_nsec + added_nsec;
+ added_nsec2 = (double)delta_cycle / cycle_per_nsec;
+ interpolated_nsec2 = start_nsec + added_nsec2;
+
+ fprintf(fp,"Time: start_count %llu, end_count %llu, delta_cycle %llu, start_nsec %llu, end_nsec_sec %llu, end_nsec_nsec %llu, end_nsec %llu, delta_nsec %llu, cycle_per_nsec %.25f, nsec_per_cycle %.25f, added_nsec %llu, added_nsec2 %llu, interpolated_nsec %llu, interpolated_nsec2 %llu\n", start_count, cycle_count, delta_cycle, start_nsec, end_nsec_sec, end_nsec_nsec, end_nsec, delta_nsec, cycle_per_nsec, nsec_per_cycle, added_nsec, added_nsec2, interpolated_nsec, interpolated_nsec2);
+ }
+ else {
+ if(ltt_time_compare(time, previous_time) == 0) nb_equal++;
+ else if(nb_equal > 0) {
+ g_warning("Consecutive %d events with time %lu.%09lu",
+ nb_equal + 1, previous_time.tv_sec, previous_time.tv_nsec);
+ nb_equal = 0;
+ }
+ previous_time = time;
+ }
+ }
+ fclose(fp);
+ }
+ }
+ }
+
+ tscs = g_object_new(LTTV_TRACESET_STATS_TYPE, NULL);
+ ts = &tscs->parent;
+ tc = &tscs->parent.parent;
+
+ lttv_context_init(tc, traceset);
+
+ /* For each case compute and print the elapsed time.
+ The first case is simply to run through all events with a
+ simple counter. */
+
+ if(a_test1 || a_test_all) {
+ count = 0;
+ lttv_hooks_add(after_event, count_event, &count);
+ t = run_one_test(ts, zero_time, max_time);
+ lttv_hooks_remove_data(after_event, count_event, &count);
+ g_warning(
+ "Processing trace while counting events (%u events in %g seconds)",
+ count, t);
+ }
+
+ /* Run through all events computing the state. */
+
+ if(a_test2 || a_test_all) {
+ lttv_state_add_event_hooks(ts);
+ t = run_one_test(ts, zero_time, max_time);
+ lttv_state_remove_event_hooks(ts);
+ g_warning("Processing trace while updating state (%g seconds)", t);
+ }
+
+ /* Run through all events computing the state and writing it out
+ periodically. */
+
+ SaveState save_state;
+
+ save_state.interval = a_sample_interval;
+ save_state.size = a_sample_number;
+ save_state.fp = stderr;
+ save_state.write_time = g_new(LttTime, a_sample_number);
+
+
+ if(a_test3 || a_test_all) {
+ for(i = 0 ; i < 2 ; i++) {
+ save_state.count = 0;
+ save_state.position = 0;
+ save_state.version = i;
+ lttv_state_add_event_hooks(ts);
+ lttv_hooks_add(after_event, save_state_event, &save_state);
+ t = run_one_test(ts, zero_time, max_time);
+ lttv_state_remove_event_hooks(ts);
+ lttv_hooks_remove_data(after_event, save_state_event, &save_state);
+ g_warning("Processing while updating/writing state (%g seconds)", t);
+ }
+ }
+
+ /* Run through all events computing the stats. */
+
+ if(a_test4 || a_test_all) {
+ if(lttv_profile_memory) {
+ g_message("Memory summary before computing stats");
+ g_mem_profile();
+ }
+
+ lttv_stats_add_event_hooks(tscs);
+ t = run_one_test(ts, zero_time, max_time);
+ lttv_stats_remove_event_hooks(tscs);
+ g_warning("Processing trace while counting stats (%g seconds)", t);
+
+ if(lttv_profile_memory) {
+ 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. */
+
+ if(a_test5 || a_test_all) {
+ if(lttv_profile_memory) {
+ g_message("Memory summary before computing state and stats");
+ g_mem_profile();
+ }
+
+ lttv_state_add_event_hooks(ts);
+ lttv_stats_add_event_hooks(tscs);
+ t = run_one_test(ts, zero_time, max_time);
+ lttv_state_remove_event_hooks(ts);
+ lttv_stats_remove_event_hooks(tscs);
+ g_warning(
+ "Processing trace while counting state and stats (%g seconds)", t);
+
+ if(lttv_profile_memory) {
+ 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");
+ g_mem_profile();
+ }
+
+ 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) {
+ g_message("Memory summary after computing/saving state");
+ g_mem_profile();
+ }
+ }
+
+ /* Seek a few times to each saved position */
+
+ if((a_test7 && a_test3) || a_test_all) {
+ int i, j;
+
+ for(i = 0 ; i < 2 ; i++) {
+ for(j = save_state.position - 1 ; j >= 0 ; j--) {
+ lttv_state_add_event_hooks(ts);
+ t = run_one_test(ts, save_state.write_time[j],
+ save_state.write_time[j]);
+ lttv_state_remove_event_hooks(ts);
+ g_warning("Seeking to %lu.%lu (%g seconds)",
+ save_state.write_time[j].tv_sec, save_state.write_time[j].tv_nsec,
+ t);
+
+ if(a_save_sample != NULL) {
+ filename = g_string_new("");
+ g_string_printf(filename, "%s.%d.xml.bak%d", a_save_sample, j, i);
+ fp = fopen(filename->str, "w");
+ if(fp == NULL) g_error("Cannot open %s", filename->str);
+ g_string_free(filename, TRUE);
+ lttv_state_write((LttvTraceState *)tc->traces[0],
+ save_state.write_time[j], fp);
+ fclose(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");
+}
+
+
+static void init()
+{
+ LttvAttributeValue value;
+
+ LttvIAttribute *attributes = LTTV_IATTRIBUTE(lttv_global_attributes());
+
+ g_info("Init batchtest.c");
+
+ lttv_option_add("trace", 't',
+ "add a trace to the trace set to analyse",
+ "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 where to dump events",
+ LTTV_OPT_STRING, &a_dump_tracefiles, NULL, NULL);
+
+ a_save_sample = NULL;
+ lttv_option_add("save-sample", 's',
+ "Save state samples to multiple files",
+ "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",
+ "number of events before a block start triggers saving state",
+ LTTV_OPT_INT, &a_save_interval, NULL, NULL);
+
+ a_sample_interval = 100000;
+ lttv_option_add("sample-interval", 'S',
+ "Interval between sampling state",
+ "number of events before sampling and writing state",
+ LTTV_OPT_INT, &a_sample_interval, NULL, NULL);
+
+ a_sample_number = 20;
+ lttv_option_add("sample-number", 'N',
+ "Number of state samples",
+ "maximum number",
+ LTTV_OPT_INT, &a_sample_number, NULL, NULL);
+
+ a_test1 = FALSE;
+ lttv_option_add("test1", '1', "Test just counting events", "",
+ LTTV_OPT_NONE, &a_test1, NULL, NULL);
+
+ a_test2 = FALSE;
+ lttv_option_add("test2", '2', "Test computing the state", "",
+ LTTV_OPT_NONE, &a_test2, NULL, NULL);
+
+ a_test3 = FALSE;
+ lttv_option_add("test3", '3', "Test computing the state, writing out a few",
+ "", LTTV_OPT_NONE, &a_test3, NULL, NULL);
+
+ a_test4 = FALSE;
+ lttv_option_add("test4", '4', "Test computing the stats", "",
+ LTTV_OPT_NONE, &a_test4, NULL, NULL);
+
+ a_test5 = FALSE;
+ lttv_option_add("test5", '5', "Test computing the state and stats", "",
+ LTTV_OPT_NONE, &a_test5, NULL, NULL);
+
+ a_test6 = FALSE;
+ lttv_option_add("test6", '6', "Test computing and saving the state", "",
+ LTTV_OPT_NONE, &a_test6, NULL, NULL);
+
+ a_test7 = FALSE;
+ lttv_option_add("test7", '7', "Test seeking to positions written out in 3",
+ "", LTTV_OPT_NONE, &a_test7, NULL, NULL);
+
+ a_test_all = FALSE;
+ lttv_option_add("testall", 'a', "Run all tests ", "",
+ LTTV_OPT_NONE, &a_test_all, NULL, NULL);
+
+ traceset = lttv_traceset_new();
+
+ before_traceset = lttv_hooks_new();
+ after_traceset = lttv_hooks_new();
+ before_trace = lttv_hooks_new();
+ after_trace = lttv_hooks_new();
+ before_tracefile = lttv_hooks_new();
+ after_tracefile = lttv_hooks_new();
+ before_event = lttv_hooks_new();
+ after_event = lttv_hooks_new();
+
+ g_assert(lttv_iattribute_find_by_path(attributes, "hooks/traceset/before",
+ LTTV_POINTER, &value));
+ *(value.v_pointer) = before_traceset;
+ g_assert(lttv_iattribute_find_by_path(attributes, "hooks/traceset/after",
+ LTTV_POINTER, &value));
+ *(value.v_pointer) = after_traceset;
+ g_assert(lttv_iattribute_find_by_path(attributes, "hooks/trace/before",
+ LTTV_POINTER, &value));
+ *(value.v_pointer) = before_trace;
+ g_assert(lttv_iattribute_find_by_path(attributes, "hooks/trace/after",
+ LTTV_POINTER, &value));
+ *(value.v_pointer) = after_trace;
+ g_assert(lttv_iattribute_find_by_path(attributes, "hooks/tracefile/before",
+ LTTV_POINTER, &value));
+ *(value.v_pointer) = before_tracefile;
+ g_assert(lttv_iattribute_find_by_path(attributes, "hooks/tracefile/after",
+ LTTV_POINTER, &value));
+ *(value.v_pointer) = after_tracefile;
+ g_assert(lttv_iattribute_find_by_path(attributes, "hooks/event/before",
+ LTTV_POINTER, &value));
+ *(value.v_pointer) = before_event;
+ g_assert(lttv_iattribute_find_by_path(attributes, "hooks/event/after",
+ LTTV_POINTER, &value));
+ *(value.v_pointer) = after_event;
+
+ g_assert(lttv_iattribute_find_by_path(attributes, "hooks/main/before",
+ LTTV_POINTER, &value));
+ g_assert((main_hooks = *(value.v_pointer)) != NULL);
+ lttv_hooks_add(main_hooks, process_traceset, NULL);
+}
+
+
+static void destroy()
+{
+ guint i, nb;
+
+ LttvTrace *trace;
+
+ g_info("Destroy batchAnalysis.c");
+
+ 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");
+ lttv_option_remove("test1");
+ lttv_option_remove("test2");
+ lttv_option_remove("test3");
+ lttv_option_remove("test4");
+ lttv_option_remove("test5");
+ lttv_option_remove("test6");
+ lttv_option_remove("test7");
+ lttv_option_remove("testall");
+
+ lttv_hooks_destroy(before_traceset);
+ lttv_hooks_destroy(after_traceset);
+ lttv_hooks_destroy(before_trace);
+ lttv_hooks_destroy(after_trace);
+ lttv_hooks_destroy(before_tracefile);
+ lttv_hooks_destroy(after_tracefile);
+ lttv_hooks_destroy(before_event);
+ lttv_hooks_destroy(after_event);
+ lttv_hooks_remove_data(main_hooks, process_traceset, NULL);
+
+ nb = lttv_traceset_number(traceset);
+ for(i = 0 ; i < nb ; i++) {
+ trace = lttv_traceset_get(traceset, i);
+ ltt_trace_close(lttv_trace(trace));
+ lttv_trace_destroy(trace);
+ }
+
+ lttv_traceset_destroy(traceset);
+}
+
+
+LTTV_MODULE("batchtest", "Batch processing of a trace for tests", \
+ "Run through a trace calling all the registered hooks for tests", \
+ init, destroy, "state", "stats", "option" )
--- /dev/null
+/* This file is part of the Linux Trace Toolkit viewer
+ * Copyright (C) 2003-2004 Michel Dagenais
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+
+ consist in AND, OR and NOT nested expressions, forming a tree with
+ simple relations as leaves. The simple relations test is a field
+ in an event is equal, not equal, smaller, smaller or equal, larger, or
+ larger or equal to a specified value. */
+
+typedef enum _lttv_expression_op
+{ LTTV_FIELD_EQ,
+ LTTV_FIELD_NE,
+ LTTV_FIELD_LT,
+ LTTV_FIELD_LE,
+ LTTV_FIELD_GT,
+ LTTV_FIELD_GE
+} lttv_expression_op;
+
+typedef _lttv_simple_expression
+{ lttv_expression_op op;
+ char *field_name;
+ char *value;
+} lttv_simple_expression;
+
+typedef _lttv_expression_type
+{ LTTV_EXPRESSION,
+ LTTV_SIMPLE_EXPRESSION
+
+}
+typedef struct _lttv_expression
+{ bool or;
+ bool not;
+ bool simple_expression;
+ union
+ { lttv_expression *e;
+ lttv_field_relation *se;
+ } e;
+} lttv_expression;
+
+read_token
+
+read_expression
+ ( read expr )
+ simple expr [ op expr ]
+
+read_simple_expression
+ read_field_path [ rel value ]
+
+read_field_path
+ read_field_component [. field path]
+
+read_field_component
+ name [ \[ value \] ]
+
+data struct:
+and/or(left/right)
+not(child)
+op(left/right)
+path(component...) -> field
+
+
--- /dev/null
+/* This file is part of the Linux Trace Toolkit viewer
+ * Copyright (C) 2003-2004 Michel Dagenais
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+#ifndef FILTER_H
+#define FILTER_H
+
+/* A filter expression consists in nested AND, OR and NOT expressions
+ involving boolean relation (>, >=, =, !=, <, <=) between event fields and
+ specific values. It is compiled into an efficient data structure which
+ is used in functions to check if a given event or tracefile satisfies the
+ filter.
+
+ The grammar for filters is:
+
+ filter = expression
+
+ expression = "(" expression ")" | "!" expression |
+ expression "&&" expression | expression "||" expression |
+ simpleExpression
+
+ simpleExpression = fieldPath op value
+
+ fieldPath = fieldComponent [ "." fieldPath ]
+
+ fieldComponent = name [ "[" integer "]" ]
+
+ value = integer | double | string
+
+*/
+
+
+typedef struct _lttv_filter lttv_filter;
+
+
+/* Compile the filter expression into an efficient data structure */
+
+lttv_filter *lttv_filter_new(char *expression, lttv_trace *t);
+
+
+/* Check if the tracefile or event satisfies the filter. The arguments are
+ declared as void * to allow these functions to be used as hooks. */
+
+bool lttv_filter_tracefile(void *filter, void *tracefile);
+
+bool lttv_filter_event(void *filter, void *event);
+
+#endif // FILTER_H
+
--- /dev/null
+/* This file is part of the Linux Trace Toolkit viewer
+ * Copyright (C) 2003-2004 Michel Dagenais
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+
+#include <lttv/hook.h>
+
+
+typedef struct _LttvHookClosure {
+ LttvHook hook;
+ void *hook_data;
+} LttvHookClosure;
+
+
+LttvHooks *lttv_hooks_new()
+{
+ return g_array_new(FALSE, FALSE, sizeof(LttvHookClosure));
+}
+
+
+void lttv_hooks_destroy(LttvHooks *h)
+{
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "lttv_hooks_destroy()");
+ g_array_free(h, TRUE);
+}
+
+
+void lttv_hooks_add(LttvHooks *h, LttvHook f, void *hook_data)
+{
+ LttvHookClosure c;
+
+ if(h == NULL)g_error("Null hook added");
+
+ c.hook = f;
+ c.hook_data = hook_data;
+ g_array_append_val(h,c);
+}
+
+
+void lttv_hooks_add_list(LttvHooks *h, LttvHooks *list)
+{
+ guint i;
+
+ if(list == NULL) return;
+ for(i = 0 ; i < list->len; i++) {
+ g_array_append_val(h,g_array_index(list, LttvHookClosure, i));
+ }
+}
+
+
+void *lttv_hooks_remove(LttvHooks *h, LttvHook f)
+{
+ unsigned i;
+
+ void *hook_data;
+
+ LttvHookClosure *c;
+
+ for(i = 0 ; i < h->len ; i++) {
+ c = &g_array_index(h, LttvHookClosure, i);
+ if(c->hook == f) {
+ hook_data = c->hook_data;
+ lttv_hooks_remove_by_position(h, i);
+ return hook_data;
+ }
+ }
+ return NULL;
+}
+
+
+void lttv_hooks_remove_data(LttvHooks *h, LttvHook f, void *hook_data)
+{
+ unsigned i;
+
+ LttvHookClosure *c;
+
+ for(i = 0 ; i < h->len ; i++) {
+ c = &g_array_index(h, LttvHookClosure, i);
+ if(c->hook == f && c->hook_data == hook_data) {
+ lttv_hooks_remove_by_position(h, i);
+ return;
+ }
+ }
+}
+
+
+void lttv_hooks_remove_list(LttvHooks *h, LttvHooks *list)
+{
+ guint i, j;
+
+ LttvHookClosure *c, *c_list;
+
+ if(list == NULL) return;
+ for(i = 0, j = 0 ; i < h->len && j < list->len ;) {
+ c = &g_array_index(h, LttvHookClosure, i);
+ c_list = &g_array_index(list, LttvHookClosure, j);
+ if(c->hook == c_list->hook && c->hook_data == c_list->hook_data) {
+ lttv_hooks_remove_by_position(h, i);
+ j++;
+ }
+ else i++;
+ }
+
+ /* Normally the hooks in h are ordered as in list. If this is not the case,
+ try harder here. */
+
+ if(j < list->len) {
+ for(; j < list->len ; j++) {
+ c_list = &g_array_index(list, LttvHookClosure, j);
+ lttv_hooks_remove_data(h, c_list->hook, c_list->hook_data);
+ }
+ }
+}
+
+
+unsigned lttv_hooks_number(LttvHooks *h)
+{
+ return h->len;
+}
+
+
+void lttv_hooks_get(LttvHooks *h, unsigned i, LttvHook *f, void **hook_data)
+{
+ LttvHookClosure *c;
+
+ c = &g_array_index(h, LttvHookClosure, i);
+ *f = c->hook;
+ *hook_data = c->hook_data;
+}
+
+
+void lttv_hooks_remove_by_position(LttvHooks *h, unsigned i)
+{
+ g_array_remove_index(h, i);
+}
+
+
+gboolean lttv_hooks_call(LttvHooks *h, void *call_data)
+{
+ gboolean ret, sum_ret = FALSE;
+
+ LttvHookClosure *c;
+
+ guint i;
+
+ if(h != NULL) {
+ for(i = 0 ; i < h->len ; i++) {
+ c = &g_array_index(h, LttvHookClosure, i);
+ ret = c->hook(c->hook_data,call_data);
+ sum_ret = sum_ret || ret;
+ }
+ }
+ return sum_ret;
+}
+
+
+gboolean lttv_hooks_call_check(LttvHooks *h, void *call_data)
+{
+ LttvHookClosure *c;
+
+ guint i;
+
+ for(i = 0 ; i < h->len ; i++) {
+ c = &g_array_index(h, LttvHookClosure, i);
+ if(c->hook(c->hook_data,call_data)) return TRUE;
+ }
+ return FALSE;
+}
+
+
+LttvHooksById *lttv_hooks_by_id_new()
+{
+ return g_ptr_array_new();
+}
+
+
+void lttv_hooks_by_id_destroy(LttvHooksById *h)
+{
+ guint i;
+
+ for(i = 0 ; i < h->len ; i++) {
+ if(h->pdata[i] != NULL) lttv_hooks_destroy((LttvHooks *)(h->pdata[i]));
+ }
+ g_ptr_array_free(h, TRUE);
+}
+
+
+LttvHooks *lttv_hooks_by_id_find(LttvHooksById *h, unsigned id)
+{
+ if(h->len <= id) g_ptr_array_set_size(h, id + 1);
+ if(h->pdata[id] == NULL) h->pdata[id] = lttv_hooks_new();
+ return h->pdata[id];
+}
+
+
+unsigned lttv_hooks_by_id_max_id(LttvHooksById *h)
+{
+ return h->len;
+}
+
+
+LttvHooks *lttv_hooks_by_id_get(LttvHooksById *h, unsigned id)
+{
+ if(id < h->len) return h->pdata[id];
+ return NULL;
+}
+
+
+void lttv_hooks_by_id_remove(LttvHooksById *h, unsigned id)
+{
+ if(id < h->len && h->pdata[id] != NULL) {
+ lttv_hooks_destroy((LttvHooks *)h->pdata[id]);
+ h->pdata[id] = NULL;
+ }
+}
+
--- /dev/null
+/* This file is part of the Linux Trace Toolkit viewer
+ * Copyright (C) 2003-2004 Michel Dagenais
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+#ifndef HOOK_H
+#define HOOK_H
+
+#include <glib.h>
+
+/* A hook is a function to call with the supplied hook data, and with
+ call site specific data (e.g., hooks for events are called with a
+ pointer to the current event). */
+
+typedef gboolean (*LttvHook)(void *hook_data, void *call_data);
+
+
+/* A list of hooks allows registering hooks to be called later. */
+
+typedef GArray LttvHooks;
+
+
+/* Create and destroy a list of hooks */
+
+LttvHooks *lttv_hooks_new();
+
+void lttv_hooks_destroy(LttvHooks *h);
+
+
+/* Add a hook and its hook data to the list */
+
+void lttv_hooks_add(LttvHooks *h, LttvHook f, void *hook_data);
+
+
+/* Add a list of hooks to the list h */
+
+void lttv_hooks_add_list(LttvHooks *h, LttvHooks *list);
+
+
+/* Remove a hook from the list. Return the hook data. */
+
+void *lttv_hooks_remove(LttvHooks *h, LttvHook f);
+
+
+/* Remove a hook from the list checking that the hook data match. */
+
+void lttv_hooks_remove_data(LttvHooks *h, LttvHook f, void *hook_data);
+
+
+/* Remove a list of hooks from the hooks list in h. */
+
+void lttv_hooks_remove_data_list(LttvHooks *h, LttvHook *list);
+
+
+/* Return the number of hooks in the list */
+
+unsigned lttv_hooks_number(LttvHooks *h);
+
+
+/* Return the hook at the specified position in the list */
+
+void lttv_hooks_get(LttvHooks *h, unsigned i, LttvHook *f, void **hook_data);
+
+
+/* Remove the specified hook. The position of the following hooks may change */
+
+void lttv_hooks_remove_by_position(LttvHooks *h, unsigned i);
+
+
+/* Call all the hooks in the list, each with its hook data,
+ with the specified call data. Return TRUE if one hook returned TRUE. */
+
+gboolean lttv_hooks_call(LttvHooks *h, void *call_data);
+
+
+/* Call the hooks in the list until one returns true, in which case TRUE is
+ returned. */
+
+gboolean lttv_hooks_call_check(LttvHooks *h, void *call_data);
+
+
+/* Sometimes different hooks need to be called based on the case. The
+ case is represented by an unsigned integer id */
+
+typedef GPtrArray LttvHooksById;
+
+
+/* Create and destroy a hooks by id list */
+
+LttvHooksById *lttv_hooks_by_id_new();
+
+void lttv_hooks_by_id_destroy(LttvHooksById *h);
+
+
+/* Obtain the hooks for a given id, creating a list if needed */
+
+LttvHooks *lttv_hooks_by_id_find(LttvHooksById *h, unsigned id);
+
+
+/* Return an id larger than any for which a list exists. */
+
+unsigned lttv_hooks_by_id_max_id(LttvHooksById *h);
+
+
+/* Get the list of hooks for an id, NULL if none exists */
+
+LttvHooks *lttv_hooks_by_id_get(LttvHooksById *h, unsigned id);
+
+
+/* Remove the list of hooks associated with an id */
+
+void lttv_hooks_by_id_remove(LttvHooksById *h, unsigned id);
+
+#endif // HOOK_H
--- /dev/null
+/* This file is part of the Linux Trace Toolkit viewer
+ * Copyright (C) 2003-2004 Michel Dagenais
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+
+#include <lttv/iattribute.h>
+
+static void
+lttv_iattribute_base_init (gpointer klass)
+{
+ static gboolean initialized = FALSE;
+
+ if (!initialized) {
+ initialized = TRUE;
+ }
+}
+
+
+GType
+lttv_iattribute_get_type (void)
+{
+ static GType type = 0;
+ if (type == 0) {
+ static const GTypeInfo info = {
+ sizeof (LttvIAttributeClass),
+ lttv_iattribute_base_init, /* base_init */
+ NULL, /* base_finalize */
+ NULL, /* class_init */
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ 0,
+ 0, /* n_preallocs */
+ NULL /* instance_init */
+ };
+ type = g_type_register_static (G_TYPE_INTERFACE, "LttvIAttribute",
+ &info, 0);
+ }
+ return type;
+}
+
+
+unsigned int lttv_iattribute_get_number(LttvIAttribute *self)
+{
+ return LTTV_IATTRIBUTE_GET_CLASS (self)->get_number (self);
+}
+
+
+gboolean lttv_iattribute_named(LttvIAttribute *self, gboolean *homogeneous)
+{
+ return LTTV_IATTRIBUTE_GET_CLASS (self)->named (self, homogeneous);
+}
+
+
+LttvAttributeType lttv_iattribute_get(LttvIAttribute *self, unsigned i,
+ LttvAttributeName *name, LttvAttributeValue *v)
+{
+ return LTTV_IATTRIBUTE_GET_CLASS (self)->get (self, i, name, v);
+}
+
+
+LttvAttributeType lttv_iattribute_get_by_name(LttvIAttribute *self,
+ LttvAttributeName name, LttvAttributeValue *v)
+{
+ return LTTV_IATTRIBUTE_GET_CLASS (self)->get_by_name (self, name, v);
+}
+
+
+LttvAttributeValue lttv_iattribute_add(LttvIAttribute *self,
+ LttvAttributeName name, LttvAttributeType t)
+{
+ return LTTV_IATTRIBUTE_GET_CLASS (self)->add (self, name, t);
+}
+
+
+void lttv_iattribute_remove(LttvIAttribute *self, unsigned i)
+{
+ return LTTV_IATTRIBUTE_GET_CLASS (self)->remove (self, i);
+}
+
+
+void lttv_iattribute_remove_by_name(LttvIAttribute *self,
+ LttvAttributeName name)
+{
+ return LTTV_IATTRIBUTE_GET_CLASS (self)->remove_by_name (self, name);
+}
+
+LttvIAttribute* lttv_iattribute_find_subdir(LttvIAttribute *self,
+ LttvAttributeName name)
+{
+ return LTTV_IATTRIBUTE_GET_CLASS (self)->find_subdir (self, name);
+}
+
+
+/* Find the named attribute in the table, which must be of the specified type.
+ If it does not exist, it is created with a default value of 0 (NULL for
+ pointer types). Since the address of the value is obtained, it may be
+ changed easily afterwards. The function returns false when the attribute
+ exists but is of incorrect type. */
+
+gboolean lttv_iattribute_find(LttvIAttribute *self, LttvAttributeName name,
+ LttvAttributeType t, LttvAttributeValue *v)
+{
+ LttvAttributeType found_type;
+
+ found_type = lttv_iattribute_get_by_name(self, name, v);
+ if(found_type == t) return TRUE;
+
+ if(found_type == LTTV_NONE) {
+ *v = lttv_iattribute_add(self, name, t);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/* Trees of attribute tables may be accessed using a hierarchical path with
+ components separated by /, like in filesystems */
+
+gboolean lttv_iattribute_find_by_path(LttvIAttribute *self, char *path,
+ LttvAttributeType t, LttvAttributeValue *v)
+{
+ LttvIAttribute *node = self;
+
+ LttvAttributeType found_type;
+
+ LttvAttributeName name;
+
+ gchar **components, **cursor;
+
+ components = g_strsplit(path, "\"", G_MAXINT);
+
+ if(components == NULL || *components == NULL) {
+ g_strfreev(components);
+ return FALSE;
+ }
+
+ for(cursor = components;;) {
+ name = g_quark_from_string(*cursor);
+ cursor++;
+
+ if(*cursor == NULL) {
+ g_strfreev(components);
+ return lttv_iattribute_find(node, name, t, v);
+ }
+ else {
+ found_type = lttv_iattribute_get_by_name(node, name, v);
+ if(found_type == LTTV_NONE) {
+ node = lttv_iattribute_find_subdir(node, name);
+ }
+ else if(found_type == LTTV_GOBJECT &&
+ LTTV_IS_IATTRIBUTE(*(v->v_gobject))) {
+ node = LTTV_IATTRIBUTE(*(v->v_gobject));
+ }
+ else {
+ g_strfreev(components);
+ return FALSE;
+ }
+ }
+ }
+}
+
+/* Shallow and deep copies */
+
+LttvIAttribute *lttv_iattribute_shallow_copy(LttvIAttribute *self)
+{
+ LttvIAttribute *copy;
+
+ LttvAttributeType t;
+
+ LttvAttributeValue v, v_copy;
+
+ LttvAttributeName name;
+
+ int i;
+
+ int nb_attributes = lttv_iattribute_get_number(self);
+
+ copy = LTTV_IATTRIBUTE(g_object_new(G_OBJECT_TYPE(self),NULL));
+
+ for(i = 0 ; i < nb_attributes ; i++) {
+ t = lttv_iattribute_get(self, i, &name, &v);
+ v_copy = lttv_iattribute_add(copy, name, t);
+ lttv_iattribute_copy_value(t, v_copy, v);
+ }
+}
+
+LttvIAttribute *lttv_iattribute_deep_copy(LttvIAttribute *self)
+{
+ LttvIAttribute *copy, *child;
+
+ LttvAttributeType t;
+
+ LttvAttributeValue v, v_copy;
+
+ LttvAttributeName name;
+
+ int i;
+
+ int nb_attributes = lttv_iattribute_get_number(self);
+
+ copy = LTTV_IATTRIBUTE(g_object_new(G_OBJECT_TYPE(self), NULL));
+
+ for(i = 0 ; i < nb_attributes ; i++) {
+ t = lttv_iattribute_get(self, i, &name, &v);
+ v_copy = lttv_iattribute_add(copy, name, t);
+ if(t == LTTV_GOBJECT && LTTV_IS_IATTRIBUTE(*(v.v_gobject))) {
+ child = LTTV_IATTRIBUTE(*(v.v_gobject));
+ *(v_copy.v_gobject) = G_OBJECT(lttv_iattribute_deep_copy(child));
+ }
+ else lttv_iattribute_copy_value(t, v_copy, v);
+ }
+}
+
+void lttv_iattribute_copy_value(LttvAttributeType t, LttvAttributeValue dest,
+ LttvAttributeValue src)
+{
+ switch(t) {
+ case LTTV_INT:
+ *(dest.v_int) = *(src.v_int);
+ break;
+
+ case LTTV_UINT:
+ *(dest.v_uint) = *(src.v_uint);
+ break;
+
+ case LTTV_LONG:
+ *(dest.v_long) = *(src.v_long);
+ break;
+
+ case LTTV_ULONG:
+ *(dest.v_ulong) = *(src.v_ulong);
+ break;
+
+ case LTTV_FLOAT:
+ *(dest.v_float) = *(src.v_float);
+ break;
+
+ case LTTV_DOUBLE:
+ *(dest.v_double) = *(src.v_double);
+ break;
+
+ case LTTV_TIME:
+ *(dest.v_time) = *(src.v_time);
+ break;
+
+ case LTTV_POINTER:
+ *(dest.v_pointer) = *(src.v_pointer);
+ break;
+
+ case LTTV_STRING:
+ *(dest.v_string) = *(src.v_string);
+ break;
+
+ case LTTV_GOBJECT:
+ *(dest.v_gobject) = *(src.v_gobject);
+ break;
+
+ case LTTV_NONE:
+ break;
+ }
+}
+
+
--- /dev/null
+/* This file is part of the Linux Trace Toolkit viewer
+ * Copyright (C) 2003-2004 Michel Dagenais
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+#ifndef IATTRIBUTE_H
+#define IATTRIBUTE_H
+
+
+#include <glib-object.h>
+#include <ltt/time.h>
+
+/* The content of a data structure may be seen as an array of pairs of
+ attribute name and value. This simple model allows generic navigation
+ and access functions over a wide range of structures. The names are
+ represented by unique integer identifiers, GQuarks. */
+
+typedef GQuark LttvAttributeName;
+
+typedef enum _LttvAttributeType {
+ LTTV_INT, LTTV_UINT, LTTV_LONG, LTTV_ULONG, LTTV_FLOAT, LTTV_DOUBLE,
+ LTTV_TIME, LTTV_POINTER, LTTV_STRING, LTTV_GOBJECT, LTTV_NONE
+} LttvAttributeType;
+
+typedef union LttvAttributeValue {
+ int *v_int;
+ unsigned *v_uint;
+ long *v_long;
+ unsigned long *v_ulong;
+ float *v_float;
+ double *v_double;
+ LttTime *v_time;
+ gpointer *v_pointer;
+ char **v_string;
+ GObject **v_gobject;
+} LttvAttributeValue;
+
+
+/* GObject interface type macros */
+
+#define LTTV_IATTRIBUTE_TYPE (lttv_iattribute_get_type ())
+#define LTTV_IATTRIBUTE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LTTV_IATTRIBUTE_TYPE, LttvIAttribute))
+#define LTTV_IATTRIBUTE_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST ((vtable), LTTV_IATTRIBUTE_TYPE, LttvIAttributeClass))
+#define LTTV_IS_IATTRIBUTE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LTTV_IATTRIBUTE_TYPE))
+#define LTTV_IS_IATTRIBUTE_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), LTTV_IATTRIBUTE_TYPE))
+#define LTTV_IATTRIBUTE_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), LTTV_IATTRIBUTE_TYPE, LttvIAttributeClass))
+
+
+typedef struct _LttvIattribute LttvIAttribute; /* dummy object */
+typedef struct _LttvIAttributeClass LttvIAttributeClass;
+
+
+struct _LttvIAttributeClass {
+ GTypeInterface parent;
+
+ unsigned int (*get_number) (LttvIAttribute *self);
+
+ gboolean (*named) (LttvIAttribute *self, gboolean *homogeneous);
+
+ LttvAttributeType (*get) (LttvIAttribute *self, unsigned i,
+ LttvAttributeName *name, LttvAttributeValue *v);
+
+ LttvAttributeType (*get_by_name) (LttvIAttribute *self,
+ LttvAttributeName name, LttvAttributeValue *v);
+
+ LttvAttributeValue (*add) (LttvIAttribute *self, LttvAttributeName name,
+ LttvAttributeType t);
+
+ void (*remove) (LttvIAttribute *self, unsigned i);
+
+ void (*remove_by_name) (LttvIAttribute *self,
+ LttvAttributeName name);
+
+ LttvIAttribute* (*find_subdir) (LttvIAttribute *self,
+ LttvAttributeName name);
+};
+
+
+GType lttv_iattribute_get_type(void);
+
+
+/* Total number of attributes */
+
+unsigned int lttv_iattribute_get_number(LttvIAttribute *self);
+
+
+/* Container type. Named (fields in struct or elements in a hash table)
+ or unnamed (elements in an array) attributes, homogeneous type or not. */
+
+gboolean lttv_iattribute_named(LttvIAttribute *self, gboolean *homogeneous);
+
+
+/* Get the i th attribute along with its type and a pointer to its value. */
+
+LttvAttributeType lttv_iattribute_get(LttvIAttribute *self, unsigned i,
+ LttvAttributeName *name, LttvAttributeValue *v);
+
+
+/* Get the named attribute in the table along with its type and a pointer to
+ its value. If the named attribute does not exist, the type is LTTV_NONE. */
+
+LttvAttributeType lttv_iattribute_get_by_name(LttvIAttribute *self,
+ LttvAttributeName name, LttvAttributeValue *v);
+
+
+/* Add an attribute, which must not exist. The name is an empty string for
+ containers with unnamed attributes. Its value is initialized to 0 or NULL
+ and its pointer returned. */
+
+LttvAttributeValue lttv_iattribute_add(LttvIAttribute *self,
+ LttvAttributeName name, LttvAttributeType t);
+
+
+/* Remove an attribute */
+
+void lttv_iattribute_remove(LttvIAttribute *self, unsigned i);
+
+void lttv_iattribute_remove_by_name(LttvIAttribute *self,
+ LttvAttributeName name);
+
+
+/* Create an empty iattribute object and add it as an attribute under the
+ specified name, or return an existing iattribute attribute. If an
+ attribute of that name already exists but is not a GObject supporting the
+ iattribute interface, return NULL. */
+
+LttvIAttribute* lttv_iattribute_find_subdir(LttvIAttribute *self,
+ LttvAttributeName name);
+
+
+/* The remaining utility functions are not part of the LttvIAttribute
+ interface but operate on objects implementing it. */
+
+/* Find the named attribute in the table, which must be of the specified type.
+ If it does not exist, it is created with a default value of 0 (NULL for
+ pointer types). Since the address of the value is obtained, it may be
+ changed easily afterwards. The function returns false when the attribute
+ exists but is of incorrect type. */
+
+gboolean lttv_iattribute_find(LttvIAttribute *self, LttvAttributeName name,
+ LttvAttributeType t, LttvAttributeValue *v);
+
+
+/* Trees of attribute tables may be accessed using a hierarchical path with
+ components separated by /, like in filesystems */
+
+gboolean lttv_iattribute_find_by_path(LttvIAttribute *self, char *path,
+ LttvAttributeType t, LttvAttributeValue *v);
+
+
+/* Shallow and deep copies */
+
+void lttv_iattribute_copy_value(LttvAttributeType t, LttvAttributeValue dest,
+ LttvAttributeValue src);
+
+LttvIAttribute *lttv_iattribute_shallow_copy(LttvIAttribute *self);
+
+LttvIAttribute *lttv_iattribute_deep_copy(LttvIAttribute *self);
+
+#endif // IATTRIBUTE_H
--- /dev/null
+/* This file is part of the Linux Trace Toolkit viewer
+ * Copyright (C) 2003-2004 Michel Dagenais
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+#ifndef LTTV_H
+#define LTTV_H
+
+#include <lttv/attribute.h>
+
+/* The modules in the visualizer communicate with the main module and
+ with each other through attributes. There is a global set of attributes */
+
+LttvAttribute *lttv_global_attributes();
+
+extern gboolean lttv_profile_memory;
+
+extern int lttv_argc;
+
+extern char **lttv_argv;
+
+/* A number of global attributes are initialized before modules are
+ loaded, for example hooks lists. More global attributes are defined
+ in individual mudules to store information or to communicate with other
+ modules (GUI windows, menus...).
+
+ The hooks lists (lttv_hooks) are initialized in the main module and may be
+ used by other modules. Each corresponds to a specific location in the main
+ module processing loop. The attribute key and typical usage for each
+ is indicated.
+
+ /hooks/options/before
+ Good place to define new command line options to be parsed.
+
+ /hooks/options/after
+ Read the values set by the command line options.
+
+ /hooks/main/before
+
+ /hooks/main/after
+
+*/
+
+#define g_info(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, format)
+#define g_debug(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, format)
+
+#endif // LTTV_H
--- /dev/null
+/* This file is part of the Linux Trace Toolkit viewer
+ * Copyright (C) 2003-2004 Michel Dagenais
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+
+#include <lttv/hook.h>
+#include <lttv/module.h>
+#include <lttv/lttv.h>
+#include <lttv/iattribute.h>
+#include <lttv/attribute.h>
+#include <lttv/option.h>
+#include <lttv/traceset.h>
+#include <ltt/trace.h>
+#include <stdio.h>
+
+
+/* The main program maintains a few central data structures and relies
+ on modules for the rest. These data structures may be accessed by modules
+ through an exported API */
+
+static LttvIAttribute *attributes;
+
+static LttvHooks
+ *before_options,
+ *after_options,
+ *before_main,
+ *after_main;
+
+static char
+ *a_module,
+ *a_module_path;
+
+static gboolean
+ a_verbose,
+ a_debug;
+
+gboolean lttv_profile_memory;
+
+int lttv_argc;
+
+char **lttv_argv;
+
+static void lttv_module_option(void *hook_data);
+
+static void lttv_module_path_option(void *hook_data);
+
+static void lttv_verbose(void *hook_data);
+
+static void lttv_debug(void *hook_data);
+
+static void lttv_help(void *hook_data);
+
+/* This is the handler to specify when we dont need all the debugging
+ messages. It receives the message and does nothing. */
+
+void ignore_and_drop_message(const gchar *log_domain, GLogLevelFlags log_level,
+ const gchar *message, gpointer user_data) {
+}
+
+
+/* Since everything is done in modules, the main program only takes care
+ of the infrastructure. */
+
+int main(int argc, char **argv) {
+
+ int i;
+
+ char
+ *profile_memory_short_option = "-M",
+ *profile_memory_long_option = "--memory";
+
+ gboolean profile_memory = FALSE;
+
+ LttvAttributeValue value;
+
+ lttv_argc = argc;
+ lttv_argv = argv;
+
+ /* Before anything else, check if memory profiling is requested */
+
+ for(i = 1 ; i < argc ; i++) {
+ if(*(argv[i]) != '-') break;
+ if(strcmp(argv[i], profile_memory_short_option) == 0 ||
+ strcmp(argv[i], profile_memory_long_option) == 0) {
+ g_mem_set_vtable(glib_mem_profiler_table);
+ g_message("Memory summary before main");
+ g_mem_profile();
+ profile_memory = TRUE;
+ break;
+ }
+ }
+
+
+ /* Initialize glib and by default ignore info and debug messages */
+
+ g_type_init();
+ //g_type_init_with_debug_flags (G_TYPE_DEBUG_OBJECTS | G_TYPE_DEBUG_SIGNALS);
+ g_log_set_handler(NULL, G_LOG_LEVEL_INFO, ignore_and_drop_message, NULL);
+ g_log_set_handler(NULL, G_LOG_LEVEL_DEBUG, ignore_and_drop_message, NULL);
+
+
+ /* Have an attributes subtree to store hooks to be registered by modules. */
+
+ attributes = LTTV_IATTRIBUTE(g_object_new(LTTV_ATTRIBUTE_TYPE, NULL));
+
+ before_options = lttv_hooks_new();
+ after_options = lttv_hooks_new();
+ before_main = lttv_hooks_new();
+ after_main = lttv_hooks_new();
+
+
+ /* Create a number of hooks lists */
+
+ g_assert(lttv_iattribute_find_by_path(attributes, "hooks/options/before",
+ LTTV_POINTER, &value));
+ *(value.v_pointer) = before_options;
+ g_assert(lttv_iattribute_find_by_path(attributes, "hooks/options/after",
+ LTTV_POINTER, &value));
+ *(value.v_pointer) = after_options;
+ g_assert(lttv_iattribute_find_by_path(attributes, "hooks/main/before",
+ LTTV_POINTER, &value));
+ *(value.v_pointer) = before_main;
+ g_assert(lttv_iattribute_find_by_path(attributes, "hooks/main/after",
+ LTTV_POINTER, &value));
+ *(value.v_pointer) = after_main;
+
+
+ /* Initialize the command line options processing */
+
+ GError *error = NULL;
+
+ LttvModule *module_module = lttv_module_require("module", &error);
+ if(error != NULL) g_error(error->message);
+ LttvModule *module_option = lttv_module_require("option", &error);
+ if(error != NULL) g_error(error->message);
+
+ /* Initialize the module loading */
+
+ lttv_library_path_add(PACKAGE_PLUGIN_DIR);
+
+
+ /* Add some built-in options */
+
+ lttv_option_add("module",'m', "load a module", "name of module to load",
+ LTTV_OPT_STRING, &a_module, lttv_module_option, NULL);
+
+ lttv_option_add("modules-path", 'L',
+ "add a directory to the module search path",
+ "directory to add to the path", LTTV_OPT_STRING, &a_module_path,
+ lttv_module_path_option, NULL);
+
+ lttv_option_add("help",'h', "basic help", "none",
+ LTTV_OPT_NONE, NULL, lttv_help, NULL);
+
+ a_verbose = FALSE;
+ lttv_option_add("verbose",'v', "print information messages", "none",
+ LTTV_OPT_NONE, NULL, lttv_verbose, NULL);
+
+ a_debug = FALSE;
+ lttv_option_add("debug",'d', "print debugging messages", "none",
+ LTTV_OPT_NONE, NULL, lttv_debug, NULL);
+
+ lttv_profile_memory = FALSE;
+ lttv_option_add(profile_memory_long_option + 2,
+ profile_memory_short_option[1], "print memory information", "none",
+ LTTV_OPT_NONE, <tv_profile_memory, NULL, NULL);
+
+
+ /* Process the options */
+
+ lttv_hooks_call(before_options, NULL);
+ lttv_option_parse(argc, argv);
+ lttv_hooks_call(after_options, NULL);
+
+
+ /* Memory profiling to be useful must be activated as early as possible */
+
+ if(profile_memory != lttv_profile_memory)
+ g_error("Memory profiling options must appear before other options");
+
+
+ /* Do the main work */
+
+ lttv_hooks_call(before_main, NULL);
+ lttv_hooks_call(after_main, NULL);
+
+
+ /* Clean up everything */
+
+ lttv_module_release(module_option);
+ lttv_module_release(module_module);
+
+ lttv_hooks_destroy(before_options);
+ lttv_hooks_destroy(after_options);
+ lttv_hooks_destroy(before_main);
+ lttv_hooks_destroy(after_main);
+ g_object_unref(attributes);
+
+ if(profile_memory) {
+ g_message("Memory summary after main");
+ g_mem_profile();
+ }
+ return 0;
+}
+
+
+LttvAttribute *lttv_global_attributes()
+{
+ return (LttvAttribute*)attributes;
+}
+
+
+void lttv_module_option(void *hook_data)
+{
+ GError *error = NULL;
+
+ lttv_module_require(a_module, &error);
+ if(error != NULL) g_error(error->message);
+}
+
+
+void lttv_module_path_option(void *hook_data)
+{
+ lttv_library_path_add(a_module_path);
+}
+
+
+void lttv_verbose(void *hook_data)
+{
+ g_log_set_handler(NULL, G_LOG_LEVEL_INFO, g_log_default_handler, NULL);
+ g_info("Logging set to include INFO level messages");
+}
+
+void lttv_debug(void *hook_data)
+{
+ g_log_set_handler(NULL, G_LOG_LEVEL_DEBUG, g_log_default_handler, NULL);
+ g_info("Logging set to include DEBUG level messages");
+}
+
+void lttv_help(void *hook_data)
+{
+ printf("Linux Trace Toolkit Visualizer\n");
+ printf("\n");
+ lttv_option_show_help();
+ printf("\n");
+}
+
+/*
+
+- Define formally traceset/trace in the GUI for the user and decide how
+ trace/traceset sharing goes in the application.
+
+- Use appropriately the new functions in time.h
+
+- remove the separate tracefiles (control/per cpu) arrays/loops in context.
+
+- split processTrace into context.c and processTrace.c
+
+- check spelling conventions.
+
+- get all the copyright notices.
+
+- remove all the warnings.
+
+- get all the .h files properly doxygen commented to produce useful documents.
+
+- have an intro/architecture document.
+
+- write a tutorial */
--- /dev/null
+
+/* This file is part of the Linux Trace Toolkit viewer
+ * Copyright (C) 2003-2004 Michel Dagenais
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+
+/* module.c : Implementation of the module loading/unloading mechanism. */
+
+#include <lttv/module.h>
+#include <gmodule.h>
+
+
+struct _LttvLibrary
+{
+ LttvLibraryInfo info;
+ GPtrArray *modules;
+ GModule *gm;
+ guint locked_loaded;
+};
+
+
+struct _LttvModule
+{
+ LttvModuleInfo info;
+ char **prerequisites_names;
+ GPtrArray *prerequisites;
+};
+
+
+/* Modules are searched by name. However, a library may be loaded which
+ provides a module with the same name as an existing one. A stack of
+ modules is thus maintained for each name.
+
+ Libraries correspond to glib modules. The g_module function is
+ responsible for loading each library only once. */
+
+static GHashTable *modules_by_name = NULL;
+
+static GPtrArray *libraries = NULL;
+
+static GHashTable *libraries_by_g_module = NULL;
+
+static GPtrArray *library_paths = NULL;
+
+static gboolean initialized = FALSE;
+
+static gboolean destroyed = TRUE;
+
+static struct _LttvModuleDescription *builtin_chain = NULL;
+
+static struct _LttvModuleDescription *module_chain = NULL;
+
+static struct _LttvModuleDescription **module_next = &module_chain;
+
+static GQuark lttv_module_error;
+
+static void init();
+
+static finish_destroy();
+
+static void module_release(LttvModule *m);
+
+
+static LttvLibrary *library_add(char *name, char *path, GModule *gm)
+{
+ LttvLibrary *l;
+
+ LttvModule *m;
+
+ struct _LttvModuleDescription *link;
+
+ GPtrArray *modules;
+
+ l = g_new(LttvLibrary, 1);
+ l->modules = g_ptr_array_new();
+ l->gm = gm;
+ l->locked_loaded = 0;
+ l->info.name = g_strdup(name);
+ l->info.path = g_strdup(path);
+ l->info.load_count = 0;
+
+ g_ptr_array_add(libraries, l);
+ g_hash_table_insert(libraries_by_g_module, gm, l);
+
+ *module_next = NULL;
+ for(link = module_chain; link != NULL; link = link->next) {
+ m = g_new(LttvModule, 1);
+ g_ptr_array_add(l->modules, m);
+
+ modules = g_hash_table_lookup(modules_by_name, link->name);
+ if(modules == NULL) {
+ modules = g_ptr_array_new();
+ g_hash_table_insert(modules_by_name, g_strdup(link->name), modules);
+ }
+ g_ptr_array_add(modules, m);
+
+ m->prerequisites_names = link->prerequisites;
+ m->prerequisites = g_ptr_array_new();
+ m->info.name = link->name;
+ m->info.short_description = link->short_description;
+ m->info.description = link->description;
+ m->info.init = link->init;
+ m->info.destroy = link->destroy;
+ m->info.library = l;
+ m->info.require_count = 0;
+ m->info.use_count = 0;
+ m->info.prerequisites_number = link->prerequisites_number;
+ }
+ return l;
+}
+
+
+static void library_remove(LttvLibrary *l)
+{
+ LttvModule *m;
+
+ GPtrArray *modules;
+
+ guint i;
+
+ char *key;
+
+ for(i = 0 ; i < l->modules->len ; i++) {
+ m = (LttvModule *)(l->modules->pdata[i]);
+
+ g_hash_table_lookup_extended(modules_by_name, m->info.name,
+ (gpointer *)&key, (gpointer *)&modules);
+ g_assert(modules != NULL);
+ g_ptr_array_remove(modules, m);
+ if(modules->len == 0) {
+ g_hash_table_remove(modules_by_name, m->info.name);
+ g_ptr_array_free(modules, TRUE);
+ g_free(key);
+ }
+
+ g_ptr_array_free(m->prerequisites, TRUE);
+ g_free(m);
+ }
+
+ g_ptr_array_remove(libraries, l);
+ g_hash_table_remove(libraries_by_g_module, l->gm);
+ g_ptr_array_free(l->modules, TRUE);
+ g_free(l->info.name);
+ g_free(l->info.path);
+ g_free(l);
+}
+
+
+static LttvLibrary *library_load(char *name, GError **error)
+{
+ GModule *gm;
+
+ int i, nb;
+
+ char *path, *pathname;
+
+ LttvLibrary *l;
+
+ GString *messages = g_string_new("");
+
+ /* insure that module.c is initialized */
+
+ init();
+
+ /* Try to find the library along all the user specified paths */
+
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Load library %s", name);
+ nb = lttv_library_path_number();
+ for(i = 0 ; i <= nb ; i++) {
+ if(i < nb) path = lttv_library_path_get(i);
+ else path = NULL;
+
+ pathname = g_module_build_path(path ,name);
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Try path %s", pathname);
+ module_chain = NULL;
+ module_next = &module_chain;
+ gm = g_module_open(pathname,0);
+ g_free(pathname);
+
+ if(gm != NULL) break;
+
+ g_string_append(messages, g_module_error());
+ g_string_append(messages, "\n");
+ g_log(G_LOG_DOMAIN,G_LOG_LEVEL_INFO,"Trial failed, %s", g_module_error());
+ }
+
+ /* Module cannot be found */
+
+ if(gm == NULL) {
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Failed to load %s", name);
+ g_set_error(error, lttv_module_error, LTTV_MODULE_NOT_FOUND,
+ "Cannot load library %s: %s", name, messages->str);
+ g_string_free(messages, TRUE);
+ return NULL;
+ }
+ g_string_free(messages, TRUE);
+
+ /* Check if the library was already loaded */
+
+ l = g_hash_table_lookup(libraries_by_g_module, gm);
+
+ /* This library was not already loaded */
+
+ if(l == NULL) {
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Library %s (%s) loaded", name,
+ g_module_name(gm));
+ l = library_add(name, path, gm);
+ }
+ return l;
+}
+
+
+LttvLibrary *lttv_library_load(char *name, GError **error)
+{
+ LttvLibrary *l = library_load(name, error);
+ l->info.load_count++;
+ return l;
+}
+
+
+static void library_unload(LttvLibrary *l)
+{
+ guint i, len;
+
+ GModule *gm;
+
+ LttvModule *m;
+
+ if(l->locked_loaded > 0) {
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Unload library %s: locked loaded",
+ l->info.name);
+ return;
+ }
+
+ if(l->info.load_count > 0) {
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Unload library %s: load count %d",
+ l->info.name, l->info.load_count);
+ return;
+ }
+
+ /* Check if all its modules have been released */
+
+ for(i = 0 ; i < l->modules->len ; i++) {
+ m = (LttvModule *)(l->modules->pdata[i]);
+ if(m->info.use_count > 0) {
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO,"Unload library %s: module %s used",
+ l->info.name, m->info.name);
+ return;
+ }
+ }
+
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Unload library %s: close the GModule",
+ l->info.name);
+ gm = l->gm;
+ library_remove(l);
+ if(gm != NULL) g_module_close(gm);
+
+ /* insure that module.c will be finalized */
+
+ finish_destroy();
+}
+
+
+void lttv_library_unload(LttvLibrary *l)
+{
+ l->info.load_count--;
+ library_unload(l);
+}
+
+
+static void library_lock_loaded(LttvLibrary *l)
+{
+ l->locked_loaded++;
+}
+
+
+static void library_unlock_loaded(LttvLibrary *l)
+{
+ l->locked_loaded--;
+ library_unload(l);
+}
+
+
+static LttvModule *module_require(char *name, GError **error)
+{
+ GError *tmp_error = NULL;
+
+ guint i, j;
+
+ LttvModule *m, *required;
+
+ LttvLibrary *l = NULL;
+
+ GPtrArray *modules;
+
+ /* Insure that module.c is initialized */
+
+ init();
+
+ /* Check if the module is already loaded */
+
+ modules = g_hash_table_lookup(modules_by_name, name);
+
+ /* Try to load a library having the module name */
+
+ if(modules == NULL) {
+ l = library_load(name, error);
+ if(l == NULL) return NULL;
+ else library_lock_loaded(l);
+
+ /* A library was found, does it contain the named module */
+
+ modules = g_hash_table_lookup(modules_by_name, name);
+ if(modules == NULL) {
+ g_set_error(error, lttv_module_error, LTTV_MODULE_NOT_FOUND,
+ "Module %s not found in library %s", name, l->info.name);
+ library_unlock_loaded(l);
+ return NULL;
+ }
+ }
+ m = (LttvModule *)(modules->pdata[modules->len - 1]);
+
+ /* We have the module */
+
+ m->info.use_count++;
+
+ /* First use of the module. Initialize after getting the prerequisites */
+
+ if(m->info.use_count == 1) {
+ for(i = 0 ; i < m->info.prerequisites_number ; i++) {
+ required = module_require(m->prerequisites_names[i], &tmp_error);
+
+ /* A prerequisite could not be found, undo everything and fail */
+
+ if(required == NULL) {
+ for(j = 0 ; j < m->prerequisites->len ; j++) {
+ module_release((LttvModule *)(m->prerequisites->pdata[j]));
+ }
+ g_ptr_array_set_size(m->prerequisites, 0);
+ if(l != NULL) library_unlock_loaded(l);
+ g_set_error(error, lttv_module_error, LTTV_MODULE_NOT_FOUND,
+ "Cannot find prerequisite for module %s: %s", name,
+ tmp_error->message);
+ g_clear_error(&tmp_error);
+ return NULL;
+ }
+ g_ptr_array_add(m->prerequisites, required);
+ }
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Module %s: init()", m->info.name);
+ m->info.init();
+ }
+
+ /* Decrement the load count of the library. It will not really be
+ unloaded since it contains a currently used module. */
+
+ if(l != NULL) library_unlock_loaded(l);
+
+ return(m);
+}
+
+
+/* The require_count for a module is the number of explicit calls to
+ lttv_module_require, while the use_count also counts the number of times
+ a module is needed as a prerequisite. */
+
+LttvModule *lttv_module_require(char *name, GError **error)
+{
+ LttvModule *m = module_require(name, error);
+ if(m != NULL) m->info.require_count++;
+ return(m);
+}
+
+
+static void module_release(LttvModule *m)
+{
+ guint i;
+
+ library_lock_loaded(m->info.library);
+
+ m->info.use_count--;
+ if(m->info.use_count == 0) {
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Module %s: destroy()",m->info.name);
+ m->info.destroy();
+ for(i = 0 ; i < m->prerequisites->len ; i++) {
+ module_release((LttvModule *)(m->prerequisites->pdata[i]));
+ }
+ g_ptr_array_set_size(m->prerequisites, 0);
+ }
+ library_unlock_loaded(m->info.library);
+}
+
+
+void lttv_module_release(LttvModule *m)
+{
+ m->info.require_count--;
+ module_release(m);
+}
+
+
+void lttv_module_info(LttvModule *m, LttvModuleInfo *info)
+{
+ *info = m->info;
+}
+
+
+unsigned lttv_module_prerequisite_number(LttvModule *m)
+{
+ return m->prerequisites->len;
+}
+
+
+LttvModule *lttv_module_prerequisite_get(LttvModule *m, unsigned i)
+{
+ return (LttvModule *)(m->prerequisites->pdata[i]);
+}
+
+
+void lttv_library_info(LttvLibrary *l, LttvLibraryInfo *info)
+{
+ *info = l->info;
+}
+
+
+unsigned lttv_library_module_number(LttvLibrary *l)
+{
+ return l->modules->len;
+}
+
+
+LttvModule *lttv_library_module_get(LttvLibrary *l, unsigned i)
+{
+ return (LttvModule *)(l->modules->pdata[i]);
+}
+
+
+unsigned lttv_library_number()
+{
+ return libraries->len;
+}
+
+
+LttvLibrary *lttv_library_get(unsigned i)
+{
+ return (LttvLibrary *)(libraries->pdata[i]);
+}
+
+
+void lttv_library_path_add(char *name)
+{
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Add library path %s", name);
+ g_ptr_array_add(library_paths,(char*)g_strdup(name));
+}
+
+
+void lttv_library_path_remove(char *name)
+{
+ guint i;
+
+ for(i = 0 ; i < library_paths->len ; i++) {
+ if(g_str_equal(name, library_paths->pdata[i])) {
+ g_free(library_paths->pdata[i]);
+ g_ptr_array_remove_index(library_paths,i);
+ return;
+ }
+ }
+}
+
+
+unsigned lttv_library_path_number()
+{
+ return library_paths->len;
+}
+
+
+char *lttv_library_path_get(unsigned i)
+{
+ return (char *)(library_paths->pdata[library_paths->len - i - 1]);
+}
+
+
+void lttv_module_register(struct _LttvModuleDescription *d)
+{
+ *module_next = d;
+ module_next = &(d->next);
+}
+
+
+static void init()
+{
+ if(initialized) return;
+ g_assert(destroyed);
+
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Init module.c");
+
+ initialized = TRUE;
+ destroyed = FALSE;
+ lttv_module_error = g_quark_from_string("LTTV_MODULE_ERROR");
+ modules_by_name = g_hash_table_new(g_str_hash, g_str_equal);
+ libraries = g_ptr_array_new();
+ libraries_by_g_module = g_hash_table_new(g_direct_hash, g_direct_equal);
+ library_paths = g_ptr_array_new();
+
+ if(builtin_chain == NULL) builtin_chain = module_chain;
+ module_chain = builtin_chain;
+ library_add("builtin", NULL, NULL);
+}
+
+
+static finish_destroy()
+{
+ guint i;
+
+ if(initialized) return;
+ g_assert(!destroyed);
+
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Finish destroy module.c");
+ g_hash_table_destroy(modules_by_name);
+ g_ptr_array_free(libraries, TRUE);
+ g_hash_table_destroy(libraries_by_g_module);
+ for(i = 0 ; i < library_paths->len ; i++) {
+ g_free(library_paths->pdata[i]);
+ }
+ g_ptr_array_free(library_paths, TRUE);
+ destroyed = TRUE;
+}
+
+
+static void destroy()
+{
+ guint i, j, nb;
+
+ LttvLibrary *l, **locked_libraries;
+
+ LttvModule *m;
+
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Destroy module.c");
+
+ /* Unload all libraries */
+
+ nb = libraries->len;
+ locked_libraries = g_new(LttvLibrary *, nb);
+
+ for(i = 0 ; i < nb ; i++) {
+ l = (LttvLibrary *)(libraries->pdata[i]);
+ locked_libraries[i] = l;
+ library_lock_loaded(l);
+ for(j = 0 ; j < l->modules->len ; j++) {
+ m = (LttvModule *)(l->modules->pdata[j]);
+ while(m->info.require_count > 0) lttv_module_release(m);
+ }
+ while(l->info.load_count > 0) lttv_library_unload(l);
+ }
+
+ for(i = 0 ; i < nb ; i++) {
+ l = locked_libraries[i];
+ library_unlock_loaded(l);
+ }
+ g_free(locked_libraries);
+
+ /* The library containing module.c may be locked by our caller */
+
+ g_assert(libraries->len <= 1);
+
+ initialized = FALSE;
+}
+
+LTTV_MODULE("module", "Modules in libraries", \
+ "Load libraries, list, require and initialize contained modules", \
+ init, destroy)
+
--- /dev/null
+/* This file is part of the Linux Trace Toolkit viewer
+ * Copyright (C) 2003-2004 Michel Dagenais
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+#ifndef MODULES_H
+#define MODULES_H
+
+#include <glib.h>
+
+/* A module contains some functionality which becomes available atfer it is
+ initialized and before it is destroyed. A module is characterized by a name,
+ a description (short and long), a list of names of other modules on which
+ it depends, and an initialization and a destruction function.
+
+ A library contains one or more modules and may be loaded dynamically.
+ The modules contained in a library are automatically registered through
+ constructors which are called when the library is loaded. For modules
+ directly linked with the main program (builtin), the constructors are
+ called before the main program starts. (However, neither malloc nor glib
+ functions are used during the registration process).
+
+ The library loading path is a set of directories, where requested
+ libraries and modules are searched for.
+*/
+
+typedef struct _LttvModule LttvModule;
+
+typedef struct _LttvLibrary LttvLibrary;
+
+typedef void (*LttvModuleInit)();
+
+typedef void (*LttvModuleDestroy)();
+
+typedef struct _LttvModuleInfo
+{
+ char *name;
+ char *short_description;
+ char *description;
+ LttvModuleInit init;
+ LttvModuleDestroy destroy;
+ LttvLibrary *library;
+ unsigned require_count;
+ unsigned use_count;
+ unsigned prerequisites_number;
+} LttvModuleInfo;
+
+
+typedef struct _LttvLibraryInfo
+{
+ char *name;
+ char *path;
+ unsigned load_count;
+} LttvLibraryInfo;
+
+
+typedef enum _LttvModuleError
+{
+ LTTV_MODULE_NOT_FOUND,
+ LTTV_MODULE_NO_INIT
+} LttvModuleError;
+
+
+/* Insure that a module is loaded and initialized. Require count
+ (number of times the module was required) and use count
+ (number of times required or used as prerequisite) serve to
+ insure that a module is destroyed only after it has been released
+ as many times as it was required (and prerequired).
+
+ The module is searched among the modules currently loaded, then as a
+ similarly named library to load which should contain the named module.
+ If the module cannot be found or loaded, NULL is returned and an
+ explanation is provided in error. */
+
+LttvModule *lttv_module_require(char *name, GError **error);
+
+void lttv_module_release(LttvModule *m);
+
+
+/* Obtain information about the module, including the containing library */
+
+void lttv_module_info(LttvModule *m, LttvModuleInfo *info);
+
+
+/* List the modules on which this module depends */
+
+unsigned lttv_module_prerequisite_number(LttvModule *m);
+
+LttvModule *lttv_module_prerequisite_get(LttvModule *m, unsigned i);
+
+
+/* Insure that a library is loaded. A load count insures that a library
+ is unloaded only after it has been asked to unload as
+ many times as it was loaded, and its modules are not in use. The library
+ is searched along the library path if name is a relative pathname.
+ If the library cannot be found or loaded, NULL is returned and an
+ explanation is provided in error. */
+
+LttvLibrary *lttv_library_load(char *name, GError **error);
+
+void lttv_library_unload(LttvLibrary *l);
+
+
+/* Obtain information about the library */
+
+void lttv_library_info(LttvLibrary *l, LttvLibraryInfo *info);
+
+
+/* List the modules contained in a library */
+
+unsigned lttv_library_module_number(LttvLibrary *l);
+
+LttvModule *lttv_library_module_get(LttvLibrary *l, unsigned i);
+
+
+/* List the currently loaded libraries */
+
+unsigned lttv_library_number();
+
+LttvLibrary *lttv_library_get(unsigned i);
+
+
+
+/* Add or remove directory names to the library search path */
+
+void lttv_library_path_add(char *name);
+
+void lttv_library_path_remove(char *name);
+
+
+/* List the directory names in the library search path */
+
+unsigned lttv_library_path_number();
+
+char *lttv_library_path_get(unsigned i);
+
+
+/* To define a module, simply call the LTTV_MODULE macro with the needed
+ arguments: single word name, one line short description, larger
+ description, initialization function, destruction function, and
+ list of names for required modules (e.g., "moduleA", "moduleB").
+ This will insure that the module is registered at library load time.
+
+ Example:
+
+ LTTV_MODULE("option", "Command line options processing", "...", \
+ init, destroy, "moduleA", "moduleB")
+*/
+
+#define LTTV_MODULE(name, short_desc, desc, init, destroy, ...) \
+ \
+ static void _LTTV_MODULE_REGISTER(__LINE__)() \
+ __attribute__((constructor)); \
+ \
+ static void _LTTV_MODULE_REGISTER(__LINE__)() \
+ { \
+ static char *module_prerequisites[] = { __VA_ARGS__ }; \
+ \
+ static struct _LttvModuleDescription module = { \
+ name, short_desc, desc, init, destroy, \
+ sizeof(module_prerequisites) / sizeof(char *), \
+ module_prerequisites, NULL}; \
+ \
+ lttv_module_register(&module); \
+ }
+
+
+/* Internal structure and function used to register modules, called by
+ LTTV_MODULE */
+
+#define __LTTV_MODULE_REGISTER(line) _lttv_module_register_ ## line
+#define _LTTV_MODULE_REGISTER(line) __LTTV_MODULE_REGISTER(line)
+
+struct _LttvModuleDescription
+{
+ char *name;
+ char *short_description;
+ char *description;
+ LttvModuleInit init;
+ LttvModuleDestroy destroy;
+ unsigned prerequisites_number;
+ char **prerequisites;
+ struct _LttvModuleDescription *next;
+};
+
+void lttv_module_register(struct _LttvModuleDescription *d);
+
+#endif // MODULES_H
+
+
+
+
+
+
--- /dev/null
+/* This file is part of the Linux Trace Toolkit viewer
+ * Copyright (C) 2003-2004 Michel Dagenais
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+
+#include <popt.h>
+#include <glib.h>
+#include <lttv/module.h>
+#include <lttv/option.h>
+
+typedef struct _LttvOption {
+ char *long_name;
+ char char_name;
+ char *description;
+ char *arg_description;
+ LttvOptionType t;
+ gpointer p;
+ LttvOptionHook hook;
+ gpointer hook_data;
+} LttvOption;
+
+GHashTable *options;
+
+
+static void
+list_options(gpointer key, gpointer value, gpointer user_data)
+{
+ g_ptr_array_add((GPtrArray *)user_data, value);
+}
+
+
+static void
+free_option(LttvOption *option)
+{
+ g_free(option->long_name);
+ g_free(option->description);
+ g_free(option->arg_description);
+ g_free(option);
+}
+
+
+void lttv_option_add(const char *long_name, const char char_name,
+ const char *description, const char *arg_description,
+ const LttvOptionType t, void *p,
+ const LttvOptionHook h, void *hook_data)
+{
+ LttvOption *option;
+
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Add option %s", long_name);
+ if(g_hash_table_lookup(options, long_name) != NULL) {
+ g_warning("duplicate option");
+ return;
+ }
+
+ option = g_new(LttvOption, 1);
+ option->long_name = g_strdup(long_name);
+ option->char_name = char_name;
+ option->description = g_strdup(description);
+ option->arg_description = g_strdup(arg_description);
+ option->t = t;
+ option->p = p;
+ option->hook = h;
+ option->hook_data = hook_data;
+ g_hash_table_insert(options, option->long_name, option);
+}
+
+
+void
+lttv_option_remove(const char *long_name)
+{
+ LttvOption *option = g_hash_table_lookup(options, long_name);
+
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Remove option %s", long_name);
+ if(option == NULL) {
+ g_warning("trying to remove unknown option %s", long_name);
+ return;
+ }
+ g_hash_table_remove(options, long_name);
+ free_option(option);
+}
+
+
+static int poptToLTT[] = {
+ POPT_ARG_NONE, POPT_ARG_STRING, POPT_ARG_INT, POPT_ARG_LONG
+};
+
+static struct poptOption endOption = { NULL, '\0', 0, NULL, 0};
+
+
+static void
+build_popts(GPtrArray **plist, struct poptOption **ppopts, poptContext *pc,
+ int argc, char **argv)
+{
+ LttvOption *option;
+
+ GPtrArray *list;
+
+ struct poptOption *popts;
+
+ poptContext c;
+
+ guint i;
+
+ list = g_ptr_array_new();
+
+ g_hash_table_foreach(options, list_options, list);
+
+ /* Build a popt options array from our list */
+
+ popts = g_new(struct poptOption, list->len + 1);
+
+ for(i = 0 ; i < list->len ; i++) {
+ option = (LttvOption *)list->pdata[i];
+ popts[i].longName = option->long_name;
+ popts[i].shortName = option->char_name;
+ popts[i].descrip = option->description;
+ popts[i].argDescrip = option->arg_description;
+ popts[i].argInfo = poptToLTT[option->t];
+ popts[i].arg = option->p;
+ popts[i].val = i + 1;
+ }
+
+ /* Terminate the array for popt and create the context */
+
+ popts[list->len] = endOption;
+ c = poptGetContext(argv[0], argc, (const char**)argv, popts, 0);
+
+ *plist = list;
+ *ppopts = popts;
+ *pc = c;
+}
+
+
+static void
+destroy_popts(GPtrArray **plist, struct poptOption **ppopts, poptContext *pc)
+{
+ g_ptr_array_free(*plist, TRUE); *plist = NULL;
+ g_free(*ppopts); *ppopts = NULL;
+ poptFreeContext(*pc);
+}
+
+
+void lttv_option_parse(int argc, char **argv)
+{
+ GPtrArray *list;
+
+ LttvOption *option;
+
+ int i, rc, first_arg;
+
+ struct poptOption *popts;
+
+ poptContext c;
+
+ i = 0;
+
+ first_arg = 0;
+
+ build_popts(&list, &popts, &c, argc, argv);
+
+ /* Parse options while not end of options event */
+
+ while((rc = poptGetNextOpt(c)) != -1) {
+
+ /* The option was recognized and the rc value returned is the argument
+ position in the array. Call the associated hook if present. */
+
+ if(rc > 0) {
+ option = (LttvOption *)(list->pdata[rc - 1]);
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Option %s encountered",
+ option->long_name);
+ if(option->hook != NULL) {
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Option %s hook called",
+ option->long_name);
+ option->hook(option->hook_data);
+ }
+ i++;
+ }
+
+ else if(rc == POPT_ERROR_BADOPT && i != first_arg) {
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,
+ "Option %s not recognized, rescan options with new additions",
+ poptBadOption(c,0));
+
+ /* Perhaps this option is newly added, restart parsing */
+
+ destroy_popts(&list, &popts, &c);
+ build_popts(&list, &popts, &c, argc, argv);
+
+ /* Get back to the same argument */
+
+ first_arg = i;
+ for(i = 0; i < first_arg; i++) {
+ rc = poptGetNextOpt(c);
+ option = (LttvOption *)(list->pdata[rc - 1]);
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Option %s rescanned, skipped",
+ option->long_name);
+ }
+ }
+
+ else {
+
+ /* The option has some error and it is not because this is a newly
+ added option not recognized. */
+
+ g_error("option %s: %s", poptBadOption(c,0), poptStrerror(rc));
+ break;
+ }
+
+ }
+
+ destroy_popts(&list, &popts, &c);
+}
+
+/* CHECK */
+static void show_help(LttvOption *option)
+{
+ printf("--%s -%c argument: %s\n" , option->long_name,
+ option->char_name,
+ option->arg_description);
+ printf(" %s\n" , option->description);
+
+}
+
+void lttv_option_show_help(void)
+{
+ LttvOption option;
+
+ GPtrArray *list = g_ptr_array_new();
+
+ int i;
+
+ g_hash_table_foreach(options, list_options, list);
+
+ printf("Built-in commands available:\n");
+ printf("\n");
+
+ for(i = 0 ; i < list->len ; i++) {
+ show_help((LttvOption *)list->pdata[i]);
+ }
+ g_ptr_array_free(list, TRUE);
+
+
+}
+
+static void init()
+{
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Init option.c");
+ options = g_hash_table_new(g_str_hash, g_str_equal);
+}
+
+
+static void destroy()
+{
+ LttvOption option;
+
+ GPtrArray *list = g_ptr_array_new();
+
+ int i;
+
+ g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Destroy option.c");
+ g_hash_table_foreach(options, list_options, list);
+ g_hash_table_destroy(options);
+
+ for(i = 0 ; i < list->len ; i++) {
+ free_option((LttvOption *)list->pdata[i]);
+ }
+ g_ptr_array_free(list, TRUE);
+}
+
+LTTV_MODULE("option", "Command line options processing", \
+ "Functions to add, remove and parse command line options", \
+ init, destroy)
--- /dev/null
+/* This file is part of the Linux Trace Toolkit viewer
+ * Copyright (C) 2003-2004 Michel Dagenais
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+#ifndef OPTION_H
+#define OPTION_H
+
+/* Define a new option with a long name (--long_name), a short
+ one character name (-c), a descriptive text, the argument type, and a
+ pointer to where the argument value will be stored. For an option of
+ type LTTV_OPT_NONE, the argument is a boolean value set to true when the
+ option is present. The option hook is called if non NULL. */
+
+typedef enum _LttvOptionType
+{LTTV_OPT_NONE, LTTV_OPT_STRING, LTTV_OPT_INT, LTTV_OPT_LONG }
+LttvOptionType;
+
+typedef void (*LttvOptionHook)(void *hook_data);
+
+void lttv_option_add(const char *long_name, const char char_name,
+ const char *description, const char *arg_description,
+ const LttvOptionType t, void *p,
+ const LttvOptionHook h, void *hook_data);
+
+
+/* Remove an option */
+
+void lttv_option_remove(const char *long_name);
+
+
+/* Parse command line options. It is possible to add options (through the
+ hooks being called) while the parsing is done. The new options will be
+ used for subsequent command line arguments. */
+
+void lttv_option_parse(int argc, char **argv);
+
+void lttv_option_show_help(void);
+
+#endif // OPTION_H
--- /dev/null
+/* This file is part of the Linux Trace Toolkit viewer
+ * Copyright (C) 2003-2004 Michel Dagenais
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+
+#include <lttv/tracecontext.h>
+#include <ltt/event.h>
+#include <ltt/facility.h>
+#include <ltt/trace.h>
+#include <ltt/type.h>
+
+void lttv_context_init(LttvTracesetContext *self, LttvTraceset *ts)
+{
+ LTTV_TRACESET_CONTEXT_GET_CLASS(self)->init(self, ts);
+}
+
+
+void lttv_context_fini(LttvTracesetContext *self)
+{
+ LTTV_TRACESET_CONTEXT_GET_CLASS(self)->fini(self);
+}
+
+
+LttvTracesetContext *
+lttv_context_new_traceset_context(LttvTracesetContext *self)
+{
+ return LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_traceset_context(self);
+}
+
+
+
+
+LttvTraceContext *
+lttv_context_new_trace_context(LttvTracesetContext *self)
+{
+ return LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_trace_context(self);
+}
+
+
+LttvTracefileContext *
+lttv_context_new_tracefile_context(LttvTracesetContext *self)
+{
+ return LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_tracefile_context(self);
+}
+
+/****************************************************************************
+ * lttv_traceset_context_compute_time_span
+ *
+ * Keep the Time_Span is sync with on the fly addition and removal of traces
+ * in a trace set. It must be called each time a trace is added/removed from
+ * the traceset. It could be more efficient to call it only once a bunch
+ * of traces are loaded, but the calculation is not long, so it's not
+ * critical.
+ *
+ * Author : Xang Xiu Yang
+ * Imported from gtkTraceSet.c by Mathieu Desnoyers
+ ***************************************************************************/
+static void lttv_traceset_context_compute_time_span(
+ LttvTracesetContext *self,
+ TimeInterval *Time_Span)
+{
+ LttvTraceset * traceset = self->ts;
+ int numTraces = lttv_traceset_number(traceset);
+ int i;
+ LttTime s, e;
+ LttvTraceContext *tc;
+ LttTrace * trace;
+
+ Time_Span->startTime.tv_sec = 0;
+ Time_Span->startTime.tv_nsec = 0;
+ Time_Span->endTime.tv_sec = 0;
+ Time_Span->endTime.tv_nsec = 0;
+
+ for(i=0; i<numTraces;i++){
+ tc = self->traces[i];
+ trace = tc->t;
+
+ ltt_trace_time_span_get(trace, &s, &e);
+
+ if(i==0){
+ Time_Span->startTime = s;
+ Time_Span->endTime = e;
+ }else{
+ if(s.tv_sec < Time_Span->startTime.tv_sec ||
+ (s.tv_sec == Time_Span->startTime.tv_sec
+ && s.tv_nsec < Time_Span->startTime.tv_nsec))
+ Time_Span->startTime = s;
+ if(e.tv_sec > Time_Span->endTime.tv_sec ||
+ (e.tv_sec == Time_Span->endTime.tv_sec &&
+ e.tv_nsec > Time_Span->endTime.tv_nsec))
+ Time_Span->endTime = e;
+ }
+ }
+}
+
+
+static void
+init(LttvTracesetContext *self, LttvTraceset *ts)
+{
+ guint i, j, nb_trace, nb_control, nb_per_cpu, nb_tracefile;
+
+ LttvTraceContext *tc;
+
+ LttvTracefileContext *tfc;
+
+ LttTime null_time = {0, 0};
+
+ nb_trace = lttv_traceset_number(ts);
+ self->ts = ts;
+ self->traces = g_new(LttvTraceContext *, nb_trace);
+ self->before = lttv_hooks_new();
+ self->after = lttv_hooks_new();
+ self->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
+ self->ts_a = lttv_traceset_attribute(ts);
+ for(i = 0 ; i < nb_trace ; i++) {
+ tc = LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_trace_context(self);
+ self->traces[i] = tc;
+
+ tc->ts_context = self;
+ tc->index = i;
+ tc->vt = lttv_traceset_get(ts, i);
+ tc->t = lttv_trace(tc->vt);
+ tc->check = lttv_hooks_new();
+ tc->before = lttv_hooks_new();
+ tc->after = lttv_hooks_new();
+ tc->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
+ tc->t_a = lttv_trace_attribute(tc->vt);
+ nb_control = ltt_trace_control_tracefile_number(tc->t);
+ nb_per_cpu = ltt_trace_per_cpu_tracefile_number(tc->t);
+ nb_tracefile = nb_control + nb_per_cpu;
+ tc->tracefiles = g_new(LttvTracefileContext *, nb_tracefile);
+
+ for(j = 0 ; j < nb_tracefile ; j++) {
+ tfc = LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_tracefile_context(self);
+ tc->tracefiles[j] = tfc;
+ tfc->index = j;
+
+ if(j < nb_control) {
+ tfc->control = TRUE;
+ tfc->tf = ltt_trace_control_tracefile_get(tc->t, j);
+ }
+ else {
+ tfc->control = FALSE;
+ tfc->tf = ltt_trace_per_cpu_tracefile_get(tc->t, j - nb_control);
+ }
+ tfc->t_context = tc;
+ tfc->check = lttv_hooks_new();
+ tfc->before = lttv_hooks_new();
+ tfc->after = lttv_hooks_new();
+ tfc->check_event = lttv_hooks_new();
+ tfc->before_event = lttv_hooks_new();
+ tfc->before_event_by_id = lttv_hooks_by_id_new();
+ tfc->after_event = lttv_hooks_new();
+ tfc->after_event_by_id = lttv_hooks_by_id_new();
+ tfc->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
+ }
+ }
+ lttv_process_traceset_seek_time(self, null_time);
+ /*CHECK why dynamically allocate the time span... and the casing is wroNg*/
+ self->Time_Span = g_new(TimeInterval,1);
+ lttv_traceset_context_compute_time_span(self, self->Time_Span);
+}
+
+
+void fini(LttvTracesetContext *self)
+{
+ guint i, j, nb_trace, nb_tracefile;
+
+ LttvTraceContext *tc;
+
+ LttvTracefileContext *tfc;
+
+ LttvTraceset *ts = self->ts;
+
+ g_free(self->Time_Span);
+
+ lttv_hooks_destroy(self->before);
+ lttv_hooks_destroy(self->after);
+ //FIXME : segfault
+ g_object_unref(self->a);
+
+ nb_trace = lttv_traceset_number(ts);
+
+ for(i = 0 ; i < nb_trace ; i++) {
+ tc = self->traces[i];
+
+ lttv_hooks_destroy(tc->check);
+ lttv_hooks_destroy(tc->before);
+ lttv_hooks_destroy(tc->after);
+ g_object_unref(tc->a);
+
+ nb_tracefile = ltt_trace_control_tracefile_number(tc->t) +
+ ltt_trace_per_cpu_tracefile_number(tc->t);
+
+ for(j = 0 ; j < nb_tracefile ; j++) {
+ tfc = tc->tracefiles[j];
+ lttv_hooks_destroy(tfc->check);
+ lttv_hooks_destroy(tfc->before);
+ lttv_hooks_destroy(tfc->after);
+ lttv_hooks_destroy(tfc->check_event);
+ lttv_hooks_destroy(tfc->before_event);
+ lttv_hooks_by_id_destroy(tfc->before_event_by_id);
+ lttv_hooks_destroy(tfc->after_event);
+ lttv_hooks_by_id_destroy(tfc->after_event_by_id);
+ g_object_unref(tfc->a);
+ g_object_unref(tfc);
+ }
+ g_free(tc->tracefiles);
+ g_object_unref(tc);
+ }
+ g_free(self->traces);
+}
+
+
+void lttv_traceset_context_add_hooks(LttvTracesetContext *self,
+ LttvHooks *before_traceset,
+ LttvHooks *after_traceset,
+ LttvHooks *check_trace,
+ LttvHooks *before_trace,
+ LttvHooks *after_trace,
+ LttvHooks *check_tracefile,
+ LttvHooks *before_tracefile,
+ LttvHooks *after_tracefile,
+ LttvHooks *check_event,
+ LttvHooks *before_event,
+ LttvHooks *after_event)
+{
+ LttvTraceset *ts = self->ts;
+
+ guint i, j, nb_trace, nb_tracefile;
+
+ LttvTraceContext *tc;
+
+ LttvTracefileContext *tfc;
+
+ void *hook_data;
+
+ lttv_hooks_add_list(self->before, before_traceset);
+ lttv_hooks_add_list(self->after, after_traceset);
+ nb_trace = lttv_traceset_number(ts);
+
+ for(i = 0 ; i < nb_trace ; i++) {
+ tc = self->traces[i];
+ lttv_hooks_add_list(tc->check, check_trace);
+ lttv_hooks_add_list(tc->before, before_trace);
+ lttv_hooks_add_list(tc->after, after_trace);
+ nb_tracefile = ltt_trace_control_tracefile_number(tc->t) +
+ ltt_trace_per_cpu_tracefile_number(tc->t);
+
+ for(j = 0 ; j < nb_tracefile ; j++) {
+ tfc = tc->tracefiles[j];
+ lttv_hooks_add_list(tfc->check, check_tracefile);
+ lttv_hooks_add_list(tfc->before, before_tracefile);
+ lttv_hooks_add_list(tfc->after, after_tracefile);
+ lttv_hooks_add_list(tfc->check_event, check_event);
+ lttv_hooks_add_list(tfc->before_event, before_event);
+ lttv_hooks_add_list(tfc->after_event, after_event);
+ }
+ }
+}
+
+
+void lttv_traceset_context_remove_hooks(LttvTracesetContext *self,
+ LttvHooks *before_traceset,
+ LttvHooks *after_traceset,
+ LttvHooks *check_trace,
+ LttvHooks *before_trace,
+ LttvHooks *after_trace,
+ LttvHooks *check_tracefile,
+ LttvHooks *before_tracefile,
+ LttvHooks *after_tracefile,
+ LttvHooks *check_event,
+ LttvHooks *before_event,
+ LttvHooks *after_event)
+{
+ LttvTraceset *ts = self->ts;
+
+ guint i, j, nb_trace, nb_tracefile;
+
+ LttvTraceContext *tc;
+
+ LttvTracefileContext *tfc;
+
+ void *hook_data;
+
+ lttv_hooks_remove_list(self->before, before_traceset);
+ lttv_hooks_remove_list(self->after, after_traceset);
+ nb_trace = lttv_traceset_number(ts);
+
+ for(i = 0 ; i < nb_trace ; i++) {
+ tc = self->traces[i];
+ lttv_hooks_remove_list(tc->check, check_trace);
+ lttv_hooks_remove_list(tc->before, before_trace);
+ lttv_hooks_remove_list(tc->after, after_trace);
+ nb_tracefile = ltt_trace_control_tracefile_number(tc->t) +
+ ltt_trace_per_cpu_tracefile_number(tc->t);
+
+ for(j = 0 ; j < nb_tracefile ; j++) {
+ tfc = tc->tracefiles[j];
+ lttv_hooks_remove_list(tfc->check, check_tracefile);
+ lttv_hooks_remove_list(tfc->before, before_tracefile);
+ lttv_hooks_remove_list(tfc->after, after_tracefile);
+ lttv_hooks_remove_list(tfc->check_event, check_event);
+ lttv_hooks_remove_list(tfc->before_event, before_event);
+ lttv_hooks_remove_list(tfc->after_event, after_event);
+ }
+ }
+}
+
+void lttv_trace_context_add_hooks(LttvTraceContext *tc,
+ LttvHooks *check_trace,
+ LttvHooks *before_trace,
+ LttvHooks *after_trace)
+{
+ lttv_hooks_add_list(tc->check, check_trace);
+ lttv_hooks_add_list(tc->before, before_trace);
+ lttv_hooks_add_list(tc->after, after_trace);
+}
+
+void lttv_trace_context_remove_hooks(LttvTraceContext *tc,
+ LttvHooks *check_trace,
+ LttvHooks *before_trace,
+ LttvHooks *after_trace)
+{
+ lttv_hooks_remove_list(tc->check, check_trace);
+ lttv_hooks_remove_list(tc->before, before_trace);
+ lttv_hooks_remove_list(tc->after, after_trace);
+}
+
+void lttv_tracefile_context_add_hooks(LttvTracefileContext *tfc,
+ LttvHooks *check_tracefile,
+ LttvHooks *before_tracefile,
+ LttvHooks *after_tracefile,
+ LttvHooks *check_event,
+ LttvHooks *before_event,
+ LttvHooks *after_event)
+{
+ lttv_hooks_add_list(tfc->check, check_tracefile);
+ lttv_hooks_add_list(tfc->before, before_tracefile);
+ lttv_hooks_add_list(tfc->after, after_tracefile);
+ lttv_hooks_add_list(tfc->check_event, check_event);
+ lttv_hooks_add_list(tfc->before_event, before_event);
+ lttv_hooks_add_list(tfc->after_event, after_event);
+}
+
+void lttv_tracefile_context_remove_hooks(LttvTracefileContext *tfc,
+ LttvHooks *check_tracefile,
+ LttvHooks *before_tracefile,
+ LttvHooks *after_tracefile,
+ LttvHooks *check_event,
+ LttvHooks *before_event,
+ LttvHooks *after_event)
+{
+ lttv_hooks_remove_list(tfc->check, check_tracefile);
+ lttv_hooks_remove_list(tfc->before, before_tracefile);
+ lttv_hooks_remove_list(tfc->after, after_tracefile);
+ lttv_hooks_remove_list(tfc->check_event, check_event);
+ lttv_hooks_remove_list(tfc->before_event, before_event);
+ lttv_hooks_remove_list(tfc->after_event, after_event);
+}
+
+void lttv_tracefile_context_add_hooks_by_id(LttvTracefileContext *tfc,
+ unsigned i,
+ LttvHooks *before_event_by_id,
+ LttvHooks *after_event_by_id)
+{
+ LttvHooks * h;
+ h = lttv_hooks_by_id_find(tfc->before_event_by_id, i);
+ lttv_hooks_add_list(h, before_event_by_id);
+ h = lttv_hooks_by_id_find(tfc->after_event_by_id, i);
+ lttv_hooks_add_list(h, after_event_by_id);
+}
+
+void lttv_tracefile_context_remove_hooks_by_id(LttvTracefileContext *tfc,
+ unsigned i)
+{
+ lttv_hooks_by_id_remove(tfc->before_event_by_id, i);
+ lttv_hooks_by_id_remove(tfc->after_event_by_id, i);
+}
+
+static LttvTracesetContext *
+new_traceset_context(LttvTracesetContext *self)
+{
+ return g_object_new(LTTV_TRACESET_CONTEXT_TYPE, NULL);
+}
+
+
+static LttvTraceContext *
+new_trace_context(LttvTracesetContext *self)
+{
+ return g_object_new(LTTV_TRACE_CONTEXT_TYPE, NULL);
+}
+
+
+static LttvTracefileContext *
+new_tracefile_context(LttvTracesetContext *self)
+{
+ return g_object_new(LTTV_TRACEFILE_CONTEXT_TYPE, NULL);
+}
+
+
+static void
+traceset_context_instance_init (GTypeInstance *instance, gpointer g_class)
+{
+ /* Be careful of anything which would not work well with shallow copies */
+}
+
+
+static void
+traceset_context_finalize (LttvTracesetContext *self)
+{
+ G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACESET_CONTEXT_TYPE)))
+ ->finalize(G_OBJECT(self));
+}
+
+
+static void
+traceset_context_class_init (LttvTracesetContextClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
+
+ gobject_class->finalize = (void (*)(GObject *self))traceset_context_finalize;
+ klass->init = init;
+ klass->fini = fini;
+ klass->new_traceset_context = new_traceset_context;
+ klass->new_trace_context = new_trace_context;
+ klass->new_tracefile_context = new_tracefile_context;
+}
+
+
+GType
+lttv_traceset_context_get_type(void)
+{
+ static GType type = 0;
+ if (type == 0) {
+ static const GTypeInfo info = {
+ sizeof (LttvTracesetContextClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) traceset_context_class_init, /* class_init */
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (LttvTracesetContext),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) traceset_context_instance_init /* instance_init */
+ };
+
+ type = g_type_register_static (G_TYPE_OBJECT, "LttvTracesetContextType",
+ &info, 0);
+ }
+ return type;
+}
+
+
+static void
+trace_context_instance_init (GTypeInstance *instance, gpointer g_class)
+{
+ /* Be careful of anything which would not work well with shallow copies */
+}
+
+
+static void
+trace_context_finalize (LttvTraceContext *self)
+{
+ G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACE_CONTEXT_TYPE)))->
+ finalize(G_OBJECT(self));
+}
+
+
+static void
+trace_context_class_init (LttvTraceContextClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
+
+ gobject_class->finalize = (void (*)(GObject *self)) trace_context_finalize;
+}
+
+
+GType
+lttv_trace_context_get_type(void)
+{
+ static GType type = 0;
+ if (type == 0) {
+ static const GTypeInfo info = {
+ sizeof (LttvTraceContextClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) trace_context_class_init, /* class_init */
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (LttvTraceContext),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) trace_context_instance_init /* instance_init */
+ };
+
+ type = g_type_register_static (G_TYPE_OBJECT, "LttvTraceContextType",
+ &info, 0);
+ }
+ return type;
+}
+
+
+static void
+tracefile_context_instance_init (GTypeInstance *instance, gpointer g_class)
+{
+ /* Be careful of anything which would not work well with shallow copies */
+}
+
+
+static void
+tracefile_context_finalize (LttvTracefileContext *self)
+{
+ G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACEFILE_CONTEXT_TYPE)))
+ ->finalize(G_OBJECT(self));
+}
+
+
+static void
+tracefile_context_class_init (LttvTracefileContextClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
+
+ gobject_class->finalize = (void (*)(GObject *self))tracefile_context_finalize;
+}
+
+
+GType
+lttv_tracefile_context_get_type(void)
+{
+ static GType type = 0;
+ if (type == 0) {
+ static const GTypeInfo info = {
+ sizeof (LttvTracefileContextClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) tracefile_context_class_init, /* class_init */
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (LttvTracefileContext),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) tracefile_context_instance_init /* instance_init */
+ };
+
+ type = g_type_register_static (G_TYPE_OBJECT, "LttvTracefileContextType",
+ &info, 0);
+ }
+ return type;
+}
+
+
+gint compare_tracefile(gconstpointer a, gconstpointer 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);
+}
+
+
+gboolean get_first(gpointer key, gpointer value, gpointer user_data) {
+ *((LttvTracefileContext **)user_data) = (LttvTracefileContext *)value;
+ return TRUE;
+}
+
+
+void lttv_process_traceset_begin(LttvTracesetContext *self, LttTime end)
+{
+ guint i, j, nbi, nb_tracefile;
+
+ LttvTraceContext *tc;
+
+ LttvTracefileContext *tfc;
+
+ /* Call all before_traceset, before_trace, and before_tracefile hooks.
+ For all qualifying tracefiles, seek to the start time, create a context,
+ read one event and insert in the pqueue based on the event time. */
+
+ lttv_hooks_call(self->before, self);
+ nbi = lttv_traceset_number(self->ts);
+ self->pqueue = g_tree_new(compare_tracefile);
+
+ for(i = 0 ; i < nbi ; i++) {
+ tc = self->traces[i];
+
+ if(!lttv_hooks_call_check(tc->check, tc)) {
+ lttv_hooks_call(tc->before, tc);
+ nb_tracefile = ltt_trace_control_tracefile_number(tc->t) +
+ ltt_trace_per_cpu_tracefile_number(tc->t);
+
+ for(j = 0 ; j < nb_tracefile ; j++) {
+ tfc = tc->tracefiles[j];
+
+ if(!lttv_hooks_call_check(tfc->check, tfc)) {
+ lttv_hooks_call(tfc->before, tfc);
+
+ if(tfc->e != NULL) {
+ 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, tfc);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+
+guint lttv_process_traceset_middle(LttvTracesetContext *self, LttTime end,
+ unsigned nb_events)
+{
+ GTree *pqueue = self->pqueue;
+
+ guint id;
+
+ LttvTraceContext *tc;
+
+ LttvTracefileContext *tfc;
+
+ LttEvent *event;
+
+ unsigned count = 0;
+
+ LttTime previous_timestamp = {0, 0};
+
+ /* Get the next event from the pqueue, call its hooks,
+ reinsert in the pqueue the following event from the same tracefile
+ unless the tracefile is finished or the event is later than the
+ start time. */
+
+ while(TRUE) {
+ tfc = NULL;
+ g_tree_foreach(pqueue, get_first, &tfc);
+ if(tfc == NULL) return count;
+
+ /* Have we reached the maximum number of events specified? However,
+ continue for all the events with the same time stamp (CHECK?). Then,
+ empty the queue and break from the loop. */
+
+ if(count >= nb_events &&
+ ltt_time_compare(tfc->timestamp, previous_timestamp) != 0)
+ return count;
+
+ previous_timestamp = tfc->timestamp;
+
+
+ /* Get the tracefile with an event for the smallest time found. If two
+ or more tracefiles have events for the same time, hope that lookup
+ and remove are consistent. */
+
+ g_tree_remove(pqueue, tfc);
+ count++;
+
+ if(!lttv_hooks_call(tfc->check_event, tfc)) {
+ id = ltt_event_eventtype_id(tfc->e);
+ lttv_hooks_call(lttv_hooks_by_id_get(tfc->before_event_by_id, id), tfc);
+ lttv_hooks_call(tfc->before_event, tfc);
+ lttv_hooks_call(lttv_hooks_by_id_get(tfc->after_event_by_id, id), tfc);
+ lttv_hooks_call(tfc->after_event, tfc);
+ }
+
+ event = ltt_tracefile_read(tfc->tf);
+ if(event != NULL) {
+ tfc->e = event;
+ 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, tfc);
+ }
+ }
+}
+
+
+void lttv_process_traceset_end(LttvTracesetContext *self)
+{
+ guint i, j, nbi, nb_tracefile;
+
+ LttvTraceContext *tc;
+
+ LttvTracefileContext *tfc;
+
+ /* Call all after_traceset, after_trace, and after_tracefile hooks. */
+
+ nbi = lttv_traceset_number(self->ts);
+
+ for(i = 0 ; i < nbi ; i++) {
+ tc = self->traces[i];
+
+ /* The check hooks are called again to avoid memorizing the results
+ obtained at the beginning. CHECK if it poses a problem */
+
+ if(!lttv_hooks_call_check(tc->check, tc)) {
+ nb_tracefile = ltt_trace_control_tracefile_number(tc->t) +
+ ltt_trace_per_cpu_tracefile_number(tc->t);
+
+ for(j = 0 ; j < nb_tracefile ; j++) {
+ tfc = tc->tracefiles[j];
+
+ if(!lttv_hooks_call_check(tfc->check, tfc)) {
+ lttv_hooks_call(tfc->after, tfc);
+ }
+ }
+ lttv_hooks_call(tc->after, tc);
+ }
+ }
+ lttv_hooks_call(self->after, self);
+
+ /* Empty and free the pqueue */
+
+ while(TRUE){
+ tfc = NULL;
+ g_tree_foreach(self->pqueue, get_first, &tfc);
+ if(tfc == NULL) break;
+ g_tree_remove(self->pqueue, &(tfc->timestamp));
+ }
+ g_tree_destroy(self->pqueue);
+}
+
+
+void lttv_process_traceset(LttvTracesetContext *self, LttTime end,
+ unsigned nb_events)
+{
+ lttv_process_traceset_begin(self, end);
+ lttv_process_traceset_middle(self, end, nb_events);
+ lttv_process_traceset_end(self);
+}
+
+
+void lttv_process_trace_seek_time(LttvTraceContext *self, LttTime start)
+{
+ guint i, nb_tracefile;
+
+ LttvTracefileContext *tfc;
+
+ LttEvent *event;
+
+ nb_tracefile = ltt_trace_control_tracefile_number(self->t) +
+ ltt_trace_per_cpu_tracefile_number(self->t);
+
+ for(i = 0 ; i < nb_tracefile ; i++) {
+ tfc = self->tracefiles[i];
+ ltt_tracefile_seek_time(tfc->tf, start);
+ event = ltt_tracefile_read(tfc->tf);
+ tfc->e = event;
+ if(event != NULL) tfc->timestamp = ltt_event_time(event);
+ }
+}
+
+
+void lttv_process_traceset_seek_time(LttvTracesetContext *self, LttTime start)
+{
+ guint i, nb_trace;
+
+ LttvTraceContext *tc;
+
+ nb_trace = lttv_traceset_number(self->ts);
+ for(i = 0 ; i < nb_trace ; i++) {
+ tc = self->traces[i];
+ lttv_process_trace_seek_time(tc, start);
+ }
+}
+
+
+static LttField *
+find_field(LttEventType *et, const char *field)
+{
+ LttType *t;
+
+ LttField *f;
+
+ guint i, nb;
+
+ char *name;
+
+ if(field == NULL) return NULL;
+
+ f = ltt_eventtype_field(et);
+ t = ltt_eventtype_type(et);
+ g_assert(ltt_type_class(t) == LTT_STRUCT);
+ nb = ltt_type_member_number(t);
+ for(i = 0 ; i < nb ; i++) {
+ ltt_type_member_type(t, i, &name);
+ if(strcmp(name, field) == 0) break;
+ }
+ g_assert(i < nb);
+ return ltt_field_member(f, i);
+}
+
+
+void
+lttv_trace_find_hook(LttTrace *t, char *facility, char *event_type,
+ char *field1, char *field2, char *field3, LttvHook h, LttvTraceHook *th)
+{
+ LttFacility *f;
+
+ LttEventType *et;
+
+ guint nb, pos, i;
+
+ char *name;
+
+ nb = ltt_trace_facility_find(t, facility, &pos);
+ if(nb < 1) g_error("No %s facility", facility);
+ f = ltt_trace_facility_get(t, pos);
+ et = ltt_facility_eventtype_get_by_name(f, event_type);
+ if(et == NULL) g_error("Event %s does not exist", event_type);
+
+ th->h = h;
+ th->id = ltt_eventtype_id(et);
+ th->f1 = find_field(et, field1);
+ th->f2 = find_field(et, field2);
+ th->f3 = find_field(et, field3);
+}
+
+
--- /dev/null
+/* This file is part of the Linux Trace Toolkit viewer
+ * Copyright (C) 2003-2004 Michel Dagenais
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+
+#include <lttv/lttv.h>
+#include <lttv/module.h>
+#include <lttv/state.h>
+#include <ltt/facility.h>
+#include <ltt/trace.h>
+#include <ltt/event.h>
+#include <ltt/type.h>
+#include <stdio.h>
+
+LttvExecutionMode
+ LTTV_STATE_MODE_UNKNOWN,
+ LTTV_STATE_USER_MODE,
+ LTTV_STATE_SYSCALL,
+ LTTV_STATE_TRAP,
+ LTTV_STATE_IRQ;
+
+LttvExecutionSubmode
+ LTTV_STATE_SUBMODE_UNKNOWN,
+ LTTV_STATE_SUBMODE_NONE;
+
+LttvProcessStatus
+ LTTV_STATE_UNNAMED,
+ LTTV_STATE_WAIT_FORK,
+ LTTV_STATE_WAIT_CPU,
+ LTTV_STATE_EXIT,
+ LTTV_STATE_WAIT,
+ LTTV_STATE_RUN;
+
+static GQuark
+ LTTV_STATE_TRACEFILES,
+ LTTV_STATE_PROCESSES,
+ LTTV_STATE_PROCESS,
+ LTTV_STATE_EVENT,
+ LTTV_STATE_SAVED_STATES,
+ LTTV_STATE_SAVED_STATES_TIME,
+ LTTV_STATE_TIME,
+ LTTV_STATE_HOOKS,
+ LTTV_STATE_NAME_TABLES,
+ LTTV_STATE_TRACE_STATE_USE_COUNT;
+
+
+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_save(LttvTraceState *self, LttvAttribute *container)
+{
+ LTTV_TRACE_STATE_GET_CLASS(self)->state_save(self, container);
+}
+
+
+void lttv_state_restore(LttvTraceState *self, LttvAttribute *container)
+{
+ LTTV_TRACE_STATE_GET_CLASS(self)->state_restore(self, container);
+}
+
+
+void lttv_state__state_saved_free(LttvTraceState *self,
+ LttvAttribute *container)
+{
+ LTTV_TRACE_STATE_GET_CLASS(self)->state_saved_free(self, container);
+}
+
+
+guint process_hash(gconstpointer key)
+{
+ return ((LttvProcessState *)key)->pid;
+}
+
+
+gboolean process_equal(gconstpointer a, gconstpointer b)
+{
+ LttvProcessState *process_a, *process_b;
+
+ process_a = (LttvProcessState *)a;
+ process_b = (LttvProcessState *)b;
+
+ if(process_a->pid != process_b->pid) return FALSE;
+ if(process_a->pid == 0 &&
+ process_a->last_cpu != process_b->last_cpu) return FALSE;
+ return TRUE;
+}
+
+
+static void
+restore_init_state(LttvTraceState *self)
+{
+ guint i, nb_tracefile;
+
+ LttvTracefileState *tfcs;
+
+ LttTime null_time = {0,0};
+
+ if(self->processes != NULL) lttv_state_free_process_table(self->processes);
+ self->processes = g_hash_table_new(process_hash, process_equal);
+ self->nb_event = 0;
+
+ nb_tracefile = ltt_trace_control_tracefile_number(self->parent.t) +
+ ltt_trace_per_cpu_tracefile_number(self->parent.t);
+
+ for(i = 0 ; i < nb_tracefile ; i++) {
+ tfcs = LTTV_TRACEFILE_STATE(self->parent.tracefiles[i]);
+ tfcs->parent.timestamp = null_time;
+ tfcs->saved_position = 0;
+ tfcs->process = lttv_state_create_process(tfcs, NULL,0);
+ tfcs->process->state->s = LTTV_STATE_RUN;
+ tfcs->process->last_cpu = tfcs->cpu_name;
+ }
+}
+
+static LttTime time_zero = {0,0};
+
+static void
+init(LttvTracesetState *self, LttvTraceset *ts)
+{
+ guint i, j, nb_trace, nb_tracefile;
+
+ LttvTraceContext *tc;
+
+ LttvTraceState *tcs;
+
+ LttvTracefileState *tfcs;
+
+ LttvAttributeValue v;
+
+ LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE))->
+ init((LttvTracesetContext *)self, ts);
+
+ nb_trace = lttv_traceset_number(ts);
+ for(i = 0 ; i < nb_trace ; i++) {
+ tc = self->parent.traces[i];
+ tcs = (LttvTraceState *)tc;
+ tcs->save_interval = 50000;
+ lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_TRACE_STATE_USE_COUNT,
+ LTTV_UINT, &v);
+ (*v.v_uint)++;
+
+ 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);
+
+ for(j = 0 ; j < nb_tracefile ; j++) {
+ tfcs = LTTV_TRACEFILE_STATE(tc->tracefiles[j]);
+ tfcs->cpu_name= g_quark_from_string(ltt_tracefile_name(tfcs->parent.tf));
+ }
+ tcs->processes = NULL;
+ restore_init_state(tcs);
+ }
+}
+
+
+static void
+fini(LttvTracesetState *self)
+{
+ guint i, j, nb_trace;
+
+ LttvTraceState *tcs;
+
+ 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;
+ }
+ LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE))->
+ fini((LttvTracesetContext *)self);
+}
+
+
+static LttvTracesetContext *
+new_traceset_context(LttvTracesetContext *self)
+{
+ return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATE_TYPE, NULL));
+}
+
+
+static LttvTraceContext *
+new_trace_context(LttvTracesetContext *self)
+{
+ return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATE_TYPE, NULL));
+}
+
+
+static LttvTracefileContext *
+new_tracefile_context(LttvTracesetContext *self)
+{
+ return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATE_TYPE, NULL));
+}
+
+
+/* Write the process state of the trace */
+
+static void write_process_state(gpointer key, gpointer value,
+ gpointer user_data)
+{
+ LttvProcessState *process;
+
+ LttvExecutionState *es;
+
+ FILE *fp = (FILE *)user_data;
+
+ guint i;
+
+ process = (LttvProcessState *)value;
+ fprintf(fp,
+" <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));
+
+ for(i = 0 ; i < process->execution_stack->len; i++) {
+ es = &g_array_index(process->execution_stack, LttvExecutionState, i);
+ fprintf(fp, " <ES MODE=\"%s\" SUBMODE=\"%s\" ENTRY_S=%lu ENTRY_NS=%lu",
+ g_quark_to_string(es->t), g_quark_to_string(es->n),
+ es->entry.tv_sec, es->entry.tv_nsec);
+ fprintf(fp, " CHANGE_S=%lu CHANGE_NS=%lu STATUS=\"%s\"/>\n",
+ es->change.tv_sec, es->change.tv_nsec, g_quark_to_string(es->s));
+ }
+ fprintf(fp, " </PROCESS>\n");
+}
+
+
+void lttv_state_write(LttvTraceState *self, LttTime t, FILE *fp)
+{
+ guint i, nb_tracefile, nb_block, nb_event;
+
+ LttvTracefileState *tfcs;
+
+ LttTracefile *tf;
+
+ LttEventPosition *ep;
+
+ ep = ltt_event_position_new();
+
+ fprintf(fp,"<PROCESS_STATE TIME_S=%lu TIME_NS=%lu>\n", t.tv_sec, t.tv_nsec);
+
+ g_hash_table_foreach(self->processes, write_process_state, fp);
+
+ nb_tracefile = ltt_trace_control_tracefile_number(self->parent.t) +
+ ltt_trace_per_cpu_tracefile_number(self->parent.t);
+
+ for(i = 0 ; i < nb_tracefile ; i++) {
+ tfcs = (LttvTracefileState *)self->parent.tracefiles[i];
+ fprintf(fp, " <TRACEFILE PID=%u TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
+ tfcs->process->pid, tfcs->parent.timestamp.tv_sec,
+ tfcs->parent.timestamp.tv_nsec);
+ if(tfcs->parent.e == NULL) fprintf(fp,"/>\n");
+ else {
+ ltt_event_position(tfcs->parent.e, ep);
+ ltt_event_position_get(ep, &nb_block, &nb_event, &tf);
+ fprintf(fp, " BLOCK=%u EVENT=%u/>\n", nb_block, nb_event);
+ }
+ }
+ g_free(ep);
+ fprintf(fp,"</PROCESS_STATE>");
+}
+
+
+/* Copy each process from an existing hash table to a new one */
+
+static void copy_process_state(gpointer key, gpointer value,gpointer user_data)
+{
+ LttvProcessState *process, *new_process;
+
+ GHashTable *new_processes = (GHashTable *)user_data;
+
+ guint i;
+
+ process = (LttvProcessState *)value;
+ new_process = g_new(LttvProcessState, 1);
+ *new_process = *process;
+ new_process->execution_stack = g_array_new(FALSE, FALSE,
+ sizeof(LttvExecutionState));
+ g_array_set_size(new_process->execution_stack,process->execution_stack->len);
+ for(i = 0 ; i < process->execution_stack->len; i++) {
+ g_array_index(new_process->execution_stack, LttvExecutionState, i) =
+ g_array_index(process->execution_stack, LttvExecutionState, i);
+ }
+ new_process->state = &g_array_index(new_process->execution_stack,
+ LttvExecutionState, new_process->execution_stack->len - 1);
+ g_hash_table_insert(new_processes, new_process, new_process);
+}
+
+
+static GHashTable *lttv_state_copy_process_table(GHashTable *processes)
+{
+ GHashTable *new_processes = g_hash_table_new(process_hash, process_equal);
+
+ g_hash_table_foreach(processes, copy_process_state, new_processes);
+ return new_processes;
+}
+
+
+/* The saved state for each trace contains a member "processes", which
+ stores a copy of the process table, and a member "tracefiles" with
+ one entry per tracefile. Each tracefile has a "process" member pointing
+ to the current process and a "position" member storing the tracefile
+ position (needed to seek to the current "next" event. */
+
+static void state_save(LttvTraceState *self, LttvAttribute *container)
+{
+ guint i, nb_tracefile;
+
+ LttvTracefileState *tfcs;
+
+ LttvAttribute *tracefiles_tree, *tracefile_tree;
+
+ LttvAttributeType type;
+
+ LttvAttributeValue value;
+
+ LttvAttributeName name;
+
+ LttEventPosition *ep;
+
+ tracefiles_tree = lttv_attribute_find_subdir(container,
+ LTTV_STATE_TRACEFILES);
+
+ value = lttv_attribute_add(container, LTTV_STATE_PROCESSES,
+ LTTV_POINTER);
+ *(value.v_pointer) = lttv_state_copy_process_table(self->processes);
+
+ nb_tracefile = ltt_trace_control_tracefile_number(self->parent.t) +
+ ltt_trace_per_cpu_tracefile_number(self->parent.t);
+
+ for(i = 0 ; i < nb_tracefile ; i++) {
+ tfcs = (LttvTracefileState *)self->parent.tracefiles[i];
+ tracefile_tree = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
+ value = lttv_attribute_add(tracefiles_tree, i,
+ LTTV_GOBJECT);
+ *(value.v_gobject) = (GObject *)tracefile_tree;
+ value = lttv_attribute_add(tracefile_tree, LTTV_STATE_PROCESS,
+ LTTV_UINT);
+ *(value.v_uint) = tfcs->process->pid;
+ value = lttv_attribute_add(tracefile_tree, LTTV_STATE_EVENT,
+ LTTV_POINTER);
+ if(tfcs->parent.e == NULL) *(value.v_pointer) = NULL;
+ else {
+ ep = ltt_event_position_new();
+ ltt_event_position(tfcs->parent.e, ep);
+ *(value.v_pointer) = ep;
+
+ guint nb_block, nb_event;
+ LttTracefile *tf;
+ ltt_event_position_get(ep, &nb_block, &nb_event, &tf);
+ g_debug("Block %u event %u time %lu.%lu", nb_block, nb_event,
+ tfcs->parent.timestamp.tv_sec, tfcs->parent.timestamp.tv_nsec);
+ }
+ }
+}
+
+
+static void state_restore(LttvTraceState *self, LttvAttribute *container)
+{
+ guint i, nb_tracefile, pid;
+
+ LttvTracefileState *tfcs;
+
+ LttvAttribute *tracefiles_tree, *tracefile_tree;
+
+ LttvAttributeType type;
+
+ LttvAttributeValue value;
+
+ LttvAttributeName name;
+
+ LttEventPosition *ep;
+
+ tracefiles_tree = lttv_attribute_find_subdir(container,
+ LTTV_STATE_TRACEFILES);
+
+ type = lttv_attribute_get_by_name(container, LTTV_STATE_PROCESSES,
+ &value);
+ g_assert(type == LTTV_POINTER);
+ lttv_state_free_process_table(self->processes);
+ self->processes = lttv_state_copy_process_table(*(value.v_pointer));
+
+ nb_tracefile = ltt_trace_control_tracefile_number(self->parent.t) +
+ ltt_trace_per_cpu_tracefile_number(self->parent.t);
+
+ for(i = 0 ; i < nb_tracefile ; i++) {
+ tfcs = (LttvTracefileState *)self->parent.tracefiles[i];
+ type = lttv_attribute_get(tracefiles_tree, i, &name, &value);
+ g_assert(type == LTTV_GOBJECT);
+ tracefile_tree = *((LttvAttribute **)(value.v_gobject));
+
+ type = lttv_attribute_get_by_name(tracefile_tree, LTTV_STATE_PROCESS,
+ &value);
+ g_assert(type == LTTV_UINT);
+ pid = *(value.v_uint);
+ tfcs->process = lttv_state_find_process_or_create(tfcs, pid);
+
+ type = lttv_attribute_get_by_name(tracefile_tree, LTTV_STATE_EVENT,
+ &value);
+ g_assert(type == LTTV_POINTER);
+ if(*(value.v_pointer) == NULL) tfcs->parent.e = NULL;
+ else {
+ ep = *(value.v_pointer);
+ ltt_tracefile_seek_position(tfcs->parent.tf, ep);
+ tfcs->parent.e = ltt_tracefile_read(tfcs->parent.tf);
+ tfcs->parent.timestamp = ltt_event_time(tfcs->parent.e);
+ }
+ }
+}
+
+
+static void state_saved_free(LttvTraceState *self, LttvAttribute *container)
+{
+ guint i, nb_tracefile;
+
+ LttvTracefileState *tfcs;
+
+ LttvAttribute *tracefiles_tree, *tracefile_tree;
+
+ LttvAttributeType type;
+
+ LttvAttributeValue value;
+
+ LttvAttributeName name;
+
+ LttEventPosition *ep;
+
+ tracefiles_tree = lttv_attribute_find_subdir(container,
+ LTTV_STATE_TRACEFILES);
+ lttv_attribute_remove_by_name(container, LTTV_STATE_TRACEFILES);
+
+ type = lttv_attribute_get_by_name(container, LTTV_STATE_PROCESSES,
+ &value);
+ g_assert(type == LTTV_POINTER);
+ lttv_state_free_process_table(*(value.v_pointer));
+ *(value.v_pointer) = NULL;
+ lttv_attribute_remove_by_name(container, LTTV_STATE_PROCESSES);
+
+ nb_tracefile = ltt_trace_control_tracefile_number(self->parent.t) +
+ ltt_trace_per_cpu_tracefile_number(self->parent.t);
+
+ for(i = 0 ; i < nb_tracefile ; i++) {
+ tfcs = (LttvTracefileState *)self->parent.tracefiles[i];
+ type = lttv_attribute_get(tracefiles_tree, i, &name, &value);
+ g_assert(type == LTTV_GOBJECT);
+ tracefile_tree = *((LttvAttribute **)(value.v_gobject));
+
+ type = lttv_attribute_get_by_name(tracefile_tree, LTTV_STATE_EVENT,
+ &value);
+ g_assert(type == LTTV_POINTER);
+ if(*(value.v_pointer) != NULL) g_free(*(value.v_pointer));
+ }
+ lttv_attribute_recursive_free(tracefiles_tree);
+}
+
+
+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
+create_name_tables(LttvTraceState *tcs)
+{
+ int i, nb;
+
+ char *f_name, *e_name;
+
+ LttvTraceHook h;
+
+ LttEventType *et;
+
+ LttType *t;
+
+ 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);
+ 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);
+ name_tables->eventtype_names[i] = g_quark_from_string(fe_name->str);
+ }
+
+ lttv_trace_find_hook(tcs->parent.t, "core", "syscall_entry",
+ "syscall_id", NULL, NULL, NULL, &h);
+ t = ltt_field_type(h.f1);
+ nb = ltt_type_element_number(t);
+
+ /* CHECK syscalls should be an emun but currently are not!
+ name_tables->syscall_names = g_new(GQuark, nb);
+
+ for(i = 0 ; i < nb ; i++) {
+ name_tables->syscall_names[i] = g_quark_from_string(
+ ltt_enum_string_get(t, i));
+ }
+ */
+
+ name_tables->syscall_names = g_new(GQuark, 256);
+ for(i = 0 ; i < 256 ; i++) {
+ g_string_printf(fe_name, "syscall %d", i);
+ name_tables->syscall_names[i] = g_quark_from_string(fe_name->str);
+ }
+
+ lttv_trace_find_hook(tcs->parent.t, "core", "trap_entry",
+ "trap_id", NULL, NULL, NULL, &h);
+ t = ltt_field_type(h.f1);
+ nb = ltt_type_element_number(t);
+
+ /*
+ name_tables->trap_names = g_new(GQuark, nb);
+ for(i = 0 ; i < nb ; i++) {
+ name_tables->trap_names[i] = g_quark_from_string(
+ ltt_enum_string_get(t, i));
+ }
+ */
+
+ name_tables->trap_names = g_new(GQuark, 256);
+ for(i = 0 ; i < 256 ; i++) {
+ g_string_printf(fe_name, "trap %d", i);
+ name_tables->trap_names[i] = g_quark_from_string(fe_name->str);
+ }
+
+ lttv_trace_find_hook(tcs->parent.t, "core", "irq_entry",
+ "irq_id", NULL, NULL, NULL, &h);
+ t = ltt_field_type(h.f1);
+ nb = ltt_type_element_number(t);
+
+ /*
+ name_tables->irq_names = g_new(GQuark, nb);
+ for(i = 0 ; i < nb ; i++) {
+ name_tables->irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
+ }
+ */
+
+ name_tables->irq_names = g_new(GQuark, 256);
+ for(i = 0 ; i < 256 ; i++) {
+ g_string_printf(fe_name, "irq %d", i);
+ 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)
+{
+ 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);
+}
+
+
+static void push_state(LttvTracefileState *tfs, LttvExecutionMode t,
+ guint state_id)
+{
+ LttvExecutionState *es;
+
+ LttvProcessState *process = tfs->process;
+
+ guint depth = process->execution_stack->len;
+
+ g_array_set_size(process->execution_stack, depth + 1);
+ es = &g_array_index(process->execution_stack, LttvExecutionState, depth);
+ es->t = t;
+ es->n = state_id;
+ es->entry = es->change = tfs->parent.timestamp;
+ es->s = process->state->s;
+ process->state = es;
+}
+
+
+static void pop_state(LttvTracefileState *tfs, LttvExecutionMode t)
+{
+ LttvProcessState *process = tfs->process;
+
+ guint depth = process->execution_stack->len;
+
+ if(process->state->t != t){
+ g_info("Different execution mode type (%d.%09d): ignore it\n",
+ tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec);
+ g_info("process state has %s when pop_int is %s\n",
+ g_quark_to_string(process->state->t),
+ g_quark_to_string(t));
+ g_info("{ %u, %u, %s, %s }\n",
+ process->pid,
+ process->ppid,
+ g_quark_to_string(process->name),
+ g_quark_to_string(process->state->s));
+ return;
+ }
+
+ 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_set_size(process->execution_stack, depth - 1);
+ process->state = &g_array_index(process->execution_stack, LttvExecutionState,
+ depth - 2);
+ process->state->change = tfs->parent.timestamp;
+}
+
+
+LttvProcessState *
+lttv_state_create_process(LttvTracefileState *tfs, LttvProcessState *parent,
+ guint pid)
+{
+ LttvProcessState *process = g_new(LttvProcessState, 1);
+
+ LttvExecutionState *es;
+
+ LttvTraceContext *tc;
+
+ LttvTraceState *tcs;
+
+ char buffer[128];
+
+ 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) {
+ process->ppid = parent->pid;
+ process->name = parent->name;
+ process->creation_time = tfs->parent.timestamp;
+ }
+
+ /* No parent. This process exists but we are missing all information about
+ its creation. The birth time is set to zero but we remember the time of
+ insertion */
+
+ else {
+ process->ppid = 0;
+ process->name = LTTV_STATE_UNNAMED;
+ process->creation_time = ltt_time_zero;
+ }
+
+ process->insertion_time = tfs->parent.timestamp;
+ sprintf(buffer,"%d-%lu.%lu",pid, process->creation_time.tv_sec,
+ process->creation_time.tv_nsec);
+ process->pid_time = g_quark_from_string(buffer);
+ process->last_cpu = tfs->cpu_name;
+ process->execution_stack = g_array_new(FALSE, FALSE,
+ sizeof(LttvExecutionState));
+ g_array_set_size(process->execution_stack, 1);
+ es = process->state = &g_array_index(process->execution_stack,
+ LttvExecutionState, 0);
+ es->t = LTTV_STATE_USER_MODE;
+ es->n = LTTV_STATE_SUBMODE_NONE;
+ es->entry = tfs->parent.timestamp;
+ es->change = tfs->parent.timestamp;
+ es->s = LTTV_STATE_WAIT_FORK;
+
+ return process;
+}
+
+
+LttvProcessState *
+lttv_state_find_process_from_trace(LttvTraceState *ts, GQuark cpu, guint pid)
+{
+ LttvProcessState key;
+ LttvProcessState *process;
+
+ key.pid = pid;
+ key.last_cpu = cpu;
+ process = g_hash_table_lookup(ts->processes, &key);
+ return process;
+}
+
+
+LttvProcessState *lttv_state_find_process(LttvTracefileState *tfs,
+ guint pid)
+{
+ LttvTraceState *ts =(LttvTraceState *)tfs->parent.t_context;
+ return lttv_state_find_process_from_trace(ts, tfs->cpu_name, pid);
+}
+
+
+LttvProcessState *
+lttv_state_find_process_or_create(LttvTracefileState *tfs, guint pid)
+{
+ LttvProcessState *process = lttv_state_find_process(tfs, pid);
+
+ if(process == NULL) process = lttv_state_create_process(tfs, NULL, pid);
+ return process;
+}
+
+
+static void exit_process(LttvTracefileState *tfs, LttvProcessState *process)
+{
+ LttvTraceState *ts = LTTV_TRACE_STATE(tfs->parent.t_context);
+ LttvProcessState key;
+
+ key.pid = process->pid;
+ key.last_cpu = process->last_cpu;
+ g_hash_table_remove(ts->processes, &key);
+ g_array_free(process->execution_stack, TRUE);
+ g_free(process);
+}
+
+
+static void free_process_state(gpointer key, gpointer value,gpointer user_data)
+{
+ g_array_free(((LttvProcessState *)value)->execution_stack, TRUE);
+ g_free(value);
+}
+
+
+static void lttv_state_free_process_table(GHashTable *processes)
+{
+ g_hash_table_foreach(processes, free_process_state, NULL);
+ g_hash_table_destroy(processes);
+}
+
+
+static gboolean syscall_entry(void *hook_data, void *call_data)
+{
+ LttField *f = ((LttvTraceHook *)hook_data)->f1;
+
+ LttvTracefileState *s = (LttvTracefileState *)call_data;
+
+ LttvExecutionSubmode submode;
+
+ submode = ((LttvTraceState *)(s->parent.t_context))->syscall_names[
+ ltt_event_get_unsigned(s->parent.e, f)];
+ push_state(s, LTTV_STATE_SYSCALL, submode);
+ return FALSE;
+}
+
+
+static gboolean syscall_exit(void *hook_data, void *call_data)
+{
+ LttvTracefileState *s = (LttvTracefileState *)call_data;
+
+ pop_state(s, LTTV_STATE_SYSCALL);
+ return FALSE;
+}
+
+
+static gboolean trap_entry(void *hook_data, void *call_data)
+{
+ LttField *f = ((LttvTraceHook *)hook_data)->f1;
+
+ LttvTracefileState *s = (LttvTracefileState *)call_data;
+
+ LttvExecutionSubmode submode;
+
+ submode = ((LttvTraceState *)(s->parent.t_context))->trap_names[
+ ltt_event_get_unsigned(s->parent.e, f)];
+ push_state(s, LTTV_STATE_TRAP, submode);
+ return FALSE;
+}
+
+
+static gboolean trap_exit(void *hook_data, void *call_data)
+{
+ LttvTracefileState *s = (LttvTracefileState *)call_data;
+
+ pop_state(s, LTTV_STATE_TRAP);
+ return FALSE;
+}
+
+
+static gboolean irq_entry(void *hook_data, void *call_data)
+{
+ LttField *f = ((LttvTraceHook *)hook_data)->f1;
+
+ LttvTracefileState *s = (LttvTracefileState *)call_data;
+
+ LttvExecutionSubmode submode;
+
+ submode = ((LttvTraceState *)(s->parent.t_context))->irq_names[
+ ltt_event_get_unsigned(s->parent.e, f)];
+
+ /* Do something with the info about being in user or system mode when int? */
+ push_state(s, LTTV_STATE_IRQ, submode);
+ return FALSE;
+}
+
+
+static gboolean irq_exit(void *hook_data, void *call_data)
+{
+ LttvTracefileState *s = (LttvTracefileState *)call_data;
+
+ pop_state(s, LTTV_STATE_IRQ);
+ return FALSE;
+}
+
+
+static gboolean schedchange(void *hook_data, void *call_data)
+{
+ LttvTraceHook *h = (LttvTraceHook *)hook_data;
+
+ LttvTracefileState *s = (LttvTracefileState *)call_data;
+
+ guint pid_in, pid_out, state_out;
+
+ pid_in = ltt_event_get_unsigned(s->parent.e, h->f1);
+ pid_out = ltt_event_get_unsigned(s->parent.e, h->f2);
+ state_out = ltt_event_get_unsigned(s->parent.e, h->f3);
+
+ 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;
+
+ s->process->state->change = s->parent.timestamp;
+ }
+ s->process = lttv_state_find_process_or_create(s, pid_in);
+ s->process->state->s = LTTV_STATE_RUN;
+ s->process->last_cpu = s->cpu_name;
+ s->process->state->change = s->parent.timestamp;
+ return FALSE;
+}
+
+
+static gboolean process_fork(void *hook_data, void *call_data)
+{
+ LttField *f = ((LttvTraceHook *)hook_data)->f1;
+
+ LttvTracefileState *s = (LttvTracefileState *)call_data;
+
+ guint child_pid;
+
+ child_pid = ltt_event_get_unsigned(s->parent.e, f);
+ lttv_state_create_process(s, s->process, child_pid);
+ return FALSE;
+}
+
+
+static gboolean process_exit(void *hook_data, void *call_data)
+{
+ LttvTracefileState *s = (LttvTracefileState *)call_data;
+
+ if(s->process != NULL) {
+ s->process->state->s = LTTV_STATE_EXIT;
+ }
+ return FALSE;
+}
+
+
+void lttv_state_add_event_hooks(LttvTracesetState *self)
+{
+ LttvTraceset *traceset = self->parent.ts;
+
+ guint i, j, k, nb_trace, nb_tracefile;
+
+ LttvTraceState *ts;
+
+ LttvTracefileState *tfs;
+
+ GArray *hooks;
+
+ LttvTraceHook hook;
+
+ LttvAttributeValue val;
+
+ nb_trace = lttv_traceset_number(traceset);
+ for(i = 0 ; i < nb_trace ; i++) {
+ ts = (LttvTraceState *)self->parent.traces[i];
+
+ /* Find the eventtype id for the following events and register the
+ associated by id hooks. */
+
+ hooks = g_array_new(FALSE, FALSE, sizeof(LttvTraceHook));
+ g_array_set_size(hooks, 9);
+
+ lttv_trace_find_hook(ts->parent.t, "core","syscall_entry","syscall_id",
+ NULL, NULL, syscall_entry, &g_array_index(hooks, LttvTraceHook, 0));
+
+ lttv_trace_find_hook(ts->parent.t, "core", "syscall_exit", NULL, NULL,
+ NULL, syscall_exit, &g_array_index(hooks, LttvTraceHook, 1));
+
+ lttv_trace_find_hook(ts->parent.t, "core", "trap_entry", "trap_id",
+ NULL, NULL, trap_entry, &g_array_index(hooks, LttvTraceHook, 2));
+
+ lttv_trace_find_hook(ts->parent.t, "core", "trap_exit", NULL, NULL, NULL,
+ trap_exit, &g_array_index(hooks, LttvTraceHook, 3));
+
+ lttv_trace_find_hook(ts->parent.t, "core", "irq_entry", "irq_id", NULL,
+ NULL, irq_entry, &g_array_index(hooks, LttvTraceHook, 4));
+
+ lttv_trace_find_hook(ts->parent.t, "core", "irq_exit", NULL, NULL, NULL,
+ irq_exit, &g_array_index(hooks, LttvTraceHook, 5));
+
+ lttv_trace_find_hook(ts->parent.t, "core", "schedchange", "in", "out",
+ "out_state", schedchange, &g_array_index(hooks, LttvTraceHook, 6));
+
+ lttv_trace_find_hook(ts->parent.t, "core", "process_fork", "child_pid",
+ NULL, NULL, process_fork, &g_array_index(hooks, LttvTraceHook, 7));
+
+ lttv_trace_find_hook(ts->parent.t, "core", "process_exit", NULL, NULL,
+ NULL, process_exit, &g_array_index(hooks, LttvTraceHook, 8));
+
+ /* Add these hooks to each before_event_by_id hooks list */
+
+ nb_tracefile = ltt_trace_control_tracefile_number(ts->parent.t) +
+ ltt_trace_per_cpu_tracefile_number(ts->parent.t);
+
+ for(j = 0 ; j < nb_tracefile ; j++) {
+ tfs = LTTV_TRACEFILE_STATE(ts->parent.tracefiles[j]);
+
+ for(k = 0 ; k < hooks->len ; k++) {
+ hook = g_array_index(hooks, LttvTraceHook, k);
+ lttv_hooks_add(lttv_hooks_by_id_find(tfs->parent.after_event_by_id,
+ hook.id), hook.h, &g_array_index(hooks, LttvTraceHook, k));
+ }
+ }
+ lttv_attribute_find(self->parent.a, LTTV_STATE_HOOKS, LTTV_POINTER, &val);
+ *(val.v_pointer) = hooks;
+ }
+}
+
+
+void lttv_state_remove_event_hooks(LttvTracesetState *self)
+{
+ LttvTraceset *traceset = self->parent.ts;
+
+ guint i, j, k, nb_trace, nb_tracefile;
+
+ LttvTraceState *ts;
+
+ LttvTracefileState *tfs;
+
+ GArray *hooks;
+
+ LttvTraceHook hook;
+
+ LttvAttributeValue val;
+
+ nb_trace = lttv_traceset_number(traceset);
+ for(i = 0 ; i < nb_trace ; i++) {
+ ts = LTTV_TRACE_STATE(self->parent.traces[i]);
+ lttv_attribute_find(self->parent.a, LTTV_STATE_HOOKS, LTTV_POINTER, &val);
+ hooks = *(val.v_pointer);
+
+ /* Add these hooks to each before_event_by_id hooks list */
+
+ nb_tracefile = ltt_trace_control_tracefile_number(ts->parent.t) +
+ ltt_trace_per_cpu_tracefile_number(ts->parent.t);
+
+ for(j = 0 ; j < nb_tracefile ; j++) {
+ tfs = LTTV_TRACEFILE_STATE(ts->parent.tracefiles[j]);
+
+ for(k = 0 ; k < hooks->len ; k++) {
+ hook = g_array_index(hooks, LttvTraceHook, k);
+ lttv_hooks_remove_data(
+ lttv_hooks_by_id_find(tfs->parent.after_event_by_id,
+ hook.id), hook.h, &g_array_index(hooks, LttvTraceHook, k));
+ }
+ }
+ g_array_free(hooks, TRUE);
+ }
+}
+
+
+static gboolean block_start(void *hook_data, void *call_data)
+{
+ LttvTracefileState *self = (LttvTracefileState *)call_data;
+
+ LttvTracefileState *tfcs;
+
+ LttvTraceState *tcs = (LttvTraceState *)(self->parent.t_context);
+
+ LttEventPosition *ep;
+
+ guint i, nb_block, nb_event, nb_tracefile;
+
+ LttTracefile *tf;
+
+ LttvAttribute *saved_states_tree, *saved_state_tree;
+
+ LttvAttributeValue value;
+
+ ep = ltt_event_position_new();
+ nb_tracefile = ltt_trace_control_tracefile_number(tcs->parent.t) +
+ ltt_trace_per_cpu_tracefile_number(tcs->parent.t);
+
+ /* Count the number of events added since the last block end in any
+ tracefile. */
+
+ for(i = 0 ; i < nb_tracefile ; i++) {
+ tfcs = (LttvTracefileState *)tcs->parent.tracefiles[i];
+ ltt_event_position(tfcs->parent.e, ep);
+ ltt_event_position_get(ep, &nb_block, &nb_event, &tf);
+ tcs->nb_event += nb_event - tfcs->saved_position;
+ tfcs->saved_position = nb_event;
+ }
+ g_free(ep);
+
+ if(tcs->nb_event >= tcs->save_interval) {
+ saved_states_tree = lttv_attribute_find_subdir(tcs->parent.t_a,
+ LTTV_STATE_SAVED_STATES);
+ saved_state_tree = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
+ value = lttv_attribute_add(saved_states_tree,
+ lttv_attribute_get_number(saved_states_tree), LTTV_GOBJECT);
+ *(value.v_gobject) = (GObject *)saved_state_tree;
+ value = lttv_attribute_add(saved_state_tree, LTTV_STATE_TIME, LTTV_TIME);
+ *(value.v_time) = self->parent.timestamp;
+ lttv_state_save(tcs, saved_state_tree);
+ tcs->nb_event = 0;
+ g_debug("Saving state at time %lu.%lu", self->parent.timestamp.tv_sec,
+ self->parent.timestamp.tv_nsec);
+ }
+ *(tcs->max_time_state_recomputed_in_seek) = self->parent.timestamp;
+ return FALSE;
+}
+
+
+static gboolean block_end(void *hook_data, void *call_data)
+{
+ LttvTracefileState *self = (LttvTracefileState *)call_data;
+
+ LttvTraceState *tcs = (LttvTraceState *)(self->parent.t_context);
+
+ LttTracefile *tf;
+
+ LttEventPosition *ep;
+
+ guint nb_block, nb_event;
+
+ ep = ltt_event_position_new();
+ ltt_event_position(self->parent.e, ep);
+ ltt_event_position_get(ep, &nb_block, &nb_event, &tf);
+ tcs->nb_event += nb_event - self->saved_position + 1;
+ self->saved_position = 0;
+ *(tcs->max_time_state_recomputed_in_seek) = self->parent.timestamp;
+ g_free(ep);
+}
+
+
+void lttv_state_save_add_event_hooks(LttvTracesetState *self)
+{
+ LttvTraceset *traceset = self->parent.ts;
+
+ guint i, j, k, nb_trace, nb_tracefile;
+
+ LttvTraceState *ts;
+
+ LttvTracefileState *tfs;
+
+ LttvTraceHook hook_start, hook_end;
+
+ nb_trace = lttv_traceset_number(traceset);
+ for(i = 0 ; i < nb_trace ; i++) {
+ ts = (LttvTraceState *)self->parent.traces[i];
+ lttv_trace_find_hook(ts->parent.t, "core","block_start",NULL,
+ NULL, NULL, block_start, &hook_start);
+ lttv_trace_find_hook(ts->parent.t, "core","block_end",NULL,
+ NULL, NULL, block_end, &hook_end);
+
+ nb_tracefile = ltt_trace_control_tracefile_number(ts->parent.t) +
+ ltt_trace_per_cpu_tracefile_number(ts->parent.t);
+
+ for(j = 0 ; j < nb_tracefile ; j++) {
+ tfs = LTTV_TRACEFILE_STATE(ts->parent.tracefiles[j]);
+ lttv_hooks_add(lttv_hooks_by_id_find(tfs->parent.after_event_by_id,
+ hook_start.id), hook_start.h, NULL);
+ lttv_hooks_add(lttv_hooks_by_id_find(tfs->parent.after_event_by_id,
+ hook_end.id), hook_end.h, NULL);
+ }
+ }
+}
+
+
+void lttv_state_save_remove_event_hooks(LttvTracesetState *self)
+{
+ LttvTraceset *traceset = self->parent.ts;
+
+ guint i, j, k, nb_trace, nb_tracefile;
+
+ LttvTraceState *ts;
+
+ LttvTracefileState *tfs;
+
+ LttvTraceHook hook_start, hook_end;
+
+ nb_trace = lttv_traceset_number(traceset);
+ for(i = 0 ; i < nb_trace ; i++) {
+ ts = LTTV_TRACE_STATE(self->parent.traces[i]);
+ lttv_trace_find_hook(ts->parent.t, "core","block_start",NULL,
+ NULL, NULL, block_start, &hook_start);
+
+ lttv_trace_find_hook(ts->parent.t, "core","block_end",NULL,
+ NULL, NULL, block_end, &hook_end);
+
+ nb_tracefile = ltt_trace_control_tracefile_number(ts->parent.t) +
+ ltt_trace_per_cpu_tracefile_number(ts->parent.t);
+
+ for(j = 0 ; j < nb_tracefile ; j++) {
+ tfs = LTTV_TRACEFILE_STATE(ts->parent.tracefiles[j]);
+ lttv_hooks_remove_data(lttv_hooks_by_id_find(
+ tfs->parent.after_event_by_id, hook_start.id), hook_start.h, NULL);
+ lttv_hooks_remove_data(lttv_hooks_by_id_find(
+ tfs->parent.after_event_by_id, hook_end.id), hook_end.h, NULL);
+ }
+ }
+}
+
+
+void lttv_state_traceset_seek_time_closest(LttvTracesetState *self, LttTime t)
+{
+ LttvTraceset *traceset = self->parent.ts;
+
+ guint i, j, nb_trace, nb_saved_state;
+
+ int min_pos, mid_pos, max_pos;
+
+ LttvTraceState *tcs;
+
+ LttvAttributeValue value;
+
+ LttvAttributeType type;
+
+ LttvAttributeName name;
+
+ LttvAttribute *saved_states_tree, *saved_state_tree, *closest_tree;
+
+ nb_trace = lttv_traceset_number(traceset);
+ for(i = 0 ; i < nb_trace ; i++) {
+ tcs = (LttvTraceState *)self->parent.traces[i];
+
+ if(ltt_time_compare(t, *(tcs->max_time_state_recomputed_in_seek)) < 0) {
+ saved_states_tree = lttv_attribute_find_subdir(tcs->parent.t_a,
+ LTTV_STATE_SAVED_STATES);
+ min_pos = -1;
+
+ if(saved_states_tree) {
+ max_pos = lttv_attribute_get_number(saved_states_tree) - 1;
+ mid_pos = max_pos / 2;
+ while(min_pos < max_pos) {
+ type = lttv_attribute_get(saved_states_tree, mid_pos, &name, &value);
+ g_assert(type == LTTV_GOBJECT);
+ saved_state_tree = *((LttvAttribute **)(value.v_gobject));
+ type = lttv_attribute_get_by_name(saved_state_tree, LTTV_STATE_TIME,
+ &value);
+ g_assert(type == LTTV_TIME);
+ if(ltt_time_compare(*(value.v_time), t) < 0) {
+ min_pos = mid_pos;
+ closest_tree = saved_state_tree;
+ }
+ else max_pos = mid_pos - 1;
+
+ mid_pos = (min_pos + max_pos + 1) / 2;
+ }
+ }
+
+ /* restore the closest earlier saved state */
+ 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 {
+ restore_init_state(tcs);
+ lttv_process_trace_seek_time(&(tcs->parent), ltt_time_zero);
+ }
+ }
+ /* We want to seek quickly without restoring/updating the state */
+ else {
+ restore_init_state(tcs);
+ lttv_process_trace_seek_time(&(tcs->parent), t);
+ }
+ }
+}
+
+
+static void
+traceset_state_instance_init (GTypeInstance *instance, gpointer g_class)
+{
+}
+
+
+static void
+traceset_state_finalize (LttvTracesetState *self)
+{
+ G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE))->
+ finalize(G_OBJECT(self));
+}
+
+
+static void
+traceset_state_class_init (LttvTracesetContextClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
+
+ gobject_class->finalize = (void (*)(GObject *self)) traceset_state_finalize;
+ klass->init = (void (*)(LttvTracesetContext *self, LttvTraceset *ts))init;
+ klass->fini = (void (*)(LttvTracesetContext *self))fini;
+ klass->new_traceset_context = new_traceset_context;
+ klass->new_trace_context = new_trace_context;
+ klass->new_tracefile_context = new_tracefile_context;
+}
+
+
+GType
+lttv_traceset_state_get_type(void)
+{
+ static GType type = 0;
+ if (type == 0) {
+ static const GTypeInfo info = {
+ sizeof (LttvTracesetStateClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) traceset_state_class_init, /* class_init */
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (LttvTracesetState),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) traceset_state_instance_init /* instance_init */
+ };
+
+ type = g_type_register_static (LTTV_TRACESET_CONTEXT_TYPE, "LttvTracesetStateType",
+ &info, 0);
+ }
+ return type;
+}
+
+
+static void
+trace_state_instance_init (GTypeInstance *instance, gpointer g_class)
+{
+}
+
+
+static void
+trace_state_finalize (LttvTraceState *self)
+{
+ G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_CONTEXT_TYPE))->
+ finalize(G_OBJECT(self));
+}
+
+
+static void
+trace_state_class_init (LttvTraceStateClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
+
+ gobject_class->finalize = (void (*)(GObject *self)) trace_state_finalize;
+ klass->state_save = state_save;
+ klass->state_restore = state_restore;
+ klass->state_saved_free = state_saved_free;
+}
+
+
+GType
+lttv_trace_state_get_type(void)
+{
+ static GType type = 0;
+ if (type == 0) {
+ static const GTypeInfo info = {
+ sizeof (LttvTraceStateClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) trace_state_class_init, /* class_init */
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (LttvTraceState),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) trace_state_instance_init /* instance_init */
+ };
+
+ type = g_type_register_static (LTTV_TRACE_CONTEXT_TYPE,
+ "LttvTraceStateType", &info, 0);
+ }
+ return type;
+}
+
+
+static void
+tracefile_state_instance_init (GTypeInstance *instance, gpointer g_class)
+{
+}
+
+
+static void
+tracefile_state_finalize (LttvTracefileState *self)
+{
+ G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_CONTEXT_TYPE))->
+ finalize(G_OBJECT(self));
+}
+
+
+static void
+tracefile_state_class_init (LttvTracefileStateClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
+
+ gobject_class->finalize = (void (*)(GObject *self)) tracefile_state_finalize;
+}
+
+
+GType
+lttv_tracefile_state_get_type(void)
+{
+ static GType type = 0;
+ if (type == 0) {
+ static const GTypeInfo info = {
+ sizeof (LttvTracefileStateClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) tracefile_state_class_init, /* class_init */
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (LttvTracefileState),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) tracefile_state_instance_init /* instance_init */
+ };
+
+ type = g_type_register_static (LTTV_TRACEFILE_CONTEXT_TYPE,
+ "LttvTracefileStateType", &info, 0);
+ }
+ return type;
+}
+
+
+static void module_init()
+{
+ LTTV_STATE_UNNAMED = g_quark_from_string("unnamed");
+ LTTV_STATE_MODE_UNKNOWN = g_quark_from_string("unknown execution mode");
+ LTTV_STATE_USER_MODE = g_quark_from_string("user mode");
+ LTTV_STATE_WAIT_FORK = g_quark_from_string("wait fork");
+ LTTV_STATE_SYSCALL = g_quark_from_string("system call");
+ LTTV_STATE_TRAP = g_quark_from_string("trap");
+ LTTV_STATE_IRQ = g_quark_from_string("irq");
+ LTTV_STATE_SUBMODE_UNKNOWN = g_quark_from_string("unknown submode");
+ LTTV_STATE_SUBMODE_NONE = g_quark_from_string("(no submode)");
+ LTTV_STATE_WAIT_CPU = g_quark_from_string("wait for cpu");
+ LTTV_STATE_EXIT = g_quark_from_string("exiting");
+ LTTV_STATE_WAIT = g_quark_from_string("wait for I/O");
+ LTTV_STATE_RUN = g_quark_from_string("running");
+ LTTV_STATE_TRACEFILES = g_quark_from_string("tracefiles");
+ LTTV_STATE_PROCESSES = g_quark_from_string("processes");
+ LTTV_STATE_PROCESS = g_quark_from_string("process");
+ LTTV_STATE_EVENT = g_quark_from_string("event");
+ LTTV_STATE_SAVED_STATES = g_quark_from_string("saved states");
+ 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()
+{
+}
+
+
+LTTV_MODULE("state", "State computation", \
+ "Update the system state, possibly saving it at intervals", \
+ module_init, module_destroy)
+
+
+
--- /dev/null
+/* This file is part of the Linux Trace Toolkit viewer
+ * Copyright (C) 2003-2004 Michel Dagenais
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+#ifndef STATE_H
+#define STATE_H
+
+#include <glib.h>
+#include <lttv/tracecontext.h>
+#include <stdio.h>
+
+/* The operating system state, kept during the trace analysis,
+ contains a subset of the real operating system state,
+ sufficient for the analysis, and possibly organized quite differently.
+
+ The state information is added to LttvTracesetContext, LttvTraceContext
+ and LttvTracefileContext objects, used by processTrace, through
+ subtyping. The context objects already reflect the multiple tracefiles
+ (one per cpu) per trace and multiple traces per trace set. The state
+ objects defined here simply add fields to the relevant context objects.
+
+ There is no traceset specific state yet. It may eventually contains such
+ things as clock differences over time.
+
+ The trace state currently consists in a process table.
+
+ The tracefile level state relates to the associated cpu. It contains the
+ position of the current event in the tracefile (since the state depends on
+ which events have been processed) and a pointer to the current process,
+ in the process table, being run on that cpu.
+
+ For each process in the process table, various informations such as exec
+ file name, pid, ppid and creation time are stored. Each process state also
+ contains an execution mode stack (e.g. irq within system call, called
+ from user mode). */
+
+typedef struct _LttvTracesetState LttvTracesetState;
+typedef struct _LttvTracesetStateClass LttvTracesetStateClass;
+
+typedef struct _LttvTraceState LttvTraceState;
+typedef struct _LttvTraceStateClass LttvTraceStateClass;
+
+typedef struct _LttvTracefileState LttvTracefileState;
+typedef struct _LttvTracefileStateClass LttvTracefileStateClass;
+
+void lttv_state_add_event_hooks(LttvTracesetState *self);
+
+void lttv_state_remove_event_hooks(LttvTracesetState *self);
+
+void lttv_state_save_add_event_hooks(LttvTracesetState *self);
+
+void lttv_state_save_remove_event_hooks(LttvTracesetState *self);
+
+void lttv_state_traceset_seek_time_closest(LttvTracesetState *self, LttTime t);
+
+/* The LttvProcessState structure defines the current state for each process.
+ A process can make system calls (in some rare cases nested) and receive
+ interrupts/faults. For instance, a process may issue a system call,
+ generate a page fault while reading an argument from user space, and
+ get caught by an interrupt. To represent these nested states, an
+ execution mode stack is maintained. The stack bottom is normal user mode
+ and the top of stack is the current execution mode.
+
+ The execution mode stack tells about the process status, execution mode and
+ submode (interrupt, system call or IRQ number). All these could be
+ defined as enumerations but may need extensions (e.g. new process state).
+ GQuark are thus used. They are as easy to manipulate as integers but have
+ a string associated, just like enumerations.
+
+ The execution mode is one of "user mode", "kernel thread", "system call",
+ "interrupt request", "fault". */
+
+typedef GQuark LttvExecutionMode;
+
+extern LttvExecutionMode
+ LTTV_STATE_USER_MODE,
+ LTTV_STATE_SYSCALL,
+ LTTV_STATE_TRAP,
+ LTTV_STATE_IRQ,
+ LTTV_STATE_MODE_UNKNOWN;
+
+
+/* The submode number depends on the execution mode. For user mode or kernel
+ thread, which are the normal mode (execution mode stack bottom),
+ it is set to "none". For interrupt requests, faults and system calls,
+ it is set respectively to the interrupt name (e.g. "timer"), fault name
+ (e.g. "page fault"), and system call name (e.g. "select"). */
+
+typedef GQuark LttvExecutionSubmode;
+
+extern LttvExecutionSubmode
+ LTTV_STATE_SUBMODE_NONE,
+ LTTV_STATE_SUBMODE_UNKNOWN;
+
+/* The process status is one of "running", "wait-cpu" (runnable), or "wait-*"
+ where "*" describes the resource waited for (e.g. timer, process,
+ disk...). */
+
+typedef GQuark LttvProcessStatus;
+
+extern LttvProcessStatus
+ LTTV_STATE_UNNAMED,
+ LTTV_STATE_WAIT_FORK,
+ LTTV_STATE_WAIT_CPU,
+ LTTV_STATE_EXIT,
+ LTTV_STATE_WAIT,
+ LTTV_STATE_RUN;
+
+
+typedef struct _LttvExecutionState {
+ LttvExecutionMode t;
+ LttvExecutionSubmode n;
+ LttTime entry;
+ LttTime change;
+ LttvProcessStatus s;
+} LttvExecutionState;
+
+
+typedef struct _LttvProcessState {
+ guint pid;
+ guint ppid;
+ LttTime creation_time;
+ LttTime insertion_time;
+ GQuark name;
+ GQuark pid_time;
+ GArray *execution_stack; /* Array of LttvExecutionState */
+ LttvExecutionState *state; /* Top of interrupt stack */
+ GQuark last_cpu; /* Last CPU where process was scheduled */
+ /* opened file descriptors, address map?... */
+} LttvProcessState;
+
+
+LttvProcessState *
+lttv_state_find_process(LttvTracefileState *tfs, guint pid);
+
+LttvProcessState *
+lttv_state_find_process_from_trace(LttvTraceState *ts, GQuark cpu, guint pid);
+
+LttvProcessState *
+lttv_state_find_process_or_create(LttvTracefileState *tfs, guint pid);
+
+LttvProcessState *
+lttv_state_create_process(LttvTracefileState *tfs, LttvProcessState *parent,
+ guint pid);
+
+void lttv_state_write(LttvTraceState *self, LttTime t, FILE *fp);
+
+/* The LttvTracesetState, LttvTraceState and LttvTracefileState types
+ inherit from the corresponding Context objects defined in processTrace. */
+
+#define LTTV_TRACESET_STATE_TYPE (lttv_traceset_state_get_type ())
+#define LTTV_TRACESET_STATE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LTTV_TRACESET_STATE_TYPE, LttvTracesetState))
+#define LTTV_TRACESET_STATE_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST ((vtable), LTTV_TRACESET_STATE_TYPE, LttvTracesetStateClass))
+#define LTTV_IS_TRACESET_STATE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LTTV_TRACESET_STATE_TYPE))
+#define LTTV_IS_TRACESET_STATE_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), LTTV_TRACESET_STATE_TYPE))
+#define LTTV_TRACESET_STATE_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), LTTV_TRACESET_STATE_TYPE, LttvTracesetStateClass))
+
+struct _LttvTracesetState {
+ LttvTracesetContext parent;
+};
+
+struct _LttvTracesetStateClass {
+ LttvTracesetContextClass parent;
+};
+
+GType lttv_traceset_state_get_type (void);
+
+
+#define LTTV_TRACE_STATE_TYPE (lttv_trace_state_get_type ())
+#define LTTV_TRACE_STATE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LTTV_TRACE_STATE_TYPE, LttvTraceState))
+#define LTTV_TRACE_STATE_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST ((vtable), LTTV_TRACE_STATE_TYPE, LttvTraceStateClass))
+#define LTTV_IS_TRACE_STATE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LTTV_TRACE_STATE_TYPE))
+#define LTTV_IS_TRACE_STATE_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), LTTV_TRACE_STATE_TYPE))
+#define LTTV_TRACE_STATE_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), LTTV_TRACE_STATE_TYPE, LttvTraceStateClass))
+
+struct _LttvTraceState {
+ LttvTraceContext parent;
+
+ GHashTable *processes; /* LttvProcessState objects indexed by pid */
+ guint nb_event, save_interval;
+ /* Block/char devices, locks, memory pages... */
+ GQuark *eventtype_names;
+ GQuark *syscall_names;
+ GQuark *trap_names;
+ GQuark *irq_names;
+ LttTime *max_time_state_recomputed_in_seek;
+};
+
+struct _LttvTraceStateClass {
+ LttvTraceContextClass parent;
+
+ void (*state_save) (LttvTraceState *self, LttvAttribute *container);
+ void (*state_restore) (LttvTraceState *self, LttvAttribute *container);
+ void (*state_saved_free) (LttvTraceState *self, LttvAttribute *container);
+};
+
+GType lttv_trace_state_get_type (void);
+
+void lttv_state_save(LttvTraceState *self, LttvAttribute *container);
+
+void lttv_state_restore(LttvTraceState *self, LttvAttribute *container);
+
+void lttv_state_state_saved_free(LttvTraceState *self,
+ LttvAttribute *container);
+
+
+#define LTTV_TRACEFILE_STATE_TYPE (lttv_tracefile_state_get_type ())
+#define LTTV_TRACEFILE_STATE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LTTV_TRACEFILE_STATE_TYPE, LttvTracefileState))
+#define LTTV_TRACEFILE_STATE_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST ((vtable), LTTV_TRACEFILE_STATE_TYPE, LttvTracefileStateClass))
+#define LTTV_IS_TRACEFILE_STATE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LTTV_TRACEFILE_STATE_TYPE))
+#define LTTV_IS_TRACEFILE_STATE_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), LTTV_TRACEFILE_STATE_TYPE))
+#define LTTV_TRACEFILE_STATE_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), LTTV_TRACEFILE_STATE_TYPE, LttvTracefileStateClass))
+
+struct _LttvTracefileState {
+ LttvTracefileContext parent;
+
+ LttvProcessState *process;
+ GQuark cpu_name;
+ guint saved_position;
+};
+
+struct _LttvTracefileStateClass {
+ LttvTracefileContextClass parent;
+};
+
+GType lttv_tracefile_state_get_type (void);
+
+
+#endif // STATE_H
--- /dev/null
+/* This file is part of the Linux Trace Toolkit viewer
+ * Copyright (C) 2003-2004 Michel Dagenais
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+
+#include <stdio.h>
+#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>
+
+#define BUF_SIZE 256
+
+GQuark
+ LTTV_STATS_PROCESS_UNKNOWN,
+ LTTV_STATS_PROCESSES,
+ LTTV_STATS_CPU,
+ LTTV_STATS_MODE_TYPES,
+ LTTV_STATS_MODES,
+ LTTV_STATS_SUBMODES,
+ LTTV_STATS_EVENT_TYPES,
+ LTTV_STATS_CPU_TIME,
+ LTTV_STATS_ELAPSED_TIME,
+ LTTV_STATS_EVENTS,
+ LTTV_STATS_EVENTS_COUNT,
+ LTTV_STATS_USE_COUNT,
+ LTTV_STATS,
+ LTTV_STATS_TRACEFILES,
+ LTTV_STATS_SUMMED;
+
+static GQuark
+ LTTV_STATS_BEFORE_HOOKS,
+ LTTV_STATS_AFTER_HOOKS;
+
+static void remove_all_processes(GHashTable *processes);
+
+static void
+find_event_tree(LttvTracefileStats *tfcs, GQuark process, GQuark cpu,
+ GQuark mode, GQuark sub_mode, LttvAttribute **events_tree,
+ LttvAttribute **event_types_tree);
+
+static void
+init(LttvTracesetStats *self, LttvTraceset *ts)
+{
+ guint i, j, nb_trace, nb_tracefile;
+
+ LttvTraceContext *tc;
+
+ LttvTraceStats *tcs;
+
+ LttvTracefileContext *tfc;
+
+ LttvTracefileStats *tfcs;
+
+ 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 =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 = 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 = 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,
+ &tfcs->current_event_types_tree);
+ }
+ }
+}
+
+
+static void
+fini(LttvTracesetStats *self)
+{
+ guint i, j, nb_trace, nb_tracefile;
+
+ LttvTraceset *ts;
+
+ LttvTraceContext *tc;
+
+ LttvTraceStats *tcs;
+
+ LttvTracefileContext *tfc;
+
+ LttvTracefileStats *tfcs;
+
+ LttTime timestamp = {0,0};
+
+ 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_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]);
+ tfcs->stats = NULL;
+ tfcs->current_events_tree = NULL;
+ tfcs->current_event_types_tree = NULL;
+ }
+ }
+ LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE))->
+ fini((LttvTracesetContext *)self);
+}
+
+
+static LttvTracesetContext *
+new_traceset_context(LttvTracesetContext *self)
+{
+ return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATS_TYPE, NULL));
+}
+
+
+static LttvTraceContext *
+new_trace_context(LttvTracesetContext *self)
+{
+ return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATS_TYPE, NULL));
+}
+
+
+static LttvTracefileContext *
+new_tracefile_context(LttvTracesetContext *self)
+{
+ return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATS_TYPE, NULL));
+}
+
+
+static void
+traceset_stats_instance_init (GTypeInstance *instance, gpointer g_class)
+{
+}
+
+
+static void
+traceset_stats_finalize (LttvTracesetStats *self)
+{
+ G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE))->
+ finalize(G_OBJECT(self));
+}
+
+
+static void
+traceset_stats_class_init (LttvTracesetContextClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
+
+ gobject_class->finalize = (void (*)(GObject *self)) traceset_stats_finalize;
+ klass->init = (void (*)(LttvTracesetContext *self, LttvTraceset *ts))init;
+ klass->fini = (void (*)(LttvTracesetContext *self))fini;
+ klass->new_traceset_context = new_traceset_context;
+ klass->new_trace_context = new_trace_context;
+ klass->new_tracefile_context = new_tracefile_context;
+}
+
+
+GType
+lttv_traceset_stats_get_type(void)
+{
+ static GType type = 0;
+ if (type == 0) {
+ static const GTypeInfo info = {
+ sizeof (LttvTracesetStatsClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) traceset_stats_class_init, /* class_init */
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (LttvTracesetStats),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) traceset_stats_instance_init /* instance_init */
+ };
+
+ type = g_type_register_static (LTTV_TRACESET_STATE_TYPE, "LttvTracesetStatsType",
+ &info, 0);
+ }
+ return type;
+}
+
+
+static void
+trace_stats_instance_init (GTypeInstance *instance, gpointer g_class)
+{
+}
+
+
+static void
+trace_stats_finalize (LttvTraceStats *self)
+{
+ G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_STATE_TYPE))->
+ finalize(G_OBJECT(self));
+}
+
+
+static void
+trace_stats_class_init (LttvTraceContextClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
+
+ gobject_class->finalize = (void (*)(GObject *self)) trace_stats_finalize;
+}
+
+
+GType
+lttv_trace_stats_get_type(void)
+{
+ static GType type = 0;
+ if (type == 0) {
+ static const GTypeInfo info = {
+ sizeof (LttvTraceStatsClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) trace_stats_class_init, /* class_init */
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (LttvTraceStats),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) trace_stats_instance_init /* instance_init */
+ };
+
+ type = g_type_register_static (LTTV_TRACE_STATE_TYPE,
+ "LttvTraceStatsType", &info, 0);
+ }
+ return type;
+}
+
+
+static void
+tracefile_stats_instance_init (GTypeInstance *instance, gpointer g_class)
+{
+}
+
+
+static void
+tracefile_stats_finalize (LttvTracefileStats *self)
+{
+ G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_STATE_TYPE))->
+ finalize(G_OBJECT(self));
+}
+
+
+static void
+tracefile_stats_class_init (LttvTracefileStatsClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
+
+ gobject_class->finalize = (void (*)(GObject *self)) tracefile_stats_finalize;
+}
+
+
+GType
+lttv_tracefile_stats_get_type(void)
+{
+ static GType type = 0;
+ if (type == 0) {
+ static const GTypeInfo info = {
+ sizeof (LttvTracefileStatsClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) tracefile_stats_class_init, /* class_init */
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (LttvTracefileStats),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) tracefile_stats_instance_init /* instance_init */
+ };
+
+ type = g_type_register_static (LTTV_TRACEFILE_STATE_TYPE,
+ "LttvTracefileStatsType", &info, 0);
+ }
+ return type;
+}
+
+
+static void
+find_event_tree(LttvTracefileStats *tfcs, GQuark process, GQuark cpu,
+ GQuark mode, GQuark sub_mode, LttvAttribute **events_tree,
+ LttvAttribute **event_types_tree)
+{
+ LttvAttribute *a;
+
+ LttvTraceStats *tcs = LTTV_TRACE_STATS(tfcs->parent.parent.t_context);
+ a = lttv_attribute_find_subdir(tcs->stats, LTTV_STATS_PROCESSES);
+ a = lttv_attribute_find_subdir(a, tfcs->parent.process->pid_time);
+ a = lttv_attribute_find_subdir(a, LTTV_STATS_CPU);
+ a = lttv_attribute_find_subdir(a, tfcs->parent.cpu_name);
+ a = lttv_attribute_find_subdir(a, LTTV_STATS_MODE_TYPES);
+ a = lttv_attribute_find_subdir(a, tfcs->parent.process->state->t);
+ a = lttv_attribute_find_subdir(a, LTTV_STATS_SUBMODES);
+ a = lttv_attribute_find_subdir(a, tfcs->parent.process->state->n);
+ *events_tree = a;
+ a = lttv_attribute_find_subdir(a, LTTV_STATS_EVENT_TYPES);
+ *event_types_tree = a;
+}
+
+
+static void update_event_tree(LttvTracefileStats *tfcs)
+{
+ LttvExecutionState *es = tfcs->parent.process->state;
+
+ find_event_tree(tfcs, tfcs->parent.process->pid_time, tfcs->parent.cpu_name,
+ es->t, es->n, &(tfcs->current_events_tree),
+ &(tfcs->current_event_types_tree));
+}
+
+
+static void mode_change(LttvTracefileStats *tfcs)
+{
+ LttvAttributeValue cpu_time;
+
+ LttTime delta;
+
+ lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CPU_TIME,
+ LTTV_TIME, &cpu_time);
+ delta = ltt_time_sub(tfcs->parent.parent.timestamp,
+ tfcs->parent.process->state->change);
+ *(cpu_time.v_time) = ltt_time_add(*(cpu_time.v_time), delta);
+}
+
+
+static void mode_end(LttvTracefileStats *tfcs)
+{
+ LttvAttributeValue elapsed_time, cpu_time;
+
+ LttTime delta;
+
+ lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_ELAPSED_TIME,
+ LTTV_TIME, &elapsed_time);
+ delta = ltt_time_sub(tfcs->parent.parent.timestamp,
+ tfcs->parent.process->state->entry);
+ *(elapsed_time.v_time) = ltt_time_add(*(elapsed_time.v_time), delta);
+
+ lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CPU_TIME,
+ LTTV_TIME, &cpu_time);
+ delta = ltt_time_sub(tfcs->parent.parent.timestamp,
+ tfcs->parent.process->state->change);
+ *(cpu_time.v_time) = ltt_time_add(*(cpu_time.v_time), delta);
+}
+
+
+static gboolean before_syscall_entry(void *hook_data, void *call_data)
+{
+ mode_change((LttvTracefileStats *)call_data);
+ return FALSE;
+}
+
+
+static gboolean after_syscall_entry(void *hook_data, void *call_data)
+{
+ update_event_tree((LttvTracefileStats *)call_data);
+ return FALSE;
+}
+
+
+gboolean before_syscall_exit(void *hook_data, void *call_data)
+{
+ mode_end((LttvTracefileStats *)call_data);
+ return FALSE;
+}
+
+
+static gboolean after_syscall_exit(void *hook_data, void *call_data)
+{
+ update_event_tree((LttvTracefileStats *)call_data);
+ return FALSE;
+}
+
+
+gboolean before_trap_entry(void *hook_data, void *call_data)
+{
+ mode_change((LttvTracefileStats *)call_data);
+ return FALSE;
+}
+
+
+static gboolean after_trap_entry(void *hook_data, void *call_data)
+{
+ update_event_tree((LttvTracefileStats *)call_data);
+ return FALSE;
+}
+
+
+gboolean before_trap_exit(void *hook_data, void *call_data)
+{
+ mode_end((LttvTracefileStats *)call_data);
+ return FALSE;
+}
+
+
+gboolean after_trap_exit(void *hook_data, void *call_data)
+{
+ update_event_tree((LttvTracefileStats *)call_data);
+ return FALSE;
+}
+
+
+gboolean before_irq_entry(void *hook_data, void *call_data)
+{
+ mode_change((LttvTracefileStats *)call_data);
+ return FALSE;
+}
+
+
+gboolean after_irq_entry(void *hook_data, void *call_data)
+{
+ update_event_tree((LttvTracefileStats *)call_data);
+ return FALSE;
+}
+
+
+gboolean before_irq_exit(void *hook_data, void *call_data)
+{
+ mode_end((LttvTracefileStats *)call_data);
+ return FALSE;
+}
+
+
+gboolean after_irq_exit(void *hook_data, void *call_data)
+{
+ update_event_tree((LttvTracefileStats *)call_data);
+ return FALSE;
+}
+
+
+gboolean before_schedchange(void *hook_data, void *call_data)
+{
+ LttvTraceHook *h = (LttvTraceHook *)hook_data;
+
+ LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
+
+ guint pid_in, pid_out, state_out;
+
+ LttvProcessState *process;
+
+ pid_in = ltt_event_get_unsigned(tfcs->parent.parent.e, h->f1);
+ pid_out = ltt_event_get_unsigned(tfcs->parent.parent.e, h->f2);
+ state_out = ltt_event_get_unsigned(tfcs->parent.parent.e, h->f3);
+
+ /* compute the time for the process to schedule out */
+
+ mode_change(tfcs);
+
+ /* get the information for the process scheduled in */
+
+ process = lttv_state_find_process_or_create(&(tfcs->parent), pid_in);
+
+ find_event_tree(tfcs, process->pid_time, tfcs->parent.cpu_name,
+ process->state->t, process->state->n, &(tfcs->current_events_tree),
+ &(tfcs->current_event_types_tree));
+
+ /* compute the time waiting for the process to schedule in */
+
+ mode_change(tfcs);
+ return FALSE;
+}
+
+
+gboolean process_fork(void *hook_data, void *call_data)
+{
+ /* nothing to do for now */
+ return FALSE;
+}
+
+
+gboolean process_exit(void *hook_data, void *call_data)
+{
+ /* We should probably exit all modes here or we could do that at
+ schedule out. */
+ return FALSE;
+}
+
+
+gboolean every_event(void *hook_data, void *call_data)
+{
+ LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
+
+ LttvAttributeValue v;
+
+ /* The current branch corresponds to the tracefile/process/interrupt state.
+ Statistics are added within it, to count the number of events of this
+ type occuring in this context. A quark has been pre-allocated for each
+ event type and is used as name. */
+
+ lttv_attribute_find(tfcs->current_event_types_tree,
+ ((LttvTraceState *)(tfcs->parent.parent.t_context))->
+ eventtype_names[ltt_event_eventtype_id(tfcs->parent.parent.e)],
+ LTTV_UINT, &v);
+ (*(v.v_uint))++;
+ return FALSE;
+}
+
+
+void
+lttv_stats_sum_trace(LttvTraceStats *self)
+{
+ LttvTraceStats *tcs;
+
+ LttvAttributeType type;
+
+ LttvAttributeValue value;
+
+ LttvAttributeName name;
+
+ unsigned sum;
+
+ 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;
+
+ 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);
+
+ for(l = 0 ; l < nb_submode ; l++) {
+ type = lttv_attribute_get(submodes_tree, l, &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(m = 0 ; m < nb_event_type ; m++) {
+ type = lttv_attribute_get(event_types_tree, m, &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);
+ }
+ lttv_attribute_recursive_add(cpu_events_tree, mode_events_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);
+ }
+}
+
+
+lttv_stats_add_event_hooks(LttvTracesetStats *self)
+{
+ LttvTraceset *traceset = self->parent.parent.ts;
+
+ guint i, j, k, nb_trace, nb_tracefile;
+
+ LttFacility *f;
+
+ LttEventType *et;
+
+ LttvTraceStats *ts;
+
+ LttvTracefileStats *tfs;
+
+ void *hook_data;
+
+ GArray *hooks, *before_hooks, *after_hooks;
+
+ LttvTraceHook hook;
+
+ LttvAttributeValue val;
+
+ nb_trace = lttv_traceset_number(traceset);
+ for(i = 0 ; i < nb_trace ; i++) {
+ ts = (LttvTraceStats *)self->parent.parent.traces[i];
+
+ /* Find the eventtype id for the following events and register the
+ associated by id hooks. */
+
+ hooks = g_array_new(FALSE, FALSE, sizeof(LttvTraceHook));
+ g_array_set_size(hooks, 7);
+
+ lttv_trace_find_hook(ts->parent.parent.t, "core","syscall_entry",
+ "syscall_id", NULL, NULL, before_syscall_entry,
+ &g_array_index(hooks, LttvTraceHook, 0));
+
+ lttv_trace_find_hook(ts->parent.parent.t, "core", "syscall_exit", NULL,
+ NULL, NULL, before_syscall_exit,
+ &g_array_index(hooks, LttvTraceHook, 1));
+
+ lttv_trace_find_hook(ts->parent.parent.t, "core", "trap_entry", "trap_id",
+ NULL, NULL, before_trap_entry,
+ &g_array_index(hooks, LttvTraceHook, 2));
+
+ lttv_trace_find_hook(ts->parent.parent.t, "core", "trap_exit", NULL, NULL,
+ NULL, before_trap_exit, &g_array_index(hooks, LttvTraceHook, 3));
+
+ lttv_trace_find_hook(ts->parent.parent.t, "core", "irq_entry", "irq_id",
+ NULL, NULL, before_irq_entry, &g_array_index(hooks, LttvTraceHook, 4));
+
+ lttv_trace_find_hook(ts->parent.parent.t, "core", "irq_exit", NULL, NULL,
+ NULL, before_irq_exit, &g_array_index(hooks, LttvTraceHook, 5));
+
+ lttv_trace_find_hook(ts->parent.parent.t, "core", "schedchange", "in",
+ "out", "out_state", before_schedchange,
+ &g_array_index(hooks, LttvTraceHook, 6));
+
+ before_hooks = hooks;
+
+ hooks = g_array_new(FALSE, FALSE, sizeof(LttvTraceHook));
+ g_array_set_size(hooks, 8);
+
+ lttv_trace_find_hook(ts->parent.parent.t, "core","syscall_entry",
+ "syscall_id", NULL, NULL, after_syscall_entry,
+ &g_array_index(hooks, LttvTraceHook, 0));
+
+ lttv_trace_find_hook(ts->parent.parent.t, "core", "syscall_exit", NULL,
+ NULL, NULL, after_syscall_exit,
+ &g_array_index(hooks, LttvTraceHook, 1));
+
+ lttv_trace_find_hook(ts->parent.parent.t, "core", "trap_entry", "trap_id",
+ NULL, NULL, after_trap_entry, &g_array_index(hooks, LttvTraceHook, 2));
+
+ lttv_trace_find_hook(ts->parent.parent.t, "core", "trap_exit", NULL, NULL,
+ NULL, after_trap_exit, &g_array_index(hooks, LttvTraceHook, 3));
+
+ lttv_trace_find_hook(ts->parent.parent.t, "core", "irq_entry", "irq_id",
+ NULL, NULL, after_irq_entry, &g_array_index(hooks, LttvTraceHook, 4));
+
+ lttv_trace_find_hook(ts->parent.parent.t, "core", "irq_exit", NULL, NULL,
+ NULL, after_irq_exit, &g_array_index(hooks, LttvTraceHook, 5));
+
+ lttv_trace_find_hook(ts->parent.parent.t, "core", "process_fork",
+ "child_pid", NULL, NULL, process_fork,
+ &g_array_index(hooks, LttvTraceHook, 6));
+
+ lttv_trace_find_hook(ts->parent.parent.t, "core", "process_exit", NULL,
+ NULL, NULL, process_exit, &g_array_index(hooks, LttvTraceHook, 7));
+
+ after_hooks = hooks;
+
+ /* Add these hooks to each before_event_by_id hooks list */
+
+ nb_tracefile = ltt_trace_control_tracefile_number(ts->parent.parent.t) +
+ ltt_trace_per_cpu_tracefile_number(ts->parent.parent.t);
+
+ for(j = 0 ; j < nb_tracefile ; j++) {
+ tfs = LTTV_TRACEFILE_STATS(ts->parent.parent.tracefiles[j]);
+ lttv_hooks_add(tfs->parent.parent.after_event, every_event, NULL);
+
+ for(k = 0 ; k < before_hooks->len ; k++) {
+ hook = g_array_index(before_hooks, LttvTraceHook, k);
+ lttv_hooks_add(lttv_hooks_by_id_find(
+ tfs->parent.parent.before_event_by_id,
+ hook.id), hook.h, &g_array_index(before_hooks, LttvTraceHook, k));
+ }
+ for(k = 0 ; k < after_hooks->len ; k++) {
+ hook = g_array_index(after_hooks, LttvTraceHook, k);
+ lttv_hooks_add(lttv_hooks_by_id_find(
+ tfs->parent.parent.after_event_by_id,
+ hook.id), hook.h, &g_array_index(after_hooks, LttvTraceHook, k));
+ }
+ }
+ lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS,
+ LTTV_POINTER, &val);
+ *(val.v_pointer) = before_hooks;
+ lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS,
+ LTTV_POINTER, &val);
+ *(val.v_pointer) = after_hooks;
+ }
+}
+
+
+lttv_stats_remove_event_hooks(LttvTracesetStats *self)
+{
+ LttvTraceset *traceset = self->parent.parent.ts;
+
+ guint i, j, k, nb_trace, nb_tracefile;
+
+ LttvTraceStats *ts;
+
+ LttvTracefileStats *tfs;
+
+ void *hook_data;
+
+ GArray *before_hooks, *after_hooks;
+
+ LttvTraceHook hook;
+
+ LttvAttributeValue val;
+
+ nb_trace = lttv_traceset_number(traceset);
+ for(i = 0 ; i < nb_trace ; i++) {
+ ts = LTTV_TRACE_STATS(self->parent.parent.traces[i]);
+ lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS,
+ LTTV_POINTER, &val);
+ before_hooks = *(val.v_pointer);
+ lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS,
+ LTTV_POINTER, &val);
+ after_hooks = *(val.v_pointer);
+
+ /* Add these hooks to each before_event_by_id hooks list */
+
+ nb_tracefile = ltt_trace_control_tracefile_number(ts->parent.parent.t) +
+ ltt_trace_per_cpu_tracefile_number(ts->parent.parent.t);
+
+ for(j = 0 ; j < nb_tracefile ; j++) {
+ tfs = LTTV_TRACEFILE_STATS(ts->parent.parent.tracefiles[j]);
+ lttv_hooks_remove_data(tfs->parent.parent.after_event, every_event,
+ NULL);
+
+ for(k = 0 ; k < before_hooks->len ; k++) {
+ hook = g_array_index(before_hooks, LttvTraceHook, k);
+ lttv_hooks_remove_data(
+ lttv_hooks_by_id_find(tfs->parent.parent.before_event_by_id,
+ hook.id), hook.h, &g_array_index(before_hooks, LttvTraceHook, k));
+ }
+ for(k = 0 ; k < after_hooks->len ; k++) {
+ hook = g_array_index(after_hooks, LttvTraceHook, k);
+ lttv_hooks_remove_data(
+ lttv_hooks_by_id_find(tfs->parent.parent.after_event_by_id,
+ hook.id), hook.h, &g_array_index(after_hooks, LttvTraceHook, k));
+ }
+ }
+ g_debug("lttv_stats_remove_event_hooks()");
+ g_array_free(before_hooks, TRUE);
+ g_array_free(after_hooks, TRUE);
+ }
+}
+
+
+static void module_init()
+{
+ LTTV_STATS_PROCESS_UNKNOWN = g_quark_from_string("unknown process");
+ LTTV_STATS_PROCESSES = g_quark_from_string("processes");
+ LTTV_STATS_CPU = g_quark_from_string("cpu");
+ LTTV_STATS_MODE_TYPES = g_quark_from_string("mode_types");
+ LTTV_STATS_MODES = g_quark_from_string("modes");
+ LTTV_STATS_SUBMODES = g_quark_from_string("submodes");
+ LTTV_STATS_EVENT_TYPES = g_quark_from_string("event_types");
+ LTTV_STATS_CPU_TIME = g_quark_from_string("cpu time");
+ LTTV_STATS_ELAPSED_TIME = g_quark_from_string("elapsed time");
+ LTTV_STATS_EVENTS = g_quark_from_string("events");
+ 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. */
--- /dev/null
+/* This file is part of the Linux Trace Toolkit viewer
+ * Copyright (C) 2003-2004 Michel Dagenais
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+#ifndef STATS_H
+#define STATS_H
+
+#include <glib.h>
+#include <lttv/state.h>
+
+/* The statistics are for a complete time interval. These structures differ
+ from the system state since they relate to static components of the
+ system (all processes which existed instead of just the currently
+ existing processes).
+
+ The basic attributes tree to gather for several different execution modes
+ (e.g., user mode, syscall, irq), thereafter called the "events tree",
+ contains the following attributes: the number of events of each type,
+ the total number of events, the number of bytes written, the time spent
+ executing, waiting for a resource, waiting for a cpu, and possibly many
+ others. The name "facility-event_type" below is to be replaced
+ by specific event types (e.g., core-schedchange, code-syscall_entry...).
+
+ event_types/
+ "facility-event_type"
+ events_count
+ cpu_time
+ elapsed_time
+ wait_time
+ bytes_written
+ packets_sent
+ ...
+
+ The events for several different execution modes are joined together to
+ form the "execution modes tree". The name "execution mode" is to be replaced
+ by "system call", "trap", "irq", "user mode" or "kernel thread".
+ The name "submode" is to be replaced by the specific system call, trap or
+ irq name. The "submode" is an empty string if none is applicable, which is
+ the case for "user mode" and "kernel thread".
+
+ An "events tree" for each "execution mode" contains the sum for all its
+ different submodes. An "events tree" in the "execution modes tree" contains
+ the sum for all its different execution modes.
+
+ mode_types/
+ "execution mode"/
+ submodes/
+ "submode"/
+ Events Tree
+ events/
+ Event Tree
+ events/
+ Events Tree
+
+ Each trace set contains an "execution modes tree". While the traces
+ come from possibly different systems, which may differ in their system
+ calls..., most of the system calls will have the same name, even if their
+ actual internal numeric id differs. Categories such as cpu id and process
+ id are not kept since these are specific to each system. When several
+ traces are taken from the same system, these categories may make sense and
+ could eventually be considered.
+
+ Each trace contains a global "execution modes tree", one for each
+ cpu and process, and one for each process/cpu combination. The name
+ "cpu number" stands for the cpu identifier, and "process_id-start_time"
+ is a unique process identifier composed of the process id
+ (unique at any given time but which may be reused over time) concatenated
+ with the process start time.
+
+ modes/
+ Execution Modes Tree
+ cpu/
+ "cpu number"/
+ Execution Modes Tree
+ processes/
+ "process_id-start_time"/
+ exec_file_name
+ parent
+ start_time
+ end_time
+ modes/
+ Execution Modes Tree
+ cpu/
+ "cpu number"/
+ Execution Modes Tree
+
+ All the events and derived values (cpu, elapsed and wait time) are
+ added during the trace analysis in the relevant
+ trace / processes / * / cpu / * / mode_types / * /submodes / *
+ "events tree". To achieve this efficiently, each tracefile context
+ contains a pointer to the current relevant "events tree" and "event_types"
+ tree within it.
+
+ Once all the events are processed, the total number of events is computed
+ within each trace / processes / * / cpu / * / mode_types / * / submodes / *.
+ Then, the "events tree" are summed for all submodes within each mode type
+ and for all mode types within a processes / * / cpu / *
+ "execution modes tree".
+
+ Finally, the "execution modes trees" for all cpu within a process,
+ for all processes, and for all traces are computed. Separately,
+ the "execution modes tree" for each cpu but for all processes within a
+ trace are summed in the trace / cpu / * subtrees.
+
+ */
+
+
+/* The various statistics branch names are GQuarks. They are pre-computed for
+ easy and efficient access */
+
+extern GQuark
+ LTTV_STATS_PROCESS_UNKNOWN,
+ LTTV_STATS_PROCESSES,
+ LTTV_STATS_CPU,
+ LTTV_STATS_MODE_TYPES,
+ LTTV_STATS_SUBMODES,
+ LTTV_STATS_EVENT_TYPES,
+ LTTV_STATS_CPU_TIME,
+ LTTV_STATS_ELAPSED_TIME,
+ LTTV_STATS_EVENTS,
+ LTTV_STATS_EVENTS_COUNT,
+ LTTV_STATS_BEFORE_HOOKS,
+ LTTV_STATS_AFTER_HOOKS;
+
+
+typedef struct _LttvTracesetStats LttvTracesetStats;
+typedef struct _LttvTracesetStatsClass LttvTracesetStatsClass;
+
+typedef struct _LttvTraceStats LttvTraceStats;
+typedef struct _LttvTraceStatsClass LttvTraceStatsClass;
+
+typedef struct _LttvTracefileStats LttvTracefileStats;
+typedef struct _LttvTracefileStatsClass LttvTracefileStatsClass;
+
+gboolean lttv_stats_add_event_hooks(LttvTracesetStats *self);
+
+gboolean lttv_stats_remove_event_hooks(LttvTracesetStats *self);
+
+void lttv_stats_sum_traceset(LttvTracesetStats *self);
+
+void lttv_stats_sum_trace(LttvTraceStats *self);
+
+
+/* The LttvTracesetStats, LttvTraceStats and LttvTracefileStats types
+ inherit from the corresponding State objects defined in state.h.. */
+
+#define LTTV_TRACESET_STATS_TYPE (lttv_traceset_stats_get_type ())
+#define LTTV_TRACESET_STATS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LTTV_TRACESET_STATS_TYPE, LttvTracesetStats))
+#define LTTV_TRACESET_STATS_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST ((vtable), LTTV_TRACESET_STATS_TYPE, LttvTracesetStatsClass))
+#define LTTV_IS_TRACESET_STATS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LTTV_TRACESET_STATS_TYPE))
+#define LTTV_IS_TRACESET_STATS_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), LTTV_TRACESET_STATS_TYPE))
+#define LTTV_TRACESET_STATS_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), LTTV_TRACESET_STATS_TYPE, LttvTracesetStatsClass))
+
+struct _LttvTracesetStats {
+ LttvTracesetState parent;
+
+ LttvAttribute *stats;
+};
+
+struct _LttvTracesetStatsClass {
+ LttvTracesetStateClass parent;
+};
+
+GType lttv_traceset_stats_get_type (void);
+
+
+#define LTTV_TRACE_STATS_TYPE (lttv_trace_stats_get_type ())
+#define LTTV_TRACE_STATS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LTTV_TRACE_STATS_TYPE, LttvTraceStats))
+#define LTTV_TRACE_STATS_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST ((vtable), LTTV_TRACE_STATS_TYPE, LttvTraceStatsClass))
+#define LTTV_IS_TRACE_STATS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LTTV_TRACE_STATS_TYPE))
+#define LTTV_IS_TRACE_STATS_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), LTTV_TRACE_STATS_TYPE))
+#define LTTV_TRACE_STATS_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), LTTV_TRACE_STATS_TYPE, LttvTraceStatsClass))
+
+struct _LttvTraceStats {
+ LttvTraceState parent;
+
+ LttvAttribute *stats;
+};
+
+struct _LttvTraceStatsClass {
+ LttvTraceStateClass parent;
+};
+
+GType lttv_trace_stats_get_type (void);
+
+
+#define LTTV_TRACEFILE_STATS_TYPE (lttv_tracefile_stats_get_type ())
+#define LTTV_TRACEFILE_STATS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LTTV_TRACEFILE_STATS_TYPE, LttvTracefileStats))
+#define LTTV_TRACEFILE_STATS_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST ((vtable), LTTV_TRACEFILE_STATS_TYPE, LttvTracefileStatsClass))
+#define LTTV_IS_TRACEFILE_STATS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LTTV_TRACEFILE_STATS_TYPE))
+#define LTTV_IS_TRACEFILE_STATS_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), LTTV_TRACEFILE_STATS_TYPE))
+#define LTTV_TRACEFILE_STATS_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), LTTV_TRACEFILE_STATS_TYPE, LttvTracefileStatsClass))
+
+struct _LttvTracefileStats {
+ LttvTracefileState parent;
+
+ LttvAttribute *stats;
+ LttvAttribute *current_events_tree;
+ LttvAttribute *current_event_types_tree;
+};
+
+struct _LttvTracefileStatsClass {
+ LttvTracefileStateClass parent;
+};
+
+GType lttv_tracefile_stats_get_type (void);
+
+
+#endif // STATS_H
--- /dev/null
+/* This file is part of the Linux Trace Toolkit viewer
+ * Copyright (C) 2003-2004 Michel Dagenais
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+#ifndef PROCESSTRACE_H
+#define PROCESSTRACE_H
+
+#include <lttv/traceset.h>
+#include <lttv/attribute.h>
+#include <lttv/hook.h>
+#include <ltt/ltt.h>
+
+/* This is the generic part of trace processing. All events within a
+ certain time interval are accessed and processing hooks are called for
+ each. The events are examined in monotonically increasing time to more
+ closely follow the traced system behavior.
+
+ Hooks are called at several different places during the processing:
+ before traceset, after traceset, check trace, before trace, after trace,
+ check tracefile, before tracefile, after tracefile,
+ check_event, before_event, before_event_by_id,
+ after_event, after_event_by_id.
+
+ In each case the "check" hooks are called first to determine if further
+ processing of the trace, tracefile or event is wanted. Then, the before
+ hooks and the after hooks are called. The before hooks for a traceset
+ are called before those for the contained traces, which are called before
+ those for the contained tracefiles. The after hooks are called in reverse
+ order. The event hooks are called after all the before_tracefile hooks
+ and before all the after_tracefile hooks.
+
+ The hooks receive two arguments, the hook_data and call_data. The hook_data
+ is specified when the hook is registered and typically links to the
+ object registering the hook (e.g. a graphical events viewer). The call_data
+ must contain all the context related to the call. The traceset hooks receive
+ the LttvTracesetContext provided by the caller. The trace hooks receive
+ the LttvTraceContext from the traces array in the LttvTracesetContext.
+ The tracefile and event hooks receive the LttvTracefileContext from
+ the tracefiles array in the LttvTraceContext. The LttEvent and LttTime
+ fields in the tracefile context are set to the current event and current
+ event time before calling the event hooks. No other context field is
+ modified.
+
+ The contexts in the traces and tracefiles arrays must be allocated by
+ the caller, either before the call or during the before hooks of the
+ enclosing traceset or trace. The order in the traces array must
+ correspond to the lttv_traceset_get function. The order in the tracefiles
+ arrays must correspond to the ltt_trace_control_tracefile_get and
+ ltt_trace_per_cpu_tracefile_get functions. The traceset, trace and
+ tracefile contexts may be subtyped as needed. Indeed, both the contexts
+ and the hooks are defined by the caller. */
+
+
+typedef struct _LttvTracesetContext LttvTracesetContext;
+typedef struct _LttvTracesetContextClass LttvTracesetContextClass;
+
+typedef struct _LttvTraceContext LttvTraceContext;
+typedef struct _LttvTraceContextClass LttvTraceContextClass;
+
+typedef struct _LttvTracefileContext LttvTracefileContext;
+typedef struct _LttvTracefileContextClass LttvTracefileContextClass;
+
+#define LTTV_TRACESET_CONTEXT_TYPE (lttv_traceset_context_get_type ())
+#define LTTV_TRACESET_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LTTV_TRACESET_CONTEXT_TYPE, LttvTracesetContext))
+#define LTTV_TRACESET_CONTEXT_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST ((vtable), LTTV_TRACESET_CONTEXT_TYPE, LttvTracesetContextClass))
+#define LTTV_IS_TRACESET_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LTTV_TRACESET_CONTEXT_TYPE))
+#define LTTV_IS_TRACESET_CONTEXT_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), LTTV_TRACESET_CONTEXT_TYPE))
+#define LTTV_TRACESET_CONTEXT_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), LTTV_TRACESET_CONTEXT_TYPE, LttvTracesetContextClass))
+
+struct _LttvTracesetContext {
+ GObject parent;
+
+ LttvTraceset *ts;
+ LttvHooks *before;
+ LttvHooks *after;
+ LttvTraceContext **traces;
+ LttvAttribute *a;
+ LttvAttribute *ts_a;
+ TimeInterval *Time_Span;
+ GTree *pqueue;
+};
+
+struct _LttvTracesetContextClass {
+ GObjectClass parent;
+
+ void (*init) (LttvTracesetContext *self, LttvTraceset *ts);
+ void (*fini) (LttvTracesetContext *self);
+ LttvTracesetContext* (*new_traceset_context) (LttvTracesetContext *self);
+ LttvTraceContext* (*new_trace_context) (LttvTracesetContext *self);
+ LttvTracefileContext* (*new_tracefile_context) (LttvTracesetContext *self);
+};
+
+GType lttv_traceset_context_get_type (void);
+
+void lttv_context_init(LttvTracesetContext *self, LttvTraceset *ts);
+
+void lttv_context_fini(LttvTracesetContext *self);
+
+LttvTracesetContext *
+lttv_context_new_traceset_context(LttvTracesetContext *self);
+
+LttvTraceContext *
+lttv_context_new_trace_context(LttvTracesetContext *self);
+
+LttvTracefileContext *
+lttv_context_new_tracefile_context(LttvTracesetContext *self);
+
+
+#define LTTV_TRACE_CONTEXT_TYPE (lttv_trace_context_get_type ())
+#define LTTV_TRACE_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LTTV_TRACE_CONTEXT_TYPE, LttvTraceContext))
+#define LTTV_TRACE_CONTEXT_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST ((vtable), LTTV_TRACE_CONTEXT_TYPE, LttvTraceContextClass))
+#define LTTV_IS_TRACE_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LTTV_TRACE_CONTEXT_TYPE))
+#define LTTV_IS_TRACE_CONTEXT_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), LTTV_TRACE_CONTEXT_TYPE))
+#define LTTV_TRACE_CONTEXT_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), LTTV_TRACE_CONTEXT_TYPE, LttvTraceContextClass))
+
+struct _LttvTraceContext {
+ GObject parent;
+
+ LttvTracesetContext *ts_context;
+ guint index; /* in ts_context->traces */
+ LttTrace *t;
+ LttvTrace *vt;
+ LttvHooks *check;
+ LttvHooks *before;
+ LttvHooks *after;
+ LttvTracefileContext **tracefiles;
+ LttvAttribute *a;
+ LttvAttribute *t_a;
+};
+
+struct _LttvTraceContextClass {
+ GObjectClass parent;
+};
+
+GType lttv_trace_context_get_type (void);
+
+#define LTTV_TRACEFILE_CONTEXT_TYPE (lttv_tracefile_context_get_type ())
+#define LTTV_TRACEFILE_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LTTV_TRACEFILE_CONTEXT_TYPE, LttvTracefileContext))
+#define LTTV_TRACEFILE_CONTEXT_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST ((vtable), LTTV_TRACEFILE_CONTEXT_TYPE, LttvTracefileContextClass))
+#define LTTV_IS_TRACEFILE_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LTTV_TRACEFILE_CONTEXT_TYPE))
+#define LTTV_IS_TRACEFILE_CONTEXT_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), LTTV_TRACEFILE_CONTEXT_TYPE))
+#define LTTV_TRACEFILE_CONTEXT_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), LTTV_TRACEFILE_CONTEXT_TYPE, LttvTracefileContextClass))
+
+struct _LttvTracefileContext {
+ GObject parent;
+
+ LttvTraceContext *t_context;
+ gboolean control;
+ guint index; /* in ts_context->tracefiles */
+ LttTracefile *tf;
+ LttvHooks *check;
+ LttvHooks *before;
+ LttvHooks *after;
+ LttEvent *e;
+ LttvHooks *check_event;
+ LttvHooks *before_event;
+ LttvHooksById *before_event_by_id;
+ LttvHooks *after_event;
+ LttvHooksById *after_event_by_id;
+ LttTime timestamp;
+ LttvAttribute *a;
+};
+
+struct _LttvTracefileContextClass {
+ GObjectClass parent;
+};
+
+GType lttv_tracefile_context_get_type (void);
+
+/* Run through the events in a traceset in sorted order calling all the
+ hooks appropriately. It starts at the current time and runs until end or
+ nb_events are processed. */
+
+void lttv_process_traceset(LttvTracesetContext *self, LttTime end,
+ unsigned nb_events);
+
+/* Process traceset can also be done in smaller pieces calling begin, middle
+ repeatedly, and end. The middle function return the number of events
+ processed. It may be larger than nb_events if several events have the
+ same timestamp. It will be smaller than nb_events if the end time
+ is reached. */
+
+void lttv_process_traceset_begin(LttvTracesetContext *self, LttTime end);
+
+guint lttv_process_traceset_middle(LttvTracesetContext *self, LttTime end,
+ unsigned nb_events);
+
+void lttv_process_traceset_end(LttvTracesetContext *self);
+
+
+void lttv_process_traceset_seek_time(LttvTracesetContext *self, LttTime start);
+
+void lttv_process_trace_seek_time(LttvTraceContext *self, LttTime start);
+
+void lttv_traceset_context_add_hooks(LttvTracesetContext *self,
+ LttvHooks *before_traceset,
+ LttvHooks *after_traceset,
+ LttvHooks *check_trace,
+ LttvHooks *before_trace,
+ LttvHooks *after_trace,
+ LttvHooks *check_tracefile,
+ LttvHooks *before_tracefile,
+ LttvHooks *after_tracefile,
+ LttvHooks *check_event,
+ LttvHooks *before_event,
+ LttvHooks *after_event);
+
+void lttv_traceset_context_remove_hooks(LttvTracesetContext *self,
+ LttvHooks *before_traceset,
+ LttvHooks *after_traceset,
+ LttvHooks *check_trace,
+ LttvHooks *before_trace,
+ LttvHooks *after_trace,
+ LttvHooks *check_tracefile,
+ LttvHooks *before_tracefile,
+ LttvHooks *after_tracefile,
+ LttvHooks *check_event,
+ LttvHooks *before_event,
+ LttvHooks *after_event);
+
+void lttv_trace_context_add_hooks(LttvTraceContext *self,
+ LttvHooks *check_trace,
+ LttvHooks *before_trace,
+ LttvHooks *after_trace);
+
+void lttv_trace_context_remove_hooks(LttvTraceContext *self,
+ LttvHooks *check_trace,
+ LttvHooks *before_trace,
+ LttvHooks *after_trace);
+
+void lttv_tracefile_context_add_hooks(LttvTracefileContext *self,
+ LttvHooks *check_tracefile,
+ LttvHooks *before_tracefile,
+ LttvHooks *after_tracefile,
+ LttvHooks *check_event,
+ LttvHooks *before_event,
+ LttvHooks *after_event);
+
+void lttv_tracefile_context_remove_hooks(LttvTracefileContext *self,
+ LttvHooks *check_tracefile,
+ LttvHooks *before_tracefile,
+ LttvHooks *after_tracefile,
+ LttvHooks *check_event,
+ LttvHooks *before_event,
+ LttvHooks *after_event);
+
+void lttv_tracefile_context_add_hooks_by_id(LttvTracefileContext *self,
+ unsigned i,
+ LttvHooks *before_event_by_id,
+ LttvHooks *after_event_by_id);
+
+void lttv_tracefile_context_remove_hooks_by_id(LttvTracefileContext *self,
+ unsigned i);
+
+typedef struct _LttvTraceHook {
+ LttvHook h;
+ guint id;
+ LttField *f1;
+ LttField *f2;
+ LttField *f3;
+} LttvTraceHook;
+
+
+/* Search in the trace for the id of the named event type within the named
+ facility. Then, find the three (if non null) named fields. All that
+ information is then used to fill the LttvTraceHook structure. This
+ is useful to find the specific id for an event within a trace, for
+ registering a hook using this structure as event data;
+ it already contains the (up to three) needed fields handles. */
+
+void lttv_trace_find_hook(LttTrace *t, char *facility, char *event_type,
+ char *field1, char *field2, char *field3, LttvHook h, LttvTraceHook *th);
+
+#endif // PROCESSTRACE_H
--- /dev/null
+/* This file is part of the Linux Trace Toolkit viewer
+ * Copyright (C) 2003-2004 Michel Dagenais
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+
+#include <lttv/traceset.h>
+#include <stdio.h>
+
+/* A trace is a sequence of events gathered in the same tracing session. The
+ events may be stored in several tracefiles in the same directory.
+ A trace set is defined when several traces are to be analyzed together,
+ possibly to study the interactions between events in the different traces.
+*/
+
+struct _LttvTraceset {
+ char * filename;
+ GPtrArray *traces;
+ LttvAttribute *a;
+};
+
+
+struct _LttvTrace {
+ LttTrace *t;
+ LttvAttribute *a;
+ guint ref_count;
+};
+
+
+LttvTraceset *lttv_traceset_new()
+{
+ LttvTraceset *s;
+
+ s = g_new(LttvTraceset, 1);
+ s->filename = NULL;
+ s->traces = g_ptr_array_new();
+ s->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
+ return s;
+}
+
+char * lttv_traceset_name(LttvTraceset * s)
+{
+ return s->filename;
+}
+
+LttvTrace *lttv_trace_new(LttTrace *t)
+{
+ LttvTrace *new_trace;
+
+ new_trace = g_new(LttvTrace, 1);
+ new_trace->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
+ new_trace->t = t;
+ new_trace->ref_count = 0;
+ return new_trace;
+}
+
+
+LttvTraceset *lttv_traceset_copy(LttvTraceset *s_orig)
+{
+ int i;
+ LttvTraceset *s;
+ LttvTrace * trace;
+
+ s = g_new(LttvTraceset, 1);
+ s->filename = NULL;
+ s->traces = g_ptr_array_new();
+ for(i=0;i<s_orig->traces->len;i++)
+ {
+ trace = g_ptr_array_index(s_orig->traces, i);
+ trace->ref_count++;
+
+ /*CHECK this used ltt_trace_copy while it may not be needed. Need to
+ define how traces and tracesets are shared */
+ g_ptr_array_add(
+ s->traces,
+ g_ptr_array_index(s_orig->traces, i));
+ }
+ s->a = LTTV_ATTRIBUTE(lttv_iattribute_deep_copy(LTTV_IATTRIBUTE(s_orig->a)));
+ return s;
+}
+
+
+LttvTraceset *lttv_traceset_load(const gchar *filename)
+{
+ LttvTraceset *s = g_new(LttvTraceset,1);
+ FILE *tf;
+
+ s->filename = g_strdup(filename);
+ tf = fopen(filename,"r");
+
+ g_critical("NOT IMPLEMENTED : load traceset data from a XML file");
+
+ fclose(tf);
+ return s;
+}
+
+gint lttv_traceset_save(LttvTraceset *s)
+{
+ FILE *tf;
+
+ tf = fopen(s->filename, "w");
+
+ g_critical("NOT IMPLEMENTED : save traceset data in a XML file");
+
+ fclose(tf);
+ return 0;
+}
+
+void lttv_traceset_destroy(LttvTraceset *s)
+{
+ g_ptr_array_free(s->traces, TRUE);
+ g_object_unref(s->a);
+ g_free(s);
+}
+
+void lttv_trace_destroy(LttvTrace *t)
+{
+ g_object_unref(t->a);
+ g_free(t);
+}
+
+
+void lttv_traceset_add(LttvTraceset *s, LttvTrace *t)
+{
+ t->ref_count++;
+ g_ptr_array_add(s->traces, t);
+}
+
+
+unsigned lttv_traceset_number(LttvTraceset *s)
+{
+ return s->traces->len;
+}
+
+
+LttvTrace *lttv_traceset_get(LttvTraceset *s, unsigned i)
+{
+ g_assert(s->traces->len > i);
+ return ((LttvTrace *)s->traces->pdata[i]);
+}
+
+
+void lttv_traceset_remove(LttvTraceset *s, unsigned i)
+{
+ LttvTrace * t;
+ g_assert(s->traces->len > i);
+ t = (LttvTrace *)s->traces->pdata[i];
+ t->ref_count--;
+ g_ptr_array_remove_index(s->traces, i);
+}
+
+
+/* A set of attributes is attached to each trace set, trace and tracefile
+ to store user defined data as needed. */
+
+LttvAttribute *lttv_traceset_attribute(LttvTraceset *s)
+{
+ return s->a;
+}
+
+
+LttvAttribute *lttv_trace_attribute(LttvTrace *t)
+{
+ return t->a;
+}
+
+
+LttTrace *lttv_trace(LttvTrace *t)
+{
+ return t->t;
+}
+
+guint lttv_trace_get_ref_number(LttvTrace * t)
+{
+ return t->ref_count;
+}
--- /dev/null
+/* This file is part of the Linux Trace Toolkit viewer
+ * Copyright (C) 2003-2004 Michel Dagenais
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+#ifndef TRACESET_H
+#define TRACESET_H
+
+#include <lttv/attribute.h>
+#include <lttv/hook.h>
+#include <ltt/ltt.h>
+
+/* A traceset is a set of traces to be analyzed together. */
+
+typedef struct _LttvTraceset LttvTraceset;
+
+typedef struct _LttvTrace LttvTrace;
+
+/* Tracesets may be added to, removed from and their content listed. */
+
+LttvTraceset *lttv_traceset_new();
+
+char * lttv_traceset_name(LttvTraceset * s);
+
+LttvTrace *lttv_trace_new(LttTrace *t);
+
+LttvTraceset *lttv_traceset_copy(LttvTraceset *s_orig);
+
+LttvTraceset *lttv_traceset_load(const gchar *filename);
+
+gint lttv_traceset_save(LttvTraceset *s);
+
+void lttv_traceset_destroy(LttvTraceset *s);
+
+void lttv_trace_destroy(LttvTrace *t);
+
+void lttv_traceset_add(LttvTraceset *s, LttvTrace *t);
+
+unsigned lttv_traceset_number(LttvTraceset *s);
+
+LttvTrace *lttv_traceset_get(LttvTraceset *s, unsigned i);
+
+void lttv_traceset_remove(LttvTraceset *s, unsigned i);
+
+/* An attributes table is attached to the set and to each trace in the set. */
+
+LttvAttribute *lttv_traceset_attribute(LttvTraceset *s);
+
+LttvAttribute *lttv_trace_attribute(LttvTrace *t);
+
+LttTrace *lttv_trace(LttvTrace *t);
+
+guint lttv_trace_get_ref_number(LttvTrace * t);
+
+#endif // TRACESET_H
+
+++ /dev/null
-AM_CFLAGS = $(GLIB_CFLAGS)
-LIBS += $(GLIB_LIBS) -lgobject-2.0 -L$(top_srcdir)/ltt -ltraceread
-
-bin_PROGRAMS = lttv
-
-INCLUDES = \
- -DPACKAGE_PLUGIN_DIR=\""$(lttvplugindir)"\" \
- @PACKAGE_CFLAGS@ \
- $(DEFAULT_INCLUDES)
-
-libdir = ${lttvplugindir}
-
-lttv_SOURCES = main.c module.c option.c \
- hook.c attribute.c \
- iattribute.c processTrace.c \
- state.c stats.c traceset.c
-
+++ /dev/null
-/* This file is part of the Linux Trace Toolkit viewer
- * Copyright (C) 2003-2004 Michel Dagenais
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License Version 2 as
- * published by the Free Software Foundation;
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA.
- */
-
-#include <lttv/attribute.h>
-#include <ltt/ltt.h>
-
-typedef union _AttributeValue {
- int dv_int;
- unsigned dv_uint;
- long dv_long;
- unsigned long dv_ulong;
- float dv_float;
- double dv_double;
- LttTime dv_time;
- gpointer dv_pointer;
- char *dv_string;
- GObject *dv_gobject;
-} AttributeValue;
-
-
-typedef struct _Attribute {
- LttvAttributeName name;
- LttvAttributeType type;
- AttributeValue value;
-} Attribute;
-
-
-LttvAttributeValue address_of_value(LttvAttributeType t, AttributeValue *v)
-{
- LttvAttributeValue va;
-
- switch(t) {
- case LTTV_INT: va.v_int = &v->dv_int; break;
- case LTTV_UINT: va.v_uint = &v->dv_uint; break;
- case LTTV_LONG: va.v_long = &v->dv_long; break;
- case LTTV_ULONG: va.v_ulong = &v->dv_ulong; break;
- case LTTV_FLOAT: va.v_float = &v->dv_float; break;
- case LTTV_DOUBLE: va.v_double = &v->dv_double; break;
- case LTTV_TIME: va.v_time = &v->dv_time; break;
- case LTTV_POINTER: va.v_pointer = &v->dv_pointer; break;
- case LTTV_STRING: va.v_string = &v->dv_string; break;
- case LTTV_GOBJECT: va.v_gobject = &v->dv_gobject; break;
- }
- return va;
-}
-
-
-AttributeValue init_value(LttvAttributeType t)
-{
- AttributeValue v;
-
- switch(t) {
- case LTTV_INT: v.dv_int = 0; break;
- case LTTV_UINT: v.dv_uint = 0; break;
- case LTTV_LONG: v.dv_long = 0; break;
- case LTTV_ULONG: v.dv_ulong = 0; break;
- case LTTV_FLOAT: v.dv_float = 0; break;
- case LTTV_DOUBLE: v.dv_double = 0; break;
- case LTTV_TIME: v.dv_time.tv_sec = 0; v.dv_time.tv_nsec = 0; break;
- case LTTV_POINTER: v.dv_pointer = NULL; break;
- case LTTV_STRING: v.dv_string = NULL; break;
- case LTTV_GOBJECT: v.dv_gobject = NULL; break;
- }
- return v;
-}
-
-
-unsigned int
-lttv_attribute_get_number(LttvAttribute *self)
-{
- return self->attributes->len;
-}
-
-
-gboolean
-lttv_attribute_named(LttvAttribute *self, gboolean *homogeneous)
-{
- *homogeneous = FALSE;
- return TRUE;
-}
-
-
-LttvAttributeType
-lttv_attribute_get(LttvAttribute *self, unsigned i, LttvAttributeName *name,
- LttvAttributeValue *v)
-{
- Attribute *a;
-
- a = &g_array_index(self->attributes, Attribute, i);
- *name = a->name;
- *v = address_of_value(a->type, &(a->value));
- return a->type;
-}
-
-
-LttvAttributeType
-lttv_attribute_get_by_name(LttvAttribute *self, LttvAttributeName name,
- LttvAttributeValue *v)
-{
- Attribute *a;
-
- unsigned i;
-
- gpointer p;
-
- p = g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
- if(p == NULL) return LTTV_NONE;
-
- i = GPOINTER_TO_UINT(p);
- i--;
- a = &g_array_index(self->attributes, Attribute, i);
- *v = address_of_value(a->type, &(a->value));
- return a->type;
-}
-
-
-LttvAttributeValue
-lttv_attribute_add(LttvAttribute *self, LttvAttributeName name,
- LttvAttributeType t)
-{
- unsigned i;
-
- Attribute a, *pa;
-
- i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
- if(i != 0) g_error("duplicate entry in attribute table");
-
- a.name = name;
- a.type = t;
- a.value = init_value(t);
- g_array_append_val(self->attributes, a);
- i = self->attributes->len - 1;
- pa = &g_array_index(self->attributes, Attribute, i);
- g_hash_table_insert(self->names, GUINT_TO_POINTER(name),
- GUINT_TO_POINTER(i + 1));
- return address_of_value(t, &(pa->value));
-}
-
-
-/* Remove an attribute */
-
-void
-lttv_attribute_remove(LttvAttribute *self, unsigned i)
-{
- Attribute *a;
-
- a = &g_array_index(self->attributes, Attribute, i);
-
- /* Remove the array element and its entry in the name index */
-
- g_hash_table_remove(self->names, GUINT_TO_POINTER(a->name));
- g_array_remove_index_fast(self->attributes, i);
-
- /* The element used to replace the removed element has its index entry
- all wrong now. Reinsert it with its new position. */
-
- if(self->attributes->len != i){
- g_hash_table_remove(self->names, GUINT_TO_POINTER(a->name));
- g_hash_table_insert(self->names, GUINT_TO_POINTER(a->name), GUINT_TO_POINTER(i + 1));
- }
-}
-
-void
-lttv_attribute_remove_by_name(LttvAttribute *self, LttvAttributeName name)
-{
- unsigned i;
-
- i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
- if(i == 0) g_error("remove by name non existent attribute");
-
- lttv_attribute_remove(self, i - 1);
-}
-
-/* Create an empty iattribute object and add it as an attribute under the
- specified name, or return an existing iattribute attribute. If an
- attribute of that name already exists but is not a GObject supporting the
- iattribute interface, return NULL. */
-
-/*CHECK*/LttvAttribute*
-lttv_attribute_find_subdir(LttvAttribute *self, LttvAttributeName name)
-{
- unsigned i;
-
- Attribute a;
-
- LttvAttribute *new;
-
- i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
- if(i != 0) {
- a = g_array_index(self->attributes, Attribute, i - 1);
- if(a.type == LTTV_GOBJECT && LTTV_IS_IATTRIBUTE(a.value.dv_gobject)) {
- return LTTV_ATTRIBUTE(a.value.dv_gobject);
- }
- else return NULL;
- }
- new = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
- *(lttv_attribute_add(self, name, LTTV_GOBJECT).v_gobject) = G_OBJECT(new);
- return (LttvAttribute *)new;
-}
-
-gboolean
-lttv_attribute_find(LttvAttribute *self, LttvAttributeName name,
- LttvAttributeType t, LttvAttributeValue *v)
-{
- unsigned i;
-
- Attribute *a;
-
- i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name));
- if(i != 0) {
- a = &g_array_index(self->attributes, Attribute, i - 1);
- if(a->type != t) return FALSE;
- *v = address_of_value(t, &(a->value));
- return TRUE;
- }
-
- *v = lttv_attribute_add(self, name, t);
- return TRUE;
-}
-
-
-void lttv_attribute_recursive_free(LttvAttribute *self)
-{
- int i, nb;
-
- Attribute *a;
-
- nb = self->attributes->len;
-
- for(i = 0 ; i < nb ; i++) {
- a = &g_array_index(self->attributes, Attribute, i);
- if(a->type == LTTV_GOBJECT && LTTV_IS_ATTRIBUTE(a->value.dv_gobject)) {
- lttv_attribute_recursive_free((LttvAttribute *)(a->value.dv_gobject));
- }
- }
- g_object_unref(self);
-}
-
-
-void lttv_attribute_recursive_add(LttvAttribute *dest, LttvAttribute *src)
-{
- int i, nb;
-
- Attribute *a;
-
- LttvAttributeValue value;
-
- nb = src->attributes->len;
-
- for(i = 0 ; i < nb ; i++) {
- a = &g_array_index(src->attributes, Attribute, i);
- if(a->type == LTTV_GOBJECT && LTTV_IS_ATTRIBUTE(a->value.dv_gobject)) {
- lttv_attribute_recursive_add(
- /*CHECK*/(LttvAttribute *)lttv_attribute_find_subdir(dest, a->name),
- (LttvAttribute *)(a->value.dv_gobject));
- }
- else {
- g_assert(lttv_attribute_find(dest, a->name, a->type, &value));
- switch(a->type) {
- case LTTV_INT:
- *value.v_int += a->value.dv_int;
- break;
- case LTTV_UINT:
- *value.v_uint += a->value.dv_uint;
- break;
- case LTTV_LONG:
- *value.v_long += a->value.dv_long;
- break;
- case LTTV_ULONG:
- *value.v_ulong += a->value.dv_ulong;
- break;
- case LTTV_FLOAT:
- *value.v_float += a->value.dv_float;
- break;
- case LTTV_DOUBLE:
- *value.v_double += a->value.dv_double;
- break;
- case LTTV_TIME:
- *value.v_time = ltt_time_add(*value.v_time, a->value.dv_time);
- break;
- case LTTV_POINTER:
- break;
- case LTTV_STRING:
- break;
- case LTTV_GOBJECT:
- break;
- case LTTV_NONE:
- break;
- }
- }
- }
-}
-
-
-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)
-{
- LttvIAttributeClass *klass = (LttvIAttributeClass *)g_iface;
-
- klass->get_number = (unsigned int (*) (LttvIAttribute *self))
- lttv_attribute_get_number;
-
- klass->named = (gboolean (*) (LttvIAttribute *self, gboolean *homogeneous))
- lttv_attribute_named;
-
- klass->get = (LttvAttributeType (*) (LttvIAttribute *self, unsigned i,
- LttvAttributeName *name, LttvAttributeValue *v)) lttv_attribute_get;
-
- klass->get_by_name = (LttvAttributeType (*) (LttvIAttribute *self,
- LttvAttributeName name, LttvAttributeValue *v))
- lttv_attribute_get_by_name;
-
- klass->add = (LttvAttributeValue (*) (LttvIAttribute *self,
- LttvAttributeName name, LttvAttributeType t)) lttv_attribute_add;
-
- klass->remove = (void (*) (LttvIAttribute *self, unsigned i))
- lttv_attribute_remove;
-
- klass->remove_by_name = (void (*) (LttvIAttribute *self,
- LttvAttributeName name)) lttv_attribute_remove_by_name;
-
- klass->find_subdir = (LttvIAttribute* (*) (LttvIAttribute *self,
- LttvAttributeName name)) lttv_attribute_find_subdir;
-}
-
-
-static void
-attribute_instance_init (GTypeInstance *instance, gpointer g_class)
-{
- LttvAttribute *self = (LttvAttribute *)instance;
- self->names = g_hash_table_new(g_direct_hash, g_direct_equal);
- self->attributes = g_array_new(FALSE, FALSE, sizeof(Attribute));
-}
-
-
-static void
-attribute_finalize (LttvAttribute *self)
-{
- g_hash_table_destroy(self->names);
- g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "attribute_finalize()");
- g_array_free(self->attributes, TRUE);
- G_OBJECT_CLASS(g_type_class_peek_parent(
- g_type_class_peek(LTTV_ATTRIBUTE_TYPE)))->finalize(G_OBJECT(self));
-}
-
-
-static void
-attribute_class_init (LttvAttributeClass *klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
-
- gobject_class->finalize = (void (*)(GObject *self))attribute_finalize;
-}
-
-GType
-lttv_attribute_get_type (void)
-{
- static GType type = 0;
- if (type == 0) {
- static const GTypeInfo info = {
- sizeof (LttvAttributeClass),
- NULL, /* base_init */
- NULL, /* base_finalize */
- (GClassInitFunc) attribute_class_init, /* class_init */
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (LttvAttribute),
- 0, /* n_preallocs */
- (GInstanceInitFunc) attribute_instance_init /* instance_init */
- };
-
- static const GInterfaceInfo iattribute_info = {
- (GInterfaceInitFunc) attribute_interface_init, /* interface_init */
- NULL, /* interface_finalize */
- NULL /* interface_data */
- };
-
- type = g_type_register_static (G_TYPE_OBJECT, "LttvAttributeType", &info,
- 0);
- g_type_add_interface_static (type, LTTV_IATTRIBUTE_TYPE, &iattribute_info);
- }
- return type;
-}
-
-
+++ /dev/null
-/* This file is part of the Linux Trace Toolkit viewer
- * Copyright (C) 2003-2004 Michel Dagenais
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License Version 2 as
- * published by the Free Software Foundation;
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA.
- */
-
-
- consist in AND, OR and NOT nested expressions, forming a tree with
- simple relations as leaves. The simple relations test is a field
- in an event is equal, not equal, smaller, smaller or equal, larger, or
- larger or equal to a specified value. */
-
-typedef enum _lttv_expression_op
-{ LTTV_FIELD_EQ,
- LTTV_FIELD_NE,
- LTTV_FIELD_LT,
- LTTV_FIELD_LE,
- LTTV_FIELD_GT,
- LTTV_FIELD_GE
-} lttv_expression_op;
-
-typedef _lttv_simple_expression
-{ lttv_expression_op op;
- char *field_name;
- char *value;
-} lttv_simple_expression;
-
-typedef _lttv_expression_type
-{ LTTV_EXPRESSION,
- LTTV_SIMPLE_EXPRESSION
-
-}
-typedef struct _lttv_expression
-{ bool or;
- bool not;
- bool simple_expression;
- union
- { lttv_expression *e;
- lttv_field_relation *se;
- } e;
-} lttv_expression;
-
-read_token
-
-read_expression
- ( read expr )
- simple expr [ op expr ]
-
-read_simple_expression
- read_field_path [ rel value ]
-
-read_field_path
- read_field_component [. field path]
-
-read_field_component
- name [ \[ value \] ]
-
-data struct:
-and/or(left/right)
-not(child)
-op(left/right)
-path(component...) -> field
-
-
+++ /dev/null
-/* This file is part of the Linux Trace Toolkit viewer
- * Copyright (C) 2003-2004 Michel Dagenais
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License Version 2 as
- * published by the Free Software Foundation;
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA.
- */
-
-
-#include <lttv/hook.h>
-
-
-typedef struct _LttvHookClosure {
- LttvHook hook;
- void *hook_data;
-} LttvHookClosure;
-
-
-LttvHooks *lttv_hooks_new()
-{
- return g_array_new(FALSE, FALSE, sizeof(LttvHookClosure));
-}
-
-
-void lttv_hooks_destroy(LttvHooks *h)
-{
- g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "lttv_hooks_destroy()");
- g_array_free(h, TRUE);
-}
-
-
-void lttv_hooks_add(LttvHooks *h, LttvHook f, void *hook_data)
-{
- LttvHookClosure c;
-
- if(h == NULL)g_error("Null hook added");
-
- c.hook = f;
- c.hook_data = hook_data;
- g_array_append_val(h,c);
-}
-
-
-void lttv_hooks_add_list(LttvHooks *h, LttvHooks *list)
-{
- guint i;
-
- if(list == NULL) return;
- for(i = 0 ; i < list->len; i++) {
- g_array_append_val(h,g_array_index(list, LttvHookClosure, i));
- }
-}
-
-
-void *lttv_hooks_remove(LttvHooks *h, LttvHook f)
-{
- unsigned i;
-
- void *hook_data;
-
- LttvHookClosure *c;
-
- for(i = 0 ; i < h->len ; i++) {
- c = &g_array_index(h, LttvHookClosure, i);
- if(c->hook == f) {
- hook_data = c->hook_data;
- lttv_hooks_remove_by_position(h, i);
- return hook_data;
- }
- }
- return NULL;
-}
-
-
-void lttv_hooks_remove_data(LttvHooks *h, LttvHook f, void *hook_data)
-{
- unsigned i;
-
- LttvHookClosure *c;
-
- for(i = 0 ; i < h->len ; i++) {
- c = &g_array_index(h, LttvHookClosure, i);
- if(c->hook == f && c->hook_data == hook_data) {
- lttv_hooks_remove_by_position(h, i);
- return;
- }
- }
-}
-
-
-void lttv_hooks_remove_list(LttvHooks *h, LttvHooks *list)
-{
- guint i, j;
-
- LttvHookClosure *c, *c_list;
-
- if(list == NULL) return;
- for(i = 0, j = 0 ; i < h->len && j < list->len ;) {
- c = &g_array_index(h, LttvHookClosure, i);
- c_list = &g_array_index(list, LttvHookClosure, j);
- if(c->hook == c_list->hook && c->hook_data == c_list->hook_data) {
- lttv_hooks_remove_by_position(h, i);
- j++;
- }
- else i++;
- }
-
- /* Normally the hooks in h are ordered as in list. If this is not the case,
- try harder here. */
-
- if(j < list->len) {
- for(; j < list->len ; j++) {
- c_list = &g_array_index(list, LttvHookClosure, j);
- lttv_hooks_remove_data(h, c_list->hook, c_list->hook_data);
- }
- }
-}
-
-
-unsigned lttv_hooks_number(LttvHooks *h)
-{
- return h->len;
-}
-
-
-void lttv_hooks_get(LttvHooks *h, unsigned i, LttvHook *f, void **hook_data)
-{
- LttvHookClosure *c;
-
- c = &g_array_index(h, LttvHookClosure, i);
- *f = c->hook;
- *hook_data = c->hook_data;
-}
-
-
-void lttv_hooks_remove_by_position(LttvHooks *h, unsigned i)
-{
- g_array_remove_index(h, i);
-}
-
-
-gboolean lttv_hooks_call(LttvHooks *h, void *call_data)
-{
- gboolean ret, sum_ret = FALSE;
-
- LttvHookClosure *c;
-
- guint i;
-
- if(h != NULL) {
- for(i = 0 ; i < h->len ; i++) {
- c = &g_array_index(h, LttvHookClosure, i);
- ret = c->hook(c->hook_data,call_data);
- sum_ret = sum_ret || ret;
- }
- }
- return sum_ret;
-}
-
-
-gboolean lttv_hooks_call_check(LttvHooks *h, void *call_data)
-{
- LttvHookClosure *c;
-
- guint i;
-
- for(i = 0 ; i < h->len ; i++) {
- c = &g_array_index(h, LttvHookClosure, i);
- if(c->hook(c->hook_data,call_data)) return TRUE;
- }
- return FALSE;
-}
-
-
-LttvHooksById *lttv_hooks_by_id_new()
-{
- return g_ptr_array_new();
-}
-
-
-void lttv_hooks_by_id_destroy(LttvHooksById *h)
-{
- guint i;
-
- for(i = 0 ; i < h->len ; i++) {
- if(h->pdata[i] != NULL) lttv_hooks_destroy((LttvHooks *)(h->pdata[i]));
- }
- g_ptr_array_free(h, TRUE);
-}
-
-
-LttvHooks *lttv_hooks_by_id_find(LttvHooksById *h, unsigned id)
-{
- if(h->len <= id) g_ptr_array_set_size(h, id + 1);
- if(h->pdata[id] == NULL) h->pdata[id] = lttv_hooks_new();
- return h->pdata[id];
-}
-
-
-unsigned lttv_hooks_by_id_max_id(LttvHooksById *h)
-{
- return h->len;
-}
-
-
-LttvHooks *lttv_hooks_by_id_get(LttvHooksById *h, unsigned id)
-{
- if(id < h->len) return h->pdata[id];
- return NULL;
-}
-
-
-void lttv_hooks_by_id_remove(LttvHooksById *h, unsigned id)
-{
- if(id < h->len && h->pdata[id] != NULL) {
- lttv_hooks_destroy((LttvHooks *)h->pdata[id]);
- h->pdata[id] = NULL;
- }
-}
-
+++ /dev/null
-/* This file is part of the Linux Trace Toolkit viewer
- * Copyright (C) 2003-2004 Michel Dagenais
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License Version 2 as
- * published by the Free Software Foundation;
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA.
- */
-
-
-#include <lttv/iattribute.h>
-
-static void
-lttv_iattribute_base_init (gpointer klass)
-{
- static gboolean initialized = FALSE;
-
- if (!initialized) {
- initialized = TRUE;
- }
-}
-
-
-GType
-lttv_iattribute_get_type (void)
-{
- static GType type = 0;
- if (type == 0) {
- static const GTypeInfo info = {
- sizeof (LttvIAttributeClass),
- lttv_iattribute_base_init, /* base_init */
- NULL, /* base_finalize */
- NULL, /* class_init */
- NULL, /* class_finalize */
- NULL, /* class_data */
- 0,
- 0, /* n_preallocs */
- NULL /* instance_init */
- };
- type = g_type_register_static (G_TYPE_INTERFACE, "LttvIAttribute",
- &info, 0);
- }
- return type;
-}
-
-
-unsigned int lttv_iattribute_get_number(LttvIAttribute *self)
-{
- return LTTV_IATTRIBUTE_GET_CLASS (self)->get_number (self);
-}
-
-
-gboolean lttv_iattribute_named(LttvIAttribute *self, gboolean *homogeneous)
-{
- return LTTV_IATTRIBUTE_GET_CLASS (self)->named (self, homogeneous);
-}
-
-
-LttvAttributeType lttv_iattribute_get(LttvIAttribute *self, unsigned i,
- LttvAttributeName *name, LttvAttributeValue *v)
-{
- return LTTV_IATTRIBUTE_GET_CLASS (self)->get (self, i, name, v);
-}
-
-
-LttvAttributeType lttv_iattribute_get_by_name(LttvIAttribute *self,
- LttvAttributeName name, LttvAttributeValue *v)
-{
- return LTTV_IATTRIBUTE_GET_CLASS (self)->get_by_name (self, name, v);
-}
-
-
-LttvAttributeValue lttv_iattribute_add(LttvIAttribute *self,
- LttvAttributeName name, LttvAttributeType t)
-{
- return LTTV_IATTRIBUTE_GET_CLASS (self)->add (self, name, t);
-}
-
-
-void lttv_iattribute_remove(LttvIAttribute *self, unsigned i)
-{
- return LTTV_IATTRIBUTE_GET_CLASS (self)->remove (self, i);
-}
-
-
-void lttv_iattribute_remove_by_name(LttvIAttribute *self,
- LttvAttributeName name)
-{
- return LTTV_IATTRIBUTE_GET_CLASS (self)->remove_by_name (self, name);
-}
-
-LttvIAttribute* lttv_iattribute_find_subdir(LttvIAttribute *self,
- LttvAttributeName name)
-{
- return LTTV_IATTRIBUTE_GET_CLASS (self)->find_subdir (self, name);
-}
-
-
-/* Find the named attribute in the table, which must be of the specified type.
- If it does not exist, it is created with a default value of 0 (NULL for
- pointer types). Since the address of the value is obtained, it may be
- changed easily afterwards. The function returns false when the attribute
- exists but is of incorrect type. */
-
-gboolean lttv_iattribute_find(LttvIAttribute *self, LttvAttributeName name,
- LttvAttributeType t, LttvAttributeValue *v)
-{
- LttvAttributeType found_type;
-
- found_type = lttv_iattribute_get_by_name(self, name, v);
- if(found_type == t) return TRUE;
-
- if(found_type == LTTV_NONE) {
- *v = lttv_iattribute_add(self, name, t);
- return TRUE;
- }
-
- return FALSE;
-}
-
-
-/* Trees of attribute tables may be accessed using a hierarchical path with
- components separated by /, like in filesystems */
-
-gboolean lttv_iattribute_find_by_path(LttvIAttribute *self, char *path,
- LttvAttributeType t, LttvAttributeValue *v)
-{
- LttvIAttribute *node = self;
-
- LttvAttributeType found_type;
-
- LttvAttributeName name;
-
- gchar **components, **cursor;
-
- components = g_strsplit(path, "\"", G_MAXINT);
-
- if(components == NULL || *components == NULL) {
- g_strfreev(components);
- return FALSE;
- }
-
- for(cursor = components;;) {
- name = g_quark_from_string(*cursor);
- cursor++;
-
- if(*cursor == NULL) {
- g_strfreev(components);
- return lttv_iattribute_find(node, name, t, v);
- }
- else {
- found_type = lttv_iattribute_get_by_name(node, name, v);
- if(found_type == LTTV_NONE) {
- node = lttv_iattribute_find_subdir(node, name);
- }
- else if(found_type == LTTV_GOBJECT &&
- LTTV_IS_IATTRIBUTE(*(v->v_gobject))) {
- node = LTTV_IATTRIBUTE(*(v->v_gobject));
- }
- else {
- g_strfreev(components);
- return FALSE;
- }
- }
- }
-}
-
-/* Shallow and deep copies */
-
-LttvIAttribute *lttv_iattribute_shallow_copy(LttvIAttribute *self)
-{
- LttvIAttribute *copy;
-
- LttvAttributeType t;
-
- LttvAttributeValue v, v_copy;
-
- LttvAttributeName name;
-
- int i;
-
- int nb_attributes = lttv_iattribute_get_number(self);
-
- copy = LTTV_IATTRIBUTE(g_object_new(G_OBJECT_TYPE(self),NULL));
-
- for(i = 0 ; i < nb_attributes ; i++) {
- t = lttv_iattribute_get(self, i, &name, &v);
- v_copy = lttv_iattribute_add(copy, name, t);
- lttv_iattribute_copy_value(t, v_copy, v);
- }
-}
-
-LttvIAttribute *lttv_iattribute_deep_copy(LttvIAttribute *self)
-{
- LttvIAttribute *copy, *child;
-
- LttvAttributeType t;
-
- LttvAttributeValue v, v_copy;
-
- LttvAttributeName name;
-
- int i;
-
- int nb_attributes = lttv_iattribute_get_number(self);
-
- copy = LTTV_IATTRIBUTE(g_object_new(G_OBJECT_TYPE(self), NULL));
-
- for(i = 0 ; i < nb_attributes ; i++) {
- t = lttv_iattribute_get(self, i, &name, &v);
- v_copy = lttv_iattribute_add(copy, name, t);
- if(t == LTTV_GOBJECT && LTTV_IS_IATTRIBUTE(*(v.v_gobject))) {
- child = LTTV_IATTRIBUTE(*(v.v_gobject));
- *(v_copy.v_gobject) = G_OBJECT(lttv_iattribute_deep_copy(child));
- }
- else lttv_iattribute_copy_value(t, v_copy, v);
- }
-}
-
-void lttv_iattribute_copy_value(LttvAttributeType t, LttvAttributeValue dest,
- LttvAttributeValue src)
-{
- switch(t) {
- case LTTV_INT:
- *(dest.v_int) = *(src.v_int);
- break;
-
- case LTTV_UINT:
- *(dest.v_uint) = *(src.v_uint);
- break;
-
- case LTTV_LONG:
- *(dest.v_long) = *(src.v_long);
- break;
-
- case LTTV_ULONG:
- *(dest.v_ulong) = *(src.v_ulong);
- break;
-
- case LTTV_FLOAT:
- *(dest.v_float) = *(src.v_float);
- break;
-
- case LTTV_DOUBLE:
- *(dest.v_double) = *(src.v_double);
- break;
-
- case LTTV_TIME:
- *(dest.v_time) = *(src.v_time);
- break;
-
- case LTTV_POINTER:
- *(dest.v_pointer) = *(src.v_pointer);
- break;
-
- case LTTV_STRING:
- *(dest.v_string) = *(src.v_string);
- break;
-
- case LTTV_GOBJECT:
- *(dest.v_gobject) = *(src.v_gobject);
- break;
-
- case LTTV_NONE:
- break;
- }
-}
-
-
+++ /dev/null
-/* This file is part of the Linux Trace Toolkit viewer
- * Copyright (C) 2003-2004 Michel Dagenais
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License Version 2 as
- * published by the Free Software Foundation;
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA.
- */
-
-
-#include <lttv/hook.h>
-#include <lttv/module.h>
-#include <lttv/lttv.h>
-#include <lttv/iattribute.h>
-#include <lttv/attribute.h>
-#include <lttv/option.h>
-#include <lttv/traceset.h>
-#include <ltt/trace.h>
-#include <stdio.h>
-
-
-/* The main program maintains a few central data structures and relies
- on modules for the rest. These data structures may be accessed by modules
- through an exported API */
-
-static LttvIAttribute *attributes;
-
-static LttvHooks
- *before_options,
- *after_options,
- *before_main,
- *after_main;
-
-static char
- *a_module,
- *a_module_path;
-
-static gboolean
- a_verbose,
- a_debug;
-
-gboolean lttv_profile_memory;
-
-int lttv_argc;
-
-char **lttv_argv;
-
-static void lttv_module_option(void *hook_data);
-
-static void lttv_module_path_option(void *hook_data);
-
-static void lttv_verbose(void *hook_data);
-
-static void lttv_debug(void *hook_data);
-
-static void lttv_help(void *hook_data);
-
-/* This is the handler to specify when we dont need all the debugging
- messages. It receives the message and does nothing. */
-
-void ignore_and_drop_message(const gchar *log_domain, GLogLevelFlags log_level,
- const gchar *message, gpointer user_data) {
-}
-
-
-/* Since everything is done in modules, the main program only takes care
- of the infrastructure. */
-
-int main(int argc, char **argv) {
-
- int i;
-
- char
- *profile_memory_short_option = "-M",
- *profile_memory_long_option = "--memory";
-
- gboolean profile_memory = FALSE;
-
- LttvAttributeValue value;
-
- lttv_argc = argc;
- lttv_argv = argv;
-
- /* Before anything else, check if memory profiling is requested */
-
- for(i = 1 ; i < argc ; i++) {
- if(*(argv[i]) != '-') break;
- if(strcmp(argv[i], profile_memory_short_option) == 0 ||
- strcmp(argv[i], profile_memory_long_option) == 0) {
- g_mem_set_vtable(glib_mem_profiler_table);
- g_message("Memory summary before main");
- g_mem_profile();
- profile_memory = TRUE;
- break;
- }
- }
-
-
- /* Initialize glib and by default ignore info and debug messages */
-
- g_type_init();
- //g_type_init_with_debug_flags (G_TYPE_DEBUG_OBJECTS | G_TYPE_DEBUG_SIGNALS);
- g_log_set_handler(NULL, G_LOG_LEVEL_INFO, ignore_and_drop_message, NULL);
- g_log_set_handler(NULL, G_LOG_LEVEL_DEBUG, ignore_and_drop_message, NULL);
-
-
- /* Have an attributes subtree to store hooks to be registered by modules. */
-
- attributes = LTTV_IATTRIBUTE(g_object_new(LTTV_ATTRIBUTE_TYPE, NULL));
-
- before_options = lttv_hooks_new();
- after_options = lttv_hooks_new();
- before_main = lttv_hooks_new();
- after_main = lttv_hooks_new();
-
-
- /* Create a number of hooks lists */
-
- g_assert(lttv_iattribute_find_by_path(attributes, "hooks/options/before",
- LTTV_POINTER, &value));
- *(value.v_pointer) = before_options;
- g_assert(lttv_iattribute_find_by_path(attributes, "hooks/options/after",
- LTTV_POINTER, &value));
- *(value.v_pointer) = after_options;
- g_assert(lttv_iattribute_find_by_path(attributes, "hooks/main/before",
- LTTV_POINTER, &value));
- *(value.v_pointer) = before_main;
- g_assert(lttv_iattribute_find_by_path(attributes, "hooks/main/after",
- LTTV_POINTER, &value));
- *(value.v_pointer) = after_main;
-
-
- /* Initialize the command line options processing */
-
- GError *error = NULL;
-
- LttvModule *module_module = lttv_module_require("module", &error);
- if(error != NULL) g_error(error->message);
- LttvModule *module_option = lttv_module_require("option", &error);
- if(error != NULL) g_error(error->message);
-
- /* Initialize the module loading */
-
- lttv_library_path_add(PACKAGE_PLUGIN_DIR);
-
-
- /* Add some built-in options */
-
- lttv_option_add("module",'m', "load a module", "name of module to load",
- LTTV_OPT_STRING, &a_module, lttv_module_option, NULL);
-
- lttv_option_add("modules-path", 'L',
- "add a directory to the module search path",
- "directory to add to the path", LTTV_OPT_STRING, &a_module_path,
- lttv_module_path_option, NULL);
-
- lttv_option_add("help",'h', "basic help", "none",
- LTTV_OPT_NONE, NULL, lttv_help, NULL);
-
- a_verbose = FALSE;
- lttv_option_add("verbose",'v', "print information messages", "none",
- LTTV_OPT_NONE, NULL, lttv_verbose, NULL);
-
- a_debug = FALSE;
- lttv_option_add("debug",'d', "print debugging messages", "none",
- LTTV_OPT_NONE, NULL, lttv_debug, NULL);
-
- lttv_profile_memory = FALSE;
- lttv_option_add(profile_memory_long_option + 2,
- profile_memory_short_option[1], "print memory information", "none",
- LTTV_OPT_NONE, <tv_profile_memory, NULL, NULL);
-
-
- /* Process the options */
-
- lttv_hooks_call(before_options, NULL);
- lttv_option_parse(argc, argv);
- lttv_hooks_call(after_options, NULL);
-
-
- /* Memory profiling to be useful must be activated as early as possible */
-
- if(profile_memory != lttv_profile_memory)
- g_error("Memory profiling options must appear before other options");
-
-
- /* Do the main work */
-
- lttv_hooks_call(before_main, NULL);
- lttv_hooks_call(after_main, NULL);
-
-
- /* Clean up everything */
-
- lttv_module_release(module_option);
- lttv_module_release(module_module);
-
- lttv_hooks_destroy(before_options);
- lttv_hooks_destroy(after_options);
- lttv_hooks_destroy(before_main);
- lttv_hooks_destroy(after_main);
- g_object_unref(attributes);
-
- if(profile_memory) {
- g_message("Memory summary after main");
- g_mem_profile();
- }
- return 0;
-}
-
-
-LttvAttribute *lttv_global_attributes()
-{
- return (LttvAttribute*)attributes;
-}
-
-
-void lttv_module_option(void *hook_data)
-{
- GError *error = NULL;
-
- lttv_module_require(a_module, &error);
- if(error != NULL) g_error(error->message);
-}
-
-
-void lttv_module_path_option(void *hook_data)
-{
- lttv_library_path_add(a_module_path);
-}
-
-
-void lttv_verbose(void *hook_data)
-{
- g_log_set_handler(NULL, G_LOG_LEVEL_INFO, g_log_default_handler, NULL);
- g_info("Logging set to include INFO level messages");
-}
-
-void lttv_debug(void *hook_data)
-{
- g_log_set_handler(NULL, G_LOG_LEVEL_DEBUG, g_log_default_handler, NULL);
- g_info("Logging set to include DEBUG level messages");
-}
-
-void lttv_help(void *hook_data)
-{
- printf("Linux Trace Toolkit Visualizer\n");
- printf("\n");
- lttv_option_show_help();
- printf("\n");
-}
-
-/*
-
-- Define formally traceset/trace in the GUI for the user and decide how
- trace/traceset sharing goes in the application.
-
-- Use appropriately the new functions in time.h
-
-- remove the separate tracefiles (control/per cpu) arrays/loops in context.
-
-- split processTrace into context.c and processTrace.c
-
-- check spelling conventions.
-
-- get all the copyright notices.
-
-- remove all the warnings.
-
-- get all the .h files properly doxygen commented to produce useful documents.
-
-- have an intro/architecture document.
-
-- write a tutorial */
+++ /dev/null
-
-/* This file is part of the Linux Trace Toolkit viewer
- * Copyright (C) 2003-2004 Michel Dagenais
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License Version 2 as
- * published by the Free Software Foundation;
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA.
- */
-
-
-/* module.c : Implementation of the module loading/unloading mechanism. */
-
-#include <lttv/module.h>
-#include <gmodule.h>
-
-
-struct _LttvLibrary
-{
- LttvLibraryInfo info;
- GPtrArray *modules;
- GModule *gm;
- guint locked_loaded;
-};
-
-
-struct _LttvModule
-{
- LttvModuleInfo info;
- char **prerequisites_names;
- GPtrArray *prerequisites;
-};
-
-
-/* Modules are searched by name. However, a library may be loaded which
- provides a module with the same name as an existing one. A stack of
- modules is thus maintained for each name.
-
- Libraries correspond to glib modules. The g_module function is
- responsible for loading each library only once. */
-
-static GHashTable *modules_by_name = NULL;
-
-static GPtrArray *libraries = NULL;
-
-static GHashTable *libraries_by_g_module = NULL;
-
-static GPtrArray *library_paths = NULL;
-
-static gboolean initialized = FALSE;
-
-static gboolean destroyed = TRUE;
-
-static struct _LttvModuleDescription *builtin_chain = NULL;
-
-static struct _LttvModuleDescription *module_chain = NULL;
-
-static struct _LttvModuleDescription **module_next = &module_chain;
-
-static GQuark lttv_module_error;
-
-static void init();
-
-static finish_destroy();
-
-static void module_release(LttvModule *m);
-
-
-static LttvLibrary *library_add(char *name, char *path, GModule *gm)
-{
- LttvLibrary *l;
-
- LttvModule *m;
-
- struct _LttvModuleDescription *link;
-
- GPtrArray *modules;
-
- l = g_new(LttvLibrary, 1);
- l->modules = g_ptr_array_new();
- l->gm = gm;
- l->locked_loaded = 0;
- l->info.name = g_strdup(name);
- l->info.path = g_strdup(path);
- l->info.load_count = 0;
-
- g_ptr_array_add(libraries, l);
- g_hash_table_insert(libraries_by_g_module, gm, l);
-
- *module_next = NULL;
- for(link = module_chain; link != NULL; link = link->next) {
- m = g_new(LttvModule, 1);
- g_ptr_array_add(l->modules, m);
-
- modules = g_hash_table_lookup(modules_by_name, link->name);
- if(modules == NULL) {
- modules = g_ptr_array_new();
- g_hash_table_insert(modules_by_name, g_strdup(link->name), modules);
- }
- g_ptr_array_add(modules, m);
-
- m->prerequisites_names = link->prerequisites;
- m->prerequisites = g_ptr_array_new();
- m->info.name = link->name;
- m->info.short_description = link->short_description;
- m->info.description = link->description;
- m->info.init = link->init;
- m->info.destroy = link->destroy;
- m->info.library = l;
- m->info.require_count = 0;
- m->info.use_count = 0;
- m->info.prerequisites_number = link->prerequisites_number;
- }
- return l;
-}
-
-
-static void library_remove(LttvLibrary *l)
-{
- LttvModule *m;
-
- GPtrArray *modules;
-
- guint i;
-
- char *key;
-
- for(i = 0 ; i < l->modules->len ; i++) {
- m = (LttvModule *)(l->modules->pdata[i]);
-
- g_hash_table_lookup_extended(modules_by_name, m->info.name,
- (gpointer *)&key, (gpointer *)&modules);
- g_assert(modules != NULL);
- g_ptr_array_remove(modules, m);
- if(modules->len == 0) {
- g_hash_table_remove(modules_by_name, m->info.name);
- g_ptr_array_free(modules, TRUE);
- g_free(key);
- }
-
- g_ptr_array_free(m->prerequisites, TRUE);
- g_free(m);
- }
-
- g_ptr_array_remove(libraries, l);
- g_hash_table_remove(libraries_by_g_module, l->gm);
- g_ptr_array_free(l->modules, TRUE);
- g_free(l->info.name);
- g_free(l->info.path);
- g_free(l);
-}
-
-
-static LttvLibrary *library_load(char *name, GError **error)
-{
- GModule *gm;
-
- int i, nb;
-
- char *path, *pathname;
-
- LttvLibrary *l;
-
- GString *messages = g_string_new("");
-
- /* insure that module.c is initialized */
-
- init();
-
- /* Try to find the library along all the user specified paths */
-
- g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Load library %s", name);
- nb = lttv_library_path_number();
- for(i = 0 ; i <= nb ; i++) {
- if(i < nb) path = lttv_library_path_get(i);
- else path = NULL;
-
- pathname = g_module_build_path(path ,name);
- g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Try path %s", pathname);
- module_chain = NULL;
- module_next = &module_chain;
- gm = g_module_open(pathname,0);
- g_free(pathname);
-
- if(gm != NULL) break;
-
- g_string_append(messages, g_module_error());
- g_string_append(messages, "\n");
- g_log(G_LOG_DOMAIN,G_LOG_LEVEL_INFO,"Trial failed, %s", g_module_error());
- }
-
- /* Module cannot be found */
-
- if(gm == NULL) {
- g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Failed to load %s", name);
- g_set_error(error, lttv_module_error, LTTV_MODULE_NOT_FOUND,
- "Cannot load library %s: %s", name, messages->str);
- g_string_free(messages, TRUE);
- return NULL;
- }
- g_string_free(messages, TRUE);
-
- /* Check if the library was already loaded */
-
- l = g_hash_table_lookup(libraries_by_g_module, gm);
-
- /* This library was not already loaded */
-
- if(l == NULL) {
- g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Library %s (%s) loaded", name,
- g_module_name(gm));
- l = library_add(name, path, gm);
- }
- return l;
-}
-
-
-LttvLibrary *lttv_library_load(char *name, GError **error)
-{
- LttvLibrary *l = library_load(name, error);
- l->info.load_count++;
- return l;
-}
-
-
-static void library_unload(LttvLibrary *l)
-{
- guint i, len;
-
- GModule *gm;
-
- LttvModule *m;
-
- if(l->locked_loaded > 0) {
- g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Unload library %s: locked loaded",
- l->info.name);
- return;
- }
-
- if(l->info.load_count > 0) {
- g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Unload library %s: load count %d",
- l->info.name, l->info.load_count);
- return;
- }
-
- /* Check if all its modules have been released */
-
- for(i = 0 ; i < l->modules->len ; i++) {
- m = (LttvModule *)(l->modules->pdata[i]);
- if(m->info.use_count > 0) {
- g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO,"Unload library %s: module %s used",
- l->info.name, m->info.name);
- return;
- }
- }
-
- g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Unload library %s: close the GModule",
- l->info.name);
- gm = l->gm;
- library_remove(l);
- if(gm != NULL) g_module_close(gm);
-
- /* insure that module.c will be finalized */
-
- finish_destroy();
-}
-
-
-void lttv_library_unload(LttvLibrary *l)
-{
- l->info.load_count--;
- library_unload(l);
-}
-
-
-static void library_lock_loaded(LttvLibrary *l)
-{
- l->locked_loaded++;
-}
-
-
-static void library_unlock_loaded(LttvLibrary *l)
-{
- l->locked_loaded--;
- library_unload(l);
-}
-
-
-static LttvModule *module_require(char *name, GError **error)
-{
- GError *tmp_error = NULL;
-
- guint i, j;
-
- LttvModule *m, *required;
-
- LttvLibrary *l = NULL;
-
- GPtrArray *modules;
-
- /* Insure that module.c is initialized */
-
- init();
-
- /* Check if the module is already loaded */
-
- modules = g_hash_table_lookup(modules_by_name, name);
-
- /* Try to load a library having the module name */
-
- if(modules == NULL) {
- l = library_load(name, error);
- if(l == NULL) return NULL;
- else library_lock_loaded(l);
-
- /* A library was found, does it contain the named module */
-
- modules = g_hash_table_lookup(modules_by_name, name);
- if(modules == NULL) {
- g_set_error(error, lttv_module_error, LTTV_MODULE_NOT_FOUND,
- "Module %s not found in library %s", name, l->info.name);
- library_unlock_loaded(l);
- return NULL;
- }
- }
- m = (LttvModule *)(modules->pdata[modules->len - 1]);
-
- /* We have the module */
-
- m->info.use_count++;
-
- /* First use of the module. Initialize after getting the prerequisites */
-
- if(m->info.use_count == 1) {
- for(i = 0 ; i < m->info.prerequisites_number ; i++) {
- required = module_require(m->prerequisites_names[i], &tmp_error);
-
- /* A prerequisite could not be found, undo everything and fail */
-
- if(required == NULL) {
- for(j = 0 ; j < m->prerequisites->len ; j++) {
- module_release((LttvModule *)(m->prerequisites->pdata[j]));
- }
- g_ptr_array_set_size(m->prerequisites, 0);
- if(l != NULL) library_unlock_loaded(l);
- g_set_error(error, lttv_module_error, LTTV_MODULE_NOT_FOUND,
- "Cannot find prerequisite for module %s: %s", name,
- tmp_error->message);
- g_clear_error(&tmp_error);
- return NULL;
- }
- g_ptr_array_add(m->prerequisites, required);
- }
- g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Module %s: init()", m->info.name);
- m->info.init();
- }
-
- /* Decrement the load count of the library. It will not really be
- unloaded since it contains a currently used module. */
-
- if(l != NULL) library_unlock_loaded(l);
-
- return(m);
-}
-
-
-/* The require_count for a module is the number of explicit calls to
- lttv_module_require, while the use_count also counts the number of times
- a module is needed as a prerequisite. */
-
-LttvModule *lttv_module_require(char *name, GError **error)
-{
- LttvModule *m = module_require(name, error);
- if(m != NULL) m->info.require_count++;
- return(m);
-}
-
-
-static void module_release(LttvModule *m)
-{
- guint i;
-
- library_lock_loaded(m->info.library);
-
- m->info.use_count--;
- if(m->info.use_count == 0) {
- g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Module %s: destroy()",m->info.name);
- m->info.destroy();
- for(i = 0 ; i < m->prerequisites->len ; i++) {
- module_release((LttvModule *)(m->prerequisites->pdata[i]));
- }
- g_ptr_array_set_size(m->prerequisites, 0);
- }
- library_unlock_loaded(m->info.library);
-}
-
-
-void lttv_module_release(LttvModule *m)
-{
- m->info.require_count--;
- module_release(m);
-}
-
-
-void lttv_module_info(LttvModule *m, LttvModuleInfo *info)
-{
- *info = m->info;
-}
-
-
-unsigned lttv_module_prerequisite_number(LttvModule *m)
-{
- return m->prerequisites->len;
-}
-
-
-LttvModule *lttv_module_prerequisite_get(LttvModule *m, unsigned i)
-{
- return (LttvModule *)(m->prerequisites->pdata[i]);
-}
-
-
-void lttv_library_info(LttvLibrary *l, LttvLibraryInfo *info)
-{
- *info = l->info;
-}
-
-
-unsigned lttv_library_module_number(LttvLibrary *l)
-{
- return l->modules->len;
-}
-
-
-LttvModule *lttv_library_module_get(LttvLibrary *l, unsigned i)
-{
- return (LttvModule *)(l->modules->pdata[i]);
-}
-
-
-unsigned lttv_library_number()
-{
- return libraries->len;
-}
-
-
-LttvLibrary *lttv_library_get(unsigned i)
-{
- return (LttvLibrary *)(libraries->pdata[i]);
-}
-
-
-void lttv_library_path_add(char *name)
-{
- g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Add library path %s", name);
- g_ptr_array_add(library_paths,(char*)g_strdup(name));
-}
-
-
-void lttv_library_path_remove(char *name)
-{
- guint i;
-
- for(i = 0 ; i < library_paths->len ; i++) {
- if(g_str_equal(name, library_paths->pdata[i])) {
- g_free(library_paths->pdata[i]);
- g_ptr_array_remove_index(library_paths,i);
- return;
- }
- }
-}
-
-
-unsigned lttv_library_path_number()
-{
- return library_paths->len;
-}
-
-
-char *lttv_library_path_get(unsigned i)
-{
- return (char *)(library_paths->pdata[library_paths->len - i - 1]);
-}
-
-
-void lttv_module_register(struct _LttvModuleDescription *d)
-{
- *module_next = d;
- module_next = &(d->next);
-}
-
-
-static void init()
-{
- if(initialized) return;
- g_assert(destroyed);
-
- g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Init module.c");
-
- initialized = TRUE;
- destroyed = FALSE;
- lttv_module_error = g_quark_from_string("LTTV_MODULE_ERROR");
- modules_by_name = g_hash_table_new(g_str_hash, g_str_equal);
- libraries = g_ptr_array_new();
- libraries_by_g_module = g_hash_table_new(g_direct_hash, g_direct_equal);
- library_paths = g_ptr_array_new();
-
- if(builtin_chain == NULL) builtin_chain = module_chain;
- module_chain = builtin_chain;
- library_add("builtin", NULL, NULL);
-}
-
-
-static finish_destroy()
-{
- guint i;
-
- if(initialized) return;
- g_assert(!destroyed);
-
- g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Finish destroy module.c");
- g_hash_table_destroy(modules_by_name);
- g_ptr_array_free(libraries, TRUE);
- g_hash_table_destroy(libraries_by_g_module);
- for(i = 0 ; i < library_paths->len ; i++) {
- g_free(library_paths->pdata[i]);
- }
- g_ptr_array_free(library_paths, TRUE);
- destroyed = TRUE;
-}
-
-
-static void destroy()
-{
- guint i, j, nb;
-
- LttvLibrary *l, **locked_libraries;
-
- LttvModule *m;
-
- g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Destroy module.c");
-
- /* Unload all libraries */
-
- nb = libraries->len;
- locked_libraries = g_new(LttvLibrary *, nb);
-
- for(i = 0 ; i < nb ; i++) {
- l = (LttvLibrary *)(libraries->pdata[i]);
- locked_libraries[i] = l;
- library_lock_loaded(l);
- for(j = 0 ; j < l->modules->len ; j++) {
- m = (LttvModule *)(l->modules->pdata[j]);
- while(m->info.require_count > 0) lttv_module_release(m);
- }
- while(l->info.load_count > 0) lttv_library_unload(l);
- }
-
- for(i = 0 ; i < nb ; i++) {
- l = locked_libraries[i];
- library_unlock_loaded(l);
- }
- g_free(locked_libraries);
-
- /* The library containing module.c may be locked by our caller */
-
- g_assert(libraries->len <= 1);
-
- initialized = FALSE;
-}
-
-LTTV_MODULE("module", "Modules in libraries", \
- "Load libraries, list, require and initialize contained modules", \
- init, destroy)
-
+++ /dev/null
-/* This file is part of the Linux Trace Toolkit viewer
- * Copyright (C) 2003-2004 Michel Dagenais
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License Version 2 as
- * published by the Free Software Foundation;
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA.
- */
-
-
-#include <popt.h>
-#include <glib.h>
-#include <lttv/module.h>
-#include <lttv/option.h>
-
-typedef struct _LttvOption {
- char *long_name;
- char char_name;
- char *description;
- char *arg_description;
- LttvOptionType t;
- gpointer p;
- LttvOptionHook hook;
- gpointer hook_data;
-} LttvOption;
-
-GHashTable *options;
-
-
-static void
-list_options(gpointer key, gpointer value, gpointer user_data)
-{
- g_ptr_array_add((GPtrArray *)user_data, value);
-}
-
-
-static void
-free_option(LttvOption *option)
-{
- g_free(option->long_name);
- g_free(option->description);
- g_free(option->arg_description);
- g_free(option);
-}
-
-
-void lttv_option_add(const char *long_name, const char char_name,
- const char *description, const char *arg_description,
- const LttvOptionType t, void *p,
- const LttvOptionHook h, void *hook_data)
-{
- LttvOption *option;
-
- g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Add option %s", long_name);
- if(g_hash_table_lookup(options, long_name) != NULL) {
- g_warning("duplicate option");
- return;
- }
-
- option = g_new(LttvOption, 1);
- option->long_name = g_strdup(long_name);
- option->char_name = char_name;
- option->description = g_strdup(description);
- option->arg_description = g_strdup(arg_description);
- option->t = t;
- option->p = p;
- option->hook = h;
- option->hook_data = hook_data;
- g_hash_table_insert(options, option->long_name, option);
-}
-
-
-void
-lttv_option_remove(const char *long_name)
-{
- LttvOption *option = g_hash_table_lookup(options, long_name);
-
- g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Remove option %s", long_name);
- if(option == NULL) {
- g_warning("trying to remove unknown option %s", long_name);
- return;
- }
- g_hash_table_remove(options, long_name);
- free_option(option);
-}
-
-
-static int poptToLTT[] = {
- POPT_ARG_NONE, POPT_ARG_STRING, POPT_ARG_INT, POPT_ARG_LONG
-};
-
-static struct poptOption endOption = { NULL, '\0', 0, NULL, 0};
-
-
-static void
-build_popts(GPtrArray **plist, struct poptOption **ppopts, poptContext *pc,
- int argc, char **argv)
-{
- LttvOption *option;
-
- GPtrArray *list;
-
- struct poptOption *popts;
-
- poptContext c;
-
- guint i;
-
- list = g_ptr_array_new();
-
- g_hash_table_foreach(options, list_options, list);
-
- /* Build a popt options array from our list */
-
- popts = g_new(struct poptOption, list->len + 1);
-
- for(i = 0 ; i < list->len ; i++) {
- option = (LttvOption *)list->pdata[i];
- popts[i].longName = option->long_name;
- popts[i].shortName = option->char_name;
- popts[i].descrip = option->description;
- popts[i].argDescrip = option->arg_description;
- popts[i].argInfo = poptToLTT[option->t];
- popts[i].arg = option->p;
- popts[i].val = i + 1;
- }
-
- /* Terminate the array for popt and create the context */
-
- popts[list->len] = endOption;
- c = poptGetContext(argv[0], argc, (const char**)argv, popts, 0);
-
- *plist = list;
- *ppopts = popts;
- *pc = c;
-}
-
-
-static void
-destroy_popts(GPtrArray **plist, struct poptOption **ppopts, poptContext *pc)
-{
- g_ptr_array_free(*plist, TRUE); *plist = NULL;
- g_free(*ppopts); *ppopts = NULL;
- poptFreeContext(*pc);
-}
-
-
-void lttv_option_parse(int argc, char **argv)
-{
- GPtrArray *list;
-
- LttvOption *option;
-
- int i, rc, first_arg;
-
- struct poptOption *popts;
-
- poptContext c;
-
- i = 0;
-
- first_arg = 0;
-
- build_popts(&list, &popts, &c, argc, argv);
-
- /* Parse options while not end of options event */
-
- while((rc = poptGetNextOpt(c)) != -1) {
-
- /* The option was recognized and the rc value returned is the argument
- position in the array. Call the associated hook if present. */
-
- if(rc > 0) {
- option = (LttvOption *)(list->pdata[rc - 1]);
- g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Option %s encountered",
- option->long_name);
- if(option->hook != NULL) {
- g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Option %s hook called",
- option->long_name);
- option->hook(option->hook_data);
- }
- i++;
- }
-
- else if(rc == POPT_ERROR_BADOPT && i != first_arg) {
- g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,
- "Option %s not recognized, rescan options with new additions",
- poptBadOption(c,0));
-
- /* Perhaps this option is newly added, restart parsing */
-
- destroy_popts(&list, &popts, &c);
- build_popts(&list, &popts, &c, argc, argv);
-
- /* Get back to the same argument */
-
- first_arg = i;
- for(i = 0; i < first_arg; i++) {
- rc = poptGetNextOpt(c);
- option = (LttvOption *)(list->pdata[rc - 1]);
- g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Option %s rescanned, skipped",
- option->long_name);
- }
- }
-
- else {
-
- /* The option has some error and it is not because this is a newly
- added option not recognized. */
-
- g_error("option %s: %s", poptBadOption(c,0), poptStrerror(rc));
- break;
- }
-
- }
-
- destroy_popts(&list, &popts, &c);
-}
-
-/* CHECK */
-static void show_help(LttvOption *option)
-{
- printf("--%s -%c argument: %s\n" , option->long_name,
- option->char_name,
- option->arg_description);
- printf(" %s\n" , option->description);
-
-}
-
-void lttv_option_show_help(void)
-{
- LttvOption option;
-
- GPtrArray *list = g_ptr_array_new();
-
- int i;
-
- g_hash_table_foreach(options, list_options, list);
-
- printf("Built-in commands available:\n");
- printf("\n");
-
- for(i = 0 ; i < list->len ; i++) {
- show_help((LttvOption *)list->pdata[i]);
- }
- g_ptr_array_free(list, TRUE);
-
-
-}
-
-static void init()
-{
- g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Init option.c");
- options = g_hash_table_new(g_str_hash, g_str_equal);
-}
-
-
-static void destroy()
-{
- LttvOption option;
-
- GPtrArray *list = g_ptr_array_new();
-
- int i;
-
- g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Destroy option.c");
- g_hash_table_foreach(options, list_options, list);
- g_hash_table_destroy(options);
-
- for(i = 0 ; i < list->len ; i++) {
- free_option((LttvOption *)list->pdata[i]);
- }
- g_ptr_array_free(list, TRUE);
-}
-
-LTTV_MODULE("option", "Command line options processing", \
- "Functions to add, remove and parse command line options", \
- init, destroy)
+++ /dev/null
-/* This file is part of the Linux Trace Toolkit viewer
- * Copyright (C) 2003-2004 Michel Dagenais
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License Version 2 as
- * published by the Free Software Foundation;
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA.
- */
-
-
-#include <lttv/processTrace.h>
-#include <ltt/event.h>
-#include <ltt/facility.h>
-#include <ltt/trace.h>
-#include <ltt/type.h>
-
-void lttv_context_init(LttvTracesetContext *self, LttvTraceset *ts)
-{
- LTTV_TRACESET_CONTEXT_GET_CLASS(self)->init(self, ts);
-}
-
-
-void lttv_context_fini(LttvTracesetContext *self)
-{
- LTTV_TRACESET_CONTEXT_GET_CLASS(self)->fini(self);
-}
-
-
-LttvTracesetContext *
-lttv_context_new_traceset_context(LttvTracesetContext *self)
-{
- return LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_traceset_context(self);
-}
-
-
-
-
-LttvTraceContext *
-lttv_context_new_trace_context(LttvTracesetContext *self)
-{
- return LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_trace_context(self);
-}
-
-
-LttvTracefileContext *
-lttv_context_new_tracefile_context(LttvTracesetContext *self)
-{
- return LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_tracefile_context(self);
-}
-
-/****************************************************************************
- * lttv_traceset_context_compute_time_span
- *
- * Keep the Time_Span is sync with on the fly addition and removal of traces
- * in a trace set. It must be called each time a trace is added/removed from
- * the traceset. It could be more efficient to call it only once a bunch
- * of traces are loaded, but the calculation is not long, so it's not
- * critical.
- *
- * Author : Xang Xiu Yang
- * Imported from gtkTraceSet.c by Mathieu Desnoyers
- ***************************************************************************/
-static void lttv_traceset_context_compute_time_span(
- LttvTracesetContext *self,
- TimeInterval *Time_Span)
-{
- LttvTraceset * traceset = self->ts;
- int numTraces = lttv_traceset_number(traceset);
- int i;
- LttTime s, e;
- LttvTraceContext *tc;
- LttTrace * trace;
-
- Time_Span->startTime.tv_sec = 0;
- Time_Span->startTime.tv_nsec = 0;
- Time_Span->endTime.tv_sec = 0;
- Time_Span->endTime.tv_nsec = 0;
-
- for(i=0; i<numTraces;i++){
- tc = self->traces[i];
- trace = tc->t;
-
- ltt_trace_time_span_get(trace, &s, &e);
-
- if(i==0){
- Time_Span->startTime = s;
- Time_Span->endTime = e;
- }else{
- if(s.tv_sec < Time_Span->startTime.tv_sec ||
- (s.tv_sec == Time_Span->startTime.tv_sec
- && s.tv_nsec < Time_Span->startTime.tv_nsec))
- Time_Span->startTime = s;
- if(e.tv_sec > Time_Span->endTime.tv_sec ||
- (e.tv_sec == Time_Span->endTime.tv_sec &&
- e.tv_nsec > Time_Span->endTime.tv_nsec))
- Time_Span->endTime = e;
- }
- }
-}
-
-
-static void
-init(LttvTracesetContext *self, LttvTraceset *ts)
-{
- guint i, j, nb_trace, nb_control, nb_per_cpu, nb_tracefile;
-
- LttvTraceContext *tc;
-
- LttvTracefileContext *tfc;
-
- LttTime null_time = {0, 0};
-
- nb_trace = lttv_traceset_number(ts);
- self->ts = ts;
- self->traces = g_new(LttvTraceContext *, nb_trace);
- self->before = lttv_hooks_new();
- self->after = lttv_hooks_new();
- self->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
- self->ts_a = lttv_traceset_attribute(ts);
- for(i = 0 ; i < nb_trace ; i++) {
- tc = LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_trace_context(self);
- self->traces[i] = tc;
-
- tc->ts_context = self;
- tc->index = i;
- tc->vt = lttv_traceset_get(ts, i);
- tc->t = lttv_trace(tc->vt);
- tc->check = lttv_hooks_new();
- tc->before = lttv_hooks_new();
- tc->after = lttv_hooks_new();
- tc->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
- tc->t_a = lttv_trace_attribute(tc->vt);
- nb_control = ltt_trace_control_tracefile_number(tc->t);
- nb_per_cpu = ltt_trace_per_cpu_tracefile_number(tc->t);
- nb_tracefile = nb_control + nb_per_cpu;
- tc->tracefiles = g_new(LttvTracefileContext *, nb_tracefile);
-
- for(j = 0 ; j < nb_tracefile ; j++) {
- tfc = LTTV_TRACESET_CONTEXT_GET_CLASS(self)->new_tracefile_context(self);
- tc->tracefiles[j] = tfc;
- tfc->index = j;
-
- if(j < nb_control) {
- tfc->control = TRUE;
- tfc->tf = ltt_trace_control_tracefile_get(tc->t, j);
- }
- else {
- tfc->control = FALSE;
- tfc->tf = ltt_trace_per_cpu_tracefile_get(tc->t, j - nb_control);
- }
- tfc->t_context = tc;
- tfc->check = lttv_hooks_new();
- tfc->before = lttv_hooks_new();
- tfc->after = lttv_hooks_new();
- tfc->check_event = lttv_hooks_new();
- tfc->before_event = lttv_hooks_new();
- tfc->before_event_by_id = lttv_hooks_by_id_new();
- tfc->after_event = lttv_hooks_new();
- tfc->after_event_by_id = lttv_hooks_by_id_new();
- tfc->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
- }
- }
- lttv_process_traceset_seek_time(self, null_time);
- /*CHECK why dynamically allocate the time span... and the casing is wroNg*/
- self->Time_Span = g_new(TimeInterval,1);
- lttv_traceset_context_compute_time_span(self, self->Time_Span);
-}
-
-
-void fini(LttvTracesetContext *self)
-{
- guint i, j, nb_trace, nb_tracefile;
-
- LttvTraceContext *tc;
-
- LttvTracefileContext *tfc;
-
- LttvTraceset *ts = self->ts;
-
- g_free(self->Time_Span);
-
- lttv_hooks_destroy(self->before);
- lttv_hooks_destroy(self->after);
- //FIXME : segfault
- g_object_unref(self->a);
-
- nb_trace = lttv_traceset_number(ts);
-
- for(i = 0 ; i < nb_trace ; i++) {
- tc = self->traces[i];
-
- lttv_hooks_destroy(tc->check);
- lttv_hooks_destroy(tc->before);
- lttv_hooks_destroy(tc->after);
- g_object_unref(tc->a);
-
- nb_tracefile = ltt_trace_control_tracefile_number(tc->t) +
- ltt_trace_per_cpu_tracefile_number(tc->t);
-
- for(j = 0 ; j < nb_tracefile ; j++) {
- tfc = tc->tracefiles[j];
- lttv_hooks_destroy(tfc->check);
- lttv_hooks_destroy(tfc->before);
- lttv_hooks_destroy(tfc->after);
- lttv_hooks_destroy(tfc->check_event);
- lttv_hooks_destroy(tfc->before_event);
- lttv_hooks_by_id_destroy(tfc->before_event_by_id);
- lttv_hooks_destroy(tfc->after_event);
- lttv_hooks_by_id_destroy(tfc->after_event_by_id);
- g_object_unref(tfc->a);
- g_object_unref(tfc);
- }
- g_free(tc->tracefiles);
- g_object_unref(tc);
- }
- g_free(self->traces);
-}
-
-
-void lttv_traceset_context_add_hooks(LttvTracesetContext *self,
- LttvHooks *before_traceset,
- LttvHooks *after_traceset,
- LttvHooks *check_trace,
- LttvHooks *before_trace,
- LttvHooks *after_trace,
- LttvHooks *check_tracefile,
- LttvHooks *before_tracefile,
- LttvHooks *after_tracefile,
- LttvHooks *check_event,
- LttvHooks *before_event,
- LttvHooks *after_event)
-{
- LttvTraceset *ts = self->ts;
-
- guint i, j, nb_trace, nb_tracefile;
-
- LttvTraceContext *tc;
-
- LttvTracefileContext *tfc;
-
- void *hook_data;
-
- lttv_hooks_add_list(self->before, before_traceset);
- lttv_hooks_add_list(self->after, after_traceset);
- nb_trace = lttv_traceset_number(ts);
-
- for(i = 0 ; i < nb_trace ; i++) {
- tc = self->traces[i];
- lttv_hooks_add_list(tc->check, check_trace);
- lttv_hooks_add_list(tc->before, before_trace);
- lttv_hooks_add_list(tc->after, after_trace);
- nb_tracefile = ltt_trace_control_tracefile_number(tc->t) +
- ltt_trace_per_cpu_tracefile_number(tc->t);
-
- for(j = 0 ; j < nb_tracefile ; j++) {
- tfc = tc->tracefiles[j];
- lttv_hooks_add_list(tfc->check, check_tracefile);
- lttv_hooks_add_list(tfc->before, before_tracefile);
- lttv_hooks_add_list(tfc->after, after_tracefile);
- lttv_hooks_add_list(tfc->check_event, check_event);
- lttv_hooks_add_list(tfc->before_event, before_event);
- lttv_hooks_add_list(tfc->after_event, after_event);
- }
- }
-}
-
-
-void lttv_traceset_context_remove_hooks(LttvTracesetContext *self,
- LttvHooks *before_traceset,
- LttvHooks *after_traceset,
- LttvHooks *check_trace,
- LttvHooks *before_trace,
- LttvHooks *after_trace,
- LttvHooks *check_tracefile,
- LttvHooks *before_tracefile,
- LttvHooks *after_tracefile,
- LttvHooks *check_event,
- LttvHooks *before_event,
- LttvHooks *after_event)
-{
- LttvTraceset *ts = self->ts;
-
- guint i, j, nb_trace, nb_tracefile;
-
- LttvTraceContext *tc;
-
- LttvTracefileContext *tfc;
-
- void *hook_data;
-
- lttv_hooks_remove_list(self->before, before_traceset);
- lttv_hooks_remove_list(self->after, after_traceset);
- nb_trace = lttv_traceset_number(ts);
-
- for(i = 0 ; i < nb_trace ; i++) {
- tc = self->traces[i];
- lttv_hooks_remove_list(tc->check, check_trace);
- lttv_hooks_remove_list(tc->before, before_trace);
- lttv_hooks_remove_list(tc->after, after_trace);
- nb_tracefile = ltt_trace_control_tracefile_number(tc->t) +
- ltt_trace_per_cpu_tracefile_number(tc->t);
-
- for(j = 0 ; j < nb_tracefile ; j++) {
- tfc = tc->tracefiles[j];
- lttv_hooks_remove_list(tfc->check, check_tracefile);
- lttv_hooks_remove_list(tfc->before, before_tracefile);
- lttv_hooks_remove_list(tfc->after, after_tracefile);
- lttv_hooks_remove_list(tfc->check_event, check_event);
- lttv_hooks_remove_list(tfc->before_event, before_event);
- lttv_hooks_remove_list(tfc->after_event, after_event);
- }
- }
-}
-
-void lttv_trace_context_add_hooks(LttvTraceContext *tc,
- LttvHooks *check_trace,
- LttvHooks *before_trace,
- LttvHooks *after_trace)
-{
- lttv_hooks_add_list(tc->check, check_trace);
- lttv_hooks_add_list(tc->before, before_trace);
- lttv_hooks_add_list(tc->after, after_trace);
-}
-
-void lttv_trace_context_remove_hooks(LttvTraceContext *tc,
- LttvHooks *check_trace,
- LttvHooks *before_trace,
- LttvHooks *after_trace)
-{
- lttv_hooks_remove_list(tc->check, check_trace);
- lttv_hooks_remove_list(tc->before, before_trace);
- lttv_hooks_remove_list(tc->after, after_trace);
-}
-
-void lttv_tracefile_context_add_hooks(LttvTracefileContext *tfc,
- LttvHooks *check_tracefile,
- LttvHooks *before_tracefile,
- LttvHooks *after_tracefile,
- LttvHooks *check_event,
- LttvHooks *before_event,
- LttvHooks *after_event)
-{
- lttv_hooks_add_list(tfc->check, check_tracefile);
- lttv_hooks_add_list(tfc->before, before_tracefile);
- lttv_hooks_add_list(tfc->after, after_tracefile);
- lttv_hooks_add_list(tfc->check_event, check_event);
- lttv_hooks_add_list(tfc->before_event, before_event);
- lttv_hooks_add_list(tfc->after_event, after_event);
-}
-
-void lttv_tracefile_context_remove_hooks(LttvTracefileContext *tfc,
- LttvHooks *check_tracefile,
- LttvHooks *before_tracefile,
- LttvHooks *after_tracefile,
- LttvHooks *check_event,
- LttvHooks *before_event,
- LttvHooks *after_event)
-{
- lttv_hooks_remove_list(tfc->check, check_tracefile);
- lttv_hooks_remove_list(tfc->before, before_tracefile);
- lttv_hooks_remove_list(tfc->after, after_tracefile);
- lttv_hooks_remove_list(tfc->check_event, check_event);
- lttv_hooks_remove_list(tfc->before_event, before_event);
- lttv_hooks_remove_list(tfc->after_event, after_event);
-}
-
-void lttv_tracefile_context_add_hooks_by_id(LttvTracefileContext *tfc,
- unsigned i,
- LttvHooks *before_event_by_id,
- LttvHooks *after_event_by_id)
-{
- LttvHooks * h;
- h = lttv_hooks_by_id_find(tfc->before_event_by_id, i);
- lttv_hooks_add_list(h, before_event_by_id);
- h = lttv_hooks_by_id_find(tfc->after_event_by_id, i);
- lttv_hooks_add_list(h, after_event_by_id);
-}
-
-void lttv_tracefile_context_remove_hooks_by_id(LttvTracefileContext *tfc,
- unsigned i)
-{
- lttv_hooks_by_id_remove(tfc->before_event_by_id, i);
- lttv_hooks_by_id_remove(tfc->after_event_by_id, i);
-}
-
-static LttvTracesetContext *
-new_traceset_context(LttvTracesetContext *self)
-{
- return g_object_new(LTTV_TRACESET_CONTEXT_TYPE, NULL);
-}
-
-
-static LttvTraceContext *
-new_trace_context(LttvTracesetContext *self)
-{
- return g_object_new(LTTV_TRACE_CONTEXT_TYPE, NULL);
-}
-
-
-static LttvTracefileContext *
-new_tracefile_context(LttvTracesetContext *self)
-{
- return g_object_new(LTTV_TRACEFILE_CONTEXT_TYPE, NULL);
-}
-
-
-static void
-traceset_context_instance_init (GTypeInstance *instance, gpointer g_class)
-{
- /* Be careful of anything which would not work well with shallow copies */
-}
-
-
-static void
-traceset_context_finalize (LttvTracesetContext *self)
-{
- G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACESET_CONTEXT_TYPE)))
- ->finalize(G_OBJECT(self));
-}
-
-
-static void
-traceset_context_class_init (LttvTracesetContextClass *klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
-
- gobject_class->finalize = (void (*)(GObject *self))traceset_context_finalize;
- klass->init = init;
- klass->fini = fini;
- klass->new_traceset_context = new_traceset_context;
- klass->new_trace_context = new_trace_context;
- klass->new_tracefile_context = new_tracefile_context;
-}
-
-
-GType
-lttv_traceset_context_get_type(void)
-{
- static GType type = 0;
- if (type == 0) {
- static const GTypeInfo info = {
- sizeof (LttvTracesetContextClass),
- NULL, /* base_init */
- NULL, /* base_finalize */
- (GClassInitFunc) traceset_context_class_init, /* class_init */
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (LttvTracesetContext),
- 0, /* n_preallocs */
- (GInstanceInitFunc) traceset_context_instance_init /* instance_init */
- };
-
- type = g_type_register_static (G_TYPE_OBJECT, "LttvTracesetContextType",
- &info, 0);
- }
- return type;
-}
-
-
-static void
-trace_context_instance_init (GTypeInstance *instance, gpointer g_class)
-{
- /* Be careful of anything which would not work well with shallow copies */
-}
-
-
-static void
-trace_context_finalize (LttvTraceContext *self)
-{
- G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACE_CONTEXT_TYPE)))->
- finalize(G_OBJECT(self));
-}
-
-
-static void
-trace_context_class_init (LttvTraceContextClass *klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
-
- gobject_class->finalize = (void (*)(GObject *self)) trace_context_finalize;
-}
-
-
-GType
-lttv_trace_context_get_type(void)
-{
- static GType type = 0;
- if (type == 0) {
- static const GTypeInfo info = {
- sizeof (LttvTraceContextClass),
- NULL, /* base_init */
- NULL, /* base_finalize */
- (GClassInitFunc) trace_context_class_init, /* class_init */
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (LttvTraceContext),
- 0, /* n_preallocs */
- (GInstanceInitFunc) trace_context_instance_init /* instance_init */
- };
-
- type = g_type_register_static (G_TYPE_OBJECT, "LttvTraceContextType",
- &info, 0);
- }
- return type;
-}
-
-
-static void
-tracefile_context_instance_init (GTypeInstance *instance, gpointer g_class)
-{
- /* Be careful of anything which would not work well with shallow copies */
-}
-
-
-static void
-tracefile_context_finalize (LttvTracefileContext *self)
-{
- G_OBJECT_CLASS(g_type_class_peek(g_type_parent(LTTV_TRACEFILE_CONTEXT_TYPE)))
- ->finalize(G_OBJECT(self));
-}
-
-
-static void
-tracefile_context_class_init (LttvTracefileContextClass *klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
-
- gobject_class->finalize = (void (*)(GObject *self))tracefile_context_finalize;
-}
-
-
-GType
-lttv_tracefile_context_get_type(void)
-{
- static GType type = 0;
- if (type == 0) {
- static const GTypeInfo info = {
- sizeof (LttvTracefileContextClass),
- NULL, /* base_init */
- NULL, /* base_finalize */
- (GClassInitFunc) tracefile_context_class_init, /* class_init */
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (LttvTracefileContext),
- 0, /* n_preallocs */
- (GInstanceInitFunc) tracefile_context_instance_init /* instance_init */
- };
-
- type = g_type_register_static (G_TYPE_OBJECT, "LttvTracefileContextType",
- &info, 0);
- }
- return type;
-}
-
-
-gint compare_tracefile(gconstpointer a, gconstpointer 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);
-}
-
-
-gboolean get_first(gpointer key, gpointer value, gpointer user_data) {
- *((LttvTracefileContext **)user_data) = (LttvTracefileContext *)value;
- return TRUE;
-}
-
-
-void lttv_process_traceset_begin(LttvTracesetContext *self, LttTime end)
-{
- guint i, j, nbi, nb_tracefile;
-
- LttvTraceContext *tc;
-
- LttvTracefileContext *tfc;
-
- /* Call all before_traceset, before_trace, and before_tracefile hooks.
- For all qualifying tracefiles, seek to the start time, create a context,
- read one event and insert in the pqueue based on the event time. */
-
- lttv_hooks_call(self->before, self);
- nbi = lttv_traceset_number(self->ts);
- self->pqueue = g_tree_new(compare_tracefile);
-
- for(i = 0 ; i < nbi ; i++) {
- tc = self->traces[i];
-
- if(!lttv_hooks_call_check(tc->check, tc)) {
- lttv_hooks_call(tc->before, tc);
- nb_tracefile = ltt_trace_control_tracefile_number(tc->t) +
- ltt_trace_per_cpu_tracefile_number(tc->t);
-
- for(j = 0 ; j < nb_tracefile ; j++) {
- tfc = tc->tracefiles[j];
-
- if(!lttv_hooks_call_check(tfc->check, tfc)) {
- lttv_hooks_call(tfc->before, tfc);
-
- if(tfc->e != NULL) {
- 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, tfc);
- }
- }
- }
- }
- }
- }
-}
-
-
-guint lttv_process_traceset_middle(LttvTracesetContext *self, LttTime end,
- unsigned nb_events)
-{
- GTree *pqueue = self->pqueue;
-
- guint id;
-
- LttvTraceContext *tc;
-
- LttvTracefileContext *tfc;
-
- LttEvent *event;
-
- unsigned count = 0;
-
- LttTime previous_timestamp = {0, 0};
-
- /* Get the next event from the pqueue, call its hooks,
- reinsert in the pqueue the following event from the same tracefile
- unless the tracefile is finished or the event is later than the
- start time. */
-
- while(TRUE) {
- tfc = NULL;
- g_tree_foreach(pqueue, get_first, &tfc);
- if(tfc == NULL) return count;
-
- /* Have we reached the maximum number of events specified? However,
- continue for all the events with the same time stamp (CHECK?). Then,
- empty the queue and break from the loop. */
-
- if(count >= nb_events &&
- ltt_time_compare(tfc->timestamp, previous_timestamp) != 0)
- return count;
-
- previous_timestamp = tfc->timestamp;
-
-
- /* Get the tracefile with an event for the smallest time found. If two
- or more tracefiles have events for the same time, hope that lookup
- and remove are consistent. */
-
- g_tree_remove(pqueue, tfc);
- count++;
-
- if(!lttv_hooks_call(tfc->check_event, tfc)) {
- id = ltt_event_eventtype_id(tfc->e);
- lttv_hooks_call(lttv_hooks_by_id_get(tfc->before_event_by_id, id), tfc);
- lttv_hooks_call(tfc->before_event, tfc);
- lttv_hooks_call(lttv_hooks_by_id_get(tfc->after_event_by_id, id), tfc);
- lttv_hooks_call(tfc->after_event, tfc);
- }
-
- event = ltt_tracefile_read(tfc->tf);
- if(event != NULL) {
- tfc->e = event;
- 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, tfc);
- }
- }
-}
-
-
-void lttv_process_traceset_end(LttvTracesetContext *self)
-{
- guint i, j, nbi, nb_tracefile;
-
- LttvTraceContext *tc;
-
- LttvTracefileContext *tfc;
-
- /* Call all after_traceset, after_trace, and after_tracefile hooks. */
-
- nbi = lttv_traceset_number(self->ts);
-
- for(i = 0 ; i < nbi ; i++) {
- tc = self->traces[i];
-
- /* The check hooks are called again to avoid memorizing the results
- obtained at the beginning. CHECK if it poses a problem */
-
- if(!lttv_hooks_call_check(tc->check, tc)) {
- nb_tracefile = ltt_trace_control_tracefile_number(tc->t) +
- ltt_trace_per_cpu_tracefile_number(tc->t);
-
- for(j = 0 ; j < nb_tracefile ; j++) {
- tfc = tc->tracefiles[j];
-
- if(!lttv_hooks_call_check(tfc->check, tfc)) {
- lttv_hooks_call(tfc->after, tfc);
- }
- }
- lttv_hooks_call(tc->after, tc);
- }
- }
- lttv_hooks_call(self->after, self);
-
- /* Empty and free the pqueue */
-
- while(TRUE){
- tfc = NULL;
- g_tree_foreach(self->pqueue, get_first, &tfc);
- if(tfc == NULL) break;
- g_tree_remove(self->pqueue, &(tfc->timestamp));
- }
- g_tree_destroy(self->pqueue);
-}
-
-
-void lttv_process_traceset(LttvTracesetContext *self, LttTime end,
- unsigned nb_events)
-{
- lttv_process_traceset_begin(self, end);
- lttv_process_traceset_middle(self, end, nb_events);
- lttv_process_traceset_end(self);
-}
-
-
-void lttv_process_trace_seek_time(LttvTraceContext *self, LttTime start)
-{
- guint i, nb_tracefile;
-
- LttvTracefileContext *tfc;
-
- LttEvent *event;
-
- nb_tracefile = ltt_trace_control_tracefile_number(self->t) +
- ltt_trace_per_cpu_tracefile_number(self->t);
-
- for(i = 0 ; i < nb_tracefile ; i++) {
- tfc = self->tracefiles[i];
- ltt_tracefile_seek_time(tfc->tf, start);
- event = ltt_tracefile_read(tfc->tf);
- tfc->e = event;
- if(event != NULL) tfc->timestamp = ltt_event_time(event);
- }
-}
-
-
-void lttv_process_traceset_seek_time(LttvTracesetContext *self, LttTime start)
-{
- guint i, nb_trace;
-
- LttvTraceContext *tc;
-
- nb_trace = lttv_traceset_number(self->ts);
- for(i = 0 ; i < nb_trace ; i++) {
- tc = self->traces[i];
- lttv_process_trace_seek_time(tc, start);
- }
-}
-
-
-static LttField *
-find_field(LttEventType *et, const char *field)
-{
- LttType *t;
-
- LttField *f;
-
- guint i, nb;
-
- char *name;
-
- if(field == NULL) return NULL;
-
- f = ltt_eventtype_field(et);
- t = ltt_eventtype_type(et);
- g_assert(ltt_type_class(t) == LTT_STRUCT);
- nb = ltt_type_member_number(t);
- for(i = 0 ; i < nb ; i++) {
- ltt_type_member_type(t, i, &name);
- if(strcmp(name, field) == 0) break;
- }
- g_assert(i < nb);
- return ltt_field_member(f, i);
-}
-
-
-void
-lttv_trace_find_hook(LttTrace *t, char *facility, char *event_type,
- char *field1, char *field2, char *field3, LttvHook h, LttvTraceHook *th)
-{
- LttFacility *f;
-
- LttEventType *et;
-
- guint nb, pos, i;
-
- char *name;
-
- nb = ltt_trace_facility_find(t, facility, &pos);
- if(nb < 1) g_error("No %s facility", facility);
- f = ltt_trace_facility_get(t, pos);
- et = ltt_facility_eventtype_get_by_name(f, event_type);
- if(et == NULL) g_error("Event %s does not exist", event_type);
-
- th->h = h;
- th->id = ltt_eventtype_id(et);
- th->f1 = find_field(et, field1);
- th->f2 = find_field(et, field2);
- th->f3 = find_field(et, field3);
-}
-
-
+++ /dev/null
-/* This file is part of the Linux Trace Toolkit viewer
- * Copyright (C) 2003-2004 Michel Dagenais
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License Version 2 as
- * published by the Free Software Foundation;
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA.
- */
-
-
-#include <lttv/lttv.h>
-#include <lttv/module.h>
-#include <lttv/state.h>
-#include <ltt/facility.h>
-#include <ltt/trace.h>
-#include <ltt/event.h>
-#include <ltt/type.h>
-#include <stdio.h>
-
-LttvExecutionMode
- LTTV_STATE_MODE_UNKNOWN,
- LTTV_STATE_USER_MODE,
- LTTV_STATE_SYSCALL,
- LTTV_STATE_TRAP,
- LTTV_STATE_IRQ;
-
-LttvExecutionSubmode
- LTTV_STATE_SUBMODE_UNKNOWN,
- LTTV_STATE_SUBMODE_NONE;
-
-LttvProcessStatus
- LTTV_STATE_UNNAMED,
- LTTV_STATE_WAIT_FORK,
- LTTV_STATE_WAIT_CPU,
- LTTV_STATE_EXIT,
- LTTV_STATE_WAIT,
- LTTV_STATE_RUN;
-
-static GQuark
- LTTV_STATE_TRACEFILES,
- LTTV_STATE_PROCESSES,
- LTTV_STATE_PROCESS,
- LTTV_STATE_EVENT,
- LTTV_STATE_SAVED_STATES,
- LTTV_STATE_SAVED_STATES_TIME,
- LTTV_STATE_TIME,
- LTTV_STATE_HOOKS,
- LTTV_STATE_NAME_TABLES,
- LTTV_STATE_TRACE_STATE_USE_COUNT;
-
-
-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_save(LttvTraceState *self, LttvAttribute *container)
-{
- LTTV_TRACE_STATE_GET_CLASS(self)->state_save(self, container);
-}
-
-
-void lttv_state_restore(LttvTraceState *self, LttvAttribute *container)
-{
- LTTV_TRACE_STATE_GET_CLASS(self)->state_restore(self, container);
-}
-
-
-void lttv_state__state_saved_free(LttvTraceState *self,
- LttvAttribute *container)
-{
- LTTV_TRACE_STATE_GET_CLASS(self)->state_saved_free(self, container);
-}
-
-
-guint process_hash(gconstpointer key)
-{
- return ((LttvProcessState *)key)->pid;
-}
-
-
-gboolean process_equal(gconstpointer a, gconstpointer b)
-{
- LttvProcessState *process_a, *process_b;
-
- process_a = (LttvProcessState *)a;
- process_b = (LttvProcessState *)b;
-
- if(process_a->pid != process_b->pid) return FALSE;
- if(process_a->pid == 0 &&
- process_a->last_cpu != process_b->last_cpu) return FALSE;
- return TRUE;
-}
-
-
-static void
-restore_init_state(LttvTraceState *self)
-{
- guint i, nb_tracefile;
-
- LttvTracefileState *tfcs;
-
- LttTime null_time = {0,0};
-
- if(self->processes != NULL) lttv_state_free_process_table(self->processes);
- self->processes = g_hash_table_new(process_hash, process_equal);
- self->nb_event = 0;
-
- nb_tracefile = ltt_trace_control_tracefile_number(self->parent.t) +
- ltt_trace_per_cpu_tracefile_number(self->parent.t);
-
- for(i = 0 ; i < nb_tracefile ; i++) {
- tfcs = LTTV_TRACEFILE_STATE(self->parent.tracefiles[i]);
- tfcs->parent.timestamp = null_time;
- tfcs->saved_position = 0;
- tfcs->process = lttv_state_create_process(tfcs, NULL,0);
- tfcs->process->state->s = LTTV_STATE_RUN;
- tfcs->process->last_cpu = tfcs->cpu_name;
- }
-}
-
-static LttTime time_zero = {0,0};
-
-static void
-init(LttvTracesetState *self, LttvTraceset *ts)
-{
- guint i, j, nb_trace, nb_tracefile;
-
- LttvTraceContext *tc;
-
- LttvTraceState *tcs;
-
- LttvTracefileState *tfcs;
-
- LttvAttributeValue v;
-
- LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE))->
- init((LttvTracesetContext *)self, ts);
-
- nb_trace = lttv_traceset_number(ts);
- for(i = 0 ; i < nb_trace ; i++) {
- tc = self->parent.traces[i];
- tcs = (LttvTraceState *)tc;
- tcs->save_interval = 50000;
- lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_TRACE_STATE_USE_COUNT,
- LTTV_UINT, &v);
- (*v.v_uint)++;
-
- 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);
-
- for(j = 0 ; j < nb_tracefile ; j++) {
- tfcs = LTTV_TRACEFILE_STATE(tc->tracefiles[j]);
- tfcs->cpu_name= g_quark_from_string(ltt_tracefile_name(tfcs->parent.tf));
- }
- tcs->processes = NULL;
- restore_init_state(tcs);
- }
-}
-
-
-static void
-fini(LttvTracesetState *self)
-{
- guint i, j, nb_trace;
-
- LttvTraceState *tcs;
-
- 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;
- }
- LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE))->
- fini((LttvTracesetContext *)self);
-}
-
-
-static LttvTracesetContext *
-new_traceset_context(LttvTracesetContext *self)
-{
- return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATE_TYPE, NULL));
-}
-
-
-static LttvTraceContext *
-new_trace_context(LttvTracesetContext *self)
-{
- return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATE_TYPE, NULL));
-}
-
-
-static LttvTracefileContext *
-new_tracefile_context(LttvTracesetContext *self)
-{
- return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATE_TYPE, NULL));
-}
-
-
-/* Write the process state of the trace */
-
-static void write_process_state(gpointer key, gpointer value,
- gpointer user_data)
-{
- LttvProcessState *process;
-
- LttvExecutionState *es;
-
- FILE *fp = (FILE *)user_data;
-
- guint i;
-
- process = (LttvProcessState *)value;
- fprintf(fp,
-" <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));
-
- for(i = 0 ; i < process->execution_stack->len; i++) {
- es = &g_array_index(process->execution_stack, LttvExecutionState, i);
- fprintf(fp, " <ES MODE=\"%s\" SUBMODE=\"%s\" ENTRY_S=%lu ENTRY_NS=%lu",
- g_quark_to_string(es->t), g_quark_to_string(es->n),
- es->entry.tv_sec, es->entry.tv_nsec);
- fprintf(fp, " CHANGE_S=%lu CHANGE_NS=%lu STATUS=\"%s\"/>\n",
- es->change.tv_sec, es->change.tv_nsec, g_quark_to_string(es->s));
- }
- fprintf(fp, " </PROCESS>\n");
-}
-
-
-void lttv_state_write(LttvTraceState *self, LttTime t, FILE *fp)
-{
- guint i, nb_tracefile, nb_block, nb_event;
-
- LttvTracefileState *tfcs;
-
- LttTracefile *tf;
-
- LttEventPosition *ep;
-
- ep = ltt_event_position_new();
-
- fprintf(fp,"<PROCESS_STATE TIME_S=%lu TIME_NS=%lu>\n", t.tv_sec, t.tv_nsec);
-
- g_hash_table_foreach(self->processes, write_process_state, fp);
-
- nb_tracefile = ltt_trace_control_tracefile_number(self->parent.t) +
- ltt_trace_per_cpu_tracefile_number(self->parent.t);
-
- for(i = 0 ; i < nb_tracefile ; i++) {
- tfcs = (LttvTracefileState *)self->parent.tracefiles[i];
- fprintf(fp, " <TRACEFILE PID=%u TIMESTAMP_S=%lu TIMESTAMP_NS=%lu",
- tfcs->process->pid, tfcs->parent.timestamp.tv_sec,
- tfcs->parent.timestamp.tv_nsec);
- if(tfcs->parent.e == NULL) fprintf(fp,"/>\n");
- else {
- ltt_event_position(tfcs->parent.e, ep);
- ltt_event_position_get(ep, &nb_block, &nb_event, &tf);
- fprintf(fp, " BLOCK=%u EVENT=%u/>\n", nb_block, nb_event);
- }
- }
- g_free(ep);
- fprintf(fp,"</PROCESS_STATE>");
-}
-
-
-/* Copy each process from an existing hash table to a new one */
-
-static void copy_process_state(gpointer key, gpointer value,gpointer user_data)
-{
- LttvProcessState *process, *new_process;
-
- GHashTable *new_processes = (GHashTable *)user_data;
-
- guint i;
-
- process = (LttvProcessState *)value;
- new_process = g_new(LttvProcessState, 1);
- *new_process = *process;
- new_process->execution_stack = g_array_new(FALSE, FALSE,
- sizeof(LttvExecutionState));
- g_array_set_size(new_process->execution_stack,process->execution_stack->len);
- for(i = 0 ; i < process->execution_stack->len; i++) {
- g_array_index(new_process->execution_stack, LttvExecutionState, i) =
- g_array_index(process->execution_stack, LttvExecutionState, i);
- }
- new_process->state = &g_array_index(new_process->execution_stack,
- LttvExecutionState, new_process->execution_stack->len - 1);
- g_hash_table_insert(new_processes, new_process, new_process);
-}
-
-
-static GHashTable *lttv_state_copy_process_table(GHashTable *processes)
-{
- GHashTable *new_processes = g_hash_table_new(process_hash, process_equal);
-
- g_hash_table_foreach(processes, copy_process_state, new_processes);
- return new_processes;
-}
-
-
-/* The saved state for each trace contains a member "processes", which
- stores a copy of the process table, and a member "tracefiles" with
- one entry per tracefile. Each tracefile has a "process" member pointing
- to the current process and a "position" member storing the tracefile
- position (needed to seek to the current "next" event. */
-
-static void state_save(LttvTraceState *self, LttvAttribute *container)
-{
- guint i, nb_tracefile;
-
- LttvTracefileState *tfcs;
-
- LttvAttribute *tracefiles_tree, *tracefile_tree;
-
- LttvAttributeType type;
-
- LttvAttributeValue value;
-
- LttvAttributeName name;
-
- LttEventPosition *ep;
-
- tracefiles_tree = lttv_attribute_find_subdir(container,
- LTTV_STATE_TRACEFILES);
-
- value = lttv_attribute_add(container, LTTV_STATE_PROCESSES,
- LTTV_POINTER);
- *(value.v_pointer) = lttv_state_copy_process_table(self->processes);
-
- nb_tracefile = ltt_trace_control_tracefile_number(self->parent.t) +
- ltt_trace_per_cpu_tracefile_number(self->parent.t);
-
- for(i = 0 ; i < nb_tracefile ; i++) {
- tfcs = (LttvTracefileState *)self->parent.tracefiles[i];
- tracefile_tree = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
- value = lttv_attribute_add(tracefiles_tree, i,
- LTTV_GOBJECT);
- *(value.v_gobject) = (GObject *)tracefile_tree;
- value = lttv_attribute_add(tracefile_tree, LTTV_STATE_PROCESS,
- LTTV_UINT);
- *(value.v_uint) = tfcs->process->pid;
- value = lttv_attribute_add(tracefile_tree, LTTV_STATE_EVENT,
- LTTV_POINTER);
- if(tfcs->parent.e == NULL) *(value.v_pointer) = NULL;
- else {
- ep = ltt_event_position_new();
- ltt_event_position(tfcs->parent.e, ep);
- *(value.v_pointer) = ep;
-
- guint nb_block, nb_event;
- LttTracefile *tf;
- ltt_event_position_get(ep, &nb_block, &nb_event, &tf);
- g_debug("Block %u event %u time %lu.%lu", nb_block, nb_event,
- tfcs->parent.timestamp.tv_sec, tfcs->parent.timestamp.tv_nsec);
- }
- }
-}
-
-
-static void state_restore(LttvTraceState *self, LttvAttribute *container)
-{
- guint i, nb_tracefile, pid;
-
- LttvTracefileState *tfcs;
-
- LttvAttribute *tracefiles_tree, *tracefile_tree;
-
- LttvAttributeType type;
-
- LttvAttributeValue value;
-
- LttvAttributeName name;
-
- LttEventPosition *ep;
-
- tracefiles_tree = lttv_attribute_find_subdir(container,
- LTTV_STATE_TRACEFILES);
-
- type = lttv_attribute_get_by_name(container, LTTV_STATE_PROCESSES,
- &value);
- g_assert(type == LTTV_POINTER);
- lttv_state_free_process_table(self->processes);
- self->processes = lttv_state_copy_process_table(*(value.v_pointer));
-
- nb_tracefile = ltt_trace_control_tracefile_number(self->parent.t) +
- ltt_trace_per_cpu_tracefile_number(self->parent.t);
-
- for(i = 0 ; i < nb_tracefile ; i++) {
- tfcs = (LttvTracefileState *)self->parent.tracefiles[i];
- type = lttv_attribute_get(tracefiles_tree, i, &name, &value);
- g_assert(type == LTTV_GOBJECT);
- tracefile_tree = *((LttvAttribute **)(value.v_gobject));
-
- type = lttv_attribute_get_by_name(tracefile_tree, LTTV_STATE_PROCESS,
- &value);
- g_assert(type == LTTV_UINT);
- pid = *(value.v_uint);
- tfcs->process = lttv_state_find_process_or_create(tfcs, pid);
-
- type = lttv_attribute_get_by_name(tracefile_tree, LTTV_STATE_EVENT,
- &value);
- g_assert(type == LTTV_POINTER);
- if(*(value.v_pointer) == NULL) tfcs->parent.e = NULL;
- else {
- ep = *(value.v_pointer);
- ltt_tracefile_seek_position(tfcs->parent.tf, ep);
- tfcs->parent.e = ltt_tracefile_read(tfcs->parent.tf);
- tfcs->parent.timestamp = ltt_event_time(tfcs->parent.e);
- }
- }
-}
-
-
-static void state_saved_free(LttvTraceState *self, LttvAttribute *container)
-{
- guint i, nb_tracefile;
-
- LttvTracefileState *tfcs;
-
- LttvAttribute *tracefiles_tree, *tracefile_tree;
-
- LttvAttributeType type;
-
- LttvAttributeValue value;
-
- LttvAttributeName name;
-
- LttEventPosition *ep;
-
- tracefiles_tree = lttv_attribute_find_subdir(container,
- LTTV_STATE_TRACEFILES);
- lttv_attribute_remove_by_name(container, LTTV_STATE_TRACEFILES);
-
- type = lttv_attribute_get_by_name(container, LTTV_STATE_PROCESSES,
- &value);
- g_assert(type == LTTV_POINTER);
- lttv_state_free_process_table(*(value.v_pointer));
- *(value.v_pointer) = NULL;
- lttv_attribute_remove_by_name(container, LTTV_STATE_PROCESSES);
-
- nb_tracefile = ltt_trace_control_tracefile_number(self->parent.t) +
- ltt_trace_per_cpu_tracefile_number(self->parent.t);
-
- for(i = 0 ; i < nb_tracefile ; i++) {
- tfcs = (LttvTracefileState *)self->parent.tracefiles[i];
- type = lttv_attribute_get(tracefiles_tree, i, &name, &value);
- g_assert(type == LTTV_GOBJECT);
- tracefile_tree = *((LttvAttribute **)(value.v_gobject));
-
- type = lttv_attribute_get_by_name(tracefile_tree, LTTV_STATE_EVENT,
- &value);
- g_assert(type == LTTV_POINTER);
- if(*(value.v_pointer) != NULL) g_free(*(value.v_pointer));
- }
- lttv_attribute_recursive_free(tracefiles_tree);
-}
-
-
-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
-create_name_tables(LttvTraceState *tcs)
-{
- int i, nb;
-
- char *f_name, *e_name;
-
- LttvTraceHook h;
-
- LttEventType *et;
-
- LttType *t;
-
- 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);
- 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);
- name_tables->eventtype_names[i] = g_quark_from_string(fe_name->str);
- }
-
- lttv_trace_find_hook(tcs->parent.t, "core", "syscall_entry",
- "syscall_id", NULL, NULL, NULL, &h);
- t = ltt_field_type(h.f1);
- nb = ltt_type_element_number(t);
-
- /* CHECK syscalls should be an emun but currently are not!
- name_tables->syscall_names = g_new(GQuark, nb);
-
- for(i = 0 ; i < nb ; i++) {
- name_tables->syscall_names[i] = g_quark_from_string(
- ltt_enum_string_get(t, i));
- }
- */
-
- name_tables->syscall_names = g_new(GQuark, 256);
- for(i = 0 ; i < 256 ; i++) {
- g_string_printf(fe_name, "syscall %d", i);
- name_tables->syscall_names[i] = g_quark_from_string(fe_name->str);
- }
-
- lttv_trace_find_hook(tcs->parent.t, "core", "trap_entry",
- "trap_id", NULL, NULL, NULL, &h);
- t = ltt_field_type(h.f1);
- nb = ltt_type_element_number(t);
-
- /*
- name_tables->trap_names = g_new(GQuark, nb);
- for(i = 0 ; i < nb ; i++) {
- name_tables->trap_names[i] = g_quark_from_string(
- ltt_enum_string_get(t, i));
- }
- */
-
- name_tables->trap_names = g_new(GQuark, 256);
- for(i = 0 ; i < 256 ; i++) {
- g_string_printf(fe_name, "trap %d", i);
- name_tables->trap_names[i] = g_quark_from_string(fe_name->str);
- }
-
- lttv_trace_find_hook(tcs->parent.t, "core", "irq_entry",
- "irq_id", NULL, NULL, NULL, &h);
- t = ltt_field_type(h.f1);
- nb = ltt_type_element_number(t);
-
- /*
- name_tables->irq_names = g_new(GQuark, nb);
- for(i = 0 ; i < nb ; i++) {
- name_tables->irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i));
- }
- */
-
- name_tables->irq_names = g_new(GQuark, 256);
- for(i = 0 ; i < 256 ; i++) {
- g_string_printf(fe_name, "irq %d", i);
- 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)
-{
- 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);
-}
-
-
-static void push_state(LttvTracefileState *tfs, LttvExecutionMode t,
- guint state_id)
-{
- LttvExecutionState *es;
-
- LttvProcessState *process = tfs->process;
-
- guint depth = process->execution_stack->len;
-
- g_array_set_size(process->execution_stack, depth + 1);
- es = &g_array_index(process->execution_stack, LttvExecutionState, depth);
- es->t = t;
- es->n = state_id;
- es->entry = es->change = tfs->parent.timestamp;
- es->s = process->state->s;
- process->state = es;
-}
-
-
-static void pop_state(LttvTracefileState *tfs, LttvExecutionMode t)
-{
- LttvProcessState *process = tfs->process;
-
- guint depth = process->execution_stack->len;
-
- if(process->state->t != t){
- g_info("Different execution mode type (%d.%09d): ignore it\n",
- tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec);
- g_info("process state has %s when pop_int is %s\n",
- g_quark_to_string(process->state->t),
- g_quark_to_string(t));
- g_info("{ %u, %u, %s, %s }\n",
- process->pid,
- process->ppid,
- g_quark_to_string(process->name),
- g_quark_to_string(process->state->s));
- return;
- }
-
- 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_set_size(process->execution_stack, depth - 1);
- process->state = &g_array_index(process->execution_stack, LttvExecutionState,
- depth - 2);
- process->state->change = tfs->parent.timestamp;
-}
-
-
-LttvProcessState *
-lttv_state_create_process(LttvTracefileState *tfs, LttvProcessState *parent,
- guint pid)
-{
- LttvProcessState *process = g_new(LttvProcessState, 1);
-
- LttvExecutionState *es;
-
- LttvTraceContext *tc;
-
- LttvTraceState *tcs;
-
- char buffer[128];
-
- 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) {
- process->ppid = parent->pid;
- process->name = parent->name;
- process->creation_time = tfs->parent.timestamp;
- }
-
- /* No parent. This process exists but we are missing all information about
- its creation. The birth time is set to zero but we remember the time of
- insertion */
-
- else {
- process->ppid = 0;
- process->name = LTTV_STATE_UNNAMED;
- process->creation_time = ltt_time_zero;
- }
-
- process->insertion_time = tfs->parent.timestamp;
- sprintf(buffer,"%d-%lu.%lu",pid, process->creation_time.tv_sec,
- process->creation_time.tv_nsec);
- process->pid_time = g_quark_from_string(buffer);
- process->last_cpu = tfs->cpu_name;
- process->execution_stack = g_array_new(FALSE, FALSE,
- sizeof(LttvExecutionState));
- g_array_set_size(process->execution_stack, 1);
- es = process->state = &g_array_index(process->execution_stack,
- LttvExecutionState, 0);
- es->t = LTTV_STATE_USER_MODE;
- es->n = LTTV_STATE_SUBMODE_NONE;
- es->entry = tfs->parent.timestamp;
- es->change = tfs->parent.timestamp;
- es->s = LTTV_STATE_WAIT_FORK;
-
- return process;
-}
-
-
-LttvProcessState *
-lttv_state_find_process_from_trace(LttvTraceState *ts, GQuark cpu, guint pid)
-{
- LttvProcessState key;
- LttvProcessState *process;
-
- key.pid = pid;
- key.last_cpu = cpu;
- process = g_hash_table_lookup(ts->processes, &key);
- return process;
-}
-
-
-LttvProcessState *lttv_state_find_process(LttvTracefileState *tfs,
- guint pid)
-{
- LttvTraceState *ts =(LttvTraceState *)tfs->parent.t_context;
- return lttv_state_find_process_from_trace(ts, tfs->cpu_name, pid);
-}
-
-
-LttvProcessState *
-lttv_state_find_process_or_create(LttvTracefileState *tfs, guint pid)
-{
- LttvProcessState *process = lttv_state_find_process(tfs, pid);
-
- if(process == NULL) process = lttv_state_create_process(tfs, NULL, pid);
- return process;
-}
-
-
-static void exit_process(LttvTracefileState *tfs, LttvProcessState *process)
-{
- LttvTraceState *ts = LTTV_TRACE_STATE(tfs->parent.t_context);
- LttvProcessState key;
-
- key.pid = process->pid;
- key.last_cpu = process->last_cpu;
- g_hash_table_remove(ts->processes, &key);
- g_array_free(process->execution_stack, TRUE);
- g_free(process);
-}
-
-
-static void free_process_state(gpointer key, gpointer value,gpointer user_data)
-{
- g_array_free(((LttvProcessState *)value)->execution_stack, TRUE);
- g_free(value);
-}
-
-
-static void lttv_state_free_process_table(GHashTable *processes)
-{
- g_hash_table_foreach(processes, free_process_state, NULL);
- g_hash_table_destroy(processes);
-}
-
-
-static gboolean syscall_entry(void *hook_data, void *call_data)
-{
- LttField *f = ((LttvTraceHook *)hook_data)->f1;
-
- LttvTracefileState *s = (LttvTracefileState *)call_data;
-
- LttvExecutionSubmode submode;
-
- submode = ((LttvTraceState *)(s->parent.t_context))->syscall_names[
- ltt_event_get_unsigned(s->parent.e, f)];
- push_state(s, LTTV_STATE_SYSCALL, submode);
- return FALSE;
-}
-
-
-static gboolean syscall_exit(void *hook_data, void *call_data)
-{
- LttvTracefileState *s = (LttvTracefileState *)call_data;
-
- pop_state(s, LTTV_STATE_SYSCALL);
- return FALSE;
-}
-
-
-static gboolean trap_entry(void *hook_data, void *call_data)
-{
- LttField *f = ((LttvTraceHook *)hook_data)->f1;
-
- LttvTracefileState *s = (LttvTracefileState *)call_data;
-
- LttvExecutionSubmode submode;
-
- submode = ((LttvTraceState *)(s->parent.t_context))->trap_names[
- ltt_event_get_unsigned(s->parent.e, f)];
- push_state(s, LTTV_STATE_TRAP, submode);
- return FALSE;
-}
-
-
-static gboolean trap_exit(void *hook_data, void *call_data)
-{
- LttvTracefileState *s = (LttvTracefileState *)call_data;
-
- pop_state(s, LTTV_STATE_TRAP);
- return FALSE;
-}
-
-
-static gboolean irq_entry(void *hook_data, void *call_data)
-{
- LttField *f = ((LttvTraceHook *)hook_data)->f1;
-
- LttvTracefileState *s = (LttvTracefileState *)call_data;
-
- LttvExecutionSubmode submode;
-
- submode = ((LttvTraceState *)(s->parent.t_context))->irq_names[
- ltt_event_get_unsigned(s->parent.e, f)];
-
- /* Do something with the info about being in user or system mode when int? */
- push_state(s, LTTV_STATE_IRQ, submode);
- return FALSE;
-}
-
-
-static gboolean irq_exit(void *hook_data, void *call_data)
-{
- LttvTracefileState *s = (LttvTracefileState *)call_data;
-
- pop_state(s, LTTV_STATE_IRQ);
- return FALSE;
-}
-
-
-static gboolean schedchange(void *hook_data, void *call_data)
-{
- LttvTraceHook *h = (LttvTraceHook *)hook_data;
-
- LttvTracefileState *s = (LttvTracefileState *)call_data;
-
- guint pid_in, pid_out, state_out;
-
- pid_in = ltt_event_get_unsigned(s->parent.e, h->f1);
- pid_out = ltt_event_get_unsigned(s->parent.e, h->f2);
- state_out = ltt_event_get_unsigned(s->parent.e, h->f3);
-
- 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;
-
- s->process->state->change = s->parent.timestamp;
- }
- s->process = lttv_state_find_process_or_create(s, pid_in);
- s->process->state->s = LTTV_STATE_RUN;
- s->process->last_cpu = s->cpu_name;
- s->process->state->change = s->parent.timestamp;
- return FALSE;
-}
-
-
-static gboolean process_fork(void *hook_data, void *call_data)
-{
- LttField *f = ((LttvTraceHook *)hook_data)->f1;
-
- LttvTracefileState *s = (LttvTracefileState *)call_data;
-
- guint child_pid;
-
- child_pid = ltt_event_get_unsigned(s->parent.e, f);
- lttv_state_create_process(s, s->process, child_pid);
- return FALSE;
-}
-
-
-static gboolean process_exit(void *hook_data, void *call_data)
-{
- LttvTracefileState *s = (LttvTracefileState *)call_data;
-
- if(s->process != NULL) {
- s->process->state->s = LTTV_STATE_EXIT;
- }
- return FALSE;
-}
-
-
-void lttv_state_add_event_hooks(LttvTracesetState *self)
-{
- LttvTraceset *traceset = self->parent.ts;
-
- guint i, j, k, nb_trace, nb_tracefile;
-
- LttvTraceState *ts;
-
- LttvTracefileState *tfs;
-
- GArray *hooks;
-
- LttvTraceHook hook;
-
- LttvAttributeValue val;
-
- nb_trace = lttv_traceset_number(traceset);
- for(i = 0 ; i < nb_trace ; i++) {
- ts = (LttvTraceState *)self->parent.traces[i];
-
- /* Find the eventtype id for the following events and register the
- associated by id hooks. */
-
- hooks = g_array_new(FALSE, FALSE, sizeof(LttvTraceHook));
- g_array_set_size(hooks, 9);
-
- lttv_trace_find_hook(ts->parent.t, "core","syscall_entry","syscall_id",
- NULL, NULL, syscall_entry, &g_array_index(hooks, LttvTraceHook, 0));
-
- lttv_trace_find_hook(ts->parent.t, "core", "syscall_exit", NULL, NULL,
- NULL, syscall_exit, &g_array_index(hooks, LttvTraceHook, 1));
-
- lttv_trace_find_hook(ts->parent.t, "core", "trap_entry", "trap_id",
- NULL, NULL, trap_entry, &g_array_index(hooks, LttvTraceHook, 2));
-
- lttv_trace_find_hook(ts->parent.t, "core", "trap_exit", NULL, NULL, NULL,
- trap_exit, &g_array_index(hooks, LttvTraceHook, 3));
-
- lttv_trace_find_hook(ts->parent.t, "core", "irq_entry", "irq_id", NULL,
- NULL, irq_entry, &g_array_index(hooks, LttvTraceHook, 4));
-
- lttv_trace_find_hook(ts->parent.t, "core", "irq_exit", NULL, NULL, NULL,
- irq_exit, &g_array_index(hooks, LttvTraceHook, 5));
-
- lttv_trace_find_hook(ts->parent.t, "core", "schedchange", "in", "out",
- "out_state", schedchange, &g_array_index(hooks, LttvTraceHook, 6));
-
- lttv_trace_find_hook(ts->parent.t, "core", "process_fork", "child_pid",
- NULL, NULL, process_fork, &g_array_index(hooks, LttvTraceHook, 7));
-
- lttv_trace_find_hook(ts->parent.t, "core", "process_exit", NULL, NULL,
- NULL, process_exit, &g_array_index(hooks, LttvTraceHook, 8));
-
- /* Add these hooks to each before_event_by_id hooks list */
-
- nb_tracefile = ltt_trace_control_tracefile_number(ts->parent.t) +
- ltt_trace_per_cpu_tracefile_number(ts->parent.t);
-
- for(j = 0 ; j < nb_tracefile ; j++) {
- tfs = LTTV_TRACEFILE_STATE(ts->parent.tracefiles[j]);
-
- for(k = 0 ; k < hooks->len ; k++) {
- hook = g_array_index(hooks, LttvTraceHook, k);
- lttv_hooks_add(lttv_hooks_by_id_find(tfs->parent.after_event_by_id,
- hook.id), hook.h, &g_array_index(hooks, LttvTraceHook, k));
- }
- }
- lttv_attribute_find(self->parent.a, LTTV_STATE_HOOKS, LTTV_POINTER, &val);
- *(val.v_pointer) = hooks;
- }
-}
-
-
-void lttv_state_remove_event_hooks(LttvTracesetState *self)
-{
- LttvTraceset *traceset = self->parent.ts;
-
- guint i, j, k, nb_trace, nb_tracefile;
-
- LttvTraceState *ts;
-
- LttvTracefileState *tfs;
-
- GArray *hooks;
-
- LttvTraceHook hook;
-
- LttvAttributeValue val;
-
- nb_trace = lttv_traceset_number(traceset);
- for(i = 0 ; i < nb_trace ; i++) {
- ts = LTTV_TRACE_STATE(self->parent.traces[i]);
- lttv_attribute_find(self->parent.a, LTTV_STATE_HOOKS, LTTV_POINTER, &val);
- hooks = *(val.v_pointer);
-
- /* Add these hooks to each before_event_by_id hooks list */
-
- nb_tracefile = ltt_trace_control_tracefile_number(ts->parent.t) +
- ltt_trace_per_cpu_tracefile_number(ts->parent.t);
-
- for(j = 0 ; j < nb_tracefile ; j++) {
- tfs = LTTV_TRACEFILE_STATE(ts->parent.tracefiles[j]);
-
- for(k = 0 ; k < hooks->len ; k++) {
- hook = g_array_index(hooks, LttvTraceHook, k);
- lttv_hooks_remove_data(
- lttv_hooks_by_id_find(tfs->parent.after_event_by_id,
- hook.id), hook.h, &g_array_index(hooks, LttvTraceHook, k));
- }
- }
- g_array_free(hooks, TRUE);
- }
-}
-
-
-static gboolean block_start(void *hook_data, void *call_data)
-{
- LttvTracefileState *self = (LttvTracefileState *)call_data;
-
- LttvTracefileState *tfcs;
-
- LttvTraceState *tcs = (LttvTraceState *)(self->parent.t_context);
-
- LttEventPosition *ep;
-
- guint i, nb_block, nb_event, nb_tracefile;
-
- LttTracefile *tf;
-
- LttvAttribute *saved_states_tree, *saved_state_tree;
-
- LttvAttributeValue value;
-
- ep = ltt_event_position_new();
- nb_tracefile = ltt_trace_control_tracefile_number(tcs->parent.t) +
- ltt_trace_per_cpu_tracefile_number(tcs->parent.t);
-
- /* Count the number of events added since the last block end in any
- tracefile. */
-
- for(i = 0 ; i < nb_tracefile ; i++) {
- tfcs = (LttvTracefileState *)tcs->parent.tracefiles[i];
- ltt_event_position(tfcs->parent.e, ep);
- ltt_event_position_get(ep, &nb_block, &nb_event, &tf);
- tcs->nb_event += nb_event - tfcs->saved_position;
- tfcs->saved_position = nb_event;
- }
- g_free(ep);
-
- if(tcs->nb_event >= tcs->save_interval) {
- saved_states_tree = lttv_attribute_find_subdir(tcs->parent.t_a,
- LTTV_STATE_SAVED_STATES);
- saved_state_tree = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
- value = lttv_attribute_add(saved_states_tree,
- lttv_attribute_get_number(saved_states_tree), LTTV_GOBJECT);
- *(value.v_gobject) = (GObject *)saved_state_tree;
- value = lttv_attribute_add(saved_state_tree, LTTV_STATE_TIME, LTTV_TIME);
- *(value.v_time) = self->parent.timestamp;
- lttv_state_save(tcs, saved_state_tree);
- tcs->nb_event = 0;
- g_debug("Saving state at time %lu.%lu", self->parent.timestamp.tv_sec,
- self->parent.timestamp.tv_nsec);
- }
- *(tcs->max_time_state_recomputed_in_seek) = self->parent.timestamp;
- return FALSE;
-}
-
-
-static gboolean block_end(void *hook_data, void *call_data)
-{
- LttvTracefileState *self = (LttvTracefileState *)call_data;
-
- LttvTraceState *tcs = (LttvTraceState *)(self->parent.t_context);
-
- LttTracefile *tf;
-
- LttEventPosition *ep;
-
- guint nb_block, nb_event;
-
- ep = ltt_event_position_new();
- ltt_event_position(self->parent.e, ep);
- ltt_event_position_get(ep, &nb_block, &nb_event, &tf);
- tcs->nb_event += nb_event - self->saved_position + 1;
- self->saved_position = 0;
- *(tcs->max_time_state_recomputed_in_seek) = self->parent.timestamp;
- g_free(ep);
-}
-
-
-void lttv_state_save_add_event_hooks(LttvTracesetState *self)
-{
- LttvTraceset *traceset = self->parent.ts;
-
- guint i, j, k, nb_trace, nb_tracefile;
-
- LttvTraceState *ts;
-
- LttvTracefileState *tfs;
-
- LttvTraceHook hook_start, hook_end;
-
- nb_trace = lttv_traceset_number(traceset);
- for(i = 0 ; i < nb_trace ; i++) {
- ts = (LttvTraceState *)self->parent.traces[i];
- lttv_trace_find_hook(ts->parent.t, "core","block_start",NULL,
- NULL, NULL, block_start, &hook_start);
- lttv_trace_find_hook(ts->parent.t, "core","block_end",NULL,
- NULL, NULL, block_end, &hook_end);
-
- nb_tracefile = ltt_trace_control_tracefile_number(ts->parent.t) +
- ltt_trace_per_cpu_tracefile_number(ts->parent.t);
-
- for(j = 0 ; j < nb_tracefile ; j++) {
- tfs = LTTV_TRACEFILE_STATE(ts->parent.tracefiles[j]);
- lttv_hooks_add(lttv_hooks_by_id_find(tfs->parent.after_event_by_id,
- hook_start.id), hook_start.h, NULL);
- lttv_hooks_add(lttv_hooks_by_id_find(tfs->parent.after_event_by_id,
- hook_end.id), hook_end.h, NULL);
- }
- }
-}
-
-
-void lttv_state_save_remove_event_hooks(LttvTracesetState *self)
-{
- LttvTraceset *traceset = self->parent.ts;
-
- guint i, j, k, nb_trace, nb_tracefile;
-
- LttvTraceState *ts;
-
- LttvTracefileState *tfs;
-
- LttvTraceHook hook_start, hook_end;
-
- nb_trace = lttv_traceset_number(traceset);
- for(i = 0 ; i < nb_trace ; i++) {
- ts = LTTV_TRACE_STATE(self->parent.traces[i]);
- lttv_trace_find_hook(ts->parent.t, "core","block_start",NULL,
- NULL, NULL, block_start, &hook_start);
-
- lttv_trace_find_hook(ts->parent.t, "core","block_end",NULL,
- NULL, NULL, block_end, &hook_end);
-
- nb_tracefile = ltt_trace_control_tracefile_number(ts->parent.t) +
- ltt_trace_per_cpu_tracefile_number(ts->parent.t);
-
- for(j = 0 ; j < nb_tracefile ; j++) {
- tfs = LTTV_TRACEFILE_STATE(ts->parent.tracefiles[j]);
- lttv_hooks_remove_data(lttv_hooks_by_id_find(
- tfs->parent.after_event_by_id, hook_start.id), hook_start.h, NULL);
- lttv_hooks_remove_data(lttv_hooks_by_id_find(
- tfs->parent.after_event_by_id, hook_end.id), hook_end.h, NULL);
- }
- }
-}
-
-
-void lttv_state_traceset_seek_time_closest(LttvTracesetState *self, LttTime t)
-{
- LttvTraceset *traceset = self->parent.ts;
-
- guint i, j, nb_trace, nb_saved_state;
-
- int min_pos, mid_pos, max_pos;
-
- LttvTraceState *tcs;
-
- LttvAttributeValue value;
-
- LttvAttributeType type;
-
- LttvAttributeName name;
-
- LttvAttribute *saved_states_tree, *saved_state_tree, *closest_tree;
-
- nb_trace = lttv_traceset_number(traceset);
- for(i = 0 ; i < nb_trace ; i++) {
- tcs = (LttvTraceState *)self->parent.traces[i];
-
- if(ltt_time_compare(t, *(tcs->max_time_state_recomputed_in_seek)) < 0) {
- saved_states_tree = lttv_attribute_find_subdir(tcs->parent.t_a,
- LTTV_STATE_SAVED_STATES);
- min_pos = -1;
-
- if(saved_states_tree) {
- max_pos = lttv_attribute_get_number(saved_states_tree) - 1;
- mid_pos = max_pos / 2;
- while(min_pos < max_pos) {
- type = lttv_attribute_get(saved_states_tree, mid_pos, &name, &value);
- g_assert(type == LTTV_GOBJECT);
- saved_state_tree = *((LttvAttribute **)(value.v_gobject));
- type = lttv_attribute_get_by_name(saved_state_tree, LTTV_STATE_TIME,
- &value);
- g_assert(type == LTTV_TIME);
- if(ltt_time_compare(*(value.v_time), t) < 0) {
- min_pos = mid_pos;
- closest_tree = saved_state_tree;
- }
- else max_pos = mid_pos - 1;
-
- mid_pos = (min_pos + max_pos + 1) / 2;
- }
- }
-
- /* restore the closest earlier saved state */
- 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 {
- restore_init_state(tcs);
- lttv_process_trace_seek_time(&(tcs->parent), ltt_time_zero);
- }
- }
- /* We want to seek quickly without restoring/updating the state */
- else {
- restore_init_state(tcs);
- lttv_process_trace_seek_time(&(tcs->parent), t);
- }
- }
-}
-
-
-static void
-traceset_state_instance_init (GTypeInstance *instance, gpointer g_class)
-{
-}
-
-
-static void
-traceset_state_finalize (LttvTracesetState *self)
-{
- G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE))->
- finalize(G_OBJECT(self));
-}
-
-
-static void
-traceset_state_class_init (LttvTracesetContextClass *klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
-
- gobject_class->finalize = (void (*)(GObject *self)) traceset_state_finalize;
- klass->init = (void (*)(LttvTracesetContext *self, LttvTraceset *ts))init;
- klass->fini = (void (*)(LttvTracesetContext *self))fini;
- klass->new_traceset_context = new_traceset_context;
- klass->new_trace_context = new_trace_context;
- klass->new_tracefile_context = new_tracefile_context;
-}
-
-
-GType
-lttv_traceset_state_get_type(void)
-{
- static GType type = 0;
- if (type == 0) {
- static const GTypeInfo info = {
- sizeof (LttvTracesetStateClass),
- NULL, /* base_init */
- NULL, /* base_finalize */
- (GClassInitFunc) traceset_state_class_init, /* class_init */
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (LttvTracesetState),
- 0, /* n_preallocs */
- (GInstanceInitFunc) traceset_state_instance_init /* instance_init */
- };
-
- type = g_type_register_static (LTTV_TRACESET_CONTEXT_TYPE, "LttvTracesetStateType",
- &info, 0);
- }
- return type;
-}
-
-
-static void
-trace_state_instance_init (GTypeInstance *instance, gpointer g_class)
-{
-}
-
-
-static void
-trace_state_finalize (LttvTraceState *self)
-{
- G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_CONTEXT_TYPE))->
- finalize(G_OBJECT(self));
-}
-
-
-static void
-trace_state_class_init (LttvTraceStateClass *klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
-
- gobject_class->finalize = (void (*)(GObject *self)) trace_state_finalize;
- klass->state_save = state_save;
- klass->state_restore = state_restore;
- klass->state_saved_free = state_saved_free;
-}
-
-
-GType
-lttv_trace_state_get_type(void)
-{
- static GType type = 0;
- if (type == 0) {
- static const GTypeInfo info = {
- sizeof (LttvTraceStateClass),
- NULL, /* base_init */
- NULL, /* base_finalize */
- (GClassInitFunc) trace_state_class_init, /* class_init */
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (LttvTraceState),
- 0, /* n_preallocs */
- (GInstanceInitFunc) trace_state_instance_init /* instance_init */
- };
-
- type = g_type_register_static (LTTV_TRACE_CONTEXT_TYPE,
- "LttvTraceStateType", &info, 0);
- }
- return type;
-}
-
-
-static void
-tracefile_state_instance_init (GTypeInstance *instance, gpointer g_class)
-{
-}
-
-
-static void
-tracefile_state_finalize (LttvTracefileState *self)
-{
- G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_CONTEXT_TYPE))->
- finalize(G_OBJECT(self));
-}
-
-
-static void
-tracefile_state_class_init (LttvTracefileStateClass *klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
-
- gobject_class->finalize = (void (*)(GObject *self)) tracefile_state_finalize;
-}
-
-
-GType
-lttv_tracefile_state_get_type(void)
-{
- static GType type = 0;
- if (type == 0) {
- static const GTypeInfo info = {
- sizeof (LttvTracefileStateClass),
- NULL, /* base_init */
- NULL, /* base_finalize */
- (GClassInitFunc) tracefile_state_class_init, /* class_init */
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (LttvTracefileState),
- 0, /* n_preallocs */
- (GInstanceInitFunc) tracefile_state_instance_init /* instance_init */
- };
-
- type = g_type_register_static (LTTV_TRACEFILE_CONTEXT_TYPE,
- "LttvTracefileStateType", &info, 0);
- }
- return type;
-}
-
-
-static void module_init()
-{
- LTTV_STATE_UNNAMED = g_quark_from_string("unnamed");
- LTTV_STATE_MODE_UNKNOWN = g_quark_from_string("unknown execution mode");
- LTTV_STATE_USER_MODE = g_quark_from_string("user mode");
- LTTV_STATE_WAIT_FORK = g_quark_from_string("wait fork");
- LTTV_STATE_SYSCALL = g_quark_from_string("system call");
- LTTV_STATE_TRAP = g_quark_from_string("trap");
- LTTV_STATE_IRQ = g_quark_from_string("irq");
- LTTV_STATE_SUBMODE_UNKNOWN = g_quark_from_string("unknown submode");
- LTTV_STATE_SUBMODE_NONE = g_quark_from_string("(no submode)");
- LTTV_STATE_WAIT_CPU = g_quark_from_string("wait for cpu");
- LTTV_STATE_EXIT = g_quark_from_string("exiting");
- LTTV_STATE_WAIT = g_quark_from_string("wait for I/O");
- LTTV_STATE_RUN = g_quark_from_string("running");
- LTTV_STATE_TRACEFILES = g_quark_from_string("tracefiles");
- LTTV_STATE_PROCESSES = g_quark_from_string("processes");
- LTTV_STATE_PROCESS = g_quark_from_string("process");
- LTTV_STATE_EVENT = g_quark_from_string("event");
- LTTV_STATE_SAVED_STATES = g_quark_from_string("saved states");
- 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()
-{
-}
-
-
-LTTV_MODULE("state", "State computation", \
- "Update the system state, possibly saving it at intervals", \
- module_init, module_destroy)
-
-
-
+++ /dev/null
-/* This file is part of the Linux Trace Toolkit viewer
- * Copyright (C) 2003-2004 Michel Dagenais
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License Version 2 as
- * published by the Free Software Foundation;
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA.
- */
-
-
-#include <stdio.h>
-#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>
-
-#define BUF_SIZE 256
-
-GQuark
- LTTV_STATS_PROCESS_UNKNOWN,
- LTTV_STATS_PROCESSES,
- LTTV_STATS_CPU,
- LTTV_STATS_MODE_TYPES,
- LTTV_STATS_MODES,
- LTTV_STATS_SUBMODES,
- LTTV_STATS_EVENT_TYPES,
- LTTV_STATS_CPU_TIME,
- LTTV_STATS_ELAPSED_TIME,
- LTTV_STATS_EVENTS,
- LTTV_STATS_EVENTS_COUNT,
- LTTV_STATS_USE_COUNT,
- LTTV_STATS,
- LTTV_STATS_TRACEFILES,
- LTTV_STATS_SUMMED;
-
-static GQuark
- LTTV_STATS_BEFORE_HOOKS,
- LTTV_STATS_AFTER_HOOKS;
-
-static void remove_all_processes(GHashTable *processes);
-
-static void
-find_event_tree(LttvTracefileStats *tfcs, GQuark process, GQuark cpu,
- GQuark mode, GQuark sub_mode, LttvAttribute **events_tree,
- LttvAttribute **event_types_tree);
-
-static void
-init(LttvTracesetStats *self, LttvTraceset *ts)
-{
- guint i, j, nb_trace, nb_tracefile;
-
- LttvTraceContext *tc;
-
- LttvTraceStats *tcs;
-
- LttvTracefileContext *tfc;
-
- LttvTracefileStats *tfcs;
-
- 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 =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 = 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 = 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,
- &tfcs->current_event_types_tree);
- }
- }
-}
-
-
-static void
-fini(LttvTracesetStats *self)
-{
- guint i, j, nb_trace, nb_tracefile;
-
- LttvTraceset *ts;
-
- LttvTraceContext *tc;
-
- LttvTraceStats *tcs;
-
- LttvTracefileContext *tfc;
-
- LttvTracefileStats *tfcs;
-
- LttTime timestamp = {0,0};
-
- 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_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]);
- tfcs->stats = NULL;
- tfcs->current_events_tree = NULL;
- tfcs->current_event_types_tree = NULL;
- }
- }
- LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE))->
- fini((LttvTracesetContext *)self);
-}
-
-
-static LttvTracesetContext *
-new_traceset_context(LttvTracesetContext *self)
-{
- return LTTV_TRACESET_CONTEXT(g_object_new(LTTV_TRACESET_STATS_TYPE, NULL));
-}
-
-
-static LttvTraceContext *
-new_trace_context(LttvTracesetContext *self)
-{
- return LTTV_TRACE_CONTEXT(g_object_new(LTTV_TRACE_STATS_TYPE, NULL));
-}
-
-
-static LttvTracefileContext *
-new_tracefile_context(LttvTracesetContext *self)
-{
- return LTTV_TRACEFILE_CONTEXT(g_object_new(LTTV_TRACEFILE_STATS_TYPE, NULL));
-}
-
-
-static void
-traceset_stats_instance_init (GTypeInstance *instance, gpointer g_class)
-{
-}
-
-
-static void
-traceset_stats_finalize (LttvTracesetStats *self)
-{
- G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE))->
- finalize(G_OBJECT(self));
-}
-
-
-static void
-traceset_stats_class_init (LttvTracesetContextClass *klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
-
- gobject_class->finalize = (void (*)(GObject *self)) traceset_stats_finalize;
- klass->init = (void (*)(LttvTracesetContext *self, LttvTraceset *ts))init;
- klass->fini = (void (*)(LttvTracesetContext *self))fini;
- klass->new_traceset_context = new_traceset_context;
- klass->new_trace_context = new_trace_context;
- klass->new_tracefile_context = new_tracefile_context;
-}
-
-
-GType
-lttv_traceset_stats_get_type(void)
-{
- static GType type = 0;
- if (type == 0) {
- static const GTypeInfo info = {
- sizeof (LttvTracesetStatsClass),
- NULL, /* base_init */
- NULL, /* base_finalize */
- (GClassInitFunc) traceset_stats_class_init, /* class_init */
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (LttvTracesetStats),
- 0, /* n_preallocs */
- (GInstanceInitFunc) traceset_stats_instance_init /* instance_init */
- };
-
- type = g_type_register_static (LTTV_TRACESET_STATE_TYPE, "LttvTracesetStatsType",
- &info, 0);
- }
- return type;
-}
-
-
-static void
-trace_stats_instance_init (GTypeInstance *instance, gpointer g_class)
-{
-}
-
-
-static void
-trace_stats_finalize (LttvTraceStats *self)
-{
- G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_STATE_TYPE))->
- finalize(G_OBJECT(self));
-}
-
-
-static void
-trace_stats_class_init (LttvTraceContextClass *klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
-
- gobject_class->finalize = (void (*)(GObject *self)) trace_stats_finalize;
-}
-
-
-GType
-lttv_trace_stats_get_type(void)
-{
- static GType type = 0;
- if (type == 0) {
- static const GTypeInfo info = {
- sizeof (LttvTraceStatsClass),
- NULL, /* base_init */
- NULL, /* base_finalize */
- (GClassInitFunc) trace_stats_class_init, /* class_init */
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (LttvTraceStats),
- 0, /* n_preallocs */
- (GInstanceInitFunc) trace_stats_instance_init /* instance_init */
- };
-
- type = g_type_register_static (LTTV_TRACE_STATE_TYPE,
- "LttvTraceStatsType", &info, 0);
- }
- return type;
-}
-
-
-static void
-tracefile_stats_instance_init (GTypeInstance *instance, gpointer g_class)
-{
-}
-
-
-static void
-tracefile_stats_finalize (LttvTracefileStats *self)
-{
- G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_STATE_TYPE))->
- finalize(G_OBJECT(self));
-}
-
-
-static void
-tracefile_stats_class_init (LttvTracefileStatsClass *klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
-
- gobject_class->finalize = (void (*)(GObject *self)) tracefile_stats_finalize;
-}
-
-
-GType
-lttv_tracefile_stats_get_type(void)
-{
- static GType type = 0;
- if (type == 0) {
- static const GTypeInfo info = {
- sizeof (LttvTracefileStatsClass),
- NULL, /* base_init */
- NULL, /* base_finalize */
- (GClassInitFunc) tracefile_stats_class_init, /* class_init */
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (LttvTracefileStats),
- 0, /* n_preallocs */
- (GInstanceInitFunc) tracefile_stats_instance_init /* instance_init */
- };
-
- type = g_type_register_static (LTTV_TRACEFILE_STATE_TYPE,
- "LttvTracefileStatsType", &info, 0);
- }
- return type;
-}
-
-
-static void
-find_event_tree(LttvTracefileStats *tfcs, GQuark process, GQuark cpu,
- GQuark mode, GQuark sub_mode, LttvAttribute **events_tree,
- LttvAttribute **event_types_tree)
-{
- LttvAttribute *a;
-
- LttvTraceStats *tcs = LTTV_TRACE_STATS(tfcs->parent.parent.t_context);
- a = lttv_attribute_find_subdir(tcs->stats, LTTV_STATS_PROCESSES);
- a = lttv_attribute_find_subdir(a, tfcs->parent.process->pid_time);
- a = lttv_attribute_find_subdir(a, LTTV_STATS_CPU);
- a = lttv_attribute_find_subdir(a, tfcs->parent.cpu_name);
- a = lttv_attribute_find_subdir(a, LTTV_STATS_MODE_TYPES);
- a = lttv_attribute_find_subdir(a, tfcs->parent.process->state->t);
- a = lttv_attribute_find_subdir(a, LTTV_STATS_SUBMODES);
- a = lttv_attribute_find_subdir(a, tfcs->parent.process->state->n);
- *events_tree = a;
- a = lttv_attribute_find_subdir(a, LTTV_STATS_EVENT_TYPES);
- *event_types_tree = a;
-}
-
-
-static void update_event_tree(LttvTracefileStats *tfcs)
-{
- LttvExecutionState *es = tfcs->parent.process->state;
-
- find_event_tree(tfcs, tfcs->parent.process->pid_time, tfcs->parent.cpu_name,
- es->t, es->n, &(tfcs->current_events_tree),
- &(tfcs->current_event_types_tree));
-}
-
-
-static void mode_change(LttvTracefileStats *tfcs)
-{
- LttvAttributeValue cpu_time;
-
- LttTime delta;
-
- lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CPU_TIME,
- LTTV_TIME, &cpu_time);
- delta = ltt_time_sub(tfcs->parent.parent.timestamp,
- tfcs->parent.process->state->change);
- *(cpu_time.v_time) = ltt_time_add(*(cpu_time.v_time), delta);
-}
-
-
-static void mode_end(LttvTracefileStats *tfcs)
-{
- LttvAttributeValue elapsed_time, cpu_time;
-
- LttTime delta;
-
- lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_ELAPSED_TIME,
- LTTV_TIME, &elapsed_time);
- delta = ltt_time_sub(tfcs->parent.parent.timestamp,
- tfcs->parent.process->state->entry);
- *(elapsed_time.v_time) = ltt_time_add(*(elapsed_time.v_time), delta);
-
- lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CPU_TIME,
- LTTV_TIME, &cpu_time);
- delta = ltt_time_sub(tfcs->parent.parent.timestamp,
- tfcs->parent.process->state->change);
- *(cpu_time.v_time) = ltt_time_add(*(cpu_time.v_time), delta);
-}
-
-
-static gboolean before_syscall_entry(void *hook_data, void *call_data)
-{
- mode_change((LttvTracefileStats *)call_data);
- return FALSE;
-}
-
-
-static gboolean after_syscall_entry(void *hook_data, void *call_data)
-{
- update_event_tree((LttvTracefileStats *)call_data);
- return FALSE;
-}
-
-
-gboolean before_syscall_exit(void *hook_data, void *call_data)
-{
- mode_end((LttvTracefileStats *)call_data);
- return FALSE;
-}
-
-
-static gboolean after_syscall_exit(void *hook_data, void *call_data)
-{
- update_event_tree((LttvTracefileStats *)call_data);
- return FALSE;
-}
-
-
-gboolean before_trap_entry(void *hook_data, void *call_data)
-{
- mode_change((LttvTracefileStats *)call_data);
- return FALSE;
-}
-
-
-static gboolean after_trap_entry(void *hook_data, void *call_data)
-{
- update_event_tree((LttvTracefileStats *)call_data);
- return FALSE;
-}
-
-
-gboolean before_trap_exit(void *hook_data, void *call_data)
-{
- mode_end((LttvTracefileStats *)call_data);
- return FALSE;
-}
-
-
-gboolean after_trap_exit(void *hook_data, void *call_data)
-{
- update_event_tree((LttvTracefileStats *)call_data);
- return FALSE;
-}
-
-
-gboolean before_irq_entry(void *hook_data, void *call_data)
-{
- mode_change((LttvTracefileStats *)call_data);
- return FALSE;
-}
-
-
-gboolean after_irq_entry(void *hook_data, void *call_data)
-{
- update_event_tree((LttvTracefileStats *)call_data);
- return FALSE;
-}
-
-
-gboolean before_irq_exit(void *hook_data, void *call_data)
-{
- mode_end((LttvTracefileStats *)call_data);
- return FALSE;
-}
-
-
-gboolean after_irq_exit(void *hook_data, void *call_data)
-{
- update_event_tree((LttvTracefileStats *)call_data);
- return FALSE;
-}
-
-
-gboolean before_schedchange(void *hook_data, void *call_data)
-{
- LttvTraceHook *h = (LttvTraceHook *)hook_data;
-
- LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
-
- guint pid_in, pid_out, state_out;
-
- LttvProcessState *process;
-
- pid_in = ltt_event_get_unsigned(tfcs->parent.parent.e, h->f1);
- pid_out = ltt_event_get_unsigned(tfcs->parent.parent.e, h->f2);
- state_out = ltt_event_get_unsigned(tfcs->parent.parent.e, h->f3);
-
- /* compute the time for the process to schedule out */
-
- mode_change(tfcs);
-
- /* get the information for the process scheduled in */
-
- process = lttv_state_find_process_or_create(&(tfcs->parent), pid_in);
-
- find_event_tree(tfcs, process->pid_time, tfcs->parent.cpu_name,
- process->state->t, process->state->n, &(tfcs->current_events_tree),
- &(tfcs->current_event_types_tree));
-
- /* compute the time waiting for the process to schedule in */
-
- mode_change(tfcs);
- return FALSE;
-}
-
-
-gboolean process_fork(void *hook_data, void *call_data)
-{
- /* nothing to do for now */
- return FALSE;
-}
-
-
-gboolean process_exit(void *hook_data, void *call_data)
-{
- /* We should probably exit all modes here or we could do that at
- schedule out. */
- return FALSE;
-}
-
-
-gboolean every_event(void *hook_data, void *call_data)
-{
- LttvTracefileStats *tfcs = (LttvTracefileStats *)call_data;
-
- LttvAttributeValue v;
-
- /* The current branch corresponds to the tracefile/process/interrupt state.
- Statistics are added within it, to count the number of events of this
- type occuring in this context. A quark has been pre-allocated for each
- event type and is used as name. */
-
- lttv_attribute_find(tfcs->current_event_types_tree,
- ((LttvTraceState *)(tfcs->parent.parent.t_context))->
- eventtype_names[ltt_event_eventtype_id(tfcs->parent.parent.e)],
- LTTV_UINT, &v);
- (*(v.v_uint))++;
- return FALSE;
-}
-
-
-void
-lttv_stats_sum_trace(LttvTraceStats *self)
-{
- LttvTraceStats *tcs;
-
- LttvAttributeType type;
-
- LttvAttributeValue value;
-
- LttvAttributeName name;
-
- unsigned sum;
-
- 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;
-
- 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);
-
- for(l = 0 ; l < nb_submode ; l++) {
- type = lttv_attribute_get(submodes_tree, l, &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(m = 0 ; m < nb_event_type ; m++) {
- type = lttv_attribute_get(event_types_tree, m, &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);
- }
- lttv_attribute_recursive_add(cpu_events_tree, mode_events_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);
- }
-}
-
-
-lttv_stats_add_event_hooks(LttvTracesetStats *self)
-{
- LttvTraceset *traceset = self->parent.parent.ts;
-
- guint i, j, k, nb_trace, nb_tracefile;
-
- LttFacility *f;
-
- LttEventType *et;
-
- LttvTraceStats *ts;
-
- LttvTracefileStats *tfs;
-
- void *hook_data;
-
- GArray *hooks, *before_hooks, *after_hooks;
-
- LttvTraceHook hook;
-
- LttvAttributeValue val;
-
- nb_trace = lttv_traceset_number(traceset);
- for(i = 0 ; i < nb_trace ; i++) {
- ts = (LttvTraceStats *)self->parent.parent.traces[i];
-
- /* Find the eventtype id for the following events and register the
- associated by id hooks. */
-
- hooks = g_array_new(FALSE, FALSE, sizeof(LttvTraceHook));
- g_array_set_size(hooks, 7);
-
- lttv_trace_find_hook(ts->parent.parent.t, "core","syscall_entry",
- "syscall_id", NULL, NULL, before_syscall_entry,
- &g_array_index(hooks, LttvTraceHook, 0));
-
- lttv_trace_find_hook(ts->parent.parent.t, "core", "syscall_exit", NULL,
- NULL, NULL, before_syscall_exit,
- &g_array_index(hooks, LttvTraceHook, 1));
-
- lttv_trace_find_hook(ts->parent.parent.t, "core", "trap_entry", "trap_id",
- NULL, NULL, before_trap_entry,
- &g_array_index(hooks, LttvTraceHook, 2));
-
- lttv_trace_find_hook(ts->parent.parent.t, "core", "trap_exit", NULL, NULL,
- NULL, before_trap_exit, &g_array_index(hooks, LttvTraceHook, 3));
-
- lttv_trace_find_hook(ts->parent.parent.t, "core", "irq_entry", "irq_id",
- NULL, NULL, before_irq_entry, &g_array_index(hooks, LttvTraceHook, 4));
-
- lttv_trace_find_hook(ts->parent.parent.t, "core", "irq_exit", NULL, NULL,
- NULL, before_irq_exit, &g_array_index(hooks, LttvTraceHook, 5));
-
- lttv_trace_find_hook(ts->parent.parent.t, "core", "schedchange", "in",
- "out", "out_state", before_schedchange,
- &g_array_index(hooks, LttvTraceHook, 6));
-
- before_hooks = hooks;
-
- hooks = g_array_new(FALSE, FALSE, sizeof(LttvTraceHook));
- g_array_set_size(hooks, 8);
-
- lttv_trace_find_hook(ts->parent.parent.t, "core","syscall_entry",
- "syscall_id", NULL, NULL, after_syscall_entry,
- &g_array_index(hooks, LttvTraceHook, 0));
-
- lttv_trace_find_hook(ts->parent.parent.t, "core", "syscall_exit", NULL,
- NULL, NULL, after_syscall_exit,
- &g_array_index(hooks, LttvTraceHook, 1));
-
- lttv_trace_find_hook(ts->parent.parent.t, "core", "trap_entry", "trap_id",
- NULL, NULL, after_trap_entry, &g_array_index(hooks, LttvTraceHook, 2));
-
- lttv_trace_find_hook(ts->parent.parent.t, "core", "trap_exit", NULL, NULL,
- NULL, after_trap_exit, &g_array_index(hooks, LttvTraceHook, 3));
-
- lttv_trace_find_hook(ts->parent.parent.t, "core", "irq_entry", "irq_id",
- NULL, NULL, after_irq_entry, &g_array_index(hooks, LttvTraceHook, 4));
-
- lttv_trace_find_hook(ts->parent.parent.t, "core", "irq_exit", NULL, NULL,
- NULL, after_irq_exit, &g_array_index(hooks, LttvTraceHook, 5));
-
- lttv_trace_find_hook(ts->parent.parent.t, "core", "process_fork",
- "child_pid", NULL, NULL, process_fork,
- &g_array_index(hooks, LttvTraceHook, 6));
-
- lttv_trace_find_hook(ts->parent.parent.t, "core", "process_exit", NULL,
- NULL, NULL, process_exit, &g_array_index(hooks, LttvTraceHook, 7));
-
- after_hooks = hooks;
-
- /* Add these hooks to each before_event_by_id hooks list */
-
- nb_tracefile = ltt_trace_control_tracefile_number(ts->parent.parent.t) +
- ltt_trace_per_cpu_tracefile_number(ts->parent.parent.t);
-
- for(j = 0 ; j < nb_tracefile ; j++) {
- tfs = LTTV_TRACEFILE_STATS(ts->parent.parent.tracefiles[j]);
- lttv_hooks_add(tfs->parent.parent.after_event, every_event, NULL);
-
- for(k = 0 ; k < before_hooks->len ; k++) {
- hook = g_array_index(before_hooks, LttvTraceHook, k);
- lttv_hooks_add(lttv_hooks_by_id_find(
- tfs->parent.parent.before_event_by_id,
- hook.id), hook.h, &g_array_index(before_hooks, LttvTraceHook, k));
- }
- for(k = 0 ; k < after_hooks->len ; k++) {
- hook = g_array_index(after_hooks, LttvTraceHook, k);
- lttv_hooks_add(lttv_hooks_by_id_find(
- tfs->parent.parent.after_event_by_id,
- hook.id), hook.h, &g_array_index(after_hooks, LttvTraceHook, k));
- }
- }
- lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS,
- LTTV_POINTER, &val);
- *(val.v_pointer) = before_hooks;
- lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS,
- LTTV_POINTER, &val);
- *(val.v_pointer) = after_hooks;
- }
-}
-
-
-lttv_stats_remove_event_hooks(LttvTracesetStats *self)
-{
- LttvTraceset *traceset = self->parent.parent.ts;
-
- guint i, j, k, nb_trace, nb_tracefile;
-
- LttvTraceStats *ts;
-
- LttvTracefileStats *tfs;
-
- void *hook_data;
-
- GArray *before_hooks, *after_hooks;
-
- LttvTraceHook hook;
-
- LttvAttributeValue val;
-
- nb_trace = lttv_traceset_number(traceset);
- for(i = 0 ; i < nb_trace ; i++) {
- ts = LTTV_TRACE_STATS(self->parent.parent.traces[i]);
- lttv_attribute_find(self->parent.parent.a, LTTV_STATS_BEFORE_HOOKS,
- LTTV_POINTER, &val);
- before_hooks = *(val.v_pointer);
- lttv_attribute_find(self->parent.parent.a, LTTV_STATS_AFTER_HOOKS,
- LTTV_POINTER, &val);
- after_hooks = *(val.v_pointer);
-
- /* Add these hooks to each before_event_by_id hooks list */
-
- nb_tracefile = ltt_trace_control_tracefile_number(ts->parent.parent.t) +
- ltt_trace_per_cpu_tracefile_number(ts->parent.parent.t);
-
- for(j = 0 ; j < nb_tracefile ; j++) {
- tfs = LTTV_TRACEFILE_STATS(ts->parent.parent.tracefiles[j]);
- lttv_hooks_remove_data(tfs->parent.parent.after_event, every_event,
- NULL);
-
- for(k = 0 ; k < before_hooks->len ; k++) {
- hook = g_array_index(before_hooks, LttvTraceHook, k);
- lttv_hooks_remove_data(
- lttv_hooks_by_id_find(tfs->parent.parent.before_event_by_id,
- hook.id), hook.h, &g_array_index(before_hooks, LttvTraceHook, k));
- }
- for(k = 0 ; k < after_hooks->len ; k++) {
- hook = g_array_index(after_hooks, LttvTraceHook, k);
- lttv_hooks_remove_data(
- lttv_hooks_by_id_find(tfs->parent.parent.after_event_by_id,
- hook.id), hook.h, &g_array_index(after_hooks, LttvTraceHook, k));
- }
- }
- g_debug("lttv_stats_remove_event_hooks()");
- g_array_free(before_hooks, TRUE);
- g_array_free(after_hooks, TRUE);
- }
-}
-
-
-static void module_init()
-{
- LTTV_STATS_PROCESS_UNKNOWN = g_quark_from_string("unknown process");
- LTTV_STATS_PROCESSES = g_quark_from_string("processes");
- LTTV_STATS_CPU = g_quark_from_string("cpu");
- LTTV_STATS_MODE_TYPES = g_quark_from_string("mode_types");
- LTTV_STATS_MODES = g_quark_from_string("modes");
- LTTV_STATS_SUBMODES = g_quark_from_string("submodes");
- LTTV_STATS_EVENT_TYPES = g_quark_from_string("event_types");
- LTTV_STATS_CPU_TIME = g_quark_from_string("cpu time");
- LTTV_STATS_ELAPSED_TIME = g_quark_from_string("elapsed time");
- LTTV_STATS_EVENTS = g_quark_from_string("events");
- 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. */
+++ /dev/null
-/* This file is part of the Linux Trace Toolkit viewer
- * Copyright (C) 2003-2004 Michel Dagenais
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License Version 2 as
- * published by the Free Software Foundation;
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA.
- */
-
-
-#include <lttv/traceset.h>
-#include <stdio.h>
-
-/* A trace is a sequence of events gathered in the same tracing session. The
- events may be stored in several tracefiles in the same directory.
- A trace set is defined when several traces are to be analyzed together,
- possibly to study the interactions between events in the different traces.
-*/
-
-struct _LttvTraceset {
- char * filename;
- GPtrArray *traces;
- LttvAttribute *a;
-};
-
-
-struct _LttvTrace {
- LttTrace *t;
- LttvAttribute *a;
- guint ref_count;
-};
-
-
-LttvTraceset *lttv_traceset_new()
-{
- LttvTraceset *s;
-
- s = g_new(LttvTraceset, 1);
- s->filename = NULL;
- s->traces = g_ptr_array_new();
- s->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
- return s;
-}
-
-char * lttv_traceset_name(LttvTraceset * s)
-{
- return s->filename;
-}
-
-LttvTrace *lttv_trace_new(LttTrace *t)
-{
- LttvTrace *new_trace;
-
- new_trace = g_new(LttvTrace, 1);
- new_trace->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
- new_trace->t = t;
- new_trace->ref_count = 0;
- return new_trace;
-}
-
-
-LttvTraceset *lttv_traceset_copy(LttvTraceset *s_orig)
-{
- int i;
- LttvTraceset *s;
- LttvTrace * trace;
-
- s = g_new(LttvTraceset, 1);
- s->filename = NULL;
- s->traces = g_ptr_array_new();
- for(i=0;i<s_orig->traces->len;i++)
- {
- trace = g_ptr_array_index(s_orig->traces, i);
- trace->ref_count++;
-
- /*CHECK this used ltt_trace_copy while it may not be needed. Need to
- define how traces and tracesets are shared */
- g_ptr_array_add(
- s->traces,
- g_ptr_array_index(s_orig->traces, i));
- }
- s->a = LTTV_ATTRIBUTE(lttv_iattribute_deep_copy(LTTV_IATTRIBUTE(s_orig->a)));
- return s;
-}
-
-
-LttvTraceset *lttv_traceset_load(const gchar *filename)
-{
- LttvTraceset *s = g_new(LttvTraceset,1);
- FILE *tf;
-
- s->filename = g_strdup(filename);
- tf = fopen(filename,"r");
-
- g_critical("NOT IMPLEMENTED : load traceset data from a XML file");
-
- fclose(tf);
- return s;
-}
-
-gint lttv_traceset_save(LttvTraceset *s)
-{
- FILE *tf;
-
- tf = fopen(s->filename, "w");
-
- g_critical("NOT IMPLEMENTED : save traceset data in a XML file");
-
- fclose(tf);
- return 0;
-}
-
-void lttv_traceset_destroy(LttvTraceset *s)
-{
- g_ptr_array_free(s->traces, TRUE);
- g_object_unref(s->a);
- g_free(s);
-}
-
-void lttv_trace_destroy(LttvTrace *t)
-{
- g_object_unref(t->a);
- g_free(t);
-}
-
-
-void lttv_traceset_add(LttvTraceset *s, LttvTrace *t)
-{
- t->ref_count++;
- g_ptr_array_add(s->traces, t);
-}
-
-
-unsigned lttv_traceset_number(LttvTraceset *s)
-{
- return s->traces->len;
-}
-
-
-LttvTrace *lttv_traceset_get(LttvTraceset *s, unsigned i)
-{
- g_assert(s->traces->len > i);
- return ((LttvTrace *)s->traces->pdata[i]);
-}
-
-
-void lttv_traceset_remove(LttvTraceset *s, unsigned i)
-{
- LttvTrace * t;
- g_assert(s->traces->len > i);
- t = (LttvTrace *)s->traces->pdata[i];
- t->ref_count--;
- g_ptr_array_remove_index(s->traces, i);
-}
-
-
-/* A set of attributes is attached to each trace set, trace and tracefile
- to store user defined data as needed. */
-
-LttvAttribute *lttv_traceset_attribute(LttvTraceset *s)
-{
- return s->a;
-}
-
-
-LttvAttribute *lttv_trace_attribute(LttvTrace *t)
-{
- return t->a;
-}
-
-
-LttTrace *lttv_trace(LttvTrace *t)
-{
- return t->t;
-}
-
-guint lttv_trace_get_ref_number(LttvTrace * t)
-{
- return t->ref_count;
-}
#include <gdk/gdk.h>
#include <lttv/lttv.h>
-#include <lttv/processTrace.h>
+#include <lttv/tracecontext.h>
#include <lttv/gtktraceset.h>
#include <lttv/hook.h>
#include <lttv/iattribute.h>
#include <string.h>
-#include <lttv/processTrace.h>
+#include <lttv/tracecontext.h>
#include <lttv/state.h>
#include "drawitem.h"
#include <lttv/module.h>
#include <lttv/hook.h>
#include <lttv/gtktraceset.h>
-#include <lttv/processTrace.h>
+#include <lttv/tracecontext.h>
#include <lttv/state.h>
#include <ltt/ltt.h>
#include <ltt/event.h>
#include <lttv/hook.h>
#include <lttv/option.h>
#include <lttv/module.h>
-#include <lttv/processTrace.h>
+#include <lttv/tracecontext.h>
#include <lttv/state.h>
#include <lttv/stats.h>
#include <lttv/menu.h>
libmainwinapi_la_SOURCES = toolbar.c menu.c gtktraceset.c
#libmainwinapi_la_LDFLAGS = -L${top_srcdir}/lttv/modules/gui/API -lcustomBox
+lttvguiinclude_HEADERS = \
+ common.h\
+ gtkdirsel.h\
+ gtkmultivpaned.h\
+ gtktraceset.h\
+ lttvfilter.h\
+ mainwindow.h\
+ menu.h\
+ toolbar.h
+
EXTRA_DIST =
--- /dev/null
+/* This file is part of the Linux Trace Toolkit viewer
+ * Copyright (C) 2003-2004 Xiangxiu Yang
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+#ifndef COMMON_H
+#define COMMON_H
+
+#include <stdio.h>
+#include <ltt/ltt.h>
+#include <gtk/gtk.h>
+#include <lttv/lttvfilter.h>
+
+#define MAX_NUMBER_EVENT "MAX_NUMBER_EVENT"
+#define TRACESET_TIME_SPAN "TRACESET_TIME_SPAN"
+
+typedef struct _MainWindow MainWindow;
+typedef struct _Tab Tab;
+
+/* constructor of the viewer */
+typedef GtkWidget * (*lttv_constructor)(MainWindow * main_window,
+ LttvTracesetSelector * s, char *key);
+typedef lttv_constructor view_constructor;
+
+typedef struct _TimeWindow {
+ LttTime start_time;
+ LttTime time_width;
+} TimeWindow;
+
+#endif // COMMON_H
--- /dev/null
+/* This file is part of the Linux Trace Toolkit viewer
+ * Copyright (C) 2003-2004 Xiangxiu Yang
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+
+#ifndef __GTK_DIR_SEL_H__
+#define __GTK_DIR_SEL_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkdialog.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_TYPE_DIR_SELECTION (gtk_dir_selection_get_type ())
+#define GTK_DIR_SELECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_DIR_SELECTION, GtkDirSelection))
+#define GTK_DIR_SELECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_DIR_SELECTION, GtkDirSelectionClass))
+#define GTK_IS_DIR_SELECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_DIR_SELECTION))
+#define GTK_IS_DIR_SELECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_DIR_SELECTION))
+#define GTK_DIR_SELECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_DIR_SELECTION, GtkDirSelectionClass))
+
+
+typedef struct _GtkDirSelection GtkDirSelection;
+typedef struct _GtkDirSelectionClass GtkDirSelectionClass;
+
+struct _GtkDirSelection
+{
+ GtkDialog parent_instance;
+
+ GtkWidget *dir_list;
+ GtkWidget *file_list;
+ GtkWidget *selection_entry;
+ GtkWidget *selection_text;
+ GtkWidget *main_vbox;
+ GtkWidget *ok_button;
+ GtkWidget *cancel_button;
+ GtkWidget *help_button;
+ GtkWidget *history_pulldown;
+ GtkWidget *history_menu;
+ GList *history_list;
+ GtkWidget *fileop_dialog;
+ GtkWidget *fileop_entry;
+ gchar *fileop_file;
+ gpointer cmpl_state;
+
+ GtkWidget *fileop_c_dir;
+ GtkWidget *fileop_del_file;
+ GtkWidget *fileop_ren_file;
+
+ GtkWidget *button_area;
+ GtkWidget *action_area;
+
+ GPtrArray *selected_names;
+ gchar *last_selected;
+};
+
+struct _GtkDirSelectionClass
+{
+ GtkDialogClass parent_class;
+
+ /* Padding for future expansion */
+ void (*_gtk_reserved1) (void);
+ void (*_gtk_reserved2) (void);
+ void (*_gtk_reserved3) (void);
+ void (*_gtk_reserved4) (void);
+};
+
+
+GType gtk_dir_selection_get_type (void) G_GNUC_CONST;
+GtkWidget* gtk_dir_selection_new (const gchar *title);
+void gtk_dir_selection_set_filename (GtkDirSelection *filesel,
+ const gchar *filename);
+/* This function returns the selected filename in the C runtime's
+ * multibyte string encoding, which may or may not be the same as that
+ * used by GDK (UTF-8). To convert to UTF-8, call g_filename_to_utf8().
+ * The returned string points to a statically allocated buffer and
+ * should be copied away.
+ */
+G_CONST_RETURN gchar* gtk_dir_selection_get_filename (GtkDirSelection *filesel);
+
+void gtk_dir_selection_complete (GtkDirSelection *filesel,
+ const gchar *pattern);
+void gtk_dir_selection_show_fileop_buttons (GtkDirSelection *filesel);
+void gtk_dir_selection_hide_fileop_buttons (GtkDirSelection *filesel);
+
+gchar** gtk_dir_selection_get_selections (GtkDirSelection *filesel);
+const gchar * gtk_dir_selection_get_dir (GtkDirSelection *filesel);
+void gtk_dir_selection_set_select_multiple (GtkDirSelection *filesel,
+ gboolean select_multiple);
+gboolean gtk_dir_selection_get_select_multiple (GtkDirSelection *filesel);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_DIR_SEL_H__ */
--- /dev/null
+
+/* This file is part of the Linux Trace Toolkit viewer
+ * Copyright (C) 2003-2004 Xiangxiu Yang
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+#ifndef __GTK_MULTI_VPANED_H__
+#define __GTK_MULTI_VPANED_H__
+
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gdk/gdk.h>
+#include <gtk/gtkcontainer.h>
+#include <lttv/common.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_TYPE_MULTI_VPANED (gtk_multi_vpaned_get_type ())
+#define GTK_MULTI_VPANED(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_MULTI_VPANED, GtkMultiVPaned))
+#define GTK_MULTI_VPANED_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_MULTI_VPANED, GtkMultiVPanedClass))
+#define GTK_IS_MULTI_VPANED(obj ) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_MULTI_VPANED))
+#define GTK_IS_MULTI_VPANED_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_MULTI_VPANED))
+#define GTK_MULTI_VPANED_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_MULTI_VPANED, GtkMultiVPanedClass))
+
+
+typedef struct _GtkMultiVPaned GtkMultiVPaned;
+typedef struct _GtkMultiVPanedClass GtkMultiVPanedClass;
+
+struct _GtkMultiVPaned
+{
+ GtkPaned container;
+
+ /*< public >*/
+ GtkPaned * first_pane;
+ GtkPaned * last_pane;
+ GtkPaned * focused_pane;
+ GtkPaned * iter;
+ guint num_children;
+
+ GtkWidget * vbox;
+ // GtkWidget * scrollWindow;
+ // GtkWidget * viewport;
+ GtkWidget * hscrollbar;
+ GtkAdjustment *hadjust;
+ MainWindow * mw;
+};
+
+struct _GtkMultiVPanedClass
+{
+ GtkPanedClass parent_class;
+};
+
+
+GType gtk_multi_vpaned_get_type (void) G_GNUC_CONST;
+GtkWidget* gtk_multi_vpaned_new (void);
+
+void gtk_multi_vpaned_set_focus (GtkWidget * widget, gpointer user_data);
+void gtk_multi_vpaned_widget_add(GtkMultiVPaned * multi_vpaned, GtkWidget * widget1);
+void gtk_multi_vpaned_widget_delete(GtkMultiVPaned * multi_vpaned);
+void gtk_multi_vpaned_widget_move_up(GtkMultiVPaned * multi_vpaned);
+void gtk_multi_vpaned_widget_move_down(GtkMultiVPaned * multi_vpaned);
+void gtk_multi_vpaned_set_adjust(GtkMultiVPaned * multi_vpaned, gboolean first_time);
+void gtk_multi_vpaned_set_data(GtkMultiVPaned * multi_vpaned, char * key, gpointer value);
+gpointer gtk_multi_vpaned_get_data(GtkMultiVPaned * multi_vpaned, char * key);
+GtkWidget * gtk_multi_vpaned_get_widget(GtkMultiVPaned * multi_vpaned);
+GtkWidget * gtk_multi_vpaned_get_first_widget(GtkMultiVPaned * multi_vpaned);
+GtkWidget * gtk_multi_vpaned_get_next_widget(GtkMultiVPaned * multi_vpaned);
+void gtk_multi_vpaned_set_scroll_value(GtkMultiVPaned * multi_vpaned, double value);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_MULTI_VPANED_H__ */
#include <lttv/lttv.h>
#include <lttv/mainwindow.h>
#include <lttv/gtktraceset.h>
-#include <lttv/processTrace.h>
+#include <lttv/tracecontext.h>
#include <lttv/toolbar.h>
#include <lttv/menu.h>
#include <lttv/state.h>
--- /dev/null
+/* This file is part of the Linux Trace Toolkit viewer
+ * Copyright (C) 2003-2004 Xiangxiu Yang
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * 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.
+ *
+ * Main window (gui module) is the place to contain and display viewers.
+ * Viewers (lttv plugins) interacte with main window through this API and
+ * events sent by gtk.
+ * This header file should be included in each graphic module.
+ * This library is used by graphical modules to interact with the
+ * tracesetWindow.
+ *
+ */
+
+#include <gtk/gtk.h>
+#include <ltt/ltt.h>
+#include <lttv/hook.h>
+#include <lttv/common.h>
+#include <lttv/stats.h>
+
+/**
+ * Function to register a view constructor so that main window can generate
+ * a toolbar item for the viewer in order to generate a new instance easily.
+ * It will be called by init function of the module.
+ * @param ButtonPixmap image shown on the toolbar item.
+ * @param tooltip tooltip of the toolbar item.
+ * @param view_constructor constructor of the viewer.
+ */
+
+void toolbar_item_reg(char ** pixmap, char *tooltip, lttv_constructor view_constructor);
+
+
+/**
+ * Function to unregister the viewer's constructor, release the space
+ * occupied by pixmap, tooltip and constructor of the viewer.
+ * It will be called when a module is unloaded.
+ * @param view_constructor constructor of the viewer which is used as
+ * a reference to find out where the pixmap and tooltip are.
+ */
+
+void toolbar_item_unreg(lttv_constructor view_constructor);
+
+
+/**
+ * Function to register a view constructor so that main window can generate
+ * a menu item for the viewer in order to generate a new instance easily.
+ * It will be called by init function of the module.
+ * @param menu_path path of the menu item.
+ * @param menu_text text of the menu item.
+ * @param view_constructor constructor of the viewer.
+ */
+
+void menu_item_reg(char *menu_path, char *menu_text, lttv_constructor view_constructor);
+
+
+/**
+ * Function to unregister the viewer's constructor, release the space
+ * occupied by menu_path, menu_text and constructor of the viewer.
+ * It will be called when a module is unloaded.
+ * @param view_constructor constructor of the viewer which is used as
+ * a reference to find out where the menu_path and menu_text are.
+ */
+
+void menu_item_unreg(lttv_constructor view_constructor);
+
+
+/**
+ * Update the status bar whenever something changed in the viewer.
+ * @param main_win the main window the viewer belongs to.
+ * @param info the message which will be shown in the status bar.
+ */
+
+void update_status(MainWindow *main_win, char *info);
+
+
+/**
+ * Function to get the current time window of the current tab.
+ * It will be called by a viewer's hook function to update the
+ * time window of the viewer and also be called by the constructor
+ * of the viewer.
+ * @param main_win the main window the viewer belongs to.
+ * @param time_interval a pointer where time interval will be stored.
+ */
+
+void get_time_window(MainWindow *main_win, TimeWindow *time_window);
+
+
+/**
+ * Function to set the time interval of the current tab.
+ * It will be called by a viewer's signal handle associated with
+ * the move_slider signal
+ * @param main_win the main window the viewer belongs to.
+ * @param time_interval a pointer where time interval is stored.
+ */
+
+void set_time_window(MainWindow *main_win, TimeWindow *time_window);
+
+/**
+ * Function to get the current time/event of the current tab.
+ * It will be called by a viewer's hook function to update the
+ * current time/event of the viewer.
+ * @param main_win the main window the viewer belongs to.
+ * @param time a pointer where time will be stored.
+ */
+
+void get_current_time(MainWindow *main_win, LttTime *time);
+
+
+/**
+ * Function to set the current time/event of the current tab.
+ * It will be called by a viewer's signal handle associated with
+ * the button-release-event signal
+ * @param main_win the main window the viewer belongs to.
+ * @param time a pointer where time is stored.
+ */
+
+void set_current_time(MainWindow *main_win, LttTime *time);
+
+
+/**
+ * Function to get the traceset from the current tab.
+ * It will be called by the constructor of the viewer and also be
+ * called by a hook funtion of the viewer to update its traceset.
+ * @param main_win the main window the viewer belongs to.
+ * @param traceset a pointer to a traceset.
+ */
+
+//void get_traceset(MainWindow *main_win, Traceset *traceset);
+
+
+/**
+ * Function to get the filter of the current tab.
+ * It will be called by the constructor of the viewer and also be
+ * called by a hook funtion of the viewer to update its filter.
+ * @param main_win, the main window the viewer belongs to.
+ * @param filter, a pointer to a filter.
+ */
+
+//void get_filter(MainWindow *main_win, Filter *filter);
+
+
+/**
+ * Function to register a hook function for a viewer to set/update its
+ * time interval.
+ * It will be called by the constructor of the viewer.
+ * @param hook hook function of the viewer. Takes a TimeInterval* as call_data.
+ * @param hook_data hook data associated with the hook function.
+ * @param main_win the main window the viewer belongs to.
+ */
+
+void reg_update_time_window(LttvHook hook, gpointer hook_data,
+ MainWindow * main_win);
+
+
+/**
+ * Function to unregister a viewer's hook function which is used to
+ * set/update the time interval of the viewer.
+ * It will be called by the destructor of the viewer.
+ * @param hook hook function of the viewer. Takes a TimeInterval as call_data.
+ * @param hook_data hook data associated with the hook function.
+ * @param main_win the main window the viewer belongs to.
+ */
+
+void unreg_update_time_window(LttvHook hook, gpointer hook_data,
+ MainWindow * main_win);
+
+
+/**
+ * Function to register a hook function for a viewer to set/update its
+ * traceset.
+ * It will be called by the constructor of the viewer.
+ * @param hook hook function of the viewer.
+ * @param hook_data hook data associated with the hook function.
+ * @param main_win the main window the viewer belongs to.
+ */
+
+void reg_update_traceset(LttvHook hook, gpointer hook_data,
+ MainWindow * main_win);
+
+
+/**
+ * Function to unregister a viewer's hook function which is used to
+ * set/update the traceset of the viewer.
+ * It will be called by the destructor of the viewer.
+ * @param hook hook function of the viewer.
+ * @param hook_data hook data associated with the hook function.
+ * @param main_win the main window the viewer belongs to.
+ */
+
+void unreg_update_traceset(LttvHook hook, gpointer hook_data,
+ MainWindow * main_win);
+
+
+/**
+ * Function to redraw each viewer belonging to the current tab
+ * @param main_win the main window the viewer belongs to.
+ */
+
+void update_traceset(MainWindow * main_win);
+
+
+/**
+ * Function to register a hook function for a viewer to set/update its
+ * filter.
+ * It will be called by the constructor of the viewer.
+ * @param hook hook function of the viewer.
+ * @param hook_data hook data associated with the hook function.
+ * @param main_win the main window the viewer belongs to.
+ */
+
+void reg_update_filter(LttvHook hook, gpointer hook_data,
+ MainWindow *main_win);
+
+
+/**
+ * Function to unregister a viewer's hook function which is used to
+ * set/update the filter of the viewer.
+ * It will be called by the destructor of the viewer.
+ * @param hook hook function of the viewer.
+ * @param hook_data hook data associated with the hook function.
+ * @param main_win the main window the viewer belongs to.
+ */
+
+void unreg_update_filter(LttvHook hook, gpointer hook_data,
+ MainWindow * main_win);
+
+
+/**
+ * Function to register a hook function for a viewer to set/update its
+ * current time.
+ * It will be called by the constructor of the viewer.
+ * @param hook hook function of the viewer.
+ * @param hook_data hook data associated with the hook function.
+ * @param main_win the main window the viewer belongs to.
+ */
+
+void reg_update_current_time(LttvHook hook, gpointer hook_data,
+ MainWindow *main_win);
+
+
+/**
+ * Function to unregister a viewer's hook function which is used to
+ * set/update the current time of the viewer.
+ * It will be called by the destructor of the viewer.
+ * @param hook hook function of the viewer.
+ * @param hook_data hook data associated with the hook function.
+ * @param main_win the main window the viewer belongs to.
+ */
+
+void unreg_update_current_time(LttvHook hook, gpointer hook_data,
+ MainWindow * main_win);
+
+
+/**
+ * Function to register a hook function for a viewer to show
+ *the content of the viewer.
+ * It will be called by the constructor of the viewer.
+ * @param hook hook function of the viewer.
+ * @param hook_data hook data associated with the hook function.
+ * @param main_win the main window the viewer belongs to.
+ */
+
+void reg_show_viewer(LttvHook hook, gpointer hook_data,
+ MainWindow *main_win);
+
+
+/**
+ * Function to unregister a viewer's hook function which is used to
+ * show the content of the viewer..
+ * It will be called by the destructor of the viewer.
+ * @param hook hook function of the viewer.
+ * @param hook_data hook data associated with the hook function.
+ * @param main_win the main window the viewer belongs to.
+ */
+
+void unreg_show_viewer(LttvHook hook, gpointer hook_data,
+ MainWindow * main_win);
+
+
+/**
+ * Function to show each viewer in the current tab.
+ * It will be called by main window after it called process_traceset
+ * @param main_win the main window the viewer belongs to.
+ */
+
+void show_viewer(MainWindow *main_win);
+
+
+/**
+ * Function to set the focused pane (viewer).
+ * It will be called by a viewer's signal handle associated with
+ * the grab_focus signal
+ * @param main_win the main window the viewer belongs to.
+ * @param paned a pointer to a pane where the viewer is contained.
+ */
+
+void set_focused_pane(MainWindow *main_win, gpointer paned);
+
+
+/**
+ * Function to register a hook function for a viewer to set/update the
+ * dividor of the hpane.
+ * It will be called by the constructor of the viewer.
+ * @param hook hook function of the viewer.
+ * @param hook_data hook data associated with the hook function.
+ * @param main_win the main window the viewer belongs to.
+ */
+
+void reg_update_dividor(LttvHook hook, gpointer hook_data,
+ MainWindow *main_win);
+
+
+/**
+ * Function to unregister a viewer's hook function which is used to
+ * set/update hpane's dividor of the viewer.
+ * It will be called by the destructor of the viewer.
+ * @param hook hook function of the viewer.
+ * @param hook_data hook data associated with the hook function.
+ * @param main_win the main window the viewer belongs to.
+ */
+
+void unreg_update_dividor(LttvHook hook, gpointer hook_data,
+ MainWindow *main_win);
+
+
+/**
+ * Function to set the position of the hpane's dividor (viewer).
+ * It will be called by a viewer's signal handle associated with
+ * the motion_notify_event event/signal
+ * @param main_win the main window the viewer belongs to.
+ * @param position position of the hpane's dividor.
+ */
+
+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.
+ * @param main_win the main window the viewer belongs to.
+ * @param start the start time of the first event to be processed.
+ * @param end the end time of the last event to be processed.
+ */
+
+void process_traceset_api(MainWindow *main_win, LttTime start,
+ LttTime end, unsigned maxNumEvents);
+
+
+/**
+ * Function to add hooks into the context of a traceset,
+ * before reading events from traceset, viewer will call this api to
+ * register hooks
+ * @param main_win the main window the viewer belongs to.
+ * @param LttvHooks hooks to be registered.
+ */
+
+void context_add_hooks_api(MainWindow *main_win ,
+ LttvHooks *before_traceset,
+ LttvHooks *after_traceset,
+ LttvHooks *check_trace,
+ LttvHooks *before_trace,
+ LttvHooks *after_trace,
+ LttvHooks *check_tracefile,
+ LttvHooks *before_tracefile,
+ LttvHooks *after_tracefile,
+ LttvHooks *check_event,
+ LttvHooks *before_event,
+ LttvHooks *after_event);
+
+
+/**
+ * Function to remove hooks from the context of a traceset,
+ * before reading events from traceset, viewer will call this api to
+ * unregister hooks
+ * @param main_win the main window the viewer belongs to.
+ * @param LttvHooks hooks to be registered.
+ */
+
+void context_remove_hooks_api(MainWindow *main_win ,
+ LttvHooks *before_traceset,
+ LttvHooks *after_traceset,
+ LttvHooks *check_trace,
+ LttvHooks *before_trace,
+ LttvHooks *after_trace,
+ LttvHooks *check_tracefile,
+ LttvHooks *before_tracefile,
+ LttvHooks *after_tracefile,
+ LttvHooks *check_event,
+ LttvHooks *before_event,
+ LttvHooks *after_event);
+
+
+/**
+ * Function to get the life span of the traceset
+ * @param main_win the main window the viewer belongs to.
+ * @param start start time of the traceset.
+ * @param end end time of the traceset.
+ */
+
+void get_traceset_time_span(MainWindow *main_win, TimeInterval *time_span);
+
+
+/**
+ * Function to add/remove event hooks for state
+ * @param main_win the main window the viewer belongs to.
+ */
+
+void state_add_event_hooks_api(MainWindow *main_win );
+void state_remove_event_hooks_api(MainWindow *main_win );
+
+
+/**
+ * Function to add/remove event hooks for stats
+ * @param main_win the main window the viewer belongs to.
+ */
+
+void stats_add_event_hooks_api(MainWindow *main_win );
+void stats_remove_event_hooks_api(MainWindow *main_win );
+
+
+/**
+ * Function to get the stats of the traceset
+ * @param main_win the main window the viewer belongs to.
+ */
+
+LttvTracesetStats* get_traceset_stats_api(MainWindow *main_win);
+
+LttvTracesetContext* get_traceset_context(MainWindow *main_win);
--- /dev/null
+/* This file is part of the Linux Trace Toolkit viewer
+ * Copyright (C) 2003-2004 Xiangxiu Yang
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+#ifndef LTTV_FILTER_H
+#define LTTV_FILTER_H
+
+#include <ltt/ltt.h>
+
+
+typedef struct _LttvTracesetSelector LttvTracesetSelector;
+typedef struct _LttvTraceSelector LttvTraceSelector;
+typedef struct _LttvTracefileSelector LttvTracefileSelector;
+typedef struct _LttvEventtypeSelector LttvEventtypeSelector;
+
+
+LttvTracesetSelector *lttv_traceset_selector_new(char * name);
+LttvTraceSelector *lttv_trace_selector_new(LttTrace *t);
+LttvTracefileSelector *lttv_tracefile_selector_new(LttTracefile *t);
+LttvEventtypeSelector *lttv_eventtype_selector_new(LttEventType * et);
+void lttv_traceset_selector_destroy(LttvTracesetSelector *s);
+void lttv_trace_selector_destroy(LttvTraceSelector *t);
+void lttv_tracefile_selector_destroy(LttvTracefileSelector *t);
+void lttv_eventtype_selector_destroy(LttvEventtypeSelector *t);
+
+
+void lttv_traceset_selector_trace_add(LttvTracesetSelector *s,
+ LttvTraceSelector *t);
+unsigned lttv_traceset_selector_trace_number(LttvTracesetSelector *s);
+LttvTraceSelector *lttv_traceset_selector_trace_get(LttvTracesetSelector *s,
+ unsigned i);
+void lttv_traceset_selector_trace_remove(LttvTracesetSelector *s,
+ unsigned i);
+
+
+void lttv_trace_selector_tracefile_add(LttvTraceSelector *s,
+ LttvTracefileSelector *t);
+unsigned lttv_trace_selector_tracefile_number(LttvTraceSelector *s);
+LttvTracefileSelector *lttv_trace_selector_tracefile_get(LttvTraceSelector *s,
+ unsigned i);
+void lttv_trace_selector_tracefile_remove(LttvTraceSelector *s, unsigned i);
+
+void lttv_trace_selector_eventtype_add(LttvTraceSelector *s,
+ LttvEventtypeSelector *et);
+unsigned lttv_trace_selector_eventtype_number(LttvTraceSelector *s);
+LttvEventtypeSelector *lttv_trace_selector_eventtype_get(LttvTraceSelector *s,
+ unsigned i);
+void lttv_trace_selector_eventtype_remove(LttvTraceSelector *s, unsigned i);
+
+
+void lttv_tracefile_selector_eventtype_add(LttvTracefileSelector *s,
+ LttvEventtypeSelector *et);
+unsigned lttv_tracefile_selector_eventtype_number(LttvTracefileSelector *s);
+LttvEventtypeSelector *lttv_tracefile_selector_eventtype_get(LttvTracefileSelector *s,
+ unsigned i);
+void lttv_tracefile_selector_eventtype_remove(LttvTracefileSelector *s, unsigned i);
+
+
+void lttv_trace_selector_set_selected(LttvTraceSelector *s, gboolean g);
+void lttv_tracefile_selector_set_selected(LttvTracefileSelector *s, gboolean g);
+void lttv_eventtype_selector_set_selected(LttvEventtypeSelector *s, gboolean g);
+gboolean lttv_trace_selector_get_selected(LttvTraceSelector *s);
+gboolean lttv_tracefile_selector_get_selected(LttvTracefileSelector *s);
+gboolean lttv_eventtype_selector_get_selected(LttvEventtypeSelector *s);
+char * lttv_traceset_selector_get_name(LttvTracesetSelector *s);
+char * lttv_trace_selector_get_name(LttvTraceSelector *s);
+char * lttv_tracefile_selector_get_name(LttvTracefileSelector *s);
+char * lttv_eventtype_selector_get_name(LttvEventtypeSelector *s);
+
+LttvEventtypeSelector * lttv_eventtype_selector_clone(LttvEventtypeSelector * s);
+void lttv_eventtype_selector_copy(LttvTraceSelector *s, LttvTracefileSelector *d);
+
+
+#endif // LTTV_FILTER_H
+
--- /dev/null
+/* This file is part of the Linux Trace Toolkit viewer
+ * Copyright (C) 2003-2004 Xiangxiu Yang
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+#ifndef _MAIN_WINDOW_
+#define _MAIN_WINDOW_
+
+#include <gtk/gtk.h>
+
+#include <ltt/ltt.h>
+#include <lttv/attribute.h>
+#include <lttv/traceset.h>
+#include <lttv/tracecontext.h>
+
+#include <lttv/common.h>
+#include <lttv/gtkmultivpaned.h>
+#include <lttv/hook.h>
+#include <lttv/stats.h>
+
+typedef struct _TracesetInfo {
+ //FIXME? TracesetContext and stats in same or different variable ?
+ LttvTracesetStats * traceset_context;
+ LttvTraceset * traceset;
+} TracesetInfo ;
+
+
+struct _MainWindow{
+ GtkWidget* mwindow; /* Main Window */
+ int window_width;
+
+ /* Status bar information */
+ // guint MainSBarContextID; /* Context ID of main status bar */
+ // guint BegTimeSBarContextID; /* Context ID of BegTime status bar */
+ // guint EndTimeSBarContextID; /* Context ID of EndTime status bar */
+
+ /* Child windows */
+ //openTracesetWindow* OpenTracesetWindow;/* Window to get prof and proc file*/
+ //viewTimeFrameWindow* ViewTimeFrameWindow;/*Window to select time frame */
+ //gotoEventWindow* GotoEventWindow; /*search for event description*/
+ //openFilterWindow* OpenFilterWindow; /* Open a filter selection window */
+ GtkWidget* help_contents;/* Window to display help contents */
+ GtkWidget* about_box; /* Window about information */
+
+ // lttv_trace_filter * filter; /* trace filter associated with the window */
+
+ /* Attributes for trace reading hooks local to the main window */
+ LttvIAttribute * attributes;
+
+ Tab * tab;
+ Tab * current_tab;
+
+ GHashTable * hash_menu_item;
+ GHashTable * hash_toolbar_item;
+};
+
+
+struct _Tab{
+ GtkWidget * label;
+ GtkMultiVPaned * multi_vpaned;
+
+ // startTime is the left of the visible area. Corresponds to the scrollbar
+ // value.
+ // Time_Width is a zoom dependant value (corresponding to page size)
+ TimeWindow time_window;
+
+ // The current time is the time selected in the visible area by the user,
+ // not the scrollbar value.
+ LttTime current_time;
+ LttvIAttribute * attributes;
+
+ struct _Tab * next;
+ MainWindow * mw;
+
+ /* Traceset related information */
+ TracesetInfo * traceset_info;
+};
+
+/**
+ * Remove menu and toolbar item when a module unloaded
+ */
+void main_window_remove_menu_item(lttv_constructor view_constructor);
+void main_window_remove_toolbar_item(lttv_constructor view_constructor);
+
+#endif /* _MAIN_WINDOW_ */
+
+
--- /dev/null
+/* This file is part of the Linux Trace Toolkit viewer
+ * Copyright (C) 2003-2004 Xiangxiu Yang
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+#ifndef MENU_H
+#define MENU_H
+
+#include <lttv/common.h>
+
+/* constructor of the viewer */
+//typedef GtkWidget* (*lttv_constructor)(void * main_window);
+
+
+typedef GArray LttvMenus;
+
+typedef struct _lttv_menu_closure {
+ lttv_constructor con;
+ char * menuPath;
+ char * menuText;
+} lttv_menu_closure;
+
+
+LttvMenus *lttv_menus_new();
+
+void lttv_menus_destroy(LttvMenus *h);
+
+void lttv_menus_add(LttvMenus *h, lttv_constructor f, char* menuPath, char * menuText);
+
+gboolean lttv_menus_remove(LttvMenus *h, lttv_constructor f);
+
+unsigned lttv_menus_number(LttvMenus *h);
+
+#endif // MENU_H
--- /dev/null
+/* This file is part of the Linux Trace Toolkit viewer
+ * Copyright (C) 2003-2004 Xiangxiu Yang
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+#ifndef TOOLBAR_H
+#define TOOLBAR_H
+
+#include <lttv/common.h>
+
+/* constructor of the viewer */
+//typedef GtkWidget* (*lttv_constructor)(void * main_window);
+
+
+typedef GArray LttvToolbars;
+
+typedef struct _lttv_toolbar_closure {
+ lttv_constructor con;
+ char * tooltip;
+ char ** pixmap;
+} lttv_toolbar_closure;
+
+LttvToolbars *lttv_toolbars_new();
+
+void lttv_toolbars_destroy(LttvToolbars *h);
+
+void lttv_toolbars_add(LttvToolbars *h, lttv_constructor f, char* tooltip, char ** pixmap);
+
+gboolean lttv_toolbars_remove(LttvToolbars *h, lttv_constructor f);
+
+unsigned lttv_toolbars_number(LttvToolbars *h);
+
+#endif // TOOLBAR_H
#include <lttv/lttv.h>
#include <lttv/module.h>
#include <lttv/gtktraceset.h>
-#include <lttv/processTrace.h>
+#include <lttv/tracecontext.h>
#include <lttv/hook.h>
#include <lttv/common.h>
#include <lttv/state.h>
libdir = ${lttvplugindir}
-lib_LTLIBRARIES = libtextDump.la libbatchAnalysis.la libbatchtest.la
+lib_LTLIBRARIES = libtextDump.la libbatchAnalysis.la
libtextDump_la_LDFLAGS = -module
libtextDump_la_SOURCES = textDump.c
libbatchAnalysis_la_LDFLAGS = -module
libbatchAnalysis_la_SOURCES = batchAnalysis.c
-libbatchtest_la_LDFLAGS = -module
-libbatchtest_la_SOURCES = batchtest.c
+noinst_HEADERS = \
+ batchanalysis.h
#include <lttv/hook.h>
#include <lttv/option.h>
#include <lttv/module.h>
-#include <lttv/processTrace.h>
+#include <lttv/tracecontext.h>
#include <lttv/state.h>
#include <lttv/stats.h>
#include <ltt/trace.h>
--- /dev/null
+/* This file is part of the Linux Trace Toolkit viewer
+ * Copyright (C) 2003-2004 Michel Dagenais
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+#ifndef BATCH_ANALYSIS_H
+#define BATCH_ANALYSIS_H
+
+/* The batch analysis module defines a main traceset and command line options
+ to specify the traces in the main traceset. It then processes that
+ traceset calling hooks lists at various stages of the analysis.
+
+ The hooks lists are defined in the global attributes for these various
+ stages of the analysis. Loaded modules may add hooks to these lists.
+ Thus, by requesting that a certain module be loaded, the analysis may
+ produce additional information as the module adds hooks and these hooks
+ are called during the analysis.
+
+ The hooks lists defined are as follows. These may be split in more
+ specific lists eventually to select the hooks applicable to state update,
+ incremental or batch processing...
+
+ /hooks/traceset/before
+ Before analyzing a traceset.
+
+ /hooks/traceset/after
+ After analyzing a traceset.
+
+ /hooks/trace/before
+ Before each trace.
+
+ /hooks/trace/after
+ After each trace.
+
+ /hooks/tracefile/before
+ Before each tracefile.
+
+ /hooks/tracefile/after
+ After each tracefile.
+
+ /hooks/event/before
+ Before each event.
+
+ /hooks/event/after
+ After each event.
+
+*/
+
+#endif // BATCH_ANALYSIS_H
+++ /dev/null
-/* This file is part of the Linux Trace Toolkit viewer
- * Copyright (C) 2003-2004 Michel Dagenais
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License Version 2 as
- * published by the Free Software Foundation;
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA.
- */
-
-/* This module inserts a hook in the program main loop. This hook processes
- all the events in the main tracefile while testing the speed and
- functionality of the state and stats computations. */
-
-
-#include <lttv/lttv.h>
-#include <lttv/attribute.h>
-#include <lttv/hook.h>
-#include <lttv/option.h>
-#include <lttv/module.h>
-#include <lttv/processTrace.h>
-#include <lttv/state.h>
-#include <lttv/stats.h>
-#include <ltt/trace.h>
-#include <ltt/event.h>
-#include <ltt/type.h>
-
-static LttvTraceset *traceset;
-
-static LttvHooks
- *before_traceset,
- *after_traceset,
- *before_trace,
- *after_trace,
- *before_tracefile,
- *after_tracefile,
- *before_event,
- *after_event,
- *main_hooks;
-
-static char *a_trace;
-
-static char *a_dump_tracefiles;
-
-static char *a_save_sample;
-
-static int
- a_sample_interval,
- a_sample_number,
- a_save_interval;
-
-static gboolean
- a_trace_event,
- a_save_state_copy,
- a_test1,
- a_test2,
- a_test3,
- a_test4,
- a_test5,
- a_test6,
- a_test7,
- a_test_all;
-
-LttEventPosition *a_event_position;
-
-typedef struct _save_state {
- guint count;
- FILE *fp;
- guint interval;
- guint position;
- guint size;
- LttTime *write_time;
- guint version;
-} SaveState;
-
-
-static void lttv_trace_option(void *hook_data)
-{
- LttTrace *trace;
-
- trace = ltt_trace_open(a_trace);
- if(trace == NULL) g_critical("cannot open trace %s", a_trace);
- lttv_traceset_add(traceset, lttv_trace_new(trace));
-}
-
-static double get_time()
-{
- GTimeVal gt;
-
- g_get_current_time(>);
- return gt.tv_sec + (double)gt.tv_usec / (double)1000000.0;
-}
-
-static double run_one_test(LttvTracesetState *ts, LttTime start, LttTime end)
-{
- 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);
- t1 = get_time();
-
- lttv_traceset_context_remove_hooks(&ts->parent,
- before_traceset, after_traceset, NULL, before_trace, after_trace,
- NULL, before_tracefile, after_tracefile, NULL, before_event, after_event);
-
- return t1 - t0;
-}
-
-
-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;
-
- (*pcount)++;
- return FALSE;
-}
-
-
-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;
-
- LttvTracefileState *tfs = (LttvTracefileState *)call_data;
-
- LttvTraceState *ts = (LttvTraceState *)tfs->parent.t_context;
-
- GString *filename;
-
- FILE *fp;
-
- (save_state->count)++;
- if(save_state->count % save_state->interval == 0 &&
- save_state->position < save_state->size) {
- if(a_save_sample != NULL) {
- filename = g_string_new("");
- g_string_printf(filename, "%s.%u.xml.%u", a_save_sample,
- save_state->position, save_state->version);
- 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);
-
- save_state->write_time[save_state->position] = tfs->parent.timestamp;
- save_state->position++;
- }
- return FALSE;
-}
-
-
-static gboolean process_traceset(void *hook_data, void *call_data)
-{
- LttvTracesetStats *tscs;
-
- LttvTracesetState *ts;
-
- LttvTracesetContext *tc;
-
- GString *filename;
-
- FILE *fp;
-
- double t;
-
- guint i, j, count, nb_control, nb_tracefile, nb_block, nb_event, nb_equal;
-
- LttTrace *trace;
-
- LttTracefile *tracefile, *tf;
-
- LttEvent *event;
-
- LttFacility *facility;
-
- LttType *type;
-
- LttEventType *event_type;
-
- LttTime time, previous_time;
-
- long long unsigned cycle_count, start_count, delta_cycle;
-
- long long unsigned start_nsec, end_nsec, delta_nsec, added_nsec, added_nsec2;
-
- double cycle_per_nsec, nsec_per_cycle;
-
- long long interpolated_nsec, interpolated_nsec2, end_nsec_sec, end_nsec_nsec;
-
- LttTime start_time;
-
- 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) {
- 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);
- nb_tracefile = nb_control + ltt_trace_per_cpu_tracefile_number(trace);
- for(j = 0 ; j < nb_tracefile ; j++) {
- if(j < nb_control) {
- tracefile = ltt_trace_control_tracefile_get(trace,j);
- }
- else {
- tracefile = ltt_trace_per_cpu_tracefile_get(trace,j - nb_control);
- }
-
- filename = g_string_new("");
- g_string_printf(filename, "%s.%u.%u.trace", a_dump_tracefiles, i, j);
- fp = fopen(filename->str, "w");
- if(fp == NULL) g_error("Cannot open %s", filename->str);
- g_string_free(filename, TRUE);
- ltt_tracefile_seek_time(tracefile, zero_time);
- previous_time = zero_time;
- nb_equal = 0;
- while((event = ltt_tracefile_read(tracefile)) != NULL) {
- facility = ltt_event_facility(event);
- event_type = ltt_event_eventtype(event);
- time = ltt_event_time(event);
- cycle_count = ltt_event_cycle_count(event);
- 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,
- (unsigned long)time.tv_nsec,
- nb_block, nb_event);
-
- if(ltt_time_compare(time, previous_time) < 0) {
- g_warning("Time decreasing trace %d tracefile %d position %u/%u",
- i, j, nb_block, nb_event);
- }
-
- if(strcmp(ltt_eventtype_name(event_type),"block_start") == 0) {
- start_count = cycle_count;
- start_time = time;
- }
- else if(strcmp(ltt_eventtype_name(event_type),"block_end") == 0) {
- delta_cycle = cycle_count - start_count;
- end_nsec_sec = (long long unsigned)time.tv_sec * (long long unsigned)1000000000;
- end_nsec_nsec = time.tv_nsec;
- end_nsec = end_nsec_sec + end_nsec_nsec;
- start_nsec = (long long unsigned)start_time.tv_sec * (long long unsigned)1000000000 + (long long unsigned)start_time.tv_nsec;
- delta_nsec = end_nsec - start_nsec;
- cycle_per_nsec = (double)delta_cycle / (double)delta_nsec;
- nsec_per_cycle = (double)delta_nsec / (double)delta_cycle;
- added_nsec = (double)delta_cycle * nsec_per_cycle;
- interpolated_nsec = start_nsec + added_nsec;
- added_nsec2 = (double)delta_cycle / cycle_per_nsec;
- interpolated_nsec2 = start_nsec + added_nsec2;
-
- fprintf(fp,"Time: start_count %llu, end_count %llu, delta_cycle %llu, start_nsec %llu, end_nsec_sec %llu, end_nsec_nsec %llu, end_nsec %llu, delta_nsec %llu, cycle_per_nsec %.25f, nsec_per_cycle %.25f, added_nsec %llu, added_nsec2 %llu, interpolated_nsec %llu, interpolated_nsec2 %llu\n", start_count, cycle_count, delta_cycle, start_nsec, end_nsec_sec, end_nsec_nsec, end_nsec, delta_nsec, cycle_per_nsec, nsec_per_cycle, added_nsec, added_nsec2, interpolated_nsec, interpolated_nsec2);
- }
- else {
- if(ltt_time_compare(time, previous_time) == 0) nb_equal++;
- else if(nb_equal > 0) {
- g_warning("Consecutive %d events with time %lu.%09lu",
- nb_equal + 1, previous_time.tv_sec, previous_time.tv_nsec);
- nb_equal = 0;
- }
- previous_time = time;
- }
- }
- fclose(fp);
- }
- }
- }
-
- tscs = g_object_new(LTTV_TRACESET_STATS_TYPE, NULL);
- ts = &tscs->parent;
- tc = &tscs->parent.parent;
-
- lttv_context_init(tc, traceset);
-
- /* For each case compute and print the elapsed time.
- The first case is simply to run through all events with a
- simple counter. */
-
- if(a_test1 || a_test_all) {
- count = 0;
- lttv_hooks_add(after_event, count_event, &count);
- t = run_one_test(ts, zero_time, max_time);
- lttv_hooks_remove_data(after_event, count_event, &count);
- g_warning(
- "Processing trace while counting events (%u events in %g seconds)",
- count, t);
- }
-
- /* Run through all events computing the state. */
-
- if(a_test2 || a_test_all) {
- lttv_state_add_event_hooks(ts);
- t = run_one_test(ts, zero_time, max_time);
- lttv_state_remove_event_hooks(ts);
- g_warning("Processing trace while updating state (%g seconds)", t);
- }
-
- /* Run through all events computing the state and writing it out
- periodically. */
-
- SaveState save_state;
-
- save_state.interval = a_sample_interval;
- save_state.size = a_sample_number;
- save_state.fp = stderr;
- save_state.write_time = g_new(LttTime, a_sample_number);
-
-
- if(a_test3 || a_test_all) {
- for(i = 0 ; i < 2 ; i++) {
- save_state.count = 0;
- save_state.position = 0;
- save_state.version = i;
- lttv_state_add_event_hooks(ts);
- lttv_hooks_add(after_event, save_state_event, &save_state);
- t = run_one_test(ts, zero_time, max_time);
- lttv_state_remove_event_hooks(ts);
- lttv_hooks_remove_data(after_event, save_state_event, &save_state);
- g_warning("Processing while updating/writing state (%g seconds)", t);
- }
- }
-
- /* Run through all events computing the stats. */
-
- if(a_test4 || a_test_all) {
- if(lttv_profile_memory) {
- g_message("Memory summary before computing stats");
- g_mem_profile();
- }
-
- lttv_stats_add_event_hooks(tscs);
- t = run_one_test(ts, zero_time, max_time);
- lttv_stats_remove_event_hooks(tscs);
- g_warning("Processing trace while counting stats (%g seconds)", t);
-
- if(lttv_profile_memory) {
- 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. */
-
- if(a_test5 || a_test_all) {
- if(lttv_profile_memory) {
- g_message("Memory summary before computing state and stats");
- g_mem_profile();
- }
-
- lttv_state_add_event_hooks(ts);
- lttv_stats_add_event_hooks(tscs);
- t = run_one_test(ts, zero_time, max_time);
- lttv_state_remove_event_hooks(ts);
- lttv_stats_remove_event_hooks(tscs);
- g_warning(
- "Processing trace while counting state and stats (%g seconds)", t);
-
- if(lttv_profile_memory) {
- 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");
- g_mem_profile();
- }
-
- 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) {
- g_message("Memory summary after computing/saving state");
- g_mem_profile();
- }
- }
-
- /* Seek a few times to each saved position */
-
- if((a_test7 && a_test3) || a_test_all) {
- int i, j;
-
- for(i = 0 ; i < 2 ; i++) {
- for(j = save_state.position - 1 ; j >= 0 ; j--) {
- lttv_state_add_event_hooks(ts);
- t = run_one_test(ts, save_state.write_time[j],
- save_state.write_time[j]);
- lttv_state_remove_event_hooks(ts);
- g_warning("Seeking to %lu.%lu (%g seconds)",
- save_state.write_time[j].tv_sec, save_state.write_time[j].tv_nsec,
- t);
-
- if(a_save_sample != NULL) {
- filename = g_string_new("");
- g_string_printf(filename, "%s.%d.xml.bak%d", a_save_sample, j, i);
- fp = fopen(filename->str, "w");
- if(fp == NULL) g_error("Cannot open %s", filename->str);
- g_string_free(filename, TRUE);
- lttv_state_write((LttvTraceState *)tc->traces[0],
- save_state.write_time[j], fp);
- fclose(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");
-}
-
-
-static void init()
-{
- LttvAttributeValue value;
-
- LttvIAttribute *attributes = LTTV_IATTRIBUTE(lttv_global_attributes());
-
- g_info("Init batchtest.c");
-
- lttv_option_add("trace", 't',
- "add a trace to the trace set to analyse",
- "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 where to dump events",
- LTTV_OPT_STRING, &a_dump_tracefiles, NULL, NULL);
-
- a_save_sample = NULL;
- lttv_option_add("save-sample", 's',
- "Save state samples to multiple files",
- "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",
- "number of events before a block start triggers saving state",
- LTTV_OPT_INT, &a_save_interval, NULL, NULL);
-
- a_sample_interval = 100000;
- lttv_option_add("sample-interval", 'S',
- "Interval between sampling state",
- "number of events before sampling and writing state",
- LTTV_OPT_INT, &a_sample_interval, NULL, NULL);
-
- a_sample_number = 20;
- lttv_option_add("sample-number", 'N',
- "Number of state samples",
- "maximum number",
- LTTV_OPT_INT, &a_sample_number, NULL, NULL);
-
- a_test1 = FALSE;
- lttv_option_add("test1", '1', "Test just counting events", "",
- LTTV_OPT_NONE, &a_test1, NULL, NULL);
-
- a_test2 = FALSE;
- lttv_option_add("test2", '2', "Test computing the state", "",
- LTTV_OPT_NONE, &a_test2, NULL, NULL);
-
- a_test3 = FALSE;
- lttv_option_add("test3", '3', "Test computing the state, writing out a few",
- "", LTTV_OPT_NONE, &a_test3, NULL, NULL);
-
- a_test4 = FALSE;
- lttv_option_add("test4", '4', "Test computing the stats", "",
- LTTV_OPT_NONE, &a_test4, NULL, NULL);
-
- a_test5 = FALSE;
- lttv_option_add("test5", '5', "Test computing the state and stats", "",
- LTTV_OPT_NONE, &a_test5, NULL, NULL);
-
- a_test6 = FALSE;
- lttv_option_add("test6", '6', "Test computing and saving the state", "",
- LTTV_OPT_NONE, &a_test6, NULL, NULL);
-
- a_test7 = FALSE;
- lttv_option_add("test7", '7', "Test seeking to positions written out in 3",
- "", LTTV_OPT_NONE, &a_test7, NULL, NULL);
-
- a_test_all = FALSE;
- lttv_option_add("testall", 'a', "Run all tests ", "",
- LTTV_OPT_NONE, &a_test_all, NULL, NULL);
-
- traceset = lttv_traceset_new();
-
- before_traceset = lttv_hooks_new();
- after_traceset = lttv_hooks_new();
- before_trace = lttv_hooks_new();
- after_trace = lttv_hooks_new();
- before_tracefile = lttv_hooks_new();
- after_tracefile = lttv_hooks_new();
- before_event = lttv_hooks_new();
- after_event = lttv_hooks_new();
-
- g_assert(lttv_iattribute_find_by_path(attributes, "hooks/traceset/before",
- LTTV_POINTER, &value));
- *(value.v_pointer) = before_traceset;
- g_assert(lttv_iattribute_find_by_path(attributes, "hooks/traceset/after",
- LTTV_POINTER, &value));
- *(value.v_pointer) = after_traceset;
- g_assert(lttv_iattribute_find_by_path(attributes, "hooks/trace/before",
- LTTV_POINTER, &value));
- *(value.v_pointer) = before_trace;
- g_assert(lttv_iattribute_find_by_path(attributes, "hooks/trace/after",
- LTTV_POINTER, &value));
- *(value.v_pointer) = after_trace;
- g_assert(lttv_iattribute_find_by_path(attributes, "hooks/tracefile/before",
- LTTV_POINTER, &value));
- *(value.v_pointer) = before_tracefile;
- g_assert(lttv_iattribute_find_by_path(attributes, "hooks/tracefile/after",
- LTTV_POINTER, &value));
- *(value.v_pointer) = after_tracefile;
- g_assert(lttv_iattribute_find_by_path(attributes, "hooks/event/before",
- LTTV_POINTER, &value));
- *(value.v_pointer) = before_event;
- g_assert(lttv_iattribute_find_by_path(attributes, "hooks/event/after",
- LTTV_POINTER, &value));
- *(value.v_pointer) = after_event;
-
- g_assert(lttv_iattribute_find_by_path(attributes, "hooks/main/before",
- LTTV_POINTER, &value));
- g_assert((main_hooks = *(value.v_pointer)) != NULL);
- lttv_hooks_add(main_hooks, process_traceset, NULL);
-}
-
-
-static void destroy()
-{
- guint i, nb;
-
- LttvTrace *trace;
-
- g_info("Destroy batchAnalysis.c");
-
- 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");
- lttv_option_remove("test1");
- lttv_option_remove("test2");
- lttv_option_remove("test3");
- lttv_option_remove("test4");
- lttv_option_remove("test5");
- lttv_option_remove("test6");
- lttv_option_remove("test7");
- lttv_option_remove("testall");
-
- lttv_hooks_destroy(before_traceset);
- lttv_hooks_destroy(after_traceset);
- lttv_hooks_destroy(before_trace);
- lttv_hooks_destroy(after_trace);
- lttv_hooks_destroy(before_tracefile);
- lttv_hooks_destroy(after_tracefile);
- lttv_hooks_destroy(before_event);
- lttv_hooks_destroy(after_event);
- lttv_hooks_remove_data(main_hooks, process_traceset, NULL);
-
- nb = lttv_traceset_number(traceset);
- for(i = 0 ; i < nb ; i++) {
- trace = lttv_traceset_get(traceset, i);
- ltt_trace_close(lttv_trace(trace));
- lttv_trace_destroy(trace);
- }
-
- lttv_traceset_destroy(traceset);
-}
-
-
-LTTV_MODULE("batchtest", "Batch processing of a trace for tests", \
- "Run through a trace calling all the registered hooks for tests", \
- init, destroy, "state", "stats", "option" )