Fix: CTF writer: validate and set `timestamp_begin`/`timestamp_end`
authorPhilippe Proulx <eeppeliteloop@gmail.com>
Tue, 13 Feb 2018 22:19:00 +0000 (17:19 -0500)
committerPhilippe Proulx <eeppeliteloop@gmail.com>
Thu, 2 May 2019 03:32:03 +0000 (23:32 -0400)
commit2a03740bf75dfb7284e1984586d8f2da6722b236
tree7b8d650cc151a0b38884e1234c28704d8181a5b5
parent2e8876d36d8df5011071725df6a2f80861817434
Fix: CTF writer: validate and set `timestamp_begin`/`timestamp_end`

Issue
=====
A CTF writer stream's packet context's `timestamp_begin` and
`timestamp_end` fields are not correctly automatically set and not
validated. There are many issues:

1. There's no validation that the `timestamp_begin` value of flushed
   packet N is greater than or equal to the `timestamp_end` value of
   packet (N - 1).

2. The automatic values are the event header's `timestamp` field of the
   first appended event for `timestamp_begin` and of the last appended
   event for `timestamp_end`. A field updating the stream's clock could
   exist in the payload of the last appended event, for example, making
   the automatic `timestamp_end` value too small.

   Also, the current code does not consider mapped integer fields with a
   size which is less than the size of the `timestamp_begin` field. In
   this case, the CTF clock update mechanism must be used.

3. Because of 2., a CTF writer stream cannot flush an empty packet (no
   appended events) without providing `timestamp_begin` and
   `timestamp_end` because there's no event to extract the automatic
   values.

4. There's no validation that `timestamp_end` is greater than or equal
   to `timestamp_begin`.

Solution
========
When flushing a CTF writer stream:

1. Set the initial packet's timestamp to one of:

   * The value of `timestamp_begin`, if the field is set.
   * The previous packet's last timestamp, if available. The stream
     object contains this value. It's not available before the first
     flush.
   * Zero.

2. Set the current clock value to the value computed in 1. It is correct
   to have a single current clock value because the library guarantees
   that a given stream class contains at most a single clock class.

3. Visit all the fields of the packet context (except the special fields
   which could not be set at this point), and then all the fields of all
   the appended events, in order, to update the current clock value.
   Apply the CTF clock update mechanism to handle updating fields which
   have a wrapping value.

4. If `timestamp_end` is set, validate that its value is greater than
   or equal to the computed current clock value. This is a validation
   step.

5. If `timestamp_end` is not set, set it to the current clock value.

6. If `timestamp_begin` is not set, set it to the initial timestamp.

7. Set the stream's last final timestamp to the value of
   `timestamp_end`.

Those steps perform validation and automatic field value setting at the
same time.

Known drawbacks
===============
This solution makes the stream flushing process slower. However, there's
room for optimization. For example, there's no need to visit all the
fields: we just need to visit the fields which are mapped to a clock
class. Moreover, if all the types of the mapped fields have a size which
is at least the size of the `timestamp_begin` field, then there's no
need to visit them at all: we can use the last event's last mapped
field's value directly because the mapped fields always overwriting the
current clock value anyway.

Tests for the `succeed/lttng-modules-2.0-pre5` trace are removed because
this solution reveals an invalid trace: the `timestamp_begin` value of
the second packet in `channel0_5` is less than the `timestamp_end` value
of the first packet. This was produced by the LTTng-modules 2.0-pre5
tracer, so it can be considered an invalid trace as per CTF.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
12 files changed:
include/babeltrace/ctf-ir/stream-internal.h
lib/ctf-ir/stream.c
tests/bindings/python/babeltrace/test_ctf_writer_empty_packet.py
tests/ctf-traces/succeed/lttng-modules-2.0-pre5/channel0_0 [deleted file]
tests/ctf-traces/succeed/lttng-modules-2.0-pre5/channel0_1 [deleted file]
tests/ctf-traces/succeed/lttng-modules-2.0-pre5/channel0_2 [deleted file]
tests/ctf-traces/succeed/lttng-modules-2.0-pre5/channel0_3 [deleted file]
tests/ctf-traces/succeed/lttng-modules-2.0-pre5/channel0_4 [deleted file]
tests/ctf-traces/succeed/lttng-modules-2.0-pre5/channel0_5 [deleted file]
tests/ctf-traces/succeed/lttng-modules-2.0-pre5/channel0_6 [deleted file]
tests/ctf-traces/succeed/lttng-modules-2.0-pre5/channel0_7 [deleted file]
tests/ctf-traces/succeed/lttng-modules-2.0-pre5/metadata [deleted file]
This page took 0.025764 seconds and 4 git commands to generate.