Add state saving functions and update processTrace accordingly.
authordagenais <dagenais@04897980-b3bd-0310-b5e0-8ef037075253>
Wed, 15 Oct 2003 02:56:59 +0000 (02:56 +0000)
committerdagenais <dagenais@04897980-b3bd-0310-b5e0-8ef037075253>
Wed, 15 Oct 2003 02:56:59 +0000 (02:56 +0000)
Add time operators functions

git-svn-id: http://ltt.polymtl.ca/svn@306 04897980-b3bd-0310-b5e0-8ef037075253

21 files changed:
ltt/branches/poly/include/ltt/Makefile.am
ltt/branches/poly/include/ltt/ltt.h
ltt/branches/poly/include/ltt/time.h [new file with mode: 0644]
ltt/branches/poly/include/lttv/iattribute.h
ltt/branches/poly/include/lttv/processTrace.h
ltt/branches/poly/include/lttv/state.h
ltt/branches/poly/include/lttv/traceset.h
ltt/branches/poly/ltt/tracefile.c
ltt/branches/poly/lttv/attribute.c
ltt/branches/poly/lttv/batchAnalysis.c
ltt/branches/poly/lttv/main.c
ltt/branches/poly/lttv/modules/gui/API/gtkTraceSet.c
ltt/branches/poly/lttv/modules/gui/mainWin/src/gtkcustom.c
ltt/branches/poly/lttv/modules/gui/mainWin/src/init_module.c
ltt/branches/poly/lttv/modules/guiControlFlow/Drawing.c
ltt/branches/poly/lttv/modules/guiEvents.c
ltt/branches/poly/lttv/processTrace.c
ltt/branches/poly/lttv/state.c
ltt/branches/poly/lttv/stats.c
ltt/branches/poly/lttv/textDump.c
ltt/branches/poly/lttv/traceset.c

index f9453e736387c11f29266ed4fa42a7cec2cf3ebc..be3e9f10bfd6ebd16622ac65f92ef4a628fde6a2 100644 (file)
@@ -4,5 +4,6 @@ lttinclude_HEADERS = \
        facility.h\
        ltt-private.h\
        ltt.h\
+       time.h\
        trace.h\
        type.h
index 158553622fc02102be136bda10faf9ac8733f12c..a5f3fee076c84496fd4a783b38a0b6ac45876a93 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef LTT_H
 #define LTT_H
 
+#include <ltt/time.h>
 #include <ltt/LTTTypes.h>
 
 /* A trace is associated with a tracing session run on a single, possibly
@@ -70,16 +71,11 @@ typedef unsigned long LttChecksum;
 
 
 /* Events are usually stored with the easily obtained CPU clock cycle count,
-   ltt_cycle_count. This can be converted to the real time value, ltt_time,
+   ltt_cycle_count. This can be converted to the real time value, LttTime,
    using linear interpolation between regularly sampled values (e.g. a few 
    times per second) of the real time clock with their corresponding 
    cycle count values. */
 
-typedef struct _LttTime {
-  unsigned long tv_sec;
-  unsigned long tv_nsec;
-} LttTime;
-
 
 typedef struct _TimeInterval{
   LttTime startTime;
@@ -89,7 +85,6 @@ typedef struct _TimeInterval{
 
 typedef uint64_t LttCycleCount;
 
-#define NANSECOND_CONST       1000000000
 
 /* Event positions are used to seek within a tracefile based on
    the block number and event position within the block. */
@@ -111,55 +106,6 @@ typedef enum _LttArchEndian
 { LTT_LITTLE_ENDIAN, LTT_BIG_ENDIAN
 } LttArchEndian;
 
-/* Time operation macros for LttTime (struct timespec) */
-/*  (T3 = T2 - T1) */
-#define TimeSub(T3, T2, T1) \
-do \
-{\
-  (T3).tv_sec  = (T2).tv_sec  - (T1).tv_sec;  \
-  if((T2).tv_nsec < (T1).tv_nsec)\
-    {\
-    (T3).tv_sec--;\
-    (T3).tv_nsec = NANSECOND_CONST - (T1).tv_nsec + (T2).tv_nsec;\
-    }\
-  else\
-    {\
-    (T3).tv_nsec = (T2).tv_nsec - (T1).tv_nsec;\
-    }\
-} while(0)
-
-/*  (T3 = T2 + T1) */
-#define TimeAdd(T3, T2, T1) \
-do \
-{\
-  (T3).tv_sec  = (T2).tv_sec  + (T1).tv_sec;  \
-  (T3).tv_nsec = (T2).tv_nsec + (T1).tv_nsec; \
-  if((T3).tv_nsec >= NANSECOND_CONST)\
-    {\
-    (T3).tv_sec += (T3).tv_nsec / NANSECOND_CONST;\
-    (T3).tv_nsec = (T3).tv_nsec % NANSECOND_CONST;\
-    }\
-} while(0)
-
-/*  (T2 = T1 * FLOAT) */
-/* WARNING : use this multiplicator carefully : on 32 bits, multiplying
- * by more than 4 could overflow the tv_nsec.
- */
-#define TimeMul(T2, T1, FLOAT) \
-do \
-{\
-  (T2).tv_sec  = (T1).tv_sec  * (FLOAT);  \
-  (T2).tv_nsec = (T1).tv_nsec * (FLOAT);  \
-  if((T2).tv_nsec >= NANSECOND_CONST)\
-    {\
-    (T2).tv_sec += (T2).tv_nsec / NANSECOND_CONST;\
-    (T2).tv_nsec = (T2).tv_nsec % NANSECOND_CONST;\
-    }\
-} while(0)
-
-
-
-
 #include <ltt/ltt-private.h>
 
  
diff --git a/ltt/branches/poly/include/ltt/time.h b/ltt/branches/poly/include/ltt/time.h
new file mode 100644 (file)
index 0000000..4f80943
--- /dev/null
@@ -0,0 +1,94 @@
+#ifndef LTT_TIME_H
+#define LTT_TIME_H
+
+
+typedef struct _LttTime {
+  unsigned long tv_sec;
+  unsigned long tv_nsec;
+} LttTime;
+
+
+static const unsigned long NANOSECONDS_PER_SECOND = 1000000000;
+
+static const LttTime ltt_time_zero = { 0, 0};
+
+
+static inline LttTime ltt_time_sub(LttTime t1, LttTime t2) 
+{
+  LttTime res;
+  res.tv_sec  = t1.tv_sec  - t2.tv_sec;
+  if(t1.tv_nsec < t2.tv_nsec) {
+    res.tv_sec--;
+    res.tv_nsec = NANOSECONDS_PER_SECOND + t1.tv_nsec - t2.tv_nsec;
+  }
+  else {
+    res.tv_nsec = t1.tv_nsec - t2.tv_nsec;
+  }
+  return res;
+}
+
+
+static inline LttTime ltt_time_add(LttTime t1, LttTime t2) 
+{
+  LttTime res;
+  res.tv_sec  = t1.tv_sec  + t2.tv_sec;
+  res.tv_nsec = t1.tv_nsec + t2.tv_nsec;
+  if(res.tv_nsec >= NANOSECONDS_PER_SECOND) {
+    res.tv_sec++;
+    res.tv_nsec -= NANOSECONDS_PER_SECOND;
+  }
+  return res;
+}
+
+
+static inline LttTime ltt_time_mul(LttTime t1, float f)
+{
+  double nsec;
+  LttTime res;
+
+  nsec = (double)t1.tv_nsec * f;
+  res.tv_sec = nsec / NANOSECONDS_PER_SECOND;
+  res.tv_nsec = nsec - res.tv_sec * NANOSECONDS_PER_SECOND;
+  res.tv_sec += t1.tv_sec * f;
+  return res;
+}
+
+
+static inline LttTime ltt_time_div(LttTime t1, float f)
+{
+  double sec;
+  LttTime res;
+
+  sec = t1.tv_sec / (double)f;
+  res.tv_sec = sec;
+  res.tv_nsec = t1.tv_nsec / (double)f + (sec - res.tv_sec) *
+      NANOSECONDS_PER_SECOND;
+  return res;
+}
+
+
+static inline int ltt_time_compare(LttTime t1, LttTime t2)
+{
+  if(t1.tv_sec > t2.tv_sec) return 1;
+  if(t1.tv_sec < t2.tv_sec) return -1;
+  if(t1.tv_nsec > t2.tv_nsec) return 1;
+  if(t1.tv_nsec < t2.tv_nsec) return -1;
+  return 0;
+}
+
+
+static inline double ltt_time_to_double(LttTime t1)
+{
+  return (double)t1.tv_sec + (double)t1.tv_nsec / NANOSECONDS_PER_SECOND;
+}
+
+
+static inline LttTime ltt_time_from_double(double t1)
+{
+  LttTime res;
+  res.tv_sec = t1;
+  res.tv_nsec = (t1 - res.tv_sec) * NANOSECONDS_PER_SECOND;
+  return res;
+}
+
+#endif // LTT_TIME_H
index 1613a4516aa617083c7b605aff7e623fa2016864..24cbd57db692d8f1f47c4f34271287c61295883d 100644 (file)
@@ -3,7 +3,7 @@
 
 
 #include <glib-object.h>
-#include <time.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 
@@ -12,8 +12,6 @@
 
 typedef GQuark LttvAttributeName;
 
-typedef struct timespec LttvTime;
-
 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
@@ -26,7 +24,7 @@ typedef union LttvAttributeValue {
   unsigned long *v_ulong;
   float *v_float;
   double *v_double;
-  LttvTime *v_time;
+  LttTime *v_time;
   gpointer *v_pointer;
   char **v_string;
   GObject **v_gobject;
index 610000cb19e276cdb41a6f33242157ae475830d1..e8505b5d8ba25bf0ca34909e207a250ece8148e7 100644 (file)
@@ -71,6 +71,7 @@ struct _LttvTracesetContext {
   LttvHooks *after;
   LttvTraceContext **traces;
   LttvAttribute *a;
+  LttvAttribute *ts_a;
   TimeInterval *Time_Span;
 };
 
@@ -113,12 +114,14 @@ struct _LttvTraceContext {
   LttvTracesetContext *ts_context;
   guint index;                /* in ts_context->traces */
   LttTrace *t;
+  LttvTrace *vt;
   LttvHooks *check;
   LttvHooks *before;
   LttvHooks *after;
   LttvTracefileContext **control_tracefiles;
   LttvTracefileContext **per_cpu_tracefiles;
   LttvAttribute *a;
+  LttvAttribute *t_a;
 };
 
 struct _LttvTraceContextClass {
@@ -160,8 +163,12 @@ struct _LttvTracefileContextClass {
 
 GType lttv_tracefile_context_get_type (void);
 
-void lttv_process_trace(LttTime start, LttTime end, LttvTraceset *traceset, 
-    LttvTracesetContext *context, unsigned maxNumEvents);
+void lttv_process_traceset(LttvTracesetContext *self, LttTime end, 
+    unsigned maxNumEvents);
+
+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, 
index f85847b4da52727c0841d586ad2c797d846da11a..b8f4be00db3276e7518eaf8310696242337b933b 100644 (file)
    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. */
+   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;
@@ -23,9 +38,15 @@ typedef struct _LttvTraceStateClass LttvTraceStateClass;
 typedef struct _LttvTracefileState LttvTracefileState;
 typedef struct _LttvTracefileStateClass LttvTracefileStateClass;
 
-gboolean lttv_state_add_event_hooks(LttvTracesetState *self);
+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);
 
-gboolean lttv_state_remove_event_hooks(LttvTracesetState *self);
+void lttv_state_save_remove_event_hooks(LttvTracesetState *self);
+
+void lttv_state_restore_closest_state(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
@@ -137,6 +158,7 @@ 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;
@@ -146,10 +168,21 @@ struct _LttvTraceState {
 
 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_saved_state_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))
@@ -163,6 +196,7 @@ struct _LttvTracefileState {
 
   LttvProcessState *process;
   GQuark cpu_name;
+  guint saved_position;
 };
 
 struct _LttvTracefileStateClass {
index ecf1046141523a85e01c045b5eeed682c259143d..4675e719a436903ce45287f1469d3e50516d9b95 100644 (file)
@@ -9,11 +9,14 @@
 
 typedef struct _LttvTraceset LttvTraceset;
 
+typedef struct _LttvTrace LttvTrace;
 
 /* Tracesets may be added to, removed from and their content listed. */
 
 LttvTraceset *lttv_traceset_new();
 
+LttvTrace *lttv_trace_new(LttTrace *t);
+
 LttvTraceset *lttv_traceset_copy(LttvTraceset *s_orig);
 
 LttvTraceset *lttv_traceset_load(const gchar *filename);
@@ -22,11 +25,13 @@ gint lttv_traceset_save(LttvTraceset *s);
 
 void lttv_traceset_destroy(LttvTraceset *s);
 
-void lttv_traceset_add(LttvTraceset *s, LttTrace *t);
+void lttv_trace_destroy(LttvTrace *t);
+
+void lttv_traceset_add(LttvTraceset *s, LttvTrace *t);
 
 unsigned lttv_traceset_number(LttvTraceset *s);
 
-LttTrace *lttv_traceset_get(LttvTraceset *s, unsigned i);
+LttvTrace *lttv_traceset_get(LttvTraceset *s, unsigned i);
 
 void lttv_traceset_remove(LttvTraceset *s, unsigned i);
 
@@ -34,8 +39,9 @@ void lttv_traceset_remove(LttvTraceset *s, unsigned i);
 
 LttvAttribute *lttv_traceset_attribute(LttvTraceset *s);
 
-LttvAttribute *lttv_traceset_trace_attribute(LttvTraceset *s, 
-    unsigned i);
+LttvAttribute *lttv_trace_attribute(LttvTrace *t);
+
+LttTrace *lttv_trace(LttvTrace *t);
 
 #endif // TRACESET_H
 
index a2f7bbadcc380376751ea64acaa6016ba8bd6afb..07b8ab3a837a1f3d5cb7a69124a1f58f5482df87 100644 (file)
@@ -33,10 +33,6 @@ void updateTracefile(LttTracefile * tf);
 /* go to the next event */
 int skipEvent(LttTracefile * t);
 
-/* compare two time (LttTime), 0:t1=t2, -1:t1<t2, 1:t1>t2 */
-int timecmp(LttTime * t1, LttTime * t2);
-
-
 
 /*****************************************************************************
  *Function name
@@ -693,8 +689,8 @@ void ltt_trace_time_span_get(LttTrace *t, LttTime *start, LttTime *end)
       j = 1;
       continue;
     }
-    if(timecmp(&startSmall,&startTmp) > 0) startSmall = startTmp;
-    if(timecmp(&endBig,&endTmp) < 0) endBig = endTmp;
+    if(ltt_time_compare(startSmall,startTmp) > 0) startSmall = startTmp;
+    if(ltt_time_compare(endBig,endTmp) < 0) endBig = endTmp;
   }
 
   for(i=0;i<t->per_cpu_tracefile_number;i++){
@@ -708,8 +704,8 @@ void ltt_trace_time_span_get(LttTrace *t, LttTime *start, LttTime *end)
       endBig     = endTmp;
       continue;
     }
-    if(timecmp(&startSmall,&startTmp) > 0) startSmall = startTmp;
-    if(timecmp(&endBig,&endTmp) < 0) endBig = endTmp;
+    if(ltt_time_compare(startSmall,startTmp) > 0) startSmall = startTmp;
+    if(ltt_time_compare(endBig,endTmp) < 0) endBig = endTmp;
   }
 
   *start = startSmall;
@@ -748,16 +744,16 @@ void ltt_tracefile_seek_time(LttTracefile *t, LttTime time)
 {
   int err;
   LttTime lttTime;
-  int headTime = timecmp(&(t->a_block_start->time), &time);
-  int tailTime = timecmp(&(t->a_block_end->time), &time);
+  int headTime = ltt_time_compare(t->a_block_start->time, time);
+  int tailTime = ltt_time_compare(t->a_block_end->time, time);
   LttEvent * ev;
 
   if(headTime < 0 && tailTime > 0){
-    if(timecmp(&(t->a_block_end->time),&(t->current_event_time)) !=0){
+    if(ltt_time_compare(t->a_block_end->time, t->current_event_time) !=0) {
       lttTime = getEventTime(t);
-      err = timecmp(&lttTime, &time);
+      err = ltt_time_compare(lttTime, time);
       if(err > 0){
-       if(t->which_event==2 || timecmp(&t->prev_event_time,&time)<0){
+       if(t->which_event==2 || (&t->prev_event_time,&time)<0){
          return;
        }else{
          updateTracefile(t);
@@ -771,7 +767,7 @@ void ltt_tracefile_seek_time(LttTracefile *t, LttTime time)
            return;
          }
          lttTime = getEventTime(t);
-         err = timecmp(&lttTime, &time);
+         err = ltt_time_compare(lttTime, time);
          if(err >= 0)return;
        }
       }else return;    
@@ -783,7 +779,7 @@ void ltt_tracefile_seek_time(LttTracefile *t, LttTime time)
     if(t->which_block == 1){
       updateTracefile(t);      
     }else{
-      if(timecmp(&(t->prev_block_end_time),&time) >= 0 ){
+      if(ltt_time_compare(t->prev_block_end_time, time) >= 0 ){
        err=readBlock(t,t->which_block-1);
        if(err) g_error("Can not read tracefile: %s\n", t->name); 
        return ltt_tracefile_seek_time(t, time) ;
@@ -1038,7 +1034,7 @@ void getCyclePerNsec(LttTracefile * t)
   LttCycleCount     lBufTotalCycle;/* Total cycles for this buffer */
 
   /* Calculate the total time for this buffer */
-  TimeSub(lBufTotalTime,t->a_block_end->time, t->a_block_start->time);
+  lBufTotalTime = ltt_time_sub(t->a_block_end->time, t->a_block_start->time);
 
   /* Calculate the total cycles for this bufffer */
   lBufTotalCycle  = t->a_block_end->cycle_count;
@@ -1046,7 +1042,7 @@ void getCyclePerNsec(LttTracefile * t)
 
   /* Convert the total time to nsecs */
   lBufTotalNSec  = lBufTotalTime.tv_sec;
-  lBufTotalNSec *= NANSECOND_CONST
+  lBufTotalNSec *= NANOSECONDS_PER_SECOND
   lBufTotalNSec += lBufTotalTime.tv_nsec;
   
   t->cycle_per_nsec = (double)lBufTotalCycle / (double)lBufTotalNSec;
@@ -1106,10 +1102,10 @@ LttTime getEventTime(LttTracefile * tf)
   nanoSec    = lEventNSec;
 
   // Determine offset in struct LttTime 
-  lTimeOffset.tv_nsec = nanoSec % NANSECOND_CONST;
-  lTimeOffset.tv_sec  = nanoSec / NANSECOND_CONST;
+  lTimeOffset.tv_nsec = nanoSec % NANOSECONDS_PER_SECOND;
+  lTimeOffset.tv_sec  = nanoSec / NANOSECONDS_PER_SECOND;
 
-  TimeAdd(time, tf->a_block_start->time, lTimeOffset);  
+  time = ltt_time_add(tf->a_block_start->time, lTimeOffset);  
   
   return time;
 }
@@ -1262,24 +1258,6 @@ int getFieldtypeSize(LttTracefile * t, LttEventType * evT, int offsetRoot,
   return size;
 }
 
-/*****************************************************************************
- *Function name
- *    timecmp   : compare two time
- *Input params 
- *    t1        : first time
- *    t2        : second time
- *Return value
- *    int       : 0: t1 == t2; -1: t1 < t2; 1: t1 > t2
- ****************************************************************************/
-
-int timecmp(LttTime * t1, LttTime * t2)
-{
-  if(t1->tv_sec < t2->tv_sec) return -1;
-  if(t1->tv_sec > t2->tv_sec) return 1;
-  if(t1->tv_nsec < t2->tv_nsec) return -1;
-  if(t1->tv_nsec > t2->tv_nsec) return 1;
-  return 0;
-}
 
 /*****************************************************************************
  *Function name
index 59241fb3e815cfc67862f6b52ec942de0ef81753..4b6938d7da86c1e04ec077e1353e2d662e2b3c32 100644 (file)
@@ -9,7 +9,7 @@ typedef union _AttributeValue {
   unsigned long dv_ulong;
   float dv_float;
   double dv_double;
-  LttvTime dv_time;
+  LttTime dv_time;
   gpointer dv_pointer;
   char *dv_string;
   GObject *dv_gobject;
@@ -274,7 +274,7 @@ void lttv_attribute_recursive_add(LttvAttribute *dest, LttvAttribute *src)
           *value.v_double += a->value.dv_double;
           break;
         case LTTV_TIME:
-          TimeAdd(*value.v_time, *value.v_time, a->value.dv_time);
+          *value.v_time = ltt_time_add(*value.v_time, a->value.dv_time);
           break;
         case LTTV_POINTER:
           break;
index 2db5783018d1db2f9a3334155c81b8754709acd1..98a686cd33d0be1d45255fbea3177bc303c18d66 100644 (file)
@@ -34,7 +34,7 @@ void lttv_trace_option(void *hook_data)
 
   trace = ltt_trace_open(a_trace);
   if(trace == NULL) g_critical("cannot open trace %s", a_trace);
-  lttv_traceset_add(traceset, trace);
+  lttv_traceset_add(traceset, lttv_trace_new(trace));
 }
 
 
@@ -68,7 +68,8 @@ static gboolean process_traceset(void *hook_data, void *call_data)
 
   g_info("BatchAnalysis process traceset");
 
-  lttv_process_trace(start, end, traceset, tc, G_MAXULONG);
+  lttv_process_traceset_seek_time(tc, start);
+  lttv_process_traceset(tc, end, G_MAXULONG);
 
   g_info("BatchAnalysis destroy context");
 
@@ -151,6 +152,8 @@ G_MODULE_EXPORT void destroy()
 {
   guint i, nb;
 
+  LttvTrace *trace;
+
   g_info("Destroy batchAnalysis.c");
 
   lttv_option_remove("trace");
@@ -168,7 +171,9 @@ G_MODULE_EXPORT void destroy()
 
   nb = lttv_traceset_number(traceset);
   for(i = 0 ; i < nb ; i++) {
-    ltt_trace_close(lttv_traceset_get(traceset, i));
+    trace = lttv_traceset_get(traceset, i);
+    ltt_trace_close(lttv_trace(trace));
+    lttv_trace_destroy(trace);
   }
 
   lttv_traceset_destroy(traceset); 
index de3c77096bf4dea8810692da3e1ce293371b235d..7b6f7153c39a6545c6226079ea07f616e82d0d12 100644 (file)
@@ -54,7 +54,7 @@ static void lttv_verbose(void *hook_data);
 
 static void lttv_debug(void *hook_data);
 
-static void lttv_help(void);
+static void lttv_help(void *hook_data);
 
 /* Since everything is done in modules, the main program only takes care
    of the infrastructure. */
@@ -182,7 +182,7 @@ void lttv_debug(void *hook_data)
   g_info("Logging set to include DEBUG level messages");
 }
 
-void lttv_help()
+void lttv_help(void *hook_data)
 {
        printf("Linux Trace Toolkit Visualizer\n");
        printf("\n");
@@ -190,8 +190,32 @@ void lttv_help()
        printf("\n");
 }
 
-/* remove countEvents.c, add alias to init to allow static/dynamic loading 
-   MODULE_INFO(name, init, destroy, { require} ). This info could be used
-   by module_load and as a constructor function when not a module
-   -> check constructor functions versus dynamic loading and init section
-   -> have a list of available modules builtin as default or mandatory */
+/* 
+
+- Make it easier to change modules from builtin to externally loaded.
+
+    have: MODULE_INFO(name, init, destroy, { require} ) in each module.
+    Maintain the list of builtin modules and search these first (or 
+    optionally last). Add the lib prefix if needed to avoid having to
+    specify libbatchAnalysis instead of batchAnalysis.
+
+- 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 */
index 3c681a97561b27f9e70a7bff433877fc902aaa5b..8d0c4d35a701e61f1c46d3d577b6f96a5deeed75 100644 (file)
@@ -598,9 +598,8 @@ void SetHPaneDividor(mainWindow *main_win, gint position)
 void processTraceset(mainWindow *main_win, LttTime start, 
                     LttTime end, unsigned maxNumEvents)
 {
-  lttv_process_trace(start, end, main_win->Traceset_Info->traceset, 
-      LTTV_TRACESET_CONTEXT(main_win->Traceset_Info->TracesetContext),
-      maxNumEvents);
+  lttv_process_traceset_seek_time(main_win->Traceset_Info->TracesetContext, start);
+  lttv_process_trace(main_win->Traceset_Info->TracesetContext, end, maxNumEvents);
 }
 
 /**
index 491e730c5c781fe9f777ebe5155c031824123b22..806ac23100fbda0e03953960830c43be36ecad88 100644 (file)
@@ -107,7 +107,6 @@ void gtk_custom_widget_add(GtkCustom * custom, GtkWidget * widget1)
   GtkWidget * w;
   TimeWindow Time_Window;
   LttTime      time;
-  double       tmpValue;
   TimeInterval *Time_Span;
   
   g_return_if_fail(GTK_IS_CUSTOM(custom));
@@ -126,30 +125,19 @@ void gtk_custom_widget_add(GtkCustom * custom, GtkWidget * widget1)
     GetCurrentTime(custom->mw,&time);
     Time_Span = LTTV_TRACESET_CONTEXT(custom->mw->Traceset_Info->TracesetContext)->Time_Span ;
 
-    tmpValue               = Time_Span->startTime.tv_sec;
-    tmpValue              *= NANSECOND_CONST;
-    tmpValue              += Time_Span->startTime.tv_nsec;
-    custom->hAdjust->lower = tmpValue;
-    custom->hAdjust->value = tmpValue;
-    tmpValue               = Time_Span->endTime.tv_sec;
-    tmpValue              *= NANSECOND_CONST;
-    tmpValue              += Time_Span->endTime.tv_nsec;
-    custom->hAdjust->upper = tmpValue;
-    //tmpValue               = time.tv_sec;
-    //tmpValue              *= NANSECOND_CONST;
-    //tmpValue              += time.tv_nsec;
-    //custom->hAdjust->value = tmpValue;
-    /* Step increment to 1/10 of visible area */
-    tmpValue               = Time_Window.Time_Width.tv_sec;
-    tmpValue              *= NANSECOND_CONST;
-    tmpValue              += Time_Window.Time_Width.tv_nsec;
-    custom->hAdjust->step_increment = tmpValue / 10;
+    custom->hAdjust->lower =  ltt_time_to_double(Time_Span->startTime) * 
+        NANOSECONDS_PER_SECOND;
+    custom->hAdjust->value = custom->hAdjust->lower;
+    custom->hAdjust->upper = ltt_time_to_double(Time_Span->endTime) *
+        NANOSECONDS_PER_SECOND;
     /* Page increment of whole visible area */
-    custom->hAdjust->page_increment = tmpValue;
+    custom->hAdjust->page_increment = ltt_time_to_double(
+        Time_Window.Time_Width) * NANOSECONDS_PER_SECOND;
     /* page_size to the whole visible area will take care that the
      * scroll value + the shown area will never be more than what is
      * in the trace. */
-    custom->hAdjust->page_size = tmpValue;
+    custom->hAdjust->page_size = custom->hAdjust->page_increment;
+    custom->hAdjust->step_increment = custom->hAdjust->page_increment / 10;
 
     gtk_range_set_update_policy (GTK_RANGE(custom->hScrollbar),
                                   GTK_UPDATE_DISCONTINUOUS);
@@ -320,8 +308,7 @@ void gtk_custom_scroll_value_changed(GtkRange *range, gpointer custom_arg)
   LttTime time;
   GtkCustom * custom = (GtkCustom*)custom_arg;
   gdouble value = gtk_range_get_value(range);
-  time.tv_sec  = value / NANSECOND_CONST;
-  time.tv_nsec = (value / NANSECOND_CONST - time.tv_sec) * NANSECOND_CONST; 
+  time = ltt_time_from_double(value / NANOSECONDS_PER_SECOND);
   SetCurrentTime(custom->mw, &time);
   g_warning("The current time is second :%d, nanosecond : %d\n", time.tv_sec, time.tv_nsec);
 }
index f6f398ae11507aa99bc0c7111d1de2bdc806e97d..f8635a2d3c57b1809a04ab649dc617fc02189cd7 100644 (file)
@@ -37,15 +37,17 @@ LttvHooks
   *main_hooks;
 
 /* Initial trace from command line */
-LttTrace *gInit_Trace = NULL;
+LttvTrace *gInit_Trace = NULL;
 
 static char *a_trace;
 
 void lttv_trace_option(void *hook_data)
 { 
-  gInit_Trace = ltt_trace_open(a_trace);
-  if(gInit_Trace == NULL) g_critical("cannot open trace %s", a_trace);
-  g_critical("lttv_trace_option : Init_Trace is %p", gInit_Trace);
+  LttTrace *trace;
+
+  trace = ltt_trace_open(a_trace);
+  if(trace == NULL) g_critical("cannot open trace %s", a_trace);
+  gInit_Trace = lttv_trace_new(trace);
 }
 
 /*****************************************************************************
@@ -215,6 +217,7 @@ void destroy_walk(gpointer data, gpointer user_data)
 G_MODULE_EXPORT void destroy() {
 
   LttvAttributeValue value;  
+  LttvTrace *trace;
 
   lttv_option_remove("trace");
 
index cb2d049d440e828579c7bb97c7ce00b5062cc054..e2225a118ab56c6c8c53e6c62c060dd1f57dd982 100644 (file)
@@ -244,9 +244,7 @@ GtkWidget *Drawing_getWidget(Drawing_t *Drawing)
 
 /* get_time_from_pixels
  *
- * Get the time interval from window time and pixels, and pixels requested. This
- * function uses TimeMul, which should only be used if the float value is lower
- * that 4, and here it's always lower than 1, so it's ok.
+ * Get the time interval from window time and pixels, and pixels requested.
  */
 void convert_pixels_to_time(
                Drawing_t *Drawing,
@@ -257,13 +255,10 @@ void convert_pixels_to_time(
 {
        LttTime window_time_interval;
        
-       TimeSub(window_time_interval, *window_time_end, *window_time_begin);
-
-       
-       TimeMul(*time, window_time_interval,
-                       (x/(float)Drawing->width));
-       TimeAdd(*time, *window_time_begin, *time);
-       
+       window_time_interval = ltt_time_sub(*window_time_end, 
+            *window_time_begin);
+       *time = ltt_time_mul(window_time_interval, (x/(float)Drawing->width));
+       *time = ltt_time_add(*window_time_begin, *time);
 }
 
 
@@ -278,14 +273,12 @@ void convert_time_to_pixels(
        LttTime window_time_interval;
        float interval_float, time_float;
        
-       TimeSub(window_time_interval, window_time_end, window_time_begin);
+       window_time_interval = ltt_time_sub(window_time_end,window_time_begin);
        
-       TimeSub(time, time, window_time_begin);
+       time = ltt_time_sub(time, window_time_begin);
        
-       interval_float = (window_time_interval.tv_sec * NANSECOND_CONST)
-                       + window_time_interval.tv_nsec;
-       time_float = (time.tv_sec * NANSECOND_CONST)
-                       + time.tv_nsec;
+       interval_float = ltt_time_to_double(window_time_interval);
+       time_float = ltt_time_to_double(time);
 
        *x = (guint)(time_float/interval_float * Drawing->width);
        
index 9b3e8641b07b40c36e8447371709c260bedc03d8..183688a006686c454713fe8fa8661b4f73c30018 100644 (file)
@@ -439,7 +439,7 @@ GuiEvents(mainWindow *pmParentWindow)
   getTracesetTimeSpan(Event_Viewer_Data->mw, &Event_Viewer_Data->time_span);
   
   time_value = Event_Viewer_Data->time_span.endTime.tv_sec - Event_Viewer_Data->time_span.startTime.tv_sec;
-  time_value *= NANSECOND_CONST;
+  time_value *= NANOSECONDS_PER_SECOND;
   time_value += (double)Event_Viewer_Data->time_span.endTime.tv_nsec - Event_Viewer_Data->time_span.startTime.tv_nsec;
   Event_Viewer_Data->VAdjust_C->upper = time_value;
 
@@ -688,8 +688,8 @@ void Tree_V_cursor_changed_cb (GtkWidget *widget, gpointer data)
   gtk_tree_view_get_cursor(GTK_TREE_VIEW(Event_Viewer_Data->Tree_V), &path, NULL);
   if(gtk_tree_model_get_iter(model,&iter,path)){
     gtk_tree_model_get(model, &iter, TIME_COLUMN, &time, -1);
-    ltt_time.tv_sec = time / NANSECOND_CONST;
-    ltt_time.tv_nsec = time % NANSECOND_CONST;
+    ltt_time.tv_sec = time / NANOSECONDS_PER_SECOND;
+    ltt_time.tv_nsec = time % NANOSECONDS_PER_SECOND;
  
     if(ltt_time.tv_sec != Event_Viewer_Data->current_time.tv_sec ||
        ltt_time.tv_nsec != Event_Viewer_Data->current_time.tv_nsec)
@@ -941,14 +941,14 @@ void get_test_data(double time_value, guint List_Height,
        end.tv_sec = G_MAXULONG;
        end.tv_nsec = G_MAXULONG;
        start = Event_Viewer_Data->time_span.startTime;
-       value = (int)(time_value / NANSECOND_CONST);
+       value = (int)(time_value / NANOSECONDS_PER_SECOND);
        start.tv_sec += value;
-       value = time_value / NANSECOND_CONST - value;
-       value *= NANSECOND_CONST;
+       value = time_value / NANOSECONDS_PER_SECOND - value;
+       value *= NANOSECONDS_PER_SECOND;
        start.tv_nsec += value;
-       if(start.tv_nsec > NANSECOND_CONST){
+       if(start.tv_nsec > NANOSECONDS_PER_SECOND){
          start.tv_sec++;
-         start.tv_nsec -= NANSECOND_CONST;
+         start.tv_nsec -= NANOSECONDS_PER_SECOND;
        }
        Event_Viewer_Data->previous_value = time_value;
        get_events(Event_Viewer_Data, start, end, RESERVE_SMALL_SIZE,&size);
@@ -990,7 +990,7 @@ void get_test_data(double time_value, guint List_Height,
       raw_data = (RawTraceData*)g_list_nth_data(first,Event_Number);
       value = raw_data->time.tv_sec;
       value -= Event_Viewer_Data->time_span.startTime.tv_sec;
-      value *= NANSECOND_CONST;
+      value *= NANOSECONDS_PER_SECOND;
       value -= Event_Viewer_Data->time_span.startTime.tv_nsec;
       value += raw_data->time.tv_nsec;
       Event_Viewer_Data->VAdjust_C->value = value;
@@ -1014,7 +1014,7 @@ void get_test_data(double time_value, guint List_Height,
 
        // Add a new row to the model 
        real_data = raw_data->time.tv_sec;
-       real_data *= NANSECOND_CONST;
+       real_data *= NANOSECONDS_PER_SECOND;
        real_data += raw_data->time.tv_nsec;
        gtk_list_store_append (Event_Viewer_Data->Store_M, &iter);
        gtk_list_store_set (Event_Viewer_Data->Store_M, &iter,
@@ -1215,7 +1215,7 @@ gboolean updateCurrentTime(void * hook_data, void * call_data)
 {
   EventViewerData *Event_Viewer_Data = (EventViewerData*) hook_data;
   Event_Viewer_Data->current_time = *(LttTime*)call_data;
-  uint64_t nsec = Event_Viewer_Data->current_time.tv_sec * NANSECOND_CONST 
+  uint64_t nsec = Event_Viewer_Data->current_time.tv_sec * NANOSECONDS_PER_SECOND 
                   + Event_Viewer_Data->current_time.tv_nsec;
   GtkTreeIter iter;
   uint64_t time;
index 339bc1af7d9fdad09a2fa46abd52d848ec8a68fb..cb9335567cb926a827e29b2b0ce2446f064eda8b 100644 (file)
@@ -92,23 +92,28 @@ init(LttvTracesetContext *self, LttvTraceset *ts)
 
   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->t = lttv_traceset_get(ts, 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;
@@ -141,6 +146,8 @@ init(LttvTracesetContext *self, LttvTraceset *ts)
       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);
 }
@@ -480,11 +487,7 @@ lttv_tracefile_context_get_type(void)
 
 gint compare_tracefile(gconstpointer a, gconstpointer b)
 {
-  if(((LttvTime *)a)->tv_sec > ((LttvTime *)b)->tv_sec) return 1;
-  if(((LttvTime *)a)->tv_sec < ((LttvTime *)b)->tv_sec) return -1;
-  if(((LttvTime *)a)->tv_nsec > ((LttvTime *)b)->tv_nsec) return 1;
-  if(((LttvTime *)a)->tv_nsec < ((LttvTime *)b)->tv_nsec) return -1;
-  return 0;
+  return ltt_time_compare(*((LttTime *)a), *((LttTime *)b));
 }
 
 
@@ -494,8 +497,8 @@ gboolean get_first(gpointer key, gpointer value, gpointer user_data) {
 }
 
 
-void lttv_process_trace(LttTime start, LttTime end, LttvTraceset *traceset
-    LttvTracesetContext *context, unsigned maxNumEvents)
+void lttv_process_traceset(LttvTracesetContext *self, LttTime end
+    unsigned maxNumEvents)
 {
   GPtrArray *traces = g_ptr_array_new();
 
@@ -514,19 +517,20 @@ void lttv_process_trace(LttTime start, LttTime end, LttvTraceset *traceset,
   LttvTracefileContext *tfc;
 
   LttEvent *event;
+
   unsigned count = 0;
-  LttTime preTimestamp;
+
+  LttTime previous_timestamp = {0, 0};
 
   /* 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(context->before, context);
-  nbi = lttv_traceset_number(traceset);
-  //  nbi = ltt_trace_set_number(traceset);
+  lttv_hooks_call(self->before, self);
+  nbi = lttv_traceset_number(self->ts);
 
   for(i = 0 ; i < nbi ; i++) {
-    tc = context->traces[i];
+    tc = self->traces[i];
     trace = tc->t;
 
     if(!lttv_hooks_call_check(tc->check, tc)) {
@@ -550,12 +554,7 @@ void lttv_process_trace(LttTime start, LttTime end, LttvTraceset *traceset,
           g_ptr_array_add(tracefiles, tfc);
           lttv_hooks_call(tfc->before, tfc);
 
-          ltt_tracefile_seek_time(tracefile, start);
-          event = ltt_tracefile_read(tracefile);
-          tfc->e = event;
-
           if(event != NULL) {
-            tfc->timestamp = ltt_event_time(event);
             g_tree_insert(pqueue, &(tfc->timestamp), tfc);
           }
         }
@@ -573,14 +572,14 @@ void lttv_process_trace(LttTime start, LttTime end, LttvTraceset *traceset,
     g_tree_foreach(pqueue, get_first, &tfc);
     if(tfc == NULL) break;
 
-    /* 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. */
+    /* 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. */
 
     count++;
     if(count > maxNumEvents){
-      if(tfc->timestamp.tv_sec == preTimestamp.tv_sec &&
-        tfc->timestamp.tv_nsec == preTimestamp.tv_nsec) {
+      if(tfc->timestamp.tv_sec == previous_timestamp.tv_sec &&
+        tfc->timestamp.tv_nsec == previous_timestamp.tv_nsec) {
        count--;
       }else{   
        while(TRUE){
@@ -592,7 +591,12 @@ void lttv_process_trace(LttTime start, LttTime end, LttvTraceset *traceset,
        break;
       }
     }
-    preTimestamp = tfc->timestamp;
+    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. */
 
     tfc = g_tree_lookup(pqueue, &(tfc->timestamp));
     g_tree_remove(pqueue, &(tfc->timestamp));
@@ -632,7 +636,7 @@ void lttv_process_trace(LttTime start, LttTime end, LttvTraceset *traceset,
   }
 
   g_assert(j == tracefiles->len);
-  lttv_hooks_call(context->after, context);
+  lttv_hooks_call(self->after, self);
 
   /* Free the traces, tracefiles and pqueue */
 
@@ -641,6 +645,44 @@ void lttv_process_trace(LttTime start, LttTime end, LttvTraceset *traceset,
   g_tree_destroy(pqueue);
 }
 
+
+void lttv_process_trace_seek_time(LttvTraceContext *self, LttTime start)
+{
+  guint i, nb_control, nb_per_cpu, nb_tracefile;
+
+  LttvTracefileContext *tfc;
+
+  LttEvent *event;
+
+  nb_control = ltt_trace_control_tracefile_number(self->t);
+  nb_per_cpu = ltt_trace_per_cpu_tracefile_number(self->t);
+  nb_tracefile = nb_control + nb_per_cpu;
+  for(i = 0 ; i < nb_tracefile ; i++) {
+    if(i < nb_control) tfc = self->control_tracefiles[i];
+    else tfc = self->per_cpu_tracefiles[i - nb_control];
+
+    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)
 {
index d53aef724fd9043d0b42926ec546daf3ec19600e..4176313c82391c008ede664a67c4f92886266af1 100644 (file)
@@ -2,6 +2,7 @@
 #include <lttv/state.h>
 #include <ltt/facility.h>
 #include <ltt/trace.h>
+#include <ltt/event.h>
 
 LttvExecutionMode
   LTTV_STATE_MODE_UNKNOWN,
@@ -23,6 +24,12 @@ LttvProcessStatus
   LTTV_STATE_RUN;
 
 static GQuark
+  LTTV_STATE_TRACEFILES,
+  LTTV_STATE_PROCESSES,
+  LTTV_STATE_PROCESS,
+  LTTV_STATE_EVENT,
+  LTTV_STATE_SAVED_STATES,
+  LTTV_STATE_TIME,
   LTTV_STATE_HOOKS;
 
 
@@ -30,11 +37,61 @@ static void fill_name_tables(LttvTraceState *tcs);
 
 static void free_name_tables(LttvTraceState *tcs);
 
-static void remove_all_processes(GHashTable *processes);
+static void lttv_state_free_process_table(GHashTable *processes);
 
-LttvProcessState *create_process(LttvTracefileState *tfs, 
+static LttvProcessState *create_process(LttvTracefileState *tfs, 
                                 LttvProcessState *parent, guint pid);
 
+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_saved_state_free(LttvTraceState *self, 
+    LttvAttribute *container)
+{
+  LTTV_TRACE_STATE_GET_CLASS(self)->state_restore(self, container);
+}
+
+
+static void
+restore_init_state(LttvTraceState *self)
+{
+  guint i, nb_control, nb_per_cpu, 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(g_direct_hash, g_direct_equal);
+  self->nb_event = 0;
+
+  nb_control = ltt_trace_control_tracefile_number(self->parent.t);
+  nb_per_cpu = ltt_trace_per_cpu_tracefile_number(self->parent.t);
+  nb_tracefile = nb_control + nb_per_cpu;
+  for(i = 0 ; i < nb_tracefile ; i++) {
+    if(i < nb_control) {
+      tfcs = LTTV_TRACEFILE_STATE(self->parent.control_tracefiles[i]);
+    }
+    else {
+      tfcs = LTTV_TRACEFILE_STATE(self->parent.per_cpu_tracefiles[i - nb_control]);
+    }
+
+    tfcs->parent.timestamp = null_time;
+    tfcs->saved_position = 0;
+    tfcs->process = create_process(tfcs, NULL,0);
+  }
+}
+
+
 static void
 init(LttvTracesetState *self, LttvTraceset *ts)
 {
@@ -46,8 +103,6 @@ init(LttvTracesetState *self, LttvTraceset *ts)
 
   LttvTracefileState *tfcs;
   
-  LttTime timestamp = {0,0};
-
   LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE))->
       init((LttvTracesetContext *)self, ts);
 
@@ -55,7 +110,7 @@ init(LttvTracesetState *self, LttvTraceset *ts)
   for(i = 0 ; i < nb_trace ; i++) {
     tc = self->parent.traces[i];
     tcs = (LttvTraceState *)tc;
-    tcs->processes = g_hash_table_new(g_direct_hash, g_direct_equal);
+    tcs->save_interval = 100000;
     fill_name_tables(tcs);
 
     nb_control = ltt_trace_control_tracefile_number(tc->t);
@@ -68,11 +123,10 @@ init(LttvTracesetState *self, LttvTraceset *ts)
       else {
         tfcs = LTTV_TRACEFILE_STATE(tc->per_cpu_tracefiles[j - nb_control]);
       }
-
-      tfcs->parent.timestamp = timestamp;
-      tfcs->process = create_process(tfcs, NULL,0);
       tfcs->cpu_name= g_quark_from_string(ltt_tracefile_name(tfcs->parent.tf));
     }
+    tcs->processes = NULL;
+    restore_init_state(tcs);
   }
 }
 
@@ -89,8 +143,8 @@ fini(LttvTracesetState *self)
   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]);
-    remove_all_processes(tcs->processes);
-    g_hash_table_destroy(tcs->processes);
+    lttv_state_free_process_table(tcs->processes);
+    tcs->processes = NULL;
     free_name_tables(tcs);
   }
   LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE))->
@@ -119,149 +173,202 @@ new_tracefile_context(LttvTracesetContext *self)
 }
 
 
-static void
-traceset_state_instance_init (GTypeInstance *instance, gpointer g_class)
+static void copy_process_state(gpointer key, gpointer value,gpointer user_data)
 {
-}
+  LttvProcessState *process, *new_process;
 
+  GHashTable *new_processes = (GHashTable *)user_data;
 
-static void
-traceset_state_finalize (LttvTracesetState *self)
-{
-  G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE))->
-      finalize(G_OBJECT(self));
+  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, GUINT_TO_POINTER(new_process->pid), 
+      new_process);
 }
 
 
-static void
-traceset_state_class_init (LttvTracesetContextClass *klass)
+static GHashTable *lttv_state_copy_process_table(GHashTable *processes)
 {
-  GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
+  GHashTable *new_processes = g_hash_table_new(g_direct_hash, g_direct_equal);
 
-  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;
+  g_hash_table_foreach(processes, copy_process_state, new_processes);
+  return new_processes;
 }
 
 
-GType 
-lttv_traceset_state_get_type(void)
+/* 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)
 {
-  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 (LttvTracesetContext),
-      0,      /* n_preallocs */
-      (GInstanceInitFunc) traceset_state_instance_init    /* instance_init */
-    };
+  guint i, nb_control, nb_per_cpu, nb_tracefile;
 
-    type = g_type_register_static (LTTV_TRACESET_CONTEXT_TYPE, "LttvTracesetStateType", 
-        &info, 0);
+  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_control = ltt_trace_control_tracefile_number(self->parent.t);
+  nb_per_cpu = ltt_trace_per_cpu_tracefile_number(self->parent.t);
+  nb_tracefile = nb_control + nb_per_cpu;
+
+  for(i = 0 ; i < nb_tracefile ; i++) {
+    if(i < nb_control) 
+        tfcs = (LttvTracefileState *)self->parent.control_tracefiles[i];
+    else tfcs = (LttvTracefileState *)
+        self->parent.per_cpu_tracefiles[i - nb_control];
+
+    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 = g_new(LttEventPosition, 1);
+      ltt_event_position(tfcs->parent.e, ep);
+      *(value.v_pointer) = ep;
+    }
   }
-  return type;
 }
 
 
-static void
-trace_state_instance_init (GTypeInstance *instance, gpointer g_class)
+static void state_restore(LttvTraceState *self, LttvAttribute *container)
 {
-}
+  guint i, nb_control, nb_per_cpu, nb_tracefile;
 
+  LttvTracefileState *tfcs;
 
-static void
-trace_state_finalize (LttvTraceState *self)
-{
-  G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACE_CONTEXT_TYPE))->
-      finalize(G_OBJECT(self));
-}
+  LttvAttribute *tracefiles_tree, *tracefile_tree;
 
+  LttvAttributeType type;
 
-static void
-trace_state_class_init (LttvTraceContextClass *klass)
-{
-  GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
+  LttvAttributeValue value;
 
-  gobject_class->finalize = (void (*)(GObject *self)) trace_state_finalize;
-}
+  LttvAttributeName name;
 
+  LttEventPosition *ep;
 
-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 */
-    };
+  tracefiles_tree = lttv_attribute_find_subdir(container, 
+      LTTV_STATE_TRACEFILES);
 
-    type = g_type_register_static (LTTV_TRACE_CONTEXT_TYPE, 
-        "LttvTraceStateType", &info, 0);
+  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_control = ltt_trace_control_tracefile_number(self->parent.t);
+  nb_per_cpu = ltt_trace_per_cpu_tracefile_number(self->parent.t);
+  nb_tracefile = nb_control + nb_per_cpu;
+
+  for(i = 0 ; i < nb_tracefile ; i++) {
+    if(i < nb_control) tfcs = (LttvTracefileState *)
+        self->parent.control_tracefiles[i];
+    else tfcs = (LttvTracefileState *)
+        self->parent.per_cpu_tracefiles[i - nb_control];
+
+    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);
+    tfcs->process = lttv_state_find_process(tfcs, *(value.v_uint));
+    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);
+    }
   }
-  return type;
 }
 
 
-static void
-tracefile_state_instance_init (GTypeInstance *instance, gpointer g_class)
+static void state_saved_free(LttvTraceState *self, LttvAttribute *container)
 {
-}
+  guint i, nb_control, nb_per_cpu, nb_tracefile;
 
+  LttvTracefileState *tfcs;
 
-static void
-tracefile_state_finalize (LttvTracefileState *self)
-{
-  G_OBJECT_CLASS(g_type_class_peek(LTTV_TRACEFILE_CONTEXT_TYPE))->
-      finalize(G_OBJECT(self));
-}
+  LttvAttribute *tracefiles_tree, *tracefile_tree;
 
+  LttvAttributeType type;
 
-static void
-tracefile_state_class_init (LttvTracefileStateClass *klass)
-{
-  GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
+  LttvAttributeValue value;
 
-  gobject_class->finalize = (void (*)(GObject *self)) tracefile_state_finalize;
-}
+  LttvAttributeName name;
 
+  LttEventPosition *ep;
 
-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 */
-    };
+  tracefiles_tree = lttv_attribute_find_subdir(container, 
+      LTTV_STATE_TRACEFILES);
+  lttv_attribute_remove_by_name(container, LTTV_STATE_TRACEFILES);
 
-    type = g_type_register_static (LTTV_TRACEFILE_CONTEXT_TYPE, 
-        "LttvTracefileStateType", &info, 0);
+  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_control = ltt_trace_control_tracefile_number(self->parent.t);
+  nb_per_cpu = ltt_trace_per_cpu_tracefile_number(self->parent.t);
+  nb_tracefile = nb_control + nb_per_cpu;
+
+  for(i = 0 ; i < nb_tracefile ; i++) {
+    if(i < nb_control) tfcs = (LttvTracefileState *)
+        self->parent.control_tracefiles[i];
+    else tfcs = (LttvTracefileState *)
+        self->parent.per_cpu_tracefiles[i - nb_control];
+
+    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));
   }
-  return type;
+  lttv_attribute_recursive_free(tracefiles_tree);
 }
 
 
@@ -412,7 +519,7 @@ static void pop_state(LttvTracefileState *tfs, LttvExecutionMode t)
 }
 
 
-LttvProcessState *create_process(LttvTracefileState *tfs, 
+static LttvProcessState *create_process(LttvTracefileState *tfs, 
     LttvProcessState *parent, guint pid)
 {
   LttvProcessState *process = g_new(LttvProcessState, 1);
@@ -458,7 +565,8 @@ LttvProcessState *create_process(LttvTracefileState *tfs,
 }
 
 
-LttvProcessState *lttv_state_find_process(LttvTracefileState *tfs, guint pid)
+LttvProcessState *lttv_state_find_process(LttvTracefileState *tfs, 
+    guint pid)
 {
   LttvTraceState *ts =(LttvTraceState *)LTTV_TRACEFILE_CONTEXT(tfs)->t_context;
   LttvProcessState *process = g_hash_table_lookup(ts->processes, 
@@ -485,9 +593,10 @@ static void free_process_state(gpointer key, gpointer value,gpointer user_data)
 }
 
 
-static void remove_all_processes(GHashTable *processes)
+static void lttv_state_free_process_table(GHashTable *processes)
 {
   g_hash_table_foreach(processes, free_process_state, NULL);
+  g_hash_table_destroy(processes);
 }
 
 
@@ -621,22 +730,16 @@ static gboolean process_exit(void *hook_data, void *call_data)
 }
 
 
-lttv_state_add_event_hooks(LttvTracesetState *self)
+void lttv_state_add_event_hooks(LttvTracesetState *self)
 {
   LttvTraceset *traceset = self->parent.ts;
 
   guint i, j, k, nb_trace, nb_control, nb_per_cpu, nb_tracefile;
 
-  LttFacility *f;
-
-  LttEventType *et;
-
   LttvTraceState *ts;
 
   LttvTracefileState *tfs;
 
-  void *hook_data;
-
   GArray *hooks;
 
   LttvTraceHook hook;
@@ -705,7 +808,7 @@ lttv_state_add_event_hooks(LttvTracesetState *self)
 }
 
 
-lttv_state_remove_event_hooks(LttvTracesetState *self)
+void lttv_state_remove_event_hooks(LttvTracesetState *self)
 {
   LttvTraceset *traceset = self->parent.ts;
 
@@ -715,8 +818,6 @@ lttv_state_remove_event_hooks(LttvTracesetState *self)
 
   LttvTracefileState *tfs;
 
-  void *hook_data;
-
   GArray *hooks;
 
   LttvTraceHook hook;
@@ -754,6 +855,315 @@ lttv_state_remove_event_hooks(LttvTracesetState *self)
 }
 
 
+static gboolean block_end(void *hook_data, void *call_data)
+{
+  LttvTracefileState *tfcs = (LttvTracefileState *)call_data;
+
+  LttvTraceState *tcs = (LttvTraceState *)(tfcs->parent.t_context);
+
+  LttEventPosition ep;
+
+  guint nb_block, nb_event;
+
+  LttTracefile *tf;
+
+  LttvAttribute *saved_states_tree, *saved_state_tree;
+
+  LttvAttributeValue value;
+
+  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 = 0;
+  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) = tfcs->parent.timestamp;
+    lttv_state_save(tcs, saved_state_tree);
+    tcs->nb_event = 0;
+  }
+  return FALSE;
+}
+
+
+void lttv_state_save_add_event_hooks(LttvTracesetState *self)
+{
+  LttvTraceset *traceset = self->parent.ts;
+
+  guint i, j, k, nb_trace, nb_control, nb_per_cpu, nb_tracefile;
+
+  LttvTraceState *ts;
+
+  LttvTracefileState *tfs;
+
+  LttvTraceHook hook;
+
+  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_end",NULL, 
+       NULL, NULL, block_end, &hook);
+
+    nb_control = ltt_trace_control_tracefile_number(ts->parent.t);
+    nb_per_cpu = ltt_trace_per_cpu_tracefile_number(ts->parent.t);
+    nb_tracefile = nb_control + nb_per_cpu;
+    for(j = 0 ; j < nb_tracefile ; j++) {
+      if(j < nb_control) {
+        tfs = LTTV_TRACEFILE_STATE(ts->parent.control_tracefiles[j]);
+      }
+      else {
+        tfs =LTTV_TRACEFILE_STATE(ts->parent.per_cpu_tracefiles[j-nb_control]);
+      }
+
+      lttv_hooks_add(lttv_hooks_by_id_find(tfs->parent.after_event_by_id, 
+         hook.id), hook.h, NULL);
+    }
+  }
+}
+
+
+void lttv_state_save_remove_event_hooks(LttvTracesetState *self)
+{
+  LttvTraceset *traceset = self->parent.ts;
+
+  guint i, j, k, nb_trace, nb_control, nb_per_cpu, nb_tracefile;
+
+  LttvTraceState *ts;
+
+  LttvTracefileState *tfs;
+
+  LttvTraceHook hook;
+
+  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_end",NULL, 
+       NULL, NULL, block_end, &hook);
+
+    nb_control = ltt_trace_control_tracefile_number(ts->parent.t);
+    nb_per_cpu = ltt_trace_per_cpu_tracefile_number(ts->parent.t);
+    nb_tracefile = nb_control + nb_per_cpu;
+    for(j = 0 ; j < nb_tracefile ; j++) {
+      if(j < nb_control) {
+        tfs = LTTV_TRACEFILE_STATE(ts->parent.control_tracefiles[j]);
+      }
+      else {
+        tfs =LTTV_TRACEFILE_STATE(ts->parent.per_cpu_tracefiles[j-nb_control]);
+      }
+
+      lttv_hooks_remove_data(lttv_hooks_by_id_find(
+          tfs->parent.after_event_by_id, hook.id), hook.h, NULL);
+    }
+  }
+}
+
+
+void lttv_state_restore_closest_state(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];
+
+    saved_states_tree = lttv_attribute_find_subdir(tcs->parent.t_a,
+        LTTV_STATE_SAVED_STATES);
+    min_pos = -1;
+    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;
+    }
+    if(min_pos == -1) {
+      restore_init_state(tcs);
+      lttv_process_trace_seek_time(&(tcs->parent), ltt_time_zero);
+    }
+    else lttv_state_restore(tcs, closest_tree);
+  }
+}
+
+
+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 (LttvTracesetContext),
+      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;
+}
+
+
 void lttv_state_init(int argc, char **argv)
 {
   LTTV_STATE_UNNAMED = g_quark_from_string("unnamed");
@@ -769,6 +1179,12 @@ void lttv_state_init(int argc, char **argv)
   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_TIME = g_quark_from_string("time");
   LTTV_STATE_HOOKS = g_quark_from_string("saved state hooks");
 }
 
index 311658c1141443ee5823016940e956a42e2ce393..eaa2041ceb5485cf969581f14161584d5578d971 100644 (file)
@@ -327,9 +327,9 @@ static void mode_change(LttvTracefileStats *tfcs)
 
   lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_CPU_TIME, 
       LTTV_TIME, &cpu_time);
-  TimeSub(delta, tfcs->parent.parent.timestamp, 
+  delta = ltt_time_sub(tfcs->parent.parent.timestamp, 
       tfcs->parent.process->state->change);
-  TimeAdd(*(cpu_time.v_time), *(cpu_time.v_time), delta);
+  *(cpu_time.v_time) = ltt_time_add(*(cpu_time.v_time), delta);
 }
 
 
@@ -341,15 +341,15 @@ static void mode_end(LttvTracefileStats *tfcs)
 
   lttv_attribute_find(tfcs->current_events_tree, LTTV_STATS_ELAPSED_TIME, 
       LTTV_TIME, &elapsed_time);
-  TimeSub(delta, tfcs->parent.parent.timestamp, 
+  delta = ltt_time_sub(tfcs->parent.parent.timestamp, 
       tfcs->parent.process->state->entry);
-  TimeAdd(*(elapsed_time.v_time), *(elapsed_time.v_time), delta);
+  *(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);
-  TimeSub(delta, tfcs->parent.parent.timestamp, 
+  delta = ltt_time_sub(tfcs->parent.parent.timestamp, 
       tfcs->parent.process->state->change);
-  TimeAdd(*(cpu_time.v_time), *(cpu_time.v_time), delta);
+  *(cpu_time.v_time) = ltt_time_add(*(cpu_time.v_time), delta);
 }
 
 
index 73cd5b90a25c1e2b7be740b542e4a246ac50125b..dbdd253668466a1c31b3b6e142639cb8d3a6457f 100644 (file)
@@ -316,6 +316,8 @@ G_MODULE_EXPORT void init(LttvModule *self, int argc, char **argv)
 
   g_info("Init textDump.c");
 
+  lttv_module_require(self, "libbatchAnalysis", argc, argv);
+
   a_string = g_string_new("");
 
   a_file_name = NULL;
index aee03471209c972293d191cad1fbc01a96d8206e..2192d212342c3747629a9593a918e030c4d52e04 100644 (file)
 struct _LttvTraceset {
   char * filename;
   GPtrArray *traces;
-  GPtrArray *attributes;
+  LttvAttribute *a;
+};
+
+
+struct _LttvTrace {
+  LttTrace *t;
   LttvAttribute *a;
 };
 
@@ -23,11 +28,21 @@ LttvTraceset *lttv_traceset_new()
   s = g_new(LttvTraceset, 1);
   s->filename = NULL;
   s->traces = g_ptr_array_new();
-  s->attributes = g_ptr_array_new();
   s->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
   return s;
 }
 
+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;
+  return new_trace;
+}
+
+
 LttvTraceset *lttv_traceset_copy(LttvTraceset *s_orig) 
 {
   int i;
@@ -38,18 +53,12 @@ LttvTraceset *lttv_traceset_copy(LttvTraceset *s_orig)
   s->traces = g_ptr_array_new();
   for(i=0;i<s_orig->traces->len;i++)
   {
+    /*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,
-       ltt_trace_copy(g_ptr_array_index(s_orig->traces, i)));
-  }
-  s->attributes = g_ptr_array_new();
-  for(i=0;i<s_orig->attributes->len;i++)
-  {
-    g_ptr_array_add(
-        s->attributes,
-        lttv_iattribute_deep_copy(g_ptr_array_index(s_orig->attributes, i)));
+       g_ptr_array_index(s_orig->traces, i));
   }
   s->a = LTTV_ATTRIBUTE(lttv_iattribute_deep_copy(LTTV_IATTRIBUTE(s_orig->a)));
   return s;
 }
@@ -80,23 +89,24 @@ gint lttv_traceset_save(LttvTraceset *s)
   fclose(tf);
   return 0;
 }
+
 void lttv_traceset_destroy(LttvTraceset *s) 
 {
-  int i, nb;
-
-  for(i = 0 ; i < s->attributes->len ; i++) {
-    g_object_unref((LttvAttribute *)s->attributes->pdata[i]);
-  }
-  g_ptr_array_free(s->attributes, TRUE);
   g_ptr_array_free(s->traces, TRUE);
   g_object_unref(s->a);
   g_free(s);
 }
 
-void lttv_traceset_add(LttvTraceset *s, LttTrace *t) 
+void lttv_trace_destroy(LttvTrace *t) 
+{
+  g_object_unref(t->a);
+  g_free(t);
+}
+
+
+void lttv_traceset_add(LttvTraceset *s, LttvTrace *t) 
 {
   g_ptr_array_add(s->traces, t);
-  g_ptr_array_add(s->attributes, g_object_new(LTTV_ATTRIBUTE_TYPE, NULL));
 }
 
 
@@ -106,18 +116,16 @@ unsigned lttv_traceset_number(LttvTraceset *s)
 }
 
 
-LttTrace *lttv_traceset_get(LttvTraceset *s, unsigned i) 
+LttvTrace *lttv_traceset_get(LttvTraceset *s, unsigned i) 
 {
   g_assert(s->traces->len > i);
-  return ((LttTrace *)s->traces->pdata[i]);
+  return ((LttvTrace *)s->traces->pdata[i]);
 }
 
 
 void lttv_traceset_remove(LttvTraceset *s, unsigned i) 
 {
   g_ptr_array_remove_index(s->traces, i);
-  g_object_unref(s->attributes->pdata[i]);
-  g_ptr_array_remove_index(s->attributes,i);
 }
 
 
@@ -130,7 +138,14 @@ LttvAttribute *lttv_traceset_attribute(LttvTraceset *s)
 }
 
 
-LttvAttribute *lttv_traceset_trace_attribute(LttvTraceset *s, unsigned i)
+LttvAttribute *lttv_trace_attribute(LttvTrace *t)
+{
+  return t->a;
+}
+
+
+LttTrace *lttv_trace(LttvTrace *t)
 {
-  return (LttvAttribute *)s->attributes->pdata[i];
+  return t->t;
 }
+
This page took 0.05248 seconds and 4 git commands to generate.