X-Git-Url: http://git.efficios.com/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Flib%2Flttng-ctl%2Flttng-ctl.c;h=fff602305ce9a13c2fb0b4dd1e350bf57af78f36;hp=4e49120732da5f5753e7322c5e60d99163e5881c;hb=refs%2Fheads%2Fsow-2019-0002-rev1;hpb=25357057de5ae4dd2a572e8f9b893c1b90cbd60a diff --git a/src/lib/lttng-ctl/lttng-ctl.c b/src/lib/lttng-ctl/lttng-ctl.c index 4e4912073..fff602305 100644 --- a/src/lib/lttng-ctl/lttng-ctl.c +++ b/src/lib/lttng-ctl/lttng-ctl.c @@ -38,26 +38,12 @@ #include #include -#include "filter/filter-ast.h" -#include "filter/filter-parser.h" -#include "filter/filter-bytecode.h" -#include "filter/memstream.h" +#include +#include +#include +#include #include "lttng-ctl-helper.h" -#ifdef DEBUG -static const int print_xml = 1; -#define dbg_printf(fmt, args...) \ - printf("[debug liblttng-ctl] " fmt, ## args) -#else -static 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 - #define COPY_DOMAIN_PACKED(dst, src) \ do { \ struct lttng_domain _tmp_domain; \ @@ -896,7 +882,7 @@ static char *set_agent_filter(const char *filter, struct lttng_event *ev) /* Add loglevel filtering if any for the JUL domain. */ if (ev->loglevel_type != LTTNG_EVENT_LOGLEVEL_ALL) { - char *op; + const char *op; if (ev->loglevel_type == LTTNG_EVENT_LOGLEVEL_RANGE) { op = ">="; @@ -930,133 +916,6 @@ error: return NULL; } -/* - * Generate the filter bytecode from a given filter expression string. Put the - * newly allocated parser context in ctxp and populate the lsm object with the - * expression len. - * - * Return 0 on success else a LTTNG_ERR_* code and ctxp is untouched. - */ -static int generate_filter(char *filter_expression, - struct lttcomm_session_msg *lsm, struct filter_parser_ctx **ctxp) -{ - int ret; - struct filter_parser_ctx *ctx = NULL; - FILE *fmem = NULL; - - assert(filter_expression); - assert(lsm); - assert(ctxp); - - /* - * 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"); - ret = -LTTNG_ERR_FILTER_NOMEM; - goto error; - } - ctx = filter_parser_ctx_alloc(fmem); - if (!ctx) { - fprintf(stderr, "Error allocating parser\n"); - ret = -LTTNG_ERR_FILTER_NOMEM; - goto filter_alloc_error; - } - ret = filter_parser_ctx_append_ast(ctx); - if (ret) { - fprintf(stderr, "Parse error\n"); - ret = -LTTNG_ERR_FILTER_INVAL; - 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 = -LTTNG_ERR_FILTER_INVAL; - goto parse_error; - } - } - - dbg_printf("Generating IR... "); - fflush(stdout); - ret = filter_visitor_ir_generate(ctx); - if (ret) { - fprintf(stderr, "Generate IR error\n"); - ret = -LTTNG_ERR_FILTER_INVAL; - 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 = -LTTNG_ERR_FILTER_INVAL; - goto parse_error; - } - - /* Normalize globbing patterns in the expression. */ - ret = filter_visitor_ir_normalize_glob_patterns(ctx); - if (ret) { - ret = -LTTNG_ERR_FILTER_INVAL; - goto parse_error; - } - - /* Validate strings used as literals in the expression. */ - ret = filter_visitor_ir_validate_string(ctx); - if (ret) { - ret = -LTTNG_ERR_FILTER_INVAL; - goto parse_error; - } - - /* Validate globbing patterns in the expression. */ - ret = filter_visitor_ir_validate_globbing(ctx); - if (ret) { - ret = -LTTNG_ERR_FILTER_INVAL; - 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 = -LTTNG_ERR_FILTER_INVAL; - goto parse_error; - } - dbg_printf("done\n"); - dbg_printf("Size of bytecode generated: %u bytes.\n", - bytecode_get_len(&ctx->bytecode->b)); - - lsm->u.enable.bytecode_len = sizeof(ctx->bytecode->b) - + bytecode_get_len(&ctx->bytecode->b); - lsm->u.enable.expression_len = strlen(filter_expression) + 1; - - /* No need to keep the memory stream. */ - if (fclose(fmem) != 0) { - PERROR("fclose"); - } - - *ctxp = ctx; - return 0; - -parse_error: - filter_ir_free(ctx); - filter_parser_ctx_free(ctx); -filter_alloc_error: - if (fclose(fmem) != 0) { - PERROR("fclose"); - } -error: - return ret; -} - /* * Enable event(s) for a channel, possibly with exclusions and a filter. * If no event name is specified, all events are enabled. @@ -1160,10 +1019,14 @@ int lttng_enable_event_with_exclusions(struct lttng_handle *handle, } } - ret = generate_filter(filter_expression, &lsm, &ctx); + ret = filter_parser_ctx_create_from_filter_expression(filter_expression, &ctx); if (ret) { goto filter_error; } + + lsm.u.enable.bytecode_len = sizeof(ctx->bytecode->b) + + bytecode_get_len(&ctx->bytecode->b); + lsm.u.enable.expression_len = strlen(filter_expression) + 1; } ret = lttng_dynamic_buffer_set_capacity(&send_buffer, @@ -1369,10 +1232,14 @@ int lttng_disable_event_ext(struct lttng_handle *handle, } } - ret = generate_filter(filter_expression, &lsm, &ctx); + ret = filter_parser_ctx_create_from_filter_expression(filter_expression, &ctx); if (ret) { goto filter_error; } + + lsm.u.enable.bytecode_len = sizeof(ctx->bytecode->b) + + bytecode_get_len(&ctx->bytecode->b); + lsm.u.enable.expression_len = strlen(filter_expression) + 1; } varlen_data = zmalloc(lsm.u.disable.bytecode_len @@ -3054,8 +2921,15 @@ end: int lttng_register_trigger(struct lttng_trigger *trigger) { int ret; + int reply_ret; struct lttcomm_session_msg lsm; struct lttng_dynamic_buffer buffer; + void *reply = NULL; + struct lttng_buffer_view reply_view; + struct lttng_trigger *reply_trigger = NULL; + bool send_fd = false; + int fd_to_send; + enum lttng_domain_type domain_type; lttng_dynamic_buffer_init(&buffer); if (!trigger) { @@ -3068,23 +2942,91 @@ int lttng_register_trigger(struct lttng_trigger *trigger) goto end; } - ret = lttng_trigger_serialize(trigger, &buffer); + domain_type = lttng_trigger_get_underlying_domain_type_restriction( + trigger); + + ret = lttng_trigger_serialize(trigger, &buffer, &fd_to_send); if (ret < 0) { ret = -LTTNG_ERR_UNK; goto end; } + if (getenv("LTTNG_REGISTER_TRIGGER_DRY_RUN")) { + /* + * Don't really send the request, just deserialize, validate + * that it is equal to the original trigger (to test + * serialization and deserialization), and return. + */ + struct lttng_buffer_view bv; + ssize_t sz; + + bv = lttng_buffer_view_from_dynamic_buffer(&buffer, 0, -1); + sz = lttng_trigger_create_from_buffer(&bv, &reply_trigger); + if (sz != bv.size) { + ret = -LTTNG_ERR_UNK; + goto end; + } + + if (!reply_trigger) { + ret = -LTTNG_ERR_UNK; + goto end; + } + + if (!lttng_trigger_is_equal(trigger, reply_trigger)) { + ret = -LTTNG_ERR_UNK; + goto end; + } + + /* Give it a dummy name. */ + lttng_trigger_set_name(trigger, "yop"); + + ret = 0; + goto end; + } + + send_fd = fd_to_send >= 0; + memset(&lsm, 0, sizeof(lsm)); lsm.cmd_type = LTTNG_REGISTER_TRIGGER; + lsm.domain.type = domain_type; lsm.u.trigger.length = (uint32_t) buffer.size; - ret = lttng_ctl_ask_sessiond_varlen_no_cmd_header(&lsm, buffer.data, - buffer.size, NULL); + reply_ret = lttng_ctl_ask_sessiond_fds_varlen_no_cmd_header(&lsm, + send_fd ? &fd_to_send : NULL, + send_fd ? 1 : 0, + buffer.data, + buffer.size, + &reply); + if (reply_ret < 0) { + ret = reply_ret; + goto end; + } else if (reply_ret == 0) { + /* Socket unexpectedly closed by the session daemon. */ + ret = -LTTNG_ERR_FATAL; + goto end; + } + + reply_view = lttng_buffer_view_init(reply, 0, reply_ret); + ret = lttng_trigger_create_from_buffer(&reply_view, &reply_trigger); + if (ret < 0) { + ret = -LTTNG_ERR_FATAL; + goto end; + } + + ret = lttng_trigger_assign(trigger, reply_trigger); + if (ret < 0) { + ret = -LTTNG_ERR_FATAL; + goto end; + } + + ret = 0; end: + free(reply); lttng_dynamic_buffer_reset(&buffer); + lttng_trigger_destroy(reply_trigger); return ret; } -int lttng_unregister_trigger(struct lttng_trigger *trigger) +int lttng_unregister_trigger(const struct lttng_trigger *trigger) { int ret; struct lttcomm_session_msg lsm; @@ -3101,7 +3043,7 @@ int lttng_unregister_trigger(struct lttng_trigger *trigger) goto end; } - ret = lttng_trigger_serialize(trigger, &buffer); + ret = lttng_trigger_serialize(trigger, &buffer, NULL); if (ret < 0) { ret = -LTTNG_ERR_UNK; goto end; @@ -3117,6 +3059,49 @@ end: return ret; } +/* + * Ask the session daemon for all registered triggers. + * Allocate a lttng_triggers collection. + * On error, returns a negative value. + */ +int lttng_list_triggers(struct lttng_triggers **triggers) +{ + int ret; + int reply_ret; + struct lttcomm_session_msg lsm; + struct lttng_buffer_view reply_view; + struct lttng_triggers *local_triggers = NULL; + void *reply = NULL; + + memset(&lsm, 0, sizeof(lsm)); + lsm.cmd_type = LTTNG_LIST_TRIGGERS; + + reply_ret = lttng_ctl_ask_sessiond(&lsm, &reply); + if (reply_ret < 0) { + ret = reply_ret; + goto end; + } else if (reply_ret == 0) { + /* Socket unexpectedly closed by the session daemon. */ + ret = -LTTNG_ERR_FATAL; + goto end; + } + + reply_view = lttng_buffer_view_init(reply, 0, reply_ret); + ret = lttng_triggers_create_from_buffer(&reply_view, &local_triggers); + if (ret < 0) { + ret = -LTTNG_ERR_FATAL; + goto end; + } + + *triggers = local_triggers; + local_triggers = NULL; + ret = 0; +end: + free(reply); + free(local_triggers); + return ret; +} + static int lttng_track_untrack_id(struct lttng_handle *handle, enum lttng_tracker_type tracker_type, const struct lttng_tracker_id *id,