Add live timer and tracefile count/size to list
[lttng-tools.git] / src / bin / lttng-sessiond / cmd.c
index 6709926572c00203dbe34242d6ff3367c9b6d077..eb516d3b10c7cbf724c7f7b4c4090db24a510274 100644 (file)
@@ -166,6 +166,8 @@ static void list_lttng_channels(int domain, struct ltt_session *session,
                        channels[i].attr.read_timer_interval =
                                uchan->attr.read_timer_interval;
                        channels[i].enabled = uchan->enabled;
+                       channels[i].attr.tracefile_size = uchan->tracefile_size;
+                       channels[i].attr.tracefile_count = uchan->tracefile_count;
                        switch (uchan->attr.output) {
                        case LTTNG_UST_MMAP:
                        default:
@@ -182,6 +184,55 @@ static void list_lttng_channels(int domain, struct ltt_session *session,
        }
 }
 
+/*
+ * Create a list of JUL domain events.
+ *
+ * Return number of events in list on success or else a negative value.
+ */
+static int list_lttng_jul_events(struct jul_domain *dom,
+               struct lttng_event **events)
+{
+       int i = 0, ret = 0;
+       unsigned int nb_event = 0;
+       struct jul_event *event;
+       struct lttng_event *tmp_events;
+       struct lttng_ht_iter iter;
+
+       assert(dom);
+       assert(events);
+
+       DBG3("Listing JUL events");
+
+       nb_event = lttng_ht_get_count(dom->events);
+       if (nb_event == 0) {
+               ret = nb_event;
+               goto error;
+       }
+
+       tmp_events = zmalloc(nb_event * sizeof(*tmp_events));
+       if (!tmp_events) {
+               PERROR("zmalloc JUL events session");
+               ret = -LTTNG_ERR_FATAL;
+               goto error;
+       }
+
+       rcu_read_lock();
+       cds_lfht_for_each_entry(dom->events->ht, &iter.iter, event, node.node) {
+               strncpy(tmp_events[i].name, event->name, sizeof(tmp_events[i].name));
+               tmp_events[i].name[sizeof(tmp_events[i].name) - 1] = '\0';
+               tmp_events[i].enabled = event->enabled;
+               i++;
+       }
+       rcu_read_unlock();
+
+       *events = tmp_events;
+       ret = nb_event;
+
+error:
+       assert(nb_event == i);
+       return ret;
+}
+
 /*
  * Create a list of ust global domain events.
  */
@@ -256,6 +307,9 @@ static int list_lttng_ust_global_events(char *channel_name,
                if (uevent->filter) {
                        tmp[i].filter = 1;
                }
+               if (uevent->exclusion) {
+                       tmp[i].exclusion = 1;
+               }
                i++;
        }
 
@@ -406,6 +460,7 @@ static int add_uri_to_consumer(struct consumer_output *consumer,
                         * URI was the same in the consumer so we do not append the subdir
                         * again so to not duplicate output dir.
                         */
+                       ret = LTTNG_OK;
                        goto error;
                }
 
@@ -770,7 +825,7 @@ static int start_kernel_session(struct ltt_kernel_session *ksess, int wpipe)
        /* Quiescent wait after starting trace */
        kernel_wait_quiescent(kernel_tracer_fd);
 
-       ksess->started = 1;
+       ksess->active = 1;
 
        ret = LTTNG_OK;
 
@@ -863,7 +918,7 @@ int cmd_enable_channel(struct ltt_session *session,
         * Don't try to enable a channel if the session has been started at
         * some point in time before. The tracer does not allow it.
         */
-       if (session->started) {
+       if (session->has_been_started) {
                ret = LTTNG_ERR_TRACE_ALREADY_STARTED;
                goto error;
        }
@@ -886,15 +941,6 @@ int cmd_enable_channel(struct ltt_session *session,
                kchan = trace_kernel_get_channel_by_name(attr->name,
                                session->kernel_session);
                if (kchan == NULL) {
-                       /*
-                        * Don't try to create a channel if the session
-                        * has been started at some point in time
-                        * before. The tracer does not allow it.
-                        */
-                       if (session->started) {
-                               ret = LTTNG_ERR_TRACE_ALREADY_STARTED;
-                               goto error;
-                       }
                        ret = channel_kernel_create(session->kernel_session, attr, wpipe);
                        if (attr->name[0] != '\0') {
                                session->kernel_session->has_non_default_channel = 1;
@@ -918,15 +964,6 @@ int cmd_enable_channel(struct ltt_session *session,
 
                uchan = trace_ust_find_channel_by_name(chan_ht, attr->name);
                if (uchan == NULL) {
-                       /*
-                        * Don't try to create a channel if the session
-                        * has been started at some point in time
-                        * before. The tracer does not allow it.
-                        */
-                       if (session->started) {
-                               ret = LTTNG_ERR_TRACE_ALREADY_STARTED;
-                               goto error;
-                       }
                        ret = channel_ust_create(usess, attr, domain->buf_type);
                        if (attr->name[0] != '\0') {
                                usess->has_non_default_channel = 1;
@@ -1022,6 +1059,19 @@ int cmd_disable_event(struct ltt_session *session, int domain,
                                channel_name);
                break;
        }
+       case LTTNG_DOMAIN_JUL:
+       {
+               struct ltt_ust_session *usess = session->ust_session;
+
+               assert(usess);
+
+               ret = event_jul_disable(usess, event_name);
+               if (ret != LTTNG_OK) {
+                       goto error;
+               }
+
+               break;
+       }
 #if 0
        case LTTNG_DOMAIN_UST_EXEC_NAME:
        case LTTNG_DOMAIN_UST_PID:
@@ -1112,6 +1162,19 @@ int cmd_disable_event_all(struct ltt_session *session, int domain,
 
                DBG3("Disable all UST events in channel %s completed", channel_name);
 
+               break;
+       }
+       case LTTNG_DOMAIN_JUL:
+       {
+               struct ltt_ust_session *usess = session->ust_session;
+
+               assert(usess);
+
+               ret = event_jul_disable_all(usess);
+               if (ret != LTTNG_OK) {
+                       goto error;
+               }
+
                break;
        }
 #if 0
@@ -1231,7 +1294,10 @@ error:
  */
 int cmd_enable_event(struct ltt_session *session, struct lttng_domain *domain,
                char *channel_name, struct lttng_event *event,
-               struct lttng_filter_bytecode *filter, int wpipe)
+               char *filter_expression,
+               struct lttng_filter_bytecode *filter,
+               struct lttng_event_exclusion *exclusion,
+               int wpipe)
 {
        int ret, channel_created = 0;
        struct lttng_channel *attr;
@@ -1344,10 +1410,58 @@ int cmd_enable_event(struct ltt_session *session, struct lttng_domain *domain,
                }
 
                /* At this point, the session and channel exist on the tracer */
-               ret = event_ust_enable_tracepoint(usess, uchan, event, filter);
+               ret = event_ust_enable_tracepoint(usess, uchan, event,
+                               filter_expression, filter, exclusion);
+               if (ret != LTTNG_OK) {
+                       goto error;
+               }
+               break;
+       }
+       case LTTNG_DOMAIN_JUL:
+       {
+               struct lttng_event uevent;
+               struct lttng_domain tmp_dom;
+               struct ltt_ust_session *usess = session->ust_session;
+
+               assert(usess);
+
+               /* Create the default JUL tracepoint. */
+               memset(&uevent, 0, sizeof(uevent));
+               uevent.type = LTTNG_EVENT_TRACEPOINT;
+               uevent.loglevel_type = LTTNG_EVENT_LOGLEVEL_ALL;
+               if (is_root) {
+                       strncpy(uevent.name, DEFAULT_SYS_JUL_EVENT_NAME,
+                                       sizeof(uevent.name));
+               } else {
+                       strncpy(uevent.name, DEFAULT_USER_JUL_EVENT_NAME,
+                                       sizeof(uevent.name));
+               }
+               uevent.name[sizeof(uevent.name) - 1] = '\0';
+
+               /*
+                * The domain type is changed because we are about to enable the
+                * default channel and event for the JUL domain that are hardcoded.
+                * This happens in the UST domain.
+                */
+               memcpy(&tmp_dom, domain, sizeof(tmp_dom));
+               tmp_dom.type = LTTNG_DOMAIN_UST;
+
+               ret = cmd_enable_event(session, &tmp_dom, DEFAULT_JUL_CHANNEL_NAME,
+                       &uevent, filter_expression, filter, NULL, wpipe);
+               if (ret != LTTNG_OK && ret != LTTNG_ERR_UST_EVENT_ENABLED) {
+                       goto error;
+               }
+
+               /* The wild card * means that everything should be enabled. */
+               if (strncmp(event->name, "*", 1) == 0 && strlen(event->name) == 1) {
+                       ret = event_jul_enable_all(usess, event);
+               } else {
+                       ret = event_jul_enable(usess, event);
+               }
                if (ret != LTTNG_OK) {
                        goto error;
                }
+
                break;
        }
 #if 0
@@ -1372,6 +1486,7 @@ error:
  */
 int cmd_enable_event_all(struct ltt_session *session,
                struct lttng_domain *domain, char *channel_name, int event_type,
+               char *filter_expression,
                struct lttng_filter_bytecode *filter, int wpipe)
 {
        int ret;
@@ -1505,7 +1620,8 @@ int cmd_enable_event_all(struct ltt_session *session,
                switch (event_type) {
                case LTTNG_EVENT_ALL:
                case LTTNG_EVENT_TRACEPOINT:
-                       ret = event_ust_enable_all_tracepoints(usess, uchan, filter);
+                       ret = event_ust_enable_all_tracepoints(usess, uchan,
+                               filter_expression, filter);
                        if (ret != LTTNG_OK) {
                                goto error;
                        }
@@ -1520,6 +1636,52 @@ int cmd_enable_event_all(struct ltt_session *session,
                        goto error;
                }
 
+               break;
+       }
+       case LTTNG_DOMAIN_JUL:
+       {
+               struct lttng_event uevent, event;
+               struct lttng_domain tmp_dom;
+               struct ltt_ust_session *usess = session->ust_session;
+
+               assert(usess);
+
+               /* Create the default JUL tracepoint. */
+               uevent.type = LTTNG_EVENT_TRACEPOINT;
+               uevent.loglevel_type = LTTNG_EVENT_LOGLEVEL_ALL;
+               if (is_root) {
+                       strncpy(uevent.name, DEFAULT_SYS_JUL_EVENT_NAME,
+                                       sizeof(uevent.name));
+               } else {
+                       strncpy(uevent.name, DEFAULT_USER_JUL_EVENT_NAME,
+                                       sizeof(uevent.name));
+               }
+               uevent.name[sizeof(uevent.name) - 1] = '\0';
+
+               /*
+                * The domain type is changed because we are about to enable the
+                * default channel and event for the JUL domain that are hardcoded.
+                * This happens in the UST domain.
+                */
+               memcpy(&tmp_dom, domain, sizeof(tmp_dom));
+               tmp_dom.type = LTTNG_DOMAIN_UST;
+
+               ret = cmd_enable_event(session, &tmp_dom, DEFAULT_JUL_CHANNEL_NAME,
+                       &uevent, NULL, NULL, NULL, wpipe);
+               if (ret != LTTNG_OK && ret != LTTNG_ERR_UST_EVENT_ENABLED) {
+                       goto error;
+               }
+
+               event.loglevel = LTTNG_LOGLEVEL_JUL_ALL;
+               event.loglevel_type = LTTNG_EVENT_LOGLEVEL_ALL;
+               strncpy(event.name, "*", sizeof(event.name));
+               event.name[sizeof(event.name) - 1] = '\0';
+
+               ret = event_jul_enable_all(usess, &event);
+               if (ret != LTTNG_OK) {
+                       goto error;
+               }
+
                break;
        }
 #if 0
@@ -1563,6 +1725,13 @@ ssize_t cmd_list_tracepoints(int domain, struct lttng_event **events)
                        goto error;
                }
                break;
+       case LTTNG_DOMAIN_JUL:
+               nb_events = jul_list_events(events);
+               if (nb_events < 0) {
+                       ret = LTTNG_ERR_UST_LIST_FAIL;
+                       goto error;
+               }
+               break;
        default:
                ret = LTTNG_ERR_UND;
                goto error;
@@ -1611,6 +1780,7 @@ error:
 int cmd_start_trace(struct ltt_session *session)
 {
        int ret;
+       unsigned long nb_chan = 0;
        struct ltt_kernel_session *ksession;
        struct ltt_ust_session *usess;
 
@@ -1620,13 +1790,26 @@ int cmd_start_trace(struct ltt_session *session)
        ksession = session->kernel_session;
        usess = session->ust_session;
 
-       if (session->enabled) {
-               /* Already started. */
+       /* Is the session already started? */
+       if (session->active) {
                ret = LTTNG_ERR_TRACE_ALREADY_STARTED;
                goto error;
        }
 
-       session->enabled = 1;
+       /*
+        * Starting a session without channel is useless since after that it's not
+        * possible to enable channel thus inform the client.
+        */
+       if (usess && usess->domain_global.channels) {
+               nb_chan += lttng_ht_get_count(usess->domain_global.channels);
+       }
+       if (ksession) {
+               nb_chan += ksession->channel_count;
+       }
+       if (!nb_chan) {
+               ret = LTTNG_ERR_NO_CHANNEL;
+               goto error;
+       }
 
        /* Kernel tracing */
        if (ksession != NULL) {
@@ -1638,7 +1821,11 @@ int cmd_start_trace(struct ltt_session *session)
 
        /* Flag session that trace should start automatically */
        if (usess) {
-               usess->start_trace = 1;
+               /*
+                * Even though the start trace might fail, flag this session active so
+                * other application coming in are started by default.
+                */
+               usess->active = 1;
 
                ret = ust_app_start_trace_all(usess);
                if (ret < 0) {
@@ -1647,7 +1834,9 @@ int cmd_start_trace(struct ltt_session *session)
                }
        }
 
-       session->started = 1;
+       /* Flag this after a successful start. */
+       session->has_been_started = 1;
+       session->active = 1;
 
        ret = LTTNG_OK;
 
@@ -1671,15 +1860,14 @@ int cmd_stop_trace(struct ltt_session *session)
        ksession = session->kernel_session;
        usess = session->ust_session;
 
-       if (!session->enabled) {
+       /* Session is not active. Skip everythong and inform the client. */
+       if (!session->active) {
                ret = LTTNG_ERR_TRACE_ALREADY_STOPPED;
                goto error;
        }
 
-       session->enabled = 0;
-
        /* Kernel tracer */
-       if (ksession && ksession->started) {
+       if (ksession && ksession->active) {
                DBG("Stop kernel tracing");
 
                /* Flush metadata if exist */
@@ -1706,11 +1894,15 @@ int cmd_stop_trace(struct ltt_session *session)
 
                kernel_wait_quiescent(kernel_tracer_fd);
 
-               ksession->started = 0;
+               ksession->active = 0;
        }
 
-       if (usess && usess->start_trace) {
-               usess->start_trace = 0;
+       if (usess && usess->active) {
+               /*
+                * Even though the stop trace might fail, flag this session inactive so
+                * other application coming in are not started by default.
+                */
+               usess->active = 0;
 
                ret = ust_app_stop_trace_all(usess);
                if (ret < 0) {
@@ -1719,6 +1911,8 @@ int cmd_stop_trace(struct ltt_session *session)
                }
        }
 
+       /* Flag inactive after a successful stop. */
+       session->active = 0;
        ret = LTTNG_OK;
 
 error:
@@ -1740,8 +1934,8 @@ int cmd_set_consumer_uri(int domain, struct ltt_session *session,
        assert(uris);
        assert(nb_uri > 0);
 
-       /* Can't enable consumer after session started. */
-       if (session->enabled) {
+       /* Can't set consumer URI if the session is active. */
+       if (session->active) {
                ret = LTTNG_ERR_TRACE_ALREADY_STARTED;
                goto error;
        }
@@ -1985,7 +2179,14 @@ int cmd_calibrate(int domain, struct lttng_calibrate *calibrate)
        {
                struct lttng_kernel_calibrate kcalibrate;
 
-               kcalibrate.type = calibrate->type;
+               switch (calibrate->type) {
+               case LTTNG_CALIBRATE_FUNCTION:
+               default:
+                       /* Default and only possible calibrate option. */
+                       kcalibrate.type = LTTNG_KERNEL_CALIBRATE_KRETPROBE;
+                       break;
+               }
+
                ret = kernel_calibrate(kernel_tracer_fd, &kcalibrate);
                if (ret < 0) {
                        ret = LTTNG_ERR_KERN_ENABLE_FAIL;
@@ -1997,7 +2198,14 @@ int cmd_calibrate(int domain, struct lttng_calibrate *calibrate)
        {
                struct lttng_ust_calibrate ucalibrate;
 
-               ucalibrate.type = calibrate->type;
+               switch (calibrate->type) {
+               case LTTNG_CALIBRATE_FUNCTION:
+               default:
+                       /* Default and only possible calibrate option. */
+                       ucalibrate.type = LTTNG_UST_CALIBRATE_TRACEPOINT;
+                       break;
+               }
+
                ret = ust_app_calibrate_glb(&ucalibrate);
                if (ret < 0) {
                        ret = LTTNG_ERR_UST_CALIBRATE_FAIL;
@@ -2111,6 +2319,10 @@ ssize_t cmd_list_domains(struct ltt_session *session,
        if (session->ust_session != NULL) {
                DBG3("Listing domains found UST global domain");
                nb_dom++;
+
+               if (session->ust_session->domain_jul.being_used) {
+                       nb_dom++;
+               }
        }
 
        *domains = zmalloc(nb_dom * sizeof(struct lttng_domain));
@@ -2128,6 +2340,12 @@ ssize_t cmd_list_domains(struct ltt_session *session,
                (*domains)[index].type = LTTNG_DOMAIN_UST;
                (*domains)[index].buf_type = session->ust_session->buffer_type;
                index++;
+
+               if (session->ust_session->domain_jul.being_used) {
+                       (*domains)[index].type = LTTNG_DOMAIN_JUL;
+                       (*domains)[index].buf_type = session->ust_session->buffer_type;
+                       index++;
+               }
        }
 
        return nb_dom;
@@ -2218,6 +2436,12 @@ ssize_t cmd_list_events(int domain, struct ltt_session *session,
                }
                break;
        }
+       case LTTNG_DOMAIN_JUL:
+               if (session->ust_session) {
+                       nb_event = list_lttng_jul_events(
+                                       &session->ust_session->domain_jul, events);
+               }
+               break;
        default:
                ret = LTTNG_ERR_UND;
                goto error;
@@ -2278,8 +2502,9 @@ void cmd_list_lttng_sessions(struct lttng_session *sessions, uid_t uid,
 
                strncpy(sessions[i].name, session->name, NAME_MAX);
                sessions[i].name[NAME_MAX - 1] = '\0';
-               sessions[i].enabled = session->enabled;
+               sessions[i].enabled = session->active;
                sessions[i].snapshot_mode = session->snapshot_mode;
+               sessions[i].live_timer_interval = session->live_timer;
                i++;
        }
 }
@@ -2297,9 +2522,24 @@ int cmd_data_pending(struct ltt_session *session)
        assert(session);
 
        /* Session MUST be stopped to ask for data availability. */
-       if (session->enabled) {
+       if (session->active) {
                ret = LTTNG_ERR_SESSION_STARTED;
                goto error;
+       } else {
+               /*
+                * If stopped, just make sure we've started before else the above call
+                * will always send that there is data pending.
+                *
+                * The consumer assumes that when the data pending command is received,
+                * the trace has been started before or else no output data is written
+                * by the streams which is a condition for data pending. So, this is
+                * *VERY* important that we don't ask the consumer before a start
+                * trace.
+                */
+               if (!session->has_been_started) {
+                       ret = 0;
+                       goto error;
+               }
        }
 
        if (ksess && ksess->consumer) {
@@ -2565,7 +2805,7 @@ error:
 /*
  * Record a kernel snapshot.
  *
- * Return 0 on success or a LTTNG_ERR code.
+ * Return LTTNG_OK on success or a LTTNG_ERR code.
  */
 static int record_kernel_snapshot(struct ltt_kernel_session *ksess,
                struct snapshot_output *output, struct ltt_session *session,
@@ -2654,12 +2894,17 @@ static int record_ust_snapshot(struct ltt_ust_session *usess,
 
        ret = ust_app_snapshot_record(usess, output, wait, nb_streams);
        if (ret < 0) {
-               if (ret == -EINVAL) {
+               switch (-ret) {
+               case EINVAL:
                        ret = LTTNG_ERR_INVALID;
-                       goto error_snapshot;
+                       break;
+               case ENODATA:
+                       ret = LTTNG_ERR_SNAPSHOT_NODATA;
+                       break;
+               default:
+                       ret = LTTNG_ERR_SNAPSHOT_FAIL;
+                       break;
                }
-
-               ret = LTTNG_ERR_SNAPSHOT_FAIL;
                goto error_snapshot;
        }
 
@@ -2725,7 +2970,7 @@ int cmd_snapshot_record(struct ltt_session *session,
        }
 
        /* The session needs to be started at least once. */
-       if (!session->started) {
+       if (!session->has_been_started) {
                ret = LTTNG_ERR_START_SESSION_ONCE;
                goto error;
        }
This page took 0.030748 seconds and 4 git commands to generate.