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 */
*/
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
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.
*/
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 */
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;
+}
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 */
case LTTNG_LIST_DOMAINS:
case LTTNG_START_TRACE:
case LTTNG_STOP_TRACE:
+ case LTTNG_DATA_AVAILABLE:
need_domain = 0;
break;
default:
bytecode);
break;
}
+ case LTTNG_DATA_AVAILABLE:
+ {
+ ret = cmd_data_available(cmd_ctx->session);
+ break;
+ }
default:
ret = LTTNG_ERR_UND;
break;
[ 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"
RELAYD_CLOSE_STREAM,
LTTNG_SET_FILTER,
LTTNG_HEALTH_CHECK,
+ LTTNG_DATA_AVAILABLE,
};
/*
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
*/