SoW-2020-0003: Trace Hit Counters
[lttng-tools.git] / src / common / map-query.c
diff --git a/src/common/map-query.c b/src/common/map-query.c
new file mode 100644 (file)
index 0000000..d89d6f3
--- /dev/null
@@ -0,0 +1,676 @@
+/*
+ * Copyright (C) 2020 Francis Deslauriers <francis.deslauriers@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <common/error.h>
+#include <common/macros.h>
+#include <common/optional.h>
+#include <common/payload.h>
+
+#include <lttng/map/map-query-internal.h>
+
+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)
+{
+       if (!query) {
+               return;
+       }
+
+       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);
+}
This page took 0.029075 seconds and 5 git commands to generate.