X-Git-Url: http://git.liburcu.org/?p=lttv.git;a=blobdiff_plain;f=lttv%2Flttv%2Ftraceset.c;h=aafa3714d0a0647ff2a248f056319a349037ab01;hp=16487a117ff90b86bf7e3675e7d93762e3a480f6;hb=8284135eaaf40b6d7897c63a59a7df0b7f0cd2c7;hpb=7a4bdb546094fea3343bfc80e3744ea26a08dd22 diff --git a/lttv/lttv/traceset.c b/lttv/lttv/traceset.c index 16487a11..aafa3714 100644 --- a/lttv/lttv/traceset.c +++ b/lttv/lttv/traceset.c @@ -23,11 +23,23 @@ #include #include #include +#include #include #include +#include #include -#include +#include #include + +/* To traverse a tree recursively */ +#include +/* For the use of realpath*/ +#include +#include +/* For strcpy*/ +#include +#include +#include /* 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, @@ -37,29 +49,29 @@ LttvTraceset *lttv_traceset_new(void) { - LttvTraceset *s; - struct bt_iter_pos begin_pos; + LttvTraceset *ts; + struct bt_iter_pos begin_pos; - s = g_new(LttvTraceset, 1); - s->filename = NULL; - s->traces = g_ptr_array_new(); - s->context = bt_context_create(); - s->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); - //TODO remove this when we have really mecanism - //s->tmpState = g_new(LttvTraceState *, 1); - //lttv_trace_state_init(s->tmpState,0); - begin_pos.type = BT_SEEK_BEGIN; - - //s->iter = bt_ctf_iter_create(lttv_traceset_get_context(s), - // &begin_pos, - // NULL); - s->iter = 0; - s->event_hooks = lttv_hooks_new(); + ts = g_new(LttvTraceset, 1); + ts->filename = NULL; + ts->common_path = NULL; + ts->traces = g_ptr_array_new(); + ts->context = bt_context_create(); + ts->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); + /*Initialize iterator to the beginning of the traces*/ + begin_pos.type = BT_SEEK_BEGIN; + ts->iter = bt_ctf_iter_create(ts->context, &begin_pos, NULL); + ts->event_hooks = lttv_hooks_new(); + ts->state_trace_handle_index = g_ptr_array_new(); + ts->has_precomputed_states = FALSE; - return s; + ts->time_span.start_time = ltt_time_zero; + ts->time_span.end_time = ltt_time_zero; + lttv_traceset_get_time_span_real(ts); + return ts; } char * lttv_traceset_name(LttvTraceset * s) @@ -79,6 +91,30 @@ LttvTrace *lttv_trace_new(LttTrace *t) return new_trace; } #endif +/* + * get_absolute_pathname : Return the unique pathname in the system + * + * pathname is the relative path. + * + * abs_pathname is being set to the absolute path. + * + */ +void get_absolute_pathname(const gchar *pathname, gchar * abs_pathname) +{ + abs_pathname[0] = '\0'; + + if (realpath(pathname, abs_pathname) != NULL) + return; + else + { + /* error, return the original path unmodified */ + strcpy(abs_pathname, pathname); + return; + } + return; +} + + /* * lttv_trace_create : Create a trace from a path @@ -94,27 +130,54 @@ LttvTrace *lttv_trace_new(LttTrace *t) */ static LttvTrace *lttv_trace_create(LttvTraceset *ts, const char *path) { - int id = bt_context_add_trace(lttv_traceset_get_context(ts), - path, - "ctf", - NULL, - NULL, - NULL); - if (id < 0) { - return NULL; - } - // Create the trace and save the trace handle id returned by babeltrace - LttvTrace *new_trace; + int id = bt_context_add_trace(lttv_traceset_get_context(ts), + path, + "ctf", + NULL, + NULL, + NULL); + if (id < 0) { + return NULL; + } + // Create the trace and save the trace handle id returned by babeltrace + LttvTrace *new_trace; + + new_trace = g_new(LttvTrace, 1); + new_trace->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); + new_trace->id = id; + new_trace->ref_count = 0; + new_trace->traceset = ts; + new_trace->state = g_new(LttvTraceState,1); + lttv_trace_state_init(new_trace->state,new_trace); + + /* Add the state to the trace_handle to state index */ + g_ptr_array_set_size(ts->state_trace_handle_index,id+1); + g_ptr_array_index(ts->state_trace_handle_index,id) = new_trace->state; + + /* Find common path */ + if (ts->common_path == NULL) { + ts->common_path = strdup(path); + } else { + /* TODO ybrosseau 2013-05-24: consider put that in a function */ + int i,j; + for (i = 0; + ts->common_path != '\0'; + i++) { + if (path[i] != ts->common_path[i]) { + /* The common path has changed, redo the other traces */ + for(j = 0; j < ts->traces->len; j++) { + LttvTrace *t = g_ptr_array_index(ts->traces, j); + strncpy(t->short_name, t->full_path+i, TRACE_NAME_SIZE); + } + + break; + } + } + strncpy(new_trace->short_name, path+i, TRACE_NAME_SIZE); + } + new_trace->full_path = strdup(path); - new_trace = g_new(LttvTrace, 1); - new_trace->a = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); - new_trace->id = id; - new_trace->ref_count = 0; - new_trace->traceset = ts; - new_trace->state = g_new(LttvTraceState,1); - lttv_trace_state_init(new_trace->state,new_trace); - ts->tmpState = new_trace->state; - return new_trace; + return new_trace; } /* @@ -128,12 +191,12 @@ static LttvTrace *lttv_trace_create(LttvTraceset *ts, const char *path) */ static int lttv_traceset_create_trace(LttvTraceset *ts, const char *path) { - LttvTrace *trace = lttv_trace_create(ts, path); - if (trace == NULL) { - return -1; - } - lttv_traceset_add(ts, trace); - return 0; + LttvTrace *trace = lttv_trace_create(ts, path); + if (trace == NULL) { + return -1; + } + lttv_traceset_add(ts, trace); + return 0; } LttvTraceset *lttv_traceset_copy(LttvTraceset *s_orig) @@ -144,7 +207,9 @@ LttvTraceset *lttv_traceset_copy(LttvTraceset *s_orig) s = g_new(LttvTraceset, 1); s->filename = NULL; + s->common_path = strdup(s_orig->common_path); s->traces = g_ptr_array_new(); + s->state_trace_handle_index = g_ptr_array_new(); for(i=0;itraces->len;i++) { trace = g_ptr_array_index(s_orig->traces, i); @@ -152,6 +217,10 @@ LttvTraceset *lttv_traceset_copy(LttvTraceset *s_orig) /* WARNING: this is an alias, not a copy. */ g_ptr_array_add(s->traces, trace); + + g_ptr_array_set_size(s->state_trace_handle_index,trace->id+1); + g_ptr_array_index(s->state_trace_handle_index,trace->id) = trace->state; + } s->context = s_orig->context; bt_context_get(s->context); @@ -198,6 +267,7 @@ void lttv_traceset_destroy(LttvTraceset *s) if(lttv_trace_get_ref_number(trace) == 0) lttv_trace_destroy(trace); } + free(s->common_path); g_ptr_array_free(s->traces, TRUE); bt_context_put(s->context); g_object_unref(s->a); @@ -221,22 +291,105 @@ LttvHooks *lttv_traceset_get_hooks(LttvTraceset *s) void lttv_trace_destroy(LttvTrace *t) { + free(t->full_path); 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); } -int lttv_traceset_add_path(LttvTraceset *ts, const char *trace_path) +int lttv_traceset_get_trace_index_from_event(LttvEvent *event) { - // todo mdenis 2012-03-27: add trace recursively and update comment - int ret = lttv_traceset_create_trace(ts, trace_path); - return ret; + LttvTraceset *ts = event->state->trace->traceset; + + return lttv_traceset_get_trace_index_from_handle_id(ts, bt_ctf_event_get_handle_id(event->bt_event)); +} + +int lttv_traceset_get_trace_index_from_handle_id(LttvTraceset *ts, int handle_id) +{ + int i; + + /* TODO ybrosseau 2013-05-22: use a map to speedup the lookup */ + + for(i = 0; i < ts->traces->len; i++) { + LttvTrace *t = g_ptr_array_index(ts->traces, i); + if (t && t->id == handle_id) { + return i; + } + } + + /* Handle id not found */ + return -1; + +} + +int lttv_traceset_add_path(LttvTraceset *ts, char *trace_path) +{ + int ret = -1; + DIR *curdir = NULL; + gboolean metaFileFound = FALSE; + + /* Open top level directory */ + curdir = opendir(trace_path); + if (curdir == NULL) { + g_warning("Cannot open directory %s (%s)", trace_path, strerror(errno)); + return ret; + } + + // Check if a metadata file exists in the current directory + int metafd = openat(dirfd(curdir), "metadata", O_RDONLY); + if (metafd < 0) { + + } else { + ret = close(metafd); + if (ret < 0) { + g_warning("Unable to close metadata " + "file descriptor : %s.", trace_path); + goto error; + } + + ret = lttv_traceset_create_trace(ts, trace_path); + if (ret < 0) { + g_warning("Opening trace \"%s\" " + "for reading.", trace_path); + goto error; + } + metaFileFound = TRUE; + } + + struct dirent curentry; + struct dirent *resultentry; + while ((ret = readdir_r(curdir, &curentry, &resultentry)) == 0) { + if (resultentry == NULL) { + /* No more entry*/ + break; + } + if (curentry.d_name[0] != '.') { + if (curentry.d_type == DT_DIR) { + + char curpath[PATH_MAX]; + snprintf(curpath, PATH_MAX, "%s/%s", trace_path, curentry.d_name); + ret = lttv_traceset_add_path(ts, curpath); + if (ret >= 0) { + metaFileFound = TRUE; + } + } + } + } + + if (ret != 0) { + g_warning("Invalid readdir"); + } + +error: + if(metaFileFound) + return ret; + else + return -1; } unsigned lttv_traceset_number(LttvTraceset *s) @@ -277,16 +430,10 @@ LttvAttribute *lttv_trace_attribute(LttvTrace *t) return t->a; } -#ifdef BABEL_CLEANUP -LttTrace *lttv_trace(LttvTrace *t) -{ - return t->t; -} -#endif gint lttv_trace_get_id(LttvTrace *t) { - return t->id; + return t->id; } guint lttv_trace_get_ref_number(LttvTrace * t) @@ -316,26 +463,59 @@ guint lttv_trace_get_num_cpu(LttvTrace *t) return 24; } -LttvTracesetPosition *lttv_traceset_create_position(LttvTraceset *traceset) +LttvTracesetPosition *lttv_traceset_create_current_position(LttvTraceset *traceset) { -#warning "TODO" - return NULL; + LttvTracesetPosition *traceset_pos; + + traceset_pos = g_new(LttvTracesetPosition, 1); + + /* Check if the new passed */ + if(traceset_pos == NULL) { + return NULL; + } + + traceset_pos->iter = traceset->iter; + traceset_pos->bt_pos = bt_iter_get_pos(bt_ctf_get_iter(traceset->iter)); + traceset_pos->timestamp = G_MAXUINT64; + traceset_pos->cpu_id = INT_MAX; + + return traceset_pos; +} + +LttvTracesetPosition *lttv_traceset_create_time_position(LttvTraceset *traceset, + LttTime timestamp) +{ + LttvTracesetPosition *traceset_pos; + + traceset_pos = g_new(LttvTracesetPosition, 1); + + /* Check if the new passed */ + if(traceset_pos == NULL) { + return NULL; + } + + traceset_pos->iter = traceset->iter; + traceset_pos->bt_pos = bt_iter_create_time_pos( + bt_ctf_get_iter(traceset_pos->iter), + ltt_time_to_uint64(timestamp)); + traceset_pos->timestamp = G_MAXUINT64; + traceset_pos->cpu_id = INT_MAX; + return traceset_pos; } void lttv_traceset_destroy_position(LttvTracesetPosition *traceset_pos) { -#warning "TODO" - return NULL; + bt_iter_free_pos(traceset_pos->bt_pos); + g_free(traceset_pos); } -void lttv_traceset_seek_to_position(LttvTracesetPosition *traceset_pos) +void lttv_traceset_seek_to_position(const LttvTracesetPosition *traceset_pos) { -#warning "TODO" + bt_iter_set_pos(bt_ctf_get_iter(traceset_pos->iter), traceset_pos->bt_pos); } guint lttv_traceset_get_cpuid_from_event(LttvEvent *event) { - struct definition *scope; unsigned long timestamp; unsigned int cpu_id; @@ -344,7 +524,7 @@ guint lttv_traceset_get_cpuid_from_event(LttvEvent *event) if (timestamp == -1ULL) { return 0; } - scope = bt_ctf_get_top_level_scope(ctf_event, BT_STREAM_PACKET_CONTEXT); + const struct bt_definition *scope = bt_ctf_get_top_level_scope(ctf_event, BT_STREAM_PACKET_CONTEXT); if (bt_ctf_field_get_error()) { return 0; } @@ -356,7 +536,264 @@ guint lttv_traceset_get_cpuid_from_event(LttvEvent *event) } } +guint64 lttv_traceset_get_timestamp_first_event(LttvTraceset *ts) +{ + LttvTracesetPosition begin_position; + struct bt_iter_pos pos; + begin_position.bt_pos = &pos; + begin_position.timestamp = G_MAXUINT64; + begin_position.cpu_id = INT_MAX; + + /* Assign iterator to the beginning of the traces */ + begin_position.bt_pos->type = BT_SEEK_BEGIN; + begin_position.iter = ts->iter; + + return lttv_traceset_position_get_timestamp(&begin_position); +} + +guint64 lttv_traceset_get_timestamp_last_event(LttvTraceset *ts) +{ + LttvTracesetPosition last_position; + struct bt_iter_pos pos; + last_position.bt_pos = &pos; + last_position.timestamp = G_MAXUINT64; + last_position.cpu_id = INT_MAX; + + /* Assign iterator to the last event of the traces */ + last_position.bt_pos->type = BT_SEEK_LAST; + last_position.iter = ts->iter; + + return lttv_traceset_position_get_timestamp(&last_position); +} + +/* + * lttv_traceset_get_timestamp_begin : returns the minimum timestamp of + * all the traces in the traceset. + * + */ +guint64 lttv_traceset_get_timestamp_begin(LttvTraceset *traceset) +{ + struct bt_context *bt_ctx; + bt_ctx = lttv_traceset_get_context(traceset); + guint64 timestamp_min, timestamp_cur = 0; + int i; + int trace_count; + LttvTrace *currentTrace; + trace_count = traceset->traces->len; + if(trace_count == 0) + timestamp_min = 0; + else{ + timestamp_min = G_MAXUINT64; + for(i = 0; i < trace_count;i++) + { + currentTrace = g_ptr_array_index(traceset->traces,i); + timestamp_cur = bt_trace_handle_get_timestamp_begin(bt_ctx, + currentTrace->id, + BT_CLOCK_REAL); + if(timestamp_cur < timestamp_min) + timestamp_min = timestamp_cur; + } + } + return timestamp_min; +} + +/* + * lttv_traceset_get_timestamp_end: returns the maximum timestamp of + * all the traces in the traceset. + * + */ +guint64 lttv_traceset_get_timestamp_end(LttvTraceset *traceset) +{ + struct bt_context *bt_ctx; + bt_ctx = lttv_traceset_get_context(traceset); + guint64 timestamp_max, timestamp_cur = 0; + int i; + int trace_count; + LttvTrace *currentTrace; + trace_count = traceset->traces->len; + + if(trace_count == 0){ + timestamp_max = 1; + } + else{ + timestamp_max = 0; + for(i =0; i < trace_count;i++) + { + currentTrace = g_ptr_array_index(traceset->traces,i); + timestamp_cur = bt_trace_handle_get_timestamp_end(bt_ctx, + currentTrace->id, + BT_CLOCK_REAL); + if(timestamp_cur > timestamp_max){ + timestamp_max = timestamp_cur; + } + } + } + return timestamp_max; +} +/* + * lttv_traceset_get_time_span_real : return a TimeInterval representing the + * minimum timestamp and the maximum timestamp of the traceset. + * + */ +TimeInterval lttv_traceset_get_time_span_real(LttvTraceset *ts) +{ + + + if(ltt_time_compare(ts->time_span.start_time, + ltt_time_zero) == 0 && ts->traces->len > 0){ + ts->time_span.start_time = ltt_time_from_uint64( + lttv_traceset_get_timestamp_first_event(ts)); + ts->time_span.end_time = ltt_time_from_uint64( + lttv_traceset_get_timestamp_last_event(ts)); + } + return ts->time_span; +} + +/* + * lttv_traceset_get_time_span : return a TimeInterval representing the + * minimum timestamp and the maximum timestamp of the traceset. + * + */ +TimeInterval lttv_traceset_get_time_span(LttvTraceset *ts) +{ + if(ltt_time_compare(ts->time_span.start_time, ltt_time_zero) == 0){ + ts->time_span.start_time =ltt_time_from_uint64( + lttv_traceset_get_timestamp_begin(ts)); + ts->time_span.end_time = ltt_time_from_uint64( + lttv_traceset_get_timestamp_end(ts)); + } + return ts->time_span; +} + const char *lttv_traceset_get_name_from_event(LttvEvent *event) { return bt_ctf_event_name(event->bt_event); } + +int set_values_position(const LttvTracesetPosition *pos) +{ + LttvTracesetPosition previous_pos; + previous_pos.iter = pos->iter; + previous_pos.bt_pos = bt_iter_get_pos(bt_ctf_get_iter(pos->iter)); + /* Seek to the new desired position */ + lttv_traceset_seek_to_position(pos); + /*Read the event*/ + struct bt_ctf_event *event = bt_ctf_iter_read_event(pos->iter); + + if(event != NULL){ + ((LttvTracesetPosition *)pos)->timestamp = bt_ctf_get_timestamp(event); + + LttvEvent lttv_event; + lttv_event.bt_event = event; + ((LttvTracesetPosition *)pos)->cpu_id = lttv_traceset_get_cpuid_from_event(<tv_event); + } + else { + /* The event is null */ + return 0; + } + + /* Reassign the previously saved position */ + lttv_traceset_seek_to_position(&previous_pos); + /*We must desallocate because the function bt_iter_get_pos() does a g_new */ + bt_iter_free_pos(previous_pos.bt_pos); + if (pos->timestamp == G_MAXUINT64) { + return 0; + } + return 1; +} + +guint64 lttv_traceset_position_get_timestamp(const LttvTracesetPosition *pos) +{ + if(pos->timestamp == G_MAXUINT64){ + if(set_values_position(pos) == 0){ + return 0; + } + } + + return pos->timestamp; +} + +int lttv_traceset_position_get_cpuid(const LttvTracesetPosition *pos){ + if(pos->cpu_id == INT_MAX ){ + if(set_values_position(pos) == 0){ + return 0; + } + } + return pos->cpu_id; +} + +LttTime lttv_traceset_position_get_time(const LttvTracesetPosition *pos) +{ + return ltt_time_from_uint64(lttv_traceset_position_get_timestamp(pos)); +} + + +/* 0 if equals, other is different */ +int lttv_traceset_position_compare(const LttvTracesetPosition *pos1, const LttvTracesetPosition *pos2) +{ +#warning " TODO :Rename for lttv_traceset_position_equals && Must return COMPARAISON OF THE 2 POSITION && verify if it is the best way to compare position" + if(pos1 == NULL || pos2 == NULL){ + return -1; + } + + int res = -1; +#ifdef HAVE_BT_ITER_EQUALS_POS + if(pos1->timestamp == G_MAXUINT64 || pos2->timestamp == G_MAXUINT64) { + res = bt_iter_equals_pos(pos1->bt_pos, pos2->bt_pos); + } +#endif + if (res < 0) { + + guint64 timeStampPos1,timeStampPos2; + guint cpuId1, cpuId2; + + timeStampPos1 = lttv_traceset_position_get_timestamp(pos1); + timeStampPos2 = lttv_traceset_position_get_timestamp(pos2); + + if (timeStampPos1 == timeStampPos2) { + + cpuId1 = lttv_traceset_position_get_cpuid(pos1); + cpuId2 = lttv_traceset_position_get_cpuid(pos2); + + if(cpuId1 == cpuId2){ + return 0; + } + } + return 1; + } else { + + return !res; + } +} + +int lttv_traceset_position_time_compare(const LttvTracesetPosition *pos1, + const LttvTracesetPosition *pos2) +{ + guint64 timeStampPos1,timeStampPos2; + + timeStampPos1 = lttv_traceset_position_get_timestamp(pos1); + timeStampPos2 = lttv_traceset_position_get_timestamp(pos2); + + return timeStampPos1 - timeStampPos2; +} +int lttv_traceset_position_compare_current(const LttvTraceset *ts, + const LttvTracesetPosition *pos) +{ + int result = 0; + LttvTracesetPosition *curPos = lttv_traceset_create_current_position(ts); + + result = lttv_traceset_position_compare(curPos,pos); + + lttv_traceset_destroy_position(curPos); + + return result; +} + +LttTime lttv_traceset_get_current_time(const LttvTraceset *ts) +{ + LttvTracesetPosition *curPos = lttv_traceset_create_current_position(ts); + guint64 currentTimestamp = lttv_traceset_position_get_timestamp(curPos); + lttv_traceset_destroy_position(curPos); + + return ltt_time_from_uint64(currentTimestamp); +}