Automatically generate discarded packets/events notifications
authorPhilippe Proulx <eeppeliteloop@gmail.com>
Thu, 22 Jun 2017 15:20:29 +0000 (11:20 -0400)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Thu, 6 Jul 2017 20:17:53 +0000 (16:17 -0400)
This patch adds discarded packets and events notifications. Those
notifications are automatically generated by each notification iterator
by looking at packet header (PH) field's `packet_seq_num` and packet
context (PC) field's `events_discarded` fields to keep track of the
current state. Automatically generating those notifications, and
forbidding the user to create them, allows them to always be
synchronized with the values of the PH and PC special fields, and
guarantees to the user that they are generated whenever there is a
change in those values.

Each notification contains a count, an optional beginning clock value,
and an optional ending clock value, as well as a stream in which the
elements are discarded by the tracer.

As of this patch, flt.utils.trimmer does not reset the value of its
copied `packet_seq_num` and `events_discarded` fields to 0, and this is
probably a bug because a notification iterator on an flt.utils.trimmer
component can see discarded packets or events notifications before the
first packet beginning notification (which should not be the case if we
consider that a trimmed stream should act like a stream which originally
had those time bounds).

The sink.text.pretty component does not do anything specific with those
new notifications yet, but they are expected to be used to replicate
Babeltrace 1's behaviour (printing warnings).

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
13 files changed:
include/Makefile.am
include/babeltrace/babeltrace.h
include/babeltrace/graph/notification-discarded-elements-internal.h [new file with mode: 0644]
include/babeltrace/graph/notification-discarded-events.h [new file with mode: 0644]
include/babeltrace/graph/notification-discarded-packets.h [new file with mode: 0644]
include/babeltrace/graph/notification-internal.h
include/babeltrace/graph/notification-iterator-internal.h
include/babeltrace/graph/notification.h
lib/graph/iterator.c
lib/graph/notification/Makefile.am
lib/graph/notification/discarded-elements.c [new file with mode: 0644]
lib/graph/notification/discarded-events.c [new file with mode: 0644]
lib/graph/notification/discarded-packets.c [new file with mode: 0644]

index aeb7cdd8aa8a2e98f757334afcdc91b146e3c063..387ab5e6c8a84a3351a4bcc5ca41cd6789f1cfc5 100644 (file)
@@ -55,6 +55,8 @@ babeltracegraphinclude_HEADERS = \
        babeltrace/graph/component.h \
        babeltrace/graph/connection.h \
        babeltrace/graph/graph.h \
+       babeltrace/graph/notification-discarded-events.h \
+       babeltrace/graph/notification-discarded-packets.h \
        babeltrace/graph/notification-event.h \
        babeltrace/graph/notification-heap.h \
        babeltrace/graph/notification-inactivity.h \
@@ -118,6 +120,7 @@ noinst_HEADERS = \
        babeltrace/graph/component-source-internal.h \
        babeltrace/graph/connection-internal.h \
        babeltrace/graph/graph-internal.h \
+       babeltrace/graph/notification-discarded-elements-internal.h \
        babeltrace/graph/notification-event-internal.h \
        babeltrace/graph/notification-heap-internal.h \
        babeltrace/graph/notification-inactivity-internal.h \
index 36f1b3839c94c68c974b1654298ef730eb9f7255..7aad9b1c5a75274b6a71c28eb5263ed53a08e48f 100644 (file)
@@ -75,6 +75,8 @@
 #include <babeltrace/graph/component.h>
 #include <babeltrace/graph/connection.h>
 #include <babeltrace/graph/graph.h>
+#include <babeltrace/graph/notification-discarded-events.h>
+#include <babeltrace/graph/notification-discarded-packets.h>
 #include <babeltrace/graph/notification-event.h>
 #include <babeltrace/graph/notification-heap.h>
 #include <babeltrace/graph/notification-inactivity.h>
diff --git a/include/babeltrace/graph/notification-discarded-elements-internal.h b/include/babeltrace/graph/notification-discarded-elements-internal.h
new file mode 100644 (file)
index 0000000..1a339ab
--- /dev/null
@@ -0,0 +1,85 @@
+#ifndef BABELTRACE_COMPONENT_NOTIFICATION_DISCARDED_ELEMENTS_INTERNAL_H
+#define BABELTRACE_COMPONENT_NOTIFICATION_DISCARDED_ELEMENTS_INTERNAL_H
+
+/*
+ * Copyright 2017 Philippe Proulx <pproulx@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <glib.h>
+#include <stdint.h>
+#include <babeltrace/compiler-internal.h>
+#include <babeltrace/graph/notification.h>
+#include <babeltrace/graph/notification-internal.h>
+
+struct bt_clock_class_priority_map;
+struct bt_ctf_stream;
+
+struct bt_notification_discarded_elements {
+       struct bt_notification parent;
+       struct bt_ctf_stream *stream;
+       struct bt_ctf_clock_value *begin_clock_value;
+       struct bt_ctf_clock_value *end_clock_value;
+       int64_t count;
+};
+
+BT_HIDDEN
+struct bt_notification *bt_notification_discarded_elements_create(
+               enum bt_notification_type type,
+               struct bt_ctf_stream *stream,
+               struct bt_ctf_clock_value *begin_clock_value,
+               struct bt_ctf_clock_value *end_clock_value,
+               uint64_t count);
+
+BT_HIDDEN
+struct bt_ctf_stream *bt_notification_discarded_elements_get_stream(
+               enum bt_notification_type type,
+               struct bt_notification *notification);
+
+BT_HIDDEN
+struct bt_ctf_clock_value *
+bt_notification_discarded_elements_get_begin_clock_value(
+               enum bt_notification_type type,
+               struct bt_notification *notification);
+
+BT_HIDDEN
+struct bt_ctf_clock_value *
+bt_notification_discarded_elements_get_end_clock_value(
+               enum bt_notification_type type,
+               struct bt_notification *notification);
+
+BT_HIDDEN
+int64_t bt_notification_discarded_elements_get_count(
+               enum bt_notification_type type,
+               struct bt_notification *notification);
+
+static inline
+struct bt_ctf_stream *bt_notification_discarded_elements_borrow_stream(
+               struct bt_notification *notification)
+{
+       struct bt_notification_discarded_elements *discarded_elems_notif;
+
+       assert(notification);
+       discarded_elems_notif = container_of(notification,
+                       struct bt_notification_discarded_elements, parent);
+       return discarded_elems_notif->stream;
+}
+
+#endif /* BABELTRACE_COMPONENT_NOTIFICATION_DISCARDED_ELEMENTS_INTERNAL_H */
diff --git a/include/babeltrace/graph/notification-discarded-events.h b/include/babeltrace/graph/notification-discarded-events.h
new file mode 100644 (file)
index 0000000..91151e4
--- /dev/null
@@ -0,0 +1,59 @@
+#ifndef BABELTRACE_GRAPH_NOTIFICATION_DISCARDED_EVENTS_H
+#define BABELTRACE_GRAPH_NOTIFICATION_DISCARDED_EVENTS_H
+
+/*
+ * Copyright 2017 Philippe Proulx <pproulx@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct bt_notification;
+struct bt_clock_class_priority_map;
+struct bt_ctf_clock_class;
+struct bt_ctf_stream;
+
+extern struct bt_ctf_clock_value *
+bt_notification_discarded_events_get_begin_clock_value(
+               struct bt_notification *notification);
+
+extern struct bt_ctf_clock_value *
+bt_notification_discarded_events_get_end_clock_value(
+               struct bt_notification *notification);
+
+extern int bt_notification_discarded_events_set_count(
+               struct bt_notification *notification,
+               uint64_t count);
+
+extern int64_t bt_notification_discarded_events_get_count(
+               struct bt_notification *notification);
+
+extern struct bt_ctf_stream *bt_notification_discarded_events_get_stream(
+               struct bt_notification *notification);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BABELTRACE_GRAPH_NOTIFICATION_DISCARDED_EVENTS_H */
diff --git a/include/babeltrace/graph/notification-discarded-packets.h b/include/babeltrace/graph/notification-discarded-packets.h
new file mode 100644 (file)
index 0000000..4460081
--- /dev/null
@@ -0,0 +1,59 @@
+#ifndef BABELTRACE_GRAPH_NOTIFICATION_DISCARDED_PACKETS_H
+#define BABELTRACE_GRAPH_NOTIFICATION_DISCARDED_PACKETS_H
+
+/*
+ * Copyright 2017 Philippe Proulx <pproulx@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct bt_notification;
+struct bt_clock_class_priority_map;
+struct bt_ctf_clock_class;
+struct bt_ctf_stream;
+
+extern struct bt_ctf_clock_value *
+bt_notification_discarded_packets_get_begin_clock_value(
+               struct bt_notification *notification);
+
+extern struct bt_ctf_clock_value *
+bt_notification_discarded_packets_get_end_clock_value(
+               struct bt_notification *notification);
+
+extern int bt_notification_discarded_packets_set_count(
+               struct bt_notification *notification,
+               uint64_t count);
+
+extern int64_t bt_notification_discarded_packets_get_count(
+               struct bt_notification *notification);
+
+extern struct bt_ctf_stream *bt_notification_discarded_packets_get_stream(
+               struct bt_notification *notification);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BABELTRACE_GRAPH_NOTIFICATION_DISCARDED_PACKETS_H */
index 00a8c7eeb7e9e148e0c5fd7915d916c6722cc239..4ffef1c504e3ec145ed3716fcf8229f84e5ade80 100644 (file)
@@ -76,6 +76,10 @@ const char *bt_notification_type_string(enum bt_notification_type type)
                return "BT_NOTIFICATION_TYPE_PACKET_BEGIN";
        case BT_NOTIFICATION_TYPE_PACKET_END:
                return "BT_NOTIFICATION_TYPE_PACKET_END";
+       case BT_NOTIFICATION_TYPE_DISCARDED_EVENTS:
+               return "BT_NOTIFICATION_TYPE_DISCARDED_EVENTS";
+       case BT_NOTIFICATION_TYPE_DISCARDED_PACKETS:
+               return "BT_NOTIFICATION_TYPE_DISCARDED_PACKETS";
        default:
                return "(unknown)";
        }
index b7aafe0160f0927a503b947c71cd5623ed0b66d4..9fcab16af8d59a4117ce730ebe3e6ab8d44c2eeb 100644 (file)
@@ -44,6 +44,8 @@ enum bt_notification_iterator_notif_type {
        BT_NOTIFICATION_ITERATOR_NOTIF_TYPE_STREAM_END =        (1U << 3),
        BT_NOTIFICATION_ITERATOR_NOTIF_TYPE_PACKET_BEGIN =      (1U << 4),
        BT_NOTIFICATION_ITERATOR_NOTIF_TYPE_PACKET_END =        (1U << 5),
+       BT_NOTIFICATION_ITERATOR_NOTIF_TYPE_DISCARDED_EVENTS =  (1U << 6),
+       BT_NOTIFICATION_ITERATOR_NOTIF_TYPE_DISCARDED_PACKETS = (1U << 7),
 };
 
 enum bt_notification_iterator_state {
index 926c019fc65e9d45dc3e21ae84e8246ed6f8bf6e..b64d40ad29c76a0ac53899c85b88dcfa53178d12 100644 (file)
@@ -37,15 +37,17 @@ struct bt_notification;
  * Notification types. Unhandled notification types should be ignored.
  */
 enum bt_notification_type {
-       BT_NOTIFICATION_TYPE_SENTINEL =         -1000,
-       BT_NOTIFICATION_TYPE_UNKNOWN =          -1,
-       BT_NOTIFICATION_TYPE_ALL =              -2,
-       BT_NOTIFICATION_TYPE_EVENT =            0,
-       BT_NOTIFICATION_TYPE_INACTIVITY =       1,
-       BT_NOTIFICATION_TYPE_STREAM_BEGIN =     2,
-       BT_NOTIFICATION_TYPE_STREAM_END =       3,
-       BT_NOTIFICATION_TYPE_PACKET_BEGIN =     4,
-       BT_NOTIFICATION_TYPE_PACKET_END =       5,
+       BT_NOTIFICATION_TYPE_SENTINEL =                 -1000,
+       BT_NOTIFICATION_TYPE_UNKNOWN =                  -1,
+       BT_NOTIFICATION_TYPE_ALL =                      -2,
+       BT_NOTIFICATION_TYPE_EVENT =                    0,
+       BT_NOTIFICATION_TYPE_INACTIVITY =               1,
+       BT_NOTIFICATION_TYPE_STREAM_BEGIN =             2,
+       BT_NOTIFICATION_TYPE_STREAM_END =               3,
+       BT_NOTIFICATION_TYPE_PACKET_BEGIN =             4,
+       BT_NOTIFICATION_TYPE_PACKET_END =               5,
+       BT_NOTIFICATION_TYPE_DISCARDED_EVENTS =         6,
+       BT_NOTIFICATION_TYPE_DISCARDED_PACKETS =        7,
        BT_NOTIFICATION_TYPE_NR, /* Not part of ABI. */
 };
 
index 87fe6376309de579986cc9422e12cf66a0c3f8fc..9cc3fbecbe2ebbbe0f4bf69eb1adf6cf0031a441 100644 (file)
@@ -30,6 +30,9 @@
 
 #include <babeltrace/compiler-internal.h>
 #include <babeltrace/ref.h>
+#include <babeltrace/ctf-ir/fields.h>
+#include <babeltrace/ctf-ir/field-types.h>
+#include <babeltrace/ctf-ir/field-types-internal.h>
 #include <babeltrace/ctf-ir/event-internal.h>
 #include <babeltrace/ctf-ir/packet-internal.h>
 #include <babeltrace/ctf-ir/stream-internal.h>
 #include <babeltrace/graph/notification-packet-internal.h>
 #include <babeltrace/graph/notification-stream.h>
 #include <babeltrace/graph/notification-stream-internal.h>
+#include <babeltrace/graph/notification-discarded-elements-internal.h>
 #include <babeltrace/graph/port.h>
 #include <babeltrace/types.h>
 #include <stdint.h>
+#include <inttypes.h>
 #include <stdlib.h>
 
+struct discarded_elements_state {
+       struct bt_ctf_clock_value *cur_begin;
+       uint64_t cur_count;
+};
+
 struct stream_state {
        struct bt_ctf_stream *stream; /* owned by this */
        struct bt_ctf_packet *cur_packet; /* owned by this */
+       struct discarded_elements_state discarded_packets_state;
+       struct discarded_elements_state discarded_events_state;
        bt_bool is_ended;
 };
 
@@ -65,6 +77,8 @@ enum action_type {
        ACTION_TYPE_ADD_STREAM_STATE,
        ACTION_TYPE_SET_STREAM_STATE_IS_ENDED,
        ACTION_TYPE_SET_STREAM_STATE_CUR_PACKET,
+       ACTION_TYPE_UPDATE_STREAM_STATE_DISCARDED_PACKETS,
+       ACTION_TYPE_UPDATE_STREAM_STATE_DISCARDED_EVENTS,
 };
 
 struct action {
@@ -98,6 +112,14 @@ struct action {
                        struct stream_state *stream_state; /* weak */
                        struct bt_ctf_packet *packet; /* owned by this */
                } set_stream_state_cur_packet;
+
+               /* ACTION_TYPE_UPDATE_STREAM_STATE_DISCARDED_PACKETS */
+               /* ACTION_TYPE_UPDATE_STREAM_STATE_DISCARDED_EVENTS */
+               struct {
+                       struct stream_state *stream_state; /* weak */
+                       struct bt_ctf_clock_value *cur_begin; /* owned by this */
+                       uint64_t cur_count;
+               } update_stream_state_discarded_elements;
        } payload;
 };
 
@@ -122,6 +144,8 @@ void destroy_stream_state(struct stream_state *stream_state)
        bt_put(stream_state->cur_packet);
        BT_LOGV_STR("Putting stream state's stream.");
        bt_put(stream_state->stream);
+       bt_put(stream_state->discarded_packets_state.cur_begin);
+       bt_put(stream_state->discarded_events_state.cur_begin);
        g_free(stream_state);
 }
 
@@ -150,7 +174,12 @@ void destroy_action(struct action *action)
                break;
        case ACTION_TYPE_SET_STREAM_STATE_IS_ENDED:
                break;
+       case ACTION_TYPE_UPDATE_STREAM_STATE_DISCARDED_PACKETS:
+       case ACTION_TYPE_UPDATE_STREAM_STATE_DISCARDED_EVENTS:
+               BT_PUT(action->payload.update_stream_state_discarded_elements.cur_begin);
+               break;
        default:
+               BT_LOGF("Unexpected action's type: type=%d", action->type);
                abort();
        }
 }
@@ -191,6 +220,10 @@ const char *action_type_string(enum action_type type)
                return "ACTION_TYPE_SET_STREAM_STATE_IS_ENDED";
        case ACTION_TYPE_SET_STREAM_STATE_CUR_PACKET:
                return "ACTION_TYPE_SET_STREAM_STATE_CUR_PACKET";
+       case ACTION_TYPE_UPDATE_STREAM_STATE_DISCARDED_PACKETS:
+               return "ACTION_TYPE_UPDATE_STREAM_STATE_DISCARDED_PACKETS";
+       case ACTION_TYPE_UPDATE_STREAM_STATE_DISCARDED_EVENTS:
+               return "ACTION_TYPE_UPDATE_STREAM_STATE_DISCARDED_EVENTS";
        default:
                return "(unknown)";
        }
@@ -262,7 +295,25 @@ void apply_actions(struct bt_notification_iterator *iterator)
                        BT_MOVE(action->payload.set_stream_state_cur_packet.stream_state->cur_packet,
                                action->payload.set_stream_state_cur_packet.packet);
                        break;
+               case ACTION_TYPE_UPDATE_STREAM_STATE_DISCARDED_PACKETS:
+               case ACTION_TYPE_UPDATE_STREAM_STATE_DISCARDED_EVENTS:
+               {
+                       struct discarded_elements_state *state;
+
+                       if (action->type == ACTION_TYPE_UPDATE_STREAM_STATE_DISCARDED_PACKETS) {
+                               state = &action->payload.update_stream_state_discarded_elements.stream_state->discarded_packets_state;
+                       } else {
+                               state = &action->payload.update_stream_state_discarded_elements.stream_state->discarded_events_state;
+                       }
+
+                       BT_MOVE(state->cur_begin,
+                               action->payload.update_stream_state_discarded_elements.cur_begin);
+                       state->cur_count = action->payload.update_stream_state_discarded_elements.cur_count;
+                       break;
+               }
                default:
+                       BT_LOGF("Unexpected action's type: type=%d",
+                               action->type);
                        abort();
                }
        }
@@ -478,7 +529,9 @@ int create_subscription_mask_from_notification_types(
                                BT_NOTIFICATION_ITERATOR_NOTIF_TYPE_STREAM_BEGIN |
                                BT_NOTIFICATION_ITERATOR_NOTIF_TYPE_STREAM_END |
                                BT_NOTIFICATION_ITERATOR_NOTIF_TYPE_PACKET_BEGIN |
-                               BT_NOTIFICATION_ITERATOR_NOTIF_TYPE_PACKET_END;
+                               BT_NOTIFICATION_ITERATOR_NOTIF_TYPE_PACKET_END |
+                               BT_NOTIFICATION_ITERATOR_NOTIF_TYPE_DISCARDED_EVENTS |
+                               BT_NOTIFICATION_ITERATOR_NOTIF_TYPE_DISCARDED_PACKETS;
                        break;
                case BT_NOTIFICATION_TYPE_EVENT:
                        iterator->subscription_mask |= BT_NOTIFICATION_ITERATOR_NOTIF_TYPE_EVENT;
@@ -498,6 +551,12 @@ int create_subscription_mask_from_notification_types(
                case BT_NOTIFICATION_TYPE_PACKET_END:
                        iterator->subscription_mask |= BT_NOTIFICATION_ITERATOR_NOTIF_TYPE_PACKET_END;
                        break;
+               case BT_NOTIFICATION_TYPE_DISCARDED_EVENTS:
+                       iterator->subscription_mask |= BT_NOTIFICATION_ITERATOR_NOTIF_TYPE_DISCARDED_EVENTS;
+                       break;
+               case BT_NOTIFICATION_TYPE_DISCARDED_PACKETS:
+                       iterator->subscription_mask |= BT_NOTIFICATION_ITERATOR_NOTIF_TYPE_DISCARDED_PACKETS;
+                       break;
                default:
                        ret = -1;
                        goto end;
@@ -674,6 +733,12 @@ bt_notification_iterator_notif_type_from_notif_type(
        case BT_NOTIFICATION_TYPE_PACKET_END:
                iter_notif_type = BT_NOTIFICATION_ITERATOR_NOTIF_TYPE_PACKET_END;
                break;
+       case BT_NOTIFICATION_TYPE_DISCARDED_EVENTS:
+               iter_notif_type = BT_NOTIFICATION_ITERATOR_NOTIF_TYPE_DISCARDED_EVENTS;
+               break;
+       case BT_NOTIFICATION_TYPE_DISCARDED_PACKETS:
+               iter_notif_type = BT_NOTIFICATION_ITERATOR_NOTIF_TYPE_DISCARDED_PACKETS;
+               break;
        default:
                abort();
        }
@@ -1015,6 +1080,38 @@ void add_action_set_stream_state_cur_packet(
                stream_state, packet);
 }
 
+static
+void add_action_update_stream_state_discarded_elements(
+               struct bt_notification_iterator *iterator,
+               enum action_type type,
+               struct stream_state *stream_state,
+               struct bt_ctf_clock_value *cur_begin,
+               uint64_t cur_count)
+{
+       struct action action = {
+               .type = type,
+               .payload.update_stream_state_discarded_elements = {
+                       .stream_state = stream_state,
+                       .cur_begin = bt_get(cur_begin),
+                       .cur_count = cur_count,
+               },
+       };
+
+       assert(stream_state);
+       assert(type == ACTION_TYPE_UPDATE_STREAM_STATE_DISCARDED_PACKETS ||
+                       type == ACTION_TYPE_UPDATE_STREAM_STATE_DISCARDED_EVENTS);
+       add_action(iterator, &action);
+       if (type == ACTION_TYPE_UPDATE_STREAM_STATE_DISCARDED_PACKETS) {
+               BT_LOGV("Added \"update stream state's discarded packets\" action: "
+                       "stream-state-addr=%p, cur-begin-addr=%p, cur-count=%" PRIu64,
+                       stream_state, cur_begin, cur_count);
+       } else if (type == ACTION_TYPE_UPDATE_STREAM_STATE_DISCARDED_EVENTS) {
+               BT_LOGV("Added \"update stream state's discarded events\" action: "
+                       "stream-state-addr=%p, cur-begin-addr=%p, cur-count=%" PRIu64,
+                       stream_state, cur_begin, cur_count);
+       }
+}
+
 static
 int ensure_stream_state_exists(struct bt_notification_iterator *iterator,
                struct bt_notification *stream_begin_notif,
@@ -1079,6 +1176,377 @@ end:
        return ret;
 }
 
+static
+struct bt_ctf_field *get_struct_field_uint(struct bt_ctf_field *struct_field,
+               const char *field_name)
+{
+       struct bt_ctf_field *field = NULL;
+       struct bt_ctf_field_type *ft = NULL;
+
+       field = bt_ctf_field_structure_get_field_by_name(struct_field,
+               field_name);
+       if (!field) {
+               BT_LOGV_STR("`%s` field does not exist.");
+               goto end;
+       }
+
+       if (!bt_ctf_field_is_integer(field)) {
+               BT_LOGV("Skipping `%s` field because its type is not an integer field type: "
+                       "field-addr=%p, ft-addr=%p, ft-id=%s", field_name,
+                       field, ft, bt_ctf_field_type_id_string(
+                               bt_ctf_field_type_get_type_id(ft)));
+               BT_PUT(field);
+               goto end;
+       }
+
+       ft = bt_ctf_field_get_type(field);
+       assert(ft);
+
+       if (bt_ctf_field_type_integer_is_signed(ft)) {
+               BT_LOGV("Skipping `%s` integer field because its type is signed: "
+                       "field-addr=%p, ft-addr=%p", field_name, field, ft);
+               BT_PUT(field);
+               goto end;
+       }
+
+end:
+       bt_put(ft);
+       return field;
+}
+
+static
+uint64_t get_packet_context_events_discarded(struct bt_ctf_packet *packet)
+{
+       struct bt_ctf_field *packet_context = NULL;
+       struct bt_ctf_field *field = NULL;
+       uint64_t retval = -1ULL;
+       int ret;
+
+       packet_context = bt_ctf_packet_get_context(packet);
+       if (!packet_context) {
+               goto end;
+       }
+
+       field = get_struct_field_uint(packet_context, "events_discarded");
+       if (!field) {
+               BT_LOGV("`events_discarded` field does not exist in packet's context field: "
+                       "packet-addr=%p, packet-context-field-addr=%p",
+                       packet, packet_context);
+               goto end;
+       }
+
+       assert(bt_ctf_field_is_integer(field));
+       ret = bt_ctf_field_unsigned_integer_get_value(field, &retval);
+       if (ret) {
+               BT_LOGV("Cannot get raw value of packet's context field's `events_discarded` integer field: "
+                       "packet-addr=%p, field-addr=%p",
+                       packet, field);
+               retval = -1ULL;
+               goto end;
+       }
+
+end:
+       bt_put(packet_context);
+       bt_put(field);
+       return retval;
+}
+
+static
+uint64_t get_packet_header_packet_seq_num(struct bt_ctf_packet *packet)
+{
+       struct bt_ctf_field *packet_header = NULL;
+       struct bt_ctf_field *field = NULL;
+       uint64_t retval = -1ULL;
+       int ret;
+
+       packet_header = bt_ctf_packet_get_header(packet);
+       if (!packet_header) {
+               goto end;
+       }
+
+       field = get_struct_field_uint(packet_header, "packet_seq_num");
+       if (!field) {
+               BT_LOGV("`packet_seq_num` field does not exist in packet's header field: "
+                       "packet-addr=%p, packet-header-field-addr=%p",
+                       packet, packet_header);
+               goto end;
+       }
+
+       assert(bt_ctf_field_is_integer(field));
+       ret = bt_ctf_field_unsigned_integer_get_value(field, &retval);
+       if (ret) {
+               BT_LOGV("Cannot get raw value of packet's header field's `packet_seq_num` integer field: "
+                       "packet-addr=%p, field-addr=%p",
+                       packet, field);
+               retval = -1ULL;
+               goto end;
+       }
+
+end:
+       bt_put(packet_header);
+       bt_put(field);
+       return retval;
+}
+
+static
+int handle_discarded_packets(struct bt_notification_iterator *iterator,
+               struct bt_ctf_packet *packet,
+               struct bt_ctf_clock_value *ts_begin,
+               struct bt_ctf_clock_value *ts_end,
+               struct stream_state *stream_state)
+{
+       struct bt_notification *notif = NULL;
+       uint64_t diff;
+       uint64_t next_count;
+       int ret = 0;
+
+       next_count = get_packet_header_packet_seq_num(packet);
+       if (next_count == -1ULL) {
+               next_count = stream_state->discarded_packets_state.cur_count;
+               goto update_state;
+       }
+
+       if (next_count < stream_state->discarded_packets_state.cur_count) {
+               BT_LOGW("Current value of packet's header field's `packet_seq_num` field is lesser than the previous value for the same stream: "
+                       "not updating the stream state's current value: "
+                       "packet-addr=%p, prev-count=%" PRIu64 ", "
+                       "cur-count=%" PRIu64,
+                       packet, stream_state->discarded_packets_state.cur_count,
+                       next_count);
+               goto end;
+       }
+
+       diff = next_count - stream_state->discarded_packets_state.cur_count;
+       if (diff > 0) {
+               /*
+                * Add a discarded packets notification. The packets
+                * are considered to be lost betweem the state's last time
+                * and the current packet's beginning time.
+                */
+               notif = bt_notification_discarded_elements_create(
+                       BT_NOTIFICATION_TYPE_DISCARDED_PACKETS,
+                       stream_state->stream,
+                       stream_state->discarded_packets_state.cur_begin,
+                       ts_begin, diff);
+               if (!notif) {
+                       BT_LOGE_STR("Cannot create discarded packets notification.");
+                       ret = -1;
+                       goto end;
+               }
+
+               add_action_push_notif(iterator, notif);
+       }
+
+update_state:
+       add_action_update_stream_state_discarded_elements(iterator,
+               ACTION_TYPE_UPDATE_STREAM_STATE_DISCARDED_PACKETS,
+               stream_state, ts_end, next_count);
+
+end:
+       bt_put(notif);
+       return ret;
+}
+
+static
+int handle_discarded_events(struct bt_notification_iterator *iterator,
+               struct bt_ctf_packet *packet,
+               struct bt_ctf_clock_value *ts_begin,
+               struct bt_ctf_clock_value *ts_end,
+               struct stream_state *stream_state)
+{
+       struct bt_notification *notif = NULL;
+       uint64_t diff;
+       uint64_t next_count;
+       int ret = 0;
+
+       next_count = get_packet_context_events_discarded(packet);
+       if (next_count == -1ULL) {
+               next_count = stream_state->discarded_events_state.cur_count;
+               goto update_state;
+       }
+
+       if (next_count < stream_state->discarded_events_state.cur_count) {
+               BT_LOGW("Current value of packet's context field's `events_discarded` field is lesser than the previous value for the same stream: "
+                       "not updating the stream state's current value: "
+                       "packet-addr=%p, prev-count=%" PRIu64 ", "
+                       "cur-count=%" PRIu64,
+                       packet, stream_state->discarded_events_state.cur_count,
+                       next_count);
+               goto end;
+       }
+
+       diff = next_count - stream_state->discarded_events_state.cur_count;
+       if (diff > 0) {
+               /*
+                * Add a discarded events notification. The events are
+                * considered to be lost betweem the state's last time
+                * and the current packet's end time.
+                */
+               notif = bt_notification_discarded_elements_create(
+                       BT_NOTIFICATION_TYPE_DISCARDED_EVENTS,
+                       stream_state->stream,
+                       stream_state->discarded_events_state.cur_begin,
+                       ts_end, diff);
+               if (!notif) {
+                       BT_LOGE_STR("Cannot create discarded events notification.");
+                       ret = -1;
+                       goto end;
+               }
+
+               add_action_push_notif(iterator, notif);
+       }
+
+update_state:
+       add_action_update_stream_state_discarded_elements(iterator,
+               ACTION_TYPE_UPDATE_STREAM_STATE_DISCARDED_EVENTS,
+               stream_state, ts_end, next_count);
+
+end:
+       bt_put(notif);
+       return ret;
+}
+
+static
+int get_field_clock_value(struct bt_ctf_field *root_field,
+               const char *field_name,
+               struct bt_ctf_clock_value **user_clock_val)
+{
+       struct bt_ctf_field *field;
+       struct bt_ctf_field_type *ft = NULL;
+       struct bt_ctf_clock_class *clock_class = NULL;
+       struct bt_ctf_clock_value *clock_value = NULL;
+       uint64_t val;
+       int ret = 0;
+
+       field = get_struct_field_uint(root_field, field_name);
+       if (!field) {
+               /* Not an error: skip this */
+               goto end;
+       }
+
+       ft = bt_ctf_field_get_type(field);
+       assert(ft);
+       clock_class = bt_ctf_field_type_integer_get_mapped_clock_class(ft);
+       if (!clock_class) {
+               BT_LOGW("Integer field type has no mapped clock class but it's expected to have one: "
+                       "ft-addr=%p", ft);
+               ret = -1;
+               goto end;
+       }
+
+       ret = bt_ctf_field_unsigned_integer_get_value(field, &val);
+       if (ret) {
+               BT_LOGW("Cannot get integer field's raw value: "
+                       "field-addr=%p", field);
+               ret = -1;
+               goto end;
+       }
+
+       clock_value = bt_ctf_clock_value_create(clock_class, val);
+       if (!clock_value) {
+               BT_LOGE_STR("Cannot create clock value from clock class.");
+               ret = -1;
+               goto end;
+       }
+
+       /* Move clock value to user */
+       *user_clock_val = clock_value;
+       clock_value = NULL;
+
+end:
+       bt_put(field);
+       bt_put(ft);
+       bt_put(clock_class);
+       bt_put(clock_value);
+       return ret;
+}
+
+static
+int get_ts_begin_ts_end_from_packet(struct bt_ctf_packet *packet,
+               struct bt_ctf_clock_value **user_ts_begin,
+               struct bt_ctf_clock_value **user_ts_end)
+{
+       struct bt_ctf_field *packet_context = NULL;
+       struct bt_ctf_clock_value *ts_begin = NULL;
+       struct bt_ctf_clock_value *ts_end = NULL;
+       int ret = 0;
+
+       packet_context = bt_ctf_packet_get_context(packet);
+       if (!packet_context) {
+               goto end;
+       }
+
+       ret = get_field_clock_value(packet_context, "timestamp_begin",
+               &ts_begin);
+       if (ret) {
+               BT_LOGW("Cannot create clock value for packet context's `timestamp_begin` field: "
+                       "packet-addr=%p, packet-context-field-addr=%p",
+                       packet, packet_context);
+               goto end;
+       }
+
+       ret = get_field_clock_value(packet_context, "timestamp_end",
+               &ts_end);
+       if (ret) {
+               BT_LOGW("Cannot create clock value for packet context's `timestamp_begin` field: "
+                       "packet-addr=%p, packet-context-field-addr=%p",
+                       packet, packet_context);
+               goto end;
+       }
+
+       /* Move clock values to user */
+       *user_ts_begin = ts_begin;
+       ts_begin = NULL;
+       *user_ts_end = ts_end;
+       ts_end = NULL;
+
+end:
+       bt_put(packet_context);
+       bt_put(ts_begin);
+       bt_put(ts_end);
+       return ret;
+}
+
+static
+int handle_discarded_elements(struct bt_notification_iterator *iterator,
+               struct bt_ctf_packet *packet, struct stream_state *stream_state)
+{
+       struct bt_ctf_clock_value *ts_begin = NULL;
+       struct bt_ctf_clock_value *ts_end = NULL;
+       int ret;
+
+       ret = get_ts_begin_ts_end_from_packet(packet, &ts_begin, &ts_end);
+       if (ret) {
+               BT_LOGW("Cannot get packet's beginning or end clock values: "
+                       "packet-addr=%p, ret=%d", packet, ret);
+               ret = -1;
+               goto end;
+       }
+
+       ret = handle_discarded_packets(iterator, packet, ts_begin, ts_end,
+               stream_state);
+       if (ret) {
+               BT_LOGW("Cannot handle discarded packets for packet: "
+                       "packet-addr=%p, ret=%d", packet, ret);
+               ret = -1;
+               goto end;
+       }
+
+       ret = handle_discarded_events(iterator, packet, ts_begin, ts_end,
+               stream_state);
+       if (ret) {
+               BT_LOGW("Cannot handle discarded events for packet: "
+                       "packet-addr=%p, ret=%d", packet, ret);
+               ret = -1;
+               goto end;
+       }
+
+end:
+       bt_put(ts_begin);
+       bt_put(ts_end);
+       return ret;
+}
+
 static
 int handle_packet_switch(struct bt_notification_iterator *iterator,
                struct bt_notification *packet_begin_notif,
@@ -1105,6 +1573,17 @@ int handle_packet_switch(struct bt_notification_iterator *iterator,
                }
        }
 
+       /*
+        * Check the new packet's header and context fields for
+        * discarded packets and events to emit those automatic
+        * notifications.
+        */
+       ret = handle_discarded_elements(iterator, new_packet, stream_state);
+       if (ret) {
+               BT_LOGE_STR("Cannot handle discarded elements for new packet.");
+               goto error;
+       }
+
        /* Beginning of the new packet */
        if (packet_begin_notif) {
                add_action_push_notif(iterator, packet_begin_notif);
@@ -1190,6 +1669,35 @@ end:
        return ret;
 }
 
+static
+int handle_notif_discarded_elements(
+               struct bt_notification_iterator *iterator,
+               struct bt_notification *notif,
+               struct bt_ctf_stream *notif_stream)
+{
+       int ret = 0;
+       struct stream_state *stream_state;
+
+       assert(notif->type == BT_NOTIFICATION_TYPE_DISCARDED_EVENTS ||
+                       notif->type == BT_NOTIFICATION_TYPE_DISCARDED_PACKETS);
+       assert(notif_stream);
+       ret = ensure_stream_state_exists(iterator, NULL, notif_stream,
+               &stream_state);
+       if (ret) {
+               BT_LOGE_STR("Cannot ensure that stream state exists.");
+               goto error;
+       }
+
+       add_action_push_notif(iterator, notif);
+       goto end;
+
+error:
+       ret = -1;
+
+end:
+       return ret;
+}
+
 static
 int handle_notif_packet_begin(
                struct bt_notification_iterator *iterator,
@@ -1349,7 +1857,10 @@ int enqueue_notification_and_automatic(
                 * types above are allowed to be returned by a user
                 * component.
                 */
-               goto error;
+               BT_LOGF("Unexpected notification type at this point: "
+                       "notif-addr=%p, notif-type=%s", notif,
+                       bt_notification_type_string(notif->type));
+               abort();
        }
 
        if (notif_packet) {
@@ -1392,6 +1903,11 @@ handle_notif:
                ret = handle_notif_packet_end(iterator, notif, notif_stream,
                        notif_packet);
                break;
+       case BT_NOTIFICATION_TYPE_DISCARDED_EVENTS:
+       case BT_NOTIFICATION_TYPE_DISCARDED_PACKETS:
+               ret = handle_notif_discarded_elements(iterator, notif,
+                       notif_stream);
+               break;
        case BT_NOTIFICATION_TYPE_INACTIVITY:
                add_action_push_notif(iterator, notif);
                break;
@@ -1616,6 +2132,23 @@ enum bt_notification_iterator_status ensure_queue_has_notifications(
                                goto end;
                        }
 
+                       /*
+                        * Ignore some notifications which are always
+                        * automatically generated by the notification
+                        * iterator to make sure they have valid values.
+                        */
+                       switch (next_return.notification->type) {
+                       case BT_NOTIFICATION_TYPE_DISCARDED_PACKETS:
+                       case BT_NOTIFICATION_TYPE_DISCARDED_EVENTS:
+                               BT_LOGV("Ignoring discarded elements notification returned by notification iterator's \"next\" method: "
+                                       "notif-type=%s",
+                                       bt_notification_type_string(next_return.notification->type));
+                               BT_PUT(next_return.notification);
+                               continue;
+                       default:
+                               break;
+                       }
+
                        /*
                         * We know the notification is valid. Before we
                         * push it to the head of the queue, push the
index db32a43c614b024577b29195aea3e77decb957c5..96560c10d49e52baf5f1fe60f1c5eb4f4ebe8073 100644 (file)
@@ -8,4 +8,7 @@ libgraph_notification_la_SOURCES = \
        event.c \
        stream.c \
        heap.c \
-       inactivity.c
+       inactivity.c \
+       discarded-events.c \
+       discarded-packets.c \
+       discarded-elements.c
diff --git a/lib/graph/notification/discarded-elements.c b/lib/graph/notification/discarded-elements.c
new file mode 100644 (file)
index 0000000..ee4e8a5
--- /dev/null
@@ -0,0 +1,228 @@
+/*
+ * Copyright 2017 Philippe Proulx <pproulx@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#define BT_LOG_TAG "NOTIF-DISCARDED"
+#include <babeltrace/lib-logging-internal.h>
+
+#include <babeltrace/object-internal.h>
+#include <babeltrace/compiler-internal.h>
+#include <babeltrace/ctf-ir/clock-class.h>
+#include <babeltrace/graph/clock-class-priority-map.h>
+#include <babeltrace/graph/clock-class-priority-map-internal.h>
+#include <babeltrace/graph/notification-internal.h>
+#include <babeltrace/graph/notification-discarded-elements-internal.h>
+#include <stdint.h>
+#include <inttypes.h>
+
+static
+void bt_notification_discarded_elements_destroy(struct bt_object *obj)
+{
+       struct bt_notification_discarded_elements *notification =
+               (struct bt_notification_discarded_elements *) obj;
+
+       BT_LOGD("Destroying discarded elements notification: addr=%p",
+               notification);
+       BT_LOGD_STR("Putting stream.");
+       bt_put(notification->stream);
+       BT_LOGD_STR("Putting beginning clock value.");
+       bt_put(notification->begin_clock_value);
+       BT_LOGD_STR("Putting end clock value.");
+       bt_put(notification->end_clock_value);
+       g_free(notification);
+}
+
+BT_HIDDEN
+struct bt_notification *bt_notification_discarded_elements_create(
+               enum bt_notification_type type,
+               struct bt_ctf_stream *stream,
+               struct bt_ctf_clock_value *begin_clock_value,
+               struct bt_ctf_clock_value *end_clock_value,
+               uint64_t count)
+{
+       struct bt_notification_discarded_elements *notification;
+       struct bt_notification *ret_notif = NULL;
+
+       if (!stream) {
+               BT_LOGW_STR("Invalid parameter: stream is NULL.");
+       }
+
+       BT_LOGD("Creating discarded elements notification object: "
+               "type=%s, stream-addr=%p, stream-name=\"%s\", "
+               "begin-clock-value-addr=%p, end-clock-value-addr=%p, "
+               "count=%" PRIu64,
+               bt_notification_type_string(type), stream,
+               bt_ctf_stream_get_name(stream), begin_clock_value,
+               end_clock_value, count);
+       notification = g_new0(struct bt_notification_discarded_elements, 1);
+       if (!notification) {
+               BT_LOGE_STR("Failed to allocate one discarded elements notification.");
+               goto error;
+       }
+
+       bt_notification_init(&notification->parent, type,
+               bt_notification_discarded_elements_destroy);
+       ret_notif = &notification->parent;
+       notification->stream = bt_get(stream);
+       notification->begin_clock_value = bt_get(begin_clock_value);
+       notification->end_clock_value = bt_get(end_clock_value);
+       notification->count = (int64_t) count;
+       BT_LOGD("Created discarded elements notification object: "
+               "type=%s, stream-addr=%p, stream-name=\"%s\", "
+               "begin-clock-value-addr=%p, end-clock-value-addr=%p, "
+               "count=%" PRIu64 ", addr=%p",
+               bt_notification_type_string(type), stream,
+               bt_ctf_stream_get_name(stream), begin_clock_value,
+               end_clock_value, count, ret_notif);
+       goto end;
+
+error:
+       BT_PUT(ret_notif);
+
+end:
+       return ret_notif;
+}
+
+BT_HIDDEN
+struct bt_ctf_clock_value *
+bt_notification_discarded_elements_get_begin_clock_value(
+               enum bt_notification_type type,
+               struct bt_notification *notification)
+{
+       struct bt_ctf_clock_value *clock_value = NULL;
+       struct bt_notification_discarded_elements *discarded_elems_notif;
+
+       if (!notification) {
+               BT_LOGW_STR("Invalid parameter: notification is NULL.");
+               goto end;
+       }
+
+       if (bt_notification_get_type(notification) !=
+                       BT_NOTIFICATION_TYPE_DISCARDED_EVENTS) {
+               BT_LOGW("Invalid parameter: notification has not the expected type: "
+                       "addr%p, expected-type=%s, notif-type=%s",
+                       notification, bt_notification_type_string(type),
+                       bt_notification_type_string(
+                               bt_notification_get_type(notification)));
+               goto end;
+       }
+
+       discarded_elems_notif = container_of(notification,
+                       struct bt_notification_discarded_elements, parent);
+       clock_value = bt_get(discarded_elems_notif->begin_clock_value);
+
+end:
+       return clock_value;
+}
+
+BT_HIDDEN
+struct bt_ctf_clock_value *
+bt_notification_discarded_elements_get_end_clock_value(
+               enum bt_notification_type type,
+               struct bt_notification *notification)
+{
+       struct bt_ctf_clock_value *clock_value = NULL;
+       struct bt_notification_discarded_elements *discarded_elems_notif;
+
+       if (!notification) {
+               BT_LOGW_STR("Invalid parameter: notification is NULL.");
+               goto end;
+       }
+
+       if (bt_notification_get_type(notification) !=
+                       BT_NOTIFICATION_TYPE_DISCARDED_EVENTS) {
+               BT_LOGW("Invalid parameter: notification has not the expected type: "
+                       "addr%p, expected-type=%s, notif-type=%s",
+                       notification, bt_notification_type_string(type),
+                       bt_notification_type_string(
+                               bt_notification_get_type(notification)));
+               goto end;
+       }
+
+       discarded_elems_notif = container_of(notification,
+                       struct bt_notification_discarded_elements, parent);
+       clock_value = bt_get(discarded_elems_notif->end_clock_value);
+
+end:
+       return clock_value;
+}
+
+BT_HIDDEN
+int64_t bt_notification_discarded_elements_get_count(
+               enum bt_notification_type type,
+               struct bt_notification *notification)
+{
+       int64_t count = (int64_t) -1;
+       struct bt_notification_discarded_elements *discarded_elems_notif;
+
+       if (!notification) {
+               BT_LOGW_STR("Invalid parameter: notification is NULL.");
+               goto end;
+       }
+
+       if (bt_notification_get_type(notification) !=
+                       BT_NOTIFICATION_TYPE_DISCARDED_EVENTS) {
+               BT_LOGW("Invalid parameter: notification has not the expected type: "
+                       "addr%p, expected-type=%s, notif-type=%s",
+                       notification, bt_notification_type_string(type),
+                       bt_notification_type_string(
+                               bt_notification_get_type(notification)));
+               goto end;
+       }
+
+       discarded_elems_notif = container_of(notification,
+                       struct bt_notification_discarded_elements, parent);
+       count = discarded_elems_notif->count;
+
+end:
+       return count;
+}
+
+BT_HIDDEN
+struct bt_ctf_stream *bt_notification_discarded_elements_get_stream(
+               enum bt_notification_type type,
+               struct bt_notification *notification)
+{
+       struct bt_ctf_stream *stream = NULL;
+       struct bt_notification_discarded_elements *discarded_elems_notif;
+
+       if (!notification) {
+               BT_LOGW_STR("Invalid parameter: notification is NULL.");
+               goto end;
+       }
+
+       if (bt_notification_get_type(notification) !=
+                       BT_NOTIFICATION_TYPE_DISCARDED_EVENTS) {
+               BT_LOGW("Invalid parameter: notification has not the expected type: "
+                       "addr%p, expected-type=%s, notif-type=%s",
+                       notification, bt_notification_type_string(type),
+                       bt_notification_type_string(
+                               bt_notification_get_type(notification)));
+               goto end;
+       }
+
+       discarded_elems_notif = container_of(notification,
+                       struct bt_notification_discarded_elements, parent);
+       stream = bt_get(discarded_elems_notif->stream);
+
+end:
+       return stream;
+}
diff --git a/lib/graph/notification/discarded-events.c b/lib/graph/notification/discarded-events.c
new file mode 100644 (file)
index 0000000..e618923
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2017 Philippe Proulx <pproulx@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <babeltrace/graph/notification.h>
+#include <babeltrace/graph/notification-discarded-events.h>
+#include <babeltrace/graph/notification-discarded-elements-internal.h>
+#include <stdint.h>
+
+struct bt_ctf_clock_value *
+bt_notification_discarded_events_get_begin_clock_value(
+               struct bt_notification *notification)
+{
+       return bt_notification_discarded_elements_get_begin_clock_value(
+               BT_NOTIFICATION_TYPE_DISCARDED_EVENTS, notification);
+}
+
+struct bt_ctf_clock_value *
+bt_notification_discarded_events_get_end_clock_value(
+               struct bt_notification *notification)
+{
+       return bt_notification_discarded_elements_get_end_clock_value(
+               BT_NOTIFICATION_TYPE_DISCARDED_EVENTS, notification);
+}
+
+int64_t bt_notification_discarded_events_get_count(
+               struct bt_notification *notification)
+{
+       return bt_notification_discarded_elements_get_count(
+               BT_NOTIFICATION_TYPE_DISCARDED_EVENTS, notification);
+}
+
+struct bt_ctf_stream *bt_notification_discarded_events_get_stream(
+               struct bt_notification *notification)
+{
+       return bt_notification_discarded_elements_get_stream(
+               BT_NOTIFICATION_TYPE_DISCARDED_EVENTS, notification);
+}
diff --git a/lib/graph/notification/discarded-packets.c b/lib/graph/notification/discarded-packets.c
new file mode 100644 (file)
index 0000000..0425a34
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2017 Philippe Proulx <pproulx@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <babeltrace/graph/notification.h>
+#include <babeltrace/graph/notification-discarded-packets.h>
+#include <babeltrace/graph/notification-discarded-elements-internal.h>
+#include <stdint.h>
+
+struct bt_ctf_clock_value *
+bt_notification_discarded_packets_get_begin_clock_value(
+               struct bt_notification *notification)
+{
+       return bt_notification_discarded_elements_get_begin_clock_value(
+               BT_NOTIFICATION_TYPE_DISCARDED_PACKETS, notification);
+}
+
+struct bt_ctf_clock_value *
+bt_notification_discarded_packets_get_end_clock_value(
+               struct bt_notification *notification)
+{
+       return bt_notification_discarded_elements_get_end_clock_value(
+               BT_NOTIFICATION_TYPE_DISCARDED_PACKETS, notification);
+}
+
+int64_t bt_notification_discarded_packets_get_count(
+               struct bt_notification *notification)
+{
+       return bt_notification_discarded_elements_get_count(
+               BT_NOTIFICATION_TYPE_DISCARDED_PACKETS, notification);
+}
+
+struct bt_ctf_stream *bt_notification_discarded_packets_get_stream(
+               struct bt_notification *notification)
+{
+       return bt_notification_discarded_elements_get_stream(
+               BT_NOTIFICATION_TYPE_DISCARDED_PACKETS, notification);
+}
This page took 0.042645 seconds and 4 git commands to generate.