Add a -l/--load option to the session-daemon
authorJérémie Galarneau <jeremie.galarneau@efficios.com>
Thu, 8 May 2014 16:02:52 +0000 (12:02 -0400)
committerDavid Goulet <dgoulet@efficios.com>
Mon, 12 May 2014 16:01:00 +0000 (12:01 -0400)
This option makes it possible to set a PATH from which session
configurations are loaded by the session daemon on startup.

Usage: lttng-sessiond -l PATH

The session configuration file found at PATH, or all those present in it
if it is a directory, will be loaded.

All sessions found under the user's session configuration directory and
under the system session configuration directory are now loaded by
default.

Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
Signed-off-by: David Goulet <dgoulet@efficios.com>
src/bin/lttng-sessiond/Makefile.am
src/bin/lttng-sessiond/load-session-thread.c [new file with mode: 0644]
src/bin/lttng-sessiond/load-session-thread.h [new file with mode: 0644]
src/bin/lttng-sessiond/lttng-sessiond.h
src/bin/lttng-sessiond/main.c

index 71df92678fe772067de250128b0771e08ac8f943..5bd62e5580b8f3e3f8478cf12d50e08db6388eac 100644 (file)
@@ -28,7 +28,8 @@ lttng_sessiond_SOURCES = utils.c utils.h \
                        testpoint.h ht-cleanup.c \
                        snapshot.c snapshot.h \
                        jul.c jul.h \
-                       save.h save.c
+                       save.h save.c \
+                       load-session-thread.h load-session-thread.c
 
 if HAVE_LIBLTTNG_UST_CTL
 lttng_sessiond_SOURCES += trace-ust.c ust-registry.c ust-app.c \
diff --git a/src/bin/lttng-sessiond/load-session-thread.c b/src/bin/lttng-sessiond/load-session-thread.c
new file mode 100644 (file)
index 0000000..845948e
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2014 - Jérémie Galarneau <jeremie.galarneau@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 _GNU_SOURCE
+#include <common/error.h>
+#include <common/config/config.h>
+
+#include "load-session-thread.h"
+#include "lttng-sessiond.h"
+
+/*
+ * Destroy the thread data previously created with the init function.
+ */
+void load_session_destroy_data(struct load_session_thread_data *data)
+{
+       if (!data) {
+               return;
+       }
+
+       if (data->sem_initialized) {
+               int ret;
+
+               ret = sem_destroy(&data->message_thread_ready);
+               if (ret) {
+                       PERROR("sem_destroy message_thread_ready");
+               }
+       }
+}
+
+/*
+ * Initialize the thread data. This MUST be called before the thread load
+ * session is created.
+ *
+ * Return 0 on success else a negative value. Note that the destroy function
+ * can be called with no or partially initialized data.
+ */
+int load_session_init_data(struct load_session_thread_data **data)
+{
+       int ret;
+       struct load_session_thread_data *_data;
+
+       assert(data);
+
+       /*
+        * Allocate memory here since this function is called from the main thread
+        * can die *before* the end of the load session thread.
+        */
+       _data = zmalloc(sizeof(*_data));
+       if (!_data) {
+               PERROR("zmalloc load session info");
+               goto error;
+       }
+       ret = sem_init(&_data->message_thread_ready, 0, 0);
+       if (ret) {
+               PERROR("sem_init message_thread_ready");
+               goto error;
+       }
+       _data->sem_initialized = 1;
+
+       *data = _data;
+       return 0;
+
+error:
+       return -1;
+}
+
+/*
+ * This thread loads session configurations once the session daemon is
+ * ready to process client messages.
+ */
+void *thread_load_session(void *data)
+{
+       int ret;
+       struct load_session_thread_data *info = data;
+
+       DBG("[load-session-thread] Load session");
+
+       ret = sem_wait(&info->message_thread_ready);
+       if (ret) {
+               PERROR("sem_wait message_thread_ready");
+               goto end;
+       }
+
+       ret = config_load_session(info->path, NULL, 0);
+       if (ret) {
+               ERR("Session load failed: %s", error_get_str(ret));
+       }
+
+end:
+       sessiond_notify_ready();
+       return NULL;
+}
diff --git a/src/bin/lttng-sessiond/load-session-thread.h b/src/bin/lttng-sessiond/load-session-thread.h
new file mode 100644 (file)
index 0000000..b7cd763
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2014 - Jérémie Galarneau <jeremie.galarneau@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 LOAD_SESSION_THREAD_H
+#define LOAD_SESSION_THREAD_H
+
+#include <semaphore.h>
+
+/* Data passed to the thread. */
+struct load_session_thread_data {
+       /* Flag if the sem_init() has been done successfully on the sem. */
+       unsigned int sem_initialized:1;
+
+       /*
+        * The load session thread waits on that semaphore which the client thread
+        * will do a sem_post() to unblock it.
+        */
+       sem_t message_thread_ready;
+
+       /* Path where the sessions are located. */
+       const char *path;
+};
+
+void *thread_load_session(void *data);
+
+int load_session_init_data(struct load_session_thread_data **data);
+void load_session_destroy_data(struct load_session_thread_data *data);
+
+#endif /* LOAD_SESSION_THREAD_H */
index 12126273c01122ab4b75c39c8c3c35b9b0a8a7e8..6ee1fe9510ef4d91c64ce6a00034c46101d723cb 100644 (file)
@@ -121,4 +121,6 @@ int sessiond_check_thread_quit_pipe(int fd, uint32_t events);
 
 void *thread_ht_cleanup(void *data);
 
+void sessiond_notify_ready(void);
+
 #endif /* _LTT_SESSIOND_H */
index 052e32e0c32ec2fb8bfe2a17e71afa0487ebf868..3a8a1b27cf5e403389ba0b962ac775ec1040e158 100644 (file)
@@ -69,6 +69,7 @@
 #include "ust-thread.h"
 #include "jul-thread.h"
 #include "save.h"
+#include "load-session-thread.h"
 
 #define CONSUMERD_FILE "lttng-consumerd"
 
@@ -80,6 +81,7 @@ static int opt_sig_parent;
 static int opt_verbose_consumer;
 static int opt_daemon, opt_background;
 static int opt_no_kernel;
+static char *opt_load_session_path;
 static pid_t ppid;          /* Parent PID for --sig-parent option */
 static pid_t child_ppid;    /* Internal parent PID use with daemonize. */
 static char *rundir;
@@ -152,6 +154,7 @@ static const struct option long_options[] = {
        { "pidfile", 1, 0, 'p' },
        { "jul-tcp-port", 1, 0, 'J' },
        { "config", 1, 0, 'f' },
+       { "load", 1, 0, 'l' },
        { NULL, 0, 0, 0 }
 };
 
@@ -200,6 +203,7 @@ static pthread_t dispatch_thread;
 static pthread_t health_thread;
 static pthread_t ht_cleanup_thread;
 static pthread_t jul_reg_thread;
+static pthread_t load_session_thread;
 
 /*
  * UST registration command queue. This queue is tied with a futex and uses a N
@@ -291,17 +295,20 @@ int is_root;                      /* Set to 1 if the daemon is running as root */
 
 const char * const config_section_name = "sessiond";
 
+/* Load session thread information to operate. */
+struct load_session_thread_data *load_info;
+
 /*
  * Whether sessiond is ready for commands/health check requests.
  * NR_LTTNG_SESSIOND_READY must match the number of calls to
- * lttng_sessiond_notify_ready().
+ * sessiond_notify_ready().
  */
-#define NR_LTTNG_SESSIOND_READY                2
+#define NR_LTTNG_SESSIOND_READY                3
 int lttng_sessiond_ready = NR_LTTNG_SESSIOND_READY;
 
 /* Notify parents that we are ready for cmd and health check */
-static
-void lttng_sessiond_notify_ready(void)
+LTTNG_HIDDEN
+void sessiond_notify_ready(void)
 {
        if (uatomic_sub_return(&lttng_sessiond_ready, 1) == 0) {
                /*
@@ -647,6 +654,15 @@ static void cleanup(void)
                free(opt_pidfile);
        }
 
+       if (opt_load_session_path) {
+               free(opt_load_session_path);
+       }
+
+       if (load_info) {
+               load_session_destroy_data(load_info);
+               free(load_info);
+       }
+
        /* <fun> */
        DBG("%c[%d;%dm*** assert failed :-) *** ==> %c[%dm%c[%d;%dm"
                        "Matthew, BEET driven development works!%c[%dm",
@@ -3723,7 +3739,7 @@ static void *thread_manage_health(void *data)
                goto error;
        }
 
-       lttng_sessiond_notify_ready();
+       sessiond_notify_ready();
 
        while (1) {
                DBG("Health check ready");
@@ -3875,7 +3891,12 @@ static void *thread_manage_clients(void *data)
                goto error;
        }
 
-       lttng_sessiond_notify_ready();
+       sessiond_notify_ready();
+       ret = sem_post(&load_info->message_thread_ready);
+       if (ret) {
+               PERROR("sem_post message_thread_ready");
+               goto error;
+       }
 
        /* This testpoint is after we signal readiness to the parent. */
        if (testpoint(sessiond_thread_manage_clients)) {
@@ -4110,6 +4131,7 @@ static void usage(void)
        fprintf(stderr, "      --no-kernel                    Disable kernel tracer\n");
        fprintf(stderr, "      --jul-tcp-port                 JUL application registration TCP port\n");
        fprintf(stderr, "  -f  --config                       Load daemon configuration file\n");
+       fprintf(stderr, "  -l  --load PATH                    Load session configuration\n");
 }
 
 /*
@@ -4229,6 +4251,13 @@ static int set_option(int opt, const char *arg, const char *optname)
                DBG3("JUL TCP port set to non default: %u", jul_tcp_port);
                break;
        }
+       case 'l':
+               opt_load_session_path = strdup(arg);
+               if (!opt_load_session_path) {
+                       perror("strdup");
+                       ret = -ENOMEM;
+               }
+               break;
        default:
                /* Unknown option or other error.
                 * Error is printed by getopt, just return */
@@ -4756,6 +4785,35 @@ error:
        return;
 }
 
+/*
+ * Start the load session thread and dettach from it so the main thread can
+ * continue. This does not return a value since whatever the outcome, the main
+ * thread will continue.
+ */
+static void start_load_session_thread(void)
+{
+       int ret;
+
+       /* Create session loading thread. */
+       ret = pthread_create(&load_session_thread, NULL, thread_load_session,
+                       load_info);
+       if (ret != 0) {
+               PERROR("pthread_create load_session_thread");
+               goto error_create;
+       }
+
+       ret = pthread_detach(load_session_thread);
+       if (ret != 0) {
+               PERROR("pthread_detach load_session_thread");
+       }
+
+       /* Everything went well so don't cleanup anything. */
+
+error_create:
+       /* The cleanup() function will destroy the load_info data. */
+       return;
+}
+
 /*
  * main
  */
@@ -5065,6 +5123,11 @@ int main(int argc, char **argv)
        /* This is to get the TCP timeout value. */
        lttcomm_inet_init();
 
+       if (load_session_init_data(&load_info) < 0) {
+               goto exit;
+       }
+       load_info->path = opt_load_session_path;
+
        /*
         * Initialize the health check subsystem. This call should set the
         * appropriate time values.
@@ -5148,7 +5211,12 @@ int main(int argc, char **argv)
                        PERROR("pthread_create kernel");
                        goto exit_kernel;
                }
+       }
 
+       /* Load possible session(s). */
+       start_load_session_thread();
+
+       if (is_root && !opt_no_kernel) {
                ret = pthread_join(kernel_thread, &status);
                if (ret != 0) {
                        PERROR("pthread_join");
This page took 0.031683 seconds and 5 git commands to generate.