From 3c729b9af1b926f739be5bbba4ec20a296746023 Mon Sep 17 00:00:00 2001 From: Philippe Proulx Date: Thu, 25 Jul 2019 18:07:59 -0400 Subject: [PATCH] lib: prepare the ground for stateful query operations This patch changes the library (and everything which depends on it) so that it is possible to make query operations stateful in the future if needed. Without this patch, a query operation can return the `BT_COMPONENT_CLASS_QUERY_METHOD_STATUS_AGAIN` status. The query executor's user can then retry the operation until it works, or abandon. However, there's no way for this query function to keep state between calls, so the process starts over every time whereas it could have progressed otherwise (for example, a temporary unresponsive network). Library changes =============== This patch does two things to address the limitation above: * It makes bt_query_executor_create() accept the component class, query object, and query parameters. It also removes those parameters, as well as the logging level, from bt_query_executor_query(). This ensures that a given query executor is dedicated to a specific query operation. Once you create a query executor, you cannot change the target component class, query object, and query parameters afterwards. The initial query executor's logging level is `BT_LOGGING_LEVEL_NONE`. You can set it before you call bt_query_executor_query() with bt_query_executor_set_logging_level(). Internally, the query executor keeps a reference on the component class, a copy of the query object, and a reference on the query parameters. * It makes a query method receive a private query executor (`bt_private_query_executor *`) object, and not receive the logging level. A private query executor is a private view of the query executor. This is where we can eventually add bt_private_query_executor_set_data() and bt_private_query_executor_get_data() to make the query operation stateful. From the query method's point of view, the private query executor is borrowed: there are no bt_private_query_executor_get_ref() and bt_private_query_executor_put_ref() functions. You can go from a private query executor to a constant query executor with bt_private_query_executor_as_query_executor_const(). This is how you can get the query executor's current logging level with bt_query_executor_get_logging_level(). To keep the changes minimal, query methods still receive the object and parameters every time. They are guaranteed, however, that for the same query executor, they remain unchanged. This guarantee is not relevant now anyway as there's no way to set and get private data. Python bindings changes ======================= * The new `_QueryExecutorCommon` class contains the common properties of a query executor and a private query executor (`is_interrupted` and `logging_level`). It requires its subclasses to implement the _as_query_executor_ptr() method to get the query executor pointer. * `QueryExecutor` inherits `_QueryExecutorCommon`. You now build a query executor with the component class, object, and (optional) query parameters: query_exec = bt2.QueryExecutor(MySrc, 'avail-servers', {'blacklist': ['node67']}) You now call the query() method without parameters: query_exec.query() You can set the logging level with: query_exec.logging_level = bt2.LoggingLevel.TRACE * The new `_PrivateQueryExecutor` class inherits `_QueryExecutorCommon`. An instance of `_PrivateQueryExecutor` is passed to the query method during a query operation. Once the user's query method returns, _bt_query_from_native() invalidates the private query executor in case the user kept a reference somewhere. Calling any method of an invalid private query executor raises `RuntimeError`. CLI changes =========== To centralize how query operations are performed in the CLI, all the sites which need to query use the new cli_query(), implemented in `src/cli/babeltrace2-query.c`. cli_query() is similar to the static query() function in `babeltrace2.c`, which already existed, but it accepts the logging level directly and returns `bt_query_executor_query_status`. The static query() function still exists, but calls cli_query() now. The automatic source discovery feature now uses cli_query() instead of creating its own query executor. Signed-off-by: Philippe Proulx Change-Id: I3c254325817c2c0091b6c4f0030bc7020443b8e0 Reviewed-on: https://review.lttng.org/c/babeltrace/+/1787 Tested-by: jenkins Reviewed-by: Simon Marchi --- include/Makefile.am | 1 + include/babeltrace2/babeltrace.h | 1 + .../graph/component-class-filter.h | 4 +- .../babeltrace2/graph/component-class-sink.h | 3 +- .../graph/component-class-source.h | 3 +- .../graph/private-query-executor.h | 48 ++++++ .../babeltrace2/graph/query-executor-const.h | 3 + include/babeltrace2/graph/query-executor.h | 17 ++- include/babeltrace2/types.h | 1 + src/bindings/python/bt2/bt2/component.py | 25 +-- .../bt2/bt2/native_bt_component_class.i | 41 ++--- .../python/bt2/bt2/native_bt_query_exec.i | 1 + src/bindings/python/bt2/bt2/query_executor.py | 94 ++++++++---- .../bt2/trace_collection_message_iterator.py | 4 +- src/cli/Makefile.am | 2 + src/cli/babeltrace2-cfg-cli-args.c | 2 +- src/cli/babeltrace2-cfg-src-auto-disc.c | 44 +++--- src/cli/babeltrace2-plugins.c | 2 +- src/cli/babeltrace2-query.c | 143 ++++++++++++++++++ src/cli/babeltrace2-query.h | 35 +++++ src/cli/babeltrace2.c | 88 +---------- src/lib/graph/query-executor.c | 111 ++++++++++---- src/lib/graph/query-executor.h | 11 ++ src/plugins/ctf/fs-src/fs.c | 6 +- src/plugins/ctf/fs-src/fs.h | 3 +- src/plugins/ctf/lttng-live/lttng-live.c | 7 +- src/plugins/ctf/lttng-live/lttng-live.h | 3 +- .../python/bt2/test_component_class.py | 40 ++--- tests/bindings/python/bt2/test_error.py | 6 +- .../python/bt2/test_query_executor.py | 89 ++++++++--- .../auto-source-discovery/bt_plugin_test.py | 6 +- tests/lib/plugin.c | 11 +- tests/lib/test-plugin-plugins/sfs.c | 3 +- .../src.ctf.fs/query/test_query_trace_info.py | 49 +++--- 34 files changed, 602 insertions(+), 305 deletions(-) create mode 100644 include/babeltrace2/graph/private-query-executor.h create mode 100644 src/cli/babeltrace2-query.c create mode 100644 src/cli/babeltrace2-query.h diff --git a/include/Makefile.am b/include/Makefile.am index 4baed59b..bddc8a5d 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -112,6 +112,7 @@ babeltrace2graphinclude_HEADERS = \ babeltrace2/graph/port-input-const.h \ babeltrace2/graph/port-output-const.h \ babeltrace2/graph/port-output-message-iterator.h \ + babeltrace2/graph/private-query-executor.h \ babeltrace2/graph/query-executor-const.h \ babeltrace2/graph/query-executor.h \ babeltrace2/graph/self-component-class-filter.h \ diff --git a/include/babeltrace2/babeltrace.h b/include/babeltrace2/babeltrace.h index d4613ca4..edd45d76 100644 --- a/include/babeltrace2/babeltrace.h +++ b/include/babeltrace2/babeltrace.h @@ -146,6 +146,7 @@ #include /* Query executor API */ +#include #include #include diff --git a/include/babeltrace2/graph/component-class-filter.h b/include/babeltrace2/graph/component-class-filter.h index 1b1bc66a..08c0ff48 100644 --- a/include/babeltrace2/graph/component-class-filter.h +++ b/include/babeltrace2/graph/component-class-filter.h @@ -82,9 +82,9 @@ typedef bt_bool typedef bt_component_class_query_method_status (*bt_component_class_filter_query_method)( bt_self_component_class_filter *comp_class, - const bt_query_executor *query_executor, + bt_private_query_executor *query_executor, const char *object, const bt_value *params, - bt_logging_level logging_level, const bt_value **result); + const bt_value **result); typedef bt_component_class_port_connected_method_status (*bt_component_class_filter_input_port_connected_method)( diff --git a/include/babeltrace2/graph/component-class-sink.h b/include/babeltrace2/graph/component-class-sink.h index 05bbd370..044895cf 100644 --- a/include/babeltrace2/graph/component-class-sink.h +++ b/include/babeltrace2/graph/component-class-sink.h @@ -48,9 +48,8 @@ typedef void (*bt_component_class_sink_finalize_method)( typedef bt_component_class_query_method_status (*bt_component_class_sink_query_method)( bt_self_component_class_sink *comp_class, - const bt_query_executor *query_executor, + bt_private_query_executor *query_executor, const char *object, const bt_value *params, - bt_logging_level logging_level, const bt_value **result); typedef bt_component_class_port_connected_method_status diff --git a/include/babeltrace2/graph/component-class-source.h b/include/babeltrace2/graph/component-class-source.h index 03648e2a..54cc2330 100644 --- a/include/babeltrace2/graph/component-class-source.h +++ b/include/babeltrace2/graph/component-class-source.h @@ -82,9 +82,8 @@ typedef bt_bool typedef bt_component_class_query_method_status (*bt_component_class_source_query_method)( bt_self_component_class_source *comp_class, - const bt_query_executor *query_executor, + bt_private_query_executor *query_executor, const char *object, const bt_value *params, - bt_logging_level logging_level, const bt_value **result); typedef bt_component_class_port_connected_method_status diff --git a/include/babeltrace2/graph/private-query-executor.h b/include/babeltrace2/graph/private-query-executor.h new file mode 100644 index 00000000..348d30d4 --- /dev/null +++ b/include/babeltrace2/graph/private-query-executor.h @@ -0,0 +1,48 @@ +#ifndef BABELTRACE2_GRAPH_PRIVATE_QUERY_EXECUTOR_H +#define BABELTRACE2_GRAPH_PRIVATE_QUERY_EXECUTOR_H + +/* + * Copyright (c) 2010-2019 EfficiOS Inc. and Linux Foundation + * + * 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. + */ + +#ifndef __BT_IN_BABELTRACE_H +# error "Please include instead." +#endif + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +static inline +const bt_query_executor * +bt_private_query_executor_as_query_executor_const( + bt_private_query_executor *query_executor) +{ + return __BT_UPCAST_CONST(bt_query_executor, query_executor); +} + +#ifdef __cplusplus +} +#endif + +#endif /* BABELTRACE2_GRAPH_PRIVATE_QUERY_EXECUTOR_H */ diff --git a/include/babeltrace2/graph/query-executor-const.h b/include/babeltrace2/graph/query-executor-const.h index 9b6be7e5..a857ed70 100644 --- a/include/babeltrace2/graph/query-executor-const.h +++ b/include/babeltrace2/graph/query-executor-const.h @@ -36,6 +36,9 @@ extern "C" { extern bt_bool bt_query_executor_is_interrupted( const bt_query_executor *query_executor); +extern bt_logging_level bt_query_executor_get_logging_level( + const bt_query_executor *query_executor); + extern void bt_query_executor_get_ref(const bt_query_executor *query_executor); extern void bt_query_executor_put_ref(const bt_query_executor *query_executor); diff --git a/include/babeltrace2/graph/query-executor.h b/include/babeltrace2/graph/query-executor.h index 460899bd..4ffc4ec4 100644 --- a/include/babeltrace2/graph/query-executor.h +++ b/include/babeltrace2/graph/query-executor.h @@ -35,7 +35,9 @@ extern "C" { #endif extern -bt_query_executor *bt_query_executor_create(void); +bt_query_executor *bt_query_executor_create( + const bt_component_class *component_class, const char *object, + const bt_value *params); typedef enum bt_query_executor_query_status { BT_QUERY_EXECUTOR_QUERY_STATUS_OK = __BT_FUNC_STATUS_OK, @@ -47,10 +49,7 @@ typedef enum bt_query_executor_query_status { extern bt_query_executor_query_status bt_query_executor_query( - bt_query_executor *query_executor, - const bt_component_class *component_class, - const char *object, const bt_value *params, - bt_logging_level logging_level, const bt_value **result); + bt_query_executor *query_executor, const bt_value **result); typedef enum bt_query_executor_add_interrupter_status { BT_QUERY_EXECUTOR_ADD_INTERRUPTER_STATUS_OK = __BT_FUNC_STATUS_OK, @@ -63,6 +62,14 @@ bt_query_executor_add_interrupter(bt_query_executor *query_executor, extern void bt_query_executor_interrupt(bt_query_executor *query_executor); +typedef enum bt_query_executor_set_logging_level_status { + BT_QUERY_EXECUTOR_SET_LOGGING_LEVEL_STATUS_OK = __BT_FUNC_STATUS_OK, +} bt_query_executor_set_logging_level_status; + +extern bt_query_executor_set_logging_level_status +bt_query_executor_set_logging_level(bt_query_executor *query_executor, + bt_logging_level logging_level); + #ifdef __cplusplus } #endif diff --git a/include/babeltrace2/types.h b/include/babeltrace2/types.h index 7f40fd8c..54bfc485 100644 --- a/include/babeltrace2/types.h +++ b/include/babeltrace2/types.h @@ -129,6 +129,7 @@ typedef struct bt_port bt_port; typedef struct bt_port_input bt_port_input; typedef struct bt_port_output bt_port_output; typedef struct bt_port_output_message_iterator bt_port_output_message_iterator; +typedef struct bt_private_query_executor bt_private_query_executor; typedef struct bt_query_executor bt_query_executor; typedef struct bt_self_component bt_self_component; typedef struct bt_self_component_class bt_self_component_class; diff --git a/src/bindings/python/bt2/bt2/component.py b/src/bindings/python/bt2/bt2/component.py index 865ff135..a057019a 100644 --- a/src/bindings/python/bt2/bt2/component.py +++ b/src/bindings/python/bt2/bt2/component.py @@ -573,7 +573,7 @@ class _UserComponentType(type): def addr(cls): return int(cls._bt_cc_ptr) - def _bt_query_from_native(cls, query_exec_ptr, obj, params_ptr, log_level): + def _bt_query_from_native(cls, priv_query_exec_ptr, obj, params_ptr): # this can raise, in which case the native call to # bt_component_class_query() returns NULL if params_ptr is not None: @@ -581,12 +581,19 @@ class _UserComponentType(type): else: params = None - query_exec = bt2_query_executor.QueryExecutor._create_from_ptr_and_get_ref( - query_exec_ptr - ) + priv_query_exec = bt2_query_executor._PrivateQueryExecutor(priv_query_exec_ptr) - # this can raise, but the native side checks the exception - results = cls._user_query(query_exec, obj, params, log_level) + try: + # this can raise, but the native side checks the exception + results = cls._user_query(priv_query_exec, obj, params) + finally: + # the private query executor is a private view on the query + # executor; it's not a shared object (the library does not + # offer an API to get/put a reference, just like "self" + # objects) from this query's point of view, so invalidate + # the object in case the user kept a reference and uses it + # later + priv_query_exec._invalidate() # this can raise, but the native side checks the exception results = bt2.create_value(results) @@ -594,15 +601,13 @@ class _UserComponentType(type): if results is None: results_ptr = native_bt.value_null else: - # return new reference results_ptr = results._ptr - # We return a new reference. + # return new reference bt2_value._Value._get_ref(results_ptr) - return int(results_ptr) - def _user_query(cls, query_executor, obj, params, log_level): + def _user_query(cls, priv_query_executor, obj, params): raise bt2.UnknownObject def _bt_component_class_ptr(self): diff --git a/src/bindings/python/bt2/bt2/native_bt_component_class.i b/src/bindings/python/bt2/bt2/native_bt_component_class.i index fffb4d7f..784b0f40 100644 --- a/src/bindings/python/bt2/bt2/native_bt_component_class.i +++ b/src/bindings/python/bt2/bt2/native_bt_component_class.i @@ -862,18 +862,22 @@ static bt_component_class_query_method_status component_class_query( const bt_component_class *component_class, bt_self_component_class *self_component_class, - const bt_query_executor *query_executor, + bt_private_query_executor *priv_query_executor, const char *object, const bt_value *params, - bt_logging_level log_level, const bt_value **result) { PyObject *py_cls = NULL; PyObject *py_params_ptr = NULL; - PyObject *py_query_exec_ptr = NULL; + PyObject *py_priv_query_exec_ptr = NULL; PyObject *py_query_func = NULL; PyObject *py_object = NULL; PyObject *py_results_addr = NULL; bt_component_class_query_method_status status = __BT_FUNC_STATUS_OK; + const bt_query_executor *query_exec = + bt_private_query_executor_as_query_executor_const( + priv_query_executor); + bt_logging_level log_level = + bt_query_executor_get_logging_level(query_exec); py_cls = lookup_cc_ptr_to_py_cls(component_class); if (!py_cls) { @@ -891,9 +895,10 @@ bt_component_class_query_method_status component_class_query( goto error; } - py_query_exec_ptr = SWIG_NewPointerObj(SWIG_as_voidptr(query_executor), - SWIGTYPE_p_bt_query_executor, 0); - if (!py_query_exec_ptr) { + py_priv_query_exec_ptr = SWIG_NewPointerObj( + SWIG_as_voidptr(priv_query_executor), + SWIGTYPE_p_bt_private_query_executor, 0); + if (!py_priv_query_exec_ptr) { BT_LOG_WRITE_CUR_LVL(BT_LOG_ERROR, log_level, BT_LOG_TAG, "Failed to create a SWIG pointer object."); goto error; @@ -907,8 +912,8 @@ bt_component_class_query_method_status component_class_query( } py_results_addr = PyObject_CallMethod(py_cls, - "_bt_query_from_native", "(OOOi)", py_query_exec_ptr, - py_object, py_params_ptr, (int) log_level); + "_bt_query_from_native", "(OOO)", py_priv_query_exec_ptr, + py_object, py_params_ptr); if (!py_results_addr) { BT_LOG_WRITE_CUR_LVL(BT_LOG_WARNING, log_level, BT_LOG_TAG, "Failed to call Python class's _bt_query_from_native() method: " @@ -934,7 +939,7 @@ error: end: Py_XDECREF(py_params_ptr); - Py_XDECREF(py_query_exec_ptr); + Py_XDECREF(py_priv_query_exec_ptr); Py_XDECREF(py_query_func); Py_XDECREF(py_object); Py_XDECREF(py_results_addr); @@ -944,46 +949,46 @@ end: static bt_component_class_query_method_status component_class_source_query( bt_self_component_class_source *self_component_class_source, - const bt_query_executor *query_executor, + bt_private_query_executor *priv_query_executor, const char *object, const bt_value *params, - bt_logging_level log_level, const bt_value **result) { const bt_component_class_source *component_class_source = bt_self_component_class_source_as_component_class_source(self_component_class_source); const bt_component_class *component_class = bt_component_class_source_as_component_class_const(component_class_source); bt_self_component_class *self_component_class = bt_self_component_class_source_as_self_component_class(self_component_class_source); - return component_class_query(component_class, self_component_class, query_executor, object, params, log_level, result); + return component_class_query(component_class, self_component_class, + priv_query_executor, object, params, result); } static bt_component_class_query_method_status component_class_filter_query( bt_self_component_class_filter *self_component_class_filter, - const bt_query_executor *query_executor, + bt_private_query_executor *priv_query_executor, const char *object, const bt_value *params, - bt_logging_level log_level, const bt_value **result) { const bt_component_class_filter *component_class_filter = bt_self_component_class_filter_as_component_class_filter(self_component_class_filter); const bt_component_class *component_class = bt_component_class_filter_as_component_class_const(component_class_filter); bt_self_component_class *self_component_class = bt_self_component_class_filter_as_self_component_class(self_component_class_filter); - return component_class_query(component_class, self_component_class, query_executor, object, params, log_level, result); + return component_class_query(component_class, self_component_class, + priv_query_executor, object, params, result); } static bt_component_class_query_method_status component_class_sink_query( bt_self_component_class_sink *self_component_class_sink, - const bt_query_executor *query_executor, + bt_private_query_executor *priv_query_executor, const char *object, const bt_value *params, - bt_logging_level log_level, const bt_value **result) { const bt_component_class_sink *component_class_sink = bt_self_component_class_sink_as_component_class_sink(self_component_class_sink); const bt_component_class *component_class = bt_component_class_sink_as_component_class_const(component_class_sink); bt_self_component_class *self_component_class = bt_self_component_class_sink_as_self_component_class(self_component_class_sink); - return component_class_query(component_class, self_component_class, query_executor, object, params, log_level, result); + return component_class_query(component_class, self_component_class, + priv_query_executor, object, params, result); } static diff --git a/src/bindings/python/bt2/bt2/native_bt_query_exec.i b/src/bindings/python/bt2/bt2/native_bt_query_exec.i index c8ccb29b..a69d7a58 100644 --- a/src/bindings/python/bt2/bt2/native_bt_query_exec.i +++ b/src/bindings/python/bt2/bt2/native_bt_query_exec.i @@ -22,5 +22,6 @@ * THE SOFTWARE. */ +%include %include %include diff --git a/src/bindings/python/bt2/bt2/query_executor.py b/src/bindings/python/bt2/bt2/query_executor.py index 146a2cf4..77b58574 100644 --- a/src/bindings/python/bt2/bt2/query_executor.py +++ b/src/bindings/python/bt2/bt2/query_executor.py @@ -28,37 +28,29 @@ from bt2 import value as bt2_value import bt2 -class QueryExecutor(object._SharedObject): - _get_ref = staticmethod(native_bt.query_executor_get_ref) - _put_ref = staticmethod(native_bt.query_executor_put_ref) +class _QueryExecutorCommon: + @property + def _common_ptr(self): + return self._as_query_executor_ptr() - def __init__(self): - ptr = native_bt.query_executor_create() + @property + def is_interrupted(self): + is_interrupted = native_bt.query_executor_is_interrupted(self._common_ptr) + return bool(is_interrupted) - if ptr is None: - raise bt2._MemoryError('cannot create query executor object') + @property + def logging_level(self): + return native_bt.query_executor_get_logging_level(self._common_ptr) - super().__init__(ptr) - def add_interrupter(self, interrupter): - utils._check_type(interrupter, bt2_interrupter.Interrupter) - native_bt.query_executor_add_interrupter(self._ptr, interrupter._ptr) +class QueryExecutor(object._SharedObject, _QueryExecutorCommon): + _get_ref = staticmethod(native_bt.query_executor_get_ref) + _put_ref = staticmethod(native_bt.query_executor_put_ref) - def interrupt(self): - native_bt.query_executor_interrupt(self._ptr) + def _as_query_executor_ptr(self): + return self._ptr - @property - def is_interrupted(self): - is_interrupted = native_bt.query_executor_is_interrupted(self._ptr) - return bool(is_interrupted) - - def query( - self, - component_class, - object, - params=None, - logging_level=bt2_logging.LoggingLevel.NONE, - ): + def __init__(self, component_class, object, params=None): if not isinstance(component_class, bt2_component._ComponentClass): err = False @@ -80,12 +72,54 @@ class QueryExecutor(object._SharedObject): params = bt2.create_value(params) params_ptr = params._ptr - utils._check_log_level(logging_level) cc_ptr = component_class._bt_component_class_ptr() + assert cc_ptr is not None + ptr = native_bt.query_executor_create(cc_ptr, object, params_ptr) + + if ptr is None: + raise bt2._MemoryError('cannot create query executor object') + + super().__init__(ptr) + + def add_interrupter(self, interrupter): + utils._check_type(interrupter, bt2_interrupter.Interrupter) + native_bt.query_executor_add_interrupter(self._ptr, interrupter._ptr) + + def interrupt(self): + native_bt.query_executor_interrupt(self._ptr) + + def _set_logging_level(self, log_level): + utils._check_log_level(log_level) + status = native_bt.query_executor_set_logging_level(self._ptr, log_level) + utils._handle_func_status(status, "cannot set query executor's logging level") - status, result_ptr = native_bt.query_executor_query( - self._ptr, cc_ptr, object, params_ptr, logging_level - ) + logging_level = property( + fget=_QueryExecutorCommon.logging_level, fset=_set_logging_level + ) + + @property + def is_interrupted(self): + is_interrupted = native_bt.query_executor_is_interrupted(self._ptr) + return bool(is_interrupted) + + def query(self): + status, result_ptr = native_bt.query_executor_query(self._ptr) utils._handle_func_status(status, 'cannot query component class') - assert result_ptr + assert result_ptr is not None return bt2_value._create_from_ptr(result_ptr) + + +class _PrivateQueryExecutor(_QueryExecutorCommon): + def __init__(self, ptr): + self._ptr = ptr + + def _check_validity(self): + if self._ptr is None: + raise RuntimeError('this object is not valid anymore') + + def _as_query_executor_ptr(self): + self._check_validity() + return native_bt.private_query_executor_as_query_executor_const(self._ptr) + + def _invalidate(self): + self._ptr = None diff --git a/src/bindings/python/bt2/bt2/trace_collection_message_iterator.py b/src/bindings/python/bt2/bt2/trace_collection_message_iterator.py index f7b819d9..fd579068 100644 --- a/src/bindings/python/bt2/bt2/trace_collection_message_iterator.py +++ b/src/bindings/python/bt2/bt2/trace_collection_message_iterator.py @@ -160,10 +160,10 @@ class TraceCollectionMessageIterator(bt2_message_iterator._MessageIterator): # query the port's component for the `babeltrace.trace-info` # object which contains the stream intersection range for each # exposed trace - query_exec = bt2.QueryExecutor() - trace_info_res = query_exec.query( + query_exec = bt2.QueryExecutor( src_comp_and_spec.comp.cls, 'babeltrace.trace-info', params ) + trace_info_res = query_exec.query() begin = None end = None diff --git a/src/cli/Makefile.am b/src/cli/Makefile.am index 8c871757..fdee56c1 100644 --- a/src/cli/Makefile.am +++ b/src/cli/Makefile.am @@ -36,6 +36,8 @@ babeltrace2_bin_SOURCES = \ babeltrace2-cfg-src-auto-disc.h \ babeltrace2-plugins.c \ babeltrace2-plugins.h \ + babeltrace2-query.c \ + babeltrace2-query.h \ logging.c \ logging.h diff --git a/src/cli/babeltrace2-cfg-cli-args.c b/src/cli/babeltrace2-cfg-cli-args.c index 8bf2c254..49ceca46 100644 --- a/src/cli/babeltrace2-cfg-cli-args.c +++ b/src/cli/babeltrace2-cfg-cli-args.c @@ -22,7 +22,7 @@ * SOFTWARE. */ -#define BT_LOG_TAG "CLI-CFG-CLI-ARGS" +#define BT_LOG_TAG "CLI/CFG-CLI-ARGS" #include "logging.h" #include diff --git a/src/cli/babeltrace2-cfg-src-auto-disc.c b/src/cli/babeltrace2-cfg-src-auto-disc.c index 22aae2da..1ffb1005 100644 --- a/src/cli/babeltrace2-cfg-src-auto-disc.c +++ b/src/cli/babeltrace2-cfg-src-auto-disc.c @@ -25,6 +25,7 @@ #include "babeltrace2-cfg-src-auto-disc.h" #include "babeltrace2-plugins.h" +#include "babeltrace2-query.h" #include "common/common.h" /* Finalize and free a `struct auto_source_discovery_result`. */ @@ -241,8 +242,7 @@ end: */ static int support_info_query_all_sources(const char *input, - const char *input_type, - bt_query_executor *query_executor, size_t plugin_count, + const char *input_type, size_t plugin_count, const char *plugin_restrict, const char *component_class_restrict, enum bt_logging_level log_level, @@ -319,8 +319,9 @@ int support_info_query_all_sources(const char *input, "type=%s", plugin_name, source_cc_name, input, input_type); BT_VALUE_PUT_REF_AND_RESET(query_result); - query_status = bt_query_executor_query(query_executor, cc, "babeltrace.support-info", - query_params, log_level, &query_result); + query_status = cli_query(cc, "babeltrace.support-info", + query_params, log_level, NULL, &query_result, + NULL); if (query_status == BT_QUERY_EXECUTOR_QUERY_STATUS_OK) { double weight; @@ -470,21 +471,19 @@ end: static int auto_discover_source_for_input_as_string(const char *input, - bt_query_executor *query_executor, size_t plugin_count, - const char *plugin_restrict, + size_t plugin_count, const char *plugin_restrict, const char *component_class_restrict, enum bt_logging_level log_level, struct auto_source_discovery *auto_disc) { return support_info_query_all_sources(input, "string", - query_executor, plugin_count, plugin_restrict, - component_class_restrict, log_level, auto_disc); + plugin_count, plugin_restrict, component_class_restrict, + log_level, auto_disc); } static int auto_discover_source_for_input_as_dir_or_file_rec(GString *input, - bt_query_executor *query_executor, size_t plugin_count, - const char *plugin_restrict, + size_t plugin_count, const char *plugin_restrict, const char *component_class_restrict, enum bt_logging_level log_level, struct auto_source_discovery *auto_disc) @@ -495,7 +494,7 @@ int auto_discover_source_for_input_as_dir_or_file_rec(GString *input, if (g_file_test(input->str, G_FILE_TEST_IS_REGULAR)) { /* It's a file. */ status = support_info_query_all_sources(input->str, - "file", query_executor, plugin_count, + "file", plugin_count, plugin_restrict, component_class_restrict, log_level, auto_disc); } else if (g_file_test(input->str, G_FILE_TEST_IS_DIR)) { GDir *dir; @@ -505,7 +504,7 @@ int auto_discover_source_for_input_as_dir_or_file_rec(GString *input, /* It's a directory. */ status = support_info_query_all_sources(input->str, - "directory", query_executor, plugin_count, + "directory", plugin_count, plugin_restrict, component_class_restrict, log_level, auto_disc); @@ -546,7 +545,7 @@ int auto_discover_source_for_input_as_dir_or_file_rec(GString *input, g_string_append(input, dirent); status = auto_discover_source_for_input_as_dir_or_file_rec( - input, query_executor, plugin_count, + input, plugin_count, plugin_restrict, component_class_restrict, log_level, auto_disc); @@ -596,8 +595,7 @@ end: static int auto_discover_source_for_input_as_dir_or_file(const char *input, - bt_query_executor *query_executor, size_t plugin_count, - const char *plugin_restrict, + size_t plugin_count, const char *plugin_restrict, const char *component_class_restrict, enum bt_logging_level log_level, struct auto_source_discovery *auto_disc) @@ -612,7 +610,7 @@ int auto_discover_source_for_input_as_dir_or_file(const char *input, } status = auto_discover_source_for_input_as_dir_or_file_rec( - mutable_input, query_executor, plugin_count, plugin_restrict, + mutable_input, plugin_count, plugin_restrict, component_class_restrict, log_level, auto_disc); g_string_free(mutable_input, TRUE); @@ -631,7 +629,6 @@ int auto_discover_source_components( uint64_t i_inputs, input_count; int status; size_t plugin_count; - bt_query_executor *query_executor = NULL; input_count = bt_value_array_get_size(inputs); @@ -642,19 +639,13 @@ int auto_discover_source_components( plugin_count = get_loaded_plugins_count(); - query_executor = bt_query_executor_create(); - if (!query_executor) { - BT_CLI_LOGE_APPEND_CAUSE("Failed to allocate a query executor."); - goto end; - } - for (i_inputs = 0; i_inputs < input_count; i_inputs++) { const bt_value *input_value; const char *input; input_value = bt_value_array_borrow_element_by_index_const(inputs, i_inputs); input = bt_value_string_get(input_value); - status = auto_discover_source_for_input_as_string(input, query_executor, + status = auto_discover_source_for_input_as_string(input, plugin_count, plugin_restrict, component_class_restrict, log_level, auto_disc); if (status < 0) { @@ -666,8 +657,8 @@ int auto_discover_source_components( } status = auto_discover_source_for_input_as_dir_or_file(input, - query_executor, plugin_count, plugin_restrict, - component_class_restrict, log_level, auto_disc); + plugin_count, plugin_restrict, component_class_restrict, + log_level, auto_disc); if (status < 0) { /* Fatal error. */ goto end; @@ -683,6 +674,5 @@ int auto_discover_source_components( status = 0; end: - bt_query_executor_put_ref(query_executor); return status; } diff --git a/src/cli/babeltrace2-plugins.c b/src/cli/babeltrace2-plugins.c index cc950ff2..73123408 100644 --- a/src/cli/babeltrace2-plugins.c +++ b/src/cli/babeltrace2-plugins.c @@ -22,7 +22,7 @@ * SOFTWARE. */ -#define BT_LOG_TAG "CLI" +#define BT_LOG_TAG "CLI/PLUGINS" #include "logging.h" #include "babeltrace2-plugins.h" diff --git a/src/cli/babeltrace2-query.c b/src/cli/babeltrace2-query.c new file mode 100644 index 00000000..4455bcc4 --- /dev/null +++ b/src/cli/babeltrace2-query.c @@ -0,0 +1,143 @@ +/* + * Copyright 2016-2019 EfficiOS Inc. + * + * 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 "CLI/QUERY" +#include "logging.h" + +#include + +#include "common/common.h" + +#include "babeltrace2-query.h" + +static +void set_fail_reason(const char **fail_reason, const char *reason) +{ + if (fail_reason) { + *fail_reason = reason; + } +} + +BT_HIDDEN +bt_query_executor_query_status cli_query(const bt_component_class *comp_cls, + const char *obj, const bt_value *params, + bt_logging_level log_level, const bt_interrupter *interrupter, + const bt_value **user_result, const char **fail_reason) +{ + const bt_value *result = NULL; + bt_query_executor_query_status status; + bt_query_executor *query_exec; + + set_fail_reason(fail_reason, "unknown error"); + BT_ASSERT(user_result); + query_exec = bt_query_executor_create(comp_cls, obj, params); + if (!query_exec) { + BT_CLI_LOGE_APPEND_CAUSE("Cannot create a query executor."); + goto error; + } + + if (bt_query_executor_set_logging_level(query_exec, log_level) != + BT_QUERY_EXECUTOR_SET_LOGGING_LEVEL_STATUS_OK) { + BT_CLI_LOGE_APPEND_CAUSE( + "Cannot set query executor's logging level: " + "log-level=%s", + bt_common_logging_level_string(log_level)); + goto error; + } + + if (interrupter) { + if (bt_query_executor_add_interrupter(query_exec, + interrupter) != + BT_QUERY_EXECUTOR_ADD_INTERRUPTER_STATUS_OK) { + BT_CLI_LOGE_APPEND_CAUSE( + "Cannot add interrupter to query executor."); + goto error; + } + } + + while (true) { + status = bt_query_executor_query(query_exec, &result); + switch (status) { + case BT_QUERY_EXECUTOR_QUERY_STATUS_OK: + goto ok; + case BT_QUERY_EXECUTOR_QUERY_STATUS_AGAIN: + { + const uint64_t sleep_time_us = 100000; + + if (interrupter && bt_interrupter_is_set(interrupter)) { + set_fail_reason(fail_reason, "interrupted by user"); + goto error; + } + + /* Wait 100 ms and retry */ + BT_LOGD("Got BT_QUERY_EXECUTOR_QUERY_STATUS_AGAIN: sleeping: " + "time-us=%" PRIu64, sleep_time_us); + + if (usleep(sleep_time_us)) { + if (interrupter && bt_interrupter_is_set(interrupter)) { + BT_CLI_LOGW_APPEND_CAUSE( + "Query was interrupted by user: " + "comp-cls-addr=%p, comp-cls-name=\"%s\", " + "query-obj=\"%s\"", comp_cls, + bt_component_class_get_name(comp_cls), + obj); + set_fail_reason(fail_reason, + "interrupted by user"); + goto error; + } + } + + continue; + } + case BT_QUERY_EXECUTOR_QUERY_STATUS_ERROR: + if (interrupter && bt_interrupter_is_set(interrupter)) { + set_fail_reason(fail_reason, "interrupted by user"); + goto error; + } + + goto error; + case BT_QUERY_EXECUTOR_QUERY_STATUS_UNKNOWN_OBJECT: + set_fail_reason(fail_reason, "unknown query object"); + goto end; + case BT_QUERY_EXECUTOR_QUERY_STATUS_MEMORY_ERROR: + set_fail_reason(fail_reason, "not enough memory"); + goto error; + default: + BT_LOGF("Unknown query status: status=%s", + bt_common_func_status_string(status)); + abort(); + } + } + +ok: + *user_result = result; + result = NULL; + goto end; + +error: + status = BT_QUERY_EXECUTOR_QUERY_STATUS_ERROR; + +end: + bt_query_executor_put_ref(query_exec); + bt_value_put_ref(result); + return status; +} diff --git a/src/cli/babeltrace2-query.h b/src/cli/babeltrace2-query.h new file mode 100644 index 00000000..c8d8a15d --- /dev/null +++ b/src/cli/babeltrace2-query.h @@ -0,0 +1,35 @@ +#ifndef CLI_BABELTRACE_QUERY_H +#define CLI_BABELTRACE_QUERY_H + +/* + * Copyright 2016-2019 EfficiOS Inc. + * + * 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 +#include "common/macros.h" + +BT_HIDDEN +bt_query_executor_query_status cli_query(const bt_component_class *comp_cls, + const char *obj, const bt_value *params, + bt_logging_level log_level, const bt_interrupter *interrupter, + const bt_value **user_result, const char **fail_reason); + +#endif /* CLI_BABELTRACE_QUERY_H */ diff --git a/src/cli/babeltrace2.c b/src/cli/babeltrace2.c index 12d9cc0c..6a344024 100644 --- a/src/cli/babeltrace2.c +++ b/src/cli/babeltrace2.c @@ -40,6 +40,7 @@ #include "babeltrace2-cfg-cli-args.h" #include "babeltrace2-cfg-cli-args-default.h" #include "babeltrace2-plugins.h" +#include "babeltrace2-query.h" #define ENV_BABELTRACE_WARN_COMMAND_NAME_DIRECTORY_CLASH "BABELTRACE_CLI_WARN_COMMAND_NAME_DIRECTORY_CLASH" #define ENV_BABELTRACE_CLI_LOG_LEVEL "BABELTRACE_CLI_LOG_LEVEL" @@ -115,93 +116,10 @@ int query(struct bt_config *cfg, const bt_component_class *comp_cls, const char *obj, const bt_value *params, const bt_value **user_result, const char **fail_reason) { - const bt_value *result = NULL; - bt_query_executor_query_status query_status; - bt_query_executor *query_exec; - *fail_reason = "unknown error"; - int ret = 0; - - BT_ASSERT(fail_reason); - BT_ASSERT(user_result); - query_exec = bt_query_executor_create(); - if (!query_exec) { - BT_CLI_LOGE_APPEND_CAUSE("Cannot create a query executor."); - goto error; - } - - bt_query_executor_add_interrupter(query_exec, the_interrupter); - - while (true) { - query_status = bt_query_executor_query( - query_exec, comp_cls, obj, params, - cfg->log_level, &result); - switch (query_status) { - case BT_QUERY_EXECUTOR_QUERY_STATUS_OK: - goto ok; - case BT_QUERY_EXECUTOR_QUERY_STATUS_AGAIN: - { - const uint64_t sleep_time_us = 100000; - - if (bt_interrupter_is_set(the_interrupter)) { - *fail_reason = "interrupted by user"; - goto error; - } - - /* Wait 100 ms and retry */ - BT_LOGD("Got BT_QUERY_EXECUTOR_QUERY_STATUS_AGAIN: sleeping: " - "time-us=%" PRIu64, sleep_time_us); - - if (usleep(sleep_time_us)) { - if (bt_interrupter_is_set(the_interrupter)) { - BT_CLI_LOGW_APPEND_CAUSE( - "Query was interrupted by user: " - "comp-cls-addr=%p, comp-cls-name=\"%s\", " - "query-obj=\"%s\"", comp_cls, - bt_component_class_get_name(comp_cls), - obj); - *fail_reason = "interrupted by user"; - goto error; - } - } - - continue; - } - case BT_QUERY_EXECUTOR_QUERY_STATUS_ERROR: - if (bt_interrupter_is_set(the_interrupter)) { - *fail_reason = "interrupted by user"; - goto error; - } - - goto error; - case BT_QUERY_EXECUTOR_QUERY_STATUS_UNKNOWN_OBJECT: - *fail_reason = "unknown query object"; - goto error; - case BT_QUERY_EXECUTOR_QUERY_STATUS_MEMORY_ERROR: - *fail_reason = "not enough memory"; - goto error; - default: - BT_LOGF("Unknown query status: status=%s", - bt_common_func_status_string(query_status)); - abort(); - } - } - -ok: - *user_result = result; - result = NULL; - goto end; - -error: - ret = -1; - -end: - bt_query_executor_put_ref(query_exec); - bt_value_put_ref(result); - return ret; + return cli_query(comp_cls, obj, params, cfg->log_level, + the_interrupter, user_result, fail_reason); } - - typedef const void *(*plugin_borrow_comp_cls_func_t)( const bt_plugin *, const char *); diff --git a/src/lib/graph/query-executor.c b/src/lib/graph/query-executor.c index a602911c..ebc1991e 100644 --- a/src/lib/graph/query-executor.c +++ b/src/lib/graph/query-executor.c @@ -54,16 +54,31 @@ void bt_query_executor_destroy(struct bt_object *obj) query_exec->interrupters = NULL; } - BT_OBJECT_PUT_REF_AND_RESET(query_exec->default_interrupter); + BT_LOGD_STR("Putting component class."); + BT_OBJECT_PUT_REF_AND_RESET(query_exec->comp_cls); + + if (query_exec->object) { + g_string_free(query_exec->object, TRUE); + query_exec->object = NULL; + } + BT_LOGD_STR("Putting parameters."); + BT_OBJECT_PUT_REF_AND_RESET(query_exec->params); + BT_OBJECT_PUT_REF_AND_RESET(query_exec->default_interrupter); g_free(query_exec); } -struct bt_query_executor *bt_query_executor_create(void) +struct bt_query_executor *bt_query_executor_create( + const bt_component_class *comp_cls, const char *object, + const bt_value *params) { struct bt_query_executor *query_exec; - BT_LOGD_STR("Creating query executor."); + BT_ASSERT_PRE_NON_NULL(comp_cls, "Component class"); + BT_ASSERT_PRE_NON_NULL(object, "Object"); + BT_LIB_LOGD("Creating query executor: " + "%![comp-cls-]+C, object=\"%s\", %![params-]%+v", + comp_cls, object, params); query_exec = g_new0(struct bt_query_executor, 1); if (!query_exec) { BT_LIB_LOGE_APPEND_CAUSE( @@ -87,11 +102,31 @@ struct bt_query_executor *bt_query_executor_create(void) goto end; } + query_exec->object = g_string_new(object); + if (!query_exec->object) { + BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate one GString."); + BT_OBJECT_PUT_REF_AND_RESET(query_exec); + goto end; + } + + query_exec->comp_cls = comp_cls; + bt_object_get_no_null_check(query_exec->comp_cls); + + if (!params) { + query_exec->params = bt_value_null; + } else { + query_exec->params = params; + } + + bt_object_get_no_null_check(query_exec->params); + query_exec->log_level = BT_LOGGING_LEVEL_NONE; bt_query_executor_add_interrupter(query_exec, query_exec->default_interrupter); bt_object_init_shared(&query_exec->base, bt_query_executor_destroy); - BT_LOGD("Created query executor: addr=%p", query_exec); + BT_LIB_LOGD("Created query executor: " + "addr=%p, %![comp-cls-]+C, object=\"%s\", %![params-]%+v", + query_exec, comp_cls, object, params); end: return (void *) query_exec; @@ -99,22 +134,20 @@ end: enum bt_query_executor_query_status bt_query_executor_query( struct bt_query_executor *query_exec, - const struct bt_component_class *comp_cls, - const char *object, const struct bt_value *params, - enum bt_logging_level log_level, const struct bt_value **user_result) { - typedef enum bt_component_class_query_method_status (*method_t)(void *, - const void *, const void *, const void *, enum bt_logging_level, - const void *); + typedef enum bt_component_class_query_method_status (*method_t)( + void * /* self component class */, + void * /* private query executor */, + const char * /* object */, + const struct bt_value * /* parameters */, + const struct bt_value ** /* result */); enum bt_query_executor_query_status status; enum bt_component_class_query_method_status query_status; method_t method = NULL; BT_ASSERT_PRE_NON_NULL(query_exec, "Query executor"); - BT_ASSERT_PRE_NON_NULL(comp_cls, "Component class"); - BT_ASSERT_PRE_NON_NULL(object, "Object"); BT_ASSERT_PRE_NON_NULL(user_result, "Result (output)"); /* @@ -133,34 +166,34 @@ enum bt_query_executor_query_status bt_query_executor_query( "not performing the query operation: " "query-exec-addr=%p, %![cc-]+C, object=\"%s\", " "%![params-]+v, log-level=%s", - query_exec, comp_cls, object, params, - bt_common_logging_level_string(log_level)); + query_exec, query_exec->comp_cls, + query_exec->object->str, query_exec->params, + bt_common_logging_level_string(query_exec->log_level)); status = BT_FUNC_STATUS_AGAIN; goto end; } - if (!params) { - params = bt_value_null; - } - - switch (comp_cls->type) { + switch (query_exec->comp_cls->type) { case BT_COMPONENT_CLASS_TYPE_SOURCE: { - struct bt_component_class_source *src_cc = (void *) comp_cls; + struct bt_component_class_source *src_cc = (void *) + query_exec->comp_cls; method = (method_t) src_cc->methods.query; break; } case BT_COMPONENT_CLASS_TYPE_FILTER: { - struct bt_component_class_filter *flt_cc = (void *) comp_cls; + struct bt_component_class_filter *flt_cc = (void *) + query_exec->comp_cls; method = (method_t) flt_cc->methods.query; break; } case BT_COMPONENT_CLASS_TYPE_SINK: { - struct bt_component_class_sink *sink_cc = (void *) comp_cls; + struct bt_component_class_sink *sink_cc = (void *) + query_exec->comp_cls; method = (method_t) sink_cc->methods.query; break; @@ -172,7 +205,7 @@ enum bt_query_executor_query_status bt_query_executor_query( if (!method) { /* Not an error: nothing to query */ BT_LIB_LOGD("Component class has no registered query method: " - "%!+C", comp_cls); + "%!+C", query_exec->comp_cls); status = BT_FUNC_STATUS_UNKNOWN_OBJECT; goto end; } @@ -180,11 +213,13 @@ enum bt_query_executor_query_status bt_query_executor_query( BT_LIB_LOGD("Calling user's query method: " "query-exec-addr=%p, %![cc-]+C, object=\"%s\", %![params-]+v, " "log-level=%s", - query_exec, comp_cls, object, params, - bt_common_logging_level_string(log_level)); + query_exec, query_exec->comp_cls, query_exec->object->str, + query_exec->params, + bt_common_logging_level_string(query_exec->log_level)); *user_result = NULL; - query_status = method((void *) comp_cls, query_exec, object, params, - log_level, user_result); + query_status = method((void *) query_exec->comp_cls, + (void *) query_exec, query_exec->object->str, + query_exec->params, user_result); BT_LIB_LOGD("User method returned: status=%s, %![res-]+v", bt_common_func_status_string(query_status), *user_result); BT_ASSERT_POST(query_status != BT_FUNC_STATUS_OK || *user_result, @@ -195,8 +230,10 @@ enum bt_query_executor_query_status bt_query_executor_query( BT_LIB_LOGW_APPEND_CAUSE( "Component class's \"query\" method failed: " "query-exec-addr=%p, %![cc-]+C, object=\"%s\", " - "%![params-]+v, log-level=%s", query_exec, comp_cls, - object, params, bt_common_logging_level_string(log_level)); + "%![params-]+v, log-level=%s", query_exec, + query_exec->comp_cls, query_exec->object->str, + query_exec->params, + bt_common_logging_level_string(query_exec->log_level)); goto end; } @@ -233,6 +270,22 @@ void bt_query_executor_interrupt(struct bt_query_executor *query_exec) query_exec); } +enum bt_query_executor_set_logging_level_status +bt_query_executor_set_logging_level(struct bt_query_executor *query_exec, + enum bt_logging_level log_level) +{ + BT_ASSERT_PRE_NON_NULL(query_exec, "Query executor"); + query_exec->log_level = log_level; + return BT_FUNC_STATUS_OK; +} + +enum bt_logging_level bt_query_executor_get_logging_level( + const struct bt_query_executor *query_exec) +{ + BT_ASSERT_PRE_NON_NULL(query_exec, "Query executor"); + return query_exec->log_level; +} + void bt_query_executor_get_ref(const struct bt_query_executor *query_executor) { bt_object_get_ref(query_executor); diff --git a/src/lib/graph/query-executor.h b/src/lib/graph/query-executor.h index c1dcc9c4..250bc1b8 100644 --- a/src/lib/graph/query-executor.h +++ b/src/lib/graph/query-executor.h @@ -30,6 +30,7 @@ #include #include "lib/object.h" +#include "lib/value.h" struct bt_query_executor { struct bt_object base; @@ -46,6 +47,16 @@ struct bt_query_executor { * owned by this. */ struct bt_interrupter *default_interrupter; + + /* Owned by this */ + const struct bt_component_class *comp_cls; + + GString *object; + + /* Owned by this */ + const struct bt_value *params; + + enum bt_logging_level log_level; }; #endif /* BABELTRACE_GRAPH_QUERY_EXECUTOR_INTERNAL_H */ diff --git a/src/plugins/ctf/fs-src/fs.c b/src/plugins/ctf/fs-src/fs.c index 398708db..8b6d547a 100644 --- a/src/plugins/ctf/fs-src/fs.c +++ b/src/plugins/ctf/fs-src/fs.c @@ -1989,13 +1989,15 @@ bt_component_class_init_method_status ctf_fs_init( BT_HIDDEN bt_component_class_query_method_status ctf_fs_query( bt_self_component_class_source *comp_class, - const bt_query_executor *query_exec, + bt_private_query_executor *priv_query_exec, const char *object, const bt_value *params, - bt_logging_level log_level, const bt_value **result) { bt_component_class_query_method_status status = BT_COMPONENT_CLASS_QUERY_METHOD_STATUS_OK; + bt_logging_level log_level = bt_query_executor_get_logging_level( + bt_private_query_executor_as_query_executor_const( + priv_query_exec)); if (strcmp(object, "metadata-info") == 0) { status = metadata_info_query(comp_class, params, log_level, diff --git a/src/plugins/ctf/fs-src/fs.h b/src/plugins/ctf/fs-src/fs.h index 8e7ca952..74432046 100644 --- a/src/plugins/ctf/fs-src/fs.h +++ b/src/plugins/ctf/fs-src/fs.h @@ -213,9 +213,8 @@ void ctf_fs_finalize(bt_self_component_source *component); BT_HIDDEN bt_component_class_query_method_status ctf_fs_query( bt_self_component_class_source *comp_class, - const bt_query_executor *query_exec, + bt_private_query_executor *priv_query_exec, const char *object, const bt_value *params, - bt_logging_level log_level, const bt_value **result); BT_HIDDEN diff --git a/src/plugins/ctf/lttng-live/lttng-live.c b/src/plugins/ctf/lttng-live/lttng-live.c index 7b5eddbd..62dc28f0 100644 --- a/src/plugins/ctf/lttng-live/lttng-live.c +++ b/src/plugins/ctf/lttng-live/lttng-live.c @@ -1443,13 +1443,16 @@ end: BT_HIDDEN bt_component_class_query_method_status lttng_live_query( bt_self_component_class_source *comp_class, - const bt_query_executor *query_exec, + bt_private_query_executor *priv_query_exec, const char *object, const bt_value *params, - bt_logging_level log_level, const bt_value **result) + const bt_value **result) { bt_component_class_query_method_status status = BT_COMPONENT_CLASS_QUERY_METHOD_STATUS_OK; bt_self_component *self_comp = NULL; + bt_logging_level log_level = bt_query_executor_get_logging_level( + bt_private_query_executor_as_query_executor_const( + priv_query_exec)); if (strcmp(object, "sessions") == 0) { status = lttng_live_query_list_sessions(params, result, diff --git a/src/plugins/ctf/lttng-live/lttng-live.h b/src/plugins/ctf/lttng-live/lttng-live.h index 77632daf..3ae12082 100644 --- a/src/plugins/ctf/lttng-live/lttng-live.h +++ b/src/plugins/ctf/lttng-live/lttng-live.h @@ -263,9 +263,8 @@ bt_component_class_init_method_status lttng_live_component_init( bt_component_class_query_method_status lttng_live_query( bt_self_component_class_source *comp_class, - const bt_query_executor *query_exec, + bt_private_query_executor *priv_query_exec, const char *object, const bt_value *params, - bt_logging_level log_level, const bt_value **result); void lttng_live_component_finalize(bt_self_component_source *component); diff --git a/tests/bindings/python/bt2/test_component_class.py b/tests/bindings/python/bt2/test_component_class.py index aa13cd6a..00a952c2 100644 --- a/tests/bindings/python/bt2/test_component_class.py +++ b/tests/bindings/python/bt2/test_component_class.py @@ -185,7 +185,7 @@ class UserComponentClassTestCase(unittest.TestCase): pass with self.assertRaises(bt2.UnknownObject): - bt2.QueryExecutor().query(MySink, 'obj', 23) + bt2.QueryExecutor(MySink, 'obj', 23).query() def test_query_raises(self): class MySink(bt2._UserSinkComponent): @@ -193,11 +193,11 @@ class UserComponentClassTestCase(unittest.TestCase): pass @classmethod - def _user_query(cls, query_exec, obj, params, log_level): + def _user_query(cls, priv_query_exec, obj, params): raise ValueError with self.assertRaises(bt2._Error): - bt2.QueryExecutor().query(MySink, 'obj', 23) + bt2.QueryExecutor(MySink, 'obj', 23).query() def test_query_wrong_return_type(self): class MySink(bt2._UserSinkComponent): @@ -205,11 +205,11 @@ class UserComponentClassTestCase(unittest.TestCase): pass @classmethod - def _user_query(cls, query_exec, obj, params, log_level): + def _user_query(cls, priv_query_exec, obj, params): return ... with self.assertRaises(bt2._Error): - bt2.QueryExecutor().query(MySink, 'obj', 23) + bt2.QueryExecutor(MySink, 'obj', 23).query() def test_query_params_none(self): class MySink(bt2._UserSinkComponent): @@ -217,14 +217,14 @@ class UserComponentClassTestCase(unittest.TestCase): pass @classmethod - def _user_query(cls, query_exec, obj, params, log_level): + def _user_query(cls, priv_query_exec, obj, params): nonlocal query_params query_params = params return None query_params = None params = None - res = bt2.QueryExecutor().query(MySink, 'obj', params) + res = bt2.QueryExecutor(MySink, 'obj', params).query() self.assertEqual(query_params, params) self.assertIsNone(res) del query_params @@ -235,12 +235,14 @@ class UserComponentClassTestCase(unittest.TestCase): pass @classmethod - def _user_query(cls, query_exec, obj, params, log_level): + def _user_query(cls, priv_query_exec, obj, params): nonlocal query_log_level - query_log_level = log_level + query_log_level = priv_query_exec.logging_level query_log_level = None - res = bt2.QueryExecutor().query(MySink, 'obj', None, bt2.LoggingLevel.WARNING) + query_exec = bt2.QueryExecutor(MySink, 'obj', None) + query_exec.logging_level = bt2.LoggingLevel.WARNING + query_exec.query() self.assertEqual(query_log_level, bt2.LoggingLevel.WARNING) del query_log_level @@ -250,10 +252,10 @@ class UserComponentClassTestCase(unittest.TestCase): pass @staticmethod - def _user_query(query_exec, obj, params, log_level): + def _user_query(priv_query_exec, obj, params): return - res = bt2.QueryExecutor().query(MySink, 'obj', None) + res = bt2.QueryExecutor(MySink, 'obj', None).query() self.assertIsNone(res) def test_query_simple(self): @@ -262,14 +264,14 @@ class UserComponentClassTestCase(unittest.TestCase): pass @classmethod - def _user_query(cls, query_exec, obj, params, log_level): + def _user_query(cls, priv_query_exec, obj, params): nonlocal query_params query_params = params return 17.5 query_params = None params = ['coucou', 23, None] - res = bt2.QueryExecutor().query(MySink, 'obj', params) + res = bt2.QueryExecutor(MySink, 'obj', params).query() self.assertEqual(query_params, params) self.assertEqual(res, 17.5) del query_params @@ -280,7 +282,7 @@ class UserComponentClassTestCase(unittest.TestCase): pass @classmethod - def _user_query(cls, query_exec, obj, params, log_level): + def _user_query(cls, priv_query_exec, obj, params): nonlocal query_params query_params = params return {'null': None, 'bt2': 'BT2'} @@ -292,7 +294,7 @@ class UserComponentClassTestCase(unittest.TestCase): 'null': None, } - res = bt2.QueryExecutor().query(MySink, 'obj', params) + res = bt2.QueryExecutor(MySink, 'obj', params).query() self.assertEqual(query_params, params) self.assertEqual(res, {'null': None, 'bt2': 'BT2'}) del query_params @@ -318,7 +320,7 @@ class ComponentClassTestCase(unittest.TestCase): pass @classmethod - def _user_query(cls, query_exec, obj, params, log_level): + def _user_query(cls, priv_query_exec, obj, params): return [obj, params, 23] self._py_comp_cls = MySink @@ -352,8 +354,8 @@ class ComponentClassTestCase(unittest.TestCase): self.assertEqual(self._py_comp_cls, self._comp_cls) def test_query(self): - res = bt2.QueryExecutor().query( + res = bt2.QueryExecutor( self._comp_cls, 'an object', {'yes': 'no', 'book': -17} - ) + ).query() expected = ['an object', {'yes': 'no', 'book': -17}, 23] self.assertEqual(res, expected) diff --git a/tests/bindings/python/bt2/test_error.py b/tests/bindings/python/bt2/test_error.py index ca750aea..b09dded2 100644 --- a/tests/bindings/python/bt2/test_error.py +++ b/tests/bindings/python/bt2/test_error.py @@ -70,7 +70,7 @@ class SinkWithFailingQuery(bt2._UserSinkComponent): pass @staticmethod - def _user_query(executor, obj, params, log_level): + def _user_query(priv_executor, obj, params): raise ValueError('Query is failing') @@ -177,10 +177,10 @@ class ErrorTestCase(unittest.TestCase): self.assertIsNone(cause.plugin_name) def test_component_class_error_cause(self): - q = bt2.QueryExecutor() + q = bt2.QueryExecutor(SinkWithFailingQuery, 'hello') with self.assertRaises(bt2._Error) as ctx: - q.query(SinkWithFailingQuery, 'hello') + q.query() cause = ctx.exception[0] self.assertIs(type(cause), bt2._ComponentClassErrorCause) diff --git a/tests/bindings/python/bt2/test_query_executor.py b/tests/bindings/python/bt2/test_query_executor.py index 6d0cc3bd..453cf5fe 100644 --- a/tests/bindings/python/bt2/test_query_executor.py +++ b/tests/bindings/python/bt2/test_query_executor.py @@ -29,7 +29,7 @@ class QueryExecutorTestCase(unittest.TestCase): pass @classmethod - def _user_query(cls, query_exec, obj, params, log_level): + def _user_query(cls, priv_query_exec, obj, params): nonlocal query_params query_params = params return {'null': None, 'bt2': 'BT2'} @@ -41,7 +41,7 @@ class QueryExecutorTestCase(unittest.TestCase): 'null': None, } - res = bt2.QueryExecutor().query(MySink, 'obj', params) + res = bt2.QueryExecutor(MySink, 'obj', params).query() self.assertEqual(query_params, params) self.assertEqual(res, {'null': None, 'bt2': 'BT2'}) del query_params @@ -52,13 +52,28 @@ class QueryExecutorTestCase(unittest.TestCase): pass @classmethod - def _user_query(cls, query_exec, obj, params, log_level): + def _user_query(cls, priv_query_exec, obj, params): nonlocal query_params query_params = params query_params = 23 - res = bt2.QueryExecutor().query(MySink, 'obj', None) - self.assertEqual(query_params, None) + res = bt2.QueryExecutor(MySink, 'obj', None).query() + self.assertIs(query_params, None) + del query_params + + def test_query_no_params(self): + class MySink(bt2._UserSinkComponent): + def _user_consume(self): + pass + + @classmethod + def _user_query(cls, priv_query_exec, obj, params): + nonlocal query_params + query_params = params + + query_params = 23 + res = bt2.QueryExecutor(MySink, 'obj').query() + self.assertIs(query_params, None) del query_params def test_query_logging_level(self): @@ -67,12 +82,14 @@ class QueryExecutorTestCase(unittest.TestCase): pass @classmethod - def _user_query(cls, query_exec, obj, params, log_level): + def _user_query(cls, priv_query_exec, obj, params): nonlocal query_log_level - query_log_level = log_level + query_log_level = priv_query_exec.logging_level query_log_level = None - res = bt2.QueryExecutor().query(MySink, 'obj', None, bt2.LoggingLevel.INFO) + query_exec = bt2.QueryExecutor(MySink, 'obj', None) + query_exec.logging_level = bt2.LoggingLevel.INFO + query_exec.query() self.assertEqual(query_log_level, bt2.LoggingLevel.INFO) del query_log_level @@ -82,11 +99,11 @@ class QueryExecutorTestCase(unittest.TestCase): pass @classmethod - def _user_query(cls, query_exec, obj, params, log_level): + def _user_query(cls, priv_query_exec, obj, params): raise ValueError with self.assertRaises(bt2._Error) as ctx: - res = bt2.QueryExecutor().query(MySink, 'obj', [17, 23]) + res = bt2.QueryExecutor(MySink, 'obj', [17, 23]).query() exc = ctx.exception self.assertEqual(len(exc), 2) @@ -102,11 +119,11 @@ class QueryExecutorTestCase(unittest.TestCase): pass @classmethod - def _user_query(cls, query_exec, obj, params, log_level): + def _user_query(cls, priv_query_exec, obj, params): raise bt2.UnknownObject with self.assertRaises(bt2.UnknownObject): - res = bt2.QueryExecutor().query(MySink, 'obj', [17, 23]) + res = bt2.QueryExecutor(MySink, 'obj', [17, 23]).query() def test_query_logging_level_invalid_type(self): class MySink(bt2._UserSinkComponent): @@ -114,11 +131,13 @@ class QueryExecutorTestCase(unittest.TestCase): pass @classmethod - def _user_query(cls, query_exec, obj, params, log_level): + def _user_query(cls, priv_query_exec, obj, params): pass + query_exec = bt2.QueryExecutor(MySink, 'obj', [17, 23]) + with self.assertRaises(TypeError): - res = bt2.QueryExecutor().query(MySink, 'obj', [17, 23], 'yeah') + query_exec.logging_level = 'yeah' def test_query_logging_level_invalid_value(self): class MySink(bt2._UserSinkComponent): @@ -126,11 +145,13 @@ class QueryExecutorTestCase(unittest.TestCase): pass @classmethod - def _user_query(cls, query_exec, obj, params, log_level): + def _user_query(cls, priv_query_exec, obj, params): pass + query_exec = bt2.QueryExecutor(MySink, 'obj', [17, 23]) + with self.assertRaises(ValueError): - res = bt2.QueryExecutor().query(MySink, 'obj', [17, 23], 12345) + query_exec.logging_level = 12345 def test_query_try_again(self): class MySink(bt2._UserSinkComponent): @@ -138,11 +159,11 @@ class QueryExecutorTestCase(unittest.TestCase): pass @classmethod - def _user_query(cls, query_exec, obj, params, log_level): + def _user_query(cls, priv_query_exec, obj, params): raise bt2.TryAgain with self.assertRaises(bt2.TryAgain): - res = bt2.QueryExecutor().query(MySink, 'obj', [17, 23]) + res = bt2.QueryExecutor(MySink, 'obj', [17, 23]).query() def test_query_add_interrupter(self): class MySink(bt2._UserSinkComponent): @@ -150,7 +171,7 @@ class QueryExecutorTestCase(unittest.TestCase): pass @classmethod - def _user_query(cls, query_exec, obj, params, log_level): + def _user_query(cls, priv_query_exec, obj, params): nonlocal interrupter2 test_self.assertFalse(query_exec.is_interrupted) interrupter2.set() @@ -161,10 +182,10 @@ class QueryExecutorTestCase(unittest.TestCase): interrupter1 = bt2.Interrupter() interrupter2 = bt2.Interrupter() test_self = self - query_exec = bt2.QueryExecutor() + query_exec = bt2.QueryExecutor(MySink, 'obj', [17, 23]) query_exec.add_interrupter(interrupter1) query_exec.add_interrupter(interrupter2) - query_exec.query(MySink, 'obj', [17, 23]) + query_exec.query() def test_query_interrupt(self): class MySink(bt2._UserSinkComponent): @@ -172,11 +193,31 @@ class QueryExecutorTestCase(unittest.TestCase): pass @classmethod - def _user_query(cls, query_exec, obj, params, log_level): + def _user_query(cls, priv_query_exec, obj, params): test_self.assertFalse(query_exec.is_interrupted) query_exec.interrupt() test_self.assertTrue(query_exec.is_interrupted) test_self = self - query_exec = bt2.QueryExecutor() - query_exec.query(MySink, 'obj', [17, 23]) + query_exec = bt2.QueryExecutor(MySink, 'obj', [17, 23]) + query_exec.query() + + def test_query_priv_executor_invalid_after(self): + class MySink(bt2._UserSinkComponent): + def _user_consume(self): + pass + + @classmethod + def _user_query(cls, priv_query_exec, obj, params): + nonlocal test_priv_query_exec + test_priv_query_exec = priv_query_exec + + test_priv_query_exec = None + query_exec = bt2.QueryExecutor(MySink, 'obj', [17, 23]) + query_exec.query() + assert test_priv_query_exec is not None + + with self.assertRaises(RuntimeError): + test_priv_query_exec.logging_level + + del test_priv_query_exec diff --git a/tests/data/cli/auto-source-discovery/bt_plugin_test.py b/tests/data/cli/auto-source-discovery/bt_plugin_test.py index a4177240..4d6e86e2 100644 --- a/tests/data/cli/auto-source-discovery/bt_plugin_test.py +++ b/tests/data/cli/auto-source-discovery/bt_plugin_test.py @@ -26,7 +26,7 @@ class TestSourceExt(Base, bt2._UserSourceComponent, message_iterator_class=TestI self._print_params(params) @staticmethod - def _user_query(query_exec, obj, params, log_level): + def _user_query(priv_query_exec, obj, params): if obj == 'babeltrace.support-info': if params['type'] == 'file': name = os.path.basename(str(params['input'])) @@ -64,7 +64,7 @@ class TestSourceSomeDir( self._print_params(params) @staticmethod - def _user_query(query_exec, obj, params, log_level): + def _user_query(priv_query_exec, obj, params): if obj == 'babeltrace.support-info': if params['type'] == 'directory': name = os.path.basename(str(params['input'])) @@ -83,7 +83,7 @@ class TestSourceABCDE(Base, bt2._UserSourceComponent, message_iterator_class=Tes self._print_params(params) @staticmethod - def _user_query(query_exec, obj, params, log_level): + def _user_query(priv_query_exec, obj, params): if obj == 'babeltrace.support-info': return ( 1.0 diff --git a/tests/lib/plugin.c b/tests/lib/plugin.c index 11ec41d1..3b5c05fc 100644 --- a/tests/lib/plugin.c +++ b/tests/lib/plugin.c @@ -129,11 +129,10 @@ static void test_sfs(const char *plugin_dir) bt_graph *graph; const char *object_str; bt_graph_add_component_status graph_ret; - bt_query_executor *query_exec = bt_query_executor_create(); + bt_query_executor *query_exec; int ret; bt_plugin_find_all_from_file_status status; - BT_ASSERT(query_exec); BT_ASSERT(sfs_path); diag("sfs plugin test below"); @@ -181,9 +180,11 @@ static void test_sfs(const char *plugin_dir) "bt_plugin_borrow_filter_component_class_by_name_const() finds a filter component class"); params = bt_value_integer_signed_create_init(23); BT_ASSERT(params); - ret = bt_query_executor_query(query_exec, - bt_component_class_filter_as_component_class_const(filter_comp_class), - "get-something", params, BT_LOGGING_LEVEL_NONE, &results); + query_exec = bt_query_executor_create( + bt_component_class_filter_as_component_class_const( + filter_comp_class), "get-something", params); + BT_ASSERT(query_exec); + ret = bt_query_executor_query(query_exec, &results); ok(ret == 0 && results, "bt_query_executor_query() succeeds"); BT_ASSERT(bt_value_is_array(results) && bt_value_array_get_size(results) == 2); object = bt_value_array_borrow_element_by_index_const(results, 0); diff --git a/tests/lib/test-plugin-plugins/sfs.c b/tests/lib/test-plugin-plugins/sfs.c index 6e0e0a4b..3d9e74a5 100644 --- a/tests/lib/test-plugin-plugins/sfs.c +++ b/tests/lib/test-plugin-plugins/sfs.c @@ -58,9 +58,8 @@ dummy_iterator_next_method( static bt_component_class_query_method_status flt_query_method( bt_self_component_class_filter *component_class, - const bt_query_executor *query_exec, + bt_private_query_executor *priv_query_exec, const char *object, const bt_value *params, - __attribute__((unused)) bt_logging_level log_level, const bt_value **result) { bt_value *res = bt_value_array_create(); diff --git a/tests/plugins/src.ctf.fs/query/test_query_trace_info.py b/tests/plugins/src.ctf.fs/query/test_query_trace_info.py index 8d8cda78..2d99d681 100644 --- a/tests/plugins/src.ctf.fs/query/test_query_trace_info.py +++ b/tests/plugins/src.ctf.fs/query/test_query_trace_info.py @@ -40,7 +40,6 @@ class QueryTraceInfoClockOffsetTestCase(unittest.TestCase): self._inputs = [ os.path.join(test_ctf_traces_path, 'intersection', '3eventsintersect') ] - self._executor = bt2.QueryExecutor() def _check(self, trace, offset): self.assertEqual(trace['range-ns']['begin'], 13515309000000000 + offset) @@ -64,38 +63,38 @@ class QueryTraceInfoClockOffsetTestCase(unittest.TestCase): # Without clock class offset def test_no_clock_class_offset(self): - res = self._executor.query( + res = bt2.QueryExecutor( self._fs, 'babeltrace.trace-info', {'inputs': self._inputs} - ) + ).query() trace = res[0] self._check(trace, 0) # With clock-class-offset-s def test_clock_class_offset_s(self): - res = self._executor.query( + res = bt2.QueryExecutor( self._fs, 'babeltrace.trace-info', {'inputs': self._inputs, 'clock-class-offset-s': 2}, - ) + ).query() trace = res[0] self._check(trace, 2000000000) # With clock-class-offset-ns def test_clock_class_offset_ns(self): - res = self._executor.query( + res = bt2.QueryExecutor( self._fs, 'babeltrace.trace-info', {'inputs': self._inputs, 'clock-class-offset-ns': 2}, - ) + ).query() trace = res[0] self._check(trace, 2) # With both, negative def test_clock_class_offset_both(self): - res = self._executor.query( + res = bt2.QueryExecutor( self._fs, 'babeltrace.trace-info', { @@ -103,41 +102,41 @@ class QueryTraceInfoClockOffsetTestCase(unittest.TestCase): 'clock-class-offset-s': -2, 'clock-class-offset-ns': -2, }, - ) + ).query() trace = res[0] self._check(trace, -2000000002) def test_clock_class_offset_s_wrong_type(self): with self.assertRaises(bt2._Error): - self._executor.query( + bt2.QueryExecutor( self._fs, 'babeltrace.trace-info', {'inputs': self._inputs, 'clock-class-offset-s': "2"}, - ) + ).query() def test_clock_class_offset_s_wrong_type_none(self): with self.assertRaises(bt2._Error): - self._executor.query( + bt2.QueryExecutor( self._fs, 'babeltrace.trace-info', {'inputs': self._inputs, 'clock-class-offset-s': None}, - ) + ).query() def test_clock_class_offset_ns_wrong_type(self): with self.assertRaises(bt2._Error): - self._executor.query( + bt2.QueryExecutor( self._fs, 'babeltrace.trace-info', {'inputs': self._inputs, 'clock-class-offset-ns': "2"}, - ) + ).query() def test_clock_class_offset_ns_wrong_type_none(self): with self.assertRaises(bt2._Error): - self._executor.query( + bt2.QueryExecutor( self._fs, 'babeltrace.trace-info', {'inputs': self._inputs, 'clock-class-offset-ns': None}, - ) + ).query() class QueryTraceInfoPortNameTestCase(unittest.TestCase): @@ -145,10 +144,8 @@ class QueryTraceInfoPortNameTestCase(unittest.TestCase): ctf = bt2.find_plugin("ctf") self._fs = ctf.source_component_classes["fs"] - self._executor = bt2.QueryExecutor() - def test_trace_uuid_stream_class_id_no_stream_id(self): - res = self._executor.query( + res = bt2.QueryExecutor( self._fs, "babeltrace.trace-info", { @@ -158,7 +155,7 @@ class QueryTraceInfoPortNameTestCase(unittest.TestCase): ) ] }, - ) + ).query() os_stream_path = PurePosixPath( '/tests/data/ctf-traces/intersection/3eventsintersect/' @@ -184,11 +181,11 @@ class QueryTraceInfoPortNameTestCase(unittest.TestCase): ) def test_trace_uuid_no_stream_class_id_no_stream_id(self): - res = self._executor.query( + res = bt2.QueryExecutor( self._fs, "babeltrace.trace-info", {"inputs": [os.path.join(test_ctf_traces_path, "succeed", "succeed1")]}, - ) + ).query() os_stream_path = PurePosixPath( '/tests/data/ctf-traces/succeed/succeed1/dummystream' @@ -213,19 +210,17 @@ class QueryTraceInfoRangeTestCase(unittest.TestCase): ctf = bt2.find_plugin("ctf") self._fs = ctf.source_component_classes["fs"] - self._executor = bt2.QueryExecutor() - def test_trace_no_range(self): # This trace has no `timestamp_begin` and `timestamp_end` in its # packet context. The `babeltrace.trace-info` query should omit # the `range-ns` fields in the `trace` and `stream` data # structures. - res = self._executor.query( + res = bt2.QueryExecutor( self._fs, "babeltrace.trace-info", {"inputs": [os.path.join(test_ctf_traces_path, "succeed", "succeed1")]}, - ) + ).query() self.assertEqual(len(res), 1) trace = res[0] -- 2.34.1