Пример #1
0
LTTNG_HIDDEN
int mi_lttng_event_tracepoint_loglevel(struct mi_writer *writer,
		struct lttng_event *event, enum lttng_domain_type domain)
{
	int ret;

	/* Event loglevel */
	ret = mi_lttng_writer_write_element_string(writer,
			config_element_loglevel,
			mi_lttng_loglevel_string(event->loglevel, domain));
	if (ret) {
		goto end;
	}

	/* Log level type */
	ret = mi_lttng_writer_write_element_string(writer,
			config_element_loglevel_type,
			mi_lttng_logleveltype_string(event->loglevel_type));
	if (ret) {
		goto end;
	}

	/* event exclusion filter */
	ret = mi_lttng_writer_write_element_bool(writer,
			config_element_exclusion, event->exclusion);
	if (ret) {
		goto end;
	}

end:
	return ret;
}
Пример #2
0
/*
 * Mi print of partial session
 */
static int mi_print_session(char *session_name, int enabled)
{
	int ret;
	assert(writer);
	assert(session_name);

	/* Open session element */
	ret = mi_lttng_writer_open_element(writer, config_element_session);
	if (ret) {
		goto end;
	}

	/* Print session name element */
	ret = mi_lttng_writer_write_element_string(writer, config_element_name,
			session_name);
	if (ret) {
		goto end;
	}

	/* Is enabled ? */
	ret = mi_lttng_writer_write_element_bool(writer, config_element_enabled,
			enabled);
	if (ret) {
		goto end;
	}

	/* Close session element */
	ret = mi_lttng_writer_close_element(writer);

end:
	return ret;
}
Пример #3
0
LTTNG_HIDDEN
int mi_lttng_session(struct mi_writer *writer,
		struct lttng_session *session, int is_open)
{
	int ret;

	assert(session);

	/* Open sessions element */
	ret = mi_lttng_writer_open_element(writer,
			config_element_session);
	if (ret) {
		goto end;
	}

	/* Name of the session */
	ret = mi_lttng_writer_write_element_string(writer,
			config_element_name, session->name);
	if (ret) {
		goto end;
	}

	/* Path */
	ret = mi_lttng_writer_write_element_string(writer,
			config_element_path, session->path);
	if (ret) {
		goto end;
	}

	/* Enabled ? */
	ret = mi_lttng_writer_write_element_bool(writer,
			config_element_enabled, session->enabled);
	if (ret) {
		goto end;
	}

	/* Snapshot mode */
	ret = mi_lttng_writer_write_element_unsigned_int(writer,
			config_element_snapshot_mode, session->snapshot_mode);
	if (ret) {
		goto end;
	}

	/* Live timer interval in usec */
	ret = mi_lttng_writer_write_element_unsigned_int(writer,
			config_element_live_timer_interval,
			session->live_timer_interval);
	if (ret) {
		goto end;
	}

	if (!is_open) {
		/* Closing session element */
		ret = mi_lttng_writer_close_element(writer);
	}
end:
	return ret;

}
Пример #4
0
LTTNG_HIDDEN
int mi_lttng_event_tracepoint_no_loglevel(struct mi_writer *writer,
		struct lttng_event *event)
{
	/* event exclusion filter */
	return mi_lttng_writer_write_element_bool(writer,
			config_element_exclusion, event->exclusion);
}
Пример #5
0
LTTNG_HIDDEN
int mi_lttng_event_common_attributes(struct mi_writer *writer,
		struct lttng_event *event)
{
	int ret;

	/* Open event element */
	ret = mi_lttng_writer_open_element(writer, config_element_event);
	if (ret) {
		goto end;
	}

	/* Event name */
	ret = mi_lttng_writer_write_element_string(writer,
			config_element_name, event->name);
	if (ret) {
		goto end;
	}

	/* Event type */
	ret = mi_lttng_writer_write_element_string(writer,
			config_element_type, mi_lttng_eventtype_string(event->type));
	if (ret) {
		goto end;
	}

	/* Is event enabled */
	ret = mi_lttng_writer_write_element_bool(writer,
			config_element_enabled, event->enabled);
	if (ret) {
		goto end;
	}

	/* Event filter enabled? */
	ret = mi_lttng_writer_write_element_bool(writer,
			config_element_filter, event->filter);

end:
	return ret;
}
Пример #6
0
LTTNG_HIDDEN
int mi_lttng_event_common_attributes(struct mi_writer *writer,
		struct lttng_event *event)
{
	int ret;
	const char *filter_expression;

	/* Open event element */
	ret = mi_lttng_writer_open_element(writer, config_element_event);
	if (ret) {
		goto end;
	}

	/* Event name */
	ret = mi_lttng_writer_write_element_string(writer,
			config_element_name, event->name);
	if (ret) {
		goto end;
	}

	/* Event type */
	ret = mi_lttng_writer_write_element_string(writer,
			config_element_type, mi_lttng_eventtype_string(event->type));
	if (ret) {
		goto end;
	}

	/* Is event enabled */
	ret = mi_lttng_writer_write_element_bool(writer,
			config_element_enabled, event->enabled);
	if (ret) {
		goto end;
	}

	/* Event filter expression */
	ret = lttng_event_get_filter_expression(event, &filter_expression);
	if (ret) {
		goto end;
	}

	if (filter_expression) {
		ret = mi_lttng_writer_write_element_string(writer,
				config_element_filter_expression,
				filter_expression);
		if (ret) {
			goto end;
		}
	}

end:
	return ret;
}
Пример #7
0
/* Mi print a partial event.
 * enabled is 0 or 1
 * success is 0 or 1
 */
static int mi_print_event(char *event_name, int enabled, int success)
{
	int ret;

	assert(writer);
	assert(event_name);

	/* Open event element */
	ret = mi_lttng_writer_open_element(writer, config_element_event);
	if (ret) {
		goto end;
	}

	/* Print the name of event */
	ret = mi_lttng_writer_write_element_string(writer,
			config_element_name, event_name);
	if (ret) {
		goto end;
	}

	/* Print enabled ? */
	ret = mi_lttng_writer_write_element_bool(writer,
			config_element_enabled, enabled);
	if (ret) {
		goto end;
	}

	/* Success ? */
	ret = mi_lttng_writer_write_element_bool(writer,
			mi_lttng_element_command_success, success);
	if (ret) {
		goto end;
	}

	/* Close event element */
	ret = mi_lttng_writer_close_element(writer);
end:
	return ret;
}
Пример #8
0
LTTNG_HIDDEN
int mi_lttng_channel(struct mi_writer *writer,
		struct lttng_channel *channel, int is_open)
{
	int ret = 0;

	assert(channel);

	/* Opening channel element */
	ret = mi_lttng_writer_open_element(writer, config_element_channel);
	if (ret) {
		goto end;
	}

	/* Name */
	ret = mi_lttng_writer_write_element_string(writer, config_element_name,
			channel->name);
	if (ret) {
		goto end;
	}

	/* Enabled ? */
	ret = mi_lttng_writer_write_element_bool(writer,
			config_element_enabled, channel->enabled);
	if (ret) {
		goto end;
	}

	/* Attribute */
	ret = mi_lttng_channel_attr(writer, &channel->attr);
	if (ret) {
		goto end;
	}

	if (!is_open) {
		/* Closing channel element */
		ret = mi_lttng_writer_close_element(writer);
		if (ret) {
			goto end;
		}
	}
end:
	return ret;
}
Пример #9
0
/*
 *  cmd_disable_events
 *
 *  Disable event to trace session
 */
int cmd_disable_events(int argc, const char **argv)
{
	int opt, ret = CMD_SUCCESS, command_ret = CMD_SUCCESS, success = 1;
	static poptContext pc;
	char *session_name = NULL;
	int event_type = -1;

	pc = poptGetContext(NULL, argc, argv, long_options, 0);
	poptReadDefaultConfig(pc, 0);

	/* Default event type */
	opt_event_type = LTTNG_EVENT_ALL;

	while ((opt = poptGetNextOpt(pc)) != -1) {
		switch (opt) {
		case OPT_HELP:
			SHOW_HELP();
			goto end;
		case OPT_TYPE_SYSCALL:
			opt_event_type = LTTNG_EVENT_SYSCALL;
			break;
		case OPT_TYPE_TRACEPOINT:
			opt_event_type = LTTNG_EVENT_TRACEPOINT;
			break;
		case OPT_TYPE_PROBE:
			opt_event_type = LTTNG_EVENT_PROBE;
			break;
		case OPT_TYPE_FUNCTION:
			opt_event_type = LTTNG_EVENT_FUNCTION;
			break;
		case OPT_TYPE_ALL:
			opt_event_type = LTTNG_EVENT_ALL;
			break;
		case OPT_LIST_OPTIONS:
			list_cmd_options(stdout, long_options);
			goto end;
		default:
			ret = CMD_UNDEFINED;
			goto end;
		}

		/* Validate event type. Multiple event type are not supported. */
		if (event_type == -1) {
			event_type = opt_event_type;
		} else {
			if (event_type != opt_event_type) {
				ERR("Multiple event type not supported.");
				ret = CMD_ERROR;
				goto end;
			}
		}
	}

	ret = print_missing_or_multiple_domains(
		opt_kernel + opt_userspace + opt_jul + opt_log4j + opt_python);
	if (ret) {
		ret = CMD_ERROR;
		goto end;
	}

	/* Ust and agent only support ALL event type */
	if ((opt_userspace || opt_jul || opt_log4j || opt_python)
			&& opt_event_type != LTTNG_EVENT_ALL) {
		ERR("Disabling userspace and agent (-j | -l | -p) event(s) based on instrumentation type is not supported.\n");
		ret = CMD_ERROR;
		goto end;
	}

	opt_event_list = (char*) poptGetArg(pc);
	if (opt_event_list == NULL && opt_disable_all == 0) {
		ERR("Missing event name(s).\n");
		ret = CMD_ERROR;
		goto end;
	}

	if (!opt_session_name) {
		session_name = get_session_name();
		if (session_name == NULL) {
			ret = CMD_ERROR;
			goto end;
		}
	} else {
		session_name = opt_session_name;
	}

	/* Mi check */
	if (lttng_opt_mi) {
		writer = mi_lttng_writer_create(fileno(stdout), lttng_opt_mi);
		if (!writer) {
			ret = -LTTNG_ERR_NOMEM;
			goto end;
		}

		/* Open command element */
		ret = mi_lttng_writer_command_open(writer,
				mi_lttng_element_command_disable_event);
		if (ret) {
			ret = CMD_ERROR;
			goto end;
		}

		/* Open output element */
		ret = mi_lttng_writer_open_element(writer,
				mi_lttng_element_command_output);
		if (ret) {
			ret = CMD_ERROR;
			goto end;
		}
	}

	command_ret = disable_events(session_name);
	if (command_ret) {
		success = 0;
	}

	/* Mi closing */
	if (lttng_opt_mi) {
		/* Close  output element */
		ret = mi_lttng_writer_close_element(writer);
		if (ret) {
			ret = CMD_ERROR;
			goto end;
		}

		ret = mi_lttng_writer_write_element_bool(writer,
				mi_lttng_element_command_success, success);
		if (ret) {
			ret = CMD_ERROR;
			goto end;
		}

		/* Command element close */
		ret = mi_lttng_writer_command_close(writer);
		if (ret) {
			ret = CMD_ERROR;
			goto end;
		}
	}

end:
	if (!opt_session_name && session_name) {
		free(session_name);
	}

	/* Mi clean-up */
	if (writer && mi_lttng_writer_destroy(writer)) {
		/* Preserve original error code */
		ret = ret ? ret : LTTNG_ERR_MI_IO_FAIL;
	}

	/* Overwrite ret if an error occurred in disable_events */
	ret = command_ret ? command_ret : ret;

	poptFreeContext(pc);
	return ret;
}
Пример #10
0
/*
 * Enabling event using the lttng API.
 * Note: in case of error only the last error code will be return.
 */
static int enable_events(char *session_name)
{
	int ret = CMD_SUCCESS, command_ret = CMD_SUCCESS;
	int error_holder = CMD_SUCCESS, warn = 0, error = 0, success = 1;
	char *event_name, *channel_name = NULL;
	struct lttng_event *ev;
	struct lttng_domain dom;
	char **exclusion_list = NULL;

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

	ev = lttng_event_create();
	if (!ev) {
		ret = CMD_ERROR;
		goto error;
	}

	if (opt_kernel) {
		if (opt_loglevel) {
			WARN("Kernel loglevels are not supported.");
		}
	}

	/* Create lttng domain */
	if (opt_kernel) {
		dom.type = LTTNG_DOMAIN_KERNEL;
		dom.buf_type = LTTNG_BUFFER_GLOBAL;
	} else if (opt_userspace) {
		dom.type = LTTNG_DOMAIN_UST;
		/* Default. */
		dom.buf_type = LTTNG_BUFFER_PER_UID;
	} else if (opt_jul) {
		dom.type = LTTNG_DOMAIN_JUL;
		/* Default. */
		dom.buf_type = LTTNG_BUFFER_PER_UID;
	} else if (opt_log4j) {
		dom.type = LTTNG_DOMAIN_LOG4J;
		/* Default. */
		dom.buf_type = LTTNG_BUFFER_PER_UID;
	} else if (opt_python) {
		dom.type = LTTNG_DOMAIN_PYTHON;
		/* Default. */
		dom.buf_type = LTTNG_BUFFER_PER_UID;
	} else {
		/* Checked by the caller. */
		assert(0);
	}

	if (opt_exclude) {
		switch (dom.type) {
		case LTTNG_DOMAIN_KERNEL:
		case LTTNG_DOMAIN_JUL:
		case LTTNG_DOMAIN_LOG4J:
		case LTTNG_DOMAIN_PYTHON:
			ERR("Event name exclusions are not yet implemented for %s events",
					get_domain_str(dom.type));
			ret = CMD_ERROR;
			goto error;
		case LTTNG_DOMAIN_UST:
			/* Exclusions supported */
			break;
		default:
			assert(0);
		}
	}

	/*
	 * Adding a filter to a probe, function or userspace-probe would be
	 * denied by the kernel tracer as it's not supported at the moment. We
	 * do an early check here to warn the user.
	 */
	if (opt_filter && opt_kernel) {
		switch (opt_event_type) {
		case LTTNG_EVENT_ALL:
		case LTTNG_EVENT_TRACEPOINT:
		case LTTNG_EVENT_SYSCALL:
			break;
		case LTTNG_EVENT_PROBE:
		case LTTNG_EVENT_USERSPACE_PROBE:
		case LTTNG_EVENT_FUNCTION:
			ERR("Filter expressions are not supported for %s events",
					get_event_type_str(opt_event_type));
			ret = CMD_ERROR;
			goto error;
		default:
			ret = CMD_UNDEFINED;
			goto error;
		}
	}

	channel_name = opt_channel_name;

	handle = lttng_create_handle(session_name, &dom);
	if (handle == NULL) {
		ret = -1;
		goto error;
	}

	/* Prepare Mi */
	if (lttng_opt_mi) {
		/* Open a events element */
		ret = mi_lttng_writer_open_element(writer, config_element_events);
		if (ret) {
			ret = CMD_ERROR;
			goto error;
		}
	}

	if (opt_enable_all) {
		/* Default setup for enable all */
		if (opt_kernel) {
			ev->type = opt_event_type;
			strcpy(ev->name, "*");
			/* kernel loglevels not implemented */
			ev->loglevel_type = LTTNG_EVENT_LOGLEVEL_ALL;
		} else {
			ev->type = LTTNG_EVENT_TRACEPOINT;
			strcpy(ev->name, "*");
			ev->loglevel_type = opt_loglevel_type;
			if (opt_loglevel) {
				assert(opt_userspace || opt_jul || opt_log4j || opt_python);
				if (opt_userspace) {
					ev->loglevel = loglevel_str_to_value(opt_loglevel);
				} else if (opt_jul) {
					ev->loglevel = loglevel_jul_str_to_value(opt_loglevel);
				} else if (opt_log4j) {
					ev->loglevel = loglevel_log4j_str_to_value(opt_loglevel);
				} else if (opt_python) {
					ev->loglevel = loglevel_python_str_to_value(opt_loglevel);
				}
				if (ev->loglevel == -1) {
					ERR("Unknown loglevel %s", opt_loglevel);
					ret = -LTTNG_ERR_INVALID;
					goto error;
				}
			} else {
				assert(opt_userspace || opt_jul || opt_log4j || opt_python);
				if (opt_userspace) {
					ev->loglevel = -1;
				} else if (opt_jul) {
					ev->loglevel = LTTNG_LOGLEVEL_JUL_ALL;
				} else if (opt_log4j) {
					ev->loglevel = LTTNG_LOGLEVEL_LOG4J_ALL;
				} else if (opt_python) {
					ev->loglevel = LTTNG_LOGLEVEL_PYTHON_DEBUG;
				}
			}
		}

		if (opt_exclude) {
			ret = create_exclusion_list_and_validate("*",
				opt_exclude, &exclusion_list);
			if (ret) {
				ret = CMD_ERROR;
				goto error;
			}

			ev->exclusion = 1;
			warn_on_truncated_exclusion_names(exclusion_list,
				&warn);
		}
		if (!opt_filter) {
			ret = lttng_enable_event_with_exclusions(handle,
					ev, channel_name,
					NULL,
					exclusion_list ? strutils_array_of_strings_len(exclusion_list) : 0,
					exclusion_list);
			if (ret < 0) {
				switch (-ret) {
				case LTTNG_ERR_KERN_EVENT_EXIST:
					WARN("Kernel events already enabled (channel %s, session %s)",
							print_channel_name(channel_name), session_name);
					warn = 1;
					break;
				case LTTNG_ERR_TRACE_ALREADY_STARTED:
				{
					const char *msg = "The command tried to enable an event in a new domain for a session that has already been started once.";
					ERR("Events: %s (channel %s, session %s)",
							msg,
							print_channel_name(channel_name),
							session_name);
					error = 1;
					break;
				}
				default:
					ERR("Events: %s (channel %s, session %s)",
							lttng_strerror(ret),
							ret == -LTTNG_ERR_NEED_CHANNEL_NAME
								? print_raw_channel_name(channel_name)
								: print_channel_name(channel_name),
							session_name);
					error = 1;
					break;
				}
				goto end;
			}

			switch (opt_event_type) {
			case LTTNG_EVENT_TRACEPOINT:
				if (opt_loglevel && dom.type != LTTNG_DOMAIN_KERNEL) {
					char *exclusion_string = print_exclusions(exclusion_list);

					if (!exclusion_string) {
						PERROR("Cannot allocate exclusion_string");
						error = 1;
						goto end;
					}
					MSG("All %s tracepoints%s are enabled in channel %s for loglevel %s",
							get_domain_str(dom.type),
							exclusion_string,
							print_channel_name(channel_name),
							opt_loglevel);
					free(exclusion_string);
				} else {
					char *exclusion_string = print_exclusions(exclusion_list);

					if (!exclusion_string) {
						PERROR("Cannot allocate exclusion_string");
						error = 1;
						goto end;
					}
					MSG("All %s tracepoints%s are enabled in channel %s",
							get_domain_str(dom.type),
							exclusion_string,
							print_channel_name(channel_name));
					free(exclusion_string);
				}
				break;
			case LTTNG_EVENT_SYSCALL:
				if (opt_kernel) {
					MSG("All %s system calls are enabled in channel %s",
							get_domain_str(dom.type),
							print_channel_name(channel_name));
				}
				break;
			case LTTNG_EVENT_ALL:
				if (opt_loglevel && dom.type != LTTNG_DOMAIN_KERNEL) {
					char *exclusion_string = print_exclusions(exclusion_list);

					if (!exclusion_string) {
						PERROR("Cannot allocate exclusion_string");
						error = 1;
						goto end;
					}
					MSG("All %s events%s are enabled in channel %s for loglevel %s",
							get_domain_str(dom.type),
							exclusion_string,
							print_channel_name(channel_name),
							opt_loglevel);
					free(exclusion_string);
				} else {
					char *exclusion_string = print_exclusions(exclusion_list);

					if (!exclusion_string) {
						PERROR("Cannot allocate exclusion_string");
						error = 1;
						goto end;
					}
					MSG("All %s events%s are enabled in channel %s",
							get_domain_str(dom.type),
							exclusion_string,
							print_channel_name(channel_name));
					free(exclusion_string);
				}
				break;
			default:
				/*
				 * We should not be here since lttng_enable_event should have
				 * failed on the event type.
				 */
				goto error;
			}
		}

		if (opt_filter) {
			command_ret = lttng_enable_event_with_exclusions(handle, ev, channel_name,
						opt_filter,
						exclusion_list ? strutils_array_of_strings_len(exclusion_list) : 0,
						exclusion_list);
			if (command_ret < 0) {
				switch (-command_ret) {
				case LTTNG_ERR_FILTER_EXIST:
					WARN("Filter on all events is already enabled"
							" (channel %s, session %s)",
						print_channel_name(channel_name), session_name);
					warn = 1;
					break;
				case LTTNG_ERR_TRACE_ALREADY_STARTED:
				{
					const char *msg = "The command tried to enable an event in a new domain for a session that has already been started once.";
					ERR("All events: %s (channel %s, session %s, filter \'%s\')",
							msg,
							print_channel_name(channel_name),
							session_name, opt_filter);
					error = 1;
					break;
				}
				default:
					ERR("All events: %s (channel %s, session %s, filter \'%s\')",
							lttng_strerror(command_ret),
							command_ret == -LTTNG_ERR_NEED_CHANNEL_NAME
								? print_raw_channel_name(channel_name)
								: print_channel_name(channel_name),
							session_name, opt_filter);
					error = 1;
					break;
				}
				error_holder = command_ret;
			} else {
				ev->filter = 1;
				MSG("Filter '%s' successfully set", opt_filter);
			}
		}

		if (lttng_opt_mi) {
			/* The wildcard * is used for kernel and ust domain to
			 * represent ALL. We copy * in event name to force the wildcard use
			 * for kernel domain
			 *
			 * Note: this is strictly for semantic and printing while in
			 * machine interface mode.
			 */
			strcpy(ev->name, "*");

			/* If we reach here the events are enabled */
			if (!error && !warn) {
				ev->enabled = 1;
			} else {
				ev->enabled = 0;
				success = 0;
			}
			ret = mi_lttng_event(writer, ev, 1, handle->domain.type);
			if (ret) {
				ret = CMD_ERROR;
				goto error;
			}

			/* print exclusion */
			ret = mi_print_exclusion(exclusion_list);
			if (ret) {
				ret = CMD_ERROR;
				goto error;
			}

			/* Success ? */
			ret = mi_lttng_writer_write_element_bool(writer,
					mi_lttng_element_command_success, success);
			if (ret) {
				ret = CMD_ERROR;
				goto error;
			}

			/* Close event element */
			ret = mi_lttng_writer_close_element(writer);
			if (ret) {
				ret = CMD_ERROR;
				goto error;
			}
		}

		goto end;
	}

	/* Strip event list */
	event_name = strtok(opt_event_list, ",");
	while (event_name != NULL) {
		/* Copy name and type of the event */
		strncpy(ev->name, event_name, LTTNG_SYMBOL_NAME_LEN);
		ev->name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0';
		ev->type = opt_event_type;

		/* Kernel tracer action */
		if (opt_kernel) {
			DBG("Enabling kernel event %s for channel %s",
					event_name,
					print_channel_name(channel_name));

			switch (opt_event_type) {
			case LTTNG_EVENT_ALL:	/* Enable tracepoints and syscalls */
				/* If event name differs from *, select tracepoint. */
				if (strcmp(ev->name, "*")) {
					ev->type = LTTNG_EVENT_TRACEPOINT;
				}
				break;
			case LTTNG_EVENT_TRACEPOINT:
				break;
			case LTTNG_EVENT_PROBE:
				ret = parse_probe_opts(ev, opt_probe);
				if (ret) {
					ERR("Unable to parse probe options");
					ret = CMD_ERROR;
					goto error;
				}
				break;
			case LTTNG_EVENT_USERSPACE_PROBE:
				ret = parse_userspace_probe_opts(ev, opt_userspace_probe);
				if (ret) {
					switch (ret) {
					case CMD_UNSUPPORTED:
						/*
						 * Error message describing
						 * what is not supported was
						 * printed in the function.
						 */
						break;
					case CMD_ERROR:
					default:
						ERR("Unable to parse userspace probe options");
						break;
					}
					goto error;
				}
				break;
			case LTTNG_EVENT_FUNCTION:
				ret = parse_probe_opts(ev, opt_function);
				if (ret) {
					ERR("Unable to parse function probe options");
					ret = CMD_ERROR;
					goto error;
				}
				break;
			case LTTNG_EVENT_SYSCALL:
				ev->type = LTTNG_EVENT_SYSCALL;
				break;
			default:
				ret = CMD_UNDEFINED;
				goto error;
			}

			/* kernel loglevels not implemented */
			ev->loglevel_type = LTTNG_EVENT_LOGLEVEL_ALL;
		} else if (opt_userspace) {		/* User-space tracer action */
			DBG("Enabling UST event %s for channel %s, loglevel %s", event_name,
					print_channel_name(channel_name), opt_loglevel ? : "<all>");

			switch (opt_event_type) {
			case LTTNG_EVENT_ALL:	/* Default behavior is tracepoint */
				/* Fall-through */
			case LTTNG_EVENT_TRACEPOINT:
				/* Copy name and type of the event */
				ev->type = LTTNG_EVENT_TRACEPOINT;
				strncpy(ev->name, event_name, LTTNG_SYMBOL_NAME_LEN);
				ev->name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0';
				break;
			case LTTNG_EVENT_PROBE:
			case LTTNG_EVENT_FUNCTION:
			case LTTNG_EVENT_SYSCALL:
			case LTTNG_EVENT_USERSPACE_PROBE:
			default:
				ERR("Event type not available for user-space tracing");
				ret = CMD_UNSUPPORTED;
				goto error;
			}

			if (opt_exclude) {
				ev->exclusion = 1;
				if (opt_event_type != LTTNG_EVENT_ALL && opt_event_type != LTTNG_EVENT_TRACEPOINT) {
					ERR("Exclusion option can only be used with tracepoint events");
					ret = CMD_ERROR;
					goto error;
				}
				/* Free previously allocated items */
				strutils_free_null_terminated_array_of_strings(
					exclusion_list);
				exclusion_list = NULL;
				ret = create_exclusion_list_and_validate(
					event_name, opt_exclude,
					&exclusion_list);
				if (ret) {
					ret = CMD_ERROR;
					goto error;
				}

				warn_on_truncated_exclusion_names(
					exclusion_list, &warn);
			}

			ev->loglevel_type = opt_loglevel_type;
			if (opt_loglevel) {
				ev->loglevel = loglevel_str_to_value(opt_loglevel);
				if (ev->loglevel == -1) {
					ERR("Unknown loglevel %s", opt_loglevel);
					ret = -LTTNG_ERR_INVALID;
					goto error;
				}
			} else {
				ev->loglevel = -1;
			}
		} else if (opt_jul || opt_log4j || opt_python) {
			if (opt_event_type != LTTNG_EVENT_ALL &&
					opt_event_type != LTTNG_EVENT_TRACEPOINT) {
				ERR("Event type not supported for domain.");
				ret = CMD_UNSUPPORTED;
				goto error;
			}

			ev->loglevel_type = opt_loglevel_type;
			if (opt_loglevel) {
				if (opt_jul) {
					ev->loglevel = loglevel_jul_str_to_value(opt_loglevel);
				} else if (opt_log4j) {
					ev->loglevel = loglevel_log4j_str_to_value(opt_loglevel);
				} else if (opt_python) {
					ev->loglevel = loglevel_python_str_to_value(opt_loglevel);
				}
				if (ev->loglevel == -1) {
					ERR("Unknown loglevel %s", opt_loglevel);
					ret = -LTTNG_ERR_INVALID;
					goto error;
				}
			} else {
				if (opt_jul) {
					ev->loglevel = LTTNG_LOGLEVEL_JUL_ALL;
				} else if (opt_log4j) {
					ev->loglevel = LTTNG_LOGLEVEL_LOG4J_ALL;
				} else if (opt_python) {
					ev->loglevel = LTTNG_LOGLEVEL_PYTHON_DEBUG;
				}
			}
			ev->type = LTTNG_EVENT_TRACEPOINT;
			strncpy(ev->name, event_name, LTTNG_SYMBOL_NAME_LEN);
			ev->name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0';
		} else {
			assert(0);
		}

		if (!opt_filter) {
			char *exclusion_string;

			command_ret = lttng_enable_event_with_exclusions(handle,
					ev, channel_name,
					NULL,
					exclusion_list ? strutils_array_of_strings_len(exclusion_list) : 0,
					exclusion_list);
			exclusion_string = print_exclusions(exclusion_list);
			if (!exclusion_string) {
				PERROR("Cannot allocate exclusion_string");
				error = 1;
				goto end;
			}
			if (command_ret < 0) {
				/* Turn ret to positive value to handle the positive error code */
				switch (-command_ret) {
				case LTTNG_ERR_KERN_EVENT_EXIST:
					WARN("Kernel event %s%s already enabled (channel %s, session %s)",
							event_name,
							exclusion_string,
							print_channel_name(channel_name), session_name);
					warn = 1;
					break;
				case LTTNG_ERR_TRACE_ALREADY_STARTED:
				{
					const char *msg = "The command tried to enable an event in a new domain for a session that has already been started once.";
					ERR("Event %s%s: %s (channel %s, session %s)", event_name,
							exclusion_string,
							msg,
							print_channel_name(channel_name),
							session_name);
					error = 1;
					break;
				}
				case LTTNG_ERR_SDT_PROBE_SEMAPHORE:
					ERR("SDT probes %s guarded by semaphores are not supported (channel %s, session %s)",
							event_name, print_channel_name(channel_name),
							session_name);
					error = 1;
					break;
				default:
					ERR("Event %s%s: %s (channel %s, session %s)", event_name,
							exclusion_string,
							lttng_strerror(command_ret),
							command_ret == -LTTNG_ERR_NEED_CHANNEL_NAME
								? print_raw_channel_name(channel_name)
								: print_channel_name(channel_name),
							session_name);
					error = 1;
					break;
				}
				error_holder = command_ret;
			} else {
				switch (dom.type) {
				case LTTNG_DOMAIN_KERNEL:
				case LTTNG_DOMAIN_UST:
					MSG("%s event %s%s created in channel %s",
						get_domain_str(dom.type),
						event_name,
						exclusion_string,
						print_channel_name(channel_name));
					break;
				case LTTNG_DOMAIN_JUL:
				case LTTNG_DOMAIN_LOG4J:
				case LTTNG_DOMAIN_PYTHON:
					/*
					 * Don't print the default channel
					 * name for agent domains.
					 */
					MSG("%s event %s%s enabled",
						get_domain_str(dom.type),
						event_name,
						exclusion_string);
					break;
				default:
					assert(0);
				}
			}
			free(exclusion_string);
		}

		if (opt_filter) {
			char *exclusion_string;

			/* Filter present */
			ev->filter = 1;

			command_ret = lttng_enable_event_with_exclusions(handle, ev, channel_name,
					opt_filter,
					exclusion_list ? strutils_array_of_strings_len(exclusion_list) : 0,
					exclusion_list);
			exclusion_string = print_exclusions(exclusion_list);
			if (!exclusion_string) {
				PERROR("Cannot allocate exclusion_string");
				error = 1;
				goto end;
			}
			if (command_ret < 0) {
				switch (-command_ret) {
				case LTTNG_ERR_FILTER_EXIST:
					WARN("Filter on event %s%s is already enabled"
							" (channel %s, session %s)",
						event_name,
						exclusion_string,
						print_channel_name(channel_name), session_name);
					warn = 1;
					break;
				case LTTNG_ERR_TRACE_ALREADY_STARTED:
				{
					const char *msg = "The command tried to enable an event in a new domain for a session that has already been started once.";
					ERR("Event %s%s: %s (channel %s, session %s, filter \'%s\')", ev->name,
							exclusion_string,
							msg,
							print_channel_name(channel_name),
							session_name, opt_filter);
					error = 1;
					break;
				}
				default:
					ERR("Event %s%s: %s (channel %s, session %s, filter \'%s\')", ev->name,
							exclusion_string,
							lttng_strerror(command_ret),
							command_ret == -LTTNG_ERR_NEED_CHANNEL_NAME
								? print_raw_channel_name(channel_name)
								: print_channel_name(channel_name),
							session_name, opt_filter);
					error = 1;
					break;
				}
				error_holder = command_ret;

			} else {
				MSG("Event %s%s: Filter '%s' successfully set",
						event_name, exclusion_string,
						opt_filter);
			}
			free(exclusion_string);
		}

		if (lttng_opt_mi) {
			if (command_ret) {
				success = 0;
				ev->enabled = 0;
			} else {
				ev->enabled = 1;
			}

			ret = mi_lttng_event(writer, ev, 1, handle->domain.type);
			if (ret) {
				ret = CMD_ERROR;
				goto error;
			}

			/* print exclusion */
			ret = mi_print_exclusion(exclusion_list);
			if (ret) {
				ret = CMD_ERROR;
				goto error;
			}

			/* Success ? */
			ret = mi_lttng_writer_write_element_bool(writer,
					mi_lttng_element_command_success, success);
			if (ret) {
				ret = CMD_ERROR;
				goto end;
			}

			/* Close event element */
			ret = mi_lttng_writer_close_element(writer);
			if (ret) {
				ret = CMD_ERROR;
				goto end;
			}
		}

		/* Next event */
		event_name = strtok(NULL, ",");
		/* Reset warn, error and success */
		success = 1;
	}
Пример #11
0
/*
 * Add event to trace session
 */
int cmd_enable_events(int argc, const char **argv)
{
	int opt, ret = CMD_SUCCESS, command_ret = CMD_SUCCESS, success = 1;
	static poptContext pc;
	char *session_name = NULL;
	const char *leftover = NULL;
	int event_type = -1;

	pc = poptGetContext(NULL, argc, argv, long_options, 0);
	poptReadDefaultConfig(pc, 0);

	/* Default event type */
	opt_event_type = LTTNG_EVENT_ALL;

	while ((opt = poptGetNextOpt(pc)) != -1) {
		switch (opt) {
		case OPT_HELP:
			SHOW_HELP();
			goto end;
		case OPT_TRACEPOINT:
			opt_event_type = LTTNG_EVENT_TRACEPOINT;
			break;
		case OPT_PROBE:
			opt_event_type = LTTNG_EVENT_PROBE;
			break;
		case OPT_USERSPACE_PROBE:
			opt_event_type = LTTNG_EVENT_USERSPACE_PROBE;
			break;
		case OPT_FUNCTION:
			opt_event_type = LTTNG_EVENT_FUNCTION;
			break;
		case OPT_SYSCALL:
			opt_event_type = LTTNG_EVENT_SYSCALL;
			break;
		case OPT_USERSPACE:
			opt_userspace = 1;
			break;
		case OPT_LOGLEVEL:
			opt_loglevel_type = LTTNG_EVENT_LOGLEVEL_RANGE;
			opt_loglevel = poptGetOptArg(pc);
			break;
		case OPT_LOGLEVEL_ONLY:
			opt_loglevel_type = LTTNG_EVENT_LOGLEVEL_SINGLE;
			opt_loglevel = poptGetOptArg(pc);
			break;
		case OPT_LIST_OPTIONS:
			list_cmd_options(stdout, long_options);
			goto end;
		case OPT_FILTER:
			break;
		case OPT_EXCLUDE:
			break;
		default:
			ret = CMD_UNDEFINED;
			goto end;
		}

		/* Validate event type. Multiple event type are not supported. */
		if (event_type == -1) {
			event_type = opt_event_type;
		} else {
			if (event_type != opt_event_type) {
				ERR("Multiple event type not supported.");
				ret = CMD_ERROR;
				goto end;
			}
		}
	}

	ret = print_missing_or_multiple_domains(
		opt_kernel + opt_userspace + opt_jul + opt_log4j + opt_python);
	if (ret) {
		ret = CMD_ERROR;
		goto end;
	}

	/* Mi check */
	if (lttng_opt_mi) {
		writer = mi_lttng_writer_create(fileno(stdout), lttng_opt_mi);
		if (!writer) {
			ret = -LTTNG_ERR_NOMEM;
			goto end;
		}

		/* Open command element */
		ret = mi_lttng_writer_command_open(writer,
				mi_lttng_element_command_enable_event);
		if (ret) {
			ret = CMD_ERROR;
			goto end;
		}

		/* Open output element */
		ret = mi_lttng_writer_open_element(writer,
				mi_lttng_element_command_output);
		if (ret) {
			ret = CMD_ERROR;
			goto end;
		}
	}

	opt_event_list = (char*) poptGetArg(pc);
	if (opt_event_list == NULL && opt_enable_all == 0) {
		ERR("Missing event name(s).\n");
		ret = CMD_ERROR;
		goto end;
	}

	leftover = poptGetArg(pc);
	if (leftover) {
		ERR("Unknown argument: %s", leftover);
		ret = CMD_ERROR;
		goto end;
	}

	if (!opt_session_name) {
		session_name = get_session_name();
		if (session_name == NULL) {
			command_ret = CMD_ERROR;
			success = 0;
			goto mi_closing;
		}
	} else {
		session_name = opt_session_name;
	}

	command_ret = enable_events(session_name);
	if (command_ret) {
		success = 0;
		goto mi_closing;
	}

mi_closing:
	/* Mi closing */
	if (lttng_opt_mi) {
		/* Close  output element */
		ret = mi_lttng_writer_close_element(writer);
		if (ret) {
			ret = CMD_ERROR;
			goto end;
		}

		ret = mi_lttng_writer_write_element_bool(writer,
				mi_lttng_element_command_success, success);
		if (ret) {
			ret = CMD_ERROR;
			goto end;
		}

		/* Command element close */
		ret = mi_lttng_writer_command_close(writer);
		if (ret) {
			ret = CMD_ERROR;
			goto end;
		}
	}

end:
	/* Mi clean-up */
	if (writer && mi_lttng_writer_destroy(writer)) {
		/* Preserve original error code */
		ret = ret ? ret : LTTNG_ERR_MI_IO_FAIL;
	}

	if (opt_session_name == NULL) {
		free(session_name);
	}

	/* Overwrite ret if an error occurred in enable_events */
	ret = command_ret ? command_ret : ret;

	poptFreeContext(pc);
	return ret;
}
Пример #12
0
/*
 *  cmd_set_session
 */
int cmd_set_session(int argc, const char **argv)
{
	int opt, ret = CMD_SUCCESS, command_ret = CMD_SUCCESS, success = 1;
	static poptContext pc;

	pc = poptGetContext(NULL, argc, argv, long_options, 0);
	poptReadDefaultConfig(pc, 0);

	while ((opt = poptGetNextOpt(pc)) != -1) {
		switch (opt) {
		case OPT_HELP:
			usage(stdout);
			goto end;
		case OPT_LIST_OPTIONS:
			list_cmd_options(stdout, long_options);
			goto end;
		default:
			usage(stderr);
			ret = CMD_UNDEFINED;
			goto end;
		}
	}

	opt_session_name = (char *) poptGetArg(pc);
	if (opt_session_name == NULL) {
		ERR("Missing session name");
		usage(stderr);
		ret = CMD_ERROR;
		goto end;
	}

	/* Mi check */
	if (lttng_opt_mi) {
		writer = mi_lttng_writer_create(fileno(stdout), lttng_opt_mi);
		if (!writer) {
			ret = -LTTNG_ERR_NOMEM;
			goto end;
		}

		/* Open command element */
		ret = mi_lttng_writer_command_open(writer,
				mi_lttng_element_command_set_session);
		if (ret) {
			ret = CMD_ERROR;
			goto end;
		}

		/* Open output element */
		ret = mi_lttng_writer_open_element(writer,
				mi_lttng_element_command_output);
		if (ret) {
			ret = CMD_ERROR;
			goto end;
		}
	}

	command_ret = set_session();
	if (command_ret) {
		success = 0;
	}

	/* Mi closing */
	if (lttng_opt_mi) {
		/* Close  output element */
		ret = mi_lttng_writer_close_element(writer);
		if (ret) {
			ret = CMD_ERROR;
			goto end;
		}

		/* Success ? */
		ret = mi_lttng_writer_write_element_bool(writer,
				mi_lttng_element_command_success, success);
		if (ret) {
			ret = CMD_ERROR;
			goto end;
		}

		/* Command element close */
		ret = mi_lttng_writer_command_close(writer);
		if (ret) {
			ret = CMD_ERROR;
			goto end;
		}
	}

end:
	/* Mi clean-up */
	if (writer && mi_lttng_writer_destroy(writer)) {
		/* Preserve original error code */
		ret = ret ? ret : LTTNG_ERR_MI_IO_FAIL;
	}

	/* Overwrite ret if an error occured during set_session() */
	ret = command_ret ? command_ret : ret;

	poptFreeContext(pc);
	return ret;
}
Пример #13
0
/*
 * Enabling event using the lttng API.
 * Note: in case of error only the last error code will be return.
 */
static int enable_events(char *session_name)
{
	int ret = CMD_SUCCESS, command_ret = CMD_SUCCESS;
	int error_holder = CMD_SUCCESS, warn = 0, error = 0, success = 1;
	char *event_name, *channel_name = NULL;
	struct lttng_event ev;
	struct lttng_domain dom;
	int exclusion_count = 0;
	char **exclusion_list = NULL;

	memset(&ev, 0, sizeof(ev));
	memset(&dom, 0, sizeof(dom));

	if (opt_kernel) {
		if (opt_filter) {
			ERR("Filter not implement for kernel tracing yet");
			ret = CMD_ERROR;
			goto error;
		}
		if (opt_loglevel) {
			WARN("Kernel loglevels are not supported.");
		}
	}

	/* Create lttng domain */
	if (opt_kernel) {
		dom.type = LTTNG_DOMAIN_KERNEL;
		dom.buf_type = LTTNG_BUFFER_GLOBAL;
	} else if (opt_userspace) {
		dom.type = LTTNG_DOMAIN_UST;
		/* Default. */
		dom.buf_type = LTTNG_BUFFER_PER_UID;
	} else if (opt_jul) {
		dom.type = LTTNG_DOMAIN_JUL;
		/* Default. */
		dom.buf_type = LTTNG_BUFFER_PER_UID;
	} else if (opt_log4j) {
		dom.type = LTTNG_DOMAIN_LOG4J;
		/* Default. */
		dom.buf_type = LTTNG_BUFFER_PER_UID;
	} else if (opt_python) {
		dom.type = LTTNG_DOMAIN_PYTHON;
		/* Default. */
		dom.buf_type = LTTNG_BUFFER_PER_UID;
	} else {
		print_missing_domain();
		ret = CMD_ERROR;
		goto error;
	}

	if (opt_kernel && opt_exclude) {
		ERR("Event name exclusions are not yet implemented for kernel events");
		ret = CMD_ERROR;
		goto error;
	}

	channel_name = opt_channel_name;

	handle = lttng_create_handle(session_name, &dom);
	if (handle == NULL) {
		ret = -1;
		goto error;
	}

	/* Prepare Mi */
	if (lttng_opt_mi) {
		/* Open a events element */
		ret = mi_lttng_writer_open_element(writer, config_element_events);
		if (ret) {
			ret = CMD_ERROR;
			goto error;
		}
	}

	if (opt_enable_all) {
		/* Default setup for enable all */
		if (opt_kernel) {
			ev.type = opt_event_type;
			ev.name[0] = '\0';
			/* kernel loglevels not implemented */
			ev.loglevel_type = LTTNG_EVENT_LOGLEVEL_ALL;
		} else {
			ev.type = LTTNG_EVENT_TRACEPOINT;
			strcpy(ev.name, "*");
			ev.loglevel_type = opt_loglevel_type;
			if (opt_loglevel) {
				assert(opt_userspace || opt_jul || opt_log4j || opt_python);
				if (opt_userspace) {
					ev.loglevel = loglevel_str_to_value(opt_loglevel);
				} else if (opt_jul) {
					ev.loglevel = loglevel_jul_str_to_value(opt_loglevel);
				} else if (opt_log4j) {
					ev.loglevel = loglevel_log4j_str_to_value(opt_loglevel);
				} else if (opt_python) {
					ev.loglevel = loglevel_python_str_to_value(opt_loglevel);
				}
				if (ev.loglevel == -1) {
					ERR("Unknown loglevel %s", opt_loglevel);
					ret = -LTTNG_ERR_INVALID;
					goto error;
				}
			} else {
				assert(opt_userspace || opt_jul || opt_log4j || opt_python);
				if (opt_userspace) {
					ev.loglevel = -1;
				} else if (opt_jul || opt_log4j) {
					ev.loglevel = LTTNG_LOGLEVEL_JUL_ALL;
				} else if (opt_python) {
					ev.loglevel = LTTNG_LOGLEVEL_PYTHON_DEBUG;
				}
			}
		}

		if (opt_exclude) {
			ret = check_exclusion_subsets("*", opt_exclude,
					&exclusion_count, &exclusion_list);
			if (ret == CMD_ERROR) {
				goto error;
			}
			ev.exclusion = 1;
		}
		if (!opt_filter) {
			ret = lttng_enable_event_with_exclusions(handle,
					&ev, channel_name,
					NULL,
					exclusion_count, exclusion_list);
			if (ret < 0) {
				switch (-ret) {
				case LTTNG_ERR_KERN_EVENT_EXIST:
					WARN("Kernel events already enabled (channel %s, session %s)",
							print_channel_name(channel_name), session_name);
					warn = 1;
					break;
				case LTTNG_ERR_TRACE_ALREADY_STARTED:
				{
					const char *msg = "The command tried to enable an event in a new domain for a session that has already been started once.";
					ERR("Events: %s (channel %s, session %s)",
							msg,
							print_channel_name(channel_name),
							session_name);
					error = 1;
					break;
				}
				default:
					ERR("Events: %s (channel %s, session %s)",
							lttng_strerror(ret),
							ret == -LTTNG_ERR_NEED_CHANNEL_NAME
								? print_raw_channel_name(channel_name)
								: print_channel_name(channel_name),
							session_name);
					error = 1;
					break;
				}
				goto end;
			}

			switch (opt_event_type) {
			case LTTNG_EVENT_TRACEPOINT:
				if (opt_loglevel && dom.type != LTTNG_DOMAIN_KERNEL) {
					char *exclusion_string = print_exclusions(exclusion_count, exclusion_list);

					if (!exclusion_string) {
						PERROR("Cannot allocate exclusion_string");
						error = 1;
						goto end;
					}
					MSG("All %s tracepoints%s are enabled in channel %s for loglevel %s",
							get_domain_str(dom.type),
							exclusion_string,
							print_channel_name(channel_name),
							opt_loglevel);
					free(exclusion_string);
				} else {
					char *exclusion_string = print_exclusions(exclusion_count, exclusion_list);

					if (!exclusion_string) {
						PERROR("Cannot allocate exclusion_string");
						error = 1;
						goto end;
					}
					MSG("All %s tracepoints%s are enabled in channel %s",
							get_domain_str(dom.type),
							exclusion_string,
							print_channel_name(channel_name));
					free(exclusion_string);
				}
				break;
			case LTTNG_EVENT_SYSCALL:
				if (opt_kernel) {
					MSG("All %s system calls are enabled in channel %s",
							get_domain_str(dom.type),
							print_channel_name(channel_name));
				}
				break;
			case LTTNG_EVENT_ALL:
				if (opt_loglevel && dom.type != LTTNG_DOMAIN_KERNEL) {
					char *exclusion_string = print_exclusions(exclusion_count, exclusion_list);

					if (!exclusion_string) {
						PERROR("Cannot allocate exclusion_string");
						error = 1;
						goto end;
					}
					MSG("All %s events%s are enabled in channel %s for loglevel %s",
							get_domain_str(dom.type),
							exclusion_string,
							print_channel_name(channel_name),
							opt_loglevel);
					free(exclusion_string);
				} else {
					char *exclusion_string = print_exclusions(exclusion_count, exclusion_list);

					if (!exclusion_string) {
						PERROR("Cannot allocate exclusion_string");
						error = 1;
						goto end;
					}
					MSG("All %s events%s are enabled in channel %s",
							get_domain_str(dom.type),
							exclusion_string,
							print_channel_name(channel_name));
					free(exclusion_string);
				}
				break;
			default:
				/*
				 * We should not be here since lttng_enable_event should have
				 * failed on the event type.
				 */
				goto error;
			}
		}

		if (opt_filter) {
			command_ret = lttng_enable_event_with_exclusions(handle, &ev, channel_name,
						opt_filter, exclusion_count, exclusion_list);
			if (command_ret < 0) {
				switch (-command_ret) {
				case LTTNG_ERR_FILTER_EXIST:
					WARN("Filter on all events is already enabled"
							" (channel %s, session %s)",
						print_channel_name(channel_name), session_name);
					warn = 1;
					break;
				case LTTNG_ERR_TRACE_ALREADY_STARTED:
				{
					const char *msg = "The command tried to enable an event in a new domain for a session that has already been started once.";
					ERR("All events: %s (channel %s, session %s, filter \'%s\')",
							msg,
							print_channel_name(channel_name),
							session_name, opt_filter);
					error = 1;
					break;
				}
				default:
					ERR("All events: %s (channel %s, session %s, filter \'%s\')",
							lttng_strerror(command_ret),
							command_ret == -LTTNG_ERR_NEED_CHANNEL_NAME
								? print_raw_channel_name(channel_name)
								: print_channel_name(channel_name),
							session_name, opt_filter);
					error = 1;
					break;
				}
				error_holder = command_ret;
			} else {
				ev.filter = 1;
				MSG("Filter '%s' successfully set", opt_filter);
			}
		}

		if (lttng_opt_mi) {
			/* The wildcard * is used for kernel and ust domain to
			 * represent ALL. We copy * in event name to force the wildcard use
			 * for kernel domain
			 *
			 * Note: this is strictly for semantic and printing while in
			 * machine interface mode.
			 */
			strcpy(ev.name, "*");

			/* If we reach here the events are enabled */
			if (!error && !warn) {
				ev.enabled = 1;
			} else {
				ev.enabled = 0;
				success = 0;
			}
			ret = mi_lttng_event(writer, &ev, 1, handle->domain.type);
			if (ret) {
				ret = CMD_ERROR;
				goto error;
			}

			/* print exclusion */
			ret = mi_print_exclusion(exclusion_count, exclusion_list);
			if (ret) {
				ret = CMD_ERROR;
				goto error;
			}

			/* Success ? */
			ret = mi_lttng_writer_write_element_bool(writer,
					mi_lttng_element_command_success, success);
			if (ret) {
				ret = CMD_ERROR;
				goto error;
			}

			/* Close event element */
			ret = mi_lttng_writer_close_element(writer);
			if (ret) {
				ret = CMD_ERROR;
				goto error;
			}
		}

		goto end;
	}

	/* Strip event list */
	event_name = strtok(opt_event_list, ",");
	while (event_name != NULL) {
		/* Copy name and type of the event */
		strncpy(ev.name, event_name, LTTNG_SYMBOL_NAME_LEN);
		ev.name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0';
		ev.type = opt_event_type;

		/* Kernel tracer action */
		if (opt_kernel) {
			DBG("Enabling kernel event %s for channel %s",
					event_name,
					print_channel_name(channel_name));

			switch (opt_event_type) {
			case LTTNG_EVENT_ALL:	/* Default behavior is tracepoint */
				ev.type = LTTNG_EVENT_TRACEPOINT;
				/* Fall-through */
			case LTTNG_EVENT_TRACEPOINT:
				break;
			case LTTNG_EVENT_PROBE:
				ret = parse_probe_opts(&ev, opt_probe);
				if (ret) {
					ERR("Unable to parse probe options");
					ret = 0;
					goto error;
				}
				break;
			case LTTNG_EVENT_FUNCTION:
				ret = parse_probe_opts(&ev, opt_function);
				if (ret) {
					ERR("Unable to parse function probe options");
					ret = 0;
					goto error;
				}
				break;
			case LTTNG_EVENT_FUNCTION_ENTRY:
				strncpy(ev.attr.ftrace.symbol_name, opt_function_entry_symbol,
						LTTNG_SYMBOL_NAME_LEN);
				ev.attr.ftrace.symbol_name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0';
				break;
			case LTTNG_EVENT_SYSCALL:
				ev.type = LTTNG_EVENT_SYSCALL;
				break;
			default:
				ret = CMD_UNDEFINED;
				goto error;
			}

			/* kernel loglevels not implemented */
			ev.loglevel_type = LTTNG_EVENT_LOGLEVEL_ALL;
		} else if (opt_userspace) {		/* User-space tracer action */
#if 0
			if (opt_cmd_name != NULL || opt_pid) {
				MSG("Only supporting tracing all UST processes (-u) for now.");
				ret = CMD_UNDEFINED;
				goto error;
			}
#endif

			DBG("Enabling UST event %s for channel %s, loglevel %s", event_name,
					print_channel_name(channel_name), opt_loglevel ? : "<all>");

			switch (opt_event_type) {
			case LTTNG_EVENT_ALL:	/* Default behavior is tracepoint */
				/* Fall-through */
			case LTTNG_EVENT_TRACEPOINT:
				/* Copy name and type of the event */
				ev.type = LTTNG_EVENT_TRACEPOINT;
				strncpy(ev.name, event_name, LTTNG_SYMBOL_NAME_LEN);
				ev.name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0';
				break;
			case LTTNG_EVENT_PROBE:
			case LTTNG_EVENT_FUNCTION:
			case LTTNG_EVENT_FUNCTION_ENTRY:
			case LTTNG_EVENT_SYSCALL:
			default:
				ERR("Event type not available for user-space tracing");
				ret = CMD_UNSUPPORTED;
				goto error;
			}

			if (opt_exclude) {
				ev.exclusion = 1;
				if (opt_event_type != LTTNG_EVENT_ALL && opt_event_type != LTTNG_EVENT_TRACEPOINT) {
					ERR("Exclusion option can only be used with tracepoint events");
					ret = CMD_ERROR;
					goto error;
				}
				/* Free previously allocated items */
				if (exclusion_list != NULL) {
					while (exclusion_count--) {
						free(exclusion_list[exclusion_count]);
					}
					free(exclusion_list);
					exclusion_list = NULL;
				}
				/* Check for proper subsets */
				ret = check_exclusion_subsets(event_name, opt_exclude,
						&exclusion_count, &exclusion_list);
				if (ret == CMD_ERROR) {
					goto error;
				}
			}

			ev.loglevel_type = opt_loglevel_type;
			if (opt_loglevel) {
				ev.loglevel = loglevel_str_to_value(opt_loglevel);
				if (ev.loglevel == -1) {
					ERR("Unknown loglevel %s", opt_loglevel);
					ret = -LTTNG_ERR_INVALID;
					goto error;
				}
			} else {
				ev.loglevel = -1;
			}
		} else if (opt_jul || opt_log4j || opt_python) {
			if (opt_event_type != LTTNG_EVENT_ALL &&
					opt_event_type != LTTNG_EVENT_TRACEPOINT) {
				ERR("Event type not supported for domain.");
				ret = CMD_UNSUPPORTED;
				goto error;
			}

			ev.loglevel_type = opt_loglevel_type;
			if (opt_loglevel) {
				if (opt_jul) {
					ev.loglevel = loglevel_jul_str_to_value(opt_loglevel);
				} else if (opt_log4j) {
					ev.loglevel = loglevel_log4j_str_to_value(opt_loglevel);
				} else if (opt_python) {
					ev.loglevel = loglevel_python_str_to_value(opt_loglevel);
				}
				if (ev.loglevel == -1) {
					ERR("Unknown loglevel %s", opt_loglevel);
					ret = -LTTNG_ERR_INVALID;
					goto error;
				}
			} else {
				if (opt_jul) {
					ev.loglevel = LTTNG_LOGLEVEL_JUL_ALL;
				} else if (opt_log4j) {
					ev.loglevel = LTTNG_LOGLEVEL_LOG4J_ALL;
				} else if (opt_python) {
					ev.loglevel = LTTNG_LOGLEVEL_PYTHON_DEBUG;
				}
			}
			ev.type = LTTNG_EVENT_TRACEPOINT;
			strncpy(ev.name, event_name, LTTNG_SYMBOL_NAME_LEN);
			ev.name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0';
		} else {
			print_missing_domain();
			ret = CMD_ERROR;
			goto error;
		}

		if (!opt_filter) {
			char *exclusion_string;

			command_ret = lttng_enable_event_with_exclusions(handle,
					&ev, channel_name,
					NULL, exclusion_count, exclusion_list);
			exclusion_string = print_exclusions(exclusion_count, exclusion_list);
			if (!exclusion_string) {
				PERROR("Cannot allocate exclusion_string");
				error = 1;
				goto end;
			}
			if (command_ret < 0) {
				/* Turn ret to positive value to handle the positive error code */
				switch (-command_ret) {
				case LTTNG_ERR_KERN_EVENT_EXIST:
					WARN("Kernel event %s%s already enabled (channel %s, session %s)",
							event_name,
							exclusion_string,
							print_channel_name(channel_name), session_name);
					warn = 1;
					break;
				case LTTNG_ERR_TRACE_ALREADY_STARTED:
				{
					const char *msg = "The command tried to enable an event in a new domain for a session that has already been started once.";
					ERR("Event %s%s: %s (channel %s, session %s)", event_name,
							exclusion_string,
							msg,
							print_channel_name(channel_name),
							session_name);
					error = 1;
					break;
				}
				default:
					ERR("Event %s%s: %s (channel %s, session %s)", event_name,
							exclusion_string,
							lttng_strerror(command_ret),
							command_ret == -LTTNG_ERR_NEED_CHANNEL_NAME
								? print_raw_channel_name(channel_name)
								: print_channel_name(channel_name),
							session_name);
					error = 1;
					break;
				}
				error_holder = command_ret;
			} else {
				/* So we don't print the default channel name for agent domain. */
				if (dom.type == LTTNG_DOMAIN_JUL ||
						dom.type == LTTNG_DOMAIN_LOG4J) {
					MSG("%s event %s%s enabled.",
							get_domain_str(dom.type), event_name,
							exclusion_string);
				} else {
					MSG("%s event %s%s created in channel %s",
							get_domain_str(dom.type), event_name,
							exclusion_string,
							print_channel_name(channel_name));
				}
			}
			free(exclusion_string);
		}

		if (opt_filter) {
			char *exclusion_string;

			/* Filter present */
			ev.filter = 1;

			command_ret = lttng_enable_event_with_exclusions(handle, &ev, channel_name,
					opt_filter, exclusion_count, exclusion_list);
			exclusion_string = print_exclusions(exclusion_count, exclusion_list);
			if (!exclusion_string) {
				PERROR("Cannot allocate exclusion_string");
				error = 1;
				goto end;
			}
			if (command_ret < 0) {
				switch (-command_ret) {
				case LTTNG_ERR_FILTER_EXIST:
					WARN("Filter on event %s%s is already enabled"
							" (channel %s, session %s)",
						event_name,
						exclusion_string,
						print_channel_name(channel_name), session_name);
					warn = 1;
					break;
				case LTTNG_ERR_TRACE_ALREADY_STARTED:
				{
					const char *msg = "The command tried to enable an event in a new domain for a session that has already been started once.";
					ERR("Event %s%s: %s (channel %s, session %s, filter \'%s\')", ev.name,
							exclusion_string,
							msg,
							print_channel_name(channel_name),
							session_name, opt_filter);
					error = 1;
					break;
				}
				default:
					ERR("Event %s%s: %s (channel %s, session %s, filter \'%s\')", ev.name,
							exclusion_string,
							lttng_strerror(command_ret),
							command_ret == -LTTNG_ERR_NEED_CHANNEL_NAME
								? print_raw_channel_name(channel_name)
								: print_channel_name(channel_name),
							session_name, opt_filter);
					error = 1;
					break;
				}
				error_holder = command_ret;

			} else {
				MSG("Event %s%s: Filter '%s' successfully set",
						event_name, exclusion_string,
						opt_filter);
			}
			free(exclusion_string);
		}

		if (lttng_opt_mi) {
			if (command_ret) {
				success = 0;
				ev.enabled = 0;
			} else {
				ev.enabled = 1;
			}

			ret = mi_lttng_event(writer, &ev, 1, handle->domain.type);
			if (ret) {
				ret = CMD_ERROR;
				goto error;
			}

			/* print exclusion */
			ret = mi_print_exclusion(exclusion_count, exclusion_list);
			if (ret) {
				ret = CMD_ERROR;
				goto error;
			}

			/* Success ? */
			ret = mi_lttng_writer_write_element_bool(writer,
					mi_lttng_element_command_success, success);
			if (ret) {
				ret = CMD_ERROR;
				goto end;
			}

			/* Close event element */
			ret = mi_lttng_writer_close_element(writer);
			if (ret) {
				ret = CMD_ERROR;
				goto end;
			}
		}

		/* Next event */
		event_name = strtok(NULL, ",");
		/* Reset warn, error and success */
		success = 1;
	}
Пример #14
0
/*
 * The 'save <options>' first level command
 */
int cmd_save(int argc, const char **argv)
{
	int ret = CMD_SUCCESS, command_ret = CMD_SUCCESS, success;
	int opt;
	const char *session_name = NULL;
	poptContext pc;
	struct lttng_save_session_attr *attr;

	pc = poptGetContext(NULL, argc, argv, save_opts, 0);
	poptReadDefaultConfig(pc, 0);

	while ((opt = poptGetNextOpt(pc)) != -1) {
		switch (opt) {
		case OPT_HELP:
			usage(stdout);
			goto end;
		case OPT_ALL:
			opt_save_all = 1;
			break;
		case OPT_FORCE:
			opt_force = 1;
			break;
		case OPT_LIST_OPTIONS:
			list_cmd_options(stdout, save_opts);
			goto end;
		default:
			usage(stderr);
			ret = CMD_UNDEFINED;
			goto end;
		}
	}

	if (!opt_save_all) {
		session_name = poptGetArg(pc);
		if (session_name) {
			DBG2("Session name: %s", session_name);
		} else {
			/* default to opt_save_all */
			opt_save_all = 1;
		}
	}

	attr = lttng_save_session_attr_create();
	if (!attr) {
		ret = CMD_FATAL;
		goto end_destroy;
	}

	if (lttng_save_session_attr_set_session_name(attr, session_name)) {
		ret = CMD_ERROR;
		goto end_destroy;
	}

	if (lttng_save_session_attr_set_overwrite(attr, opt_force)) {
		ret = CMD_ERROR;
		goto end_destroy;
	}

	if (lttng_save_session_attr_set_output_url(attr, opt_output_path)) {
		ret = CMD_ERROR;
		goto end_destroy;
	}

	/* Mi check */
	if (lttng_opt_mi) {
		writer = mi_lttng_writer_create(fileno(stdout), lttng_opt_mi);
		if (!writer) {
			ret = -LTTNG_ERR_NOMEM;
			goto end_destroy;
		}

		/* Open command element */
		ret = mi_lttng_writer_command_open(writer,
				mi_lttng_element_command_save);
		if (ret) {
			ret = CMD_ERROR;
			goto end_destroy;
		}

		/* Open output element */
		ret = mi_lttng_writer_open_element(writer,
				mi_lttng_element_command_output);
		if (ret) {
			ret = CMD_ERROR;
			goto end_destroy;
		}
	}

	command_ret = lttng_save_session(attr);
	if (command_ret < 0) {
		ERR("%s", lttng_strerror(command_ret));
		success = 0;
	} else {
		/* Inform the user of what just happened on success. */
		if (session_name && opt_output_path) {
			MSG("Session %s saved successfully in %s.", session_name,
					opt_output_path);
		} else if (session_name && !opt_output_path) {
			MSG("Session %s saved successfully.", session_name);
		} else if (!session_name && opt_output_path) {
			MSG("All sessions have been saved successfully in %s.",
					opt_output_path);
		} else {
			MSG("All sessions have been saved successfully.");
		}
		success = 1;
	}

	/* Mi Printing and closing */
	if (lttng_opt_mi) {
		/* Mi print */
		ret = mi_save_print(session_name);
		if (ret) {
			ret = CMD_ERROR;
			goto end_destroy;
		}

		/* Close  output element */
		ret = mi_lttng_writer_close_element(writer);
		if (ret) {
			ret = CMD_ERROR;
			goto end_destroy;
		}

		/* Success ? */
		ret = mi_lttng_writer_write_element_bool(writer,
				mi_lttng_element_command_success, success);
		if (ret) {
			ret = CMD_ERROR;
			goto end_destroy;
		}

		/* Command element close */
		ret = mi_lttng_writer_command_close(writer);
		if (ret) {
			ret = CMD_ERROR;
			goto end_destroy;
		}
	}
end_destroy:
	lttng_save_session_attr_destroy(attr);
end:
	/* Mi clean-up */
	if (writer && mi_lttng_writer_destroy(writer)) {
		/* Preserve original error code */
		ret = ret ? ret : -LTTNG_ERR_MI_IO_FAIL;
	}

	/* Overwrite ret if command failed */
	ret = command_ret ? -command_ret : ret;

	poptFreeContext(pc);
	return ret;
}
Пример #15
0
/*
 * Adding channel using the lttng API.
 */
static int enable_channel(char *session_name)
{
	struct lttng_channel *channel = NULL;
	int ret = CMD_SUCCESS, warn = 0, error = 0, success = 0;
	char *channel_name;
	struct lttng_domain dom;

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

	/* Validate options. */
	if (opt_kernel) {
		if (opt_blocking_timeout.set) {
			ERR("Retry timeout option not supported for kernel domain (-k)");
			ret = CMD_ERROR;
			goto error;
		}
	}

	/* Create lttng domain */
	if (opt_kernel) {
		dom.type = LTTNG_DOMAIN_KERNEL;
		dom.buf_type = LTTNG_BUFFER_GLOBAL;
		if (opt_buffer_uid || opt_buffer_pid) {
			ERR("Buffer type not supported for domain -k");
			ret = CMD_ERROR;
			goto error;
		}
	} else if (opt_userspace) {
		dom.type = LTTNG_DOMAIN_UST;
		if (opt_buffer_pid) {
			dom.buf_type = LTTNG_BUFFER_PER_PID;
		} else {
			if (opt_buffer_global) {
				ERR("Buffer type not supported for domain -u");
				ret = CMD_ERROR;
				goto error;
			}
			dom.buf_type = LTTNG_BUFFER_PER_UID;
		}
	} else {
		/* Checked by the caller. */
		assert(0);
	}

	set_default_attr(&dom);

	if (chan_opts.attr.tracefile_size == 0 && chan_opts.attr.tracefile_count) {
		ERR("Missing option --tracefile-size. "
				"A file count without a size won't do anything.");
		ret = CMD_ERROR;
		goto error;
	}

	if ((chan_opts.attr.tracefile_size > 0) &&
			(chan_opts.attr.tracefile_size < chan_opts.attr.subbuf_size)) {
		WARN("Tracefile size rounded up from (%" PRIu64 ") to subbuffer size (%" PRIu64 ")",
				chan_opts.attr.tracefile_size, chan_opts.attr.subbuf_size);
		chan_opts.attr.tracefile_size = chan_opts.attr.subbuf_size;
	}

	/* Setting channel output */
	if (opt_output) {
		if (!strncmp(output_mmap, opt_output, strlen(output_mmap))) {
			chan_opts.attr.output = LTTNG_EVENT_MMAP;
		} else if (!strncmp(output_splice, opt_output, strlen(output_splice))) {
			chan_opts.attr.output = LTTNG_EVENT_SPLICE;
		} else {
			ERR("Unknown output type %s. Possible values are: %s, %s\n",
					opt_output, output_mmap, output_splice);
			ret = CMD_ERROR;
			goto error;
		}
	}

	handle = lttng_create_handle(session_name, &dom);
	if (handle == NULL) {
		ret = -1;
		goto error;
	}

	/* Mi open channels element */
	if (lttng_opt_mi) {
		assert(writer);
		ret = mi_lttng_channels_open(writer);
		if (ret) {
			ret = CMD_ERROR;
			goto error;
		}
	}

	/* Strip channel list (format: chan1,chan2,...) */
	channel_name = strtok(opt_channels, ",");
	while (channel_name != NULL) {
		void *extended_ptr;

		/* Validate channel name's length */
		if (strlen(channel_name) >= sizeof(chan_opts.name)) {
			ERR("Channel name is too long (max. %zu characters)",
					sizeof(chan_opts.name) - 1);
			error = 1;
			goto skip_enable;
		}

		/*
		 * A dynamically-allocated channel is used in order to allow
		 * the configuration of extended attributes (post-2.9).
		 */
		channel = lttng_channel_create(&dom);
		if (!channel) {
			ERR("Unable to create channel object");
			error = 1;
			goto error;
		}

		/* Copy channel name */
		strcpy(channel->name, channel_name);
		channel->enabled = 1;
		extended_ptr = channel->attr.extended.ptr;
		memcpy(&channel->attr, &chan_opts.attr, sizeof(chan_opts.attr));
		channel->attr.extended.ptr = extended_ptr;
		if (opt_monitor_timer.set) {
			ret = lttng_channel_set_monitor_timer_interval(channel,
					opt_monitor_timer.interval);
			if (ret) {
				ERR("Failed to set the channel's monitor timer interval");
				error = 1;
				goto error;
			}
		}
		if (opt_blocking_timeout.set) {
			ret = lttng_channel_set_blocking_timeout(channel,
					opt_blocking_timeout.value);
			if (ret) {
				ERR("Failed to set the channel's blocking timeout");
				error = 1;
				goto error;
			}
		}

		DBG("Enabling channel %s", channel_name);

		ret = lttng_enable_channel(handle, channel);
		if (ret < 0) {
			success = 0;
			switch (-ret) {
			case LTTNG_ERR_KERN_CHAN_EXIST:
			case LTTNG_ERR_UST_CHAN_EXIST:
			case LTTNG_ERR_CHAN_EXIST:
				WARN("Channel %s: %s (session %s)", channel_name,
						lttng_strerror(ret), session_name);
				warn = 1;
				break;
			case LTTNG_ERR_INVALID_CHANNEL_NAME:
				ERR("Invalid channel name: \"%s\". "
				    "Channel names may not start with '.', and "
				    "may not contain '/'.", channel_name);
				error = 1;
				break;
			default:
				ERR("Channel %s: %s (session %s)", channel_name,
						lttng_strerror(ret), session_name);
				error = 1;
				break;
			}
		} else {
			MSG("%s channel %s enabled for session %s",
					get_domain_str(dom.type), channel_name, session_name);
			success = 1;
		}

skip_enable:
		if (lttng_opt_mi) {
			/* Mi print the channel element and leave it open */
			ret = mi_lttng_channel(writer, channel, 1);
			if (ret) {
				ret = CMD_ERROR;
				goto error;
			}

			/* Individual Success ? */
			ret = mi_lttng_writer_write_element_bool(writer,
					mi_lttng_element_command_success, success);
			if (ret) {
				ret = CMD_ERROR;
				goto error;
			}

			/* Close channel element */
			ret = mi_lttng_writer_close_element(writer);
			if (ret) {
				ret = CMD_ERROR;
				goto error;
			}
		}

		/* Next channel */
		channel_name = strtok(NULL, ",");
		lttng_channel_destroy(channel);
		channel = NULL;
	}

	if (lttng_opt_mi) {
		/* Close channels element */
		ret = mi_lttng_writer_close_element(writer);
		if (ret) {
			ret = CMD_ERROR;
			goto error;
		}
	}

	ret = CMD_SUCCESS;

error:
	if (channel) {
		lttng_channel_destroy(channel);
	}
	/* If more important error happen bypass the warning */
	if (!ret && warn) {
		ret = CMD_WARNING;
	}
	/* If more important error happen bypass the warning */
	if (!ret && error) {
		ret = CMD_ERROR;
	}

	lttng_destroy_handle(handle);

	return ret;
}
Пример #16
0
/*
 * Add channel to trace session
 */
int cmd_enable_channels(int argc, const char **argv)
{
	int opt, ret = CMD_SUCCESS, command_ret = CMD_SUCCESS, success = 1;
	static poptContext pc;
	char *session_name = NULL;
	char *opt_arg = NULL;

	init_channel_config();

	pc = poptGetContext(NULL, argc, argv, long_options, 0);
	poptReadDefaultConfig(pc, 0);

	while ((opt = poptGetNextOpt(pc)) != -1) {
		switch (opt) {
		case OPT_HELP:
			usage(stdout);
			goto end;
		case OPT_DISCARD:
			chan.attr.overwrite = 0;
			DBG("Channel set to discard");
			break;
		case OPT_OVERWRITE:
			chan.attr.overwrite = 1;
			DBG("Channel set to overwrite");
			break;
		case OPT_SUBBUF_SIZE:
		{
			uint64_t rounded_size;
			int order;

			/* Parse the size */
			opt_arg = poptGetOptArg(pc);
			if (utils_parse_size_suffix(opt_arg, &chan.attr.subbuf_size) < 0 || !chan.attr.subbuf_size) {
				ERR("Wrong value in --subbuf-size parameter: %s", opt_arg);
				ret = CMD_ERROR;
				goto end;
			}

			order = get_count_order_u64(chan.attr.subbuf_size);
			assert(order >= 0);
			rounded_size = 1ULL << order;
			if (rounded_size < chan.attr.subbuf_size) {
				ERR("The subbuf size (%" PRIu64 ") is rounded and overflows!",
						chan.attr.subbuf_size);
				ret = CMD_ERROR;
				goto end;
			}

			if (rounded_size != chan.attr.subbuf_size) {
				WARN("The subbuf size (%" PRIu64 ") is rounded to the next power of 2 (%" PRIu64 ")",
						chan.attr.subbuf_size, rounded_size);
				chan.attr.subbuf_size = rounded_size;
			}

			/* Should now be power of 2 */
			assert(!((chan.attr.subbuf_size - 1) & chan.attr.subbuf_size));

			DBG("Channel subbuf size set to %" PRIu64, chan.attr.subbuf_size);
			break;
		}
		case OPT_NUM_SUBBUF:
		{
			uint64_t rounded_size;
			int order;

			errno = 0;
			opt_arg = poptGetOptArg(pc);
			chan.attr.num_subbuf = strtoull(opt_arg, NULL, 0);
			if (errno != 0 || !chan.attr.num_subbuf || !isdigit(opt_arg[0])) {
				ERR("Wrong value in --num-subbuf parameter: %s", opt_arg);
				ret = CMD_ERROR;
				goto end;
			}

			order = get_count_order_u64(chan.attr.num_subbuf);
			assert(order >= 0);
			rounded_size = 1ULL << order;
			if (rounded_size < chan.attr.num_subbuf) {
				ERR("The number of subbuffers (%" PRIu64 ") is rounded and overflows!",
						chan.attr.num_subbuf);
				ret = CMD_ERROR;
				goto end;
			}

			if (rounded_size != chan.attr.num_subbuf) {
				WARN("The number of subbuffers (%" PRIu64 ") is rounded to the next power of 2 (%" PRIu64 ")",
						chan.attr.num_subbuf, rounded_size);
				chan.attr.num_subbuf = rounded_size;
			}

			/* Should now be power of 2 */
			assert(!((chan.attr.num_subbuf - 1) & chan.attr.num_subbuf));

			DBG("Channel subbuf num set to %" PRIu64, chan.attr.num_subbuf);
			break;
		}
		case OPT_SWITCH_TIMER:
		{
			unsigned long v;

			errno = 0;
			opt_arg = poptGetOptArg(pc);
			v = strtoul(opt_arg, NULL, 0);
			if (errno != 0 || !isdigit(opt_arg[0])) {
				ERR("Wrong value in --switch-timer parameter: %s", opt_arg);
				ret = CMD_ERROR;
				goto end;
			}
			if (v != (uint32_t) v) {
				ERR("32-bit overflow in --switch-timer parameter: %s", opt_arg);
				ret = CMD_ERROR;
				goto end;
			}
			chan.attr.switch_timer_interval = (uint32_t) v;
			DBG("Channel switch timer interval set to %d", chan.attr.switch_timer_interval);
			break;
		}
		case OPT_READ_TIMER:
		{
			unsigned long v;

			errno = 0;
			opt_arg = poptGetOptArg(pc);
			v = strtoul(opt_arg, NULL, 0);
			if (errno != 0 || !isdigit(opt_arg[0])) {
				ERR("Wrong value in --read-timer parameter: %s", opt_arg);
				ret = CMD_ERROR;
				goto end;
			}
			if (v != (uint32_t) v) {
				ERR("32-bit overflow in --read-timer parameter: %s", opt_arg);
				ret = CMD_ERROR;
				goto end;
			}
			chan.attr.read_timer_interval = (uint32_t) v;
			DBG("Channel read timer interval set to %d", chan.attr.read_timer_interval);
			break;
		}
		case OPT_USERSPACE:
			opt_userspace = 1;
			break;
		case OPT_TRACEFILE_SIZE:
			opt_arg = poptGetOptArg(pc);
			if (utils_parse_size_suffix(opt_arg, &chan.attr.tracefile_size) < 0) {
				ERR("Wrong value in --tracefile-size parameter: %s", opt_arg);
				ret = CMD_ERROR;
				goto end;
			}
			DBG("Maximum tracefile size set to %" PRIu64,
					chan.attr.tracefile_size);
			break;
		case OPT_TRACEFILE_COUNT:
		{
			unsigned long v;

			errno = 0;
			opt_arg = poptGetOptArg(pc);
			v = strtoul(opt_arg, NULL, 0);
			if (errno != 0 || !isdigit(opt_arg[0])) {
				ERR("Wrong value in --tracefile-count parameter: %s", opt_arg);
				ret = CMD_ERROR;
				goto end;
			}
			if (v != (uint32_t) v) {
				ERR("32-bit overflow in --tracefile-count parameter: %s", opt_arg);
				ret = CMD_ERROR;
				goto end;
			}
			chan.attr.tracefile_count = (uint32_t) v;
			DBG("Maximum tracefile count set to %" PRIu64,
					chan.attr.tracefile_count);
			break;
		}
		case OPT_LIST_OPTIONS:
			list_cmd_options(stdout, long_options);
			goto end;
		default:
			usage(stderr);
			ret = CMD_UNDEFINED;
			goto end;
		}
	}

	/* Mi check */
	if (lttng_opt_mi) {
		writer = mi_lttng_writer_create(fileno(stdout), lttng_opt_mi);
		if (!writer) {
			ret = -LTTNG_ERR_NOMEM;
			goto end;
		}

		/* Open command element */
		ret = mi_lttng_writer_command_open(writer,
				mi_lttng_element_command_enable_channels);
		if (ret) {
			ret = CMD_ERROR;
			goto end;
		}

		/* Open output element */
		ret = mi_lttng_writer_open_element(writer,
				mi_lttng_element_command_output);
		if (ret) {
			ret = CMD_ERROR;
			goto end;
		}
	}

	opt_channels = (char*) poptGetArg(pc);
	if (opt_channels == NULL) {
		ERR("Missing channel name.\n");
		usage(stderr);
		ret = CMD_ERROR;
		success = 0;
		goto mi_closing;
	}

	if (!opt_session_name) {
		session_name = get_session_name();
		if (session_name == NULL) {
			command_ret = CMD_ERROR;
			success = 0;
			goto mi_closing;
		}
	} else {
		session_name = opt_session_name;
	}

	command_ret = enable_channel(session_name);
	if (command_ret) {
		success = 0;
	}

mi_closing:
	/* Mi closing */
	if (lttng_opt_mi) {
		/* Close  output element */
		ret = mi_lttng_writer_close_element(writer);
		if (ret) {
			goto end;
		}

		/* Success ? */
		ret = mi_lttng_writer_write_element_bool(writer,
				mi_lttng_element_command_success, success);
		if (ret) {
			goto end;
		}

		/* Command element close */
		ret = mi_lttng_writer_command_close(writer);
		if (ret) {
			goto end;
		}
	}

end:
	/* Mi clean-up */
	if (writer && mi_lttng_writer_destroy(writer)) {
		/* Preserve original error code */
		ret = ret ? ret : LTTNG_ERR_MI_IO_FAIL;
	}

	if (!opt_session_name && session_name) {
		free(session_name);
	}

	/* Overwrite ret if an error occurred when enable_channel */
	ret = command_ret ? command_ret : ret;
	poptFreeContext(pc);
	return ret;
}
Пример #17
0
/*
 *  cmd_stop
 *
 *  The 'stop <options>' first level command
 */
int cmd_stop(int argc, const char **argv)
{
	int opt, ret = CMD_SUCCESS, command_ret = CMD_SUCCESS, success = 1;
	static poptContext pc;
	const char *leftover = NULL;

	pc = poptGetContext(NULL, argc, argv, long_options, 0);
	poptReadDefaultConfig(pc, 0);

	while ((opt = poptGetNextOpt(pc)) != -1) {
		switch (opt) {
		case OPT_HELP:
			SHOW_HELP();
			goto end;
		case OPT_LIST_OPTIONS:
			list_cmd_options(stdout, long_options);
			goto end;
		default:
			ret = CMD_UNDEFINED;
			goto end;
		}
	}

	/* Mi check */
	if (lttng_opt_mi) {
		writer = mi_lttng_writer_create(fileno(stdout), lttng_opt_mi);
		if (!writer) {
			ret = -LTTNG_ERR_NOMEM;
			goto end;
		}

		/* Open command element */
		ret = mi_lttng_writer_command_open(writer,
				mi_lttng_element_command_stop);
		if (ret) {
			ret = CMD_ERROR;
			goto end;
		}

		/* Open output element */
		ret = mi_lttng_writer_open_element(writer,
				mi_lttng_element_command_output);
		if (ret) {
			ret = CMD_ERROR;
			goto end;
		}

		/*
		 * Open sessions element
		 * For validation
		 */
		ret = mi_lttng_writer_open_element(writer,
				config_element_sessions);
		if (ret) {
			ret = CMD_ERROR;
			goto end;
		}
	}

	opt_session_name = (char*) poptGetArg(pc);

	leftover = poptGetArg(pc);
	if (leftover) {
		ERR("Unknown argument: %s", leftover);
		ret = CMD_ERROR;
		goto end;
	}

	command_ret = stop_tracing();
	if (command_ret) {
		success = 0;
	}

	/* Mi closing */
	if (lttng_opt_mi) {
		/* Close sessions and  output element */
		ret = mi_lttng_close_multi_element(writer, 2);
		if (ret) {
			ret = CMD_ERROR;
			goto end;
		}

		/* Success ? */
		ret = mi_lttng_writer_write_element_bool(writer,
				mi_lttng_element_command_success, success);
		if (ret) {
			ret = CMD_ERROR;
			goto end;
		}

		/* Command element close */
		ret = mi_lttng_writer_command_close(writer);
		if (ret) {
			ret = CMD_ERROR;
			goto end;
		}
	}

end:
	/* Mi clean-up */
	if (writer && mi_lttng_writer_destroy(writer)) {
		/* Preserve original error code */
		ret = ret ? ret : -LTTNG_ERR_MI_IO_FAIL;
	}

	/* Overwrite ret if an error occurred in stop_tracing() */
	ret = command_ret ? command_ret : ret;

	poptFreeContext(pc);
	return ret;
}
Пример #18
0
/*
 * Add channel to trace session
 */
int cmd_enable_channels(int argc, const char **argv)
{
	int opt, ret = CMD_SUCCESS, command_ret = CMD_SUCCESS, success = 1;
	static poptContext pc;
	char *session_name = NULL;
	char *opt_arg = NULL;
	const char *leftover = NULL;

	init_channel_config();

	pc = poptGetContext(NULL, argc, argv, long_options, 0);
	poptReadDefaultConfig(pc, 0);

	while ((opt = poptGetNextOpt(pc)) != -1) {
		switch (opt) {
		case OPT_HELP:
			SHOW_HELP();
			goto end;
		case OPT_DISCARD:
			chan_opts.attr.overwrite = 0;
			DBG("Channel set to discard");
			break;
		case OPT_OVERWRITE:
			chan_opts.attr.overwrite = 1;
			DBG("Channel set to overwrite");
			break;
		case OPT_SUBBUF_SIZE:
		{
			uint64_t rounded_size;
			int order;

			/* Parse the size */
			opt_arg = poptGetOptArg(pc);
			if (utils_parse_size_suffix(opt_arg, &chan_opts.attr.subbuf_size) < 0 || !chan_opts.attr.subbuf_size) {
				ERR("Wrong value in --subbuf-size parameter: %s", opt_arg);
				ret = CMD_ERROR;
				goto end;
			}

			order = get_count_order_u64(chan_opts.attr.subbuf_size);
			assert(order >= 0);
			rounded_size = 1ULL << order;
			if (rounded_size < chan_opts.attr.subbuf_size) {
				ERR("The subbuf size (%" PRIu64 ") is rounded and overflows!",
						chan_opts.attr.subbuf_size);
				ret = CMD_ERROR;
				goto end;
			}

			if (rounded_size != chan_opts.attr.subbuf_size) {
				WARN("The subbuf size (%" PRIu64 ") is rounded to the next power of 2 (%" PRIu64 ")",
						chan_opts.attr.subbuf_size, rounded_size);
				chan_opts.attr.subbuf_size = rounded_size;
			}

			/* Should now be power of 2 */
			assert(!((chan_opts.attr.subbuf_size - 1) & chan_opts.attr.subbuf_size));

			DBG("Channel subbuf size set to %" PRIu64, chan_opts.attr.subbuf_size);
			break;
		}
		case OPT_NUM_SUBBUF:
		{
			uint64_t rounded_size;
			int order;

			errno = 0;
			opt_arg = poptGetOptArg(pc);
			chan_opts.attr.num_subbuf = strtoull(opt_arg, NULL, 0);
			if (errno != 0 || !chan_opts.attr.num_subbuf || !isdigit(opt_arg[0])) {
				ERR("Wrong value in --num-subbuf parameter: %s", opt_arg);
				ret = CMD_ERROR;
				goto end;
			}

			order = get_count_order_u64(chan_opts.attr.num_subbuf);
			assert(order >= 0);
			rounded_size = 1ULL << order;
			if (rounded_size < chan_opts.attr.num_subbuf) {
				ERR("The number of subbuffers (%" PRIu64 ") is rounded and overflows!",
						chan_opts.attr.num_subbuf);
				ret = CMD_ERROR;
				goto end;
			}

			if (rounded_size != chan_opts.attr.num_subbuf) {
				WARN("The number of subbuffers (%" PRIu64 ") is rounded to the next power of 2 (%" PRIu64 ")",
						chan_opts.attr.num_subbuf, rounded_size);
				chan_opts.attr.num_subbuf = rounded_size;
			}

			/* Should now be power of 2 */
			assert(!((chan_opts.attr.num_subbuf - 1) & chan_opts.attr.num_subbuf));

			DBG("Channel subbuf num set to %" PRIu64, chan_opts.attr.num_subbuf);
			break;
		}
		case OPT_SWITCH_TIMER:
		{
			uint64_t v;

			errno = 0;
			opt_arg = poptGetOptArg(pc);

			if (utils_parse_time_suffix(opt_arg, &v) < 0) {
				ERR("Wrong value for --switch-timer parameter: %s", opt_arg);
				ret = CMD_ERROR;
				goto end;
			}

			if (v != (uint32_t) v) {
				ERR("32-bit overflow in --switch-timer parameter: %s", opt_arg);
				ret = CMD_ERROR;
				goto end;
			}
			chan_opts.attr.switch_timer_interval = (uint32_t) v;
			DBG("Channel switch timer interval set to %d %s",
					chan_opts.attr.switch_timer_interval,
					USEC_UNIT);
			break;
		}
		case OPT_READ_TIMER:
		{
			uint64_t v;

			errno = 0;
			opt_arg = poptGetOptArg(pc);

			if (utils_parse_time_suffix(opt_arg, &v) < 0) {
				ERR("Wrong value for --read-timer parameter: %s", opt_arg);
				ret = CMD_ERROR;
				goto end;
			}

			if (v != (uint32_t) v) {
				ERR("32-bit overflow in --read-timer parameter: %s", opt_arg);
				ret = CMD_ERROR;
				goto end;
			}
			chan_opts.attr.read_timer_interval = (uint32_t) v;
			DBG("Channel read timer interval set to %d %s",
					chan_opts.attr.read_timer_interval,
					USEC_UNIT);
			break;
		}
		case OPT_MONITOR_TIMER:
		{
			uint64_t v;

			errno = 0;
			opt_arg = poptGetOptArg(pc);

			if (utils_parse_time_suffix(opt_arg, &v) < 0) {
				ERR("Wrong value for --monitor-timer parameter: %s", opt_arg);
				ret = CMD_ERROR;
				goto end;
			}
			opt_monitor_timer.interval = (uint64_t) v;
			opt_monitor_timer.set = true;
			DBG("Channel monitor timer interval set to %" PRIu64 " %s",
					opt_monitor_timer.interval,
					USEC_UNIT);
			break;
		}
		case OPT_BLOCKING_TIMEOUT:
		{
			uint64_t v;
			long long v_msec;

			errno = 0;
			opt_arg = poptGetOptArg(pc);

			if (strcmp(opt_arg, "inf") == 0) {
				opt_blocking_timeout.value = (int64_t) -1;
				opt_blocking_timeout.set = true;
				DBG("Channel blocking timeout set to infinity");
				break;
			}

			if (utils_parse_time_suffix(opt_arg, &v) < 0) {
				ERR("Wrong value for --blocking-timeout parameter: %s", opt_arg);
				ret = CMD_ERROR;
				goto end;
			}

			/*
			 * While LTTng-UST and LTTng-tools will accept a
			 * blocking timeout expressed in µs, the current
			 * tracer implementation relies on poll() which
			 * takes an "int timeout" parameter expressed in
			 * msec.
			 *
			 * Since the error reporting from the tracer is
			 * not precise, we perform this check here to
			 * provide a helpful error message in case of
			 * overflow.
			 *
			 * The setter (liblttng-ctl) also performs an
			 * equivalent check.
			 */
			v_msec = v / 1000;
			if (v_msec != (int32_t) v_msec) {
				ERR("32-bit milliseconds overflow in --blocking-timeout parameter: %s", opt_arg);
				ret = CMD_ERROR;
				goto end;
			}

			opt_blocking_timeout.value = (int64_t) v;
			opt_blocking_timeout.set = true;
			DBG("Channel blocking timeout set to %" PRId64 " %s%s",
					opt_blocking_timeout.value,
					USEC_UNIT,
					opt_blocking_timeout.value == 0 ?
						" (non-blocking)" : "");
			break;
		}
		case OPT_USERSPACE:
			opt_userspace = 1;
			break;
		case OPT_TRACEFILE_SIZE:
			opt_arg = poptGetOptArg(pc);
			if (utils_parse_size_suffix(opt_arg, &chan_opts.attr.tracefile_size) < 0) {
				ERR("Wrong value in --tracefile-size parameter: %s", opt_arg);
				ret = CMD_ERROR;
				goto end;
			}
			DBG("Maximum tracefile size set to %" PRIu64,
					chan_opts.attr.tracefile_size);
			break;
		case OPT_TRACEFILE_COUNT:
		{
			unsigned long v;

			errno = 0;
			opt_arg = poptGetOptArg(pc);
			v = strtoul(opt_arg, NULL, 0);
			if (errno != 0 || !isdigit(opt_arg[0])) {
				ERR("Wrong value in --tracefile-count parameter: %s", opt_arg);
				ret = CMD_ERROR;
				goto end;
			}
			if (v != (uint32_t) v) {
				ERR("32-bit overflow in --tracefile-count parameter: %s", opt_arg);
				ret = CMD_ERROR;
				goto end;
			}
			chan_opts.attr.tracefile_count = (uint32_t) v;
			DBG("Maximum tracefile count set to %" PRIu64,
					chan_opts.attr.tracefile_count);
			break;
		}
		case OPT_LIST_OPTIONS:
			list_cmd_options(stdout, long_options);
			goto end;
		default:
			ret = CMD_UNDEFINED;
			goto end;
		}
	}

	ret = print_missing_or_multiple_domains(opt_kernel + opt_userspace);
	if (ret) {
		ret = CMD_ERROR;
		goto end;
	}

	if (chan_opts.attr.overwrite == 1 && opt_blocking_timeout.set &&
			opt_blocking_timeout.value != 0) {
		ERR("You cannot specify --overwrite and --blocking-timeout=N, "
			"where N is different than 0");
		ret = CMD_ERROR;
		goto end;
	}

	/* Mi check */
	if (lttng_opt_mi) {
		writer = mi_lttng_writer_create(fileno(stdout), lttng_opt_mi);
		if (!writer) {
			ret = -LTTNG_ERR_NOMEM;
			goto end;
		}

		/* Open command element */
		ret = mi_lttng_writer_command_open(writer,
				mi_lttng_element_command_enable_channels);
		if (ret) {
			ret = CMD_ERROR;
			goto end;
		}

		/* Open output element */
		ret = mi_lttng_writer_open_element(writer,
				mi_lttng_element_command_output);
		if (ret) {
			ret = CMD_ERROR;
			goto end;
		}
	}

	opt_channels = (char*) poptGetArg(pc);
	if (opt_channels == NULL) {
		ERR("Missing channel name.\n");
		ret = CMD_ERROR;
		success = 0;
		goto mi_closing;
	}

	leftover = poptGetArg(pc);
	if (leftover) {
		ERR("Unknown argument: %s", leftover);
		ret = CMD_ERROR;
		success = 0;
		goto mi_closing;
	}

	if (!opt_session_name) {
		session_name = get_session_name();
		if (session_name == NULL) {
			command_ret = CMD_ERROR;
			success = 0;
			goto mi_closing;
		}
	} else {
		session_name = opt_session_name;
	}

	command_ret = enable_channel(session_name);
	if (command_ret) {
		success = 0;
	}

mi_closing:
	/* Mi closing */
	if (lttng_opt_mi) {
		/* Close  output element */
		ret = mi_lttng_writer_close_element(writer);
		if (ret) {
			goto end;
		}

		/* Success ? */
		ret = mi_lttng_writer_write_element_bool(writer,
				mi_lttng_element_command_success, success);
		if (ret) {
			goto end;
		}

		/* Command element close */
		ret = mi_lttng_writer_command_close(writer);
		if (ret) {
			goto end;
		}
	}

end:
	/* Mi clean-up */
	if (writer && mi_lttng_writer_destroy(writer)) {
		/* Preserve original error code */
		ret = ret ? ret : LTTNG_ERR_MI_IO_FAIL;
	}

	if (!opt_session_name && session_name) {
		free(session_name);
	}

	/* Overwrite ret if an error occurred when enable_channel */
	ret = command_ret ? command_ret : ret;
	poptFreeContext(pc);
	return ret;
}
Пример #19
0
/*
 * The 'destroy <options>' first level command
 */
int cmd_destroy(int argc, const char **argv)
{
	int opt;
	int ret = CMD_SUCCESS , i, command_ret = CMD_SUCCESS, success = 1;
	static poptContext pc;
	char *session_name = NULL;
	const char *leftover = NULL;

	struct lttng_session *sessions;
	int count;
	int found;

	pc = poptGetContext(NULL, argc, argv, long_options, 0);
	poptReadDefaultConfig(pc, 0);

	while ((opt = poptGetNextOpt(pc)) != -1) {
		switch (opt) {
		case OPT_HELP:
			SHOW_HELP();
			break;
		case OPT_LIST_OPTIONS:
			list_cmd_options(stdout, long_options);
			break;
		default:
			ret = CMD_UNDEFINED;
			break;
		}
		goto end;
	}

	/* Mi preparation */
	if (lttng_opt_mi) {
		writer = mi_lttng_writer_create(fileno(stdout), lttng_opt_mi);
		if (!writer) {
			ret = -LTTNG_ERR_NOMEM;
			goto end;
		}

		/* Open command element */
		ret = mi_lttng_writer_command_open(writer,
				mi_lttng_element_command_destroy);
		if (ret) {
			ret = CMD_ERROR;
			goto end;
		}

		/* Open output element */
		ret = mi_lttng_writer_open_element(writer,
				mi_lttng_element_command_output);
		if (ret) {
			ret = CMD_ERROR;
			goto end;
		}

		/* For validation and semantic purpose we open a sessions element */
		ret = mi_lttng_sessions_open(writer);
		if (ret) {
			ret = CMD_ERROR;
			goto end;
		}
	}

	/* Recuperate all sessions for further operation */
	count = lttng_list_sessions(&sessions);
	if (count < 0) {
		ERR("%s", lttng_strerror(count));
		command_ret = CMD_ERROR;
		success = 0;
		goto mi_closing;
	}

	/* Ignore session name in case all sessions are to be destroyed */
	if (opt_destroy_all) {
		command_ret = destroy_all_sessions(sessions, count);
		if (command_ret) {
			success = 0;
		}
	} else {
		opt_session_name = (char *) poptGetArg(pc);

		if (!opt_session_name) {
			/* No session name specified, lookup default */
			session_name = get_session_name();
			if (session_name == NULL) {
				command_ret = CMD_ERROR;
				success = 0;
				goto mi_closing;
			}
		} else {
			session_name = opt_session_name;
		}

		/* Find the corresponding lttng_session struct */
		found = 0;
		for (i = 0; i < count; i++) {
			if (strncmp(sessions[i].name, session_name, NAME_MAX) == 0) {
				found = 1;
				command_ret = destroy_session(&sessions[i]);
				if (command_ret) {
					success = 0;
				}

			}
		}

		if (!found) {
			ERR("Session name %s not found", session_name);
			command_ret = LTTNG_ERR_SESS_NOT_FOUND;
			success = 0;
			goto mi_closing;
		}
	}

	leftover = poptGetArg(pc);
	if (leftover) {
		ERR("Unknown argument: %s", leftover);
		ret = CMD_ERROR;
		success = 0;
		goto mi_closing;
	}

mi_closing:
	/* Mi closing */
	if (lttng_opt_mi) {
		/* Close sessions and output element element */
		ret = mi_lttng_close_multi_element(writer, 2);
		if (ret) {
			ret = CMD_ERROR;
			goto end;
		}

		/* Success ? */
		ret = mi_lttng_writer_write_element_bool(writer,
				mi_lttng_element_command_success, success);
		if (ret) {
			ret = CMD_ERROR;
			goto end;
		}

		/* Command element close */
		ret = mi_lttng_writer_command_close(writer);
		if (ret) {
			ret = CMD_ERROR;
			goto end;
		}
	}
end:
	/* Mi clean-up */
	if (writer && mi_lttng_writer_destroy(writer)) {
		/* Preserve original error code */
		ret = ret ? ret : -LTTNG_ERR_MI_IO_FAIL;
	}

	if (opt_session_name == NULL) {
		free(session_name);
	}

	/* Overwrite ret if an error occurred during destroy_session/all */
	ret = command_ret ? command_ret : ret;

	poptFreeContext(pc);
	return ret;
}
Пример #20
0
/*
 * Add/remove tracker to/from session.
 */
static
int cmd_track_untrack(enum cmd_type cmd_type, const char *cmd_str,
		int argc, const char **argv)
{
	int opt, ret = 0;
	enum cmd_error_code command_ret = CMD_SUCCESS;
	int success = 1;
	static poptContext pc;
	char *session_name = NULL;
	struct mi_writer *writer = NULL;

	if (argc < 1) {
		command_ret = CMD_ERROR;
		goto end;
	}

	pc = poptGetContext(NULL, argc, argv, long_options, 0);
	poptReadDefaultConfig(pc, 0);

	while ((opt = poptGetNextOpt(pc)) != -1) {
		switch (opt) {
		case OPT_HELP:
			SHOW_HELP();
			goto end;
		case OPT_LIST_OPTIONS:
			list_cmd_options(stdout, long_options);
			goto end;
		case OPT_SESSION:
		case OPT_PID:
			opt_pid = 1;
			break;
		default:
			command_ret = CMD_UNDEFINED;
			goto end;
		}
	}

	ret = print_missing_or_multiple_domains(opt_kernel + opt_userspace);
	if (ret) {
		ret = CMD_ERROR;
		goto end;
	}

	if (!opt_session_name) {
		session_name = get_session_name();
		if (session_name == NULL) {
			command_ret = CMD_ERROR;
			goto end;
		}
	} else {
		session_name = opt_session_name;
	}

	/* Currently only PID tracker is supported */
	if (!opt_pid) {
		ERR("Please specify at least one tracker with its expected arguments");
		command_ret = CMD_ERROR;
		goto end;
	}

	/* Mi check */
	if (lttng_opt_mi) {
		writer = mi_lttng_writer_create(fileno(stdout), lttng_opt_mi);
		if (!writer) {
			command_ret = CMD_ERROR;
			goto end;
		}
	}

	if (writer) {
		/* Open command element */
		ret = mi_lttng_writer_command_open(writer,
				get_mi_element_command(cmd_type));
		if (ret) {
			command_ret = CMD_ERROR;
			goto end;
		}

		/* Open output element */
		ret = mi_lttng_writer_open_element(writer,
				mi_lttng_element_command_output);
		if (ret) {
			command_ret = CMD_ERROR;
			goto end;
		}
	}

	command_ret = track_untrack_pid(cmd_type,
			cmd_str, session_name, opt_pid_string,
			opt_all, writer);
	if (command_ret != CMD_SUCCESS) {
		success = 0;
	}

	/* Mi closing */
	if (writer) {
		/* Close  output element */
		ret = mi_lttng_writer_close_element(writer);
		if (ret) {
			command_ret = CMD_ERROR;
			goto end;
		}

		/* Success ? */
		ret = mi_lttng_writer_write_element_bool(writer,
				mi_lttng_element_command_success, success);
		if (ret) {
			command_ret = CMD_ERROR;
			goto end;
		}

		/* Command element close */
		ret = mi_lttng_writer_command_close(writer);
		if (ret) {
			command_ret = CMD_ERROR;
			goto end;
		}
	}

end:
	if (!opt_session_name) {
		free(session_name);
	}

	/* Mi clean-up */
	if (writer && mi_lttng_writer_destroy(writer)) {
		/* Preserve original error code */
		command_ret = CMD_ERROR;
	}

	poptFreeContext(pc);
	return (int) command_ret;
}
Пример #21
0
/*
 * Adding channel using the lttng API.
 */
static int enable_channel(char *session_name)
{
	int ret = CMD_SUCCESS, warn = 0, error = 0, success = 0;
	char *channel_name;
	struct lttng_domain dom;

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

	/* Create lttng domain */
	if (opt_kernel) {
		dom.type = LTTNG_DOMAIN_KERNEL;
		dom.buf_type = LTTNG_BUFFER_GLOBAL;
		if (opt_buffer_uid || opt_buffer_pid) {
			ERR("Buffer type not supported for domain -k");
			ret = CMD_ERROR;
			goto error;
		}
	} else if (opt_userspace) {
		dom.type = LTTNG_DOMAIN_UST;
		if (opt_buffer_pid) {
			dom.buf_type = LTTNG_BUFFER_PER_PID;
		} else {
			if (opt_buffer_global) {
				ERR("Buffer type not supported for domain -u");
				ret = CMD_ERROR;
				goto error;
			}
			dom.buf_type = LTTNG_BUFFER_PER_UID;
		}
	} else {
		print_missing_domain();
		ret = CMD_ERROR;
		goto error;
	}

	set_default_attr(&dom);

	if (chan.attr.tracefile_size == 0 && chan.attr.tracefile_count) {
		ERR("Missing option --tracefile-size. "
				"A file count without a size won't do anything.");
		ret = CMD_ERROR;
		goto error;
	}

	if ((chan.attr.tracefile_size > 0) &&
			(chan.attr.tracefile_size < chan.attr.subbuf_size)) {
		WARN("Tracefile size rounded up from (%" PRIu64 ") to subbuffer size (%" PRIu64 ")",
				chan.attr.tracefile_size, chan.attr.subbuf_size);
		chan.attr.tracefile_size = chan.attr.subbuf_size;
	}

	/* Setting channel output */
	if (opt_output) {
		if (!strncmp(output_mmap, opt_output, strlen(output_mmap))) {
			chan.attr.output = LTTNG_EVENT_MMAP;
		} else if (!strncmp(output_splice, opt_output, strlen(output_splice))) {
			chan.attr.output = LTTNG_EVENT_SPLICE;
		} else {
			ERR("Unknown output type %s. Possible values are: %s, %s\n",
					opt_output, output_mmap, output_splice);
			usage(stderr);
			ret = CMD_ERROR;
			goto error;
		}
	}

	handle = lttng_create_handle(session_name, &dom);
	if (handle == NULL) {
		ret = -1;
		goto error;
	}

	/* Mi open channels element */
	if (lttng_opt_mi) {
		assert(writer);
		ret = mi_lttng_channels_open(writer);
		if (ret) {
			ret = CMD_ERROR;
			goto error;
		}
	}

	/* Strip channel list (format: chan1,chan2,...) */
	channel_name = strtok(opt_channels, ",");
	while (channel_name != NULL) {
		/* Copy channel name and normalize it */
		strncpy(chan.name, channel_name, NAME_MAX);
		chan.name[NAME_MAX - 1] = '\0';

		DBG("Enabling channel %s", channel_name);

		ret = lttng_enable_channel(handle, &chan);
		if (ret < 0) {
			success = 0;
			switch (-ret) {
			case LTTNG_ERR_KERN_CHAN_EXIST:
			case LTTNG_ERR_UST_CHAN_EXIST:
			case LTTNG_ERR_CHAN_EXIST:
				WARN("Channel %s: %s (session %s)", channel_name,
						lttng_strerror(ret), session_name);
				warn = 1;
				break;
			default:
				ERR("Channel %s: %s (session %s)", channel_name,
						lttng_strerror(ret), session_name);
				error = 1;
				break;
			}
		} else {
			MSG("%s channel %s enabled for session %s",
					get_domain_str(dom.type), channel_name, session_name);
			success = 1;
		}

		if (lttng_opt_mi) {
			/* Mi print the channel element and leave it open */
			ret = mi_lttng_channel(writer, &chan, 1);
			if (ret) {
				ret = CMD_ERROR;
				goto error;
			}

			/* Individual Success ? */
			ret = mi_lttng_writer_write_element_bool(writer,
					mi_lttng_element_command_success, success);
			if (ret) {
				ret = CMD_ERROR;
				goto error;
			}

			/* Close channel element */
			ret = mi_lttng_writer_close_element(writer);
			if (ret) {
				ret = CMD_ERROR;
				goto error;
			}
		}

		/* Next channel */
		channel_name = strtok(NULL, ",");
	}

	if (lttng_opt_mi) {
		/* Close channels element */
		ret = mi_lttng_writer_close_element(writer);
		if (ret) {
			ret = CMD_ERROR;
			goto error;
		}
	}

	ret = CMD_SUCCESS;

error:
	/* If more important error happen bypass the warning */
	if (!ret && warn) {
		ret = CMD_WARNING;
	}
	/* If more important error happen bypass the warning */
	if (!ret && error) {
		ret = CMD_ERROR;
	}

	lttng_destroy_handle(handle);

	return ret;
}
Пример #22
0
/*
 *  The 'create <options>' first level command
 *
 *  Returns one of the CMD_* result constants.
 */
int cmd_create(int argc, const char **argv)
{
	int opt, ret = CMD_SUCCESS, command_ret = CMD_SUCCESS, success = 1;
	char *opt_arg = NULL;
	const char *leftover = NULL;
	static poptContext pc;

	pc = poptGetContext(NULL, argc, argv, long_options, 0);
	poptReadDefaultConfig(pc, 0);

	while ((opt = poptGetNextOpt(pc)) != -1) {
		switch (opt) {
		case OPT_HELP:
			SHOW_HELP();
			goto end;
		case OPT_LIST_OPTIONS:
			list_cmd_options(stdout, long_options);
			goto end;
		case OPT_LIVE_TIMER:
		{
			uint64_t v;

			errno = 0;
			opt_arg = poptGetOptArg(pc);
			if (!opt_arg) {
				/* Set up default values. */
				opt_live_timer = (uint32_t) DEFAULT_LTTNG_LIVE_TIMER;
				DBG("Session live timer interval set to default value %d",
						opt_live_timer);
				break;
			}

			if (utils_parse_time_suffix(opt_arg, &v) < 0) {
				ERR("Wrong value for --live parameter: %s", opt_arg);
				ret = CMD_ERROR;
				goto end;
			}

			if (v != (uint32_t) v) {
				ERR("32-bit overflow in --live parameter: %s", opt_arg);
				ret = CMD_ERROR;
				goto end;
			}

			if (v == 0) {
				ERR("Live timer interval must be greater than zero");
				ret = CMD_ERROR;
				goto end;
			}

			opt_live_timer = (uint32_t) v;
			DBG("Session live timer interval set to %d", opt_live_timer);
			break;
		}
		default:
			ret = CMD_UNDEFINED;
			goto end;
		}
	}

	if (opt_no_consumer) {
		MSG("The option --no-consumer is obsolete. Use --no-output now.");
		ret = CMD_WARNING;
		goto end;
	}

	ret = validate_url_option_combination();
	if (ret) {
		ret = CMD_ERROR;
		goto end;
	}

	/* Spawn a session daemon if needed */
	if (!opt_no_sessiond) {
		ret = launch_sessiond();
		if (ret) {
			ret = CMD_ERROR;
			goto end;
		}
	}

	/* MI initialization */
	if (lttng_opt_mi) {
		writer = mi_lttng_writer_create(fileno(stdout), lttng_opt_mi);
		if (!writer) {
			ret = -LTTNG_ERR_NOMEM;
			goto end;
		}

		/* Open command element */
		ret = mi_lttng_writer_command_open(writer,
				mi_lttng_element_command_create);
		if (ret) {
			ret = CMD_ERROR;
			goto end;
		}

		/* Open output element */
		ret = mi_lttng_writer_open_element(writer,
				mi_lttng_element_command_output);
		if (ret) {
			ret = CMD_ERROR;
			goto end;
		}
	}
	opt_session_name = (char*) poptGetArg(pc);

	leftover = poptGetArg(pc);
	if (leftover) {
		ERR("Unknown argument: %s", leftover);
		ret = CMD_ERROR;
		goto end;
	}

	command_ret = create_session();
	if (command_ret) {
		success = 0;
	}

	if (lttng_opt_mi) {
		/* Close  output element */
		ret = mi_lttng_writer_close_element(writer);
		if (ret) {
			ret = CMD_ERROR;
			goto end;
		}

		/* Success ? */
		ret = mi_lttng_writer_write_element_bool(writer,
				mi_lttng_element_command_success, success);
		if (ret) {
			ret = CMD_ERROR;
			goto end;
		}

		/* Command element close */
		ret = mi_lttng_writer_command_close(writer);
		if (ret) {
			ret = CMD_ERROR;
			goto end;
		}
	}

end:
	/* Mi clean-up */
	if (writer && mi_lttng_writer_destroy(writer)) {
		/* Preserve original error code */
		ret = ret ? ret : -LTTNG_ERR_MI_IO_FAIL;
	}

	/* Overwrite ret if an error occurred in create_session() */
	ret = command_ret ? command_ret : ret;

	poptFreeContext(pc);
	return ret;
}
Пример #23
0
/*
 * The 'snapshot <cmd> <options>' first level command
 */
int cmd_snapshot(int argc, const char **argv)
{
	int opt, ret = CMD_SUCCESS, command_ret = CMD_SUCCESS, success = 1;
	char *session_name = NULL;
	static poptContext pc;

	pc = poptGetContext(NULL, argc, argv, snapshot_opts, 0);
	poptReadDefaultConfig(pc, 0);

	/* Mi check */
	if (lttng_opt_mi) {
		writer = mi_lttng_writer_create(fileno(stdout), lttng_opt_mi);
		if (!writer) {
			ret = -LTTNG_ERR_NOMEM;
			goto end;
		}

		/* Open command element */
		ret = mi_lttng_writer_command_open(writer,
				mi_lttng_element_command_snapshot);
		if (ret) {
			ret = CMD_ERROR;
			goto end;
		}

		/* Open output element */
		ret = mi_lttng_writer_open_element(writer,
				mi_lttng_element_command_output);
		if (ret) {
			ret = CMD_ERROR;
			goto end;
		}
	}

	while ((opt = poptGetNextOpt(pc)) != -1) {
		switch (opt) {
		case OPT_HELP:
			usage(stdout);
			goto end;
		case OPT_LIST_OPTIONS:
			list_cmd_options(stdout, snapshot_opts);
			goto end;
		case OPT_LIST_COMMANDS:
			list_commands(actions, stdout);
			goto end;
		case OPT_MAX_SIZE:
		{
			uint64_t val;
			const char *opt = poptGetOptArg(pc);

			if (utils_parse_size_suffix((char *) opt, &val) < 0) {
				ERR("Unable to handle max-size value %s", opt);
				ret = CMD_ERROR;
				goto end;
			}

			opt_max_size = val;

			break;
		}
		default:
			usage(stderr);
			ret = CMD_UNDEFINED;
			goto end;
		}
	}

	if (!opt_session_name) {
		session_name = get_session_name();
		if (session_name == NULL) {
			ret = CMD_ERROR;
			goto end;
		}
		current_session_name = session_name;
	} else {
		current_session_name = opt_session_name;
	}

	command_ret = handle_command(poptGetArgs(pc));
	if (command_ret) {
		switch (-command_ret) {
		case LTTNG_ERR_EPERM:
			ERR("The session needs to be set in no output mode (--no-output)");
			break;
		case LTTNG_ERR_SNAPSHOT_NODATA:
			WARN("%s", lttng_strerror(command_ret));
			break;
		default:
			ERR("%s", lttng_strerror(command_ret));
			break;
		}
		success = 0;
	}

	if (lttng_opt_mi) {
		/* Close output element */
		ret = mi_lttng_writer_close_element(writer);
		if (ret) {
			ret = CMD_ERROR;
			goto end;
		}

		/* Success ? */
		ret = mi_lttng_writer_write_element_bool(writer,
				mi_lttng_element_command_success, success);
		if (ret) {
			ret = CMD_ERROR;
			goto end;
		}

		/* Command element close */
		ret = mi_lttng_writer_command_close(writer);
		if (ret) {
			ret = CMD_ERROR;
			goto end;
		}
	}

end:
	/* Mi clean-up */
	if (writer && mi_lttng_writer_destroy(writer)) {
		/* Preserve original error code */
		ret = ret ? ret : -LTTNG_ERR_MI_IO_FAIL;
	}

	if (!opt_session_name) {
		free(session_name);
	}

	/* Overwrite ret if an error occured during handle_command */
	ret = command_ret ? command_ret : ret;
	poptFreeContext(pc);
	return ret;
}
Пример #24
0
static
enum cmd_error_code track_untrack_pid(enum cmd_type cmd_type, const char *cmd_str,
		const char *session_name, const char *pid_string,
		int all, struct mi_writer *writer)
{
	int ret, success = 1 , i;
	enum cmd_error_code retval = CMD_SUCCESS;
	int *pid_list = NULL;
	int nr_pids;
	struct lttng_domain dom;
	struct lttng_handle *handle = NULL;
	int (*cmd_func)(struct lttng_handle *handle, int pid);

	switch (cmd_type) {
	case CMD_TRACK:
		cmd_func = lttng_track_pid;
		break;
	case CMD_UNTRACK:
		cmd_func = lttng_untrack_pid;
		break;
	default:
		ERR("Unknown command");
		retval = CMD_ERROR;
		goto end;
	}

	memset(&dom, 0, sizeof(dom));
	if (opt_kernel) {
		dom.type = LTTNG_DOMAIN_KERNEL;
	} else if (opt_userspace) {
		dom.type = LTTNG_DOMAIN_UST;
	} else {
		/* Checked by the caller. */
		assert(0);
	}

	ret = parse_pid_string(pid_string, all, &pid_list, &nr_pids);
	if (ret != CMD_SUCCESS) {
		ERR("Error parsing PID string");
		retval = CMD_ERROR;
		goto end;
	}

	handle = lttng_create_handle(session_name, &dom);
	if (handle == NULL) {
		retval = CMD_ERROR;
		goto end;
	}

	if (writer) {
		/* Open process element */
		ret = mi_lttng_targets_open(writer);
		if (ret) {
			retval = CMD_ERROR;
			goto end;
		}
	}

	for (i = 0; i < nr_pids; i++) {
		DBG("%s PID %d", cmd_str, pid_list[i]);
		ret = cmd_func(handle, pid_list[i]);
		if (ret) {
			switch (-ret) {
			case LTTNG_ERR_PID_TRACKED:
				WARN("PID %i already tracked in session %s",
						pid_list[i], session_name);
				success = 1;
				retval = CMD_SUCCESS;
				break;
			case LTTNG_ERR_PID_NOT_TRACKED:
				WARN("PID %i not tracked in session %s",
						pid_list[i], session_name);
				success = 1;
				retval = CMD_SUCCESS;
				break;
			default:
				ERR("%s", lttng_strerror(ret));
				success = 0;
				retval = CMD_ERROR;
				break;
			}
		} else {
			MSG("PID %i %sed in session %s",
					pid_list[i], cmd_str, session_name);
			success = 1;
		}

		/* Mi */
		if (writer) {
			ret = mi_lttng_pid_target(writer, pid_list[i], 1);
			if (ret) {
				retval = CMD_ERROR;
				goto end;
			}

			ret = mi_lttng_writer_write_element_bool(writer,
					mi_lttng_element_success, success);
			if (ret) {
				retval = CMD_ERROR;
				goto end;
			}

			ret = mi_lttng_writer_close_element(writer);
			if (ret) {
				retval = CMD_ERROR;
				goto end;
			}
		}
	}

	if (writer) {
		/* Close targets element */
		ret = mi_lttng_writer_close_element(writer);
		if (ret) {
			retval = CMD_ERROR;
			goto end;
		}
	}

end:
	if (handle) {
		lttng_destroy_handle(handle);
	}
	free(pid_list);
	return retval;
}