SoW-2019-0002: Dynamic Snapshot
[lttng-tools.git] / src / lib / lttng-ctl / lttng-ctl.c
index 4e49120732da5f5753e7322c5e60d99163e5881c..fff602305ce9a13c2fb0b4dd1e350bf57af78f36 100644 (file)
 #include <lttng/destruction-handle.h>
 #include <lttng/tracker-internal.h>
 
-#include "filter/filter-ast.h"
-#include "filter/filter-parser.h"
-#include "filter/filter-bytecode.h"
-#include "filter/memstream.h"
+#include <common/filter/filter-ast.h>
+#include <common/filter/filter-parser.h>
+#include <common/filter/filter-bytecode.h>
+#include <common/filter/memstream.h>
 #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,
This page took 0.028568 seconds and 5 git commands to generate.