Command metadata regenerate
authorJulien Desfossez <jdesfossez@efficios.com>
Fri, 7 Aug 2015 20:06:49 +0000 (16:06 -0400)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Fri, 11 Mar 2016 23:25:14 +0000 (18:25 -0500)
Command to regenerate the metadata file when the session is running.
This allows the user to regenerate the metadata after a major NTP
correction and that way update the clock offset from epoch in the
metadata.

Works for kernel and UST per-uid session local or remote (not live).

Signed-off-by: Julien Desfossez <jdesfossez@efficios.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
33 files changed:
doc/man/lttng.1
include/lttng/lttng-error.h
include/lttng/lttng.h
src/bin/lttng-relayd/main.c
src/bin/lttng-sessiond/cmd.c
src/bin/lttng-sessiond/cmd.h
src/bin/lttng-sessiond/consumer.c
src/bin/lttng-sessiond/consumer.h
src/bin/lttng-sessiond/main.c
src/bin/lttng-sessiond/ust-app.c
src/bin/lttng-sessiond/ust-registry.h
src/bin/lttng/Makefile.am
src/bin/lttng/command.h
src/bin/lttng/commands/metadata.c [new file with mode: 0644]
src/bin/lttng/lttng.c
src/common/consumer/consumer-metadata-cache.c
src/common/consumer/consumer-metadata-cache.h
src/common/consumer/consumer.c
src/common/consumer/consumer.h
src/common/error.c
src/common/kernel-consumer/kernel-consumer.c
src/common/kernel-ctl/kernel-ctl.c
src/common/kernel-ctl/kernel-ctl.h
src/common/kernel-ctl/kernel-ioctl.h
src/common/relayd/relayd.c
src/common/relayd/relayd.h
src/common/sessiond-comm/relayd.h
src/common/sessiond-comm/sessiond-comm.h
src/common/ust-consumer/ust-consumer.c
src/common/ust-consumer/ust-consumer.h
src/common/utils.c
src/common/utils.h
src/lib/lttng-ctl/lttng-ctl.c

index 7aef3d57a4cd88e5adfafecc637243a042e190ea..bd2776114f597df6ec3983990a1a2eaacf239cee 100644 (file)
@@ -848,6 +848,31 @@ already exists.
 .RE
 .PP
 
 .RE
 .PP
 
+.PP
+\fBmetadata\fP [OPTIONS] ACTION
+.RS
+Metadata command for a LTTng session.
+
+.B OPTIONS:
+
+.TP
+.BR "\-h, \-\-help"
+Show summary of possible options and commands.
+.TP
+.BR "\-\-list-options"
+Simple listing of options
+
+.PP
+.B ACTION:
+
+.TP
+\fBregenerate\fP [-s <NAME>]
+Regenerate the metadata of a session. This allows the user to regenerate the
+metadata after a major NTP correction and that way update the clock offset from
+epoch in the metadata. Only works on kernel, UST per-uid and non-live sessions.
+.RE
+.PP
+
 .PP
 \fBsave\fP [OPTIONS] [SESSION]
 .RS
 .PP
 \fBsave\fP [OPTIONS] [SESSION]
 .RS
index 1030bdfc34f4343d3189f33b1586e323ce2cec92..b55d9478c5f25958786d3f224c4feff82e532ce1 100644 (file)
@@ -138,6 +138,9 @@ enum lttng_error_code {
        LTTNG_ERR_PID_NOT_TRACKED        = 115, /* PID not tracked */
        LTTNG_ERR_INVALID_CHANNEL_DOMAIN = 116, /* Invalid channel domain */
        LTTNG_ERR_OVERFLOW               = 117, /* Overflow occured. */
        LTTNG_ERR_PID_NOT_TRACKED        = 115, /* PID not tracked */
        LTTNG_ERR_INVALID_CHANNEL_DOMAIN = 116, /* Invalid channel domain */
        LTTNG_ERR_OVERFLOW               = 117, /* Overflow occured. */
+       LTTNG_ERR_SESSION_NOT_STARTED    = 118, /* Session not started */
+       LTTNG_ERR_LIVE_SESSION           = 119, /* Live session unsupported */
+       LTTNG_ERR_PER_PID_SESSION        = 120, /* Per-PID sessions unsupported */
 
        /* MUST be last element */
        LTTNG_ERR_NR,                           /* Last element */
 
        /* MUST be last element */
        LTTNG_ERR_NR,                           /* Last element */
index c5be66128b60da0cc76c5972a095a5ccbd8a4f79..2088864d254e9cb16b42ab31649ebf4603a1db81 100644 (file)
@@ -159,6 +159,14 @@ extern int lttng_set_consumer_url(struct lttng_handle *handle,
  */
 extern int lttng_data_pending(const char *session_name);
 
  */
 extern int lttng_data_pending(const char *session_name);
 
+/*
+ * Trigger the regeneration of the metadata for a session.
+ * The new metadata overwrite the previous one locally or remotely (through
+ * the lttng-relayd). Only kernel, per-uid and non-live sessions are supported.
+ * Return 0 on success, a negative LTTng error code on error.
+ */
+extern int lttng_metadata_regenerate(const char *session_name);
+
 #ifdef __cplusplus
 }
 #endif
 #ifdef __cplusplus
 }
 #endif
index e4ded2b8655d17c5f270bd67cfffca65697766f8..cc5009940e13cf05b49d5122879bfc24a110a838 100644 (file)
@@ -1330,6 +1330,90 @@ end_no_session:
        return ret;
 }
 
        return ret;
 }
 
+/*
+ * relay_reset_metadata: reset a metadata stream
+ */
+static
+int relay_reset_metadata(struct lttcomm_relayd_hdr *recv_hdr,
+               struct relay_connection *conn)
+{
+       int ret, send_ret;
+       struct relay_session *session = conn->session;
+       struct lttcomm_relayd_reset_metadata stream_info;
+       struct lttcomm_relayd_generic_reply reply;
+       struct relay_stream *stream;
+
+       DBG("Reset metadata received");
+
+       if (!session || conn->version_check_done == 0) {
+               ERR("Trying to reset a metadata stream before version check");
+               ret = -1;
+               goto end_no_session;
+       }
+
+       ret = conn->sock->ops->recvmsg(conn->sock, &stream_info,
+                       sizeof(struct lttcomm_relayd_reset_metadata), 0);
+       if (ret < sizeof(struct lttcomm_relayd_reset_metadata)) {
+               if (ret == 0) {
+                       /* Orderly shutdown. Not necessary to print an error. */
+                       DBG("Socket %d did an orderly shutdown", conn->sock->fd);
+               } else {
+                       ERR("Relay didn't receive valid reset_metadata struct "
+                                       "size : %d", ret);
+               }
+               ret = -1;
+               goto end_no_session;
+       }
+       DBG("Update metadata to version %" PRIu64, be64toh(stream_info.version));
+
+       /* Unsupported for live sessions for now. */
+       if (session->live_timer != 0) {
+               ret = -1;
+               goto end;
+       }
+
+       stream = stream_get_by_id(be64toh(stream_info.stream_id));
+       if (!stream) {
+               ret = -1;
+               goto end;
+       }
+       pthread_mutex_lock(&stream->lock);
+       if (!stream->is_metadata) {
+               ret = -1;
+               goto end_unlock;
+       }
+
+       ret = utils_rotate_stream_file(stream->path_name, stream->channel_name,
+                       0, 0, -1, -1, stream->stream_fd->fd, NULL,
+                       &stream->stream_fd->fd);
+       if (ret < 0) {
+               ERR("Failed to rotate metadata file %s of channel %s",
+                               stream->path_name, stream->channel_name);
+               goto end_unlock;
+       }
+
+end_unlock:
+       pthread_mutex_unlock(&stream->lock);
+       stream_put(stream);
+
+end:
+       memset(&reply, 0, sizeof(reply));
+       if (ret < 0) {
+               reply.ret_code = htobe32(LTTNG_ERR_UNK);
+       } else {
+               reply.ret_code = htobe32(LTTNG_OK);
+       }
+       send_ret = conn->sock->ops->sendmsg(conn->sock, &reply,
+                       sizeof(struct lttcomm_relayd_generic_reply), 0);
+       if (send_ret < 0) {
+               ERR("Relay sending reset metadata reply");
+               ret = send_ret;
+       }
+
+end_no_session:
+       return ret;
+}
+
 /*
  * relay_unknown_command: send -1 if received unknown command
  */
 /*
  * relay_unknown_command: send -1 if received unknown command
  */
@@ -2060,6 +2144,9 @@ static int relay_process_control(struct lttcomm_relayd_hdr *recv_hdr,
        case RELAYD_STREAMS_SENT:
                ret = relay_streams_sent(recv_hdr, conn);
                break;
        case RELAYD_STREAMS_SENT:
                ret = relay_streams_sent(recv_hdr, conn);
                break;
+       case RELAYD_RESET_METADATA:
+               ret = relay_reset_metadata(recv_hdr, conn);
+               break;
        case RELAYD_UPDATE_SYNC_INFO:
        default:
                ERR("Received unknown command (%u)", be32toh(recv_hdr->cmd));
        case RELAYD_UPDATE_SYNC_INFO:
        default:
                ERR("Received unknown command (%u)", be32toh(recv_hdr->cmd));
index 1ee0c98f99dadc3516714409aa20164f44f552ff..9af6d9d4acce64b9b9855e46ed462a624573c693 100644 (file)
@@ -28,6 +28,7 @@
 #include <common/relayd/relayd.h>
 #include <common/utils.h>
 #include <common/compat/string.h>
 #include <common/relayd/relayd.h>
 #include <common/utils.h>
 #include <common/compat/string.h>
+#include <common/kernel-ctl/kernel-ctl.h>
 
 #include "channel.h"
 #include "consumer.h"
 
 #include "channel.h"
 #include "consumer.h"
@@ -39,6 +40,7 @@
 #include "utils.h"
 #include "syscall.h"
 #include "agent.h"
 #include "utils.h"
 #include "syscall.h"
 #include "agent.h"
+#include "buffer-registry.h"
 
 #include "cmd.h"
 
 
 #include "cmd.h"
 
@@ -3372,6 +3374,156 @@ error:
        return ret;
 }
 
        return ret;
 }
 
+/*
+ * Check if we can regenerate the metadata for this session.
+ * Only kernel, UST per-uid and non-live sessions are supported.
+ *
+ * Return 0 if the metadata can be generated, a LTTNG_ERR code otherwise.
+ */
+static
+int check_metadata_regenerate_support(struct ltt_session *session)
+{
+       int ret;
+
+       assert(session);
+
+       if (session->live_timer != 0) {
+               ret = LTTNG_ERR_LIVE_SESSION;
+               goto end;
+       }
+       if (!session->active) {
+               ret = LTTNG_ERR_SESSION_NOT_STARTED;
+               goto end;
+       }
+       if (session->ust_session) {
+               switch (session->ust_session->buffer_type) {
+               case LTTNG_BUFFER_PER_UID:
+                       break;
+               case LTTNG_BUFFER_PER_PID:
+                       ret = LTTNG_ERR_PER_PID_SESSION;
+                       goto end;
+               default:
+                       assert(0);
+                       ret = LTTNG_ERR_UNK;
+                       goto end;
+               }
+       }
+       if (session->consumer->type == CONSUMER_DST_NET &&
+                       session->consumer->relay_minor_version < 8) {
+               ret = LTTNG_ERR_RELAYD_VERSION_FAIL;
+               goto end;
+       }
+       ret = 0;
+
+end:
+       return ret;
+}
+
+static
+int ust_metadata_regenerate(struct ltt_ust_session *usess)
+{
+       int ret = 0;
+       struct buffer_reg_uid *uid_reg = NULL;
+       struct buffer_reg_session *session_reg = NULL;
+
+       rcu_read_lock();
+       cds_list_for_each_entry(uid_reg, &usess->buffer_reg_uid_list, lnode) {
+               struct ust_registry_session *registry;
+               struct ust_registry_channel *chan;
+               struct lttng_ht_iter iter_chan;
+
+               session_reg = uid_reg->registry;
+               registry = session_reg->reg.ust;
+
+               pthread_mutex_lock(&registry->lock);
+               registry->metadata_len_sent = 0;
+               memset(registry->metadata, 0, registry->metadata_alloc_len);
+               registry->metadata_len = 0;
+               registry->metadata_version++;
+               ret = ust_metadata_session_statedump(registry, NULL,
+                               registry->major, registry->minor);
+               if (ret) {
+                       pthread_mutex_unlock(&registry->lock);
+                       ERR("Failed to generate session metadata (err = %d)",
+                                       ret);
+                       goto end;
+               }
+               cds_lfht_for_each_entry(registry->channels->ht, &iter_chan.iter,
+                               chan, node.node) {
+                       struct ust_registry_event *event;
+                       struct lttng_ht_iter iter_event;
+
+                       ret = ust_metadata_channel_statedump(registry, chan);
+                       if (ret) {
+                               pthread_mutex_unlock(&registry->lock);
+                               ERR("Failed to generate channel metadata "
+                                               "(err = %d)", ret);
+                               goto end;
+                       }
+                       cds_lfht_for_each_entry(chan->ht->ht, &iter_event.iter,
+                                       event, node.node) {
+                               ret = ust_metadata_event_statedump(registry,
+                                               chan, event);
+                               if (ret) {
+                                       pthread_mutex_unlock(&registry->lock);
+                                       ERR("Failed to generate event metadata "
+                                                       "(err = %d)", ret);
+                                       goto end;
+                               }
+                       }
+               }
+               pthread_mutex_unlock(&registry->lock);
+       }
+
+end:
+       rcu_read_unlock();
+       return ret;
+}
+
+/*
+ * Command LTTNG_METADATA_REGENERATE from the lttng-ctl library.
+ *
+ * Ask the consumer to truncate the existing metadata file(s) and
+ * then regenerate the metadata. Live and per-pid sessions are not
+ * supported and return an error.
+ *
+ * Return 0 on success or else a LTTNG_ERR code.
+ */
+int cmd_metadata_regenerate(struct ltt_session *session)
+{
+       int ret;
+
+       assert(session);
+
+       ret = check_metadata_regenerate_support(session);
+       if (ret) {
+               goto end;
+       }
+
+       if (session->kernel_session) {
+               ret = kernctl_session_metadata_regenerate(
+                               session->kernel_session->fd);
+               if (ret < 0) {
+                       ERR("Failed to regenerate the kernel metadata");
+                       goto end;
+               }
+       }
+
+       if (session->ust_session) {
+               ret = ust_metadata_regenerate(session->ust_session);
+               if (ret < 0) {
+                       ERR("Failed to regenerate the UST metadata");
+                       goto end;
+               }
+       }
+       DBG("Cmd metadata regenerate for session %s", session->name);
+       ret = LTTNG_OK;
+
+end:
+       return ret;
+}
+
+
 /*
  * Send relayd sockets from snapshot output to consumer. Ignore request if the
  * snapshot output is *not* set with a remote destination.
 /*
  * Send relayd sockets from snapshot output to consumer. Ignore request if the
  * snapshot output is *not* set with a remote destination.
index e9c9054ea5ae0db3baf9db7fc7d6eda45f5cddee..a220e3a457c3320fd2db4f1774ea6c0edc512384 100644 (file)
@@ -110,5 +110,6 @@ int cmd_snapshot_record(struct ltt_session *session,
 
 int cmd_set_session_shm_path(struct ltt_session *session,
                const char *shm_path);
 
 int cmd_set_session_shm_path(struct ltt_session *session,
                const char *shm_path);
+int cmd_metadata_regenerate(struct ltt_session *session);
 
 #endif /* CMD_H */
 
 #endif /* CMD_H */
index 395657066847944742c6a7a86c72254c0e048022..bd019dd31da15f6953b873899f12b4dd07770c9a 100644 (file)
@@ -1259,7 +1259,7 @@ end:
  */
 int consumer_push_metadata(struct consumer_socket *socket,
                uint64_t metadata_key, char *metadata_str, size_t len,
  */
 int consumer_push_metadata(struct consumer_socket *socket,
                uint64_t metadata_key, char *metadata_str, size_t len,
-               size_t target_offset)
+               size_t target_offset, uint64_t version)
 {
        int ret;
        struct lttcomm_consumer_msg msg;
 {
        int ret;
        struct lttcomm_consumer_msg msg;
@@ -1275,6 +1275,7 @@ int consumer_push_metadata(struct consumer_socket *socket,
        msg.u.push_metadata.key = metadata_key;
        msg.u.push_metadata.target_offset = target_offset;
        msg.u.push_metadata.len = len;
        msg.u.push_metadata.key = metadata_key;
        msg.u.push_metadata.target_offset = target_offset;
        msg.u.push_metadata.len = len;
+       msg.u.push_metadata.version = version;
 
        health_code_update();
        ret = consumer_send_msg(socket, &msg);
 
        health_code_update();
        ret = consumer_send_msg(socket, &msg);
index 18d989809d4fed93823675df2c10abd338bc018c..75a40f8ae61c6a6837703902e13ad0ae8278272f 100644 (file)
@@ -282,7 +282,7 @@ int consumer_setup_metadata(struct consumer_socket *socket,
                uint64_t metadata_key);
 int consumer_push_metadata(struct consumer_socket *socket,
                uint64_t metadata_key, char *metadata_str, size_t len,
                uint64_t metadata_key);
 int consumer_push_metadata(struct consumer_socket *socket,
                uint64_t metadata_key, char *metadata_str, size_t len,
-               size_t target_offset);
+               size_t target_offset, uint64_t version);
 int consumer_flush_channel(struct consumer_socket *socket, uint64_t key);
 int consumer_get_discarded_events(uint64_t session_id, uint64_t channel_key,
                struct consumer_output *consumer, uint64_t *discarded);
 int consumer_flush_channel(struct consumer_socket *socket, uint64_t key);
 int consumer_get_discarded_events(uint64_t session_id, uint64_t channel_key,
                struct consumer_output *consumer, uint64_t *discarded);
index dbd99cc637659e242c1012cd6717f20b4e0a36d4..65f598b602fbe92830a7f62595bfd495a881634a 100644 (file)
@@ -3039,6 +3039,7 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int sock,
        case LTTNG_SNAPSHOT_RECORD:
        case LTTNG_SAVE_SESSION:
        case LTTNG_SET_SESSION_SHM_PATH:
        case LTTNG_SNAPSHOT_RECORD:
        case LTTNG_SAVE_SESSION:
        case LTTNG_SET_SESSION_SHM_PATH:
+       case LTTNG_METADATA_REGENERATE:
                need_domain = 0;
                break;
        default:
                need_domain = 0;
                break;
        default:
@@ -4143,6 +4144,11 @@ error_add_context:
                                cmd_ctx->lsm->u.set_shm_path.shm_path);
                break;
        }
                                cmd_ctx->lsm->u.set_shm_path.shm_path);
                break;
        }
+       case LTTNG_METADATA_REGENERATE:
+       {
+               ret = cmd_metadata_regenerate(cmd_ctx->session);
+               break;
+       }
        default:
                ret = LTTNG_ERR_UND;
                break;
        default:
                ret = LTTNG_ERR_UND;
                break;
index 9b634facc1422630827e5e92268839ef37b20146..9a766e4ab68e628cbdec4d9f0432ec0b83dea547 100644 (file)
@@ -551,7 +551,7 @@ ssize_t ust_app_push_metadata(struct ust_registry_session *registry,
        char *metadata_str = NULL;
        size_t len, offset, new_metadata_len_sent;
        ssize_t ret_val;
        char *metadata_str = NULL;
        size_t len, offset, new_metadata_len_sent;
        ssize_t ret_val;
-       uint64_t metadata_key;
+       uint64_t metadata_key, metadata_version;
 
        assert(registry);
        assert(socket);
 
        assert(registry);
        assert(socket);
@@ -581,6 +581,7 @@ ssize_t ust_app_push_metadata(struct ust_registry_session *registry,
        offset = registry->metadata_len_sent;
        len = registry->metadata_len - registry->metadata_len_sent;
        new_metadata_len_sent = registry->metadata_len;
        offset = registry->metadata_len_sent;
        len = registry->metadata_len - registry->metadata_len_sent;
        new_metadata_len_sent = registry->metadata_len;
+       metadata_version = registry->metadata_version;
        if (len == 0) {
                DBG3("No metadata to push for metadata key %" PRIu64,
                                registry->metadata_key);
        if (len == 0) {
                DBG3("No metadata to push for metadata key %" PRIu64,
                                registry->metadata_key);
@@ -617,7 +618,7 @@ push_data:
         * different bidirectionnal communication sockets.
         */
        ret = consumer_push_metadata(socket, metadata_key,
         * different bidirectionnal communication sockets.
         */
        ret = consumer_push_metadata(socket, metadata_key,
-                       metadata_str, len, offset);
+                       metadata_str, len, offset, metadata_version);
        pthread_mutex_lock(&registry->lock);
        if (ret < 0) {
                /*
        pthread_mutex_lock(&registry->lock);
        if (ret < 0) {
                /*
index 77b9a866657c940dde26ab19dc3a9ed748e714eb..34db29ea13462ec477f47ae4e8d55646f68a19b2 100644 (file)
@@ -68,6 +68,8 @@ struct ust_registry_session {
        size_t metadata_len, metadata_alloc_len;
        /* Length of bytes sent to the consumer. */
        size_t metadata_len_sent;
        size_t metadata_len, metadata_alloc_len;
        /* Length of bytes sent to the consumer. */
        size_t metadata_len_sent;
+       /* Current version of the metadata. */
+       uint64_t metadata_version;
 
        char root_shm_path[PATH_MAX];
        char shm_path[PATH_MAX];
 
        char root_shm_path[PATH_MAX];
        char shm_path[PATH_MAX];
index 7cf329ee24c03d59808dadffe6b9fb642fcb53e6..93a563ff56e88e70d1d0bad6d1c59bdc8e5db326 100644 (file)
@@ -17,6 +17,7 @@ lttng_SOURCES = command.h conf.c conf.h commands/start.c \
                                commands/load.c \
                                commands/track-untrack.c \
                                commands/status.c \
                                commands/load.c \
                                commands/track-untrack.c \
                                commands/status.c \
+                               commands/metadata.c \
                                utils.c utils.h lttng.c
 
 lttng_LDADD = $(top_builddir)/src/lib/lttng-ctl/liblttng-ctl.la \
                                utils.c utils.h lttng.c
 
 lttng_LDADD = $(top_builddir)/src/lib/lttng-ctl/liblttng-ctl.la \
index fc6f01c1c6db6e891aaa6e8cc5a425f192341683..451e30f793014877a00e0fc28917ebd8cd0867ba 100644 (file)
@@ -64,5 +64,6 @@ DECL_COMMAND(save);
 DECL_COMMAND(load);
 DECL_COMMAND(track);
 DECL_COMMAND(untrack);
 DECL_COMMAND(load);
 DECL_COMMAND(track);
 DECL_COMMAND(untrack);
+DECL_COMMAND(metadata);
 
 #endif /* _LTTNG_CMD_H */
 
 #endif /* _LTTNG_CMD_H */
diff --git a/src/bin/lttng/commands/metadata.c b/src/bin/lttng/commands/metadata.c
new file mode 100644 (file)
index 0000000..20c577e
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2015 - Julien Desfossez <jdesfossez@efficios.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2 only,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#define _LGPL_SOURCE
+#include <assert.h>
+#include <ctype.h>
+#include <popt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <common/mi-lttng.h>
+
+#include "../command.h"
+
+static char *opt_session_name;
+static char *session_name = NULL;
+
+static int metadata_regenerate(int argc, const char **argv);
+
+enum {
+       OPT_HELP = 1,
+       OPT_LIST_OPTIONS,
+       OPT_LIST_COMMANDS,
+};
+
+static struct poptOption long_options[] = {
+       /* { longName, shortName, argInfo, argPtr, value, descrip, argDesc, } */
+       { "help",               'h', POPT_ARG_NONE, 0, OPT_HELP, 0, 0, },
+       { "session",            's', POPT_ARG_STRING, &opt_session_name, 0, 0, 0},
+       { "list-options",       0, POPT_ARG_NONE, NULL, OPT_LIST_OPTIONS, 0, 0, },
+       { "list-commands",      0, POPT_ARG_NONE, NULL, OPT_LIST_COMMANDS},
+       { 0, 0, 0, 0, 0, 0, 0, },
+};
+
+static struct cmd_struct actions[] = {
+       { "regenerate", metadata_regenerate },
+       { NULL, NULL }  /* Array closure */
+};
+
+/*
+ * usage
+ */
+static void usage(FILE *ofp)
+{
+       fprintf(ofp, "usage: lttng metadata [OPTION] ACTION\n");
+       fprintf(ofp, "\n");
+       fprintf(ofp, "Actions:\n");
+       fprintf(ofp, "   regenerate\n");
+       fprintf(ofp, "      Regenerate and overwrite the metadata of the session.\n");
+       fprintf(ofp, "Options:\n");
+       fprintf(ofp, "  -h, --help               Show this help.\n");
+       fprintf(ofp, "      --list-options       Simple listing of options.\n");
+       fprintf(ofp, "  -s, --session NAME       Apply to session name.\n");
+       fprintf(ofp, "\n");
+}
+
+/*
+ * Count and return the number of arguments in argv.
+ */
+static int count_arguments(const char **argv)
+{
+       int i = 0;
+
+       assert(argv);
+
+       while (argv[i] != NULL) {
+               i++;
+       }
+
+       return i;
+}
+
+static int metadata_regenerate(int argc, const char **argv)
+{
+       int ret;
+
+       ret = lttng_metadata_regenerate(session_name);
+       if (ret == 0) {
+               MSG("Metadata successfully regenerated for session %s", session_name);
+       }
+       return ret;
+}
+
+static int handle_command(const char **argv)
+{
+       struct cmd_struct *cmd;
+       int ret = CMD_SUCCESS, i = 0, argc, command_ret = CMD_SUCCESS;
+
+       if (argv == NULL) {
+               usage(stderr);
+               command_ret = CMD_ERROR;
+               goto end;
+       }
+
+       argc = count_arguments(argv);
+
+       cmd = &actions[i];
+       while (cmd->func != NULL) {
+               /* Find command */
+               if (strcmp(argv[0], cmd->name) == 0) {
+                       command_ret = cmd->func(argc, argv);
+                       goto end;
+               }
+
+               cmd = &actions[i++];
+       }
+
+       ret = CMD_UNDEFINED;
+
+end:
+       /* Overwrite ret if an error occurred in cmd->func() */
+       ret = command_ret ? command_ret : ret;
+       return ret;
+}
+
+/*
+ * Metadata command handling.
+ */
+int cmd_metadata(int argc, const char **argv)
+{
+       int opt, ret = CMD_SUCCESS, command_ret = CMD_SUCCESS;
+       static poptContext pc;
+
+       if (argc < 1) {
+               usage(stderr);
+               ret = CMD_ERROR;
+               goto end;
+       }
+
+       pc = poptGetContext(NULL, argc, argv, long_options, 0);
+       poptReadDefaultConfig(pc, 0);
+
+       while ((opt = poptGetNextOpt(pc)) != -1) {
+               switch (opt) {
+               case OPT_HELP:
+                       usage(stdout);
+                       goto end;
+               case OPT_LIST_OPTIONS:
+                       list_cmd_options(stdout, long_options);
+                       goto end;
+               case OPT_LIST_COMMANDS:
+                       list_commands(actions, stdout);
+                       goto end;
+               default:
+                       usage(stderr);
+                       ret = CMD_UNDEFINED;
+                       goto end;
+               }
+       }
+
+       if (!opt_session_name) {
+               session_name = get_session_name();
+               if (session_name == NULL) {
+                       ret = CMD_ERROR;
+                       goto end;
+               }
+       } else {
+               session_name = opt_session_name;
+       }
+
+       command_ret = handle_command(poptGetArgs(pc));
+       if (command_ret) {
+               switch (-command_ret) {
+               default:
+                       ERR("%s", lttng_strerror(command_ret));
+                       break;
+               }
+       }
+
+end:
+       if (!opt_session_name) {
+               free(session_name);
+       }
+
+       /* Overwrite ret if an error occurred during handle_command() */
+       ret = command_ret ? command_ret : ret;
+
+       poptFreeContext(pc);
+       return ret;
+}
index d4dbe2697a8d2a591ed1c045267a559cee69420f..86f5b0c24b221b2459ae4f4b210d7be359d41c72 100644 (file)
@@ -84,6 +84,7 @@ static struct cmd_struct commands[] =  {
        { "load", cmd_load},
        { "track", cmd_track},
        { "untrack", cmd_untrack},
        { "load", cmd_load},
        { "track", cmd_track},
        { "untrack", cmd_untrack},
+       { "metadata", cmd_metadata},
        { NULL, NULL}   /* Array closure */
 };
 
        { NULL, NULL}   /* Array closure */
 };
 
@@ -128,6 +129,7 @@ static void usage(FILE *ofp)
        fprintf(ofp, "    load              Load session configuration\n");
        fprintf(ofp, "    track             Track specific system resources\n");
        fprintf(ofp, "    untrack           Untrack specific system resources\n");
        fprintf(ofp, "    load              Load session configuration\n");
        fprintf(ofp, "    track             Track specific system resources\n");
        fprintf(ofp, "    untrack           Untrack specific system resources\n");
+       fprintf(ofp, "    metadata          Regenerate the metadata of a session\n");
        fprintf(ofp, "\n");
        fprintf(ofp, "Each command also has its own -h, --help option.\n");
        fprintf(ofp, "\n");
        fprintf(ofp, "\n");
        fprintf(ofp, "Each command also has its own -h, --help option.\n");
        fprintf(ofp, "\n");
index 48257c299750aa0953016808766c6a634a17c65e..3211ec1e84878d7735fe2280891719fd9fd308d6 100644 (file)
@@ -70,6 +70,41 @@ end:
        return ret;
 }
 
        return ret;
 }
 
+/*
+ * Reset the metadata cache.
+ */
+static
+void metadata_cache_reset(struct consumer_metadata_cache *cache)
+{
+       memset(cache->data, 0, cache->cache_alloc_size);
+       cache->max_offset = 0;
+}
+
+/*
+ * Check if the metadata cache version changed.
+ * If it did, reset the metadata cache.
+ * The metadata cache lock MUST be held.
+ *
+ * Returns 0 on success, a negative value on error.
+ */
+static
+int metadata_cache_check_version(struct consumer_metadata_cache *cache,
+               struct lttng_consumer_channel *channel, uint64_t version)
+{
+       int ret = 0;
+
+       if (cache->version == version) {
+               goto end;
+       }
+
+       DBG("Metadata cache version update to %" PRIu64, version);
+       metadata_cache_reset(cache);
+       cache->version = version;
+
+end:
+       return ret;
+}
+
 /*
  * Write metadata to the cache, extend the cache if necessary. We support
  * overlapping updates, but they need to be contiguous. Send the
 /*
  * Write metadata to the cache, extend the cache if necessary. We support
  * overlapping updates, but they need to be contiguous. Send the
@@ -79,7 +114,8 @@ end:
  * Return 0 on success, a negative value on error.
  */
 int consumer_metadata_cache_write(struct lttng_consumer_channel *channel,
  * Return 0 on success, a negative value on error.
  */
 int consumer_metadata_cache_write(struct lttng_consumer_channel *channel,
-               unsigned int offset, unsigned int len, char *data)
+               unsigned int offset, unsigned int len, uint64_t version,
+               char *data)
 {
        int ret = 0;
        int size_ret;
 {
        int ret = 0;
        int size_ret;
@@ -89,6 +125,12 @@ int consumer_metadata_cache_write(struct lttng_consumer_channel *channel,
        assert(channel->metadata_cache);
 
        cache = channel->metadata_cache;
        assert(channel->metadata_cache);
 
        cache = channel->metadata_cache;
+
+       ret = metadata_cache_check_version(cache, channel, version);
+       if (ret < 0) {
+               goto end;
+       }
+
        DBG("Writing %u bytes from offset %u in metadata cache", len, offset);
 
        if (offset + len > cache->cache_alloc_size) {
        DBG("Writing %u bytes from offset %u in metadata cache", len, offset);
 
        if (offset + len > cache->cache_alloc_size) {
index 8ce7f30b19ee7d795af047ca35f78fbf9b7f3ecb..7dcf6976f3ada26eb4adf05beba86e710bc28752 100644 (file)
 struct consumer_metadata_cache {
        char *data;
        uint64_t cache_alloc_size;
 struct consumer_metadata_cache {
        char *data;
        uint64_t cache_alloc_size;
+       /*
+        * Current version of the metadata cache.
+        */
+       uint64_t version;
        /*
         * The upper-limit of data written inside the buffer.
         *
        /*
         * The upper-limit of data written inside the buffer.
         *
@@ -42,7 +46,8 @@ struct consumer_metadata_cache {
 };
 
 int consumer_metadata_cache_write(struct lttng_consumer_channel *channel,
 };
 
 int consumer_metadata_cache_write(struct lttng_consumer_channel *channel,
-               unsigned int offset, unsigned int len, char *data);
+               unsigned int offset, unsigned int len, uint64_t version,
+               char *data);
 int consumer_metadata_cache_allocate(struct lttng_consumer_channel *channel);
 void consumer_metadata_cache_destroy(struct lttng_consumer_channel *channel);
 int consumer_metadata_cache_flushed(struct lttng_consumer_channel *channel,
 int consumer_metadata_cache_allocate(struct lttng_consumer_channel *channel);
 void consumer_metadata_cache_destroy(struct lttng_consumer_channel *channel);
 int consumer_metadata_cache_flushed(struct lttng_consumer_channel *channel,
index 7911a5b4e8d4d0701d40e88d3ebdd6841c4061af..d57271c3a9d27222c72d95d20128a3fdd4788df6 100644 (file)
@@ -1556,6 +1556,16 @@ ssize_t lttng_consumer_on_read_subbuffer_mmap(
                if (stream->metadata_flag) {
                        /* Metadata requires the control socket. */
                        pthread_mutex_lock(&relayd->ctrl_sock_mutex);
                if (stream->metadata_flag) {
                        /* Metadata requires the control socket. */
                        pthread_mutex_lock(&relayd->ctrl_sock_mutex);
+                       if (stream->reset_metadata_flag) {
+                               ret = relayd_reset_metadata(&relayd->control_sock,
+                                               stream->relayd_stream_id,
+                                               stream->metadata_version);
+                               if (ret < 0) {
+                                       relayd_hang_up = 1;
+                                       goto write_error;
+                               }
+                               stream->reset_metadata_flag = 0;
+                       }
                        netlen += sizeof(struct lttcomm_relayd_metadata_payload);
                }
 
                        netlen += sizeof(struct lttcomm_relayd_metadata_payload);
                }
 
@@ -1579,6 +1589,15 @@ ssize_t lttng_consumer_on_read_subbuffer_mmap(
                /* No streaming, we have to set the len with the full padding */
                len += padding;
 
                /* No streaming, we have to set the len with the full padding */
                len += padding;
 
+               if (stream->metadata_flag && stream->reset_metadata_flag) {
+                       ret = utils_truncate_stream_file(stream->out_fd, 0);
+                       if (ret < 0) {
+                               ERR("Reset metadata file");
+                               goto end;
+                       }
+                       stream->reset_metadata_flag = 0;
+               }
+
                /*
                 * Check if we need to change the tracefile before writing the packet.
                 */
                /*
                 * Check if we need to change the tracefile before writing the packet.
                 */
@@ -1744,6 +1763,16 @@ ssize_t lttng_consumer_on_read_subbuffer_splice(
                         */
                        pthread_mutex_lock(&relayd->ctrl_sock_mutex);
 
                         */
                        pthread_mutex_lock(&relayd->ctrl_sock_mutex);
 
+                       if (stream->reset_metadata_flag) {
+                               ret = relayd_reset_metadata(&relayd->control_sock,
+                                               stream->relayd_stream_id,
+                                               stream->metadata_version);
+                               if (ret < 0) {
+                                       relayd_hang_up = 1;
+                                       goto write_error;
+                               }
+                               stream->reset_metadata_flag = 0;
+                       }
                        ret = write_relayd_metadata_id(splice_pipe[1], stream, relayd,
                                        padding);
                        if (ret < 0) {
                        ret = write_relayd_metadata_id(splice_pipe[1], stream, relayd,
                                        padding);
                        if (ret < 0) {
@@ -1767,6 +1796,14 @@ ssize_t lttng_consumer_on_read_subbuffer_splice(
                /* No streaming, we have to set the len with the full padding */
                len += padding;
 
                /* No streaming, we have to set the len with the full padding */
                len += padding;
 
+               if (stream->metadata_flag && stream->reset_metadata_flag) {
+                       ret = utils_truncate_stream_file(stream->out_fd, 0);
+                       if (ret < 0) {
+                               ERR("Reset metadata file");
+                               goto end;
+                       }
+                       stream->reset_metadata_flag = 0;
+               }
                /*
                 * Check if we need to change the tracefile before writing the packet.
                 */
                /*
                 * Check if we need to change the tracefile before writing the packet.
                 */
index 3af7db9136f3b011eef851397a2747ac86878ce2..59764e105c36ef086c77dec6508312e7d8b54d58 100644 (file)
@@ -292,6 +292,11 @@ struct lttng_consumer_stream {
 
        /* Identify if the stream is the metadata */
        unsigned int metadata_flag;
 
        /* Identify if the stream is the metadata */
        unsigned int metadata_flag;
+       /*
+        * Last known metadata version, reset the metadata file in case
+        * of change.
+        */
+       uint64_t metadata_version;
        /* Used when the stream is set for network streaming */
        uint64_t relayd_stream_id;
        /*
        /* Used when the stream is set for network streaming */
        uint64_t relayd_stream_id;
        /*
@@ -382,6 +387,11 @@ struct lttng_consumer_stream {
 
        /* Indicate if the stream still has some data to be read. */
        unsigned int has_data:1;
 
        /* Indicate if the stream still has some data to be read. */
        unsigned int has_data:1;
+       /*
+        * Inform the consumer or relay to reset the metadata
+        * file before writing in it (regeneration).
+        */
+       unsigned int reset_metadata_flag:1;
 };
 
 /*
 };
 
 /*
index c3fde51d4f66990a8e96355f3f764cbb4c6d97a7..9232894ff1c6ba6fca06fd92cff7dca12d40ed60 100644 (file)
@@ -170,6 +170,9 @@ static const char *error_string_array[] = {
        [ ERROR_INDEX(LTTNG_ERR_PID_NOT_TRACKED) ] = "PID not tracked",
        [ ERROR_INDEX(LTTNG_ERR_INVALID_CHANNEL_DOMAIN) ] = "Invalid channel domain",
        [ ERROR_INDEX(LTTNG_ERR_OVERFLOW) ] = "Overflow occured",
        [ ERROR_INDEX(LTTNG_ERR_PID_NOT_TRACKED) ] = "PID not tracked",
        [ ERROR_INDEX(LTTNG_ERR_INVALID_CHANNEL_DOMAIN) ] = "Invalid channel domain",
        [ ERROR_INDEX(LTTNG_ERR_OVERFLOW) ] = "Overflow occured",
+       [ ERROR_INDEX(LTTNG_ERR_SESSION_NOT_STARTED) ] = "Session not started",
+       [ ERROR_INDEX(LTTNG_ERR_LIVE_SESSION) ] = "Live sessions are not supported",
+       [ ERROR_INDEX(LTTNG_ERR_PER_PID_SESSION) ] = "Per-PID tracing sessions are not supported",
 
        /* Last element */
        [ ERROR_INDEX(LTTNG_ERR_NR) ] = "Unknown error code"
 
        /* Last element */
        [ ERROR_INDEX(LTTNG_ERR_NR) ] = "Unknown error code"
index e5c0c2e83a3930e1079ef96d056767b64893a7c7..9e3540426620f64f89cf69c8bbefa3cbe08f8962 100644 (file)
@@ -1202,6 +1202,37 @@ end:
        return ret;
 }
 
        return ret;
 }
 
+/*
+ * Check if the local version of the metadata stream matches with the version
+ * of the metadata stream in the kernel. If it was updated, set the reset flag
+ * on the stream.
+ */
+static
+int metadata_stream_check_version(int infd, struct lttng_consumer_stream *stream)
+{
+       int ret;
+       uint64_t cur_version;
+
+       ret = kernctl_get_metadata_version(infd, &cur_version);
+       if (ret < 0) {
+               ERR("Failed to get the metadata version");
+               goto end;
+       }
+
+       if (stream->metadata_version == cur_version) {
+               ret = 0;
+               goto end;
+       }
+
+       DBG("New metadata version detected");
+       stream->metadata_version = cur_version;
+       stream->reset_metadata_flag = 1;
+       ret = 0;
+
+end:
+       return ret;
+}
+
 /*
  * Consume data on a file descriptor and write it on a trace file.
  */
 /*
  * Consume data on a file descriptor and write it on a trace file.
  */
@@ -1272,6 +1303,10 @@ ssize_t lttng_kconsumer_read_subbuffer(struct lttng_consumer_stream *stream,
                }
        } else {
                write_index = 0;
                }
        } else {
                write_index = 0;
+               ret = metadata_stream_check_version(infd, stream);
+               if (ret < 0) {
+                       goto end;
+               }
        }
 
        switch (stream->chan->output) {
        }
 
        switch (stream->chan->output) {
index dd228773bc655eb985e88a6b2fe20e8c87221115..1ddf4e81dcc27931071c3d1f25fd00fbe4e719bf 100644 (file)
@@ -209,6 +209,11 @@ int kernctl_list_tracker_pids(int fd)
        return ioctl(fd, LTTNG_KERNEL_SESSION_LIST_TRACKER_PIDS);
 }
 
        return ioctl(fd, LTTNG_KERNEL_SESSION_LIST_TRACKER_PIDS);
 }
 
+int kernctl_session_metadata_regenerate(int fd)
+{
+       return ioctl(fd, LTTNG_KERNEL_SESSION_METADATA_REGEN);
+}
+
 int kernctl_create_stream(int fd)
 {
        return compat_ioctl_no_arg(fd, LTTNG_KERNEL_OLD_STREAM,
 int kernctl_create_stream(int fd)
 {
        return compat_ioctl_no_arg(fd, LTTNG_KERNEL_OLD_STREAM,
@@ -406,6 +411,12 @@ int kernctl_buffer_flush(int fd)
        return ioctl(fd, RING_BUFFER_FLUSH);
 }
 
        return ioctl(fd, RING_BUFFER_FLUSH);
 }
 
+/* returns the version of the metadata. */
+int kernctl_get_metadata_version(int fd, uint64_t *version)
+{
+       return ioctl(fd, RING_BUFFER_GET_METADATA_VERSION, version);
+}
+
 
 /* Buffer operations */
 
 
 /* Buffer operations */
 
index 929488841708206fa3016b44cd13991ea82a304e..6736937d0dbbb987bb8c4bc011e01388fef464a9 100644 (file)
@@ -65,6 +65,8 @@ int kernctl_track_pid(int fd, int pid);
 int kernctl_untrack_pid(int fd, int pid);
 int kernctl_list_tracker_pids(int fd);
 
 int kernctl_untrack_pid(int fd, int pid);
 int kernctl_list_tracker_pids(int fd);
 
+int kernctl_session_metadata_regenerate(int fd);
+
 /* Buffer operations */
 
 /* For mmap mode, readable without "get" operation */
 /* Buffer operations */
 
 /* For mmap mode, readable without "get" operation */
@@ -90,6 +92,7 @@ int kernctl_get_subbuf(int fd, unsigned long *pos);
 int kernctl_put_subbuf(int fd);
 
 int kernctl_buffer_flush(int fd);
 int kernctl_put_subbuf(int fd);
 
 int kernctl_buffer_flush(int fd);
+int kernctl_get_metadata_version(int fd, uint64_t *version);
 
 /* index */
 int kernctl_get_timestamp_begin(int fd, uint64_t *timestamp_begin);
 
 /* index */
 int kernctl_get_timestamp_begin(int fd, uint64_t *timestamp_begin);
index b37605bb19793583a53e91eed61c830b61027307..f5e866b8832213d16b3516b38e757684d23eb580 100644 (file)
@@ -49,6 +49,8 @@
 #define RING_BUFFER_GET_MMAP_READ_OFFSET    _IOR(0xF6, 0x0B, unsigned long)
 /* flush the current sub-buffer */
 #define RING_BUFFER_FLUSH                   _IO(0xF6, 0x0C)
 #define RING_BUFFER_GET_MMAP_READ_OFFSET    _IOR(0xF6, 0x0B, unsigned long)
 /* flush the current sub-buffer */
 #define RING_BUFFER_FLUSH                   _IO(0xF6, 0x0C)
+/* Get the current version of the metadata cache (after a get_next). */
+#define RING_BUFFER_GET_METADATA_VERSION    _IOR(0xF6, 0x0D, uint64_t)
 
 /* returns the timestamp begin of the current sub-buffer */
 #define LTTNG_RING_BUFFER_GET_TIMESTAMP_BEGIN     _IOR(0xF6, 0x20, uint64_t)
 
 /* returns the timestamp begin of the current sub-buffer */
 #define LTTNG_RING_BUFFER_GET_TIMESTAMP_BEGIN     _IOR(0xF6, 0x20, uint64_t)
 #define LTTNG_KERNEL_SESSION_UNTRACK_PID       \
        _IOR(0xF6, 0x59, int32_t)
 #define LTTNG_KERNEL_SESSION_LIST_TRACKER_PIDS _IO(0xF6, 0x58)
 #define LTTNG_KERNEL_SESSION_UNTRACK_PID       \
        _IOR(0xF6, 0x59, int32_t)
 #define LTTNG_KERNEL_SESSION_LIST_TRACKER_PIDS _IO(0xF6, 0x58)
+#define LTTNG_KERNEL_SESSION_METADATA_REGEN    _IO(0xF6, 0x59)
 
 /* Channel FD ioctl */
 #define LTTNG_KERNEL_STREAM                    _IO(0xF6, 0x62)
 
 /* Channel FD ioctl */
 #define LTTNG_KERNEL_STREAM                    _IO(0xF6, 0x62)
index 60b7ee84970d89dfa1125c5b46a62387dff0b1d6..acf6c38e7c54b959ad35233314801ec9c8aebf60 100644 (file)
@@ -882,3 +882,58 @@ int relayd_send_index(struct lttcomm_relayd_sock *rsock,
 error:
        return ret;
 }
 error:
        return ret;
 }
+
+/*
+ * Ask the relay to reset the metadata trace file (regeneration).
+ */
+int relayd_reset_metadata(struct lttcomm_relayd_sock *rsock,
+               uint64_t stream_id, uint64_t version)
+{
+       int ret;
+       struct lttcomm_relayd_reset_metadata msg;
+       struct lttcomm_relayd_generic_reply reply;
+
+       /* Code flow error. Safety net. */
+       assert(rsock);
+
+       /* Should have been prevented by the sessiond. */
+       if (rsock->minor < 8) {
+               ERR("Metadata regeneration unsupported before 2.8");
+               ret = -1;
+               goto error;
+       }
+
+       DBG("Relayd reset metadata stream id %" PRIu64, stream_id);
+
+       memset(&msg, 0, sizeof(msg));
+       msg.stream_id = htobe64(stream_id);
+       msg.version = htobe64(version);
+
+       /* Send command */
+       ret = send_command(rsock, RELAYD_RESET_METADATA, (void *) &msg, sizeof(msg), 0);
+       if (ret < 0) {
+               goto error;
+       }
+
+       /* Receive response */
+       ret = recv_reply(rsock, (void *) &reply, sizeof(reply));
+       if (ret < 0) {
+               goto error;
+       }
+
+       reply.ret_code = be32toh(reply.ret_code);
+
+       /* Return session id or negative ret code. */
+       if (reply.ret_code != LTTNG_OK) {
+               ret = -1;
+               ERR("Relayd reset metadata replied error %d", reply.ret_code);
+       } else {
+               /* Success */
+               ret = 0;
+       }
+
+       DBG("Relayd reset metadata stream id %" PRIu64 " successfully", stream_id);
+
+error:
+       return ret;
+}
index 9890efb870c16648cc291a40f01b011b896e5c02..f090a0db63681b3b83ec451113039b3d40dd0b75 100644 (file)
@@ -49,5 +49,7 @@ int relayd_end_data_pending(struct lttcomm_relayd_sock *sock, uint64_t id,
 int relayd_send_index(struct lttcomm_relayd_sock *rsock,
                struct ctf_packet_index *index, uint64_t relay_stream_id,
                uint64_t net_seq_num);
 int relayd_send_index(struct lttcomm_relayd_sock *rsock,
                struct ctf_packet_index *index, uint64_t relay_stream_id,
                uint64_t net_seq_num);
+int relayd_reset_metadata(struct lttcomm_relayd_sock *rsock,
+               uint64_t stream_id, uint64_t version);
 
 #endif /* _RELAYD_H */
 
 #endif /* _RELAYD_H */
index 358123273fb20a757f3da8dbca6ba999921eb532..1fc48c442b4e52b68391683fd3a3f392ce3eb038 100644 (file)
@@ -173,4 +173,13 @@ struct lttcomm_relayd_create_session_2_4 {
        uint32_t snapshot;
 } LTTNG_PACKED;
 
        uint32_t snapshot;
 } LTTNG_PACKED;
 
+/*
+ * Used to ask the relay to reset the metadata trace file (regeneration).
+ * Send the new version of the metadata (starts at 0).
+ */
+struct lttcomm_relayd_reset_metadata {
+       uint64_t stream_id;
+       uint64_t version;
+} LTTNG_PACKED;
+
 #endif /* _RELAYD_COMM */
 #endif /* _RELAYD_COMM */
index a60fc4506a9c63b42cc36300a79e08b125e69802..344ba508dc0d109608506aafc25f97f1abef927d 100644 (file)
@@ -94,6 +94,7 @@ enum lttcomm_sessiond_command {
        LTTNG_UNTRACK_PID                   = 33,
        LTTNG_LIST_TRACKER_PIDS             = 34,
        LTTNG_SET_SESSION_SHM_PATH          = 40,
        LTTNG_UNTRACK_PID                   = 33,
        LTTNG_LIST_TRACKER_PIDS             = 34,
        LTTNG_SET_SESSION_SHM_PATH          = 40,
+       LTTNG_METADATA_REGENERATE           = 41,
 };
 
 enum lttcomm_relayd_command {
 };
 
 enum lttcomm_relayd_command {
@@ -115,6 +116,8 @@ enum lttcomm_relayd_command {
        RELAYD_LIST_SESSIONS                = 15,
        /* All streams of the channel have been sent to the relayd (2.4+). */
        RELAYD_STREAMS_SENT                 = 16,
        RELAYD_LIST_SESSIONS                = 15,
        /* All streams of the channel have been sent to the relayd (2.4+). */
        RELAYD_STREAMS_SENT                 = 16,
+       /* Ask the relay to reset the metadata trace file (2.8+) */
+       RELAYD_RESET_METADATA               = 17,
 };
 
 /*
 };
 
 /*
@@ -486,6 +489,7 @@ struct lttcomm_consumer_msg {
                        uint64_t key;   /* Metadata channel key. */
                        uint64_t target_offset; /* Offset in the consumer */
                        uint64_t len;   /* Length of metadata to be received. */
                        uint64_t key;   /* Metadata channel key. */
                        uint64_t target_offset; /* Offset in the consumer */
                        uint64_t len;   /* Length of metadata to be received. */
+                       uint64_t version; /* Version of the metadata. */
                } LTTNG_PACKED push_metadata;
                struct {
                        uint64_t key;   /* Metadata channel key. */
                } LTTNG_PACKED push_metadata;
                struct {
                        uint64_t key;   /* Metadata channel key. */
@@ -517,6 +521,9 @@ struct lttcomm_consumer_msg {
                        uint64_t session_id;
                        uint64_t channel_key;
                } LTTNG_PACKED lost_packets;
                        uint64_t session_id;
                        uint64_t channel_key;
                } LTTNG_PACKED lost_packets;
+               struct {
+                       uint64_t session_id;
+               } LTTNG_PACKED metadata_regenerate;
        } u;
 } LTTNG_PACKED;
 
        } u;
 } LTTNG_PACKED;
 
index 5686fbd09fe58966cebf3f3be70bf8ec9acd339e..fe7445b7f133818353fb96b1df10ed0171db88bf 100644 (file)
@@ -1197,8 +1197,8 @@ error:
  * complete.
  */
 int lttng_ustconsumer_recv_metadata(int sock, uint64_t key, uint64_t offset,
  * complete.
  */
 int lttng_ustconsumer_recv_metadata(int sock, uint64_t key, uint64_t offset,
-               uint64_t len, struct lttng_consumer_channel *channel,
-               int timer, int wait)
+               uint64_t len, uint64_t version,
+               struct lttng_consumer_channel *channel, int timer, int wait)
 {
        int ret, ret_code = LTTCOMM_CONSUMERD_SUCCESS;
        char *metadata_str;
 {
        int ret, ret_code = LTTCOMM_CONSUMERD_SUCCESS;
        char *metadata_str;
@@ -1225,7 +1225,8 @@ int lttng_ustconsumer_recv_metadata(int sock, uint64_t key, uint64_t offset,
        health_code_update();
 
        pthread_mutex_lock(&channel->metadata_cache->lock);
        health_code_update();
 
        pthread_mutex_lock(&channel->metadata_cache->lock);
-       ret = consumer_metadata_cache_write(channel, offset, len, metadata_str);
+       ret = consumer_metadata_cache_write(channel, offset, len, version,
+                       metadata_str);
        if (ret < 0) {
                /* Unable to handle metadata. Notify session daemon. */
                ret_code = LTTCOMM_CONSUMERD_ERROR_METADATA;
        if (ret < 0) {
                /* Unable to handle metadata. Notify session daemon. */
                ret_code = LTTCOMM_CONSUMERD_ERROR_METADATA;
@@ -1587,6 +1588,7 @@ int lttng_ustconsumer_recv_cmd(struct lttng_consumer_local_data *ctx,
                uint64_t len = msg.u.push_metadata.len;
                uint64_t key = msg.u.push_metadata.key;
                uint64_t offset = msg.u.push_metadata.target_offset;
                uint64_t len = msg.u.push_metadata.len;
                uint64_t key = msg.u.push_metadata.key;
                uint64_t offset = msg.u.push_metadata.target_offset;
+               uint64_t version = msg.u.push_metadata.version;
                struct lttng_consumer_channel *channel;
 
                DBG("UST consumer push metadata key %" PRIu64 " of len %" PRIu64, key,
                struct lttng_consumer_channel *channel;
 
                DBG("UST consumer push metadata key %" PRIu64 " of len %" PRIu64, key,
@@ -1637,7 +1639,7 @@ int lttng_ustconsumer_recv_cmd(struct lttng_consumer_local_data *ctx,
                health_code_update();
 
                ret = lttng_ustconsumer_recv_metadata(sock, key, offset,
                health_code_update();
 
                ret = lttng_ustconsumer_recv_metadata(sock, key, offset,
-                               len, channel, 0, 1);
+                               len, version, channel, 0, 1);
                if (ret < 0) {
                        /* error receiving from sessiond */
                        goto error_fatal;
                if (ret < 0) {
                        /* error receiving from sessiond */
                        goto error_fatal;
@@ -2097,6 +2099,38 @@ error:
        return ret;
 }
 
        return ret;
 }
 
+static
+void metadata_stream_reset_cache(struct lttng_consumer_stream *stream,
+               struct consumer_metadata_cache *cache)
+{
+       DBG("Metadata stream update to version %" PRIu64,
+                       cache->version);
+       stream->ust_metadata_pushed = 0;
+       stream->metadata_version = cache->version;
+       stream->reset_metadata_flag = 1;
+}
+
+/*
+ * Check if the version of the metadata stream and metadata cache match.
+ * If the cache got updated, reset the metadata stream.
+ * The stream lock and metadata cache lock MUST be held.
+ * Return 0 on success, a negative value on error.
+ */
+static
+int metadata_stream_check_version(struct lttng_consumer_stream *stream)
+{
+       int ret = 0;
+       struct consumer_metadata_cache *cache = stream->chan->metadata_cache;
+
+       if (cache->version == stream->metadata_version) {
+               goto end;
+       }
+       metadata_stream_reset_cache(stream, cache);
+
+end:
+       return ret;
+}
+
 /*
  * Write up to one packet from the metadata cache to the channel.
  *
 /*
  * Write up to one packet from the metadata cache to the channel.
  *
@@ -2110,6 +2144,10 @@ int commit_one_metadata_packet(struct lttng_consumer_stream *stream)
        int ret;
 
        pthread_mutex_lock(&stream->chan->metadata_cache->lock);
        int ret;
 
        pthread_mutex_lock(&stream->chan->metadata_cache->lock);
+       ret = metadata_stream_check_version(stream);
+       if (ret < 0) {
+               goto end;
+       }
        if (stream->chan->metadata_cache->max_offset
                        == stream->ust_metadata_pushed) {
                ret = 0;
        if (stream->chan->metadata_cache->max_offset
                        == stream->ust_metadata_pushed) {
                ret = 0;
@@ -2693,7 +2731,7 @@ int lttng_ustconsumer_request_metadata(struct lttng_consumer_local_data *ctx,
        struct lttcomm_metadata_request_msg request;
        struct lttcomm_consumer_msg msg;
        enum lttcomm_return_code ret_code = LTTCOMM_CONSUMERD_SUCCESS;
        struct lttcomm_metadata_request_msg request;
        struct lttcomm_consumer_msg msg;
        enum lttcomm_return_code ret_code = LTTCOMM_CONSUMERD_SUCCESS;
-       uint64_t len, key, offset;
+       uint64_t len, key, offset, version;
        int ret;
 
        assert(channel);
        int ret;
 
        assert(channel);
@@ -2773,6 +2811,7 @@ int lttng_ustconsumer_request_metadata(struct lttng_consumer_local_data *ctx,
        len = msg.u.push_metadata.len;
        key = msg.u.push_metadata.key;
        offset = msg.u.push_metadata.target_offset;
        len = msg.u.push_metadata.len;
        key = msg.u.push_metadata.key;
        offset = msg.u.push_metadata.target_offset;
+       version = msg.u.push_metadata.version;
 
        assert(key == channel->key);
        if (len == 0) {
 
        assert(key == channel->key);
        if (len == 0) {
@@ -2795,7 +2834,7 @@ int lttng_ustconsumer_request_metadata(struct lttng_consumer_local_data *ctx,
        health_code_update();
 
        ret = lttng_ustconsumer_recv_metadata(ctx->consumer_metadata_socket,
        health_code_update();
 
        ret = lttng_ustconsumer_recv_metadata(ctx->consumer_metadata_socket,
-                       key, offset, len, channel, timer, wait);
+                       key, offset, len, version, channel, timer, wait);
        if (ret >= 0) {
                /*
                 * Only send the status msg if the sessiond is alive meaning a positive
        if (ret >= 0) {
                /*
                 * Only send the status msg if the sessiond is alive meaning a positive
index f933e90dc9ce689b8ba0560cac8b2fd0b7ccfab7..67b5bb51142a46bf79765440acb7bc371b3d0f6f 100644 (file)
@@ -57,8 +57,8 @@ void lttng_ustconsumer_close_all_metadata(struct lttng_ht *ht);
 void lttng_ustconsumer_close_metadata(struct lttng_consumer_channel *metadata);
 void lttng_ustconsumer_close_stream_wakeup(struct lttng_consumer_stream *stream);
 int lttng_ustconsumer_recv_metadata(int sock, uint64_t key, uint64_t offset,
 void lttng_ustconsumer_close_metadata(struct lttng_consumer_channel *metadata);
 void lttng_ustconsumer_close_stream_wakeup(struct lttng_consumer_stream *stream);
 int lttng_ustconsumer_recv_metadata(int sock, uint64_t key, uint64_t offset,
-               uint64_t len, struct lttng_consumer_channel *channel,
-               int timer, int wait);
+               uint64_t len, uint64_t version,
+               struct lttng_consumer_channel *channel, int timer, int wait);
 int lttng_ustconsumer_request_metadata(struct lttng_consumer_local_data *ctx,
                struct lttng_consumer_channel *channel, int timer, int wait);
 int lttng_ustconsumer_sync_metadata(struct lttng_consumer_local_data *ctx,
 int lttng_ustconsumer_request_metadata(struct lttng_consumer_local_data *ctx,
                struct lttng_consumer_channel *channel, int timer, int wait);
 int lttng_ustconsumer_sync_metadata(struct lttng_consumer_local_data *ctx,
@@ -185,8 +185,8 @@ void lttng_ustconsumer_close_stream_wakeup(struct lttng_consumer_stream *stream)
 }
 static inline
 int lttng_ustconsumer_recv_metadata(int sock, uint64_t key, uint64_t offset,
 }
 static inline
 int lttng_ustconsumer_recv_metadata(int sock, uint64_t key, uint64_t offset,
-               uint64_t len, struct lttng_consumer_channel *channel,
-               int timer)
+               uint64_t len, uint64_t version,
+               struct lttng_consumer_channel *channel, int timer)
 {
        return -ENOSYS;
 }
 {
        return -ENOSYS;
 }
index 6e772671451aec4e90e9943dd4c78eddd087c083..d71d92446ce71e14177e26005797211c4f7f0730 100644 (file)
@@ -843,7 +843,6 @@ int utils_rotate_stream_file(char *path_name, char *file_name, uint64_t size,
 {
        int ret;
 
 {
        int ret;
 
-       assert(new_count);
        assert(stream_fd);
 
        ret = close(out_fd);
        assert(stream_fd);
 
        ret = close(out_fd);
@@ -866,18 +865,22 @@ int utils_rotate_stream_file(char *path_name, char *file_name, uint64_t size,
                 * Unlinking the old file rather than overwriting it
                 * achieves this.
                 */
                 * Unlinking the old file rather than overwriting it
                 * achieves this.
                 */
-               *new_count = (*new_count + 1) % count;
-               ret = utils_unlink_stream_file(path_name, file_name,
-                               size, *new_count, uid, gid, 0);
+               if (new_count) {
+                       *new_count = (*new_count + 1) % count;
+               }
+               ret = utils_unlink_stream_file(path_name, file_name, size,
+                               new_count ? *new_count : 0, uid, gid, 0);
                if (ret < 0 && errno != ENOENT) {
                        goto error;
                }
        } else {
                if (ret < 0 && errno != ENOENT) {
                        goto error;
                }
        } else {
-               (*new_count)++;
+               if (new_count) {
+                       (*new_count)++;
+               }
        }
 
        }
 
-       ret = utils_create_stream_file(path_name, file_name, size, *new_count,
-                       uid, gid, 0);
+       ret = utils_create_stream_file(path_name, file_name, size,
+                       new_count ? *new_count : 0, uid, gid, 0);
        if (ret < 0) {
                goto error;
        }
        if (ret < 0) {
                goto error;
        }
@@ -1322,3 +1325,23 @@ end:
        }
        return ret;
 }
        }
        return ret;
 }
+
+LTTNG_HIDDEN
+int utils_truncate_stream_file(int fd, off_t length)
+{
+       int ret;
+
+       ret = ftruncate(fd, length);
+       if (ret < 0) {
+               PERROR("ftruncate");
+               goto end;
+       }
+       ret = lseek(fd, length, SEEK_SET);
+       if (ret < 0) {
+               PERROR("lseek");
+               goto end;
+       }
+
+end:
+       return ret;
+}
index 4f82ebd44ce4accbc780db25db33167ea97fbae6..5272d54a6b811ba3256a2c0f7a118a41ae7676ff 100644 (file)
@@ -58,5 +58,6 @@ char *utils_generate_optstring(const struct option *long_options,
                size_t opt_count);
 int utils_create_lock_file(const char *filepath);
 int utils_recursive_rmdir(const char *path);
                size_t opt_count);
 int utils_create_lock_file(const char *filepath);
 int utils_recursive_rmdir(const char *path);
+int utils_truncate_stream_file(int fd, off_t length);
 
 #endif /* _COMMON_UTILS_H */
 
 #endif /* _COMMON_UTILS_H */
index fe0527d425b0e32e86b75d6b415a0e2aebf5e65b..61396eb461958b179f5975f1e19f3739da13bac9 100644 (file)
@@ -2374,6 +2374,36 @@ int lttng_list_tracker_pids(struct lttng_handle *handle,
        return 0;
 }
 
        return 0;
 }
 
+/*
+ * Regenerate the metadata for a session.
+ * Return 0 on success, a negative error code on error.
+ */
+int lttng_metadata_regenerate(const char *session_name)
+{
+       int ret;
+       struct lttcomm_session_msg lsm;
+
+       if (!session_name) {
+               ret = -LTTNG_ERR_INVALID;
+               goto end;
+       }
+
+       memset(&lsm, 0, sizeof(lsm));
+       lsm.cmd_type = LTTNG_METADATA_REGENERATE;
+
+       lttng_ctl_copy_string(lsm.session.name, session_name,
+                       sizeof(lsm.session.name));
+
+       ret = lttng_ctl_ask_sessiond(&lsm, NULL);
+       if (ret < 0) {
+               goto end;
+       }
+
+       ret = 0;
+end:
+       return ret;
+}
+
 /*
  * lib constructor.
  */
 /*
  * lib constructor.
  */
This page took 0.076229 seconds and 4 git commands to generate.