/* * Create a brand new session using name and url for destination. * * Returns LTTNG_OK on success or a negative error code. */ int lttng_create_session(const char *name, const char *url) { int ret; ssize_t size; struct lttcomm_session_msg lsm; struct lttng_uri *uris = NULL; if (name == NULL) { return -LTTNG_ERR_INVALID; } memset(&lsm, 0, sizeof(lsm)); lsm.cmd_type = LTTNG_CREATE_SESSION; copy_string(lsm.session.name, name, sizeof(lsm.session.name)); /* There should never be a data URL */ size = parse_str_urls_to_uri(url, NULL, &uris); if (size < 0) { return -LTTNG_ERR_INVALID; } lsm.u.uri.size = size; ret = ask_sessiond_varlen(&lsm, uris, sizeof(struct lttng_uri) * size, NULL); free(uris); return ret; }
/* * Set URL for a consumer for a session and domain. * * Return 0 on success, else a negative value. */ int lttng_set_consumer_url(struct lttng_handle *handle, const char *control_url, const char *data_url) { int ret; ssize_t size; struct lttcomm_session_msg lsm; struct lttng_uri *uris = NULL; if (handle == NULL || (control_url == NULL && data_url == NULL)) { return -LTTNG_ERR_INVALID; } memset(&lsm, 0, sizeof(lsm)); lsm.cmd_type = LTTNG_SET_CONSUMER_URI; copy_string(lsm.session.name, handle->session_name, sizeof(lsm.session.name)); copy_lttng_domain(&lsm.domain, &handle->domain); size = parse_str_urls_to_uri(control_url, data_url, &uris); if (size < 0) { return -LTTNG_ERR_INVALID; } lsm.u.uri.size = size; ret = ask_sessiond_varlen(&lsm, uris, sizeof(struct lttng_uri) * size, NULL); free(uris); return ret; }
/* * This is an extension of create session that is ONLY and SHOULD only be used * by the lttng command line program. It exists to avoid using URI parsing in * the lttng client. * * We need the date and time for the trace path subdirectory for the case where * the user does NOT define one using either -o or -U. Using the normal * lttng_create_session API call, we have no clue on the session daemon side if * the URL was generated automatically by the client or define by the user. * * So this function "wrapper" is hidden from the public API, takes the datetime * string and appends it if necessary to the URI subdirectory before sending it * to the session daemon. * * With this extra function, the lttng_create_session call behavior is not * changed and the timestamp is appended to the URI on the session daemon side * if necessary. */ int _lttng_create_session_ext(const char *name, const char *url, const char *datetime) { int ret; ssize_t size; struct lttcomm_session_msg lsm; struct lttng_uri *uris = NULL; if (name == NULL || datetime == NULL || url == NULL) { return -LTTNG_ERR_INVALID; } memset(&lsm, 0, sizeof(lsm)); lsm.cmd_type = LTTNG_CREATE_SESSION; copy_string(lsm.session.name, name, sizeof(lsm.session.name)); /* There should never be a data URL */ size = parse_str_urls_to_uri(url, NULL, &uris); if (size < 0) { ret = -LTTNG_ERR_INVALID; goto error; } lsm.u.uri.size = size; if (size > 0 && uris[0].dtype != LTTNG_DST_PATH && strlen(uris[0].subdir) == 0) { /* Don't append datetime if the name was automatically created. */ if (strncmp(name, DEFAULT_SESSION_NAME "-", strlen(DEFAULT_SESSION_NAME) + 1)) { ret = snprintf(uris[0].subdir, sizeof(uris[0].subdir), "%s-%s", name, datetime); } else { ret = snprintf(uris[0].subdir, sizeof(uris[0].subdir), "%s", name); } if (ret < 0) { PERROR("snprintf uri subdir"); ret = -LTTNG_ERR_FATAL; goto error; } } ret = ask_sessiond_varlen(&lsm, uris, sizeof(struct lttng_uri) * size, NULL); error: free(uris); return ret; }
/* * Create or enable an event with a filter expression. * * Return negative error value on error. * Return size of returned session payload data if OK. */ int lttng_enable_event_with_filter(struct lttng_handle *handle, struct lttng_event *event, const char *channel_name, const char *filter_expression) { struct lttcomm_session_msg lsm; struct filter_parser_ctx *ctx; FILE *fmem; int ret = 0; if (!filter_expression) { /* * Fall back to normal event enabling if no filter * specified. */ return lttng_enable_event(handle, event, channel_name); } /* * Empty filter string will always be rejected by the parser * anyway, so treat this corner-case early to eliminate * lttng_fmemopen error for 0-byte allocation. */ if (handle == NULL || filter_expression[0] == '\0') { return -LTTNG_ERR_INVALID; } /* * 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 -LTTNG_ERR_FILTER_NOMEM; } ctx = filter_parser_ctx_alloc(fmem); if (!ctx) { fprintf(stderr, "Error allocating parser\n"); ret = -LTTNG_ERR_FILTER_NOMEM; goto alloc_error; } ret = filter_parser_ctx_append_ast(ctx); if (ret) { fprintf(stderr, "Parse error\n"); ret = -LTTNG_ERR_FILTER_INVAL; goto parse_error; } ret = filter_visitor_set_parent(ctx); if (ret) { fprintf(stderr, "Set parent 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; } 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)); memset(&lsm, 0, sizeof(lsm)); lsm.cmd_type = LTTNG_ENABLE_EVENT_WITH_FILTER; /* Copy channel name */ copy_string(lsm.u.enable.channel_name, channel_name, sizeof(lsm.u.enable.channel_name)); /* Copy event name */ if (event) { memcpy(&lsm.u.enable.event, event, sizeof(lsm.u.enable.event)); } lsm.u.enable.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.enable.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; }
/* * 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); }