ust-metadata.c ust-clock.h agent-thread.c agent-thread.h
endif
-lttng_sessiond_SOURCES += rotation-thread.c
+lttng_sessiond_SOURCES += rotation-thread.c rotate.c
# Add main.c at the end for compile order
lttng_sessiond_SOURCES += lttng-sessiond.h main.c
#include "buffer-registry.h"
#include "notification-thread.h"
#include "notification-thread-commands.h"
+#include "rotate.h"
#include "rotation-thread.h"
#include "cmd.h"
usess = session->ust_session;
ksess = session->kernel_session;
+ if (session->rotate_count > 0) {
+ session->rotate_count++;
+ /*
+ * The currently active tracing path is now the folder we
+ * want to rename.
+ */
+ snprintf(session->rotation_chunk.current_rotate_path,
+ PATH_MAX, "%s",
+ session->rotation_chunk.active_tracing_path);
+ ret = rename_complete_chunk(session,
+ session->session_last_stop_ts);
+ if (ret < 0) {
+ ERR("Renaming session on destroy");
+ }
+ }
+
/* Clean kernel session teardown */
kernel_destroy_session(ksess);
trace_ust_destroy_session(usess);
}
- if (session->rotate_count > 0) {
- session->rotate_count++;
- /*
- * The currently active tracing path is now the folder we
- * want to rename.
- */
- snprintf(session->rotation_chunk.current_rotate_path,
- PATH_MAX, "%s",
- session->rotation_chunk.active_tracing_path);
- ret = rename_complete_chunk(session,
- session->session_last_stop_ts);
- if (ret < 0) {
- ERR("Renaming session on destroy");
- }
- }
-
/*
* Must notify the kernel thread here to update it's poll set in order to
* remove the channel(s)' fd just destroyed.
}
static
-int rename_first_chunk(struct consumer_output *consumer, char *datetime)
+int rename_first_chunk(struct ltt_session *session,
+ struct consumer_output *consumer, char *datetime)
{
int ret;
char *tmppath = NULL, *tmppath2 = NULL;
* Move the per-domain folder inside the first rotation
* folder.
*/
- ret = rename(tmppath, tmppath2);
+ ret = session_rename_chunk(session, tmppath, tmppath2, 1);
if (ret < 0) {
PERROR("Rename first trace directory");
ret = -LTTNG_ERR_ROTATE_NO_DATA;
if (session->rotate_count == 0) {
timeinfo = localtime(&session->session_start_ts);
strftime(datetime, sizeof(datetime), "%Y%m%d-%H%M%S", timeinfo);
+ /* Either one of the two sessions is enough to get the root path. */
if (session->kernel_session) {
snprintf(session->rotation_chunk.current_rotate_path,
PATH_MAX, "%s/%s-",
}
}
if (session->kernel_session) {
- ret = rename_first_chunk(session->kernel_session->consumer,
+ ret = rename_first_chunk(session,
+ session->kernel_session->consumer,
datetime);
if (ret < 0) {
goto error;
}
}
if (session->ust_session) {
- ret = rename_first_chunk(session->ust_session->consumer,
+ ret = rename_first_chunk(session,
+ session->ust_session->consumer,
datetime);
if (ret < 0) {
goto error;
goto end;
-error:
- (*pending_return)->status = LTTNG_ROTATE_ERROR;
end:
return ret;
}
msg.u.rotate_channel.pathname);
/* Create directory. Ignore if exist. */
+ /* FIXME: not sure this is useful */
ret = run_as_mkdir_recursive(msg.u.rotate_channel.pathname,
S_IRWXU | S_IRWXG, uid, gid);
if (ret < 0) {
health_code_update();
return ret;
}
+
+int consumer_rotate_rename(struct consumer_socket *socket, uint64_t session_id,
+ struct consumer_output *output, char *current_path, char *new_path,
+ uint32_t create, uid_t uid, gid_t gid)
+{
+ int ret;
+ struct lttcomm_consumer_msg msg;
+
+ assert(socket);
+
+ DBG("Consumer rotate rename session %" PRIu64, session_id);
+
+ memset(&msg, 0, sizeof(msg));
+ msg.cmd_type = LTTNG_CONSUMER_ROTATE_RENAME;
+ msg.u.rotate_rename.session_id = session_id;
+ msg.u.rotate_rename.create = create;
+ msg.u.rotate_rename.uid = uid;
+ msg.u.rotate_rename.gid = gid;
+
+ if (output->type == CONSUMER_DST_NET) {
+ ERR("TODO");
+ ret = -1;
+ msg.u.rotate_rename.relayd_id = output->net_seq_index;
+ goto error;
+ } else {
+ msg.u.rotate_rename.relayd_id = (uint64_t) -1ULL;
+ snprintf(msg.u.rotate_rename.current_path, PATH_MAX, "%s",
+ current_path);
+ snprintf(msg.u.rotate_rename.new_path, PATH_MAX, "%s",
+ new_path);
+ fprintf(stderr, "rotate rename from %s to %s\n", current_path,
+ new_path);
+ }
+
+ health_code_update();
+ fprintf(stderr, "send %d to the consumer\n",
+ LTTNG_CONSUMER_ROTATE_RENAME);
+
+ ret = 0;
+ ret = consumer_send_msg(socket, &msg);
+ if (ret < 0) {
+ goto error;
+ }
+
+error:
+ health_code_update();
+ return ret;
+}
int consumer_rotate_channel(struct consumer_socket *socket, uint64_t key,
uid_t uid, gid_t gid, struct consumer_output *output,
char *tmp, uint32_t metadata);
+int consumer_rotate_rename(struct consumer_socket *socket, uint64_t session_id,
+ struct consumer_output *output, char *current_path, char *new_path,
+ uint32_t create, uid_t uid, gid_t gid);
#endif /* _CONSUMER_H */
--- /dev/null
+/*
+ * Copyright (C) 2017 - 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 <lttng/trigger/trigger.h>
+#include <common/error.h>
+#include <common/config/session-config.h>
+#include <common/defaults.h>
+#include <common/utils.h>
+#include <common/futex.h>
+#include <common/align.h>
+#include <common/time.h>
+#include <common/hashtable/utils.h>
+#include <common/kernel-ctl/kernel-ctl.h>
+#include <sys/eventfd.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <signal.h>
+#include <inttypes.h>
+
+#include "session.h"
+#include "rotate.h"
+#include "rotation-thread.h"
+#include "lttng-sessiond.h"
+#include "health-sessiond.h"
+#include "cmd.h"
+
+#include <urcu.h>
+#include <urcu/list.h>
+#include <urcu/rculfhash.h>
+
+unsigned long hash_channel_key(struct rotation_channel_key *key)
+{
+ return hash_key_u64(&key->key, lttng_ht_seed) ^ hash_key_ulong(
+ (void *) (unsigned long) key->domain, lttng_ht_seed);
+}
+
+int rotate_add_channel_pending(uint64_t key, enum lttng_domain_type domain,
+ struct ltt_session *session)
+{
+ int ret;
+ struct rotation_channel_info *new_info;
+ struct rotation_channel_key channel_key = { .key = key,
+ .domain = domain };
+
+ new_info = zmalloc(sizeof(struct rotation_channel_info));
+ if (!new_info) {
+ goto error;
+ }
+
+ new_info->channel_key.key = key;
+ new_info->channel_key.domain = domain;
+ new_info->session = session;
+ cds_lfht_node_init(&new_info->rotate_channels_ht_node);
+
+ session->nr_chan_rotate_pending++;
+ cds_lfht_add(channel_pending_rotate_ht,
+ hash_channel_key(&channel_key),
+ &new_info->rotate_channels_ht_node);
+
+ ret = 0;
+ goto end;
+
+error:
+ ret = -1;
+end:
+ return ret;
+}
+
+int session_rename_chunk(struct ltt_session *session, char *current_path,
+ char *new_path, uint32_t create)
+{
+ int ret;
+ struct consumer_socket *socket;
+ struct consumer_output *output;
+ struct lttng_ht_iter iter;
+ uid_t uid;
+ gid_t gid;
+
+ /*
+ * Either one of the sessions is enough to find the consumer_output
+ * and uid/gid.
+ */
+ if (session->kernel_session) {
+ output = session->kernel_session->consumer;
+ uid = session->kernel_session->uid;
+ gid = session->kernel_session->gid;
+ } else if (session->ust_session) {
+ output = session->ust_session->consumer;
+ uid = session->ust_session->uid;
+ gid = session->ust_session->gid;
+ } else {
+ assert(0);
+ }
+
+ if (!output || !output->socks) {
+ ERR("No consumer output found");
+ ret = -1;
+ goto end;
+ }
+
+ rcu_read_lock();
+ /*
+ * We have to iterate to find a socket, but we only need to send the
+ * rename command to one consumer, so we break after the first one.
+ */
+ cds_lfht_for_each_entry(output->socks->ht, &iter.iter, socket, node.node) {
+ pthread_mutex_lock(socket->lock);
+ ret = consumer_rotate_rename(socket, session->id, output,
+ current_path, new_path, create, uid, gid);
+ pthread_mutex_unlock(socket->lock);
+ if (ret) {
+ ERR("Consumer rename chunk");
+ ret = -1;
+ rcu_read_unlock();
+ goto end;
+ }
+ break;
+ }
+ rcu_read_unlock();
+
+ ret = 0;
+
+end:
+ return ret;
+}
+
+int rename_complete_chunk(struct ltt_session *session, time_t ts)
+{
+ struct tm *timeinfo;
+ char datetime[16];
+ char *tmppath = NULL;
+ int ret;
+
+ timeinfo = localtime(&ts);
+ strftime(datetime, sizeof(datetime), "%Y%m%d-%H%M%S", timeinfo);
+
+ tmppath = zmalloc(PATH_MAX * sizeof(char));
+ if (!tmppath) {
+ ERR("Alloc tmppath");
+ ret = -1;
+ goto end;
+ }
+
+ snprintf(tmppath, PATH_MAX, "%s%s-%" PRIu64,
+ session->rotation_chunk.current_rotate_path,
+ datetime, session->rotate_count);
+
+ fprintf(stderr, "rename %s to %s\n", session->rotation_chunk.current_rotate_path,
+ tmppath);
+
+ ret = session_rename_chunk(session,
+ session->rotation_chunk.current_rotate_path,
+ tmppath, 0);
+ if (ret) {
+ ERR("Session rename");
+ ret = -1;
+ goto end;
+ }
+
+ /*
+ * Store the path where the readable chunk is. This path is valid
+ * and can be queried by the client with rotate_pending until the next
+ * rotation is started.
+ */
+ snprintf(session->rotation_chunk.current_rotate_path, PATH_MAX,
+ "%s", tmppath);
+ session->rotate_pending = 0;
+
+end:
+ free(tmppath);
+ return ret;
+}
+
--- /dev/null
+/*
+ * Copyright (C) 2017 - 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.
+ */
+
+#ifndef ROTATE_H
+#define ROTATE_H
+
+#include "rotation-thread.h"
+
+extern struct cds_lfht *channel_pending_rotate_ht;
+
+unsigned long hash_channel_key(struct rotation_channel_key *key);
+
+int rotate_add_channel_pending(uint64_t key, enum lttng_domain_type domain,
+ struct ltt_session *session);
+
+int session_rename_chunk(struct ltt_session *session, char *current_path,
+ char *new_path, uint32_t create);
+
+int rename_complete_chunk(struct ltt_session *session, time_t ts);
+
+#endif /* ROTATE_H */
#include "rotation-thread.h"
#include "lttng-sessiond.h"
#include "health-sessiond.h"
+#include "rotate.h"
#include "cmd.h"
#include <urcu.h>
struct cds_lfht *channel_pending_rotate_ht;
-static
-unsigned long hash_channel_key(struct rotation_channel_key *key)
-{
- return hash_key_u64(&key->key, lttng_ht_seed) ^ hash_key_ulong(
- (void *) (unsigned long) key->domain, lttng_ht_seed);
-}
-
static
void channel_rotation_info_destroy(struct rotation_channel_info *channel_info)
{
free(channel_info);
}
-int rotate_add_channel_pending(uint64_t key, enum lttng_domain_type domain,
- struct ltt_session *session)
-{
- int ret;
- struct rotation_channel_info *new_info;
- struct rotation_channel_key channel_key = { .key = key,
- .domain = domain };
-
- new_info = zmalloc(sizeof(struct rotation_channel_info));
- if (!new_info) {
- goto error;
- }
-
- new_info->channel_key.key = key;
- new_info->channel_key.domain = domain;
- new_info->session = session;
- cds_lfht_node_init(&new_info->rotate_channels_ht_node);
-
- session->nr_chan_rotate_pending++;
- cds_lfht_add(channel_pending_rotate_ht,
- hash_channel_key(&channel_key),
- &new_info->rotate_channels_ht_node);
-
- ret = 0;
- goto end;
-
-error:
- ret = -1;
-end:
- return ret;
-}
-
static
int match_channel_info(struct cds_lfht_node *node, const void *key)
{
return 0;
}
-int rename_complete_chunk(struct ltt_session *session, time_t ts)
-{
- struct tm *timeinfo;
- char datetime[16];
- char *tmppath = NULL;
- int ret;
-
- timeinfo = localtime(&ts);
- strftime(datetime, sizeof(datetime), "%Y%m%d-%H%M%S", timeinfo);
-
- tmppath = zmalloc(PATH_MAX * sizeof(char));
- if (!tmppath) {
- ERR("Alloc tmppath");
- ret = -1;
- goto end;
- }
-
- snprintf(tmppath, PATH_MAX, "%s%s-%" PRIu64,
- session->rotation_chunk.current_rotate_path,
- datetime, session->rotate_count);
-
- fprintf(stderr, "rename %s to %s\n", session->rotation_chunk.current_rotate_path,
- tmppath);
- ret = rename(session->rotation_chunk.current_rotate_path,
- tmppath);
- if (ret < 0) {
- PERROR("Rename completed rotation chunk");
- goto end;
- }
- /*
- * Store the path where the readable chunk is. This path is valid
- * and can be queried by the client with rotate_pending until the next
- * rotation is started.
- */
- snprintf(session->rotation_chunk.current_rotate_path, PATH_MAX,
- "%s", tmppath);
- session->rotate_pending = 0;
-
-end:
- free(tmppath);
- return ret;
-}
-
static
int handle_channel_rotation_pipe(int fd, uint32_t revents,
struct rotation_thread_handle *handle,
#include <common/hashtable/hashtable.h>
#include <pthread.h>
-struct cds_lfht *channel_pending_rotate_ht;
-
struct rotation_channel_key {
uint64_t key;
enum lttng_domain_type domain;
int rotate_add_channel_pending(uint64_t key, enum lttng_domain_type domain,
struct ltt_session *session);
-void rotate_del_channel_pending(uint64_t key, enum lttng_domain_type domain);
void *thread_rotation(void *data);
-/* FIXME: TMP */
-int rename_complete_chunk(struct ltt_session *session, time_t ts);
-
#endif /* ROTATION_THREAD_H */
rcu_read_unlock();
return ret;
}
+
+int lttng_consumer_rotate_rename(char *current_path, char *new_path,
+ uint32_t create, uid_t uid, gid_t gid)
+{
+ int ret;
+
+ if (create) {
+ ret = utils_mkdir_recursive(new_path, S_IRWXU | S_IRWXG,
+ uid, gid);
+ if (ret < 0) {
+ ERR("Create directory on rotate");
+ goto end;
+ }
+
+ }
+ ret = rename(current_path, new_path);
+ if (ret < 0) {
+ PERROR("Rename completed rotation chunk");
+ }
+
+end:
+ return ret;
+}
LTTNG_CONSUMER_SET_CHANNEL_MONITOR_PIPE,
LTTNG_CONSUMER_SET_CHANNEL_ROTATE_PIPE,
LTTNG_CONSUMER_ROTATE_CHANNEL,
+ LTTNG_CONSUMER_ROTATE_RENAME,
};
/* State of each fd in consumer */
struct lttng_consumer_stream *stream);
int lttng_consumer_rotate_ready_streams(uint64_t key,
struct lttng_consumer_local_data *ctx);
+int lttng_consumer_rotate_rename(char *current_path, char *new_path,
+ uint32_t create, uid_t uid, gid_t gid);
#endif /* LIB_CONSUMER_H */
}
break;
}
+ case LTTNG_CONSUMER_ROTATE_RENAME:
+ {
+ DBG("Consumer rename session %" PRIu64 " after rotation",
+ msg.u.rotate_rename.session_id);
+ ret = lttng_consumer_rotate_rename(msg.u.rotate_rename.current_path,
+ msg.u.rotate_rename.new_path,
+ msg.u.rotate_rename.create,
+ msg.u.rotate_rename.uid,
+ msg.u.rotate_rename.gid);
+ if (ret < 0) {
+ ERR("Rotate rename failed");
+ ret_code = LTTCOMM_CONSUMERD_CHAN_NOT_FOUND;
+ }
+
+ health_code_update();
+
+ ret = consumer_send_status_msg(sock, ret_code);
+ if (ret < 0) {
+ /* Somehow, the session daemon is not responding anymore. */
+ goto end_nosignal;
+ }
+
+ }
default:
goto end_nosignal;
}
uint64_t relayd_id; /* Relayd id if apply. */
uint64_t key;
} LTTNG_PACKED rotate_channel;
+ struct {
+ char current_path[PATH_MAX];
+ char new_path[PATH_MAX];
+ uint64_t relayd_id; /* Relayd id if apply. */
+ uint64_t session_id;
+ uint32_t create; /* Create new_path before move. */
+ uint32_t uid;
+ uint32_t gid;
+ } LTTNG_PACKED rotate_rename;
} u;
} LTTNG_PACKED;
}
break;
}
+ case LTTNG_CONSUMER_ROTATE_RENAME:
+ {
+ DBG("Consumer rename session %" PRIu64 " after rotation",
+ msg.u.rotate_rename.session_id);
+ ret = lttng_consumer_rotate_rename(msg.u.rotate_rename.current_path,
+ msg.u.rotate_rename.new_path,
+ msg.u.rotate_rename.create,
+ msg.u.rotate_rename.uid,
+ msg.u.rotate_rename.gid);
+ if (ret < 0) {
+ ERR("Rotate rename failed");
+ ret_code = LTTCOMM_CONSUMERD_CHAN_NOT_FOUND;
+ }
+
+ health_code_update();
+
+ ret = consumer_send_status_msg(sock, ret_code);
+ if (ret < 0) {
+ /* Somehow, the session daemon is not responding anymore. */
+ goto end_nosignal;
+ }
+
+ }
default:
break;
}