bt2/native_btpacket.i \
bt2/native_btplugin.i \
bt2/native_btport.i \
+ bt2/native_btqueryexec.i \
bt2/native_btref.i \
bt2/native_btstreamclass.i \
bt2/native_btstream.i \
bt2/plugin.py \
bt2/port.py \
bt2/py_plugin.py \
+ bt2/query_executor.py \
bt2/stream_class.py \
bt2/stream.py \
bt2/trace.py \
from bt2.port import _PrivateOutputPort
from bt2.port import _PrivatePort
from bt2.py_plugin import *
+from bt2.query_executor import *
from bt2.stream import _Stream
from bt2.stream_class import *
from bt2.trace import *
pass
+class InvalidQueryObject(Error):
+ pass
+
+
+class InvalidQueryParams(Error):
+ pass
+
+
class UnsupportedFeature(Exception):
pass
pass
+class QueryExecutorCanceled(Exception):
+ pass
+
+
class NotificationIteratorCanceled(Exception):
pass
def help(self):
return native_bt.component_class_get_help(self._ptr)
- def query(self, obj, params=None):
- return _query(self._ptr, obj, params)
-
def __eq__(self, other):
if not isinstance(other, _GenericComponentClass):
try:
return '\n'.join(trimmed)
-def _query(comp_cls_ptr, obj, params):
- utils._check_str(obj)
-
- if params is None:
- params_ptr = native_bt.value_null
- else:
- params = bt2.create_value(params)
- params_ptr = params._ptr
-
- results_ptr = native_bt.component_class_query(comp_cls_ptr, obj,
- params_ptr)
-
- if results_ptr is None:
- raise bt2.Error('cannot query info with object "{}"'.format(obj))
-
- return bt2.values._create_from_ptr(results_ptr)
-
-
# Metaclass for component classes defined by Python code.
#
# The Python user can create a standard Python class which inherits one
def addr(cls):
return int(cls._cc_ptr)
- def query(cls, obj, params=None):
- return _query(cls._cc_ptr, obj, params)
-
- def _query_from_native(cls, obj, params_ptr):
+ def _query_from_native(cls, 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:
else:
params = None
- try:
- results = cls._query(obj, params)
- except:
- if not _NO_PRINT_TRACEBACK:
- traceback.print_exc()
+ native_bt.get(query_exec_ptr)
+ query_exec = bt2.QueryExecutor._create_from_ptr(query_exec_ptr)
- return
+ # this can raise, but the native side checks the exception
+ results = cls._query(query_exec, obj, params)
if results is NotImplemented:
return results
- try:
- results = bt2.create_value(results)
- except:
- if not _NO_PRINT_TRACEBACK:
- traceback.print_exc()
-
- return
+ # this can raise, but the native side checks the exception
+ results = bt2.create_value(results)
if results is None:
results_addr = int(native_bt.value_null)
return results_addr
- @classmethod
- def _query(cls, obj, params):
+ def _query(cls, query_executor, obj, params):
# BT catches this and returns NULL to the user
return NotImplemented
}
}
+/* Output argument typemap for value output (always appends) */
+%typemap(in, numinputs=0) struct bt_value **BTOUTVALUE (struct bt_value *temp_value = NULL) {
+ $1 = &temp_value;
+}
+
+%typemap(argout) struct bt_value **BTOUTVALUE {
+ if (*$1) {
+ /* SWIG_Python_AppendOutput() steals the created object */
+ $result = SWIG_Python_AppendOutput($result, SWIG_NewPointerObj(SWIG_as_voidptr(*$1), SWIGTYPE_p_bt_value, 0));
+ } else {
+ /* SWIG_Python_AppendOutput() steals Py_None */
+ Py_INCREF(Py_None);
+ $result = SWIG_Python_AppendOutput($result, Py_None);
+ }
+}
+
/* Output argument typemap for initialized uint64_t output parameter (always appends) */
%typemap(in, numinputs=0) uint64_t *OUTPUTINIT (uint64_t temp = -1ULL) {
$1 = &temp;
%include "native_btpacket.i"
%include "native_btplugin.i"
%include "native_btport.i"
+%include "native_btqueryexec.i"
%include "native_btref.i"
%include "native_btstream.i"
%include "native_btstreamclass.i"
struct bt_component_class *component_class);
const char *bt_component_class_get_help(
struct bt_component_class *component_class);
-struct bt_value *bt_component_class_query(
- struct bt_component_class *component_class,
- const char *object, struct bt_value *params);
enum bt_component_class_type bt_component_class_get_type(
struct bt_component_class *component_class);
static PyObject *py_mod_bt2_exc_try_again_type = NULL;
static PyObject *py_mod_bt2_exc_stop_type = NULL;
static PyObject *py_mod_bt2_exc_port_connection_refused_type = NULL;
-static PyObject *py_mod_bt2_exc_graph_canceled_type = NULL;
static PyObject *py_mod_bt2_exc_notif_iter_canceled_type = NULL;
-static PyObject *py_mod_bt2_exc_connection_ended_type = NULL;
+static PyObject *py_mod_bt2_exc_invalid_query_object_type = NULL;
+static PyObject *py_mod_bt2_exc_invalid_query_params_type = NULL;
static void bt_py3_cc_init_from_bt2(void)
{
assert(py_mod_bt2_exc_error_type);
py_mod_bt2_exc_unsupported_feature_type =
PyObject_GetAttrString(py_mod_bt2, "UnsupportedFeature");
+ assert(py_mod_bt2_exc_unsupported_feature_type);
py_mod_bt2_exc_try_again_type =
PyObject_GetAttrString(py_mod_bt2, "TryAgain");
+ assert(py_mod_bt2_exc_try_again_type);
py_mod_bt2_exc_stop_type =
PyObject_GetAttrString(py_mod_bt2, "Stop");
+ assert(py_mod_bt2_exc_stop_type);
py_mod_bt2_exc_port_connection_refused_type =
PyObject_GetAttrString(py_mod_bt2, "PortConnectionRefused");
- py_mod_bt2_exc_graph_canceled_type =
- PyObject_GetAttrString(py_mod_bt2, "GraphCanceled");
- py_mod_bt2_exc_connection_ended_type =
- PyObject_GetAttrString(py_mod_bt2, "ConnectionEnded");
- assert(py_mod_bt2_exc_stop_type);
+ assert(py_mod_bt2_exc_port_connection_refused_type);
+ py_mod_bt2_exc_invalid_query_object_type =
+ PyObject_GetAttrString(py_mod_bt2, "InvalidQueryObject");
+ assert(py_mod_bt2_exc_invalid_query_object_type);
+ py_mod_bt2_exc_invalid_query_params_type =
+ PyObject_GetAttrString(py_mod_bt2, "InvalidQueryParams");
+ assert(py_mod_bt2_exc_invalid_query_params_type);
}
static void bt_py3_cc_exit_handler(void)
Py_XDECREF(py_mod_bt2_exc_try_again_type);
Py_XDECREF(py_mod_bt2_exc_stop_type);
Py_XDECREF(py_mod_bt2_exc_port_connection_refused_type);
- Py_XDECREF(py_mod_bt2_exc_graph_canceled_type);
Py_XDECREF(py_mod_bt2_exc_notif_iter_canceled_type);
- Py_XDECREF(py_mod_bt2_exc_connection_ended_type);
+ Py_XDECREF(py_mod_bt2_exc_invalid_query_object_type);
+ Py_XDECREF(py_mod_bt2_exc_invalid_query_params_type);
}
return status;
}
+static enum bt_query_status bt_py3_exc_to_query_status(void)
+{
+ enum bt_query_status status = BT_QUERY_STATUS_OK;
+ PyObject *exc = PyErr_Occurred();
+
+ if (!exc) {
+ goto end;
+ }
+
+ if (PyErr_GivenExceptionMatches(exc,
+ py_mod_bt2_exc_invalid_query_object_type)) {
+ status = BT_QUERY_STATUS_INVALID_OBJECT;
+ } else if (PyErr_GivenExceptionMatches(exc,
+ py_mod_bt2_exc_invalid_query_params_type)) {
+ status = BT_QUERY_STATUS_INVALID_PARAMS;
+ } else if (PyErr_GivenExceptionMatches(exc,
+ py_mod_bt2_exc_try_again_type)) {
+ status = BT_QUERY_STATUS_AGAIN;
+ } else {
+ status = BT_QUERY_STATUS_ERROR;
+ }
+
+end:
+ PyErr_Clear();
+ return status;
+}
+
static enum bt_component_status bt_py3_exc_to_component_status(void)
{
enum bt_component_status status = BT_COMPONENT_STATUS_OK;
Py_XDECREF(py_method_result);
}
-static struct bt_value *bt_py3_cc_query(
+static struct bt_component_class_query_return bt_py3_cc_query(
struct bt_component_class *comp_cls,
+ struct bt_query_executor *query_exec,
const char *object, struct bt_value *params)
{
PyObject *py_cls = NULL;
PyObject *py_params_ptr = NULL;
+ PyObject *py_query_exec_ptr = NULL;
PyObject *py_query_func = NULL;
PyObject *py_object = NULL;
PyObject *py_results_addr = NULL;
- struct bt_value *results = NULL;
+ struct bt_component_class_query_return ret = {
+ .status = BT_QUERY_STATUS_OK,
+ .result = NULL,
+ };
py_cls = lookup_cc_ptr_to_py_cls(comp_cls);
if (!py_cls) {
goto error;
}
+ py_query_exec_ptr = SWIG_NewPointerObj(SWIG_as_voidptr(query_exec),
+ SWIGTYPE_p_bt_query_executor, 0);
+ if (!py_query_exec_ptr) {
+ BT_LOGE_STR("Failed to create a SWIG pointer object.");
+ goto error;
+ }
+
py_object = SWIG_FromCharPtr(object);
if (!py_object) {
BT_LOGE_STR("Failed to create a Python string.");
}
py_results_addr = PyObject_CallMethod(py_cls,
- "_query_from_native", "(OO)", py_object, py_params_ptr);
- if (!py_results_addr || py_results_addr == Py_None) {
- BT_LOGE_STR("User's _query() method failed.");
- goto error;
+ "_query_from_native", "(OOO)", py_query_exec_ptr,
+ py_object, py_params_ptr);
+ ret.status = bt_py3_exc_to_query_status();
+ if (!py_results_addr && ret.status == BT_QUERY_STATUS_OK) {
+ /* Pretty sure this should never happen, but just in case */
+ BT_LOGE("_query_from_native() class method failed without raising an exception: "
+ "status=%d", ret.status);
+ ret.status = BT_QUERY_STATUS_ERROR;
+ goto end;
+ }
+
+ if (ret.status != BT_QUERY_STATUS_OK) {
+ goto end;
}
if (py_results_addr == Py_NotImplemented) {
* (PyLong) containing the address of a BT value object (new
* reference).
*/
- results = (void *) PyLong_AsUnsignedLongLong(py_results_addr);
+ ret.result = (void *) PyLong_AsUnsignedLongLong(py_results_addr);
assert(!PyErr_Occurred());
- assert(results);
+ assert(ret.result);
goto end;
error:
- BT_PUT(results);
+ BT_PUT(ret.result);
PyErr_Clear();
+ ret.status = BT_QUERY_STATUS_ERROR;
+ BT_PUT(ret.result);
end:
Py_XDECREF(py_params_ptr);
+ Py_XDECREF(py_query_exec_ptr);
Py_XDECREF(py_query_func);
Py_XDECREF(py_object);
Py_XDECREF(py_results_addr);
- return results;
+ return ret;
}
static enum bt_notification_iterator_status bt_py3_cc_notification_iterator_init(
--- /dev/null
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Philippe Proulx <pproulx@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/* Types */
+struct bt_query_executor;
+
+/* Query status */
+enum bt_query_status {
+ BT_QUERY_STATUS_OK = 0,
+ BT_QUERY_STATUS_AGAIN = 11,
+ BT_QUERY_STATUS_EXECUTOR_CANCELED = 125,
+ BT_QUERY_STATUS_ERROR = -1,
+ BT_QUERY_STATUS_INVALID = -22,
+ BT_QUERY_STATUS_INVALID_OBJECT = -23,
+ BT_QUERY_STATUS_INVALID_PARAMS = -24,
+ BT_QUERY_STATUS_NOMEM = -12,
+};
+
+/* Functions */
+struct bt_query_executor *bt_query_executor_create(void);
+enum bt_query_status bt_query_executor_query(
+ struct bt_query_executor *query_executor,
+ struct bt_component_class *component_class,
+ const char *object, struct bt_value *params,
+ struct bt_value **BTOUTVALUE);
+enum bt_query_status bt_query_executor_cancel(
+ struct bt_query_executor *query_executor);
+int bt_query_executor_is_canceled(struct bt_query_executor *query_executor);
* THE SOFTWARE.
*/
-%{
-#include <babeltrace/version.h>
-%}
-
/* Version functions */
int bt_version_get_major(void);
int bt_version_get_minor(void);
--- /dev/null
+# The MIT License (MIT)
+#
+# Copyright (c) 2017 Philippe Proulx <pproulx@efficios.com>
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+from bt2 import native_bt, object, utils
+import bt2.component
+import bt2
+
+
+class QueryExecutor(object._Object):
+ def _handle_status(self, status, gen_error_msg):
+ if status == native_bt.QUERY_STATUS_AGAIN:
+ raise bt2.TryAgain
+ elif status == native_bt.QUERY_STATUS_EXECUTOR_CANCELED:
+ raise bt2.QueryExecutorCanceled
+ elif status == native_bt.QUERY_STATUS_INVALID_OBJECT:
+ raise bt2.InvalidQueryObject
+ elif status == native_bt.QUERY_STATUS_INVALID_PARAMS:
+ raise bt2.InvalidQueryParams
+ elif status < 0:
+ raise bt2.Error(gen_error_msg)
+
+ def __init__(self):
+ ptr = native_bt.query_executor_create()
+
+ if ptr is None:
+ raise bt2.CreationError('cannot create query executor object')
+
+ super().__init__(ptr)
+
+ def cancel(self):
+ status = native_bt.query_executor_cancel(self._ptr)
+ self._handle_status(status, 'cannot cancel query executor object')
+
+ @property
+ def is_canceled(self):
+ is_canceled = native_bt.query_executor_is_canceled(self._ptr)
+ assert(is_canceled >= 0)
+ return is_canceled > 0
+
+ def query(self, component_class, object, params=None):
+ if not isinstance(component_class, bt2.component._GenericComponentClass):
+ err = False
+
+ try:
+ if not issubclass(component_class, bt2.component._UserComponent):
+ err = True
+ except TypeError:
+ err = True
+
+ if err:
+ o = component_class
+ raise TypeError("'{}' is not a component class object".format(o))
+
+ utils._check_str(object)
+
+ if params is None:
+ params_ptr = native_bt.value_null
+ else:
+ params = bt2.create_value(params)
+ params_ptr = params._ptr
+
+ if isinstance(component_class, bt2.component._GenericComponentClass):
+ cc_ptr = component_class._ptr
+ else:
+ cc_ptr = component_class._cc_ptr
+
+ status, result_ptr = native_bt.query_executor_query(self._ptr, cc_ptr,
+ object, params_ptr)
+ self._handle_status(status, 'cannot query component class')
+ assert(result_ptr)
+ return bt2.values._create_from_ptr(result_ptr)
+
+ def __eq__(self, other):
+ if type(other) is not type(self):
+ return False
+
+ return self.addr == other.addr
#include "logging.h"
#include <babeltrace/babeltrace.h>
-#include <babeltrace/plugin/plugin.h>
#include <babeltrace/common-internal.h>
-#include <babeltrace/graph/component.h>
-#include <babeltrace/graph/component-source.h>
-#include <babeltrace/graph/component-sink.h>
-#include <babeltrace/graph/component-filter.h>
-#include <babeltrace/graph/component-class.h>
-#include <babeltrace/graph/port.h>
-#include <babeltrace/graph/graph.h>
-#include <babeltrace/graph/connection.h>
-#include <babeltrace/graph/notification-iterator.h>
-#include <babeltrace/ref.h>
-#include <babeltrace/values.h>
#include <babeltrace/values-internal.h>
-#include <babeltrace/logging.h>
#include <unistd.h>
#include <stdlib.h>
#include <popt.h>
/* Application's processing graph (weak) */
static struct bt_graph *the_graph;
+static struct bt_query_executor *the_query_executor;
static bool canceled = false;
GPtrArray *loaded_plugins;
bt_graph_cancel(the_graph);
}
+ if (the_query_executor) {
+ bt_query_executor_cancel(the_query_executor);
+ }
+
canceled = true;
}
g_ptr_array_free(loaded_plugins, TRUE);
}
+static
+int create_the_query_executor(void)
+{
+ int ret = 0;
+
+ the_query_executor = bt_query_executor_create();
+ if (!the_query_executor) {
+ BT_LOGE_STR("Cannot create a query executor.");
+ ret = -1;
+ }
+
+ return ret;
+}
+
+static
+void destroy_the_query_executor(void)
+{
+ BT_PUT(the_query_executor);
+}
+
+static
+int query(struct bt_component_class *comp_cls, const char *obj,
+ struct bt_value *params, struct bt_value **user_result,
+ const char **fail_reason)
+{
+ struct bt_value *result = NULL;
+ enum bt_query_status status;
+ *fail_reason = "unknown error";
+ int ret = 0;
+
+ assert(fail_reason);
+ assert(user_result);
+ ret = create_the_query_executor();
+ if (ret) {
+ /* create_the_query_executor() logs errors */
+ goto end;
+ }
+
+ if (canceled) {
+ BT_LOGI("Canceled by user before executing the query: "
+ "comp-cls-addr=%p, comp-cls-name=\"%s\", "
+ "query-obj=\"%s\"", comp_cls,
+ bt_component_class_get_name(comp_cls), obj);
+ *fail_reason = "canceled by user";
+ goto error;
+ }
+
+ while (true) {
+ status = bt_query_executor_query(the_query_executor, comp_cls,
+ obj, params, &result);
+ switch (status) {
+ case BT_QUERY_STATUS_OK:
+ goto ok;
+ case BT_QUERY_STATUS_AGAIN:
+ {
+ const uint64_t sleep_time_us = 100000;
+
+ /* Wait 100 ms and retry */
+ BT_LOGV("Got BT_QUERY_STATUS_AGAIN: sleeping: "
+ "time-us=%" PRIu64, sleep_time_us);
+
+ if (usleep(sleep_time_us)) {
+ if (bt_query_executor_is_canceled(the_query_executor)) {
+ BT_LOGI("Query was canceled 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 = "canceled by user";
+ goto error;
+ }
+ }
+
+ continue;
+ }
+ case BT_QUERY_STATUS_EXECUTOR_CANCELED:
+ *fail_reason = "canceled by user";
+ goto error;
+ case BT_QUERY_STATUS_ERROR:
+ case BT_QUERY_STATUS_INVALID:
+ goto error;
+ case BT_QUERY_STATUS_INVALID_OBJECT:
+ *fail_reason = "invalid or unknown query object";
+ goto error;
+ case BT_QUERY_STATUS_INVALID_PARAMS:
+ *fail_reason = "invalid query parameters";
+ goto error;
+ case BT_QUERY_STATUS_NOMEM:
+ *fail_reason = "not enough memory";
+ goto error;
+ default:
+ BT_LOGF("Unknown query status: status=%d", status);
+ abort();
+ }
+ }
+
+ok:
+ *user_result = result;
+ result = NULL;
+ goto end;
+
+error:
+ ret = -1;
+
+end:
+ destroy_the_query_executor();
+ bt_put(result);
+ return ret;
+}
+
static
struct bt_plugin *find_plugin(const char *name)
{
int ret = 0;
struct bt_component_class *comp_cls = NULL;
struct bt_value *results = NULL;
+ const char *fail_reason = NULL;
comp_cls = find_component_class(cfg->cmd_data.query.cfg_component->plugin_name->str,
cfg->cmd_data.query.cfg_component->comp_cls_name->str,
goto end;
}
- results = bt_component_class_query(comp_cls,
- cfg->cmd_data.query.object->str,
- cfg->cmd_data.query.cfg_component->params);
- if (!results) {
- BT_LOGE("Failed to query component class: plugin-name=\"%s\", "
- "comp-cls-name=\"%s\", comp-cls-type=%d "
- "object=\"%s\"",
- cfg->cmd_data.query.cfg_component->plugin_name->str,
- cfg->cmd_data.query.cfg_component->comp_cls_name->str,
- cfg->cmd_data.query.cfg_component->type,
- cfg->cmd_data.query.object->str);
- fprintf(stderr, "%s%sFailed to query info to %s",
- bt_common_color_bold(),
- bt_common_color_fg_red(),
- bt_common_color_reset());
- print_plugin_comp_cls_opt(stderr,
- cfg->cmd_data.query.cfg_component->plugin_name->str,
- cfg->cmd_data.query.cfg_component->comp_cls_name->str,
- cfg->cmd_data.query.cfg_component->type);
- fprintf(stderr, "%s%s with object `%s`%s\n",
- bt_common_color_bold(),
- bt_common_color_fg_red(),
- cfg->cmd_data.query.object->str,
- bt_common_color_reset());
- ret = -1;
- goto end;
+ ret = query(comp_cls, cfg->cmd_data.query.object->str,
+ cfg->cmd_data.query.cfg_component->params, &results,
+ &fail_reason);
+ if (ret) {
+ goto failed;
}
print_value(stdout, results, 0);
+ goto end;
+
+failed:
+ BT_LOGE("Failed to query component class: %s: plugin-name=\"%s\", "
+ "comp-cls-name=\"%s\", comp-cls-type=%d "
+ "object=\"%s\"", fail_reason,
+ cfg->cmd_data.query.cfg_component->plugin_name->str,
+ cfg->cmd_data.query.cfg_component->comp_cls_name->str,
+ cfg->cmd_data.query.cfg_component->type,
+ cfg->cmd_data.query.object->str);
+ fprintf(stderr, "%s%sFailed to query info to %s",
+ bt_common_color_bold(),
+ bt_common_color_fg_red(),
+ bt_common_color_reset());
+ print_plugin_comp_cls_opt(stderr,
+ cfg->cmd_data.query.cfg_component->plugin_name->str,
+ cfg->cmd_data.query.cfg_component->comp_cls_name->str,
+ cfg->cmd_data.query.cfg_component->type);
+ fprintf(stderr, "%s%s with object `%s`: %s%s\n",
+ bt_common_color_bold(),
+ bt_common_color_fg_red(),
+ cfg->cmd_data.query.object->str,
+ fail_reason,
+ bt_common_color_reset());
+ ret = -1;
end:
bt_put(comp_cls);
static const enum bt_component_class_type comp_cls_type =
BT_COMPONENT_CLASS_TYPE_SOURCE;
int64_t array_size, i;
+ const char *fail_reason = NULL;
assert(cfg->cmd_data.print_lttng_live_sessions.url);
comp_cls = find_component_class(plugin_name, comp_cls_name,
goto error;
}
- results = bt_component_class_query(comp_cls, "sessions",
- params);
- if (!results) {
- BT_LOGE_STR("Failed to query for sessions.");
- fprintf(stderr, "%s%sFailed to request sessions%s\n",
- bt_common_color_bold(),
- bt_common_color_fg_red(),
- bt_common_color_reset());
- goto error;
+ ret = query(comp_cls, "sessions", params, &results, &fail_reason);
+ if (ret) {
+ goto failed;
}
if (!bt_value_is_array(results)) {
BT_PUT(map);
}
+
+ goto end;
+
+failed:
+ BT_LOGE("Failed to query for sessions: %s", fail_reason);
+ fprintf(stderr, "%s%sFailed to request sessions: %s%s\n",
+ bt_common_color_bold(),
+ bt_common_color_fg_red(),
+ fail_reason,
+ bt_common_color_reset());
+
+error:
+ ret = -1;
+
end:
bt_put(v);
bt_put(map);
bt_put(params);
bt_put(comp_cls);
return 0;
-
-error:
- ret = -1;
- goto end;
}
static
static const char * const comp_cls_name = "fs";
static const enum bt_component_class_type comp_cls_type =
BT_COMPONENT_CLASS_TYPE_SOURCE;
+ const char *fail_reason = NULL;
assert(cfg->cmd_data.print_ctf_metadata.path);
comp_cls = find_component_class(plugin_name, comp_cls_name,
goto end;
}
- results = bt_component_class_query(comp_cls, "metadata-info",
- params);
- if (!results) {
- ret = -1;
- BT_LOGE_STR("Failed to query for metadata info.");
- fprintf(stderr, "%s%sFailed to request metadata info%s\n",
- bt_common_color_bold(),
- bt_common_color_fg_red(),
- bt_common_color_reset());
- goto end;
+ ret = query(comp_cls, "metadata-info", params, &results, &fail_reason);
+ if (ret) {
+ goto failed;
}
metadata_text_value = bt_value_map_get(results, "text");
ret = bt_value_string_get(metadata_text_value, &metadata_text);
assert(ret == 0);
printf("%s\n", metadata_text);
+ goto end;
+
+failed:
+ ret = -1;
+ BT_LOGE("Failed to query for metadata info: %s", fail_reason);
+ fprintf(stderr, "%s%sFailed to request metadata info: %s%s\n",
+ bt_common_color_bold(),
+ bt_common_color_fg_red(),
+ fail_reason,
+ bt_common_color_reset());
end:
+ destroy_the_query_executor();
bt_put(results);
bt_put(params);
bt_put(metadata_text_value);
struct bt_value *stream_info = NULL;
struct port_id *port_id = NULL;
struct trace_range *trace_range = NULL;
+ const char *fail_reason = NULL;
component_path_value = bt_value_map_get(cfg_comp->params, "path");
if (!bt_value_is_string(component_path_value)) {
goto error;
}
- query_result = bt_component_class_query(comp_cls, "trace-info",
- query_params);
- if (!query_result) {
- BT_LOGD("Component class \'%s\' does not support the \'trace-info\' query.",
+ ret = query(comp_cls, "trace-info", query_params, &query_result,
+ &fail_reason);
+ if (ret) {
+ BT_LOGD("Component class does not support the `trace-info` query: %s: "
+ "comp-class-name=\"%s\"", fail_reason,
bt_component_class_get_name(comp_cls));
ret = -1;
goto error;
babeltrace/graph/notification-packet.h \
babeltrace/graph/notification-stream.h \
babeltrace/graph/port.h \
+ babeltrace/graph/query-executor.h \
babeltrace/graph/private-component-filter.h \
babeltrace/graph/private-component-sink.h \
babeltrace/graph/private-component-source.h \
babeltrace/graph/notification-packet-internal.h \
babeltrace/graph/notification-stream-internal.h \
babeltrace/graph/port-internal.h \
+ babeltrace/graph/query-executor-internal.h \
babeltrace/lib-logging-internal.h \
babeltrace/list-internal.h \
babeltrace/logging-internal.h \
#include <babeltrace/graph/private-connection.h>
#include <babeltrace/graph/private-notification-iterator.h>
#include <babeltrace/graph/private-port.h>
+#include <babeltrace/graph/query-executor.h>
#endif /* BABELTRACE_BABELTRACE_H */
#include <stdint.h>
#include <babeltrace/graph/component-status.h>
#include <babeltrace/graph/notification-iterator.h>
+#include <babeltrace/graph/query-executor.h>
#include <babeltrace/types.h>
#ifdef __cplusplus
struct bt_port;
struct bt_value;
struct bt_private_notification_iterator;
+struct bt_query_executor;
/**
* Component class type.
enum bt_notification_iterator_status status;
};
+struct bt_component_class_query_return {
+ struct bt_value *result;
+ enum bt_query_status status;
+};
+
typedef enum bt_component_status (*bt_component_class_init_method)(
struct bt_private_component *private_component,
struct bt_value *params, void *init_method_data);
struct bt_private_notification_iterator *private_notification_iterator,
int64_t time);
-typedef struct bt_value *(*bt_component_class_query_method)(
+typedef struct bt_component_class_query_return (*bt_component_class_query_method)(
struct bt_component_class *component_class,
+ struct bt_query_executor *query_executor,
const char *object, struct bt_value *params);
typedef enum bt_component_status (*bt_component_class_accept_port_connection_method)(
extern const char *bt_component_class_get_help(
struct bt_component_class *component_class);
-extern struct bt_value *bt_component_class_query(
- struct bt_component_class *component_class,
- const char *object, struct bt_value *params);
-
/**
* Get a component class' type.
*
--- /dev/null
+#ifndef BABELTRACE_GRAPH_QUERY_EXECUTOR_INTERNAL_H
+#define BABELTRACE_GRAPH_QUERY_EXECUTOR_INTERNAL_H
+
+/*
+ * Copyright 2017 Philippe Proulx <pproulx@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <babeltrace/types.h>
+#include <babeltrace/object-internal.h>
+
+struct bt_query_executor {
+ struct bt_object base;
+ bt_bool canceled;
+};
+
+static inline const char *bt_query_status_string(enum bt_query_status status)
+{
+ switch (status) {
+ case BT_QUERY_STATUS_OK:
+ return "BT_QUERY_STATUS_OK";
+ case BT_QUERY_STATUS_AGAIN:
+ return "BT_QUERY_STATUS_AGAIN";
+ case BT_QUERY_STATUS_EXECUTOR_CANCELED:
+ return "BT_QUERY_STATUS_EXECUTOR_CANCELED";
+ case BT_QUERY_STATUS_ERROR:
+ return "BT_QUERY_STATUS_ERROR";
+ case BT_QUERY_STATUS_INVALID:
+ return "BT_QUERY_STATUS_INVALID";
+ case BT_QUERY_STATUS_INVALID_OBJECT:
+ return "BT_QUERY_STATUS_INVALID_OBJECT";
+ case BT_QUERY_STATUS_INVALID_PARAMS:
+ return "BT_QUERY_STATUS_INVALID_PARAMS";
+ case BT_QUERY_STATUS_NOMEM:
+ return "BT_QUERY_STATUS_NOMEM";
+ default:
+ return "(unknown)";
+ }
+};
+
+#endif /* BABELTRACE_GRAPH_QUERY_EXECUTOR_INTERNAL_H */
--- /dev/null
+#ifndef BABELTRACE_GRAPH_QUERY_EXECUTOR_H
+#define BABELTRACE_GRAPH_QUERY_EXECUTOR_H
+
+/*
+ * BabelTrace - Babeltrace Component Connection Interface
+ *
+ * Copyright 2017 Philippe Proulx <pproulx@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <babeltrace/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct bt_value;
+struct bt_query_executor;
+struct bt_component_class;
+
+enum bt_query_status {
+ BT_QUERY_STATUS_OK = 0,
+ BT_QUERY_STATUS_AGAIN = 11,
+ BT_QUERY_STATUS_EXECUTOR_CANCELED = 125,
+ BT_QUERY_STATUS_ERROR = -1,
+ BT_QUERY_STATUS_INVALID = -22,
+ BT_QUERY_STATUS_INVALID_OBJECT = -23,
+ BT_QUERY_STATUS_INVALID_PARAMS = -24,
+ BT_QUERY_STATUS_NOMEM = -12,
+};
+
+extern
+struct bt_query_executor *bt_query_executor_create(void);
+
+extern
+enum bt_query_status bt_query_executor_query(
+ struct bt_query_executor *query_executor,
+ struct bt_component_class *component_class,
+ const char *object, struct bt_value *params,
+ struct bt_value **result);
+
+extern
+enum bt_query_status bt_query_executor_cancel(
+ struct bt_query_executor *query_executor);
+
+extern
+bt_bool bt_query_executor_is_canceled(struct bt_query_executor *query_executor);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BABELTRACE_GRAPH_QUERY_EXECUTOR_H */
sink.c \
filter.c \
iterator.c \
- component-class-sink-colander.c
+ component-class-sink-colander.c \
+ query-executor.c
libgraph_la_LIBADD = \
notification/libgraph-notification.la
end:
return ret;
}
-
-struct bt_value *bt_component_class_query(
- struct bt_component_class *component_class,
- const char *object, struct bt_value *params)
-{
- struct bt_value *results = NULL;
-
- if (!component_class) {
- BT_LOGW_STR("Invalid parameter: component class is NULL.");
- goto end;
- }
-
- if (!object) {
- BT_LOGW_STR("Invalid parameter: object string is NULL.");
- goto end;
- }
-
- if (!params) {
- BT_LOGW_STR("Invalid parameter: parameters value is NULL.");
- goto end;
- }
-
- if (!component_class->methods.query) {
- /* Not an error: nothing to query */
- BT_LOGD("Component class has no registered query method: "
- "addr=%p, name=\"%s\", type=%s",
- component_class,
- bt_component_class_get_name(component_class),
- bt_component_class_type_string(component_class->type));
- goto end;
- }
-
- BT_LOGD("Calling user's query method: "
- "comp-class-addr=%p, comp-class-name=\"%s\", comp-class-type=%s"
- "object=\"%s\", params-addr=%p",
- component_class,
- bt_component_class_get_name(component_class),
- bt_component_class_type_string(component_class->type),
- object, params);
- results = component_class->methods.query(component_class,
- object, params);
- BT_LOGD("User method returned: results-addr=%p", results);
-
-end:
- return results;
-}
}
}
-extern enum bt_graph_status bt_graph_cancel(struct bt_graph *graph)
+enum bt_graph_status bt_graph_cancel(struct bt_graph *graph)
{
enum bt_graph_status ret = BT_GRAPH_STATUS_OK;
return ret;
}
-extern bt_bool bt_graph_is_canceled(struct bt_graph *graph)
+bt_bool bt_graph_is_canceled(struct bt_graph *graph)
{
- return graph ? graph->canceled : BT_FALSE;
+ bt_bool canceled = BT_FALSE;
+
+ if (!graph) {
+ BT_LOGW_STR("Invalid parameter: graph is NULL.");
+ goto end;
+ }
+
+ canceled = graph->canceled;
+
+end:
+ return canceled;
}
BT_HIDDEN
--- /dev/null
+/*
+ * Copyright 2017 Philippe Proulx <pproulx@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#define BT_LOG_TAG "QUERY-EXECUTOR"
+#include <babeltrace/lib-logging-internal.h>
+
+#include <babeltrace/graph/query-executor.h>
+#include <babeltrace/graph/query-executor-internal.h>
+#include <babeltrace/graph/component-class.h>
+#include <babeltrace/graph/component-class-internal.h>
+#include <babeltrace/values.h>
+#include <babeltrace/object-internal.h>
+#include <babeltrace/compiler-internal.h>
+
+static
+void bt_query_executor_destroy(struct bt_object *obj)
+{
+ struct bt_query_executor *query_exec =
+ container_of(obj, struct bt_query_executor, base);
+
+ BT_LOGD("Destroying port: addr=%p", query_exec);
+ g_free(query_exec);
+}
+
+struct bt_query_executor *bt_query_executor_create(void)
+{
+ struct bt_query_executor *query_exec;
+
+ BT_LOGD_STR("Creating query executor.");
+ query_exec = g_new0(struct bt_query_executor, 1);
+ if (!query_exec) {
+ BT_LOGE_STR("Failed to allocate one query executor.");
+ goto end;
+ }
+
+ bt_object_init(query_exec, bt_query_executor_destroy);
+ BT_LOGD("Created query executor: addr=%p", query_exec);
+
+end:
+ return query_exec;
+}
+
+enum bt_query_status bt_query_executor_query(
+ struct bt_query_executor *query_exec,
+ struct bt_component_class *component_class,
+ const char *object, struct bt_value *params,
+ struct bt_value **user_result)
+{
+ struct bt_component_class_query_return ret = {
+ .result = NULL,
+ .status = BT_QUERY_STATUS_OK,
+ };
+
+ if (!query_exec) {
+ BT_LOGW_STR("Invalid parameter: query executor is NULL.");
+ ret.status = BT_QUERY_STATUS_INVALID;
+ goto end;
+ }
+
+ if (query_exec->canceled) {
+ BT_LOGW_STR("Invalid parameter: query executor is canceled.");
+ ret.status = BT_QUERY_STATUS_EXECUTOR_CANCELED;
+ goto end;
+ }
+
+ if (!component_class) {
+ BT_LOGW_STR("Invalid parameter: component class is NULL.");
+ ret.status = BT_QUERY_STATUS_INVALID;
+ goto end;
+ }
+
+ if (!object) {
+ BT_LOGW_STR("Invalid parameter: object string is NULL.");
+ ret.status = BT_QUERY_STATUS_INVALID;
+ goto end;
+ }
+
+ if (!params) {
+ params = bt_value_null;
+ }
+
+ if (!component_class->methods.query) {
+ /* Not an error: nothing to query */
+ BT_LOGD("Component class has no registered query method: "
+ "addr=%p, name=\"%s\", type=%s",
+ component_class,
+ bt_component_class_get_name(component_class),
+ bt_component_class_type_string(component_class->type));
+ ret.status = BT_QUERY_STATUS_ERROR;
+ goto end;
+ }
+
+ BT_LOGD("Calling user's query method: "
+ "query-exec-addr=%p, comp-class-addr=%p, "
+ "comp-class-name=\"%s\", comp-class-type=%s, "
+ "object=\"%s\", params-addr=%p",
+ query_exec, component_class,
+ bt_component_class_get_name(component_class),
+ bt_component_class_type_string(component_class->type),
+ object, params);
+ ret = component_class->methods.query(component_class, query_exec,
+ object, params);
+ BT_LOGD("User method returned: status=%s, result-addr=%p",
+ bt_query_status_string(ret.status), ret.result);
+ if (query_exec->canceled) {
+ BT_PUT(ret.result);
+ ret.status = BT_QUERY_STATUS_EXECUTOR_CANCELED;
+ goto end;
+ } else {
+ if (ret.status == BT_QUERY_STATUS_EXECUTOR_CANCELED) {
+ /*
+ * The user cannot decide that the executor is
+ * canceled if it's not.
+ */
+ BT_PUT(ret.result);
+ ret.status = BT_QUERY_STATUS_ERROR;
+ goto end;
+ }
+ }
+
+ switch (ret.status) {
+ case BT_QUERY_STATUS_INVALID:
+ /*
+ * This is reserved for invalid parameters passed to
+ * this function.
+ */
+ BT_PUT(ret.result);
+ ret.status = BT_QUERY_STATUS_ERROR;
+ break;
+ case BT_QUERY_STATUS_OK:
+ if (!ret.result) {
+ ret.result = bt_value_null;
+ }
+ break;
+ default:
+ if (ret.result) {
+ BT_LOGW("User method did not return BT_QUERY_STATUS_OK, but result is not NULL: "
+ "status=%s, result-addr=%p",
+ bt_query_status_string(ret.status), ret.result);
+ BT_PUT(ret.result);
+ }
+ }
+
+end:
+ if (user_result) {
+ *user_result = ret.result;
+ ret.result = NULL;
+ }
+
+ bt_put(ret.result);
+ return ret.status;
+}
+
+enum bt_query_status bt_query_executor_cancel(
+ struct bt_query_executor *query_exec)
+{
+ enum bt_query_status ret = BT_QUERY_STATUS_OK;
+
+ if (!query_exec) {
+ BT_LOGW_STR("Invalid parameter: query executor is NULL.");
+ ret = BT_QUERY_STATUS_INVALID;
+ goto end;
+ }
+
+ query_exec->canceled = BT_TRUE;
+ BT_LOGV("Canceled query executor: addr=%p", query_exec);
+
+end:
+ return ret;
+}
+
+bt_bool bt_query_executor_is_canceled(struct bt_query_executor *query_exec)
+{
+ bt_bool canceled = BT_FALSE;
+
+ if (!query_exec) {
+ BT_LOGW_STR("Invalid parameter: query executor is NULL.");
+ goto end;
+ }
+
+ canceled = query_exec->canceled;
+
+end:
+ return canceled;
+}
}
BT_HIDDEN
-struct bt_value *ctf_fs_query(struct bt_component_class *comp_class,
+struct bt_component_class_query_return ctf_fs_query(
+ struct bt_component_class *comp_class,
+ struct bt_query_executor *query_exec,
const char *object, struct bt_value *params)
{
- struct bt_value *result = NULL;
+ struct bt_component_class_query_return ret = {
+ .result = NULL,
+ .status = BT_QUERY_STATUS_OK,
+ };
if (!strcmp(object, "metadata-info")) {
- result = metadata_info_query(comp_class, params);
+ ret = metadata_info_query(comp_class, params);
} else if (!strcmp(object, "trace-info")) {
- result = trace_info_query(comp_class, params);
+ ret = trace_info_query(comp_class, params);
} else {
BT_LOGE("Unknown query object `%s`", object);
+ ret.status = BT_QUERY_STATUS_INVALID_OBJECT;
goto end;
}
end:
- return result;
+ return ret;
}
void ctf_fs_finalize(struct bt_private_component *component);
BT_HIDDEN
-struct bt_value *ctf_fs_query(struct bt_component_class *comp_class,
+struct bt_component_class_query_return ctf_fs_query(
+ struct bt_component_class *comp_class,
+ struct bt_query_executor *query_exec,
const char *object, struct bt_value *params);
BT_HIDDEN
};
BT_HIDDEN
-struct bt_value *metadata_info_query(struct bt_component_class *comp_class,
+struct bt_component_class_query_return metadata_info_query(
+ struct bt_component_class *comp_class,
struct bt_value *params)
{
- struct bt_value *result = NULL;
+ struct bt_component_class_query_return query_ret = {
+ .result = NULL,
+ .status = BT_QUERY_STATUS_OK,
+ };
+
struct bt_value *path_value = NULL;
char *metadata_text = NULL;
FILE *metadata_fp = NULL;
const char *path;
bool is_packetized;
- result = bt_value_map_create();
- if (!result) {
+ query_ret.result = bt_value_map_create();
+ if (!query_ret.result) {
+ query_ret.status = BT_QUERY_STATUS_NOMEM;
goto error;
}
if (!bt_value_is_map(params)) {
BT_LOGE_STR("Query parameters is not a map value object.");
+ query_ret.status = BT_QUERY_STATUS_INVALID_PARAMS;
goto error;
}
ret = bt_value_string_get(path_value, &path);
if (ret) {
BT_LOGE_STR("Cannot get `path` string parameter.");
+ query_ret.status = BT_QUERY_STATUS_INVALID_PARAMS;
goto error;
}
g_string_append(g_metadata_text, metadata_text);
- ret = bt_value_map_insert_string(result, "text",
+ ret = bt_value_map_insert_string(query_ret.result, "text",
g_metadata_text->str);
if (ret) {
BT_LOGE_STR("Cannot insert metadata text into query result.");
goto error;
}
- ret = bt_value_map_insert_bool(result, "is-packetized",
+ ret = bt_value_map_insert_bool(query_ret.result, "is-packetized",
is_packetized);
if (ret) {
BT_LOGE_STR("Cannot insert \"is-packetized\" attribute into query result.");
goto end;
error:
- BT_PUT(result);
+ BT_PUT(query_ret.result);
+
+ if (query_ret.status >= 0) {
+ query_ret.status = BT_QUERY_STATUS_ERROR;
+ }
end:
bt_put(path_value);
if (metadata_fp) {
fclose(metadata_fp);
}
- return result;
+
+ return query_ret;
}
static
}
BT_HIDDEN
-struct bt_value *trace_info_query(struct bt_component_class *comp_class,
+struct bt_component_class_query_return trace_info_query(
+ struct bt_component_class *comp_class,
struct bt_value *params)
{
- struct bt_value *trace_infos = NULL;
+ struct bt_component_class_query_return query_ret = {
+ .result = NULL,
+ .status = BT_QUERY_STATUS_OK,
+ };
+
struct bt_value *path_value = NULL;
int ret = 0;
const char *path = NULL;
if (!bt_value_is_map(params)) {
BT_LOGE("Query parameters is not a map value object.");
+ query_ret.status = BT_QUERY_STATUS_INVALID_PARAMS;
goto error;
}
ret = bt_value_string_get(path_value, &path);
if (ret) {
BT_LOGE("Cannot get `path` string parameter.");
+ query_ret.status = BT_QUERY_STATUS_INVALID_PARAMS;
goto error;
}
goto error;
}
- trace_infos = bt_value_array_create();
- if (!trace_infos) {
+ query_ret.result = bt_value_array_create();
+ if (!query_ret.result) {
+ query_ret.status = BT_QUERY_STATUS_NOMEM;
goto error;
}
goto error;
}
- status = bt_value_array_append(trace_infos, trace_info);
+ status = bt_value_array_append(query_ret.result, trace_info);
bt_put(trace_info);
if (status != BT_VALUE_STATUS_OK) {
goto error;
goto end;
error:
- BT_PUT(trace_infos);
+ BT_PUT(query_ret.result);
+
+ if (query_ret.status >= 0) {
+ query_ret.status = BT_QUERY_STATUS_ERROR;
+ }
+
end:
if (normalized_path) {
g_string_free(normalized_path, TRUE);
}
/* "path" becomes invalid with the release of path_value. */
bt_put(path_value);
- return trace_infos;
+ return query_ret;
}
#include <babeltrace/graph/component-class.h>
BT_HIDDEN
-struct bt_value *metadata_info_query(struct bt_component_class *comp_class,
+struct bt_component_class_query_return metadata_info_query(
+ struct bt_component_class *comp_class,
struct bt_value *params);
BT_HIDDEN
-struct bt_value *trace_info_query(struct bt_component_class *comp_class,
+struct bt_component_class_query_return trace_info_query(
+ struct bt_component_class *comp_class,
struct bt_value *params);
#endif /* BABELTRACE_PLUGIN_CTF_FS_QUERY_H */
enum bt_component_status lttng_live_component_init(struct bt_private_component *source,
struct bt_value *params, void *init_method_data);
-struct bt_value *lttng_live_query(struct bt_component_class *comp_class,
+struct bt_component_class_query_return lttng_live_query(
+ struct bt_component_class *comp_class,
+ struct bt_query_executor *query_exec,
const char *object, struct bt_value *params);
void lttng_live_component_finalize(struct bt_private_component *component);
}
static
-struct bt_value *lttng_live_query_list_sessions(struct bt_component_class *comp_class,
+struct bt_component_class_query_return lttng_live_query_list_sessions(
+ struct bt_component_class *comp_class,
+ struct bt_query_executor *query_exec,
struct bt_value *params)
{
+ struct bt_component_class_query_return query_ret = {
+ .result = NULL,
+ .status = BT_QUERY_STATUS_OK,
+ };
+
struct bt_value *url_value = NULL;
- struct bt_value *results = NULL;
const char *url;
struct bt_live_viewer_connection *viewer_connection = NULL;
url_value = bt_value_map_get(params, "url");
if (!url_value || bt_value_is_null(url_value) || !bt_value_is_string(url_value)) {
BT_LOGW("Mandatory \"url\" parameter missing");
+ query_ret.status = BT_QUERY_STATUS_INVALID_PARAMS;
goto error;
}
if (bt_value_string_get(url_value, &url) != BT_VALUE_STATUS_OK) {
BT_LOGW("\"url\" parameter is required to be a string value");
+ query_ret.status = BT_QUERY_STATUS_INVALID_PARAMS;
goto error;
}
goto error;
}
- results = bt_live_viewer_connection_list_sessions(viewer_connection);
+ query_ret.result =
+ bt_live_viewer_connection_list_sessions(viewer_connection);
+ if (!query_ret.result) {
+ goto error;
+ }
+
goto end;
+
error:
- BT_PUT(results);
+ BT_PUT(query_ret.result);
+
+ if (query_ret.status >= 0) {
+ query_ret.status = BT_QUERY_STATUS_ERROR;
+ }
+
end:
if (viewer_connection) {
bt_live_viewer_connection_destroy(viewer_connection);
}
BT_PUT(url_value);
- return results;
+ return query_ret;
}
BT_HIDDEN
-struct bt_value *lttng_live_query(struct bt_component_class *comp_class,
+struct bt_component_class_query_return lttng_live_query(
+ struct bt_component_class *comp_class,
+ struct bt_query_executor *query_exec,
const char *object, struct bt_value *params)
{
+ struct bt_component_class_query_return ret = {
+ .result = NULL,
+ .status = BT_QUERY_STATUS_OK,
+ };
+
if (strcmp(object, "sessions") == 0) {
return lttng_live_query_list_sessions(comp_class,
- params);
+ query_exec, params);
}
BT_LOGW("Unknown query object `%s`", object);
- return NULL;
+ ret.status = BT_QUERY_STATUS_INVALID_OBJECT;
+ return ret;
}
static
pass
with self.assertRaises(bt2.Error):
- MySink.query('obj', 23)
+ bt2.QueryExecutor().query(MySink, 'obj', 23)
def test_query_raises(self):
class MySink(bt2._UserSinkComponent):
pass
@classmethod
- def _query(cls, obj, params):
+ def _query(cls, query_exec, obj, params):
raise ValueError
with self.assertRaises(bt2.Error):
- MySink.query('obj', 23)
+ bt2.QueryExecutor().query(MySink, 'obj', 23)
def test_query_wrong_return_type(self):
class MySink(bt2._UserSinkComponent):
pass
@classmethod
- def _query(cls, obj, params):
+ def _query(cls, query_exec, obj, params):
return ...
with self.assertRaises(bt2.Error):
- MySink.query('obj', 23)
+ bt2.QueryExecutor().query(MySink, 'obj', 23)
def test_query_params_none(self):
class MySink(bt2._UserSinkComponent):
pass
@classmethod
- def _query(cls, obj, params):
+ def _query(cls, query_exec, obj, params):
nonlocal query_params
query_params = params
return None
query_params = None
params = None
- res = MySink.query('obj', params)
+ res = bt2.QueryExecutor().query(MySink, 'obj', params)
self.assertEqual(query_params, params)
self.assertIsNone(res)
del query_params
pass
@classmethod
- def _query(cls, obj, params):
+ def _query(cls, query_exec, obj, params):
nonlocal query_params
query_params = params
return 17.5
query_params = None
params = ['coucou', 23, None]
- res = MySink.query('obj', params)
+ res = bt2.QueryExecutor().query(MySink, 'obj', params)
self.assertEqual(query_params, params)
self.assertEqual(res, 17.5)
del query_params
pass
@classmethod
- def _query(cls, obj, params):
+ def _query(cls, query_exec, obj, params):
nonlocal query_params
query_params = params
return {
'null': None,
}
- res = MySink.query('obj', params)
+ res = bt2.QueryExecutor().query(MySink, 'obj', params)
self.assertEqual(query_params, params)
self.assertEqual(res, {
'null': None,
pass
@classmethod
- def _query(cls, obj, params):
+ def _query(cls, query_exec, obj, params):
return [obj, params, 23]
self._py_comp_cls = MySink
self.assertEqual(self._py_comp_cls, self._comp_cls)
def test_query(self):
- res = self._comp_cls.query('an object', {'yes': 'no', 'book': -17})
+ res = bt2.QueryExecutor().query(self._comp_cls, 'an object',
+ {'yes': 'no', 'book': -17})
expected = ['an object', {'yes': 'no', 'book': -17}, 23]
self.assertEqual(res, expected)
--- /dev/null
+from bt2 import values
+import unittest
+import copy
+import bt2
+
+
+class QueryExecutorTestCase(unittest.TestCase):
+ def test_query(self):
+ class MySink(bt2._UserSinkComponent):
+ def _consume(self):
+ pass
+
+ @classmethod
+ def _query(cls, query_exec, obj, params):
+ nonlocal query_params
+ query_params = params
+ return {
+ 'null': None,
+ 'bt2': 'BT2',
+ }
+
+ query_params = None
+ params = {
+ 'array': ['coucou', 23, None],
+ 'other_map': {
+ 'yes': 'yeah',
+ '19': 19,
+ 'minus 1.5': -1.5,
+ },
+ 'null': None,
+ }
+
+ res = bt2.QueryExecutor().query(MySink, 'obj', params)
+ self.assertEqual(query_params, params)
+ self.assertEqual(res, {
+ 'null': None,
+ 'bt2': 'BT2',
+ })
+ del query_params
+
+ def test_query_params_none(self):
+ class MySink(bt2._UserSinkComponent):
+ def _consume(self):
+ pass
+
+ @classmethod
+ def _query(cls, 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)
+ del query_params
+
+ def test_query_gen_error(self):
+ class MySink(bt2._UserSinkComponent):
+ def _consume(self):
+ pass
+
+ @classmethod
+ def _query(cls, query_exec, obj, params):
+ raise ValueError
+
+ with self.assertRaises(bt2.Error):
+ res = bt2.QueryExecutor().query(MySink, 'obj', [17, 23])
+
+ def test_query_invalid_object(self):
+ class MySink(bt2._UserSinkComponent):
+ def _consume(self):
+ pass
+
+ @classmethod
+ def _query(cls, query_exec, obj, params):
+ raise bt2.InvalidQueryObject
+
+ with self.assertRaises(bt2.InvalidQueryObject):
+ res = bt2.QueryExecutor().query(MySink, 'obj', [17, 23])
+
+ def test_query_invalid_params(self):
+ class MySink(bt2._UserSinkComponent):
+ def _consume(self):
+ pass
+
+ @classmethod
+ def _query(cls, query_exec, obj, params):
+ raise bt2.InvalidQueryParams
+
+ with self.assertRaises(bt2.InvalidQueryParams):
+ res = bt2.QueryExecutor().query(MySink, 'obj', [17, 23])
+
+ def test_query_try_again(self):
+ class MySink(bt2._UserSinkComponent):
+ def _consume(self):
+ pass
+
+ @classmethod
+ def _query(cls, query_exec, obj, params):
+ raise bt2.TryAgain
+
+ with self.assertRaises(bt2.TryAgain):
+ res = bt2.QueryExecutor().query(MySink, 'obj', [17, 23])
+
+ def test_cancel_no_query(self):
+ query_exec = bt2.QueryExecutor()
+ self.assertFalse(query_exec.is_canceled)
+ query_exec.cancel()
+ self.assertTrue(query_exec.is_canceled)
+
+ def test_query_canceled(self):
+ class MySink(bt2._UserSinkComponent):
+ def _consume(self):
+ pass
+
+ @classmethod
+ def _query(cls, query_exec, obj, params):
+ raise bt2.TryAgain
+
+ query_exec = bt2.QueryExecutor()
+ query_exec.cancel()
+
+ with self.assertRaises(bt2.QueryExecutorCanceled):
+ res = query_exec.query(MySink, 'obj', [17, 23])
+
+ def test_eq(self):
+ query_exec = bt2.QueryExecutor()
+ self.assertEqual(query_exec, query_exec)
+
+ def test_eq_invalid(self):
+ query_exec = bt2.QueryExecutor()
+ self.assertNotEqual(query_exec, 23)
return BT_NOTIFICATION_ITERATOR_STATUS_OK;
}
-static struct bt_value *query_method(
+static struct bt_component_class_query_return query_method(
struct bt_component_class *component_class,
+ struct bt_query_executor *query_exec,
const char *object, struct bt_value *params)
{
- int ret;
- struct bt_value *results = bt_value_array_create();
+ struct bt_component_class_query_return ret = {
+ .status = BT_QUERY_STATUS_OK,
+ .result = bt_value_array_create(),
+ };
+ int iret;
- assert(results);
- ret = bt_value_array_append_string(results, object);
- assert(ret == 0);
- ret = bt_value_array_append(results, params);
- assert(ret == 0);
- return results;
+ assert(ret.result);
+ iret = bt_value_array_append_string(ret.result, object);
+ assert(iret == 0);
+ iret = bt_value_array_append(ret.result, params);
+ assert(iret == 0);
+ return ret;
}
BT_PLUGIN_MODULE();
#include <babeltrace/values.h>
#include <babeltrace/graph/component.h>
#include <babeltrace/graph/graph.h>
+#include <babeltrace/graph/query-executor.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
const char *object_str;
enum bt_value_status value_ret;
enum bt_graph_status graph_ret;
+ struct bt_query_executor *query_exec = bt_query_executor_create();
+ int ret;
+ assert(query_exec);
assert(sfs_path);
diag("sfs plugin test below");
"bt_plugin_get_component_class_by_name_and_type() does not find a component class given the wrong type");
params = bt_value_integer_create_init(23);
assert(params);
- ok (!bt_component_class_query(NULL, "get-something", params),
- "bt_component_class_query() handles NULL (component class)");
- ok (!bt_component_class_query(filter_comp_class, NULL, params),
- "bt_component_class_query() handles NULL (object)");
- ok (!bt_component_class_query(filter_comp_class, "get-something", NULL),
- "bt_component_class_query() handles NULL (parameters)");
- results = bt_component_class_query(filter_comp_class,
- "get-something", params);
- ok(results, "bt_component_class_query() succeeds");
+ ret = bt_query_executor_query(NULL, filter_comp_class, "object",
+ params, &results);
+ ok (ret, "bt_query_executor_query() handles NULL (query executor)");
+ ret = bt_query_executor_query(query_exec, NULL, "object",
+ params, &results);
+ ok (ret, "bt_query_executor_query() handles NULL (component class)");
+ ret = bt_query_executor_query(query_exec, filter_comp_class, NULL,
+ params, &results);
+ ok (ret, "bt_query_executor_query() handles NULL (object)");
+ ret = bt_query_executor_query(query_exec, filter_comp_class,
+ "get-something", params, &results);
+ ok(ret == 0 && results, "bt_query_executor_query() succeeds");
assert(bt_value_is_array(results) && bt_value_array_size(results) == 2);
object = bt_value_array_get(results, 0);
assert(object && bt_value_is_string(object));
bt_put(res_params);
bt_put(results);
bt_put(params);
+ bt_put(query_exec);
}
static void test_create_all_from_dir(const char *plugin_dir)