From 931bdbaa3a3fd1d586a0045c15cac23d6cfc67f9 Mon Sep 17 00:00:00 2001 From: Simon Marchi Date: Mon, 2 Dec 2019 14:53:11 -0500 Subject: [PATCH] actions: introduce stop session action MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This patch introduces the API for the "stop session" action. A stop session action is created using the lttng_action_stop_session_create function. It is mandatory to set a session name using lttng_action_stop_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: Ie00d744340f85f15a333680cf86d3882bd612d1a Signed-off-by: Simon Marchi Signed-off-by: Jérémie Galarneau --- include/Makefile.am | 4 +- include/lttng/action/action.h | 1 + include/lttng/action/stop-session-internal.h | 29 +++ include/lttng/action/stop-session.h | 47 ++++ include/lttng/lttng.h | 1 + src/common/Makefile.am | 1 + src/common/actions/action.c | 7 + src/common/actions/stop-session.c | 261 +++++++++++++++++++ 8 files changed, 350 insertions(+), 1 deletion(-) create mode 100644 include/lttng/action/stop-session-internal.h create mode 100644 include/lttng/action/stop-session.h create mode 100644 src/common/actions/stop-session.c diff --git a/include/Makefile.am b/include/Makefile.am index dace86e03..b31df9da1 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -122,7 +122,8 @@ lttnginclude_HEADERS = \ lttngactioninclude_HEADERS= \ lttng/action/action.h \ lttng/action/notify.h \ - lttng/action/start-session.h + lttng/action/start-session.h \ + lttng/action/stop-session.h lttngconditioninclude_HEADERS= \ lttng/condition/condition.h \ @@ -146,6 +147,7 @@ noinst_HEADERS = \ lttng/action/action-internal.h \ lttng/action/notify-internal.h \ lttng/action/start-session-internal.h \ + lttng/action/stop-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 aa3d11589..cc26ed914 100644 --- a/include/lttng/action/action.h +++ b/include/lttng/action/action.h @@ -18,6 +18,7 @@ enum lttng_action_type { LTTNG_ACTION_TYPE_UNKNOWN = -1, LTTNG_ACTION_TYPE_NOTIFY = 0, LTTNG_ACTION_TYPE_START_SESSION = 1, + LTTNG_ACTION_TYPE_STOP_SESSION = 2, }; enum lttng_action_status { diff --git a/include/lttng/action/stop-session-internal.h b/include/lttng/action/stop-session-internal.h new file mode 100644 index 000000000..150002e84 --- /dev/null +++ b/include/lttng/action/stop-session-internal.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2019 Simon Marchi + * + * SPDX-License-Identifier: LGPL-2.1-only + * + */ + +#ifndef LTTNG_ACTION_STOP_SESSION_INTERNAL_H +#define LTTNG_ACTION_STOP_SESSION_INTERNAL_H + +#include + +#include + +struct lttng_action; +struct lttng_buffer_view; + +/* + * Create a "stop 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_stop_session_create_from_buffer( + const struct lttng_buffer_view *view, + struct lttng_action **action); + +#endif /* LTTNG_ACTION_STOP_SESSION_INTERNAL_H */ diff --git a/include/lttng/action/stop-session.h b/include/lttng/action/stop-session.h new file mode 100644 index 000000000..5c1673137 --- /dev/null +++ b/include/lttng/action/stop-session.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2019 Simon Marchi + * + * SPDX-License-Identifier: LGPL-2.1-only + * + */ + +#ifndef LTTNG_ACTION_STOP_SESSION_H +#define LTTNG_ACTION_STOP_SESSION_H + +struct lttng_action; + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Create a newly allocated stop-session action object. + * + * A stop 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_stop_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_stop_session_create(void); + +/* + * Set the session name of an lttng_action object of type + * LTTNG_ACTION_TYPE_STOP_SESSION. + */ +extern enum lttng_action_status lttng_action_stop_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_STOP_SESSION. + */ +extern enum lttng_action_status lttng_action_stop_session_get_session_name( + const struct lttng_action *action, const char **session_name); + +#ifdef __cplusplus +} +#endif + +#endif /* LTTNG_ACTION_STOP_SESSION_H */ diff --git a/include/lttng/lttng.h b/include/lttng/lttng.h index 6b4ca5657..24638a351 100644 --- a/include/lttng/lttng.h +++ b/include/lttng/lttng.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include diff --git a/src/common/Makefile.am b/src/common/Makefile.am index 10e2d40f3..5303f2643 100644 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -30,6 +30,7 @@ libcommon_la_SOURCES = \ actions/action.c \ actions/notify.c \ actions/start-session.c \ + actions/stop-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 bd11301cc..208858e26 100644 --- a/src/common/actions/action.c +++ b/src/common/actions/action.c @@ -10,6 +10,7 @@ #include #include #include +#include static const char *lttng_action_type_string(enum lttng_action_type action_type) { @@ -20,6 +21,8 @@ static const char *lttng_action_type_string(enum lttng_action_type action_type) return "NOTIFY"; case LTTNG_ACTION_TYPE_START_SESSION: return "START_SESSION"; + case LTTNG_ACTION_TYPE_STOP_SESSION: + return "STOP_SESSION"; default: return "???"; } @@ -134,6 +137,10 @@ ssize_t lttng_action_create_from_buffer(const struct lttng_buffer_view *view, create_from_buffer_cb = lttng_action_start_session_create_from_buffer; break; + case LTTNG_ACTION_TYPE_STOP_SESSION: + create_from_buffer_cb = + lttng_action_stop_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/stop-session.c b/src/common/actions/stop-session.c new file mode 100644 index 000000000..a36e873cf --- /dev/null +++ b/src/common/actions/stop-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_STOP_SESSION_ACTION(action) \ + (lttng_action_get_type_const(action) == LTTNG_ACTION_TYPE_STOP_SESSION) + +struct lttng_action_stop_session { + struct lttng_action parent; + + /* Owned by this. */ + char *session_name; +}; + +struct lttng_action_stop_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_stop_session *action_stop_session_from_action( + struct lttng_action *action) +{ + assert(action); + + return container_of(action, struct lttng_action_stop_session, parent); +} + +static const struct lttng_action_stop_session * +action_stop_session_from_action_const(const struct lttng_action *action) +{ + assert(action); + + return container_of(action, struct lttng_action_stop_session, parent); +} + +static bool lttng_action_stop_session_validate(struct lttng_action *action) +{ + bool valid; + struct lttng_action_stop_session *action_stop_session; + + if (!action) { + valid = false; + goto end; + } + + action_stop_session = action_stop_session_from_action(action); + + /* A non-empty session name is mandatory. */ + if (!action_stop_session->session_name || + strlen(action_stop_session->session_name) == 0) { + valid = false; + goto end; + } + + valid = true; +end: + return valid; +} + +static bool lttng_action_stop_session_is_equal( + const struct lttng_action *_a, const struct lttng_action *_b) +{ + bool is_equal = false; + const struct lttng_action_stop_session *a, *b; + + a = action_stop_session_from_action_const(_a); + b = action_stop_session_from_action_const(_b); + + /* 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_stop_session_serialize( + struct lttng_action *action, struct lttng_dynamic_buffer *buf) +{ + struct lttng_action_stop_session *action_stop_session; + struct lttng_action_stop_session_comm comm; + size_t session_name_len; + int ret; + + assert(action); + assert(buf); + + action_stop_session = action_stop_session_from_action(action); + + assert(action_stop_session->session_name); + + DBG("Serializing stop session action: session-name: %s", + action_stop_session->session_name); + + session_name_len = strlen(action_stop_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_stop_session->session_name, session_name_len); + if (ret) { + ret = -1; + goto end; + } + + ret = 0; +end: + return ret; +} + +static void lttng_action_stop_session_destroy(struct lttng_action *action) +{ + struct lttng_action_stop_session *action_stop_session; + + if (!action) { + goto end; + } + + action_stop_session = action_stop_session_from_action(action); + + free(action_stop_session->session_name); + free(action_stop_session); + +end: + return; +} + +ssize_t lttng_action_stop_session_create_from_buffer( + const struct lttng_buffer_view *view, + struct lttng_action **p_action) +{ + ssize_t consumed_len; + const struct lttng_action_stop_session_comm *comm; + const char *session_name; + struct lttng_action *action; + enum lttng_action_status status; + + action = lttng_action_stop_session_create(); + if (!action) { + consumed_len = -1; + goto end; + } + + comm = (const struct lttng_action_stop_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_stop_session_set_session_name( + action, session_name); + if (status != LTTNG_ACTION_STATUS_OK) { + consumed_len = -1; + goto end; + } + + consumed_len = sizeof(struct lttng_action_stop_session_comm) + + comm->session_name_len; + *p_action = action; + action = NULL; + +end: + lttng_action_stop_session_destroy(action); + + return consumed_len; +} + +struct lttng_action *lttng_action_stop_session_create(void) +{ + struct lttng_action *action; + + action = zmalloc(sizeof(struct lttng_action_stop_session)); + if (!action) { + goto end; + } + + lttng_action_init(action, LTTNG_ACTION_TYPE_STOP_SESSION, + lttng_action_stop_session_validate, + lttng_action_stop_session_serialize, + lttng_action_stop_session_is_equal, + lttng_action_stop_session_destroy); + +end: + return action; +} + +enum lttng_action_status lttng_action_stop_session_set_session_name( + struct lttng_action *action, const char *session_name) +{ + struct lttng_action_stop_session *action_stop_session; + enum lttng_action_status status; + + if (!action || !IS_STOP_SESSION_ACTION(action) || !session_name || + strlen(session_name) == 0) { + status = LTTNG_ACTION_STATUS_INVALID; + goto end; + } + + action_stop_session = action_stop_session_from_action(action); + + free(action_stop_session->session_name); + + action_stop_session->session_name = strdup(session_name); + if (!action_stop_session->session_name) { + status = LTTNG_ACTION_STATUS_ERROR; + goto end; + } + + status = LTTNG_ACTION_STATUS_OK; +end: + return status; +} + +enum lttng_action_status lttng_action_stop_session_get_session_name( + const struct lttng_action *action, const char **session_name) +{ + const struct lttng_action_stop_session *action_stop_session; + enum lttng_action_status status; + + if (!action || !IS_STOP_SESSION_ACTION(action) || !session_name) { + status = LTTNG_ACTION_STATUS_INVALID; + goto end; + } + + action_stop_session = action_stop_session_from_action_const(action); + + *session_name = action_stop_session->session_name; + + status = LTTNG_ACTION_STATUS_OK; +end: + return status; +} -- 2.34.1