X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fcommon%2Ferror-query.c;h=2eb1c971715902767e6550c2971d7026c346c6b5;hp=a3663ad7c72e3bccd8926a28e2655459729655c5;hb=6a751b953a43c566b74818ec6325db0978e16c66;hpb=ad63a966ae7a204528fa77599f92100d7341be7a diff --git a/src/common/error-query.c b/src/common/error-query.c index a3663ad7c..2eb1c9717 100644 --- a/src/common/error-query.c +++ b/src/common/error-query.c @@ -10,9 +10,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -35,23 +37,17 @@ struct lttng_error_query_trigger { struct lttng_trigger *trigger; }; -struct lttng_error_query_action_comm { - LTTNG_OPTIONAL_COMM(uint32_t) action_index; - /* Trigger payload. */ - char payload[]; +struct lttng_error_query_condition { + struct lttng_error_query parent; + /* Mutable only because of the reference count. */ + struct lttng_trigger *trigger; }; struct lttng_error_query_action { struct lttng_error_query parent; /* Mutable only because of the reference count. */ struct lttng_trigger *trigger; - /* - * Index of the target action. Since action lists can't be nested, - * the targetted action is the top-level group if the action_index is - * unset. Otherwise, the index refers to the index within the top-level - * group. - */ - LTTNG_OPTIONAL(unsigned int) action_index; + struct lttng_action_path action_path; }; struct lttng_error_query_result { @@ -90,6 +86,15 @@ struct lttng_error_query_results { struct lttng_dynamic_pointer_array results; }; +static +enum lttng_error_code lttng_error_query_result_mi_serialize( + const struct lttng_error_query_result *result, + struct mi_writer *writer); + +static +enum lttng_error_code lttng_error_query_result_counter_mi_serialize( + const struct lttng_error_query_result *result, + struct mi_writer *writer); struct lttng_error_query *lttng_error_query_trigger_create( const struct lttng_trigger *trigger) @@ -122,15 +127,13 @@ end: return query ? &query->parent : NULL; } -extern struct lttng_error_query *lttng_error_query_action_create( - const struct lttng_trigger *trigger, - const struct lttng_action *action) +struct lttng_error_query *lttng_error_query_condition_create( + const struct lttng_trigger *trigger) { - struct lttng_error_query_action *query = NULL; - typeof(query->action_index) action_index; + struct lttng_error_query_condition *query = NULL; struct lttng_trigger *trigger_copy = NULL; - if (!trigger || !action) { + if (!trigger) { goto end; } @@ -139,49 +142,83 @@ extern struct lttng_error_query *lttng_error_query_action_create( goto end; } + query = zmalloc(sizeof(*query)); + if (!query) { + PERROR("Failed to allocate condition error query"); + goto error; + } + + query->parent.target_type = LTTNG_ERROR_QUERY_TARGET_TYPE_CONDITION; + query->trigger = trigger_copy; + trigger_copy = NULL; + +error: + lttng_trigger_put(trigger_copy); +end: + return query ? &query->parent : NULL; +} + +static +struct lttng_action *get_trigger_action_from_path( + struct lttng_trigger *trigger, + const struct lttng_action_path *action_path) +{ + size_t index_count, i; + enum lttng_action_path_status path_status; + struct lttng_action *current_action = NULL; + + path_status = lttng_action_path_get_index_count( + action_path, &index_count); + if (path_status != LTTNG_ACTION_PATH_STATUS_OK) { + goto end; + } + + current_action = lttng_trigger_get_action(trigger); + for (i = 0; i < index_count; i++) { + uint64_t path_index; + + path_status = lttng_action_path_get_index_at_index( + action_path, i, &path_index); + current_action = lttng_action_list_borrow_mutable_at_index( + current_action, path_index); + if (!current_action) { + /* Invalid action path. */ + goto end; + } + } + +end: + return current_action; +} + +static +bool is_valid_action_path(const struct lttng_trigger *trigger, + const struct lttng_action_path *action_path) +{ /* - * If an action is not the top-level action of the trigger, our only - * hope of finding its position is if the top-level action is an - * action list. - * - * Note that action comparisons are performed by pointer since multiple - * otherwise identical actions can be found in an action list (two - * notify actions, for example). + * While 'trigger's constness is casted-away, the trigger and resulting + * action are not modified; we merely check for the action's existence. */ - if (action != trigger->action && - lttng_action_get_type(trigger->action) == - LTTNG_ACTION_TYPE_GROUP) { - unsigned int i, action_list_count; - enum lttng_action_status action_status; - - action_status = lttng_action_list_get_count( - trigger->action, &action_list_count); - if (action_status != LTTNG_ACTION_STATUS_OK) { - goto error; - } + return !!get_trigger_action_from_path( + (struct lttng_trigger *) trigger, action_path); +} - for (i = 0; i < action_list_count; i++) { - const struct lttng_action *candidate_action = - lttng_action_list_get_at_index( - trigger->action, i); +struct lttng_error_query *lttng_error_query_action_create( + const struct lttng_trigger *trigger, + const struct lttng_action_path *action_path) +{ + struct lttng_error_query_action *query = NULL; + struct lttng_trigger *trigger_copy = NULL; + int ret_copy; - assert(candidate_action); - if (candidate_action == action) { - LTTNG_OPTIONAL_SET(&action_index, i); - break; - } - } + if (!trigger || !action_path || + !is_valid_action_path(trigger, action_path)) { + goto end; + } - if (!action_index.is_set) { - /* Not found; invalid action. */ - goto error; - } - } else { - /* - * Trigger action is not a group and not equal to the target - * action; invalid action provided. - */ - goto error; + trigger_copy = lttng_trigger_copy(trigger); + if (!trigger_copy) { + goto end; } query = zmalloc(sizeof(*query)); @@ -190,12 +227,19 @@ extern struct lttng_error_query *lttng_error_query_action_create( goto error; } + ret_copy = lttng_action_path_copy(action_path, &query->action_path); + if (ret_copy) { + goto error; + } + query->parent.target_type = LTTNG_ERROR_QUERY_TARGET_TYPE_ACTION; query->trigger = trigger_copy; trigger_copy = NULL; - query->action_index = action_index; + goto end; + error: lttng_trigger_put(trigger_copy); + lttng_error_query_destroy(query ? &query->parent : NULL); end: return query ? &query->parent : NULL; } @@ -608,6 +652,28 @@ end: return ret; } +static +int lttng_error_query_condition_serialize(const struct lttng_error_query *query, + struct lttng_payload *payload) +{ + int ret; + const struct lttng_error_query_condition *query_trigger = + container_of(query, typeof(*query_trigger), parent); + + if (!lttng_trigger_validate(query_trigger->trigger)) { + ret = -1; + goto end; + } + + ret = lttng_trigger_serialize(query_trigger->trigger, payload); + if (ret) { + goto end; + } + +end: + return ret; +} + static int lttng_error_query_action_serialize(const struct lttng_error_query *query, struct lttng_payload *payload) @@ -615,26 +681,22 @@ int lttng_error_query_action_serialize(const struct lttng_error_query *query, int ret; const struct lttng_error_query_action *query_action = container_of(query, typeof(*query_action), parent); - struct lttng_error_query_action_comm header = { - .action_index.is_set = query_action->action_index.is_set, - .action_index.value = query_action->action_index.value, - }; if (!lttng_trigger_validate(query_action->trigger)) { ret = -1; goto end; } - ret = lttng_dynamic_buffer_append( - &payload->buffer, &header, sizeof(header)); + ret = lttng_trigger_serialize(query_action->trigger, payload); if (ret) { goto end; } - ret = lttng_trigger_serialize(query_action->trigger, payload); + ret = lttng_action_path_serialize(&query_action->action_path, payload); if (ret) { goto end; } + end: return ret; } @@ -656,6 +718,16 @@ const struct lttng_trigger *lttng_error_query_trigger_borrow_target( return query_trigger->trigger; } +LTTNG_HIDDEN +const struct lttng_trigger *lttng_error_query_condition_borrow_target( + const struct lttng_error_query *query) +{ + const struct lttng_error_query_condition *query_trigger = + container_of(query, typeof(*query_trigger), parent); + + return query_trigger->trigger; +} + LTTNG_HIDDEN const struct lttng_trigger *lttng_error_query_action_borrow_trigger_target( const struct lttng_error_query *query) @@ -671,28 +743,11 @@ struct lttng_action *lttng_error_query_action_borrow_action_target( const struct lttng_error_query *query, struct lttng_trigger *trigger) { - struct lttng_action *target_action = NULL; const struct lttng_error_query_action *query_action = container_of(query, typeof(*query_action), parent); - struct lttng_action *trigger_action = - lttng_trigger_get_action(trigger); - - if (!query_action->action_index.is_set) { - target_action = trigger_action; - } else { - if (lttng_action_get_type(trigger_action) != - LTTNG_ACTION_TYPE_GROUP) { - ERR("Invalid action error query target index: trigger action is not a group"); - goto end; - } - target_action = lttng_action_list_borrow_mutable_at_index( - trigger_action, - LTTNG_OPTIONAL_GET(query_action->action_index)); - } - -end: - return target_action; + return get_trigger_action_from_path( + trigger, &query_action->action_path); } LTTNG_HIDDEN @@ -700,7 +755,7 @@ int lttng_error_query_serialize(const struct lttng_error_query *query, struct lttng_payload *payload) { int ret; - struct lttng_error_query_comm header = { + const struct lttng_error_query_comm header = { .target_type = (typeof(header.target_type)) query->target_type, }; @@ -718,6 +773,13 @@ int lttng_error_query_serialize(const struct lttng_error_query *query, goto end; } + break; + case LTTNG_ERROR_QUERY_TARGET_TYPE_CONDITION: + ret = lttng_error_query_condition_serialize(query, payload); + if (ret) { + goto end; + } + break; case LTTNG_ERROR_QUERY_TARGET_TYPE_ACTION: ret = lttng_error_query_action_serialize(query, payload); @@ -782,28 +844,41 @@ ssize_t lttng_error_query_create_from_payload(struct lttng_payload_view *view, break; } - case LTTNG_ERROR_QUERY_TARGET_TYPE_ACTION: + case LTTNG_ERROR_QUERY_TARGET_TYPE_CONDITION: { - const struct lttng_action *target_action; ssize_t trigger_used_size; - struct lttng_error_query_action_comm *action_header; + struct lttng_payload_view trigger_view = + lttng_payload_view_from_view( + view, used_size, -1); - { - struct lttng_payload_view action_header_view = - lttng_payload_view_from_view(view, - used_size, - sizeof(*action_header)); + if (!lttng_payload_view_is_valid(&trigger_view)) { + used_size = -1; + goto end; + } - if (!lttng_payload_view_is_valid(&action_header_view)) { - used_size = -1; - goto end; - } + trigger_used_size = lttng_trigger_create_from_payload( + &trigger_view, &trigger); + if (trigger_used_size < 0) { + used_size = -1; + goto end; + } - action_header = (typeof(action_header)) action_header_view.buffer.data; - used_size += sizeof(*action_header); + used_size += trigger_used_size; + + *query = lttng_error_query_condition_create(trigger); + if (!*query) { + used_size = -1; + goto end; } + break; + } + case LTTNG_ERROR_QUERY_TARGET_TYPE_ACTION: + { + struct lttng_action_path *action_path = NULL; + { + ssize_t trigger_used_size; struct lttng_payload_view trigger_view = lttng_payload_view_from_view( view, used_size, -1); @@ -823,22 +898,30 @@ ssize_t lttng_error_query_create_from_payload(struct lttng_payload_view *view, used_size += trigger_used_size; } - if (!action_header->action_index.is_set) { - target_action = trigger->action; - } else { - if (lttng_action_get_type(trigger->action) != - LTTNG_ACTION_TYPE_GROUP) { + { + ssize_t action_path_used_size; + struct lttng_payload_view action_path_view = + lttng_payload_view_from_view( + view, used_size, -1); + + if (!lttng_payload_view_is_valid(&action_path_view)) { + used_size = -1; + goto end; + } + + action_path_used_size = lttng_action_path_create_from_payload( + &action_path_view, &action_path); + if (action_path_used_size < 0) { used_size = -1; goto end; } - target_action = lttng_action_list_get_at_index( - trigger->action, - action_header->action_index.value); + used_size += action_path_used_size; } *query = lttng_error_query_action_create( - trigger, target_action); + trigger, action_path); + lttng_action_path_destroy(action_path); if (!*query) { used_size = -1; goto end; @@ -976,3 +1059,176 @@ enum lttng_error_query_result_status lttng_error_query_result_counter_get_value( end: return status; } + +static +enum lttng_error_code lttng_error_query_result_counter_mi_serialize( + const struct lttng_error_query_result *result, + struct mi_writer *writer) +{ + int ret; + enum lttng_error_code ret_code; + enum lttng_error_query_result_status status; + uint64_t value; + + assert(result); + assert(writer); + + status = lttng_error_query_result_counter_get_value(result, &value); + assert(status == LTTNG_ERROR_QUERY_RESULT_STATUS_OK); + + /* Open error query result counter element. */ + ret = mi_lttng_writer_open_element( + writer, mi_lttng_element_error_query_result_counter); + if (ret) { + goto mi_error; + } + + /* Value. */ + ret = mi_lttng_writer_write_element_unsigned_int(writer, + mi_lttng_element_error_query_result_counter_value, + value); + if (ret) { + goto mi_error; + } + + /* Close error query result counter element. */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto mi_error; + } + + ret_code = LTTNG_OK; + goto end; + +mi_error: + ret_code = LTTNG_ERR_MI_IO_FAIL; +end: + return ret_code; +} + +static +enum lttng_error_code lttng_error_query_result_mi_serialize( + const struct lttng_error_query_result *result, + struct mi_writer *writer) +{ + int ret; + enum lttng_error_code ret_code; + enum lttng_error_query_result_status result_status; + enum lttng_error_query_result_type type; + const char *name = NULL; + const char *description = NULL; + + assert(result); + assert(writer); + + type = lttng_error_query_result_get_type(result); + + result_status = lttng_error_query_result_get_name(result, &name); + assert(result_status == LTTNG_ERROR_QUERY_RESULT_STATUS_OK); + + result_status = lttng_error_query_result_get_description( + result, &description); + assert(result_status == LTTNG_ERROR_QUERY_RESULT_STATUS_OK); + + /* Open error query result element. */ + ret = mi_lttng_writer_open_element( + writer, mi_lttng_element_error_query_result); + if (ret) { + goto mi_error; + } + + /* Name. */ + ret = mi_lttng_writer_write_element_string( + writer, mi_lttng_element_error_query_result_name, name); + if (ret) { + goto mi_error; + } + + /* Description. */ + ret = mi_lttng_writer_write_element_string(writer, + mi_lttng_element_error_query_result_description, + description); + if (ret) { + goto mi_error; + } + + /* Serialize the result according to its sub type. */ + switch (type) { + case LTTNG_ERROR_QUERY_RESULT_TYPE_COUNTER: + ret_code = lttng_error_query_result_counter_mi_serialize( + result, writer); + break; + default: + abort(); + } + + if (ret_code != LTTNG_OK) { + goto end; + } + + /* Close error query result element. */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto mi_error; + } + + ret_code = LTTNG_OK; + goto end; + +mi_error: + ret_code = LTTNG_ERR_MI_IO_FAIL; +end: + return ret_code; +} + +LTTNG_HIDDEN +enum lttng_error_code lttng_error_query_results_mi_serialize( + const struct lttng_error_query_results *results, + struct mi_writer *writer) +{ + int ret; + enum lttng_error_code ret_code; + unsigned int i, count; + enum lttng_error_query_results_status results_status; + + assert(results); + assert(writer); + + /* Open error query results element. */ + ret = mi_lttng_writer_open_element( + writer, mi_lttng_element_error_query_results); + if (ret) { + goto mi_error; + } + + results_status = lttng_error_query_results_get_count(results, &count); + assert(results_status == LTTNG_ERROR_QUERY_RESULTS_STATUS_OK); + + for (i = 0; i < count; i++) { + const struct lttng_error_query_result *result; + + results_status = lttng_error_query_results_get_result( + results, &result, i); + assert(results_status == LTTNG_ERROR_QUERY_RESULTS_STATUS_OK); + + /* A single error query result. */ + ret_code = lttng_error_query_result_mi_serialize(result, writer); + if (ret_code != LTTNG_OK) { + goto end; + } + } + + /* Close error query results. */ + ret = mi_lttng_writer_close_element(writer); + if (ret) { + goto mi_error; + } + + ret_code = LTTNG_OK; + goto end; + +mi_error: + ret_code = LTTNG_ERR_MI_IO_FAIL; +end: + return ret_code; +}