a_test6,
a_test7,
a_test8,
+ a_test9,
a_test_all;
static GQuark QUARK_BLOCK_START,
}
+ if(a_test9 || a_test_all) {
+ /* Run seek_forward and seek_backward test */
+ LttvTracesetContextPosition *saved_pos =
+ lttv_traceset_context_position_new();
+ guint count;
+ LttvTracesetContext *tsc = &ts->parent;
+ g_message("Running test 9 : seek_forward and seek_backward");
+ lttv_process_traceset_seek_time(tsc, ltt_time_zero);
+
+ count = lttv_process_traceset_seek_n_forward(tsc, 500, NULL);
+ g_assert(count == 500);
+ lttv_traceset_context_position_save(tsc, saved_pos);
+ count = lttv_process_traceset_seek_n_forward(tsc, 150000, NULL);
+ g_assert(count == 150000);
+ count = lttv_process_traceset_seek_n_backward(tsc, 150000,
+ seek_back_default_offset, lttv_process_traceset_seek_time, NULL);
+ g_assert(count == 150000);
+ if(lttv_traceset_context_ctx_pos_compare(tsc, saved_pos)) {
+ g_warning("Problem with seek_n ! Positions differ. (1)");
+ }
+
+ lttv_process_traceset_seek_n_forward(tsc, 500, NULL);
+ lttv_traceset_context_position_save(tsc, saved_pos);
+ lttv_process_traceset_seek_n_forward(tsc, 15000, NULL);
+ lttv_process_traceset_seek_n_backward(tsc, 15005,
+ seek_back_default_offset, lttv_process_traceset_seek_time, NULL);
+ lttv_process_traceset_seek_n_forward(tsc, 5, NULL);
+ if(lttv_traceset_context_ctx_pos_compare(tsc, saved_pos)) {
+ g_warning("Problem with seek_n ! Positions differ. (2)");
+ }
+
+ lttv_process_traceset_seek_time(tsc, ltt_time_infinite);
+
+ count = lttv_process_traceset_seek_n_forward(tsc, 15000, NULL);
+ if(count > 0)
+ g_warning("Problem with seek_n ! Forward at end of traceset.");
+
+ lttv_process_traceset_seek_time(tsc, ltt_time_infinite);
+
+ lttv_traceset_context_position_save(tsc, saved_pos);
+ lttv_process_traceset_seek_n_backward(tsc, 300,
+ seek_back_default_offset, lttv_process_traceset_seek_time, NULL);
+ count = lttv_process_traceset_seek_n_forward(tsc, 299, NULL);
+ count = lttv_process_traceset_seek_n_forward(tsc, 1, NULL);
+
+ if(lttv_traceset_context_ctx_pos_compare(tsc, saved_pos)) {
+ g_warning("Problem with seek_n ! Positions differ. (4)");
+ }
+
+ /* try a volountary error */
+ lttv_process_traceset_seek_time(tsc, ltt_time_infinite);
+
+ lttv_traceset_context_position_save(tsc, saved_pos);
+ lttv_process_traceset_seek_n_backward(tsc, 301,
+ seek_back_default_offset, lttv_process_traceset_seek_time, NULL);
+ count = lttv_process_traceset_seek_n_forward(tsc, 299, NULL);
+ count = lttv_process_traceset_seek_n_forward(tsc, 1, NULL);
+
+ if(lttv_traceset_context_ctx_pos_compare(tsc, saved_pos) == 0) {
+ g_warning("Problem with seek_n ! Positions _should_ differ. (5)");
+ }
+
+ /* Try a seek by closest time : Hint : try this one with and without states
+ * computed. */
+ lttv_process_traceset_seek_time(tsc, ltt_time_zero);
+ count = lttv_process_traceset_seek_n_forward(tsc, 200000, NULL);
+ lttv_traceset_context_position_save(tsc, saved_pos);
+ lttv_process_traceset_seek_n_backward(tsc, 100301,
+ //seek_back_default_offset, lttv_state_traceset_seek_time_closest, NULL);
+ seek_back_default_offset, lttv_process_traceset_seek_time, NULL);
+ count = lttv_process_traceset_seek_n_forward(tsc, 100301, NULL);
+
+ if(lttv_traceset_context_ctx_pos_compare(tsc, saved_pos)) {
+ g_warning("Problem with seek_n with state seek time! Positions differ. (6)");
+ }
+
+ lttv_traceset_context_position_destroy(saved_pos);
+ }
if(a_trace_event) lttv_hooks_remove_data(event_hook, trace_event, NULL);
g_free(save_state.write_time);
a_test8 = FALSE;
lttv_option_add("test8", '8', "Test seeking to positions using saved states computed at 6 : check if number of events fits",
"", LTTV_OPT_NONE, &a_test8, NULL, NULL);
+
+ a_test9 = FALSE;
+ lttv_option_add("test9", '9', "Test seeking backward/forward positions",
+ "", LTTV_OPT_NONE, &a_test9, NULL, NULL);
+
a_test_all = FALSE;
lttv_option_add("testall", 'a', "Run all tests ", "",
lttv_option_remove("test6");
lttv_option_remove("test7");
lttv_option_remove("test8");
+ lttv_option_remove("test9");
lttv_option_remove("testall");
lttv_hooks_destroy(before_traceset);
const LttEvent* event,
const LttTracefile* tracefile,
const LttTrace* trace,
- const LttvProcessState* state,
const LttvTracefileContext* context
/*,...*/)
{
*/
gboolean lresult = FALSE, rresult = FALSE;
+
+ LttvProcessState* state;
+
+ if(LTTV_IS_TRACESET_STATE(context)) {
+ guint cpu = ltt_tracefile_num(context->tf);
+ LttvTraceState *ts = (LttvTraceState*)context->t_context;
+ state = ts->running_process[cpu];
+ } else {
+ state = NULL;
+ }
/*
* Parse left branch
*/
if(t->left == LTTV_TREE_NODE) {
- lresult = lttv_filter_tree_parse(t->l_child.t,event,tracefile,trace,state,context);
+ lresult = lttv_filter_tree_parse(t->l_child.t,event,tracefile,trace,context);
}
else if(t->left == LTTV_TREE_LEAF) {
lresult = lttv_filter_tree_parse_branch(t->l_child.leaf,event,tracefile,trace,state,context);
* Parse right branch
*/
if(t->right == LTTV_TREE_NODE) {
- rresult = lttv_filter_tree_parse(t->r_child.t,event,tracefile,trace,state,context);
+ rresult = lttv_filter_tree_parse(t->r_child.t,event,tracefile,trace,context);
}
else if(t->right == LTTV_TREE_LEAF) {
rresult = lttv_filter_tree_parse_branch(t->r_child.leaf,event,tracefile,trace,state,context);
typedef struct _LttvSimpleExpression LttvSimpleExpression;
typedef struct _LttvFilterTree LttvFilterTree;
-typedef struct _LttvFilter LttvFilter;
+#ifndef LTTVFILTER_TYPE_DEFINED
+typedef struct _LttvFilter LttvFilter;
+#define LTTVFILTER_TYPE_DEFINED
+#endif
/**
* @enum _LttvStructType
const LttEvent* event,
const LttTracefile* tracefile,
const LttTrace* trace,
- const LttvProcessState* state,
const LttvTracefileContext* context);
gboolean lttv_filter_tree_parse_branch(
#include <ltt/facility.h>
#include <ltt/trace.h>
#include <ltt/type.h>
+#include <lttv/filter.h>
#include <errno.h>
#define min(a,b) (((a)<(b))?(a):(b))
guint i;
guint num_traces = lttv_traceset_number(self->ts);
+ for(i=0;i<pos->ep->len;i++){
+ LttEventPosition *ep = g_array_index(pos->ep, LttEventPosition*, i);
+ if(ep != NULL) g_free(ep);
+ }
+
pos->tfc = g_array_set_size(pos->tfc, 0);
pos->ep = g_array_set_size(pos->ep, 0);
src_ep = &g_array_index(src->ep, LttEventPosition*, i);
dest_ep = &g_array_index(dest->ep, LttEventPosition*, i);
if(*src_ep != NULL) {
- *dest_ep = ltt_event_position_new();
+ if(*dest_ep == NULL) *dest_ep = ltt_event_position_new();
ltt_event_position_copy(
*dest_ep,
*src_ep);
overwrite at this position : this is a circular array.
*/
guint events_found;
+ guint n; /* number of events requested */
GPtrArray *array; /* array of LttvTracesetContextPositions pointers */
+ LttvFilter *filter;
};
static gint seek_back_event_hook(void *hook_data, void* call_data)
LttvTracefileContext *tfc = (LttvTracefileContext*)call_data;
LttvTracesetContext *tsc = tfc->t_context->ts_context;
LttvTracesetContextPosition *pos;
-
- if(sd->events_found < sd->array->len) {
- pos = (LttvTracesetContextPosition*)g_ptr_array_index (sd->array,
- sd->events_found);
- } else {
- pos = (LttvTracesetContextPosition*)g_ptr_array_index (sd->array,
- sd->first_event);
+
+ if(sd->filter != NULL) {
+ if(!lttv_filter_tree_parse(sd->filter->head,
+ ltt_tracefile_get_event(tfc->tf),
+ tfc->tf,
+ tfc->t_context->t,
+ tfc))
+ return FALSE;
}
+
+ pos = (LttvTracesetContextPosition*)g_ptr_array_index (sd->array,
+ sd->first_event);
lttv_traceset_context_position_save(tsc, pos);
if(sd->first_event >= sd->array->len - 1) sd->first_event = 0;
else sd->first_event++;
- sd->events_found = min(sd->array->len, sd->events_found + 1);
+ sd->events_found = min(sd->n, sd->events_found + 1);
return FALSE;
}
-
/* Seek back n events back from the current position.
*
* Parameters :
* @self The trace set context
* @n number of events to jump over
* @first_offset The initial offset value used. Hint : try about 100000ns.
+ * never put first_offset at ltt_time_zero.
+ * @time_seeker Function pointer of the function to use to seek time :
+ * either lttv_process_traceset_seek_time
+ * or lttv_state_traceset_seek_time_closest
+ * @filter The filter to call.
*
* Return value : the number of events found (might be lower than the number
* requested if beginning of traceset is reached).
* contain any hook, as process_traceset_middle is used in this routine.
*/
guint lttv_process_traceset_seek_n_backward(LttvTracesetContext *self,
- guint n, LttTime first_offset)
+ guint n, LttTime first_offset,
+ seek_time_fct time_seeker,
+ LttvFilter *filter)
{
+ if(lttv_traceset_number(self->ts) == 0) return 0;
+ g_assert(ltt_time_compare(first_offset, ltt_time_zero) != 0);
+
guint i;
LttvTracesetContextPosition *next_iter_end_pos =
lttv_traceset_context_position_new();
LttvTracesetContextPosition *end_pos = lttv_traceset_context_position_new();
+ LttvTracesetContextPosition *saved_pos = lttv_traceset_context_position_new();
LttTime time;
LttTime time_offset;
struct seek_back_data sd;
sd.first_event = 0;
sd.events_found = 0;
sd.array = g_ptr_array_sized_new(n);
+ sd.filter = filter;
+ sd.n = n;
g_ptr_array_set_size(sd.array, n);
for(i=0;i<n;i++) {
g_ptr_array_index (sd.array, i) = lttv_traceset_context_position_new();
}
-
+
lttv_traceset_context_position_save(self, next_iter_end_pos);
+ lttv_traceset_context_position_save(self, saved_pos);
/* Get the current time from which we will offset */
time = lttv_traceset_context_position_get_time(next_iter_end_pos);
/* the position saved might be end of traceset... */
/* stop criteria : - n events found
* - time < beginning of trace */
if(ltt_time_compare(time, self->time_span.start_time) < 0) break;
- if(sd.events_found == n) break;
lttv_traceset_context_position_copy(end_pos, next_iter_end_pos);
/* this time becomes the new reference time */
time = ltt_time_sub(time, time_offset);
- lttv_process_traceset_seek_time(self, time);
+ time_seeker(self, time);
lttv_traceset_context_position_save(self, next_iter_end_pos);
+ /* Resync the time in case of a seek_closest */
+ time = lttv_traceset_context_position_get_time(next_iter_end_pos);
+ if(ltt_time_compare(time, self->time_span.end_time) > 0) {
+ time = self->time_span.end_time;
+ }
/* Process the traceset, calling a hook which adds events
* to the array, overwriting the tail. It changes first_event and
lttv_process_traceset_middle(self, ltt_time_infinite,
G_MAXUINT, end_pos);
+ if(sd.events_found < n) {
+ if(sd.first_event > 0) {
+ /* Save the first position */
+ LttvTracesetContextPosition *pos =
+ (LttvTracesetContextPosition*)g_ptr_array_index (sd.array, 0);
+ lttv_traceset_context_position_copy(saved_pos, pos);
+ }
+ g_assert(n-sd.events_found <= sd.array->len);
+ /* Change array size to n - events_found */
+ for(i=n-sd.events_found;i<sd.array->len;i++) {
+ LttvTracesetContextPosition *pos =
+ (LttvTracesetContextPosition*)g_ptr_array_index (sd.array, i);
+ lttv_traceset_context_position_destroy(pos);
+ }
+ g_ptr_array_set_size(sd.array, n-sd.events_found);
+ sd.first_event = 0;
+
+ } else break; /* Second end criterion : n events found */
+
time_offset = ltt_time_mul(time_offset, BACKWARD_SEEK_MUL);
}
lttv_process_traceset_end(self, NULL, NULL, NULL, hooks, NULL);
- if(sd.events_found > 0) {
+ if(sd.events_found >= n) {
/* Seek the traceset to the first event in the circular array */
LttvTracesetContextPosition *pos =
(LttvTracesetContextPosition*)g_ptr_array_index (sd.array,
sd.first_event);
g_assert(lttv_process_traceset_seek_position(self, pos) == 0);
+ } else {
+ /* Will seek to the last saved position : in the worst case, it will be the
+ * original position (if events_found is 0) */
+ g_assert(lttv_process_traceset_seek_position(self, saved_pos) == 0);
}
- for(i=0;i<n;i++) {
+ for(i=0;i<sd.array->len;i++) {
LttvTracesetContextPosition *pos =
(LttvTracesetContextPosition*)g_ptr_array_index (sd.array, i);
lttv_traceset_context_position_destroy(pos);
lttv_hooks_destroy(hooks);
+ lttv_traceset_context_position_destroy(saved_pos);
+
return sd.events_found;
}
struct seek_forward_data {
guint event_count; /* event counter */
guint n; /* requested number of events to jump over */
+ LttvFilter *filter;
};
static gint seek_forward_event_hook(void *hook_data, void* call_data)
{
struct seek_forward_data *sd = (struct seek_forward_data*)hook_data;
+ LttvTracefileContext *tfc = (LttvTracefileContext*)call_data;
+ if(sd->filter != NULL) {
+ if(!lttv_filter_tree_parse(sd->filter->head,
+ ltt_tracefile_get_event(tfc->tf),
+ tfc->tf,
+ tfc->t_context->t,
+ tfc))
+ return FALSE;
+ }
+
sd->event_count++;
if(sd->event_count >= sd->n)
/* Seek back n events forward from the current position
*
* Parameters :
- * @self the trace set context
- * @n number of events to jump over
+ * @self the trace set context
+ * @n number of events to jump over
+ * @filter filter to call.
*
* returns : the number of events jumped over (may be less than requested if end
* of traceset reached) */
guint lttv_process_traceset_seek_n_forward(LttvTracesetContext *self,
- guint n)
+ guint n, LttvFilter *filter)
{
struct seek_forward_data sd;
sd.event_count = 0;
sd.n = n;
+ sd.filter = filter;
LttvHooks *hooks = lttv_hooks_new();
lttv_hooks_add(hooks, seek_forward_event_hook, &sd, LTTV_PRIO_DEFAULT);
typedef struct _LttvTracesetContextPosition LttvTracesetContextPosition;
typedef struct _LttvTraceContextPosition LttvTraceContextPosition;
+#ifndef LTTVFILTER_TYPE_DEFINED
+typedef struct _LttvFilter LttvFilter;
+#define LTTVFILTER_TYPE_DEFINED
+#endif
+
#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 BACKWARD_SEEK_MUL 2 /* Multiplication factor of time_offset between
backward seek iterations */
+static const LttTime seek_back_default_offset = { 0, 100000 };
+
guint lttv_process_traceset_seek_n_forward(LttvTracesetContext *self,
- guint n);
+ guint n,
+ LttvFilter *filter);
+typedef void (*seek_time_fct)(LttvTracesetContext *self, LttTime start);
+/* If first_offset is ltt_time_zero, it will choose a default value */
guint lttv_process_traceset_seek_n_backward(LttvTracesetContext *self,
- guint n, LttTime first_offset);
+ guint n,
+ LttTime first_offset,
+ seek_time_fct,
+ LttvFilter *filter);
+
#endif // PROCESSTRACE_H