SoW-2019-0002: Dynamic Snapshot
[lttng-tools.git] / src / lib / lttng-ctl / lttng-ctl.c
index 406de885c713a4f4ab6a4d022c117f2a43946980..fff602305ce9a13c2fb0b4dd1e350bf57af78f36 100644 (file)
@@ -4,20 +4,10 @@
  * Linux Trace Toolkit Control Library
  *
  * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
- * Copyright (C) 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ * Copyright (C) 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
  *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License, version 2.1 only,
- * as published by the Free Software Foundation.
+ * SPDX-License-Identifier: LGPL-2.1-only
  *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
 #define _LGPL_SOURCE
 #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;                        \
@@ -906,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 = ">=";
@@ -940,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.
@@ -1170,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,
@@ -1379,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
@@ -2839,8 +2696,7 @@ end:
  */
 int lttng_list_tracker_ids(struct lttng_handle *handle,
                enum lttng_tracker_type tracker_type,
-               struct lttng_tracker_id ***_ids,
-               size_t *_nr_ids)
+               struct lttng_tracker_ids **_ids)
 {
        int ret, i;
        struct lttcomm_session_msg lsm;
@@ -2848,7 +2704,7 @@ int lttng_list_tracker_ids(struct lttng_handle *handle,
        char *cmd_payload = NULL, *p;
        size_t cmd_header_len;
        size_t nr_ids = 0;
-       struct lttng_tracker_id **ids = NULL;
+       struct lttng_tracker_id*ids = NULL;
 
        if (handle == NULL) {
                return -LTTNG_ERR_INVALID;
@@ -2877,7 +2733,7 @@ int lttng_list_tracker_ids(struct lttng_handle *handle,
        free(cmd_header);
        cmd_header = NULL;
 
-       ids = zmalloc(sizeof(*ids) * nr_ids);
+       ids = lttng_tracker_ids_create(nr_ids);
        if (!ids) {
                ret = -LTTNG_ERR_NOMEM;
                goto error;
@@ -2891,9 +2747,9 @@ int lttng_list_tracker_ids(struct lttng_handle *handle,
 
                tracker_id = (struct lttcomm_tracker_id_header *) p;
                p += sizeof(struct lttcomm_tracker_id_header);
-               id = lttng_tracker_id_create();
+               id = lttng_tracker_ids_get_pointer_of_index(ids, i);
                if (!id) {
-                       ret = -LTTNG_ERR_NOMEM;
+                       ret = -LTTNG_ERR_INVALID;
                        goto error;
                }
 
@@ -2918,18 +2774,13 @@ int lttng_list_tracker_ids(struct lttng_handle *handle,
                        ret = -LTTNG_ERR_INVALID;
                        goto error;
                }
-
-               /* Assign the new object to the list */
-               ids[i] = id;
        }
        free(cmd_payload);
        *_ids = ids;
-       *_nr_ids = nr_ids;
        return 0;
 
 error:
-       lttng_tracker_ids_destroy(ids, nr_ids);
-       free(ids);
+       lttng_tracker_ids_destroy(ids);
        free(cmd_payload);
        free(cmd_header);
        return ret;
@@ -2948,20 +2799,32 @@ error:
 int lttng_list_tracker_pids(struct lttng_handle *handle,
                int *_enabled, int32_t **_pids, size_t *_nr_pids)
 {
-       struct lttng_tracker_id **ids = NULL;
-       size_t nr_ids = 0;
+       struct lttng_tracker_id*ids = NULL;
+       unsigned int nr_ids = 0;
        int *pids = NULL;
        int ret = 0, i;
        enum lttng_tracker_id_status status;
+       const struct lttng_tracker_id *id;
 
-       ret = lttng_list_tracker_ids(handle, LTTNG_TRACKER_PID, &ids, &nr_ids);
-       if (ret < 0)
+       ret = lttng_list_tracker_ids(handle, LTTNG_TRACKER_PID, &ids);
+       if (ret < 0) {
                return ret;
+       }
 
-       if (nr_ids == 1 && lttng_tracker_id_get_type(ids[0]) == LTTNG_ID_ALL) {
-               *_enabled = 0;
+       status = lttng_tracker_ids_get_count(ids, &nr_ids);
+       if (status != LTTNG_TRACKER_ID_STATUS_OK) {
+               ret = -LTTNG_ERR_INVALID;
                goto end;
        }
+
+       if (nr_ids == 1) {
+               id = lttng_tracker_ids_get_at_index(ids, 0);
+               if (id && lttng_tracker_id_get_type(id) == LTTNG_ID_ALL) {
+                       *_enabled = 0;
+                       goto end;
+               }
+       }
+
        *_enabled = 1;
 
        pids = zmalloc(nr_ids * sizeof(*pids));
@@ -2970,8 +2833,7 @@ int lttng_list_tracker_pids(struct lttng_handle *handle,
                goto end;
        }
        for (i = 0; i < nr_ids; i++) {
-               struct lttng_tracker_id *id = ids[i];
-
+               id = lttng_tracker_ids_get_at_index(ids, i);
                status = lttng_tracker_id_get_value(id, &pids[i]);
                if (status != LTTNG_TRACKER_ID_STATUS_OK) {
                        ret = -LTTNG_ERR_UNK;
@@ -2981,8 +2843,7 @@ int lttng_list_tracker_pids(struct lttng_handle *handle,
        *_pids = pids;
        *_nr_pids = nr_ids;
 end:
-       lttng_tracker_ids_destroy(ids, nr_ids);
-       free(ids);
+       lttng_tracker_ids_destroy(ids);
        if (ret < 0) {
                free(pids);
        }
@@ -3060,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) {
@@ -3074,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;
@@ -3107,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;
@@ -3123,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,
@@ -3130,7 +3109,7 @@ static int lttng_track_untrack_id(struct lttng_handle *handle,
 {
        int ret;
        struct lttcomm_session_msg lsm;
-       const char *var_data;
+       const char *var_data = NULL;
        size_t var_data_len = 0;
        int value;
        enum lttng_tracker_id_status status;
This page took 0.032553 seconds and 5 git commands to generate.