From 806e2684ce24d3772af37ee46c5f0500c7a0723f Mon Sep 17 00:00:00 2001 From: David Goulet Date: Wed, 17 Oct 2012 12:05:42 -0400 Subject: [PATCH] Lib lttng-ctl data available command support 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 --- include/lttng/lttng-error.h | 2 +- include/lttng/lttng.h | 10 ++++ src/bin/lttng-sessiond/cmd.c | 41 +++++++++++++++ src/bin/lttng-sessiond/cmd.h | 1 + src/bin/lttng-sessiond/consumer.c | 63 ++++++++++++++++++++++++ src/bin/lttng-sessiond/consumer.h | 2 + src/bin/lttng-sessiond/main.c | 6 +++ src/common/error.c | 1 + src/common/sessiond-comm/sessiond-comm.h | 1 + src/lib/lttng-ctl/lttng-ctl.c | 32 ++++++++++++ 10 files changed, 158 insertions(+), 1 deletion(-) diff --git a/include/lttng/lttng-error.h b/include/lttng/lttng-error.h index 0eeb74616..c728913bc 100644 --- a/include/lttng/lttng-error.h +++ b/include/lttng/lttng-error.h @@ -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 */ diff --git a/include/lttng/lttng.h b/include/lttng/lttng.h index f92ccb6fd..4171cde41 100644 --- a/include/lttng/lttng.h +++ b/include/lttng/lttng.h @@ -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 diff --git a/src/bin/lttng-sessiond/cmd.c b/src/bin/lttng-sessiond/cmd.c index b1e66e755..1d4f9264e 100644 --- a/src/bin/lttng-sessiond/cmd.c +++ b/src/bin/lttng-sessiond/cmd.c @@ -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. */ diff --git a/src/bin/lttng-sessiond/cmd.h b/src/bin/lttng-sessiond/cmd.h index 850c881fb..97ddf029c 100644 --- a/src/bin/lttng-sessiond/cmd.h +++ b/src/bin/lttng-sessiond/cmd.h @@ -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 */ diff --git a/src/bin/lttng-sessiond/consumer.c b/src/bin/lttng-sessiond/consumer.c index 071135bda..3a4577ab0 100644 --- a/src/bin/lttng-sessiond/consumer.c +++ b/src/bin/lttng-sessiond/consumer.c @@ -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; +} diff --git a/src/bin/lttng-sessiond/consumer.h b/src/bin/lttng-sessiond/consumer.h index 1a1e1c8d8..acc039a23 100644 --- a/src/bin/lttng-sessiond/consumer.h +++ b/src/bin/lttng-sessiond/consumer.h @@ -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 */ diff --git a/src/bin/lttng-sessiond/main.c b/src/bin/lttng-sessiond/main.c index 1c5623bc3..2f0a39fed 100644 --- a/src/bin/lttng-sessiond/main.c +++ b/src/bin/lttng-sessiond/main.c @@ -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; diff --git a/src/common/error.c b/src/common/error.c index ce11bf208..4354cc3bb 100644 --- a/src/common/error.c +++ b/src/common/error.c @@ -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" diff --git a/src/common/sessiond-comm/sessiond-comm.h b/src/common/sessiond-comm/sessiond-comm.h index 5d2fa36a8..f60c5d238 100644 --- a/src/common/sessiond-comm/sessiond-comm.h +++ b/src/common/sessiond-comm/sessiond-comm.h @@ -87,6 +87,7 @@ enum lttcomm_sessiond_command { RELAYD_CLOSE_STREAM, LTTNG_SET_FILTER, LTTNG_HEALTH_CHECK, + LTTNG_DATA_AVAILABLE, }; /* diff --git a/src/lib/lttng-ctl/lttng-ctl.c b/src/lib/lttng-ctl/lttng-ctl.c index edaebf59c..c6238e11c 100644 --- a/src/lib/lttng-ctl/lttng-ctl.c +++ b/src/lib/lttng-ctl/lttng-ctl.c @@ -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 */ -- 2.34.1