Lib lttng-ctl data available command support
authorDavid Goulet <dgoulet@efficios.com>
Wed, 17 Oct 2012 16:05:42 +0000 (12:05 -0400)
committerDavid Goulet <dgoulet@efficios.com>
Fri, 19 Oct 2012 17:15:08 +0000 (13:15 -0400)
New API call lttng_data_available that returns 0 if the data is NOT
available for reading or else 1 if it it.

The session daemon supports the call and uses the consumer data
available feature.

Note that there is still no support for this command on the relayd side
at this commit.

Signed-off-by: David Goulet <dgoulet@efficios.com>
include/lttng/lttng-error.h
include/lttng/lttng.h
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/common/error.c
src/common/sessiond-comm/sessiond-comm.h
src/lib/lttng-ctl/lttng-ctl.c

index 0eeb74616a210f60c630ca176be87a7a24a6fe3e..c728913bcd7052fdd853b00d33aae1935d5317be 100644 (file)
@@ -33,7 +33,7 @@ enum lttng_error_code {
        LTTNG_OK                         = 10,  /* Ok */
        LTTNG_ERR_UNK                    = 11,  /* Unknown Error */
        LTTNG_ERR_UND                    = 12,  /* Undefine command */
-       /* 13 */
+       LTTNG_ERR_SESSION_STARTED        = 13,  /* Session is running */
        LTTNG_ERR_UNKNOWN_DOMAIN         = 14,  /* Tracing domain not known */
        /* 15 */
        LTTNG_ERR_NO_SESSION             = 16,  /* No session found */
index f92ccb6fdb3615266bb86c06dc465accb01ded9b..4171cde41c998d123fac3b407a337ec622b42cfe 100644 (file)
@@ -581,6 +581,16 @@ extern int lttng_disable_consumer(struct lttng_handle *handle);
  */
 extern int lttng_health_check(enum lttng_health_component c);
 
+/*
+ * For a given session name, this call checks if the data is ready to be read
+ * or is still being extracted by the consumer(s) hence not ready to be used by
+ * any readers.
+ *
+ * Return 0 if the data is _NOT_ available else 1 if the data is ready. On
+ * error, a negative value is returned and readable by lttng_strerror().
+ */
+extern int lttng_data_available(const char *session_name);
+
 #ifdef __cplusplus
 }
 #endif
index b1e66e755bf0f621fb8c78f84a6d8c9043cedc55..1d4f9264eb0a57e4aedfa595767b1478b9402a4f 100644 (file)
@@ -2334,6 +2334,47 @@ error:
        return ret;
 }
 
+/*
+ * Command LTTNG_DATA_AVAILABLE returning 0 if the data is NOT ready to be read
+ * or else 1 if the data is available for trace analysis.
+ */
+int cmd_data_available(struct ltt_session *session)
+{
+       int ret;
+       struct ltt_kernel_session *ksess = session->kernel_session;
+       struct ltt_ust_session *usess = session->ust_session;
+
+       assert(session);
+
+       /* Session MUST be stopped to ask for data availability. */
+       if (session->enabled) {
+               ret = LTTNG_ERR_SESSION_STARTED;
+               goto error;
+       }
+
+       if (ksess && ksess->consumer) {
+               ret = consumer_is_data_available(ksess->id, ksess->consumer);
+               if (ret == 0) {
+                       /* Data is still being extracted for the kernel. */
+                       goto error;
+               }
+       }
+
+       if (usess && usess->consumer) {
+               ret = consumer_is_data_available(usess->id, usess->consumer);
+               if (ret == 0) {
+                       /* Data is still being extracted for the kernel. */
+                       goto error;
+               }
+       }
+
+       /* Data is ready to be read by a viewer */
+       ret = 1;
+
+error:
+       return ret;
+}
+
 /*
  * Init command subsystem.
  */
index 850c881fbf0804663f88cd992e2fdf253049ac02..97ddf029c97e9570eb30ac9a8a7d7accce30f977 100644 (file)
@@ -82,5 +82,6 @@ ssize_t cmd_list_tracepoint_fields(int domain,
 ssize_t cmd_list_tracepoints(int domain, struct lttng_event **events);
 
 int cmd_calibrate(int domain, struct lttng_calibrate *calibrate);
+int cmd_data_available(struct ltt_session *session);
 
 #endif /* CMD_H */
index 071135bda6975b09abf4f4db7841454dfecdc269..3a4577ab0bb36dfa98aa655447526bfdf8717131 100644 (file)
@@ -695,3 +695,66 @@ int consumer_set_subdir(struct consumer_output *consumer,
 error:
        return ret;
 }
+
+/*
+ * Ask the consumer if the data is ready to bread (available) for the specific
+ * session id.
+ *
+ * This function has a different behavior with the consumer i.e. that it waits
+ * for a reply from the consumer if yes or no the data is available.
+ */
+int consumer_is_data_available(unsigned int id,
+               struct consumer_output *consumer)
+{
+       int ret;
+       int32_t ret_code;
+       struct consumer_socket *socket;
+       struct lttng_ht_iter iter;
+       struct lttcomm_consumer_msg msg;
+
+       assert(consumer);
+
+       msg.cmd_type = LTTNG_CONSUMER_DATA_AVAILABLE;
+
+       msg.u.data_available.session_id = (uint64_t) id;
+
+       DBG3("Consumer data available for id %u", id);
+
+       cds_lfht_for_each_entry(consumer->socks->ht, &iter.iter, socket,
+                       node.node) {
+               /* Code flow error */
+               assert(socket->fd >= 0);
+
+               pthread_mutex_lock(socket->lock);
+
+               ret = lttcomm_send_unix_sock(socket->fd, &msg, sizeof(msg));
+               if (ret < 0) {
+                       PERROR("send consumer data available command");
+                       pthread_mutex_unlock(socket->lock);
+                       goto error;
+               }
+
+               /*
+                * Waiting for the reply code where 0 the data is not available and 1
+                * it is for trace reading.
+                */
+               ret = lttcomm_recv_unix_sock(socket->fd, &ret_code, sizeof(ret_code));
+               if (ret < 0) {
+                       PERROR("recv consumer data available status");
+                       pthread_mutex_unlock(socket->lock);
+                       goto error;
+               }
+
+               pthread_mutex_unlock(socket->lock);
+
+               if (ret_code == 0) {
+                       break;
+               }
+       }
+
+       DBG("Consumer data available ret %d", ret_code);
+       return ret_code;
+
+error:
+       return -1;
+}
index 1a1e1c8d8086d4d9155fda1436a955d192d741a8..acc039a2394b7d1069d7a46f56073d8cc6ec8bde 100644 (file)
@@ -199,5 +199,7 @@ void consumer_init_channel_comm_msg(struct lttcomm_consumer_msg *msg,
                uint64_t mmap_len,
                const char *name,
                unsigned int nb_init_streams);
+int consumer_is_data_available(unsigned int id,
+               struct consumer_output *consumer);
 
 #endif /* _CONSUMER_H */
index 1c5623bc3282c980840ff06f361244e8ac2f497b..2f0a39fede12d5e130d9fc8f88f011dd2f80dc96 100644 (file)
@@ -2102,6 +2102,7 @@ static int process_client_msg(struct command_ctx *cmd_ctx, int sock,
        case LTTNG_LIST_DOMAINS:
        case LTTNG_START_TRACE:
        case LTTNG_STOP_TRACE:
+       case LTTNG_DATA_AVAILABLE:
                need_domain = 0;
                break;
        default:
@@ -2788,6 +2789,11 @@ skip_domain:
                                bytecode);
                break;
        }
+       case LTTNG_DATA_AVAILABLE:
+       {
+               ret = cmd_data_available(cmd_ctx->session);
+               break;
+       }
        default:
                ret = LTTNG_ERR_UND;
                break;
index ce11bf208ad7e05a3292eb790d56885916aa66d7..4354cc3bbf6353bf30df4a9c7d9bb3e7a3a027b7 100644 (file)
@@ -99,6 +99,7 @@ static const char *error_string_array[] = {
        [ ERROR_INDEX(LTTNG_ERR_FILTER_EXIST) ] = "Filter already exist",
        [ ERROR_INDEX(LTTNG_ERR_NO_CONSUMER) ] = "Consumer not found for tracing session",
        [ ERROR_INDEX(LTTNG_ERR_NO_SESSIOND) ] = "No session daemon is available",
+       [ ERROR_INDEX(LTTNG_ERR_SESSION_STARTED) ] = "Session is running",
 
        /* Last element */
        [ ERROR_INDEX(LTTNG_ERR_NR) ] = "Unknown error code"
index 5d2fa36a8b02fa9b7417b92c87a49b5a742c384f..f60c5d238a364037fa21a75b42ac128910ce3d61 100644 (file)
@@ -87,6 +87,7 @@ enum lttcomm_sessiond_command {
        RELAYD_CLOSE_STREAM,
        LTTNG_SET_FILTER,
        LTTNG_HEALTH_CHECK,
+       LTTNG_DATA_AVAILABLE,
 };
 
 /*
index edaebf59c8654515ac7872d0888e4a84dd6ab0ad..c6238e11c81e17b746553725d2d062d67a22d2d3 100644 (file)
@@ -1590,6 +1590,38 @@ int _lttng_create_session_ext(const char *name, const char *url,
                        NULL);
 }
 
+/*
+ * For a given session name, this call checks if the data is ready to be read
+ * or is still being extracted by the consumer(s) hence not ready to be used by
+ * any readers.
+ */
+int lttng_data_available(const char *session_name)
+{
+       int ret;
+       struct lttcomm_session_msg lsm;
+
+       if (session_name == NULL) {
+               return -LTTNG_ERR_INVALID;
+       }
+
+       lsm.cmd_type = LTTNG_DATA_AVAILABLE;
+
+       copy_string(lsm.session.name, session_name, sizeof(lsm.session.name));
+
+       ret = ask_sessiond(&lsm, NULL);
+
+       /*
+        * The ask_sessiond function negate the return code if it's not LTTNG_OK so
+        * getting -1 means that the reply ret_code was 1 thus meaning that the
+        * data is available. Yes it is hackish but for now this is the only way.
+        */
+       if (ret == -1) {
+               ret = 1;
+       }
+
+       return ret;
+}
+
 /*
  * lib constructor
  */
This page took 0.035889 seconds and 4 git commands to generate.