Exemplo n.º 1
0
/*
 *  Ask the session daemon for all available events of a session channel.
 *  Sets the contents of the events array.
 *  Returns the number of lttng_event entries in events;
 *  on error, returns a negative value.
 */
int lttng_list_events(struct lttng_handle *handle,
		const char *channel_name, struct lttng_event **events)
{
	int ret;
	struct lttcomm_session_msg lsm;

	/* Safety check. An handle and channel name are mandatory */
	if (handle == NULL || channel_name == NULL) {
		return -LTTNG_ERR_INVALID;
	}

	memset(&lsm, 0, sizeof(lsm));
	lsm.cmd_type = LTTNG_LIST_EVENTS;
	lttng_ctl_copy_string(lsm.session.name, handle->session_name,
			sizeof(lsm.session.name));
	lttng_ctl_copy_string(lsm.u.list.channel_name, channel_name,
			sizeof(lsm.u.list.channel_name));

	lttng_ctl_copy_lttng_domain(&lsm.domain, &handle->domain);

	ret = lttng_ctl_ask_sessiond(&lsm, (void**) events);
	if (ret < 0) {
		return ret;
	}

	return ret / sizeof(struct lttng_event);
}
Exemplo n.º 2
0
/*
 * Add context to a channel.
 *
 * If the given channel is NULL, add the contexts to all channels.
 * The event_name param is ignored.
 *
 * Returns the size of the returned payload data or a negative error code.
 */
int lttng_add_context(struct lttng_handle *handle,
		struct lttng_event_context *ctx, const char *event_name,
		const char *channel_name)
{
	struct lttcomm_session_msg lsm;

	/* Safety check. Both are mandatory */
	if (handle == NULL || ctx == NULL) {
		return -LTTNG_ERR_INVALID;
	}

	memset(&lsm, 0, sizeof(lsm));

	lsm.cmd_type = LTTNG_ADD_CONTEXT;

	/* If no channel name, send empty string. */
	if (channel_name == NULL) {
		lttng_ctl_copy_string(lsm.u.context.channel_name, "",
				sizeof(lsm.u.context.channel_name));
	} else {
		lttng_ctl_copy_string(lsm.u.context.channel_name, channel_name,
				sizeof(lsm.u.context.channel_name));
	}

	lttng_ctl_copy_lttng_domain(&lsm.domain, &handle->domain);

	memcpy(&lsm.u.context.ctx, ctx, sizeof(struct lttng_event_context));

	lttng_ctl_copy_string(lsm.session.name, handle->session_name,
			sizeof(lsm.session.name));

	return lttng_ctl_ask_sessiond(&lsm, NULL);
}
Exemplo n.º 3
0
/*
 * 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_pending(const char *session_name)
{
	int ret;
	struct lttcomm_session_msg lsm;
	uint8_t *pending = NULL;

	if (session_name == NULL) {
		return -LTTNG_ERR_INVALID;
	}

	memset(&lsm, 0, sizeof(lsm));
	lsm.cmd_type = LTTNG_DATA_PENDING;

	lttng_ctl_copy_string(lsm.session.name, session_name,
			sizeof(lsm.session.name));

	ret = lttng_ctl_ask_sessiond(&lsm, (void **) &pending);
	if (ret < 0) {
		goto end;
	} else if (ret != 1) {
		/* Unexpected payload size */
		ret = -LTTNG_ERR_INVALID;
		goto end;
	}

	ret = (int) *pending;
end:
	free(pending);
	return ret;
}
Exemplo n.º 4
0
/*
 * List PIDs in the tracker.
 *
 * @enabled is set to whether the PID tracker is enabled.
 * @pids is set to an allocated array of PIDs currently tracked. On
 * success, @pids must be freed by the caller.
 * @nr_pids is set to the number of entries contained by the @pids array.
 *
 * Returns 0 on success, else a negative LTTng error code.
 */
int lttng_list_tracker_pids(struct lttng_handle *handle,
		int *_enabled, int32_t **_pids, size_t *_nr_pids)
{
	int ret, enabled = 1;
	struct lttcomm_session_msg lsm;
	size_t nr_pids;
	int32_t *pids;

	if (handle == NULL) {
		return -LTTNG_ERR_INVALID;
	}

	memset(&lsm, 0, sizeof(lsm));
	lsm.cmd_type = LTTNG_LIST_TRACKER_PIDS;
	lttng_ctl_copy_string(lsm.session.name, handle->session_name,
			sizeof(lsm.session.name));
	lttng_ctl_copy_lttng_domain(&lsm.domain, &handle->domain);

	ret = lttng_ctl_ask_sessiond(&lsm, (void **) &pids);
	if (ret < 0) {
		return ret;
	}
	nr_pids = ret / sizeof(int32_t);
	if (nr_pids == 1 && pids[0] == -1) {
		free(pids);
		pids = NULL;
		enabled = 0;
		nr_pids = 0;
	}
	*_enabled = enabled;
	*_pids = pids;
	*_nr_pids = nr_pids;
	return 0;
}
Exemplo n.º 5
0
/*
 *  Enable channel per domain
 *  Returns size of returned session payload data or a negative error code.
 */
int lttng_enable_channel(struct lttng_handle *handle,
		struct lttng_channel *chan)
{
	struct lttcomm_session_msg lsm;

	/*
	 * NULL arguments are forbidden. No default values.
	 */
	if (handle == NULL || chan == NULL) {
		return -LTTNG_ERR_INVALID;
	}

	memset(&lsm, 0, sizeof(lsm));

	memcpy(&lsm.u.channel.chan, chan, sizeof(lsm.u.channel.chan));

	lsm.cmd_type = LTTNG_ENABLE_CHANNEL;

	lttng_ctl_copy_lttng_domain(&lsm.domain, &handle->domain);

	lttng_ctl_copy_string(lsm.session.name, handle->session_name,
			sizeof(lsm.session.name));

	return lttng_ctl_ask_sessiond(&lsm, 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_pending(const char *session_name)
{
	int ret;
	struct lttcomm_session_msg lsm;

	if (session_name == NULL) {
		return -LTTNG_ERR_INVALID;
	}

	memset(&lsm, 0, sizeof(lsm));
	lsm.cmd_type = LTTNG_DATA_PENDING;

	lttng_ctl_copy_string(lsm.session.name, session_name,
			sizeof(lsm.session.name));

	ret = lttng_ctl_ask_sessiond(&lsm, NULL);

	/*
	 * The lttng_ctl_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;
}
Exemplo n.º 7
0
/*
 *  Ask the session daemon for all available sessions.
 *  Sets the contents of the sessions array.
 *  Returns the number of lttng_session entries in sessions;
 *  on error, returns a negative value.
 */
int lttng_list_sessions(struct lttng_session **sessions)
{
	int ret;
	struct lttcomm_session_msg lsm;

	memset(&lsm, 0, sizeof(lsm));
	lsm.cmd_type = LTTNG_LIST_SESSIONS;
	ret = lttng_ctl_ask_sessiond(&lsm, (void**) sessions);
	if (ret < 0) {
		return ret;
	}

	return ret / sizeof(struct lttng_session);
}
Exemplo n.º 8
0
/*
 *  Destroy session using name.
 *  Returns size of returned session payload data or a negative error code.
 */
int lttng_destroy_session(const char *session_name)
{
	struct lttcomm_session_msg lsm;

	if (session_name == NULL) {
		return -LTTNG_ERR_INVALID;
	}

	memset(&lsm, 0, sizeof(lsm));
	lsm.cmd_type = LTTNG_DESTROY_SESSION;

	lttng_ctl_copy_string(lsm.session.name, session_name,
			sizeof(lsm.session.name));

	return lttng_ctl_ask_sessiond(&lsm, NULL);
}
Exemplo n.º 9
0
/*
 *  Start tracing for all traces of the session.
 *  Returns size of returned session payload data or a negative error code.
 */
int lttng_start_tracing(const char *session_name)
{
	struct lttcomm_session_msg lsm;

	if (session_name == NULL) {
		return -LTTNG_ERR_INVALID;
	}

	memset(&lsm, 0, sizeof(lsm));
	lsm.cmd_type = LTTNG_START_TRACE;

	lttng_ctl_copy_string(lsm.session.name, session_name,
			sizeof(lsm.session.name));

	return lttng_ctl_ask_sessiond(&lsm, NULL);
}
Exemplo n.º 10
0
/*
 * Stop tracing for all traces of the session.
 */
static int _lttng_stop_tracing(const char *session_name, int wait)
{
	int ret, data_ret;
	struct lttcomm_session_msg lsm;

	if (session_name == NULL) {
		return -LTTNG_ERR_INVALID;
	}

	memset(&lsm, 0, sizeof(lsm));
	lsm.cmd_type = LTTNG_STOP_TRACE;

	lttng_ctl_copy_string(lsm.session.name, session_name,
			sizeof(lsm.session.name));

	ret = lttng_ctl_ask_sessiond(&lsm, NULL);
	if (ret < 0 && ret != -LTTNG_ERR_TRACE_ALREADY_STOPPED) {
		goto error;
	}

	if (!wait) {
		goto end;
	}

	/* Check for data availability */
	do {
		data_ret = lttng_data_pending(session_name);
		if (data_ret < 0) {
			/* Return the data available call error. */
			ret = data_ret;
			goto error;
		}

		/*
		 * Data sleep time before retrying (in usec). Don't sleep if the call
		 * returned value indicates availability.
		 */
		if (data_ret) {
			usleep(DEFAULT_DATA_AVAILABILITY_WAIT_TIME);
		}
	} while (data_ret != 0);

end:
error:
	return ret;
}
Exemplo n.º 11
0
/*
 * Returns size of returned session payload data or a negative error code.
 */
int lttng_calibrate(struct lttng_handle *handle,
		struct lttng_calibrate *calibrate)
{
	struct lttcomm_session_msg lsm;

	/* Safety check. NULL pointer are forbidden */
	if (handle == NULL || calibrate == NULL) {
		return -LTTNG_ERR_INVALID;
	}

	memset(&lsm, 0, sizeof(lsm));
	lsm.cmd_type = LTTNG_CALIBRATE;
	lttng_ctl_copy_lttng_domain(&lsm.domain, &handle->domain);

	memcpy(&lsm.u.calibrate, calibrate, sizeof(lsm.u.calibrate));

	return lttng_ctl_ask_sessiond(&lsm, NULL);
}
Exemplo n.º 12
0
int lttng_set_session_shm_path(const char *session_name,
		const char *shm_path)
{
	struct lttcomm_session_msg lsm;

	if (session_name == NULL) {
		return -LTTNG_ERR_INVALID;
	}

	memset(&lsm, 0, sizeof(lsm));
	lsm.cmd_type = LTTNG_SET_SESSION_SHM_PATH;

	lttng_ctl_copy_string(lsm.session.name, session_name,
			sizeof(lsm.session.name));
	lttng_ctl_copy_string(lsm.u.set_shm_path.shm_path, shm_path,
			sizeof(lsm.u.set_shm_path.shm_path));

	return lttng_ctl_ask_sessiond(&lsm, NULL);
}
Exemplo n.º 13
0
/*
 * Register an outside consumer.
 * Returns size of returned session payload data or a negative error code.
 */
int lttng_register_consumer(struct lttng_handle *handle,
		const char *socket_path)
{
	struct lttcomm_session_msg lsm;

	if (handle == NULL || socket_path == NULL) {
		return -LTTNG_ERR_INVALID;
	}

	memset(&lsm, 0, sizeof(lsm));
	lsm.cmd_type = LTTNG_REGISTER_CONSUMER;
	lttng_ctl_copy_string(lsm.session.name, handle->session_name,
			sizeof(lsm.session.name));
	lttng_ctl_copy_lttng_domain(&lsm.domain, &handle->domain);

	lttng_ctl_copy_string(lsm.u.reg.path, socket_path, sizeof(lsm.u.reg.path));

	return lttng_ctl_ask_sessiond(&lsm, NULL);
}
Exemplo n.º 14
0
/*
 * The lttng-ctl API does not expose all the information needed to save the
 * session configurations. Thus, we must send a save command to the session
 * daemon which will, in turn, save its current session configuration.
 */
int lttng_save_session(struct lttng_save_session_attr *attr)
{
	struct lttcomm_session_msg lsm;
	int ret;

	if (!attr) {
		ret = -LTTNG_ERR_INVALID;
		goto end;
	}

	memset(&lsm, 0, sizeof(lsm));
	lsm.cmd_type = LTTNG_SAVE_SESSION;

	memcpy(&lsm.u.save_session.attr, attr,
		sizeof(struct lttng_save_session_attr));
	ret = lttng_ctl_ask_sessiond(&lsm, NULL);
end:
	return ret;
}
Exemplo n.º 15
0
/*
 *  Lists all available tracepoint fields of domain.
 *  Sets the contents of the event field array.
 *  Returns the number of lttng_event_field entries in events;
 *  on error, returns a negative value.
 */
int lttng_list_tracepoint_fields(struct lttng_handle *handle,
		struct lttng_event_field **fields)
{
	int ret;
	struct lttcomm_session_msg lsm;

	if (handle == NULL) {
		return -LTTNG_ERR_INVALID;
	}

	memset(&lsm, 0, sizeof(lsm));
	lsm.cmd_type = LTTNG_LIST_TRACEPOINT_FIELDS;
	lttng_ctl_copy_lttng_domain(&lsm.domain, &handle->domain);

	ret = lttng_ctl_ask_sessiond(&lsm, (void **) fields);
	if (ret < 0) {
		return ret;
	}

	return ret / sizeof(struct lttng_event_field);
}
Exemplo n.º 16
0
/*
 *  Lists all available kernel system calls. Allocates and sets the contents of
 *  the events array.
 *
 *  Returns the number of lttng_event entries in events; on error, returns a
 *  negative value.
 */
int lttng_list_syscalls(struct lttng_event **events)
{
	int ret;
	struct lttcomm_session_msg lsm;

	if (!events) {
		return -LTTNG_ERR_INVALID;
	}

	memset(&lsm, 0, sizeof(lsm));
	lsm.cmd_type = LTTNG_LIST_SYSCALLS;
	/* Force kernel domain for system calls. */
	lsm.domain.type = LTTNG_DOMAIN_KERNEL;

	ret = lttng_ctl_ask_sessiond(&lsm, (void **) events);
	if (ret < 0) {
		return ret;
	}

	return ret / sizeof(struct lttng_event);
}
Exemplo n.º 17
0
/*
 *  All tracing will be stopped for registered events of the channel.
 *  Returns size of returned session payload data or a negative error code.
 */
int lttng_disable_channel(struct lttng_handle *handle, const char *name)
{
	struct lttcomm_session_msg lsm;

	/* Safety check. Both are mandatory */
	if (handle == NULL || name == NULL) {
		return -LTTNG_ERR_INVALID;
	}

	memset(&lsm, 0, sizeof(lsm));

	lsm.cmd_type = LTTNG_DISABLE_CHANNEL;

	lttng_ctl_copy_string(lsm.u.disable.channel_name, name,
			sizeof(lsm.u.disable.channel_name));

	lttng_ctl_copy_lttng_domain(&lsm.domain, &handle->domain);

	lttng_ctl_copy_string(lsm.session.name, handle->session_name,
			sizeof(lsm.session.name));

	return lttng_ctl_ask_sessiond(&lsm, NULL);
}
Exemplo n.º 18
0
/*
 *  Remove PID from session tracker.
 *  Return 0 on success else a negative LTTng error code.
 */
int lttng_untrack_pid(struct lttng_handle *handle, int pid)
{
	struct lttcomm_session_msg lsm;

	/*
	 * NULL arguments are forbidden. No default values.
	 */
	if (handle == NULL) {
		return -LTTNG_ERR_INVALID;
	}

	memset(&lsm, 0, sizeof(lsm));

	lsm.cmd_type = LTTNG_UNTRACK_PID;
	lsm.u.pid_tracker.pid = pid;

	lttng_ctl_copy_lttng_domain(&lsm.domain, &handle->domain);

	lttng_ctl_copy_string(lsm.session.name, handle->session_name,
			sizeof(lsm.session.name));

	return lttng_ctl_ask_sessiond(&lsm, NULL);
}
Exemplo n.º 19
0
/*
 *  Ask the session daemon for all available domains of a session.
 *  Sets the contents of the domains array.
 *  Returns the number of lttng_domain entries in domains;
 *  on error, returns a negative value.
 */
int lttng_list_domains(const char *session_name,
		struct lttng_domain **domains)
{
	int ret;
	struct lttcomm_session_msg lsm;

	if (session_name == NULL) {
		return -LTTNG_ERR_INVALID;
	}

	memset(&lsm, 0, sizeof(lsm));
	lsm.cmd_type = LTTNG_LIST_DOMAINS;

	lttng_ctl_copy_string(lsm.session.name, session_name,
			sizeof(lsm.session.name));

	ret = lttng_ctl_ask_sessiond(&lsm, (void**) domains);
	if (ret < 0) {
		return ret;
	}

	return ret / sizeof(struct lttng_domain);
}
Exemplo n.º 20
0
/*
 *  Ask the session daemon for all available channels of a session.
 *  Sets the contents of the channels array.
 *  Returns the number of lttng_channel entries in channels;
 *  on error, returns a negative value.
 */
int lttng_list_channels(struct lttng_handle *handle,
		struct lttng_channel **channels)
{
	int ret;
	struct lttcomm_session_msg lsm;

	if (handle == NULL) {
		return -LTTNG_ERR_INVALID;
	}

	memset(&lsm, 0, sizeof(lsm));
	lsm.cmd_type = LTTNG_LIST_CHANNELS;
	lttng_ctl_copy_string(lsm.session.name, handle->session_name,
			sizeof(lsm.session.name));

	lttng_ctl_copy_lttng_domain(&lsm.domain, &handle->domain);

	ret = lttng_ctl_ask_sessiond(&lsm, (void**) channels);
	if (ret < 0) {
		return ret;
	}

	return ret / sizeof(struct lttng_channel);
}
Exemplo n.º 21
0
/*
 * Enable event(s) for a channel, possibly with exclusions and a filter.
 * If no event name is specified, all events are enabled.
 * If no channel name is specified, the default name is used.
 * If filter expression is not NULL, the filter is set for the event.
 * If exclusion count is not zero, the exclusions are set for the event.
 * Returns size of returned session payload data or a negative error code.
 */
int lttng_enable_event_with_exclusions(struct lttng_handle *handle,
		struct lttng_event *ev, const char *channel_name,
		const char *original_filter_expression,
		int exclusion_count, char **exclusion_list)
{
	struct lttcomm_session_msg lsm;
	char *varlen_data;
	int ret = 0;
	unsigned int free_filter_expression = 0;
	struct filter_parser_ctx *ctx = NULL;
	/*
	 * Cast as non-const since we may replace the filter expression
	 * by a dynamically allocated string. Otherwise, the original
	 * string is not modified.
	 */
	char *filter_expression = (char *) original_filter_expression;

	if (handle == NULL || ev == NULL) {
		ret = -LTTNG_ERR_INVALID;
		goto error;
	}

	/* Empty filter string will always be rejected by the parser
	 * anyway, so treat this corner-case early to eliminate
	 * lttng_fmemopen error for 0-byte allocation.
	 */
	if (filter_expression && filter_expression[0] == '\0') {
		ret = -LTTNG_ERR_INVALID;
		goto error;
	}

	memset(&lsm, 0, sizeof(lsm));

	/* If no channel name, send empty string. */
	if (channel_name == NULL) {
		lttng_ctl_copy_string(lsm.u.enable.channel_name, "",
				sizeof(lsm.u.enable.channel_name));
	} else {
		lttng_ctl_copy_string(lsm.u.enable.channel_name, channel_name,
				sizeof(lsm.u.enable.channel_name));
	}

	lsm.cmd_type = LTTNG_ENABLE_EVENT;
	if (ev->name[0] == '\0') {
		/* Enable all events */
		lttng_ctl_copy_string(ev->name, "*", sizeof(ev->name));
	}

	lttng_ctl_copy_lttng_domain(&lsm.domain, &handle->domain);
	/* FIXME: copying non-packed struct to packed struct. */
	memcpy(&lsm.u.enable.event, ev, sizeof(lsm.u.enable.event));

	lttng_ctl_copy_string(lsm.session.name, handle->session_name,
			sizeof(lsm.session.name));
	lsm.u.enable.exclusion_count = exclusion_count;
	lsm.u.enable.bytecode_len = 0;

	/*
	 * For the JUL domain, a filter is enforced except for the enable all
	 * event. This is done to avoid having the event in all sessions thus
	 * filtering by logger name.
	 */
	if (exclusion_count == 0 && filter_expression == NULL &&
			(handle->domain.type != LTTNG_DOMAIN_JUL &&
				handle->domain.type != LTTNG_DOMAIN_LOG4J &&
				handle->domain.type != LTTNG_DOMAIN_PYTHON)) {
		goto ask_sessiond;
	}

	/*
	 * We have either a filter or some exclusions, so we need to set up
	 * a variable-length memory block from where to send the data
	 */

	/* Parse filter expression */
	if (filter_expression != NULL || handle->domain.type == LTTNG_DOMAIN_JUL
			|| handle->domain.type == LTTNG_DOMAIN_LOG4J
			|| handle->domain.type == LTTNG_DOMAIN_PYTHON) {
		if (handle->domain.type == LTTNG_DOMAIN_JUL ||
				handle->domain.type == LTTNG_DOMAIN_LOG4J ||
				handle->domain.type == LTTNG_DOMAIN_PYTHON) {
			char *agent_filter;

			/* Setup JUL filter if needed. */
			agent_filter = set_agent_filter(filter_expression, ev);
			if (!agent_filter) {
				if (!filter_expression) {
					/* No JUL and no filter, just skip everything below. */
					goto ask_sessiond;
				}
			} else {
				/*
				 * With an agent filter, the original filter has been added to
				 * it thus replace the filter expression.
				 */
				filter_expression = agent_filter;
				free_filter_expression = 1;
			}
		}

		ret = generate_filter(filter_expression, &lsm, &ctx);
		if (ret) {
			goto filter_error;
		}
	}

	varlen_data = zmalloc(lsm.u.enable.bytecode_len
			+ lsm.u.enable.expression_len
			+ LTTNG_SYMBOL_NAME_LEN * exclusion_count);
	if (!varlen_data) {
		ret = -LTTNG_ERR_EXCLUSION_NOMEM;
		goto mem_error;
	}

	/* Put exclusion names first in the data */
	while (exclusion_count--) {
		strncpy(varlen_data + LTTNG_SYMBOL_NAME_LEN * exclusion_count,
			*(exclusion_list + exclusion_count), LTTNG_SYMBOL_NAME_LEN);
	}
	/* Add filter expression next */
	if (lsm.u.enable.expression_len != 0) {
		memcpy(varlen_data
			+ LTTNG_SYMBOL_NAME_LEN * lsm.u.enable.exclusion_count,
			filter_expression,
			lsm.u.enable.expression_len);
	}
	/* Add filter bytecode next */
	if (ctx && lsm.u.enable.bytecode_len != 0) {
		memcpy(varlen_data
			+ LTTNG_SYMBOL_NAME_LEN * lsm.u.enable.exclusion_count
			+ lsm.u.enable.expression_len,
			&ctx->bytecode->b,
			lsm.u.enable.bytecode_len);
	}

	ret = lttng_ctl_ask_sessiond_varlen(&lsm, varlen_data,
			(LTTNG_SYMBOL_NAME_LEN * lsm.u.enable.exclusion_count) +
			lsm.u.enable.bytecode_len + lsm.u.enable.expression_len, NULL);
	free(varlen_data);

mem_error:
	if (filter_expression && ctx) {
		filter_bytecode_free(ctx);
		filter_ir_free(ctx);
		filter_parser_ctx_free(ctx);
	}
filter_error:
	if (free_filter_expression) {
		/*
		 * The filter expression has been replaced and must be freed as it is
		 * not the original filter expression received as a parameter.
		 */
		free(filter_expression);
	}
error:
	/*
	 * Return directly to the caller and don't ask the sessiond since something
	 * went wrong in the parsing of data above.
	 */
	return ret;

ask_sessiond:
	ret = lttng_ctl_ask_sessiond(&lsm, NULL);
	return ret;
}