Document libbabeltrace2's C API
[babeltrace.git] / doc / api / libbabeltrace2 / examples / epitome.c
CommitLineData
43c59509
PP
1#include <stdlib.h>
2#include <stdio.h>
3#include <stdint.h>
4#include <inttypes.h>
5#include <string.h>
6#include <babeltrace2/babeltrace.h>
7
8/* Sink component's private data */
9struct epitome_out {
10 /* Upstream message iterator (owned by this) */
11 bt_message_iterator *message_iterator;
12
13 /* Current event message index */
14 uint64_t index;
15};
16
17/*
18 * Initializes the sink component.
19 */
20static
21bt_component_class_initialize_method_status epitome_out_initialize(
22 bt_self_component_sink *self_component_sink,
23 bt_self_component_sink_configuration *configuration,
24 const bt_value *params, void *initialize_method_data)
25{
26 /* Allocate a private data structure */
27 struct epitome_out *epitome_out = malloc(sizeof(*epitome_out));
28
29 /* Initialize the first event message's index */
30 epitome_out->index = 1;
31
32 /* Set the component's user data to our private data structure */
33 bt_self_component_set_data(
34 bt_self_component_sink_as_self_component(self_component_sink),
35 epitome_out);
36
37 /*
38 * Add an input port named `in` to the sink component.
39 *
40 * This is needed so that this sink component can be connected to a
41 * filter or a source component. With a connected upstream
42 * component, this sink component can create a message iterator
43 * to consume messages.
44 */
45 bt_self_component_sink_add_input_port(self_component_sink,
46 "in", NULL, NULL);
47
48 return BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_OK;
49}
50
51/*
52 * Finalizes the sink component.
53 */
54static
55void epitome_out_finalize(bt_self_component_sink *self_component_sink)
56{
57 /* Retrieve our private data from the component's user data */
58 struct epitome_out *epitome_out = bt_self_component_get_data(
59 bt_self_component_sink_as_self_component(self_component_sink));
60
61 /* Free the allocated structure */
62 free(epitome_out);
63}
64
65/*
66 * Called when the trace processing graph containing the sink component
67 * is configured.
68 *
69 * This is where we can create our upstream message iterator.
70 */
71static
72bt_component_class_sink_graph_is_configured_method_status
73epitome_out_graph_is_configured(bt_self_component_sink *self_component_sink)
74{
75 /* Retrieve our private data from the component's user data */
76 struct epitome_out *epitome_out = bt_self_component_get_data(
77 bt_self_component_sink_as_self_component(self_component_sink));
78
79 /* Borrow our unique port */
80 bt_self_component_port_input *in_port =
81 bt_self_component_sink_borrow_input_port_by_index(
82 self_component_sink, 0);
83
84 /* Create the uptream message iterator */
85 bt_message_iterator_create_from_sink_component(self_component_sink,
86 in_port, &epitome_out->message_iterator);
87
88 return BT_COMPONENT_CLASS_SINK_GRAPH_IS_CONFIGURED_METHOD_STATUS_OK;
89}
90
91/*
92 * Prints a line for `message`, if it's an event message, to the
93 * standard output.
94 */
95static
96void print_message(struct epitome_out *epitome_out, const bt_message *message)
97{
98 /* Discard if it's not an event message */
99 if (bt_message_get_type(message) != BT_MESSAGE_TYPE_EVENT) {
100 goto end;
101 }
102
103 /* Borrow the event message's event and its class */
104 const bt_event *event =
105 bt_message_event_borrow_event_const(message);
106 const bt_event_class *event_class = bt_event_borrow_class_const(event);
107
108 /* Get the number of payload field members */
109 const bt_field *payload_field =
110 bt_event_borrow_payload_field_const(event);
111 uint64_t member_count = bt_field_class_structure_get_member_count(
112 bt_field_borrow_class_const(payload_field));
113
114 /* Write a corresponding line to the standard output */
115 printf("#%" PRIu64 ": %s (%" PRIu64 " payload member%s)\n",
116 epitome_out->index, bt_event_class_get_name(event_class),
117 member_count, member_count == 1 ? "" : "s");
118
119 /* Increment the current event message's index */
120 epitome_out->index++;
121
122end:
123 return;
124}
125
126/*
127 * Consumes a batch of messages and writes the corresponding lines to
128 * the standard output.
129 */
130bt_component_class_sink_consume_method_status epitome_out_consume(
131 bt_self_component_sink *self_component_sink)
132{
133 bt_component_class_sink_consume_method_status status =
134 BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_OK;
135
136 /* Retrieve our private data from the component's user data */
137 struct epitome_out *epitome_out = bt_self_component_get_data(
138 bt_self_component_sink_as_self_component(self_component_sink));
139
140 /* Consume a batch of messages from the upstream message iterator */
141 bt_message_array_const messages;
142 uint64_t message_count;
143 bt_message_iterator_next_status next_status =
144 bt_message_iterator_next(epitome_out->message_iterator, &messages,
145 &message_count);
146
147 switch (next_status) {
148 case BT_MESSAGE_ITERATOR_NEXT_STATUS_END:
149 /* End of iteration: put the message iterator's reference */
150 bt_message_iterator_put_ref(epitome_out->message_iterator);
151 status = BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_END;
152 goto end;
153 case BT_MESSAGE_ITERATOR_NEXT_STATUS_AGAIN:
154 status = BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_AGAIN;
155 goto end;
156 case BT_MESSAGE_ITERATOR_NEXT_STATUS_MEMORY_ERROR:
157 status = BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_MEMORY_ERROR;
158 goto end;
159 case BT_MESSAGE_ITERATOR_NEXT_STATUS_ERROR:
160 status = BT_COMPONENT_CLASS_SINK_CONSUME_METHOD_STATUS_ERROR;
161 goto end;
162 default:
163 break;
164 }
165
166 /* For each consumed message */
167 for (uint64_t i = 0; i < message_count; i++) {
168 /* Current message */
169 const bt_message *message = messages[i];
170
171 /* Print line for current message if it's an event message */
172 print_message(epitome_out, message);
173
174 /* Put this message's reference */
175 bt_message_put_ref(message);
176 }
177
178end:
179 return status;
180}
181
182/* Mandatory */
183BT_PLUGIN_MODULE();
184
185/* Define the `epitome` plugin */
186BT_PLUGIN(epitome);
187
188/* Define the `output` sink component class */
189BT_PLUGIN_SINK_COMPONENT_CLASS(output, epitome_out_consume);
190
191/* Set some of the `output` sink component class's optional methods */
192BT_PLUGIN_SINK_COMPONENT_CLASS_INITIALIZE_METHOD(output,
193 epitome_out_initialize);
194BT_PLUGIN_SINK_COMPONENT_CLASS_FINALIZE_METHOD(output, epitome_out_finalize);
195BT_PLUGIN_SINK_COMPONENT_CLASS_GRAPH_IS_CONFIGURED_METHOD(output,
196 epitome_out_graph_is_configured);
This page took 0.029113 seconds and 4 git commands to generate.