X-Git-Url: https://git.efficios.com/?a=blobdiff_plain;f=src%2Fcommon%2Fmap-query.c;fp=src%2Fcommon%2Fmap-query.c;h=f25001f88519b0408f505112394424a9731527f3;hb=c3e68e71e0bca1c067bf24447163ac6850a9b09e;hp=0000000000000000000000000000000000000000;hpb=11f6ce94d8fb73f017888681aaba5d7df55fc735;p=deliverable%2Flttng-tools.git diff --git a/src/common/map-query.c b/src/common/map-query.c new file mode 100644 index 000000000..f25001f88 --- /dev/null +++ b/src/common/map-query.c @@ -0,0 +1,674 @@ +/* + * Copyright (C) 2020 Francis Deslauriers + * + * SPDX-License-Identifier: LGPL-2.1-only + * + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +struct lttng_map_query *lttng_map_query_create( + enum lttng_map_query_config_cpu cpu, + enum lttng_map_query_config_buffer buffer, + enum lttng_map_query_config_app_bitness bitness) +{ + struct lttng_map_query *query = NULL; + + if ((buffer == LTTNG_MAP_QUERY_CONFIG_BUFFER_KERNEL_GLOBAL) ^ + (bitness == LTTNG_MAP_QUERY_CONFIG_APP_BITNESS_KERNEL)) { + /* + * If any of the buffer or bitness config is set to kernel, + * they other has to as well. + */ + goto end; + } + + if (bitness != LTTNG_MAP_QUERY_CONFIG_APP_BITNESS_ALL && + bitness != LTTNG_MAP_QUERY_CONFIG_APP_BITNESS_KERNEL) { + /* We currently don't support targetting a specific bitness. */ + goto end; + } + + query = zmalloc(sizeof(struct lttng_map_query)); + if (!query) { + goto end; + } + + query->config_cpu = cpu; + query->config_buffer = buffer; + query->config_bitness = bitness; + + query->sum_by_uid = false; + query->sum_by_pid = false; + query->sum_by_cpu = false; + // defaults to true for now. + query->sum_by_app_bitness = true; + + if (query->config_cpu == LTTNG_MAP_QUERY_CONFIG_CPU_SUBSET) { + lttng_dynamic_array_init(&query->cpu_array, sizeof(int), NULL); + } + + switch(query->config_buffer) { + case LTTNG_MAP_QUERY_CONFIG_BUFFER_UST_UID_SUBSET: + lttng_dynamic_array_init(&query->uid_array, sizeof(uid_t), NULL); + break; + case LTTNG_MAP_QUERY_CONFIG_BUFFER_UST_PID_SUBSET: + lttng_dynamic_array_init(&query->pid_array, sizeof(pid_t), NULL); + break; + default: + break; + } +end: + return query; +} + +enum lttng_map_query_status lttng_map_query_set_sum_by_cpu( + struct lttng_map_query *query, bool sum_by_cpu) +{ + query->sum_by_cpu = sum_by_cpu; + + return LTTNG_MAP_QUERY_STATUS_OK; +} + +enum lttng_map_query_status lttng_map_query_set_sum_by_app_bitness( + struct lttng_map_query *query, bool sum_by_app_bitness) +{ + enum lttng_map_query_status status; + + if (query->config_bitness != LTTNG_MAP_QUERY_CONFIG_APP_BITNESS_ALL) { + status = LTTNG_MAP_QUERY_STATUS_INVALID; + goto end; + } + + query->sum_by_app_bitness = sum_by_app_bitness; + status = LTTNG_MAP_QUERY_STATUS_OK; + +end: + return status; +} + +enum lttng_map_query_status lttng_map_query_set_sum_by_pid( + struct lttng_map_query *query, bool sum_by_pid) +{ + enum lttng_map_query_status status; + + switch (query->config_buffer) { + case LTTNG_MAP_QUERY_CONFIG_BUFFER_UST_PID_ALL: + case LTTNG_MAP_QUERY_CONFIG_BUFFER_UST_PID_SUBSET: + break; + default: + status = LTTNG_MAP_QUERY_STATUS_INVALID; + goto end; + } + + query->sum_by_pid = sum_by_pid; + status = LTTNG_MAP_QUERY_STATUS_OK; + +end: + return status; +} + +enum lttng_map_query_status lttng_map_query_set_sum_by_uid( + struct lttng_map_query *query, bool sum_by_uid) +{ + enum lttng_map_query_status status; + + switch (query->config_buffer) { + case LTTNG_MAP_QUERY_CONFIG_BUFFER_UST_UID_ALL: + case LTTNG_MAP_QUERY_CONFIG_BUFFER_UST_UID_SUBSET: + break; + default: + status = LTTNG_MAP_QUERY_STATUS_INVALID; + goto end; + } + + query->sum_by_uid = sum_by_uid; + status = LTTNG_MAP_QUERY_STATUS_OK; + +end: + return status; +} + +enum lttng_map_query_status lttng_map_query_add_cpu( + struct lttng_map_query *query, int cpu_id) +{ + enum lttng_map_query_status status; + unsigned int cpu_count; + int ret; + + if (query->config_cpu != LTTNG_MAP_QUERY_CONFIG_CPU_SUBSET) { + status = LTTNG_MAP_QUERY_STATUS_INVALID; + goto end; + } + + lttng_map_query_get_cpu_count(query, &cpu_count); + if (cpu_count > 0) { + ERR("Only one CPU can be targeted in a query at the moment"); + status = LTTNG_MAP_QUERY_STATUS_INVALID; + goto end; + } + + ret = lttng_dynamic_array_add_element(&query->cpu_array, &cpu_id); + if (ret) { + status = LTTNG_MAP_QUERY_STATUS_ERROR; + goto end; + } + + status = LTTNG_MAP_QUERY_STATUS_OK; +end: + return status; +} + +enum lttng_map_query_status lttng_map_query_add_uid( + struct lttng_map_query *query, uid_t uid) +{ + int ret; + unsigned int uid_count; + enum lttng_map_query_status status; + + if (query->config_buffer != LTTNG_MAP_QUERY_CONFIG_BUFFER_UST_UID_SUBSET) { + status = LTTNG_MAP_QUERY_STATUS_INVALID; + goto end; + } + + lttng_map_query_get_uid_count(query, &uid_count); + if (uid_count > 0) { + ERR("Only one UID can be targeted in a query at the moment"); + status = LTTNG_MAP_QUERY_STATUS_INVALID; + goto end; + } + + ret = lttng_dynamic_array_add_element(&query->uid_array, &uid); + if (ret) { + status = LTTNG_MAP_QUERY_STATUS_ERROR; + goto end; + } + + status = LTTNG_MAP_QUERY_STATUS_OK; +end: + return status; +} + +enum lttng_map_query_status lttng_map_query_add_pid( + struct lttng_map_query *query, pid_t pid) +{ + int ret; + unsigned int pid_count; + enum lttng_map_query_status status; + + if (query->config_buffer != LTTNG_MAP_QUERY_CONFIG_BUFFER_UST_PID_SUBSET) { + status = LTTNG_MAP_QUERY_STATUS_INVALID; + goto end; + } + + lttng_map_query_get_pid_count(query, &pid_count); + if (pid_count > 0) { + ERR("Only one PID can be targeted in a query at the moment"); + status = LTTNG_MAP_QUERY_STATUS_INVALID; + goto end; + } + + ret = lttng_dynamic_array_add_element(&query->pid_array, &pid); + if (ret) { + status = LTTNG_MAP_QUERY_STATUS_ERROR; + goto end; + } + + status = LTTNG_MAP_QUERY_STATUS_OK; +end: + return status; +} + +enum lttng_map_query_status lttng_map_query_add_key_filter( + struct lttng_map_query *query, const char *key_filter) +{ + enum lttng_map_query_status status; + + query->key_filter = strdup(key_filter); + if (!query->key_filter) { + status = LTTNG_MAP_QUERY_STATUS_ERROR; + goto end; + } + + status = LTTNG_MAP_QUERY_STATUS_OK; +end: + return status; +} + +enum lttng_map_query_config_cpu lttng_map_query_get_config_cpu( + const struct lttng_map_query *query) +{ + return query->config_cpu; +} + +enum lttng_map_query_config_buffer lttng_map_query_get_config_buffer( + const struct lttng_map_query *query) +{ + return query->config_buffer; +} + +enum lttng_map_query_config_app_bitness lttng_map_query_get_config_app_bitness( + const struct lttng_map_query *query) +{ + return query->config_bitness; +} + +bool lttng_map_query_get_config_sum_by_cpu( + const struct lttng_map_query *query) +{ + return query->sum_by_cpu; +} + +bool lttng_map_query_get_config_sum_by_pid( + const struct lttng_map_query *query) +{ + return query->sum_by_pid; +} + +bool lttng_map_query_get_config_sum_by_uid( + const struct lttng_map_query *query) +{ + return query->sum_by_uid; +} + +bool lttng_map_query_get_config_sum_by_app_bitness( + const struct lttng_map_query *query) +{ + return query->sum_by_app_bitness; +} + +enum lttng_map_query_status lttng_map_query_get_cpu_count( + const struct lttng_map_query *query, unsigned int *count) +{ + enum lttng_map_query_status status; + + assert(query); + if (query->config_cpu != LTTNG_MAP_QUERY_CONFIG_CPU_SUBSET) { + status = LTTNG_MAP_QUERY_STATUS_INVALID; + goto end; + } + + if (!count) { + status = LTTNG_MAP_QUERY_STATUS_INVALID; + goto end; + } + + *count = lttng_dynamic_array_get_count(&query->cpu_array); + status = LTTNG_MAP_QUERY_STATUS_OK; + +end: + return status; +} + +enum lttng_map_query_status lttng_map_query_get_cpu_at_index( + const struct lttng_map_query *query, unsigned int index, + int *cpu) +{ + enum lttng_map_query_status status; + + assert(query); + + if (query->config_cpu != LTTNG_MAP_QUERY_CONFIG_CPU_SUBSET) { + status = LTTNG_MAP_QUERY_STATUS_INVALID; + goto end; + } + + + *cpu = *(int *) lttng_dynamic_array_get_element(&query->cpu_array, index); + status = LTTNG_MAP_QUERY_STATUS_OK; +end: + return status; +} + +enum lttng_map_query_status lttng_map_query_get_uid_count( + const struct lttng_map_query *query, unsigned int *count) +{ + enum lttng_map_query_status status; + + assert(query); + if (query->config_buffer != LTTNG_MAP_QUERY_CONFIG_BUFFER_UST_UID_SUBSET) { + status = LTTNG_MAP_QUERY_STATUS_INVALID; + goto end; + } + + if (!count) { + status = LTTNG_MAP_QUERY_STATUS_INVALID; + goto end; + } + + *count = lttng_dynamic_array_get_count(&query->uid_array); + status = LTTNG_MAP_QUERY_STATUS_OK; + +end: + return status; +} + +enum lttng_map_query_status lttng_map_query_get_uid_at_index( + const struct lttng_map_query *query, unsigned int index, + uid_t *uid) +{ + enum lttng_map_query_status status; + + assert(query); + + if (query->config_buffer != LTTNG_MAP_QUERY_CONFIG_BUFFER_UST_UID_SUBSET) { + status = LTTNG_MAP_QUERY_STATUS_INVALID; + goto end; + } + + + *uid = *(uid_t *) lttng_dynamic_array_get_element(&query->uid_array, index); + status = LTTNG_MAP_QUERY_STATUS_OK; +end: + return status; +} + +enum lttng_map_query_status lttng_map_query_get_pid_count( + const struct lttng_map_query *query, unsigned int *count) +{ + enum lttng_map_query_status status; + + assert(query); + if (query->config_buffer != LTTNG_MAP_QUERY_CONFIG_BUFFER_UST_PID_SUBSET) { + status = LTTNG_MAP_QUERY_STATUS_INVALID; + goto end; + } + + if (!count) { + status = LTTNG_MAP_QUERY_STATUS_INVALID; + goto end; + } + + *count = lttng_dynamic_array_get_count(&query->pid_array); + status = LTTNG_MAP_QUERY_STATUS_OK; + +end: + return status; +} + +enum lttng_map_query_status lttng_map_query_get_pid_at_index( + const struct lttng_map_query *query, unsigned int index, + pid_t *pid) +{ + enum lttng_map_query_status status; + + assert(query); + + if (query->config_buffer != LTTNG_MAP_QUERY_CONFIG_BUFFER_UST_PID_SUBSET) { + status = LTTNG_MAP_QUERY_STATUS_INVALID; + goto end; + } + + + *pid = *(pid_t *) lttng_dynamic_array_get_element(&query->pid_array, index); + status = LTTNG_MAP_QUERY_STATUS_OK; +end: + return status; +} + + +enum lttng_map_query_status lttng_map_query_get_key_filter( + const struct lttng_map_query *query, const char **key_filter) +{ + enum lttng_map_query_status status; + + if (query->key_filter == NULL) { + status = LTTNG_MAP_QUERY_STATUS_NONE; + goto end; + } + + *key_filter = query->key_filter; + status = LTTNG_MAP_QUERY_STATUS_OK; +end: + return status; +} + +LTTNG_HIDDEN +ssize_t lttng_map_query_create_from_payload(struct lttng_payload_view *src_view, + struct lttng_map_query **query) +{ + ssize_t ret, offset = 0; + struct lttng_map_query *local_query; + const struct lttng_map_query_comm *query_comm; + + if (!src_view || !query) { + ret = -1; + goto end; + } + + query_comm = (typeof(query_comm)) src_view->buffer.data; + offset += sizeof(*query_comm); + + local_query = lttng_map_query_create(query_comm->config_cpu, + query_comm->config_buffer, query_comm->config_app_bitness); + if (!local_query) { + ret = -1; + goto end; + } + + local_query->sum_by_cpu = query_comm->sum_by_cpu; + local_query->sum_by_pid = query_comm->sum_by_pid; + local_query->sum_by_uid = query_comm->sum_by_uid; + local_query->sum_by_app_bitness = query_comm->sum_by_app_bitness; + + if (query_comm->key_filter_length != 0) { + const char *key_filter; + struct lttng_payload_view key_filter_view = + lttng_payload_view_from_view( + src_view, offset, + query_comm->key_filter_length); + + key_filter = key_filter_view.buffer.data; + if (!lttng_buffer_view_contains_string(&key_filter_view.buffer, + key_filter, query_comm->key_filter_length)){ + ret = -1; + goto end; + } + + lttng_map_query_add_key_filter(local_query, key_filter); + + offset += query_comm->key_filter_length; + } + + if (local_query->config_cpu == LTTNG_MAP_QUERY_CONFIG_CPU_SUBSET) { + unsigned int cpu_idx; + + assert(query_comm->cpu_count > 0); + + for (cpu_idx = 0; cpu_idx < query_comm->cpu_count; cpu_idx++) { + int cpu_id; + struct lttng_payload_view cpu_id_view = + lttng_payload_view_from_view( src_view, + offset, sizeof(cpu_id)); + cpu_id = *(int *) cpu_id_view.buffer.data; + lttng_map_query_add_cpu(local_query, cpu_id); + offset+=sizeof(cpu_id); + } + } + + switch (local_query->config_buffer){ + case LTTNG_MAP_QUERY_CONFIG_BUFFER_UST_PID_SUBSET: + { + unsigned int pid_idx; + + assert(query_comm->pid_count > 0); + + for (pid_idx = 0; pid_idx < query_comm->pid_count; pid_idx++) { + pid_t pid; + struct lttng_payload_view pid_view = + lttng_payload_view_from_view( src_view, + offset, sizeof(pid)); + pid = *(pid_t *) pid_view.buffer.data; + lttng_map_query_add_pid(local_query, pid); + offset+=sizeof(pid); + } + break; + } + case LTTNG_MAP_QUERY_CONFIG_BUFFER_UST_UID_SUBSET: + { + unsigned int uid_idx; + + assert(query_comm->uid_count > 0); + + for (uid_idx = 0; uid_idx < query_comm->uid_count; uid_idx++) { + uid_t uid; + struct lttng_payload_view uid_view = + lttng_payload_view_from_view( src_view, + offset, sizeof(uid)); + uid = *(uid_t *) uid_view.buffer.data; + lttng_map_query_add_uid(local_query, uid); + offset+=sizeof(uid); + } + } + default: + break; + } + + ret = offset; + *query = local_query; + local_query = NULL; +end: + return ret; +} + +LTTNG_HIDDEN +int lttng_map_query_serialize(const struct lttng_map_query *query, + struct lttng_payload *payload) +{ + int ret; + struct lttng_map_query_comm query_comm = {}; + enum lttng_map_query_status status; + + query_comm.config_cpu = (uint8_t) query->config_cpu; + query_comm.config_buffer = (uint8_t) query->config_buffer; + query_comm.config_app_bitness = (uint8_t) query->config_bitness; + + query_comm.sum_by_cpu = (uint8_t) query->sum_by_cpu; + query_comm.sum_by_uid = (uint8_t) query->sum_by_uid; + query_comm.sum_by_pid = (uint8_t) query->sum_by_pid; + query_comm.sum_by_app_bitness = (uint8_t) query->sum_by_app_bitness; + + if (query->config_cpu == LTTNG_MAP_QUERY_CONFIG_CPU_SUBSET) { + unsigned int cpu_count; + status = lttng_map_query_get_cpu_count(query, &cpu_count); + if (status != LTTNG_MAP_QUERY_STATUS_OK) { + ret = -1; + goto end; + } + + query_comm.cpu_count = cpu_count; + } + + switch (query->config_buffer){ + case LTTNG_MAP_QUERY_CONFIG_BUFFER_UST_PID_SUBSET: + { + unsigned int pid_count; + status = lttng_map_query_get_pid_count(query, &pid_count); + if (status != LTTNG_MAP_QUERY_STATUS_OK) { + ret = -1; + goto end; + } + query_comm.pid_count = pid_count; + break; + } + case LTTNG_MAP_QUERY_CONFIG_BUFFER_UST_UID_SUBSET: + { + unsigned int uid_count; + status = lttng_map_query_get_uid_count(query, &uid_count); + if (status != LTTNG_MAP_QUERY_STATUS_OK) { + ret = -1; + goto end; + } + query_comm.uid_count = uid_count; + } + default: + break; + } + + if (query->key_filter) { + query_comm.key_filter_length = strlen(query->key_filter) + 1; + } else { + query_comm.key_filter_length = 0; + } + + ret = lttng_dynamic_buffer_append(&payload->buffer, &query_comm, + sizeof(query_comm)); + if (ret) { + goto end; + } + + /* key_filter */ + ret = lttng_dynamic_buffer_append( + &payload->buffer, query->key_filter, + query_comm.key_filter_length); + if (ret) { + goto end; + } + + if (query->config_cpu == LTTNG_MAP_QUERY_CONFIG_CPU_SUBSET) { + ret = lttng_dynamic_buffer_append(&payload->buffer, + query->cpu_array.buffer.data, + query->cpu_array.buffer.size); + if (ret) { + goto end; + } + } + + switch (query->config_buffer){ + case LTTNG_MAP_QUERY_CONFIG_BUFFER_UST_PID_SUBSET: + { + ret = lttng_dynamic_buffer_append(&payload->buffer, + query->pid_array.buffer.data, + query->pid_array.buffer.size); + if (ret) { + goto end; + } + } + case LTTNG_MAP_QUERY_CONFIG_BUFFER_UST_UID_SUBSET: + { + ret = lttng_dynamic_buffer_append(&payload->buffer, + query->uid_array.buffer.data, + query->uid_array.buffer.size); + if (ret) { + goto end; + } + } + default: + break; + } + +end: + return ret; +} + +void lttng_map_query_destroy(struct lttng_map_query *query) +{ + assert(query); + + if (query->config_cpu == LTTNG_MAP_QUERY_CONFIG_CPU_SUBSET) { + lttng_dynamic_array_reset(&query->cpu_array); + } + + switch(query->config_buffer) { + case LTTNG_MAP_QUERY_CONFIG_BUFFER_UST_UID_SUBSET: + lttng_dynamic_array_reset(&query->uid_array); + break; + case LTTNG_MAP_QUERY_CONFIG_BUFFER_UST_PID_SUBSET: + lttng_dynamic_array_reset(&query->pid_array); + break; + default: + break; + } + free(query->key_filter); + free(query); +}