Introduce extension points for trace hit counters
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Mon, 15 Jul 2024 21:41:32 +0000 (17:41 -0400)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Fri, 26 Jul 2024 20:07:06 +0000 (16:07 -0400)
Introduce two extension points for trace hit counters:

1) Future "actions" to perform other than "increment",

2) Future dimension indexing schemes (keys) other than tokens.

Ensure the LTTng-UST protocol with session daemon has those extension
points so we don't need to break ABI when we need to extend trace hit
counters with those features.

Also ensure the ABI between the tracepoint probe provider and the
tracer passes all the relevant context for future features, e.g.
tracepoint arguments and contexts.

Change the layout of struct lttng_ust_abi_counter_key_dimension
by adding a "key_type" field. A new struct lttng_ust_abi_counter_key_dimension_tokens
inherits from struct lttng_ust_abi_counter_key_dimension, and contains
the uint32_t nr_key_tokens field. The only currently supported key_type
is LTTNG_UST_ABI_KEY_TYPE_TOKENS = 0.

Change the layout of struct lttng_ust_abi_counter_event by adding an
"action" field. The only currently supported action is
LTTNG_UST_ABI_COUNTER_ACTION_INCREMENT = 0.

Change the struct lttng_ust_abi_key_token_string so it inherits from
struct lttng_ust_abi_key_token. The "len" field of
struct lttng_ust_abi_key_token now includes the length of the entire
child structure.

Change the newly introduced ABI between probe providers to change the
"event_counter_add" callback into a "counter_hit" callback, which takes
one less argument (no integer value), but takes additional stack_data,
probe_ctx, and event_counter_ctx arguments for future use.

Introduce a new LTTNG_UST_CTL_NOTIFY_CMD_KEY notification command to
separate key notifications from event notifications, given that they
require different arguments.

Revert back the register event notification to return a 32-bit event ID:
there is no point in changing the pre-existing protocol for event
registration now that key registration gets its own protocol commands.

Note that the protocol major is left at 10 even though we revert the
event ID change, because the protocol was bumped to 10 due to a
different change:

commit f63969cc383c ("dynamic-type: remove underscore prefix from mapping names")

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Change-Id: I0ed00dacfdaf333ffad406f8d017ee21bcbc212b

12 files changed:
include/lttng/ust-abi.h
include/lttng/ust-ctl.h
include/lttng/ust-events.h
include/lttng/ust-tracepoint-event.h
src/common/counter-clients/percpu-32-modular.c
src/common/counter-clients/percpu-64-modular.c
src/common/events.h
src/common/ustcomm.c
src/common/ustcomm.h
src/lib/lttng-ust-ctl/ustctl.c
src/lib/lttng-ust/lttng-events.c
src/lib/lttng-ust/lttng-ust-abi.c

index 7db52c4e2222d4062cf4d804de41e634ee3536a1..7cda357d073d454ab59cbe34e15b96e9896ea441 100644 (file)
@@ -125,32 +125,80 @@ enum lttng_ust_abi_counter_bitness {
        LTTNG_UST_ABI_COUNTER_BITNESS_64 = 1,
 };
 
-struct lttng_ust_abi_counter_key_string {
-       uint32_t string_len;            /* string length (includes \0) */
-       char str[];                     /* Null-terminated string. */
+struct lttng_ust_abi_key_token {
+       uint32_t len;                           /* length of child structure. */
+       uint32_t type;                          /* enum lttng_ust_abi_key_token_type */
+       /*
+        * The size of this structure is fixed because it is embedded into
+        * children structures.
+        */
 } __attribute__((packed));
 
-struct lttng_ust_abi_key_token {
-       uint32_t len;                           /* length of this structure. */
-       uint32_t type;                          /* enum lttng_ust_key_token_type */
+/* Length of this structure excludes the following string. */
+struct lttng_ust_abi_key_token_string {
+       struct lttng_ust_abi_key_token parent;
+       uint32_t string_len;            /* string length (includes \0) */
 
-       /* Followed by a struct lttng_ust_abi_counter_key_string for LTTNG_UST_ABI_KEY_TOKEN_STRING. */
+       char str[];                     /* Null-terminated string following this structure. */
 } __attribute__((packed));
 
+/*
+ * token types event_name and provider_name don't have specific fields,
+ * so they do not need to derive their own specific child structure.
+ */
+
+/*
+ * Dimension indexing: All events should use the same key type to index
+ * a given map dimension.
+ */
+enum lttng_ust_abi_key_type {
+       LTTNG_UST_ABI_KEY_TYPE_TOKENS = 0,              /* Dimension key is a set of tokens. */
+       LTTNG_UST_ABI_KEY_TYPE_INTEGER = 1,             /* Dimension key is an integer value. */
+};
+
 struct lttng_ust_abi_counter_key_dimension {
-       uint32_t len;                           /* length of this structure */
+       uint32_t len;                           /* length of child structure */
+       uint32_t key_type;                      /* enum lttng_ust_abi_key_type */
+       /*
+        * The size of this structure is fixed because it is embedded into
+        * children structures.
+        */
+} __attribute__((packed));
+
+struct lttng_ust_abi_counter_key_dimension_tokens {
+       struct lttng_ust_abi_counter_key_dimension parent;
        uint32_t nr_key_tokens;
 
-       /* Followed by a variable-length array of key tokens */
+       /* Followed by an array of nr_key_tokens struct lttng_ust_abi_key_token elements. */
 } __attribute__((packed));
 
+/*
+ * The "integer" key type is not implemented yet, but when it will be
+ * introduced in the future, its specific key dimension will allow
+ * defining the function to apply over input argument, bytecode to run
+ * and so on.
+ */
+
+enum lttng_ust_abi_counter_action {
+       LTTNG_UST_ABI_COUNTER_ACTION_INCREMENT = 0,
+
+       /*
+        * Can be extended with additional actions, such as decrement,
+        * set value, run bytecode, and so on.
+        */
+};
+
 struct lttng_ust_abi_counter_event {
        uint32_t len;                           /* length of this structure */
+       uint32_t action;                        /* enum lttng_ust_abi_counter_action */
 
        struct lttng_ust_abi_event event;
        uint32_t number_key_dimensions;         /* array of dimensions is an array of var. len. elements. */
 
-       /* Followed by a variable-length array of key dimensions */
+       /*
+        * Followed by additional data specific to the action, and by a
+        * variable-length array of key dimensions.
+        */
 } __attribute__((packed));
 
 enum lttng_ust_abi_counter_dimension_flags {
@@ -159,6 +207,7 @@ enum lttng_ust_abi_counter_dimension_flags {
 };
 
 struct lttng_ust_abi_counter_dimension {
+       uint32_t key_type;                      /* enum lttng_ust_abi_key_type */
        uint32_t flags;                         /* enum lttng_ust_abi_counter_dimension_flags */
        uint64_t size;                          /* dimension size */
        uint64_t underflow_index;
index 3c197394c3d49c2c5164ba6c6d1cc144aa605095..0bae1eac68affcdd8c7b58b801d10b06716736c1 100644 (file)
@@ -312,6 +312,7 @@ enum lttng_ust_ctl_notify_cmd {
        LTTNG_UST_CTL_NOTIFY_CMD_EVENT = 0,
        LTTNG_UST_CTL_NOTIFY_CMD_CHANNEL = 1,
        LTTNG_UST_CTL_NOTIFY_CMD_ENUM = 2,
+       LTTNG_UST_CTL_NOTIFY_CMD_KEY = 3,
 };
 
 enum lttng_ust_ctl_channel_header {
@@ -543,7 +544,42 @@ int lttng_ust_ctl_recv_register_event(int sock,
  * Returns 0 on success, negative error value on error.
  */
 int lttng_ust_ctl_reply_register_event(int sock,
-       uint64_t id,                    /* id (input) */
+       uint32_t id,                    /* id (input) */
+       int ret_code);                  /* return code. 0 ok, negative error */
+
+/*
+ * Returns 0 on success, negative UST or system error value on error.
+ */
+int lttng_ust_ctl_recv_register_key(int sock,
+       int *session_objd,              /* session descriptor (output) */
+       int *map_objd,                  /* map descriptor (output) */
+       uint32_t *dimension,            /*
+                                        * Against which dimension is
+                                        * this key expressed. (output)
+                                        */
+       uint64_t **dimension_indexes,   /*
+                                        * Indexes (output,
+                                        * dynamically
+                                        * allocated, must be
+                                        * free(3)'d by the
+                                        * caller if function
+                                        * returns success.)
+                                        * Contains @dimension
+                                        * elements.
+                                        */
+       char **key_string,              /*
+                                        * key string (output,
+                                        * dynamically allocated, must
+                                        * be free(3)'d by the caller if
+                                        * function returns success.)
+                                        */
+       uint64_t *user_token);
+
+/*
+ * Returns 0 on success, negative error value on error.
+ */
+int lttng_ust_ctl_reply_register_key(int sock,
+       uint64_t index,                 /* Index within dimension (input) */
        int ret_code);                  /* return code. 0 ok, negative error */
 
 /*
@@ -593,6 +629,11 @@ enum lttng_ust_ctl_counter_arithmetic {
        LTTNG_UST_CTL_COUNTER_ARITHMETIC_SATURATION     = 1,
 };
 
+enum lttng_ust_ctl_key_type {
+       LTTNG_UST_CTL_KEY_TYPE_TOKENS = 0,
+       LTTNG_UST_CTL_KEY_TYPE_INTEGER = 1,
+};
+
 /* Used as alloc flags. */
 enum lttng_ust_ctl_counter_alloc {
        LTTNG_UST_CTL_COUNTER_ALLOC_PER_CPU = (1 << 0),
@@ -607,6 +648,7 @@ struct lttng_ust_ctl_counter_dimension {
        uint64_t size;
        uint64_t underflow_index;
        uint64_t overflow_index;
+       enum lttng_ust_ctl_key_type key_type;
        uint8_t has_underflow;
        uint8_t has_overflow;
 };
index 36304bc4e9f2022f0767400cf8b080b4414a3e64..1058145998d62a7de6dfc032d3219de81b220ad6 100644 (file)
@@ -433,6 +433,22 @@ struct lttng_ust_event_recorder {
 
 struct lttng_ust_event_counter_private;
 
+/*
+ * IMPORTANT: this structure is part of the ABI between the probe and
+ * UST. Fields need to be only added at the end, never reordered, never
+ * removed.
+ *
+ * The field @struct_size should be used to determine the size of the
+ * structure. It should be queried before using additional fields added
+ * at the end of the structure.
+ */
+struct lttng_ust_event_counter_ctx {
+       uint32_t struct_size;           /* Size of this structure. */
+       int args_available;             /* Input arguments are available. */
+
+       /* End of base ABI. Fields below should be used after checking struct_size. */
+};
+
 /*
  * IMPORTANT: this structure is part of the ABI between the probe and
  * UST. Fields need to be only added at the end, never reordered, never
@@ -455,6 +471,8 @@ struct lttng_ust_event_counter {
 
        struct lttng_ust_channel_counter *chan;
 
+       int use_args;                                   /* Use input arguments. */
+
        /* End of base ABI. Fields below should be used after checking struct_size. */
 };
 
@@ -602,7 +620,10 @@ struct lttng_ust_channel_counter_ops {
 
        struct lttng_ust_channel_counter_ops_private *priv;     /* Private channel counter ops interface */
 
-       int (*event_counter_add)(struct lttng_ust_event_counter *event_counter, int64_t v);
+       int (*counter_hit)(struct lttng_ust_event_counter *event_counter,
+               const char *stack_data,
+               struct lttng_ust_probe_ctx *probe_ctx,
+               struct lttng_ust_event_counter_ctx *event_counter_ctx);
 
        /* End of base ABI. Fields below should be used after checking struct_size. */
 };
index 1a7ea7448641933c993a8fd6cbf92b6f0fb5047e..5cc69d85c532d85ba5a878038815031d2806037e 100644 (file)
@@ -1049,8 +1049,19 @@ void lttng_ust__event_probe__##_provider##___##_name(LTTNG_UST__TP_ARGS_DATA_PRO
        case LTTNG_UST_EVENT_TYPE_COUNTER:                                    \
        {                                                                     \
                struct lttng_ust_event_counter *__event_counter = (struct lttng_ust_event_counter *) __event->child; \
+               struct lttng_ust_event_counter_ctx __event_counter_ctx;       \
                                                                              \
-               (void) __event_counter->chan->ops->event_counter_add(__event_counter, 1); \
+               __event_counter_ctx.struct_size = sizeof(struct lttng_ust_event_counter_ctx); \
+               __event_counter_ctx.args_available = CMM_ACCESS_ONCE(__event_counter->use_args); \
+                                                                             \
+               if (caa_unlikely(!__interpreter_stack_prepared && __event_counter_ctx.args_available)) \
+                       lttng_ust__event_prepare_interpreter_stack__##_provider##___##_name(__stackvar.__interpreter_stack_data, \
+                               LTTNG_UST__TP_ARGS_DATA_VAR(_args));          \
+                                                                             \
+               (void) __event_counter->chan->ops->counter_hit(__event_counter, \
+                               __stackvar.__interpreter_stack_data,          \
+                               &__probe_ctx,                                 \
+                               &__event_counter_ctx);                        \
                break;                                                        \
        }                                                                     \
        }                                                                     \
index 8675dc3d1837bd22c0d9d2fb96639e31c268cee9..38a5a4f115f2225f5d5b1e07b14dfb4e5cda5aaa 100644 (file)
@@ -49,6 +49,8 @@ static struct lttng_ust_channel_counter *counter_create(size_t nr_dimensions,
        if (!counter)
                goto error;
        lttng_chan_counter->priv->counter = counter;
+       for (i = 0; i < nr_dimensions; i++)
+               lttng_chan_counter->priv->dimension_key_types[i] = dimensions[i].key_type;
        return lttng_chan_counter;
 
 error:
@@ -68,12 +70,22 @@ static int counter_add(struct lttng_ust_channel_counter *counter,
        return lttng_counter_add(&client_config, counter->priv->counter, dimension_indexes, v);
 }
 
-static int event_counter_add(struct lttng_ust_event_counter *event_counter, int64_t v)
+static int counter_hit(struct lttng_ust_event_counter *event_counter,
+               const char *stack_data __attribute__((unused)),
+               struct lttng_ust_probe_ctx *probe_ctx __attribute__((unused)),
+               struct lttng_ust_event_counter_ctx *event_counter_ctx __attribute__((unused)))
 {
        struct lttng_ust_channel_counter *counter = event_counter->chan;
-       size_t index = event_counter->priv->parent.id;
 
-       return counter_add(counter, &index, v);
+       switch (event_counter->priv->action) {
+       case LTTNG_EVENT_COUNTER_ACTION_INCREMENT:
+       {
+               size_t index = event_counter->priv->parent.id;
+               return counter_add(counter, &index, 1);
+       }
+       default:
+               return -ENOSYS;
+       }
 }
 
 static int counter_read(struct lttng_ust_channel_counter *counter, const size_t *dimension_indexes, int cpu,
@@ -108,7 +120,7 @@ static struct lttng_counter_transport lttng_counter_transport = {
                        .counter_aggregate = counter_aggregate,
                        .counter_clear = counter_clear,
                }),
-               .event_counter_add = event_counter_add,
+               .counter_hit = counter_hit,
        },
        .client_config = &client_config,
 };
index c73f8d99ffca2c372a02bb4d187754bad3bdb5c4..20bf4bc11a46d478c537cf96286972f75547881f 100644 (file)
@@ -49,6 +49,8 @@ static struct lttng_ust_channel_counter *counter_create(size_t nr_dimensions,
        if (!counter)
                goto error;
        lttng_chan_counter->priv->counter = counter;
+       for (i = 0; i < nr_dimensions; i++)
+               lttng_chan_counter->priv->dimension_key_types[i] = dimensions[i].key_type;
        return lttng_chan_counter;
 
 error:
@@ -68,12 +70,22 @@ static int counter_add(struct lttng_ust_channel_counter *counter,
        return lttng_counter_add(&client_config, counter->priv->counter, dimension_indexes, v);
 }
 
-static int event_counter_add(struct lttng_ust_event_counter *event_counter, int64_t v)
+static int counter_hit(struct lttng_ust_event_counter *event_counter,
+               const char *stack_data __attribute__((unused)),
+               struct lttng_ust_probe_ctx *probe_ctx __attribute__((unused)),
+               struct lttng_ust_event_counter_ctx *event_counter_ctx __attribute__((unused)))
 {
        struct lttng_ust_channel_counter *counter = event_counter->chan;
-       size_t index = event_counter->priv->parent.id;
 
-       return counter_add(counter, &index, v);
+       switch (event_counter->priv->action) {
+       case LTTNG_EVENT_COUNTER_ACTION_INCREMENT:
+       {
+               size_t index = event_counter->priv->parent.id;
+               return counter_add(counter, &index, 1);
+       }
+       default:
+               return -ENOSYS;
+       }
 }
 
 static int counter_read(struct lttng_ust_channel_counter *counter, const size_t *dimension_indexes, int cpu,
@@ -108,7 +120,7 @@ static struct lttng_counter_transport lttng_counter_transport = {
                        .counter_aggregate = counter_aggregate,
                        .counter_clear = counter_clear,
                }),
-               .event_counter_add = event_counter_add,
+               .counter_hit = counter_hit,
        },
        .client_config = &client_config,
 };
index 2ac7a44e4652e64988e2fe0c920ea93a4f988a78..d53a587b2aaf6dea0428fb6ec14dd498ae40cbac 100644 (file)
@@ -86,10 +86,21 @@ struct lttng_key_token {
        } arg;
 };
 
+enum lttng_key_type {
+       LTTNG_KEY_TYPE_TOKENS = 0,
+       LTTNG_KEY_TYPE_INTEGER = 1,
+};
+
 #define LTTNG_NR_KEY_TOKEN 8
 struct lttng_counter_key_dimension {
-       size_t nr_key_tokens;
-       struct lttng_key_token key_tokens[LTTNG_NR_KEY_TOKEN];
+       enum lttng_key_type key_type;
+
+       union {
+               struct {
+                       size_t nr_key_tokens;
+                       struct lttng_key_token key_tokens[LTTNG_NR_KEY_TOKEN];
+               } tokens;
+       } u;
 };
 
 #define LTTNG_COUNTER_DIMENSION_MAX 4
@@ -102,6 +113,7 @@ struct lttng_counter_dimension {
        uint64_t size;
        uint64_t underflow_index;
        uint64_t overflow_index;
+       enum lttng_key_type key_type;
        uint8_t has_underflow;
        uint8_t has_overflow;
 };
@@ -143,10 +155,16 @@ struct lttng_event_recorder_enabler {
        struct lttng_ust_channel_buffer *chan;
 };
 
+enum lttng_event_counter_action {
+       LTTNG_EVENT_COUNTER_ACTION_INCREMENT = 0,
+};
+
 struct lttng_event_counter_enabler {
        struct lttng_event_enabler_session_common parent;
        struct lttng_ust_channel_counter *chan;
        struct lttng_counter_key key;
+
+       enum lttng_event_counter_action action;
 };
 
 struct lttng_event_notifier_enabler {
@@ -322,6 +340,7 @@ struct lttng_ust_event_counter_private {
        struct lttng_ust_event_session_common_private parent;
 
        struct lttng_ust_event_counter *pub;    /* Public event interface */
+       enum lttng_event_counter_action action;
        char key[LTTNG_KEY_TOKEN_STRING_LEN_MAX];
 };
 
@@ -471,6 +490,7 @@ struct lttng_ust_channel_counter_private {
        struct lttng_session *session;
        struct cds_list_head node;                      /* Counter list (in session) */
        size_t free_index;                              /* Next index to allocate */
+       enum lttng_key_type dimension_key_types[LTTNG_COUNTER_DIMENSION_MAX];
 };
 
 /*
index 1cf368b8fdfbebd7a39d5abb918e9e0f421d10b0..7bec2048a4dfeea784698c1254d9ef160cf02984 100644 (file)
@@ -1370,7 +1370,7 @@ int ustcomm_register_event(int sock,
        const struct lttng_ust_event_field * const *lttng_fields,
        const char *model_emf_uri,
        uint64_t user_token,
-       uint64_t *id)                   /* event id (output) */
+       uint32_t *id)                   /* event id (output) */
 {
        ssize_t len;
        struct {
@@ -1478,7 +1478,7 @@ int ustcomm_register_event(int sock,
                if (reply.r.ret_code < 0)
                        return reply.r.ret_code;
                *id = reply.r.id;
-               DBG("Sent register event notification for name \"%s\": ret_code %d, id %" PRIu64 "\n",
+               DBG("Sent register event notification for name \"%s\": ret_code %d, id %" PRIu32 "\n",
                        event_name, reply.r.ret_code, reply.r.id);
                return 0;
        default:
@@ -1500,6 +1500,113 @@ error_fields:
        return ret;
 }
 
+/*
+ * Returns 0 on success, negative error value on error.
+ * Returns -EPIPE or -ECONNRESET if other end has hung up.
+ */
+int ustcomm_register_key(int sock,
+       int session_objd,               /* session descriptor */
+       int map_objd,                   /* map descriptor */
+       uint32_t dimension,
+       const uint64_t *dimension_indexes,
+       const char *key_string,         /* key string (input) */
+       uint64_t user_token,
+       uint64_t *index)                /* (output) */
+{
+       ssize_t len;
+       struct {
+               struct ustcomm_notify_hdr header;
+               struct ustcomm_notify_key_msg m;
+       } msg;
+       struct {
+               struct ustcomm_notify_hdr header;
+               struct ustcomm_notify_key_reply r;
+       } reply;
+       size_t dimension_indexes_len;
+       int ret;
+
+       memset(&msg, 0, sizeof(msg));
+       msg.header.notify_cmd = LTTNG_UST_CTL_NOTIFY_CMD_KEY;
+       msg.m.session_objd = session_objd;
+       msg.m.map_objd = map_objd;
+       msg.m.dimension = dimension;
+       dimension_indexes_len = sizeof(uint64_t) * dimension;
+       msg.m.key_string_len = strlen(key_string) + 1;
+       msg.m.user_token = user_token;
+
+       len = ustcomm_send_unix_sock(sock, &msg, sizeof(msg));
+       if (len > 0 && len != sizeof(msg)) {
+               ret = -EIO;
+               goto error_send;
+       }
+       if (len < 0) {
+               ret = len;
+               goto error_send;
+       }
+
+       /* send dimension_indexes */
+       if (dimension_indexes) {
+               len = ustcomm_send_unix_sock(sock, dimension_indexes, dimension_indexes_len);
+               if (len > 0 && len != dimension_indexes_len) {
+                       ret = -EIO;
+                       goto error_dimension_indexes;
+               }
+               if (len < 0) {
+                       ret = len;
+                       goto error_dimension_indexes;
+               }
+       }
+
+       /* send key_string */
+       len = ustcomm_send_unix_sock(sock, key_string, msg.m.key_string_len);
+       if (len > 0 && len != dimension_indexes_len) {
+               ret = -EIO;
+               goto error_dimension_indexes;
+       }
+       if (len < 0) {
+               ret = len;
+               goto error_dimension_indexes;
+       }
+
+       /* receive reply */
+       len = ustcomm_recv_unix_sock(sock, &reply, sizeof(reply));
+       switch (len) {
+       case 0: /* orderly shutdown */
+               return -EPIPE;
+       case sizeof(reply):
+               if (reply.header.notify_cmd != msg.header.notify_cmd) {
+                       ERR("Unexpected result message command "
+                               "expected: %u vs received: %u\n",
+                               msg.header.notify_cmd, reply.header.notify_cmd);
+                       return -EINVAL;
+               }
+               if (reply.r.ret_code > 0)
+                       return -EINVAL;
+               if (reply.r.ret_code < 0)
+                       return reply.r.ret_code;
+               *index = reply.r.index;
+               DBG("Sent register key notification for key \"%s\": ret_code %d, index %" PRIu64 "\n",
+                       key_string, reply.r.ret_code, reply.r.index);
+               return 0;
+       default:
+               if (len < 0) {
+                       /* Transport level error */
+                       if (errno == EPIPE || errno == ECONNRESET)
+                               len = -errno;
+                       return len;
+               } else {
+                       ERR("incorrect message size: %zd\n", len);
+                       return len;
+               }
+       }
+       /* Unreached. */
+
+       /* Error path only. */
+error_dimension_indexes:
+error_send:
+       return ret;
+}
+
 /*
  * Returns 0 on success, negative error value on error.
  * Returns -EPIPE or -ECONNRESET if other end has hung up.
index 6b5553919fb1132d662ca24ae20555a81fc87974..7ecb365be78f16b853f763755f6e6b5c91ad6d57 100644 (file)
@@ -144,16 +144,31 @@ struct ustcomm_notify_event_msg {
        /* followed by signature, fields, and model_emf_uri */
 } __attribute__((packed));
 
-#define USTCOMM_NOTIFY_EVENT_REPLY_PADDING     24
+#define USTCOMM_NOTIFY_EVENT_REPLY_PADDING     32
 struct ustcomm_notify_event_reply {
        int32_t ret_code;       /* 0: ok, negative: error code */
-
-       /* 32-bit (lower bits) event id for backward compatibility with ABI major < 10 */
-       uint32_t old_event_id;  /* TODO: remove field on future protocol compatibility break. */
-       uint64_t id;            /* 64-bit event id.  */
+       uint32_t id;    /* 32-bit event id. */
        char padding[USTCOMM_NOTIFY_EVENT_REPLY_PADDING];
 } __attribute__((packed));
 
+#define USTCOMM_NOTIFY_KEY_MSG_PADDING 24
+struct ustcomm_notify_key_msg {
+       uint32_t session_objd;
+       uint32_t map_objd;
+       uint32_t dimension;
+       uint32_t key_string_len;
+       uint64_t user_token;
+       char padding[USTCOMM_NOTIFY_KEY_MSG_PADDING];
+       /* followed by dimension_indexes (array of @dimension uint64_t items) and key_string. */
+} __attribute__((packed));
+
+#define USTCOMM_NOTIFY_KEY_REPLY_PADDING       32
+struct ustcomm_notify_key_reply {
+       int32_t ret_code;       /* 0: ok, negative: error code */
+       uint64_t index;         /* 64-bit key index. */
+       char padding[USTCOMM_NOTIFY_KEY_REPLY_PADDING];
+} __attribute__((packed));
+
 #define USTCOMM_NOTIFY_ENUM_MSG_PADDING                32
 struct ustcomm_notify_enum_msg {
        uint32_t session_objd;
@@ -292,7 +307,21 @@ int ustcomm_register_event(int sock,
        const struct lttng_ust_event_field * const *fields,
        const char *model_emf_uri,
        uint64_t user_token,
-       uint64_t *id)                   /* (output) */
+       uint32_t *id)                   /* (output) */
+       __attribute__((visibility("hidden")));
+
+/*
+ * Returns 0 on success, negative error value on error.
+ * Returns -EPIPE or -ECONNRESET if other end has hung up.
+ */
+int ustcomm_register_key(int sock,
+       int session_objd,               /* session descriptor */
+       int map_objd,                   /* map descriptor */
+       uint32_t dimension,
+       const uint64_t *dimension_indexes,
+       const char *key_string,         /* key string (input) */
+       uint64_t user_token,
+       uint64_t *index)                /* (output) */
        __attribute__((visibility("hidden")));
 
 /*
index bf8c137386621ad11338ce4cbaa52cdd24b65057..92e524646f773f266cf6cafbda5168e01def4b63 100644 (file)
@@ -2548,6 +2548,9 @@ int lttng_ust_ctl_recv_notify(int sock, enum lttng_ust_ctl_notify_cmd *notify_cm
        case 2:
                *notify_cmd = LTTNG_UST_CTL_NOTIFY_CMD_ENUM;
                break;
+       case 3:
+               *notify_cmd = LTTNG_UST_CTL_NOTIFY_CMD_KEY;
+               break;
        default:
                return -EINVAL;
        }
@@ -2681,7 +2684,7 @@ signature_error:
  * Returns 0 on success, negative error value on error.
  */
 int lttng_ust_ctl_reply_register_event(int sock,
-       uint64_t id,
+       uint32_t id,
        int ret_code)
 {
        ssize_t len;
@@ -2693,7 +2696,6 @@ int lttng_ust_ctl_reply_register_event(int sock,
        memset(&reply, 0, sizeof(reply));
        reply.header.notify_cmd = LTTNG_UST_CTL_NOTIFY_CMD_EVENT;
        reply.r.ret_code = ret_code;
-       reply.r.old_event_id = (uint32_t) id;   /* For backward compatibility */
        reply.r.id = id;
        len = ustcomm_send_unix_sock(sock, &reply, sizeof(reply));
        if (len > 0 && len != sizeof(reply))
@@ -2703,6 +2705,134 @@ int lttng_ust_ctl_reply_register_event(int sock,
        return 0;
 }
 
+/*
+ * Returns 0 on success, negative UST or system error value on error.
+ */
+int lttng_ust_ctl_recv_register_key(int sock,
+       int *session_objd,              /* session descriptor (output) */
+       int *map_objd,                  /* map descriptor (output) */
+       uint32_t *dimension,            /*
+                                        * Against which dimension is
+                                        * this key expressed. (output)
+                                        */
+       uint64_t **dimension_indexes,   /*
+                                        * Indexes (output,
+                                        * dynamically
+                                        * allocated, must be
+                                        * free(3)'d by the
+                                        * caller if function
+                                        * returns success.)
+                                        * Contains @dimension
+                                        * elements.
+                                        */
+       char **key_string,              /*
+                                        * key string (output,
+                                        * dynamically allocated, must
+                                        * be free(3)'d by the caller if
+                                        * function returns success.)
+                                        */
+       uint64_t *user_token)
+{
+       ssize_t len;
+       struct ustcomm_notify_key_msg msg;
+       size_t dimension_indexes_len, key_string_len;
+       uint64_t *a_dimension_indexes = NULL;
+       char *a_key_string = NULL;
+
+       len = ustcomm_recv_unix_sock(sock, &msg, sizeof(msg));
+       if (len > 0 && len != sizeof(msg))
+               return -EIO;
+       if (len == 0)
+               return -EPIPE;
+       if (len < 0)
+               return len;
+
+       *session_objd = msg.session_objd;
+       *map_objd = msg.map_objd;
+       *dimension = msg.dimension;
+       dimension_indexes_len = msg.dimension * sizeof(uint64_t);
+       key_string_len = msg.key_string_len;
+       *user_token = msg.user_token;
+
+       if (dimension_indexes_len) {
+               /* recv dimension_indexes */
+               a_dimension_indexes = zmalloc(dimension_indexes_len);
+               if (!a_dimension_indexes) {
+                       len = -ENOMEM;
+                       goto error;
+               }
+               len = ustcomm_recv_unix_sock(sock, a_dimension_indexes, dimension_indexes_len);
+               if (len > 0 && len != dimension_indexes_len) {
+                       len = -EIO;
+                       goto error;
+               }
+               if (len == 0) {
+                       len = -EPIPE;
+                       goto error;
+               }
+               if (len < 0) {
+                       goto error;
+               }
+       }
+
+       if (key_string_len) {
+               /* recv key_string */
+               a_key_string = zmalloc(key_string_len);
+               if (!a_key_string) {
+                       len = -ENOMEM;
+                       goto error;
+               }
+               len = ustcomm_recv_unix_sock(sock, a_key_string, key_string_len);
+               if (len > 0 && len != key_string_len) {
+                       len = -EIO;
+                       goto error;
+               }
+               if (len == 0) {
+                       len = -EPIPE;
+                       goto error;
+               }
+               if (len < 0) {
+                       goto error;
+               }
+               /* Enforce end of string */
+               a_key_string[key_string_len - 1] = '\0';
+       }
+
+       *dimension_indexes = a_dimension_indexes;
+       *key_string = a_key_string;
+       return 0;
+
+error:
+       free(a_key_string);
+       free(a_dimension_indexes);
+       return len;
+}
+
+/*
+ * Returns 0 on success, negative error value on error.
+ */
+int lttng_ust_ctl_reply_register_key(int sock,
+       uint64_t index,                 /* Index within dimension (input) */
+       int ret_code)                   /* return code. 0 ok, negative error */
+{
+       ssize_t len;
+       struct {
+               struct ustcomm_notify_hdr header;
+               struct ustcomm_notify_key_reply r;
+       } reply;
+
+       memset(&reply, 0, sizeof(reply));
+       reply.header.notify_cmd = LTTNG_UST_CTL_NOTIFY_CMD_KEY;
+       reply.r.ret_code = ret_code;
+       reply.r.index = index;
+       len = ustcomm_send_unix_sock(sock, &reply, sizeof(reply));
+       if (len > 0 && len != sizeof(reply))
+               return -EIO;
+       if (len < 0)
+               return len;
+       return 0;
+}
+
 /*
  * Returns 0 on success, negative UST or system error value on error.
  */
@@ -2996,6 +3126,14 @@ struct lttng_ust_ctl_daemon_counter *
                ust_dim[i].overflow_index = dimensions[i].overflow_index;
                ust_dim[i].has_underflow = dimensions[i].has_underflow;
                ust_dim[i].has_overflow = dimensions[i].has_overflow;
+               switch (dimensions[i].key_type) {
+               case LTTNG_UST_CTL_KEY_TYPE_TOKENS:
+                       ust_dim[i].key_type = LTTNG_KEY_TYPE_TOKENS;
+                       break;
+               case LTTNG_UST_CTL_KEY_TYPE_INTEGER:    /* Fall-through */
+               default:
+                       goto free_attr;
+               }
        }
        counter->counter = transport->ops.priv->counter_create(nr_dimensions,
                ust_dim, global_sum_step, global_counter_fd,
@@ -3065,6 +3203,15 @@ int lttng_ust_ctl_create_counter_data(struct lttng_ust_ctl_daemon_counter *count
        dimension->size = counter->attr->dimensions[0].size;
        dimension->underflow_index = counter->attr->dimensions[0].underflow_index;
        dimension->overflow_index = counter->attr->dimensions[0].overflow_index;
+       switch (counter->attr->dimensions[0].key_type) {
+       case LTTNG_UST_CTL_KEY_TYPE_TOKENS:
+               dimension->key_type = LTTNG_UST_ABI_KEY_TYPE_TOKENS;
+               break;
+       case LTTNG_UST_CTL_KEY_TYPE_INTEGER:    /* Fall-through */
+       default:
+               ret = -EINVAL;
+               goto error;
+       }
 
        counter_data = zmalloc(sizeof(*counter_data));
        if (!counter_data) {
@@ -3180,6 +3327,8 @@ int lttng_ust_ctl_send_old_counter_data_to_ust(int sock, int parent_handle,
        old_counter_conf.dimensions[0].has_overflow = (dimension->flags & LTTNG_UST_ABI_COUNTER_DIMENSION_FLAG_OVERFLOW) ? 1 : 0;
        old_counter_conf.dimensions[0].underflow_index = dimension->underflow_index;
        old_counter_conf.dimensions[0].overflow_index = dimension->overflow_index;
+       if (dimension->key_type != LTTNG_UST_ABI_KEY_TYPE_TOKENS)
+               return -EINVAL;
 
        size = sizeof(old_counter_conf);
        lum.handle = parent_handle;
index 88094fd79fc1554bd34cbba08a41d982e2c19b24..2839d0c06de3586a73885feff444960fc74296cb 100644 (file)
@@ -742,8 +742,11 @@ int format_event_key(struct lttng_event_enabler_common *event_enabler, char *key
        if (key->nr_dimensions != 1)
                return -EINVAL;
        dim = &key->key_dimensions[0];
-       for (i = 0; i < dim->nr_key_tokens; i++) {
-               const struct lttng_key_token *token = &dim->key_tokens[i];
+       /* Currently only tokens keys are supported. */
+       if (dim->key_type != LTTNG_KEY_TYPE_TOKENS)
+               return -EINVAL;
+       for (i = 0; i < dim->u.tokens.nr_key_tokens; i++) {
+               const struct lttng_key_token *token = &dim->u.tokens.key_tokens[i];
                size_t token_len;
                const char *str;
 
@@ -950,6 +953,7 @@ struct lttng_ust_event_common *lttng_ust_event_alloc(struct lttng_event_enabler_
                        event_counter->priv->parent.parent.user_token = event_counter_enabler->parent.parent.user_token;
                event_counter->priv->parent.parent.desc = desc;
                strcpy(event_counter_priv->key, key_string);
+               event_counter_priv->action = event_counter_enabler->action;
                return event_counter->parent;
        }
        default:
@@ -1005,7 +1009,6 @@ int lttng_event_register_to_sessiond(struct lttng_event_enabler_common *event_en
 {
        switch (event_enabler->enabler_type) {
        case LTTNG_EVENT_ENABLER_TYPE_RECORDER:         /* Fall-through */
-       case LTTNG_EVENT_ENABLER_TYPE_COUNTER:
        {
                struct lttng_event_enabler_session_common *event_enabler_session =
                        caa_container_of(event_enabler, struct lttng_event_enabler_session_common, parent);
@@ -1013,8 +1016,9 @@ int lttng_event_register_to_sessiond(struct lttng_event_enabler_common *event_en
                        caa_container_of(event->priv, struct lttng_ust_event_session_common_private, parent);
                struct lttng_ust_session *session = event_enabler_session->chan->session;
                const struct lttng_ust_event_desc *desc = event->priv->desc;
-               int notify_socket, loglevel;
+               int notify_socket, loglevel, ret;
                const char *uri;
+               uint32_t id;
 
                if (desc->loglevel)
                        loglevel = *(*desc->loglevel);
@@ -1030,7 +1034,7 @@ int lttng_event_register_to_sessiond(struct lttng_event_enabler_common *event_en
                        return notify_socket;
 
                /* Fetch event ID from sessiond */
-               return ustcomm_register_event(notify_socket,
+               ret = ustcomm_register_event(notify_socket,
                        session,
                        session->priv->objd,
                        event_enabler_session->chan->priv->objd,
@@ -1041,7 +1045,39 @@ int lttng_event_register_to_sessiond(struct lttng_event_enabler_common *event_en
                        desc->tp_class->fields,
                        uri,
                        event_enabler_session->parent.user_token,
-                       &event_session_priv->id);
+                       &id);
+               if (ret)
+                       return ret;
+               event_session_priv->id = id;
+               return 0;
+       }
+       case LTTNG_EVENT_ENABLER_TYPE_COUNTER:
+       {
+               struct lttng_event_enabler_session_common *event_enabler_session =
+                       caa_container_of(event_enabler, struct lttng_event_enabler_session_common, parent);
+               struct lttng_ust_event_session_common_private *event_session_priv =
+                       caa_container_of(event->priv, struct lttng_ust_event_session_common_private, parent);
+               struct lttng_ust_session *session = event_enabler_session->chan->session;
+               uint64_t dimension_index[LTTNG_COUNTER_DIMENSION_MAX];
+               int notify_socket, ret;
+
+               notify_socket = lttng_get_notify_socket(session->priv->owner);
+               if (notify_socket < 0)
+                       return notify_socket;
+
+               /* Fetch key index from sessiond */
+               ret = ustcomm_register_key(notify_socket,
+                       session->priv->objd,
+                       event_enabler_session->chan->priv->objd,
+                       0,      /* target dimension */
+                       NULL,
+                       name,
+                       event_enabler_session->parent.user_token,
+                       dimension_index);       /* Filled up to target dimension. */
+               if (ret)
+                       return ret;
+               event_session_priv->id = dimension_index[0];
+               return 0;
        }
 
        case LTTNG_EVENT_ENABLER_TYPE_NOTIFIER:
@@ -1697,10 +1733,20 @@ struct lttng_event_counter_enabler *lttng_event_counter_enabler_create(
                struct lttng_ust_channel_counter *chan)
 {
        struct lttng_event_counter_enabler *event_enabler;
+       enum lttng_event_counter_action action;
 
        event_enabler = zmalloc(sizeof(*event_enabler));
        if (!event_enabler)
                return NULL;
+
+       switch (counter_event->action) {
+       case LTTNG_UST_ABI_COUNTER_ACTION_INCREMENT:
+               action = LTTNG_EVENT_COUNTER_ACTION_INCREMENT;
+               break;
+       default:
+               goto error;
+       }
+       event_enabler->action = action;
        event_enabler->parent.parent.enabler_type = LTTNG_EVENT_ENABLER_TYPE_COUNTER;
        event_enabler->parent.parent.format_type = format_type;
        CDS_INIT_LIST_HEAD(&event_enabler->parent.parent.filter_bytecode_head);
@@ -1717,6 +1763,10 @@ struct lttng_event_counter_enabler *lttng_event_counter_enabler_create(
        lttng_session_lazy_sync_event_enablers(event_enabler->chan->parent->session);
 
        return event_enabler;
+
+error:
+       free(event_enabler);
+       return NULL;
 }
 
 struct lttng_event_notifier_enabler *lttng_event_notifier_enabler_create(
index 63e21f21cd3b0f0f1fdf0fdac818aea12a1b65a9..2adb127ee96d07cafba669055c01b3fc9e2e5b0e 100644 (file)
@@ -701,6 +701,14 @@ long lttng_session_create_counter(
        dimensions[0].overflow_index = dimension.overflow_index;
        dimensions[0].has_underflow = dimension.flags & LTTNG_UST_ABI_COUNTER_DIMENSION_FLAG_UNDERFLOW;
        dimensions[0].has_overflow = dimension.flags & LTTNG_UST_ABI_COUNTER_DIMENSION_FLAG_OVERFLOW;
+       switch (dimension.key_type) {
+       case LTTNG_UST_ABI_KEY_TYPE_TOKENS:
+               dimensions[0].key_type = LTTNG_KEY_TYPE_TOKENS;
+               break;
+       case LTTNG_UST_ABI_KEY_TYPE_INTEGER:    /* Fall-through */
+       default:
+               return -EINVAL;
+       }
 
        counter_objd = objd_alloc(NULL, &lttng_counter_ops, owner, "counter");
        if (counter_objd < 0) {
@@ -1374,79 +1382,110 @@ objd_error:
        return ret;
 }
 
+static
+int copy_counter_key_dimension_tokens(const struct lttng_ust_abi_counter_key_dimension_tokens *abi_dim_tokens,
+               const char *addr, size_t *offset, size_t arg_len, struct lttng_counter_key_dimension *internal_dim)
+{
+       struct lttng_ust_abi_counter_key_dimension_tokens dim_tokens;
+       size_t nr_key_tokens, j;
+       int ret;
+
+       if (abi_dim_tokens->parent.len < sizeof(struct lttng_ust_abi_counter_key_dimension_tokens))
+               return -EINVAL;
+       ret = copy_abi_struct(&dim_tokens, sizeof(dim_tokens), abi_dim_tokens, abi_dim_tokens->parent.len);
+       if (ret)
+               return ret;
+       nr_key_tokens = dim_tokens.nr_key_tokens;
+       if (!nr_key_tokens || nr_key_tokens > LTTNG_NR_KEY_TOKEN)
+               return -EINVAL;
+       internal_dim->key_type = LTTNG_KEY_TYPE_TOKENS;
+       internal_dim->u.tokens.nr_key_tokens = nr_key_tokens;
+       *offset += sizeof(struct lttng_ust_abi_counter_key_dimension_tokens);
+       for (j = 0; j < nr_key_tokens; j++) {
+               struct lttng_key_token *internal_token = &internal_dim->u.tokens.key_tokens[j];
+               const struct lttng_ust_abi_key_token *abi_token;
+
+               if (*offset + sizeof(struct lttng_ust_abi_key_token) > arg_len)
+                       return -EINVAL;
+               abi_token = (const struct lttng_ust_abi_key_token *)(addr + *offset);
+               if (abi_token->len < sizeof(struct lttng_ust_abi_key_token))
+                       return -EINVAL;
+               if (*offset + abi_token->len > arg_len)
+                       return -EINVAL;
+               switch (abi_token->type) {
+               case LTTNG_UST_ABI_KEY_TOKEN_STRING:
+               {
+                       const struct lttng_ust_abi_key_token_string *abi_key_string;
+                       struct lttng_ust_abi_key_token_string token_string;
+
+                       if (abi_token->len < sizeof(struct lttng_ust_abi_key_token_string))
+                               return -EINVAL;
+                       abi_key_string = (const struct lttng_ust_abi_key_token_string *)(addr + *offset);
+                       ret = copy_abi_struct(&token_string, sizeof(token_string), abi_key_string, abi_key_string->parent.len);
+                       if (ret)
+                               return ret;
+                       *offset += abi_key_string->parent.len;
+                       internal_token->type = LTTNG_KEY_TOKEN_STRING;
+                       if (!abi_key_string->string_len || abi_key_string->string_len > LTTNG_KEY_TOKEN_STRING_LEN_MAX)
+                               return -EINVAL;
+                       *offset += abi_key_string->string_len;
+                       if (*offset > arg_len)
+                               return -EINVAL;
+                       if (abi_key_string->str[abi_key_string->string_len - 1] != '\0' ||
+                                       strlen(abi_key_string->str) + 1 != abi_key_string->string_len)
+                               return -EINVAL;
+                       memcpy(internal_token->arg.string, abi_key_string->str, abi_key_string->string_len);
+                       break;
+               }
+               case LTTNG_UST_ABI_KEY_TOKEN_EVENT_NAME:
+                       internal_token->type = LTTNG_KEY_TOKEN_EVENT_NAME;
+                       *offset += abi_token->len;
+                       break;
+               case LTTNG_UST_ABI_KEY_TOKEN_PROVIDER_NAME:
+                       internal_token->type = LTTNG_KEY_TOKEN_PROVIDER_NAME;
+                       *offset += abi_token->len;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+       }
+       return 0;
+}
+
 static
 int copy_counter_key(struct lttng_counter_key *internal_key,
-                    unsigned long arg, size_t arg_len,
+                    unsigned long arg, size_t action_fields_len, size_t arg_len,
                     const struct lttng_ust_abi_counter_event *counter_event)
 {
-       size_t i, j, nr_dimensions, offset = 0;
-       char *addr = (char *)arg;
+       size_t i, nr_dimensions, offset = 0;
+       const char *addr = (const char *)arg;
        int ret;
 
        nr_dimensions = counter_event->number_key_dimensions;
        if (nr_dimensions != 1)
                return -EINVAL;
        internal_key->nr_dimensions = nr_dimensions;
-       offset += counter_event->len;
+       offset += counter_event->len + action_fields_len;
        for (i = 0; i < nr_dimensions; i++) {
-               const struct lttng_ust_abi_counter_key_dimension *abi_dim;
-               struct lttng_ust_abi_counter_key_dimension dim;
                struct lttng_counter_key_dimension *internal_dim = &internal_key->key_dimensions[i];
-               size_t nr_key_tokens;
+               const struct lttng_ust_abi_counter_key_dimension *abi_dim;
 
                abi_dim = (const struct lttng_ust_abi_counter_key_dimension *)(addr + offset);
-               offset += abi_dim->len;
-               if (offset > arg_len || abi_dim->len < lttng_ust_offsetofend(struct lttng_ust_abi_counter_key_dimension, nr_key_tokens))
+               if (offset + abi_dim->len > arg_len || abi_dim->len < lttng_ust_offsetofend(struct lttng_ust_abi_counter_key_dimension, key_type))
                        return -EINVAL;
-               ret = copy_abi_struct(&dim, sizeof(dim), abi_dim, abi_dim->len);
-               if (ret)
-                       return ret;
-               nr_key_tokens = dim.nr_key_tokens;
-               if (!nr_key_tokens || nr_key_tokens > LTTNG_NR_KEY_TOKEN)
-                       return -EINVAL;
-               internal_dim->nr_key_tokens = nr_key_tokens;
-               for (j = 0; j < nr_key_tokens; j++) {
-                       const struct lttng_ust_abi_key_token *abi_token;
-                       struct lttng_ust_abi_key_token token;
-                       struct lttng_key_token *internal_token = &internal_dim->key_tokens[j];
-
-                       abi_token = (const struct lttng_ust_abi_key_token *)(addr + offset);
-                       offset += abi_token->len;
-                       if (offset > arg_len || abi_token->len < lttng_ust_offsetofend(struct lttng_ust_abi_key_token, type))
-                               return -EINVAL;
-                       ret = copy_abi_struct(&token, sizeof(token), abi_token, abi_token->len);
+               switch (abi_dim->key_type) {
+               case LTTNG_UST_ABI_KEY_TYPE_TOKENS:
+               {
+                       struct lttng_ust_abi_counter_key_dimension_tokens *dim_tokens =
+                               caa_container_of(abi_dim, struct lttng_ust_abi_counter_key_dimension_tokens, parent);
+                       ret = copy_counter_key_dimension_tokens(dim_tokens, addr, &offset, arg_len,
+                                       internal_dim);
                        if (ret)
                                return ret;
-                       switch (token.type) {
-                       case LTTNG_UST_ABI_KEY_TOKEN_STRING:
-                       {
-                               const struct lttng_ust_abi_counter_key_string *abi_key_string;
-
-                               abi_key_string = (const struct lttng_ust_abi_counter_key_string *)(addr + offset);
-                               offset += sizeof(struct lttng_ust_abi_counter_key_string);
-                               if (offset > arg_len)
-                                       return -EINVAL;
-                               internal_token->type = LTTNG_KEY_TOKEN_STRING;
-                               if (!abi_key_string->string_len || abi_key_string->string_len > LTTNG_KEY_TOKEN_STRING_LEN_MAX)
-                                       return -EINVAL;
-                               offset += abi_key_string->string_len;
-                               if (offset > arg_len)
-                                       return -EINVAL;
-                               if (abi_key_string->str[abi_key_string->string_len - 1] != '\0' ||
-                                               strlen(abi_key_string->str) + 1 != abi_key_string->string_len)
-                                       return -EINVAL;
-                               memcpy(internal_token->arg.string, abi_key_string->str, abi_key_string->string_len);
-                               break;
-                       }
-                       case LTTNG_UST_ABI_KEY_TOKEN_EVENT_NAME:
-                               internal_token->type = LTTNG_KEY_TOKEN_EVENT_NAME;
-                               break;
-                       case LTTNG_UST_ABI_KEY_TOKEN_PROVIDER_NAME:
-                               internal_token->type = LTTNG_KEY_TOKEN_PROVIDER_NAME;
-                               break;
-                       default:
-                               return -EINVAL;
-                       }
+                       break;
+               }
+               default:
+                       return -EINVAL;
                }
        }
        return 0;
@@ -1462,7 +1501,9 @@ int lttng_abi_create_event_counter_enabler(int channel_objd,
        struct lttng_counter_key counter_key = {};
        struct lttng_event_counter_enabler *enabler;
        enum lttng_enabler_format_type format_type;
+       size_t action_fields_len = 0;
        int event_objd, ret;
+       size_t i;
 
        if (arg_len < lttng_ust_offsetofend(struct lttng_ust_abi_counter_event, number_key_dimensions)) {
                return -EINVAL;
@@ -1476,16 +1517,31 @@ int lttng_abi_create_event_counter_enabler(int channel_objd,
        if (ret) {
                return ret;
        }
+       switch (counter_event.action) {
+       case LTTNG_UST_ABI_COUNTER_ACTION_INCREMENT:
+               /* No additional fields specific to this action. */
+               break;
+       default:
+               return -EINVAL;
+       }
        counter_event.event.name[LTTNG_UST_ABI_SYM_NAME_LEN - 1] = '\0';
        if (strutils_is_star_glob_pattern(counter_event.event.name)) {
                format_type = LTTNG_ENABLER_FORMAT_STAR_GLOB;
        } else {
                format_type = LTTNG_ENABLER_FORMAT_EVENT;
        }
-       ret = copy_counter_key(&counter_key, arg, arg_len, &counter_event);
+       ret = copy_counter_key(&counter_key, arg, action_fields_len, arg_len, &counter_event);
        if (ret) {
                return ret;
        }
+       /*
+        * Validate that each dimension counter key type match the map
+        * key type.
+        */
+       for (i = 0; i < counter_key.nr_dimensions; i++) {
+               if (channel->priv->dimension_key_types[i] != counter_key.key_dimensions[i].key_type)
+                       return -EINVAL;
+       }
        event_objd = objd_alloc(NULL, &lttng_event_enabler_ops, owner,
                "event enabler");
        if (event_objd < 0) {
This page took 0.041314 seconds and 4 git commands to generate.