X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Flib%2Flttng-ctl%2Flttng-ctl.c;h=780b44dd7cdebba0ed70c69a4459abc42df38658;hp=a05a8049ec5dd7186fe83fa01ce83478a41f392f;hb=53a80697a772bc2e260e3dff006f910be6709f04;hpb=00e2e675d54dc726a7c8f8887c889cc8ef022003 diff --git a/src/lib/lttng-ctl/lttng-ctl.c b/src/lib/lttng-ctl/lttng-ctl.c index a05a8049e..780b44dd7 100644 --- a/src/lib/lttng-ctl/lttng-ctl.c +++ b/src/lib/lttng-ctl/lttng-ctl.c @@ -32,6 +32,26 @@ #include #include +#include "filter-parser.h" +#include "filter-ast.h" +#include "filter-bytecode.h" +#include "memstream.h" + +#ifdef DEBUG +const int print_xml = 1; +#define dbg_printf(fmt, args...) \ + printf("[debug liblttng-ctl] " fmt, ## args) +#else +const int print_xml = 0; +#define dbg_printf(fmt, args...) \ +do { \ + /* do nothing but check printf format */ \ + if (0) \ + printf("[debug liblttnctl] " fmt, ## args); \ +} while (0) +#endif + + /* Socket to session daemon for communication */ static int sessiond_socket; static char sessiond_sock_path[PATH_MAX]; @@ -114,6 +134,31 @@ end: return ret; } +/* + * Send var len data to the session daemon. + * + * On success, returns the number of bytes sent (>=0) + * On error, returns -1 + */ +static int send_session_varlen(void *data, size_t len) +{ + int ret; + + if (!connected) { + ret = -ENOTCONN; + goto end; + } + if (!data || !len) { + ret = 0; + goto end; + } + + ret = lttcomm_send_unix_sock(sessiond_socket, data, len); + +end: + return ret; +} + /* * Receive data from the sessiond socket. * @@ -311,10 +356,14 @@ static int disconnect_sessiond(void) /* * Ask the session daemon a specific command and put the data into buf. + * Takes extra var. len. data as input to send to the session daemon. * * Return size of data (only payload, not header) or a negative error code. */ -static int ask_sessiond(struct lttcomm_session_msg *lsm, void **buf) +static int ask_sessiond_varlen(struct lttcomm_session_msg *lsm, + void *vardata, + size_t varlen, + void **buf) { int ret; size_t size; @@ -331,6 +380,11 @@ static int ask_sessiond(struct lttcomm_session_msg *lsm, void **buf) if (ret < 0) { goto end; } + /* Send var len data */ + ret = send_session_varlen(vardata, varlen); + if (ret < 0) { + goto end; + } /* Get header from data transmission */ ret = recv_data_sessiond(&llm, sizeof(llm)); @@ -381,6 +435,16 @@ end: return ret; } +/* + * Ask the session daemon a specific command and put the data into buf. + * + * Return size of data (only payload, not header) or a negative error code. + */ +static int ask_sessiond(struct lttcomm_session_msg *lsm, void **buf) +{ + return ask_sessiond_varlen(lsm, NULL, 0, buf); +} + /* * Create lttng handle and return pointer. * The returned pointer will be NULL in case of malloc() error. @@ -555,6 +619,139 @@ int lttng_enable_event(struct lttng_handle *handle, return ask_sessiond(&lsm, NULL); } +/* + * set filter for an event + * Return negative error value on error. + * Return size of returned session payload data if OK. + */ + +int lttng_set_event_filter(struct lttng_handle *handle, + const char *event_name, const char *channel_name, + const char *filter_expression) +{ + struct lttcomm_session_msg lsm; + struct filter_parser_ctx *ctx; + FILE *fmem; + int ret = 0; + + /* Safety check. */ + if (handle == NULL) { + return -1; + } + + if (!filter_expression) { + return 0; + } + + /* + * casting const to non-const, as the underlying function will + * use it in read-only mode. + */ + fmem = lttng_fmemopen((void *) filter_expression, + strlen(filter_expression), "r"); + if (!fmem) { + fprintf(stderr, "Error opening memory as stream\n"); + return -ENOMEM; + } + ctx = filter_parser_ctx_alloc(fmem); + if (!ctx) { + fprintf(stderr, "Error allocating parser\n"); + ret = -ENOMEM; + goto alloc_error; + } + ret = filter_parser_ctx_append_ast(ctx); + if (ret) { + fprintf(stderr, "Parse error\n"); + ret = -EINVAL; + goto parse_error; + } + ret = filter_visitor_set_parent(ctx); + if (ret) { + fprintf(stderr, "Set parent error\n"); + ret = -EINVAL; + goto parse_error; + } + if (print_xml) { + ret = filter_visitor_print_xml(ctx, stdout, 0); + if (ret) { + fflush(stdout); + fprintf(stderr, "XML print error\n"); + ret = -EINVAL; + goto parse_error; + } + } + + dbg_printf("Generating IR... "); + fflush(stdout); + ret = filter_visitor_ir_generate(ctx); + if (ret) { + fprintf(stderr, "Generate IR error\n"); + ret = -EINVAL; + goto parse_error; + } + dbg_printf("done\n"); + + dbg_printf("Validating IR... "); + fflush(stdout); + ret = filter_visitor_ir_check_binary_op_nesting(ctx); + if (ret) { + ret = -EINVAL; + goto parse_error; + } + dbg_printf("done\n"); + + dbg_printf("Generating bytecode... "); + fflush(stdout); + ret = filter_visitor_bytecode_generate(ctx); + if (ret) { + fprintf(stderr, "Generate bytecode error\n"); + ret = -EINVAL; + goto parse_error; + } + dbg_printf("done\n"); + dbg_printf("Size of bytecode generated: %u bytes.\n", + bytecode_get_len(&ctx->bytecode->b)); + + memset(&lsm, 0, sizeof(lsm)); + + lsm.cmd_type = LTTNG_SET_FILTER; + + /* Copy channel name */ + copy_string(lsm.u.filter.channel_name, channel_name, + sizeof(lsm.u.filter.channel_name)); + /* Copy event name */ + copy_string(lsm.u.filter.event_name, event_name, + sizeof(lsm.u.filter.event_name)); + lsm.u.filter.bytecode_len = sizeof(ctx->bytecode->b) + + bytecode_get_len(&ctx->bytecode->b); + + copy_lttng_domain(&lsm.domain, &handle->domain); + + copy_string(lsm.session.name, handle->session_name, + sizeof(lsm.session.name)); + + ret = ask_sessiond_varlen(&lsm, &ctx->bytecode->b, + lsm.u.filter.bytecode_len, NULL); + + filter_bytecode_free(ctx); + filter_ir_free(ctx); + filter_parser_ctx_free(ctx); + if (fclose(fmem) != 0) { + perror("fclose"); + } + return ret; + +parse_error: + filter_bytecode_free(ctx); + filter_ir_free(ctx); + filter_parser_ctx_free(ctx); +alloc_error: + if (fclose(fmem) != 0) { + perror("fclose"); + } + return ret; +} + /* * Disable event(s) of a channel and domain. * If no event name is specified, all events are disabled.