From: Jonathan Rajotte Date: Tue, 9 Jun 2020 00:29:58 +0000 (-0400) Subject: liblttng-ctl: add facilities for lttng_snapshot_output object X-Git-Url: http://git.efficios.com/?p=lttng-tools.git;a=commitdiff_plain;h=b30fa1919a1e0274b8d4734acb8cb54753808609 liblttng-ctl: add facilities for lttng_snapshot_output object Internal: is_equal, serialize, validate, from_buffer. Public: set_local_path, set_network_url set_network_urls These APIs are used by the upcoming "snapshot session" action used to trigger a snapshot on a given condition. The internal API is added to transmit a snapshot output as part of an action while the public API is added to clean-up the current snapshot_output API which will be used by the client to create the snapshot_session actions. For instance, with set_local_path, it is no longer necessary to create a local snapshot output by calling lttng_snapshot_output_set_ctrl_url with a "file://" protocol. Signed-off-by: Simon Marchi Signed-off-by: Jonathan Rajotte Signed-off-by: Jérémie Galarneau Change-Id: I00f9521faf9f66890ad6ea9a05ad7f6468f805f8 --- diff --git a/include/lttng/snapshot.h b/include/lttng/snapshot.h index 9bdf775a9..24f165287 100644 --- a/include/lttng/snapshot.h +++ b/include/lttng/snapshot.h @@ -65,6 +65,42 @@ int lttng_snapshot_output_set_size(uint64_t size, /* Set the snapshot name. */ int lttng_snapshot_output_set_name(const char *name, struct lttng_snapshot_output *output); + +/* + * Set the output destination to be a path on the local filesystem. + * + * The path must be absolute. It can optionally begin with `file://`. + * + * Return 0 on success or else a negative LTTNG_ERR code. + */ +int lttng_snapshot_output_set_local_path(const char *path, + struct lttng_snapshot_output *output); + +/* + * Set the output destination to be the network from a combined control/data + * URL. + * + * `url` must start with `net://` or `net6://`. + * + * Return 0 on success or else a negative LTTNG_ERR code. + */ +int lttng_snapshot_output_set_network_url(const char *url, + struct lttng_snapshot_output *output); + +/* + * Set the output destination to be the network using separate URLs for control + * and data. + * + * Both ctrl_url and data_url must be non-null. + * + * `ctrl_url` and `data_url` must start with `tcp://` or `tcp6://`. + * + * Return 0 on success or else a negative LTTNG_ERR code. + */ +int lttng_snapshot_output_set_network_urls( + const char *ctrl_url, const char *data_url, + struct lttng_snapshot_output *output); + /* Set the control URL. Local and remote URL are supported. */ int lttng_snapshot_output_set_ctrl_url(const char *url, struct lttng_snapshot_output *output); diff --git a/src/common/Makefile.am b/src/common/Makefile.am index 75fe7c907..5b186ce1f 100644 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -59,6 +59,7 @@ libcommon_la_SOURCES = \ session-consumed-size.c \ session-descriptor.c \ session-rotation.c \ + snapshot.c snapshot.h \ spawn-viewer.c spawn-viewer.h \ time.c \ trace-chunk.c trace-chunk.h \ diff --git a/src/common/snapshot.c b/src/common/snapshot.c new file mode 100644 index 000000000..9d1627fcb --- /dev/null +++ b/src/common/snapshot.c @@ -0,0 +1,174 @@ +/* + * Copyright (C) 2020 Simon Marchi + * + * SPDX-License-Identifier: GPL-2.0-only + * + */ + +#include +#include +#include +#include +#include + +#include +#include + +LTTNG_HIDDEN +bool lttng_snapshot_output_validate(const struct lttng_snapshot_output *output) +{ + bool valid = false; + size_t len; + + /* + * It is mandatory to have a ctrl_url. If there is only one output + * URL (in the net://, net6:// or file:// form), it will be in this + * field. + */ + len = lttng_strnlen(output->ctrl_url, sizeof(output->ctrl_url)); + if (len == 0 || len >= sizeof(output->ctrl_url)) { + goto end; + } + + len = lttng_strnlen(output->data_url, sizeof(output->data_url)); + if (len >= sizeof(output->data_url)) { + goto end; + } + + len = lttng_strnlen(output->name, sizeof(output->name)); + if (len >= sizeof(output->name)) { + goto end; + } + + valid = true; + +end: + return valid; +} + +LTTNG_HIDDEN +bool lttng_snapshot_output_is_equal( + const struct lttng_snapshot_output *a, + const struct lttng_snapshot_output *b) +{ + bool equal = false; + + assert(a); + assert(b); + + if (a->max_size != b->max_size) { + goto end; + } + + if (strcmp(a->name, b->name) != 0) { + goto end; + } + + if (strcmp(a->ctrl_url, b->ctrl_url) != 0) { + goto end; + } + + if (strcmp(a->data_url, b->data_url) != 0) { + goto end; + } + + equal = true; + +end: + return equal; +} + +/* + * This is essentially the same as `struct lttng_snapshot_output`, but packed. + */ +struct lttng_snapshot_output_comm { + uint32_t id; + uint64_t max_size; + char name[LTTNG_NAME_MAX]; + char ctrl_url[PATH_MAX]; + char data_url[PATH_MAX]; +} LTTNG_PACKED; + +LTTNG_HIDDEN +int lttng_snapshot_output_serialize( + const struct lttng_snapshot_output *output, + struct lttng_dynamic_buffer *buf) +{ + struct lttng_snapshot_output_comm comm; + int ret; + + comm.id = output->id; + comm.max_size = output->max_size; + + ret = lttng_strncpy(comm.name, output->name, sizeof(comm.name)); + if (ret) { + goto end; + } + + ret = lttng_strncpy(comm.ctrl_url, output->ctrl_url, sizeof(comm.ctrl_url)); + if (ret) { + goto end; + } + + ret = lttng_strncpy(comm.data_url, output->data_url, sizeof(comm.data_url)); + if (ret) { + goto end; + } + + ret = lttng_dynamic_buffer_append(buf, &comm, sizeof(comm)); + if (ret) { + goto end; + } + +end: + return ret; +} + +LTTNG_HIDDEN +ssize_t lttng_snapshot_output_create_from_buffer( + const struct lttng_buffer_view *view, + struct lttng_snapshot_output **output_p) +{ + const struct lttng_snapshot_output_comm *comm; + struct lttng_snapshot_output *output = NULL; + int ret; + + if (view->size != sizeof(*comm)) { + ret = -1; + goto end; + } + + output = lttng_snapshot_output_create(); + if (!output) { + ret = -1; + goto end; + } + + comm = (const struct lttng_snapshot_output_comm *) view->data; + + output->id = comm->id; + output->max_size = comm->max_size; + + ret = lttng_strncpy(output->name, comm->name, sizeof(output->name)); + if (ret) { + goto end; + } + + ret = lttng_strncpy(output->ctrl_url, comm->ctrl_url, sizeof(output->ctrl_url)); + if (ret) { + goto end; + } + + ret = lttng_strncpy(output->data_url, comm->data_url, sizeof(output->data_url)); + if (ret) { + goto end; + } + + *output_p = output; + output = NULL; + ret = sizeof(*comm); + +end: + lttng_snapshot_output_destroy(output); + return ret; +} diff --git a/src/common/snapshot.h b/src/common/snapshot.h new file mode 100644 index 000000000..95a63e13b --- /dev/null +++ b/src/common/snapshot.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2020 Simon Marchi + * + * SPDX-License-Identifier: GPL-2.0-only + * + */ + +#ifndef COMMON_SNAPSHOT_H +#define COMMON_SNAPSHOT_H + +#include + +#include + +struct lttng_buffer_view; +struct lttng_dynamic_buffer; +struct lttng_snapshot_output; + +LTTNG_HIDDEN +bool lttng_snapshot_output_validate(const struct lttng_snapshot_output *output); + +LTTNG_HIDDEN +bool lttng_snapshot_output_is_equal( + const struct lttng_snapshot_output *a, + const struct lttng_snapshot_output *b); + +LTTNG_HIDDEN +int lttng_snapshot_output_serialize( + const struct lttng_snapshot_output *output, + struct lttng_dynamic_buffer *buf); + +LTTNG_HIDDEN +ssize_t lttng_snapshot_output_create_from_buffer( + const struct lttng_buffer_view *view, + struct lttng_snapshot_output **output_p); + +#endif /* COMMON_SNAPSHOT_H */ diff --git a/src/lib/lttng-ctl/snapshot.c b/src/lib/lttng-ctl/snapshot.c index 0aebf1575..2d7725c96 100644 --- a/src/lib/lttng-ctl/snapshot.c +++ b/src/lib/lttng-ctl/snapshot.c @@ -323,3 +323,126 @@ int lttng_snapshot_output_set_data_url(const char *url, lttng_ctl_copy_string(output->data_url, url, sizeof(output->data_url)); return 0; } + +int lttng_snapshot_output_set_local_path(const char *path, + struct lttng_snapshot_output *output) +{ + int ret; + struct lttng_uri *uris = NULL; + ssize_t num_uris; + + if (!path || !output) { + ret = -LTTNG_ERR_INVALID; + goto end; + } + + num_uris = uri_parse_str_urls(path, NULL, &uris); + if (num_uris != 1) { + ret = -LTTNG_ERR_INVALID; + goto end; + } + + if (uris[0].dtype != LTTNG_DST_PATH) { + ret = -LTTNG_ERR_INVALID; + goto end; + } + + ret = lttng_strncpy(output->ctrl_url, path, sizeof(output->ctrl_url)); + if (ret != 0) { + ret = -LTTNG_ERR_INVALID; + goto end; + } + +end: + free(uris); + return ret; +} + +int lttng_snapshot_output_set_network_url(const char *url, + struct lttng_snapshot_output *output) +{ + int ret; + struct lttng_uri *uris = NULL; + ssize_t num_uris; + + if (!url || !output) { + ret = -LTTNG_ERR_INVALID; + goto end; + } + + num_uris = uri_parse_str_urls(url, NULL, &uris); + if (num_uris != 2) { + ret = -LTTNG_ERR_INVALID; + goto end; + } + + if (uris[0].dtype != LTTNG_DST_IPV4 && + uris[0].dtype != LTTNG_DST_IPV6) { + ret = -LTTNG_ERR_INVALID; + goto end; + } + + if (uris[1].dtype != LTTNG_DST_IPV4 && + uris[1].dtype != LTTNG_DST_IPV6) { + ret = -LTTNG_ERR_INVALID; + goto end; + } + + ret = lttng_strncpy(output->ctrl_url, url, sizeof(output->ctrl_url)); + if (ret != 0) { + ret = -LTTNG_ERR_INVALID; + goto end; + } + +end: + free(uris); + return ret; +} + +int lttng_snapshot_output_set_network_urls( + const char *ctrl_url, const char *data_url, + struct lttng_snapshot_output *output) +{ + int ret; + struct lttng_uri *uris = NULL; + ssize_t num_uris; + + if (!ctrl_url || !data_url || !output) { + ret = -LTTNG_ERR_INVALID; + goto end; + } + + num_uris = uri_parse_str_urls(ctrl_url, data_url, &uris); + if (num_uris != 2) { + ret = -LTTNG_ERR_INVALID; + goto end; + } + + if (uris[0].dtype != LTTNG_DST_IPV4 && + uris[0].dtype != LTTNG_DST_IPV6) { + ret = -LTTNG_ERR_INVALID; + goto end; + } + + if (uris[1].dtype != LTTNG_DST_IPV4 && + uris[1].dtype != LTTNG_DST_IPV6) { + ret = -LTTNG_ERR_INVALID; + goto end; + } + + ret = lttng_strncpy(output->ctrl_url, ctrl_url, sizeof(output->ctrl_url)); + if (ret != 0) { + ret = -LTTNG_ERR_INVALID; + goto end; + } + + ret = lttng_strncpy(output->data_url, data_url, sizeof(output->data_url)); + if (ret != 0) { + ret = -LTTNG_ERR_INVALID; + goto end; + } + +end: + free(uris); + return ret; +}