bin: compile lttng-sessiond as C++
[lttng-tools.git] / src / bin / lttng-sessiond / snapshot.cpp
diff --git a/src/bin/lttng-sessiond/snapshot.cpp b/src/bin/lttng-sessiond/snapshot.cpp
new file mode 100644 (file)
index 0000000..0347220
--- /dev/null
@@ -0,0 +1,329 @@
+/*
+ * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#define _LGPL_SOURCE
+#include <inttypes.h>
+#include <string.h>
+#include <urcu/uatomic.h>
+
+#include <common/defaults.h>
+
+#include "snapshot.h"
+#include "utils.h"
+
+/*
+ * Return the atomically incremented value of next_output_id.
+ */
+static inline unsigned long get_next_output_id(struct snapshot *snapshot)
+{
+       return uatomic_add_return(&snapshot->next_output_id, 1);
+}
+
+/*
+ * Initialized snapshot output with the given values.
+ *
+ * Return 0 on success or else a negative value.
+ */
+static int output_init(const struct ltt_session *session,
+               uint64_t max_size, const char *name,
+               struct lttng_uri *uris, size_t nb_uri,
+               struct consumer_output *consumer, struct snapshot_output *output,
+               struct snapshot *snapshot)
+{
+       int ret = 0, i;
+
+       memset(output, 0, sizeof(struct snapshot_output));
+
+       /*
+        * max_size of -1ULL means unset. Set to default (unlimited).
+        */
+       if (max_size == (uint64_t) -1ULL) {
+               max_size = 0;
+       }
+       output->max_size = max_size;
+
+       if (snapshot) {
+               output->id = get_next_output_id(snapshot);
+       }
+       lttng_ht_node_init_ulong(&output->node, (unsigned long) output->id);
+
+       if (name && name[0] != '\0') {
+               if (lttng_strncpy(output->name, name, sizeof(output->name))) {
+                       ret = -LTTNG_ERR_INVALID;
+                       goto error;
+               }
+       } else {
+               /* Set default name. */
+               ret = snprintf(output->name, sizeof(output->name), "%s-%" PRIu32,
+                               DEFAULT_SNAPSHOT_NAME, output->id);
+               if (ret < 0) {
+                       ret = -ENOMEM;
+                       goto error;
+               }
+       }
+
+       if (!consumer) {
+               goto end;
+       }
+
+       output->consumer = consumer_copy_output(consumer);
+       if (!output->consumer) {
+               ret = -ENOMEM;
+               goto error;
+       }
+       output->consumer->snapshot = 1;
+
+       /* No URL given. */
+       if (nb_uri == 0) {
+               ret = 0;
+               goto end;
+       }
+
+       if (uris[0].dtype == LTTNG_DST_PATH) {
+               memset(output->consumer->dst.session_root_path, 0,
+                               sizeof(output->consumer->dst.session_root_path));
+               if (lttng_strncpy(output->consumer->dst.session_root_path,
+                               uris[0].dst.path,
+                               sizeof(output->consumer->dst.session_root_path))) {
+                       ret = -LTTNG_ERR_INVALID;
+                       goto error;
+               }
+               output->consumer->type = CONSUMER_DST_LOCAL;
+               ret = 0;
+               goto end;
+       }
+
+       if (nb_uri != 2) {
+               /* Absolutely needs two URIs for network. */
+               ret = -LTTNG_ERR_INVALID;
+               goto error;
+       }
+
+       for (i = 0; i < nb_uri; i ++) {
+               /* Network URIs */
+               ret = consumer_set_network_uri(session, output->consumer,
+                               &uris[i]);
+               if (ret < 0) {
+                       goto error;
+               }
+       }
+
+error:
+end:
+       return ret;
+}
+
+/*
+ * Initialize a snapshot output object using the given parameters and URI(s).
+ * The name value and uris can be NULL.
+ *
+ * Return 0 on success or else a negative value.
+ */
+int snapshot_output_init_with_uri(const struct ltt_session *session,
+               uint64_t max_size, const char *name,
+               struct lttng_uri *uris, size_t nb_uri,
+               struct consumer_output *consumer, struct snapshot_output *output,
+               struct snapshot *snapshot)
+{
+       return output_init(session, max_size, name, uris, nb_uri, consumer,
+                       output, snapshot);
+}
+
+/*
+ * Initialize a snapshot output object using the given parameters. The name
+ * value and url can be NULL.
+ *
+ * Return 0 on success or else a negative value.
+ */
+int snapshot_output_init(const struct ltt_session *session,
+               uint64_t max_size, const char *name,
+               const char *ctrl_url, const char *data_url,
+               struct consumer_output *consumer, struct snapshot_output *output,
+               struct snapshot *snapshot)
+{
+       int ret = 0, nb_uri;
+       struct lttng_uri *uris = NULL;
+
+       /* Create an array of URIs from URLs. */
+       nb_uri = uri_parse_str_urls(ctrl_url, data_url, &uris);
+       if (nb_uri < 0) {
+               ret = nb_uri;
+               goto error;
+       }
+
+       ret = output_init(session, max_size, name, uris, nb_uri, consumer,
+                       output, snapshot);
+
+error:
+       free(uris);
+       return ret;
+}
+
+struct snapshot_output *snapshot_output_alloc(void)
+{
+       return (snapshot_output *) zmalloc(sizeof(struct snapshot_output));
+}
+
+/*
+ * Delete output from the snapshot object.
+ */
+void snapshot_delete_output(struct snapshot *snapshot,
+               struct snapshot_output *output)
+{
+       int ret;
+       struct lttng_ht_iter iter;
+
+       LTTNG_ASSERT(snapshot);
+       LTTNG_ASSERT(snapshot->output_ht);
+       LTTNG_ASSERT(output);
+
+       iter.iter.node = &output->node.node;
+       rcu_read_lock();
+       ret = lttng_ht_del(snapshot->output_ht, &iter);
+       rcu_read_unlock();
+       LTTNG_ASSERT(!ret);
+       /*
+        * This is safe because the ownership of a snapshot object is in a session
+        * for which the session lock need to be acquired to read and modify it.
+        */
+       snapshot->nb_output--;
+}
+
+/*
+ * Add output object to the snapshot.
+ */
+void snapshot_add_output(struct snapshot *snapshot,
+               struct snapshot_output *output)
+{
+       LTTNG_ASSERT(snapshot);
+       LTTNG_ASSERT(snapshot->output_ht);
+       LTTNG_ASSERT(output);
+
+       rcu_read_lock();
+       lttng_ht_add_unique_ulong(snapshot->output_ht, &output->node);
+       rcu_read_unlock();
+       /*
+        * This is safe because the ownership of a snapshot object is in a session
+        * for which the session lock need to be acquired to read and modify it.
+        */
+       snapshot->nb_output++;
+}
+
+/*
+ * Destroy and free a snapshot output object.
+ */
+void snapshot_output_destroy(struct snapshot_output *obj)
+{
+       LTTNG_ASSERT(obj);
+
+       if (obj->consumer) {
+               consumer_output_send_destroy_relayd(obj->consumer);
+               consumer_output_put(obj->consumer);
+       }
+       free(obj);
+}
+
+/*
+ * RCU read side lock MUST be acquired before calling this since the returned
+ * pointer is in a RCU hash table.
+ *
+ * Return the reference on success or else NULL.
+ */
+struct snapshot_output *snapshot_find_output_by_name(const char *name,
+               struct snapshot *snapshot)
+{
+       struct lttng_ht_iter iter;
+       struct snapshot_output *output = NULL;
+
+       LTTNG_ASSERT(snapshot);
+       LTTNG_ASSERT(name);
+
+       cds_lfht_for_each_entry(snapshot->output_ht->ht, &iter.iter, output,
+               node.node) {
+               if (!strncmp(output->name, name, strlen(name))) {
+                       return output;
+               }
+       }
+
+       /* Not found */
+       return NULL;
+}
+
+/*
+ * RCU read side lock MUST be acquired before calling this since the returned
+ * pointer is in a RCU hash table.
+ *
+ * Return the reference on success or else NULL.
+ */
+struct snapshot_output *snapshot_find_output_by_id(uint32_t id,
+               struct snapshot *snapshot)
+{
+       struct lttng_ht_node_ulong *node;
+       struct lttng_ht_iter iter;
+       struct snapshot_output *output = NULL;
+
+       LTTNG_ASSERT(snapshot);
+
+       lttng_ht_lookup(snapshot->output_ht, (void *)((unsigned long) id), &iter);
+       node = lttng_ht_iter_get_node_ulong(&iter);
+       if (!node) {
+               DBG3("Snapshot output not found with id %" PRId32, id);
+               goto error;
+       }
+       output = caa_container_of(node, struct snapshot_output, node);
+
+error:
+       return output;
+}
+
+/*
+ * Initialized a snapshot object that was already allocated.
+ *
+ * Return 0 on success or else a negative errno value.
+ */
+int snapshot_init(struct snapshot *obj)
+{
+       int ret;
+
+       LTTNG_ASSERT(obj);
+
+       memset(obj, 0, sizeof(struct snapshot));
+
+       obj->output_ht = lttng_ht_new(0, LTTNG_HT_TYPE_ULONG);
+       if (!obj->output_ht) {
+               ret = -ENOMEM;
+               goto error;
+       }
+
+       ret = 0;
+
+error:
+       return ret;
+}
+
+/*
+ * Destroy snapshot object but the pointer is not freed so it's safe to pass a
+ * static reference.
+ */
+void snapshot_destroy(struct snapshot *obj)
+{
+       struct lttng_ht_iter iter;
+       struct snapshot_output *output;
+
+       if (!obj->output_ht) {
+               return;
+       }
+
+       rcu_read_lock();
+       cds_lfht_for_each_entry(obj->output_ht->ht, &iter.iter, output,
+                       node.node) {
+               snapshot_delete_output(obj, output);
+               snapshot_output_destroy(output);
+       }
+       rcu_read_unlock();
+       ht_cleanup_push(obj->output_ht);
+}
This page took 0.025585 seconds and 4 git commands to generate.