From: Simon Marchi Date: Fri, 29 Nov 2019 21:48:45 +0000 (-0500) Subject: actions: introduce start session action X-Git-Tag: v2.13.0-rc1~626 X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=commitdiff_plain;h=58397d0d83913a52d42e1fe9b9a09f4ebdde8f27;hp=3dd04a6a94950c91b0895e6da9da5f84db1e7abc actions: introduce start session action This patch introduces the API for the "start session" action. A start session action is created using the lttng_action_start_session_create function. It is mandatory to set a session name using lttng_action_start_session_set_session_name before using the action in a trigger. The patch adds the code for serializing the action and deserializing it on the sessiond side, but not the code for executing it. Change-Id: I90598e25a461ccabcf7dc327aaa73b3d35e203af Signed-off-by: Simon Marchi Signed-off-by: Jérémie Galarneau --- diff --git a/include/Makefile.am b/include/Makefile.am index 1f89b1bf6..dace86e03 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -121,7 +121,8 @@ lttnginclude_HEADERS = \ lttngactioninclude_HEADERS= \ lttng/action/action.h \ - lttng/action/notify.h + lttng/action/notify.h \ + lttng/action/start-session.h lttngconditioninclude_HEADERS= \ lttng/condition/condition.h \ @@ -144,6 +145,7 @@ noinst_HEADERS = \ lttng/load-internal.h \ lttng/action/action-internal.h \ lttng/action/notify-internal.h \ + lttng/action/start-session-internal.h \ lttng/condition/condition-internal.h \ lttng/condition/buffer-usage-internal.h \ lttng/condition/session-consumed-size-internal.h \ diff --git a/include/lttng/action/action.h b/include/lttng/action/action.h index f3f8d9dee..aa3d11589 100644 --- a/include/lttng/action/action.h +++ b/include/lttng/action/action.h @@ -17,6 +17,15 @@ extern "C" { enum lttng_action_type { LTTNG_ACTION_TYPE_UNKNOWN = -1, LTTNG_ACTION_TYPE_NOTIFY = 0, + LTTNG_ACTION_TYPE_START_SESSION = 1, +}; + +enum lttng_action_status { + LTTNG_ACTION_STATUS_OK = 0, + LTTNG_ACTION_STATUS_ERROR = -1, + LTTNG_ACTION_STATUS_UNKNOWN = -2, + LTTNG_ACTION_STATUS_INVALID = -3, + LTTNG_ACTION_STATUS_UNSET = -4, }; /* diff --git a/include/lttng/action/start-session-internal.h b/include/lttng/action/start-session-internal.h new file mode 100644 index 000000000..7f60103eb --- /dev/null +++ b/include/lttng/action/start-session-internal.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2019 Simon Marchi + * + * SPDX-License-Identifier: LGPL-2.1-only + * + */ + +#ifndef LTTNG_ACTION_START_SESSION_INTERNAL_H +#define LTTNG_ACTION_START_SESSION_INTERNAL_H + +#include + +#include + +struct lttng_action; +struct lttng_buffer_view; + +/* + * Create a "start session" action from a buffer view. + * + * On success, return the number of bytes consumed from `view`, and the created + * action in `*action`. On failure, return -1. + */ +LTTNG_HIDDEN +extern ssize_t lttng_action_start_session_create_from_buffer( + const struct lttng_buffer_view *view, + struct lttng_action **action); + +#endif /* LTTNG_ACTION_START_SESSION_INTERNAL_H */ diff --git a/include/lttng/action/start-session.h b/include/lttng/action/start-session.h new file mode 100644 index 000000000..b2ba470a2 --- /dev/null +++ b/include/lttng/action/start-session.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2019 Simon Marchi + * + * SPDX-License-Identifier: LGPL-2.1-only + * + */ + +#ifndef LTTNG_ACTION_START_SESSION_H +#define LTTNG_ACTION_START_SESSION_H + +struct lttng_action; + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Create a newly allocated start-session action object. + * + * A start session action object must have a session name set to be considered + * valid when used with a trigger object (lttng_trigger). A name can be set + * using `lttng_action_start_session_set_session_name`. + * + * Returns a new action on success, NULL on failure. This action must be + * destroyed using lttng_action_destroy(). + */ +extern struct lttng_action *lttng_action_start_session_create(void); + +/* + * Set the session name of an lttng_action object of type + * LTTNG_ACTION_TYPE_START_SESSION. + */ +extern enum lttng_action_status lttng_action_start_session_set_session_name( + struct lttng_action *action, const char *session_name); + +/* + * Get the session name of an lttng_action object of type + * LTTNG_ACTION_TYPE_START_SESSION. + */ +extern enum lttng_action_status lttng_action_start_session_get_session_name( + const struct lttng_action *action, const char **session_name); + +#ifdef __cplusplus +} +#endif + +#endif /* LTTNG_ACTION_START_SESSION_H */ diff --git a/include/lttng/lttng.h b/include/lttng/lttng.h index 5d84510b5..6b4ca5657 100644 --- a/include/lttng/lttng.h +++ b/include/lttng/lttng.h @@ -18,6 +18,7 @@ /* Include every LTTng ABI/API available. */ #include #include +#include #include #include #include diff --git a/src/common/Makefile.am b/src/common/Makefile.am index 7ec0f52a5..10e2d40f3 100644 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -29,6 +29,7 @@ EXTRA_DIST = mi-lttng-4.0.xsd libcommon_la_SOURCES = \ actions/action.c \ actions/notify.c \ + actions/start-session.c \ buffer-usage.c \ buffer-view.h buffer-view.c \ common.h \ diff --git a/src/common/actions/action.c b/src/common/actions/action.c index 50e1b1d84..bd11301cc 100644 --- a/src/common/actions/action.c +++ b/src/common/actions/action.c @@ -9,6 +9,7 @@ #include #include #include +#include static const char *lttng_action_type_string(enum lttng_action_type action_type) { @@ -17,6 +18,8 @@ static const char *lttng_action_type_string(enum lttng_action_type action_type) return "UNKNOWN"; case LTTNG_ACTION_TYPE_NOTIFY: return "NOTIFY"; + case LTTNG_ACTION_TYPE_START_SESSION: + return "START_SESSION"; default: return "???"; } @@ -127,6 +130,10 @@ ssize_t lttng_action_create_from_buffer(const struct lttng_buffer_view *view, case LTTNG_ACTION_TYPE_NOTIFY: create_from_buffer_cb = lttng_action_notify_create_from_buffer; break; + case LTTNG_ACTION_TYPE_START_SESSION: + create_from_buffer_cb = + lttng_action_start_session_create_from_buffer; + break; default: ERR("Failed to create action from buffer, unhandled action type: action-type=%u (%s)", action_comm->action_type, diff --git a/src/common/actions/start-session.c b/src/common/actions/start-session.c new file mode 100644 index 000000000..d4095526e --- /dev/null +++ b/src/common/actions/start-session.c @@ -0,0 +1,261 @@ +/* + * Copyright (C) 2019 Simon Marchi + * + * SPDX-License-Identifier: LGPL-2.1-only + * + */ + +#include +#include +#include +#include +#include +#include + +#define IS_START_SESSION_ACTION(action) \ + (lttng_action_get_type_const(action) == LTTNG_ACTION_TYPE_START_SESSION) + +struct lttng_action_start_session { + struct lttng_action parent; + + /* Owned by this. */ + char *session_name; +}; + +struct lttng_action_start_session_comm { + /* Includes the trailing \0. */ + uint32_t session_name_len; + + /* + * Variable data: + * + * - session name (null terminated) + */ + char data[]; +} LTTNG_PACKED; + +static struct lttng_action_start_session *action_start_session_from_action( + struct lttng_action *action) +{ + assert(action); + + return container_of(action, struct lttng_action_start_session, parent); +} + +static const struct lttng_action_start_session * +action_start_session_from_action_const(const struct lttng_action *action) +{ + assert(action); + + return container_of(action, struct lttng_action_start_session, parent); +} + +static bool lttng_action_start_session_validate(struct lttng_action *action) +{ + bool valid; + struct lttng_action_start_session *action_start_session; + + if (!action) { + valid = false; + goto end; + } + + action_start_session = action_start_session_from_action(action); + + /* A non-empty session name is mandatory. */ + if (!action_start_session->session_name || + strlen(action_start_session->session_name) == 0) { + valid = false; + goto end; + } + + valid = true; +end: + return valid; +} + +static bool lttng_action_start_session_is_equal( + const struct lttng_action *_a, const struct lttng_action *_b) +{ + bool is_equal = false; + struct lttng_action_start_session *a, *b; + + a = container_of(_a, struct lttng_action_start_session, parent); + b = container_of(_b, struct lttng_action_start_session, parent); + + /* Action is not valid if this is not true. */ + assert(a->session_name); + assert(b->session_name); + if (strcmp(a->session_name, b->session_name)) { + goto end; + } + + is_equal = true; +end: + return is_equal; +} + +static int lttng_action_start_session_serialize( + struct lttng_action *action, struct lttng_dynamic_buffer *buf) +{ + struct lttng_action_start_session *action_start_session; + struct lttng_action_start_session_comm comm; + size_t session_name_len; + int ret; + + assert(action); + assert(buf); + + action_start_session = action_start_session_from_action(action); + + assert(action_start_session->session_name); + + DBG("Serializing start session action: session-name: %s", + action_start_session->session_name); + + session_name_len = strlen(action_start_session->session_name) + 1; + comm.session_name_len = session_name_len; + + ret = lttng_dynamic_buffer_append(buf, &comm, sizeof(comm)); + if (ret) { + ret = -1; + goto end; + } + + ret = lttng_dynamic_buffer_append(buf, + action_start_session->session_name, session_name_len); + if (ret) { + ret = -1; + goto end; + } + + ret = 0; +end: + return ret; +} + +static void lttng_action_start_session_destroy(struct lttng_action *action) +{ + struct lttng_action_start_session *action_start_session; + + if (!action) { + goto end; + } + + action_start_session = action_start_session_from_action(action); + + free(action_start_session->session_name); + free(action_start_session); + +end: + return; +} + +ssize_t lttng_action_start_session_create_from_buffer( + const struct lttng_buffer_view *view, + struct lttng_action **p_action) +{ + ssize_t consumed_len; + const struct lttng_action_start_session_comm *comm; + const char *session_name; + struct lttng_action *action; + enum lttng_action_status status; + + action = lttng_action_start_session_create(); + if (!action) { + consumed_len = -1; + goto end; + } + + comm = (const struct lttng_action_start_session_comm *) view->data; + session_name = (const char *) &comm->data; + + if (!lttng_buffer_view_contains_string( + view, session_name, comm->session_name_len)) { + consumed_len = -1; + goto end; + } + + status = lttng_action_start_session_set_session_name( + action, session_name); + if (status != LTTNG_ACTION_STATUS_OK) { + consumed_len = -1; + goto end; + } + + consumed_len = sizeof(struct lttng_action_start_session_comm) + + comm->session_name_len; + *p_action = action; + action = NULL; + +end: + lttng_action_start_session_destroy(action); + + return consumed_len; +} + +struct lttng_action *lttng_action_start_session_create(void) +{ + struct lttng_action *action; + + action = zmalloc(sizeof(struct lttng_action_start_session)); + if (!action) { + goto end; + } + + lttng_action_init(action, LTTNG_ACTION_TYPE_START_SESSION, + lttng_action_start_session_validate, + lttng_action_start_session_serialize, + lttng_action_start_session_is_equal, + lttng_action_start_session_destroy); + +end: + return action; +} + +enum lttng_action_status lttng_action_start_session_set_session_name( + struct lttng_action *action, const char *session_name) +{ + struct lttng_action_start_session *action_start_session; + enum lttng_action_status status; + + if (!action || !IS_START_SESSION_ACTION(action) || !session_name || + strlen(session_name) == 0) { + status = LTTNG_ACTION_STATUS_INVALID; + goto end; + } + + action_start_session = action_start_session_from_action(action); + + free(action_start_session->session_name); + + action_start_session->session_name = strdup(session_name); + if (!action_start_session->session_name) { + status = LTTNG_ACTION_STATUS_ERROR; + goto end; + } + + status = LTTNG_ACTION_STATUS_OK; +end: + return status; +} + +enum lttng_action_status lttng_action_start_session_get_session_name( + const struct lttng_action *action, const char **session_name) +{ + const struct lttng_action_start_session *action_start_session; + enum lttng_action_status status; + + if (!action || !IS_START_SESSION_ACTION(action) || !session_name) { + status = LTTNG_ACTION_STATUS_INVALID; + goto end; + } + + action_start_session = action_start_session_from_action_const(action); + + *session_name = action_start_session->session_name; + + status = LTTNG_ACTION_STATUS_OK; +end: + return status; +}