eepp

read-ctf-example.c

Jun 18th, 2021
42
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <stdint.h>
  4. #include <stdbool.h>
  5. #include <assert.h>
  6. #include <babeltrace2/babeltrace.h>
  7.  
  8. /*
  9.  * Shared data between our relay sink component and the
  10.  * bt_graph_run_once() call site.
  11.  */
  12. struct relay_data {
  13.     bt_message_array_const msgs;
  14.     uint64_t msg_count;
  15. };
  16.  
  17. /*
  18.  * Consumer method of our relay sink component class.
  19.  *
  20.  * See <https://babeltrace.org/docs/v2.0/libbabeltrace2/group__api-graph.html#ga301a677396bd8f5bd8b920fd5fa60418>.
  21.  */
  22. static bt_graph_simple_sink_component_consume_func_status relay_consume(
  23.         bt_message_iterator * const msg_iter,
  24.         void * const user_data)
  25. {
  26.     struct relay_data * const relay_data =
  27.         (struct relay_data *) user_data;
  28.     bt_message_iterator_next_status msg_iter_next_status;
  29.     bt_graph_simple_sink_component_consume_func_status status =
  30.         BT_GRAPH_SIMPLE_SINK_COMPONENT_CONSUME_FUNC_STATUS_OK;
  31.  
  32.     /* Consume the next messages, storing them in `*relay_data` */
  33.     msg_iter_next_status = bt_message_iterator_next(msg_iter,
  34.         &relay_data->msgs, &relay_data->msg_count);
  35.     switch (msg_iter_next_status) {
  36.     case BT_MESSAGE_ITERATOR_NEXT_STATUS_END:
  37.         status = BT_GRAPH_SIMPLE_SINK_COMPONENT_CONSUME_FUNC_STATUS_END;
  38.         break;
  39.     case BT_GRAPH_SIMPLE_SINK_COMPONENT_CONSUME_FUNC_STATUS_MEMORY_ERROR:
  40.         status = BT_GRAPH_SIMPLE_SINK_COMPONENT_CONSUME_FUNC_STATUS_MEMORY_ERROR;
  41.         break;
  42.     case BT_GRAPH_SIMPLE_SINK_COMPONENT_CONSUME_FUNC_STATUS_ERROR:
  43.         status = BT_GRAPH_SIMPLE_SINK_COMPONENT_CONSUME_FUNC_STATUS_ERROR;
  44.         break;
  45.     default:
  46.         assert(status ==
  47.             BT_GRAPH_SIMPLE_SINK_COMPONENT_CONSUME_FUNC_STATUS_OK);
  48.         break;
  49.     }
  50.  
  51.     return status;
  52. }
  53.  
  54. /*
  55.  * Adds our own sink component named `relay` to the trace processing
  56.  * graph `graph`.
  57.  *
  58.  * On success, `*comp` is the added sink component.
  59.  *
  60.  * See <https://babeltrace.org/docs/v2.0/libbabeltrace2/group__api-graph.html#api-graph-lc-add-ss>.
  61.  */
  62. static bt_graph_add_component_status add_relay_comp(bt_graph * const graph,
  63.         struct relay_data * const relay_data,
  64.         const bt_component_sink ** const comp)
  65. {
  66.     return bt_graph_add_simple_sink_component(graph, "relay", NULL,
  67.         relay_consume, NULL, relay_data, comp);
  68. }
  69.  
  70. /*
  71.  * Creates and returns the parameters to initialize the `src.ctf.fs`
  72.  * component with the trace directory `trace_dir`.
  73.  *
  74.  * See <https://babeltrace.org/docs/v2.0/libbabeltrace2/group__api-val.html>.
  75.  */
  76. static bt_value *create_ctf_fs_comp_params(const char * const trace_dir)
  77. {
  78.     bt_value *params;
  79.     bt_value *inputs = NULL;
  80.     bt_value_map_insert_entry_status insert_entry_status;
  81.     bt_value_array_append_element_status append_elem_status;
  82.  
  83.     /* Create an empty map value */
  84.     params = bt_value_map_create();
  85.     if (!params) {
  86.         goto error;
  87.     }
  88.  
  89.     /*
  90.      * Insert an empty array value having the key `inputs`.
  91.      *
  92.      * `inputs` is a borrowed value object here, _not_ our
  93.      * reference.
  94.      */
  95.     insert_entry_status = bt_value_map_insert_empty_array_entry(params,
  96.         "inputs", &inputs);
  97.     if (insert_entry_status != BT_VALUE_MAP_INSERT_ENTRY_STATUS_OK) {
  98.         goto error;
  99.     }
  100.  
  101.     /* Append the trace directory to the `inputs` array value */
  102.     append_elem_status = bt_value_array_append_string_element(inputs,
  103.         trace_dir);
  104.     if (append_elem_status != BT_VALUE_ARRAY_APPEND_ELEMENT_STATUS_OK) {
  105.         goto error;
  106.     }
  107.  
  108.     goto end;
  109.  
  110. error:
  111.     BT_VALUE_PUT_REF_AND_RESET(params);
  112.  
  113. end:
  114.     return params;
  115. }
  116.  
  117. /*
  118.  * Adds a `src.ctf.fs` component named `ctf` to read the trace directory
  119.  * `trace_dir` to the trace processing graph `graph`.
  120.  *
  121.  * See <https://babeltrace.org/docs/v2.0/man7/babeltrace2-source.ctf.fs.7/>.
  122.  *
  123.  * On success, `*comp` is the added source component.
  124.  */
  125. static bt_graph_add_component_status add_ctf_fs_comp(bt_graph * const graph,
  126.         const char * const trace_dir,
  127.         const bt_component_source ** const comp)
  128. {
  129.     const bt_plugin *plugin;
  130.     bt_plugin_find_status plugin_find_status;
  131.     const bt_component_class_source *comp_cls;
  132.     bt_value *params = NULL;
  133.     bt_graph_add_component_status add_comp_status;
  134.  
  135.     /* Find the `ctf` plugin */
  136.     plugin_find_status = bt_plugin_find("ctf", BT_TRUE, BT_TRUE,
  137.         BT_TRUE, BT_TRUE, BT_TRUE, &plugin);
  138.     if (plugin_find_status != BT_PLUGIN_FIND_STATUS_OK) {
  139.         goto error;
  140.     }
  141.  
  142.     /* Borrow the `fs` source component class within the `ctf` plugin */
  143.     comp_cls = bt_plugin_borrow_source_component_class_by_name_const(
  144.         plugin, "fs");
  145.     if (!comp_cls) {
  146.         goto error;
  147.     }
  148.  
  149.     /* Create the parameters to initialize the source component */
  150.     params = create_ctf_fs_comp_params(trace_dir);
  151.     if (!params) {
  152.         goto error;
  153.     }
  154.  
  155.     /* Add the source component to the graph */
  156.     add_comp_status = bt_graph_add_source_component(graph, comp_cls,
  157.         "ctf", params, BT_LOGGING_LEVEL_NONE, comp);
  158.     goto end;
  159.  
  160. error:
  161.     add_comp_status = BT_GRAPH_ADD_COMPONENT_STATUS_ERROR;
  162.  
  163. end:
  164.     bt_plugin_put_ref(plugin);
  165.     bt_value_put_ref(params);
  166.     return add_comp_status;
  167. }
  168.  
  169. /*
  170.  * Adds a `flt.utils.muxer` component named `muxer` to the trace
  171.  * processing graph `graph`.
  172.  *
  173.  * See <https://babeltrace.org/docs/v2.0/man7/babeltrace2-filter.utils.muxer.7/>.
  174.  *
  175.  * On success, `*comp` is the added filter component.
  176.  */
  177. static bt_graph_add_component_status add_muxer_comp(bt_graph * const graph,
  178.         const bt_component_filter ** const comp)
  179. {
  180.     const bt_plugin *plugin;
  181.     bt_plugin_find_status plugin_find_status;
  182.     const bt_component_class_filter *comp_cls;
  183.     bt_graph_add_component_status add_comp_status;
  184.  
  185.     /* Find the `utils` plugin */
  186.     plugin_find_status = bt_plugin_find("utils", BT_TRUE, BT_TRUE,
  187.         BT_TRUE, BT_TRUE, BT_TRUE, &plugin);
  188.     if (plugin_find_status != BT_PLUGIN_FIND_STATUS_OK) {
  189.         goto error;
  190.     }
  191.  
  192.     /* Borrow the `muxer` filter comp. class within the `utils` plugin */
  193.     comp_cls = bt_plugin_borrow_filter_component_class_by_name_const(
  194.         plugin, "muxer");
  195.     if (!comp_cls) {
  196.         goto error;
  197.     }
  198.  
  199.     /* Add the filter component to the graph (no init. parameters) */
  200.     add_comp_status = bt_graph_add_filter_component(graph, comp_cls,
  201.         "muxer", NULL, BT_LOGGING_LEVEL_NONE, comp);
  202.     goto end;
  203.  
  204. error:
  205.     add_comp_status = BT_GRAPH_ADD_COMPONENT_STATUS_ERROR;
  206.  
  207. end:
  208.     bt_plugin_put_ref(plugin);
  209.     return add_comp_status;
  210. }
  211.  
  212. /*
  213.  * Creates a trace processing graph having this layout:
  214.  *
  215.  *     +------------+    +-----------------+    +--------------+
  216.  *     | src.ctf.fs |    | flt.utils.muxer |    | Our own sink |
  217.  *     |    [ctf]   |    |     [muxer]     |    |    [relay]   |
  218.  *     |            |    |                 |    |              |
  219.  *     |    stream0 @--->@ in0         out @--->@ in           |
  220.  *     |    stream1 @--->@ in1             |    +--------------+
  221.  *     |    stream2 @--->@ in2             |
  222.  *     |    stream3 @--->@ in3             |
  223.  *     +------------+    @ in4             |
  224.  *                       +-----------------+
  225.  *
  226.  * In the example above, the `src.ctf.fs` component reads a CTF trace
  227.  * having four data streams. The `trace_dir` parameter is the directory
  228.  * containing the CTF trace to read.
  229.  *
  230.  * Our own relay sink component, of which the consuming method is
  231.  * relay_consume(), consumes messages from the `flt.utils.muxer`
  232.  * component, storing them to a structure (`*relay_data`) shared with
  233.  * the bt_graph_run_once() call site.
  234.  *
  235.  * See <https://babeltrace.org/docs/v2.0/libbabeltrace2/group__api-graph.html>.
  236.  */
  237. static bt_graph *create_graph(const char * const trace_dir,
  238.         struct relay_data * const relay_data)
  239. {
  240.     bt_graph *graph;
  241.     const bt_component_source *ctf_fs_comp;
  242.     const bt_component_filter *muxer_comp;
  243.     const bt_component_sink *relay_comp;
  244.     bt_graph_add_component_status add_comp_status;
  245.     bt_graph_connect_ports_status connect_ports_status;
  246.     uint64_t i;
  247.  
  248.     /* Create an empty trace processing graph */
  249.     graph = bt_graph_create(0);
  250.     if (!graph) {
  251.         goto error;
  252.     }
  253.  
  254.     /* Create and add the three required components to `graph` */
  255.     add_comp_status = add_ctf_fs_comp(graph, trace_dir, &ctf_fs_comp);
  256.     if (add_comp_status != BT_GRAPH_ADD_COMPONENT_STATUS_OK) {
  257.         goto error;
  258.     }
  259.  
  260.     add_comp_status = add_muxer_comp(graph, &muxer_comp);
  261.     if (add_comp_status != BT_GRAPH_ADD_COMPONENT_STATUS_OK) {
  262.         goto error;
  263.     }
  264.  
  265.     add_comp_status = add_relay_comp(graph, relay_data, &relay_comp);
  266.     if (add_comp_status != BT_GRAPH_ADD_COMPONENT_STATUS_OK) {
  267.         goto error;
  268.     }
  269.  
  270.     /*
  271.      * Connect all the output ports of the `ctf` source component to
  272.      * the input ports of the `muxer` filter component.
  273.      *
  274.      * An `flt.utils.muxer` component adds an input port every time
  275.      * you connect one, making one always available.
  276.      *
  277.      * See <https://babeltrace.org/docs/v2.0/man7/babeltrace2-filter.utils.muxer.7/#doc-_input>.
  278.      */
  279.     for (i = 0; i < bt_component_source_get_output_port_count(ctf_fs_comp);
  280.             i++) {
  281.         const bt_port_output * const out_port =
  282.             bt_component_source_borrow_output_port_by_index_const(
  283.                 ctf_fs_comp, i);
  284.         const bt_port_input * const in_port =
  285.             bt_component_filter_borrow_input_port_by_index_const(
  286.                 muxer_comp, i);
  287.  
  288.         /* Connect ports */
  289.         connect_ports_status = bt_graph_connect_ports(graph,
  290.             out_port, in_port, NULL);
  291.  
  292.         if (connect_ports_status != BT_GRAPH_CONNECT_PORTS_STATUS_OK) {
  293.             goto error;
  294.         }
  295.     }
  296.  
  297.     /* Connect the `muxer` output port to the `relay` input port */
  298.     connect_ports_status = bt_graph_connect_ports(graph,
  299.         bt_component_filter_borrow_output_port_by_index_const(
  300.             muxer_comp, 0),
  301.         bt_component_sink_borrow_input_port_by_index_const(
  302.             relay_comp, 0), NULL);
  303.     if (connect_ports_status != BT_GRAPH_CONNECT_PORTS_STATUS_OK) {
  304.         goto error;
  305.     }
  306.  
  307.     goto end;
  308.  
  309. error:
  310.     BT_GRAPH_PUT_REF_AND_RESET(graph);
  311.  
  312. end:
  313.     return graph;
  314. }
  315.  
  316. /*
  317.  * Handles a single message `msg`, printing its name if it's an event
  318.  * message.
  319.  *
  320.  * See <https://babeltrace.org/docs/v2.0/libbabeltrace2/group__api-msg.html>.
  321.  */
  322. static void handle_msg(const bt_message * const msg)
  323. {
  324.     const bt_event *event;
  325.  
  326.     if (bt_message_get_type(msg) != BT_MESSAGE_TYPE_EVENT) {
  327.         goto end;
  328.     }
  329.  
  330.     event = bt_message_event_borrow_event_const(msg);
  331.     puts(bt_event_class_get_name(bt_event_borrow_class_const(event)));
  332.  
  333. end:
  334.     return;
  335. }
  336.  
  337. /*
  338.  * Runs the trace processing graph `graph`, our relay sink component
  339.  * transferring its consumed messages to `*relay_data`.
  340.  *
  341.  * See <https://babeltrace.org/docs/v2.0/libbabeltrace2/group__api-graph.html#api-graph-lc-run>.
  342.  */
  343. static int run_graph(bt_graph * const graph,
  344.         struct relay_data * const relay_data)
  345. {
  346.     bt_graph_run_once_status status;
  347.  
  348.     while (true) {
  349.         uint64_t i;
  350.  
  351.         /*
  352.          * bt_graph_run_once() calls the consuming method of
  353.          * our relay sink component (relay_consume()).
  354.          *
  355.          * relay_consume() consumes a batch of messages from the
  356.          * `flt.utils.muxer` component and stores them in
  357.          * `*relay_data`.
  358.          */
  359.         status = bt_graph_run_once(graph);
  360.         assert(status != BT_GRAPH_RUN_ONCE_STATUS_AGAIN);
  361.         if (status != BT_GRAPH_RUN_ONCE_STATUS_OK) {
  362.             break;
  363.         }
  364.  
  365.         /* Handle each consumed message */
  366.         for (i = 0; i < relay_data->msg_count; i++) {
  367.             const bt_message * const msg = relay_data->msgs[i];
  368.  
  369.             handle_msg(msg);
  370.  
  371.             /*
  372.              * The message reference `msg` is ours: release
  373.              * it now.
  374.              */
  375.             bt_message_put_ref(msg);
  376.         }
  377.     }
  378.  
  379.     return status == BT_GRAPH_RUN_ONCE_STATUS_END ? 0 : -1;
  380. }
  381.  
  382. /*
  383.  * Reads the CTF trace located in the directory `argv[1]`, printing one
  384.  * event name per line to the standard output.
  385.  */
  386. int main(const int argc, const char * const * const argv)
  387. {
  388.     int ret = EXIT_SUCCESS;
  389.     struct relay_data relay_data = { 0 };
  390.     bt_graph *graph;
  391.  
  392.     assert(argc == 2);
  393.  
  394.     /* Create the trace processing graph */
  395.     graph = create_graph(argv[1], &relay_data);
  396.     if (!graph) {
  397.         ret = EXIT_FAILURE;
  398.         goto end;
  399.     }
  400.  
  401.     /* Run the graph, printing one event name per line */
  402.     if (run_graph(graph, &relay_data)) {
  403.         ret = EXIT_FAILURE;
  404.     }
  405.  
  406. end:
  407.     bt_graph_put_ref(graph);
  408.     return ret;
  409. }
  410.  
RAW Paste Data