* Julien Desfossez ([email protected]) wrote:
> From: Francis Deslauriers <[email protected]>
> 

something tells me it does not start from the last patch sent by
Francis, am I correct ? A mixup maybe ?

> Signed-off-by: Francis Deslauriers <[email protected]>
> Signed-off-by: Julien Desfossez <[email protected]>
> ---
>  include/babeltrace/iterator.h |    1 +
>  lib/iterator.c                |  207 
> +++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 208 insertions(+)
> 
> diff --git a/include/babeltrace/iterator.h b/include/babeltrace/iterator.h
> index aa6470e..c8edbd1 100644
> --- a/include/babeltrace/iterator.h
> +++ b/include/babeltrace/iterator.h
> @@ -48,6 +48,7 @@ struct bt_iter_pos {
>               BT_SEEK_CUR,
>               BT_SEEK_BEGIN,
>               BT_SEEK_END,
> +             BT_SEEK_LAST
>       } type;
>       union {
>               uint64_t seek_time;
> diff --git a/lib/iterator.c b/lib/iterator.c
> index f5f413e..16b54bc 100644
> --- a/lib/iterator.c
> +++ b/lib/iterator.c
> @@ -187,6 +187,193 @@ static int seek_ctf_trace_by_timestamp(struct ctf_trace 
> *tin,
>       return found ? 0 : EOF;
>  }
>  
> +int seek_last_element_ctf_file_stream(struct trace_collection *tc,
> +             struct ctf_file_stream **cfs, int max_packet,
> +             int max_stream_id, int max_stream_class_id,
> +             int max_trace_descriptor_id, uint64_t max_timestamp)
> +{
> +     struct trace_descriptor *max_td_read;
> +     struct ctf_trace *max_tin;
> +     struct ctf_stream_declaration *max_stream_class;
> +     struct ctf_stream_definition *max_stream;
> +     struct ctf_stream_pos *max_stream_pos;
> +     int ret;
> +
> +     if (!tc)
> +             return -EINVAL;
> +
> +     /* get the targeted trace descriptor */
> +     max_td_read = g_ptr_array_index(tc->array, max_trace_descriptor_id);
> +     max_tin = container_of(max_td_read, struct ctf_trace, parent);
> +
> +     /* get targeted stream class */
> +     max_stream_class = g_ptr_array_index(max_tin->streams,
> +                                             max_stream_class_id);
> +     /* get targeted stream */
> +     max_stream = g_ptr_array_index(max_stream_class->streams,
> +                                     max_stream_id);
> +     *cfs = container_of(max_stream, struct ctf_file_stream, parent);
> +     max_stream_pos = &(*cfs)->pos;
> +
> +     /* we seek to the last packet of the stream. */
> +     max_stream_pos->packet_seek(&max_stream_pos->parent,
> +                     max_packet, SEEK_SET);
> +     /*
> +      * iterate over all the event until we reach on that
> +      * his timestamp correspond with the max saved previously.
> +      */
> +     do {
> +             ret = stream_read_event(*cfs);
> +     } while ((*cfs)->parent.real_timestamp != max_timestamp && ret == 0);
> +
> +     /* insert the stream in the heap */
> +     return ret;
> +}
> +
> +int find_last_event(struct ctf_file_stream *cfs, uint64_t *timestamp_end,
> +             int *packet)
> +{
> +     struct ctf_stream_pos *stream_pos;
> +     uint64_t tmp = 0;
> +     int ret = 0;
> +     int count = 0;
> +     int event_read = 0;
> +     int i;
> +
> +     if (!cfs)
> +             return -EINVAL;
> +
> +     stream_pos = &cfs->pos;
> +     /*
> +      * we start by the last packet as the current one.
> +      * If the current one is empty we go back one packet if possible.
> +      */
> +     for (i = stream_pos->packet_real_index->len - 1; i >= 0; i--) {
> +             stream_pos->packet_seek(&stream_pos->parent, i, SEEK_SET);
> +             count = 0;
> +             /* read each event until we reach the end of the packet */
> +             do {
> +                     tmp = cfs->parent.real_timestamp;
> +                     ret = stream_read_event(cfs);
> +                     count++;
> +             } while (ret == 0);
> +
> +             if (count > 1)
> +                     event_read = 1;
> +             /*
> +              * Check if we have read at least one event before
> +              * reaching the end of file.
> +              */
> +             if (ret == EOF && count > 1) {
> +                     *timestamp_end = tmp;
> +                     *packet = i;
> +                     break;
> +             }
> +             /* Error */
> +             else if (ret > 0) {
> +                     return ret;
> +             }
> +     }
> +
> +     /* Check if we read at least one event on the stream */
> +     if (!event_read) {
> +             return 1;
> +     }
> +     return 0;
> +}
> +
> +int find_max_timestamp_ctf_file_stream(
> +             struct ctf_stream_declaration *stream_class, int *max_stream_id,
> +             int *packet, uint64_t *max_timestamp, int *new_max)
> +{
> +     struct ctf_file_stream *cfs;
> +     uint64_t savedtime;
> +     int i;
> +     int max_packet = 0;
> +     int ret = 0;
> +     int error = 1;
> +
> +     for (i = 0; i < stream_class->streams->len; i++) {
> +             struct ctf_stream_definition *stream;
> +
> +             stream = g_ptr_array_index(stream_class->streams, i);
> +             if (!stream)
> +                     continue;
> +             cfs = container_of(stream, struct ctf_file_stream, parent);
> +             ret = find_last_event(cfs, &savedtime, &max_packet);
> +             /* Can return either EOF, 0, or error (> 0). */
> +             if (ret == 0 && savedtime >= *max_timestamp) {
> +                     *new_max = 1;
> +                     *max_stream_id = i;
> +                     *packet = max_packet;
> +                     *max_timestamp = savedtime;
> +             }
> +             error = error & ret;
> +     }
> +
> +     return error;
> +}
> +
> +int seek_last_ctf_file_stream(struct trace_collection *tc,
> +                             struct ctf_file_stream **cfs)
> +{
> +     uint64_t max_timestamp = 0;
> +     int i, j;
> +     int ret;
> +     int found = 0;
> +     int new_max_found;
> +     int max_packet;
> +     int max_stream_id;
> +     int max_stream_class_id;
> +     int max_trace_descriptor_id;
> +
> +     if (!tc)
> +             return -EINVAL;
> +
> +     /* For each trace in the trace_collection */
> +     for (i = 0; i < tc->array->len; i++) {
> +             struct ctf_trace *tin;
> +             struct trace_descriptor *td_read;
> +
> +             td_read = g_ptr_array_index(tc->array, i);
> +             if (!td_read)
> +                     continue;
> +             tin = container_of(td_read, struct ctf_trace, parent);
> +             /* For each stream_class in the trace */
> +             for (j = 0; j < tin->streams->len; j++) {
> +                     struct ctf_stream_declaration *stream_class;
> +
> +                     stream_class = g_ptr_array_index(tin->streams, j);
> +                     if (!stream_class)
> +                             continue;
> +                     /* For each file_stream in the stream_class */
> +                     new_max_found = 0;
> +                     ret = find_max_timestamp_ctf_file_stream(stream_class,
> +                                     &max_stream_id, &max_packet,
> +                                     &max_timestamp, &new_max_found);
> +                     if (!ret && new_max_found) {
> +                             found = 1;
> +                             max_trace_descriptor_id = i;
> +                             max_stream_class_id = j;
> +                     }
> +             }
> +     }
> +     /*
> +      * Now we know in which trace, stream_class and stream is the
> +      * last event of the trace_collection.
> +      * We can seek to this targeted event.
> +      */
> +     if (!found) {
> +             ret = -1;
> +     } else {
> +             ret = seek_last_element_ctf_file_stream(tc, cfs, max_packet,
> +                             max_stream_id, max_stream_class_id,
> +                             max_trace_descriptor_id, max_timestamp);
> +     }
> +
> +     return ret;
> +}
> +
>  int bt_iter_set_pos(struct bt_iter *iter, const struct bt_iter_pos *iter_pos)
>  {
>       struct trace_collection *tc;
> @@ -329,6 +516,26 @@ int bt_iter_set_pos(struct bt_iter *iter, const struct 
> bt_iter_pos *iter_pos)
>                       }
>               }
>               break;
> +     case BT_SEEK_LAST:
> +     {
> +             struct ctf_file_stream *cfs;
> +
> +             tc = iter->ctx->tc;
> +             ret = seek_last_ctf_file_stream(tc, &cfs);
> +             if (ret < 0)
> +                     goto error;
> +
> +             /* remove all stream from the heap*/
> +             heap_free(iter->stream_heap);
> +             /* Create a new empty heap*/
> +             ret = heap_init(iter->stream_heap, 0, stream_compare);
> +             if (ret < 0)
> +                     goto error;
> +             /*Insert the stream that contains the last event.*/
> +             heap_insert(iter->stream_heap, cfs);
> +
> +             return 0;
> +     }
>       default:
>               /* not implemented */
>               return -EINVAL;
> -- 
> 1.7.10.4
> 

-- 
Mathieu Desnoyers
Operating System Efficiency R&D Consultant
EfficiOS Inc.
http://www.efficios.com

_______________________________________________
lttng-dev mailing list
[email protected]
http://lists.lttng.org/cgi-bin/mailman/listinfo/lttng-dev

Reply via email to