+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;
+}
+