Exemplo n.º 1
0
static
struct lttng_notification *create_notification_from_current_message(
		struct lttng_notification_channel *channel)
{
	ssize_t ret;
	struct lttng_notification *notification = NULL;
	struct lttng_buffer_view view;

	if (channel->reception_buffer.size <=
			sizeof(struct lttng_notification_channel_message)) {
		goto end;
	}

	view = lttng_buffer_view_from_dynamic_buffer(&channel->reception_buffer,
			sizeof(struct lttng_notification_channel_message), -1);

	ret = lttng_notification_create_from_buffer(&view, &notification);
	if (ret != channel->reception_buffer.size -
			sizeof(struct lttng_notification_channel_message)) {
		lttng_notification_destroy(notification);
		notification = NULL;
		goto end;
	}
end:
	return notification;
}
Exemplo n.º 2
0
static
int enqueue_dropped_notification(
		struct lttng_notification_channel *channel)
{
	int ret = 0;
	struct pending_notification *pending_notification;
	struct cds_list_head *last_element =
			channel->pending_notifications.list.prev;

	pending_notification = caa_container_of(last_element,
			struct pending_notification, node);
	if (!pending_notification->notification) {
		/*
		 * The last enqueued notification indicates dropped
		 * notifications; there is nothing to do as we group
		 * dropped notifications together.
		 */
		goto end;
	}

	if (channel->pending_notifications.count >=
			DEFAULT_CLIENT_MAX_QUEUED_NOTIFICATIONS_COUNT &&
			pending_notification->notification) {
		/*
		 * Discard the last enqueued notification to indicate
		 * that notifications were dropped at this point.
		 */
		lttng_notification_destroy(
				pending_notification->notification);
		pending_notification->notification = NULL;
		goto end;
	}

	pending_notification = zmalloc(sizeof(*pending_notification));
	if (!pending_notification) {
		ret = -1;
		goto end;
	}
	CDS_INIT_LIST_HEAD(&pending_notification->node);
	cds_list_add(&pending_notification->node,
			&channel->pending_notifications.list);
	channel->pending_notifications.count++;
end:
	return ret;
}
Exemplo n.º 3
0
int main(int argc, char **argv)
{
	int ret = 0;
	enum lttng_condition_status condition_status;
	enum lttng_notification_channel_status nc_status;
	struct lttng_notification_channel *notification_channel = NULL;
	struct lttng_condition *condition = NULL;
	struct lttng_action *action = NULL;
	struct lttng_trigger *trigger = NULL;

	/*
	 * Disable buffering on stdout.
	 * Safety measure to prevent hang on the validation side since
	 * stdout is used for outside synchronization.
	 */
	setbuf(stdout, NULL);

	if (argc < 8) {
		printf("error: Missing arguments for tests\n");
		ret = 1;
		goto end;
	}

	ret = parse_arguments(argv);
	if (ret) {
		printf("error: Could not parse arguments\n");
		goto end;
	}

	/* Setup */
	notification_channel = lttng_notification_channel_create(
			lttng_session_daemon_notification_endpoint);
	if (!notification_channel) {
		printf("error: Could not create notification channel\n");
		ret = 1;
		goto end;
	}

	switch (buffer_usage_type) {
	case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
		condition = lttng_condition_buffer_usage_low_create();
		break;
	case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH:
		condition = lttng_condition_buffer_usage_high_create();
		break;
	default:
		printf("error: Invalid buffer_usage_type\n");
		ret = 1;
		goto end;
	}

	if (!condition) {
		printf("error: Could not create condition object\n");
		ret = 1;
		goto end;
	}

	if (is_threshold_ratio) {
		condition_status = lttng_condition_buffer_usage_set_threshold_ratio(
				condition, threshold_ratio);
	} else {
		condition_status = lttng_condition_buffer_usage_set_threshold(
				condition, threshold_bytes);
	}

	if (condition_status != LTTNG_CONDITION_STATUS_OK) {
		printf("error: Could not set threshold\n");
		ret = 1;
		goto end;
	}

	condition_status = lttng_condition_buffer_usage_set_session_name(
			condition, session_name);
	if (condition_status != LTTNG_CONDITION_STATUS_OK) {
		printf("error: Could not set session name\n");
		ret = 1;
		goto end;
	}
	condition_status = lttng_condition_buffer_usage_set_channel_name(
			condition, channel_name);
	if (condition_status != LTTNG_CONDITION_STATUS_OK) {
		printf("error: Could not set channel name\n");
		ret = 1;
		goto end;
	}
	condition_status = lttng_condition_buffer_usage_set_domain_type(
			condition, domain_type);
	if (condition_status != LTTNG_CONDITION_STATUS_OK) {
		printf("error: Could not set domain type\n");
		ret = 1;
		goto end;
	}

	action = lttng_action_notify_create();
	if (!action) {
		printf("error: Could not create action notify\n");
		ret = 1;
		goto end;
	}

	trigger = lttng_trigger_create(condition, action);
	if (!trigger) {
		printf("error: Could not create trigger\n");
		ret = 1;
		goto end;
	}

	ret = lttng_register_trigger(trigger);

	/*
	 * An equivalent trigger might already be registered if an other app
	 * registered an equivalent trigger.
	 */
	if (ret < 0 && ret != -LTTNG_ERR_TRIGGER_EXISTS) {
		printf("error: %s\n", lttng_strerror(ret));
		ret = 1;
		goto end;
	}

	nc_status = lttng_notification_channel_subscribe(notification_channel, condition);
	if (nc_status != LTTNG_NOTIFICATION_CHANNEL_STATUS_OK) {
		printf("error: Could not subscribe\n");
		ret = 1;
		goto end;
	}

	/* Tell outside process that the client is ready */
	printf("sync: ready\n");

	for (;;) {
		struct lttng_notification *notification;
		enum lttng_notification_channel_status status;
		const struct lttng_evaluation *notification_evaluation;
		const struct lttng_condition *notification_condition;

		if (nr_notifications == nr_expected_notifications) {
			ret = 0;
			goto end;
		}
		/* Receive the next notification. */
		status = lttng_notification_channel_get_next_notification(
				notification_channel,
				&notification);

		switch (status) {
		case LTTNG_NOTIFICATION_CHANNEL_STATUS_OK:
			break;
		case LTTNG_NOTIFICATION_CHANNEL_STATUS_NOTIFICATIONS_DROPPED:
			ret = 1;
			printf("error: No drop should be observed during this test app\n");
			goto end;
		case LTTNG_NOTIFICATION_CHANNEL_STATUS_CLOSED:
			/*
			 * The notification channel has been closed by the
			 * session daemon. This is typically caused by a session
			 * daemon shutting down (cleanly or because of a crash).
			 */
			printf("error: Notification channel was closed\n");
			ret = 1;
			goto end;
		default:
			/* Unhandled conditions / errors. */
			printf("error: Unknown notification channel status\n");
			ret = 1;
			goto end;
		}

		notification_condition = lttng_notification_get_condition(notification);
		notification_evaluation = lttng_notification_get_evaluation(notification);

		ret = handle_condition(notification_condition, notification_evaluation);
		nr_notifications++;

		lttng_notification_destroy(notification);
		if (ret != 0) {
			goto end;
		}
	}
end:
	if (trigger) {
		lttng_unregister_trigger(trigger);
	}
	if (lttng_notification_channel_unsubscribe(notification_channel, condition)) {
		printf("error: channel unsubscribe error\n");
	}
	lttng_trigger_destroy(trigger);
	lttng_condition_destroy(condition);
	lttng_action_destroy(action);
	lttng_notification_channel_destroy(notification_channel);
	printf("exit: %d\n", ret);
	return ret;
}
Exemplo n.º 4
0
static
int test_notification(
		struct lttng_notification_channel *notification_channel,
		const struct session *session,
		const char *expected_notification_type_name,
		enum lttng_condition_type expected_condition_type)
{
	int ret = 0;
	bool notification_pending;
	enum lttng_notification_channel_status notification_channel_status;
	enum lttng_condition_status condition_status;
	enum lttng_evaluation_status evaluation_status;
	enum lttng_trace_archive_location_status location_status;
	enum lttng_condition_type condition_type;
	struct lttng_notification *notification = NULL;
	const struct lttng_condition *condition;
	const struct lttng_evaluation *evaluation;
	const char *session_name = NULL;
	const struct lttng_trace_archive_location *location = NULL;
	uint64_t rotation_id = UINT64_MAX;
	const char *chunk_path = NULL;

	notification_channel_status = lttng_notification_channel_has_pending_notification(
			notification_channel, &notification_pending);
	ok(notification_channel_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK,
			"Check for %s notification pending on notification channel",
			expected_notification_type_name);
	if (notification_channel_status != LTTNG_NOTIFICATION_CHANNEL_STATUS_OK) {
		ret = -1;
		goto end;
	}

	ok(notification_pending,
			"Session %s notification is pending on notification channel",
			expected_notification_type_name);
	if (!notification_pending) {
		ret = -1;
		goto end;
	}

	notification_channel_status = lttng_notification_channel_get_next_notification(
			notification_channel, &notification);
	ok(notification_channel_status == LTTNG_NOTIFICATION_CHANNEL_STATUS_OK && notification,
			"Get %s notification from notification channel",
			expected_notification_type_name);
	if (notification_channel_status != LTTNG_NOTIFICATION_CHANNEL_STATUS_OK || !notification) {
		ret = -1;
		goto end;
	}

	condition = lttng_notification_get_condition(notification);
	if (!condition) {
		diag("Failed to get notification condition");
		ret = -1;
		goto end;
	}

	condition_type = lttng_condition_get_type(condition);
	ok(condition_type == expected_condition_type,
			"Notification condition obtained from notification channel is of type \"%s\"",
			expected_notification_type_name);
	if (condition_type != expected_condition_type) {
		ret = -1;
		goto end;
	}

	condition_status = lttng_condition_session_rotation_get_session_name(
			condition, &session_name);
	ok(condition_status == LTTNG_CONDITION_STATUS_OK && session_name &&
			!strcmp(session_name, session->name),
			"Condition obtained from notification has the correct session name assigned");
	if (condition_status != LTTNG_CONDITION_STATUS_OK || !session_name) {
		ret = -1;
		goto end;
	}

	evaluation = lttng_notification_get_evaluation(notification);
	if (!evaluation) {
		diag("Failed to get notification evaluation");
		ret = -1;
		goto end;
	}
	condition_type = lttng_evaluation_get_type(evaluation);
	ok(condition_type == expected_condition_type,
			"Condition evaluation obtained from notification channel is of type \"%s\"",
			expected_notification_type_name);
	if (condition_type != expected_condition_type) {
		ret = -1;
		goto end;
	}

	evaluation_status = lttng_evaluation_session_rotation_get_id(evaluation,
			&rotation_id);
	ok(evaluation_status == LTTNG_EVALUATION_STATUS_OK,
			"Get %s id from notification evaluation",
			expected_notification_type_name);
	if (evaluation_status != LTTNG_EVALUATION_STATUS_OK) {
		ret = -1;
		goto end;
	}

	if (expected_condition_type != LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED) {
		/*
		 * Remaining tests only apply to "session rotation completed"
		 * notifications.
		 */
		goto end;
	}

	evaluation_status = lttng_evaluation_session_rotation_completed_get_location(
			evaluation, &location);
	ok(evaluation_status == LTTNG_EVALUATION_STATUS_OK && location,
			"Get session %s chunk location from evaluation",
			expected_notification_type_name);
	if (evaluation_status != LTTNG_EVALUATION_STATUS_OK || !location) {
		ret = -1;
		goto end;
	}

	ok(lttng_trace_archive_location_get_type(location) == LTTNG_TRACE_ARCHIVE_LOCATION_TYPE_LOCAL,
			"Location returned from the session rotation completed notification is of type 'local'");

	location_status = lttng_trace_archive_location_local_get_absolute_path(
			location, &chunk_path);
	ok(location_status == LTTNG_TRACE_ARCHIVE_LOCATION_STATUS_OK && chunk_path,
			"Retrieved path from location returned by the session rotation completed notification");
	diag("Chunk available at %s", chunk_path ? chunk_path : "NULL");

	ok(chunk_path && !strncmp(session->output_path, chunk_path, strlen(session->output_path)),
			"Returned path from location starts with the output path");

end:
	lttng_notification_destroy(notification);
	return ret;
}