Implement field listing command
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Tue, 8 May 2012 12:13:02 +0000 (08:13 -0400)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Fri, 1 Jun 2012 17:35:22 +0000 (13:35 -0400)
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
include/lttng/ust-abi.h
include/lttng/ust-events.h
liblttng-ust/ltt-probes.c
liblttng-ust/lttng-ust-abi.c

index b3af9bf49528d6e131d44c10ff86db59699e316f..898d6cfea790eb814e6353a4fd8c5297cedd336d 100644 (file)
@@ -85,6 +85,23 @@ struct lttng_ust_event {
        } u;
 };
 
+enum lttng_ust_field_type {
+       LTTNG_UST_FIELD_OTHER                   = 0,
+       LTTNG_UST_FIELD_INTEGER                 = 1,
+       LTTNG_UST_FIELD_ENUM                    = 2,
+       LTTNG_UST_FIELD_FLOAT                   = 3,
+       LTTNG_UST_FIELD_STRING                  = 4,
+};
+
+#define LTTNG_UST_FIELD_ITER_PADDING           LTTNG_UST_SYM_NAME_LEN + 32
+struct lttng_ust_field_iter {
+       char event_name[LTTNG_UST_SYM_NAME_LEN];
+       char field_name[LTTNG_UST_SYM_NAME_LEN];
+       enum lttng_ust_field_type type;
+       int loglevel;                           /* event loglevel */
+       char padding[LTTNG_UST_FIELD_ITER_PADDING];
+};
+
 enum lttng_ust_context_type {
        LTTNG_UST_CONTEXT_VTID                  = 0,
        LTTNG_UST_CONTEXT_VPID                  = 1,
@@ -164,6 +181,7 @@ struct lttng_ust_calibrate {
 #define LTTNG_UST_TRACEPOINT_LIST              _UST_CMD(0x42)
 #define LTTNG_UST_WAIT_QUIESCENT               _UST_CMD(0x43)
 #define LTTNG_UST_REGISTER_DONE                        _UST_CMD(0x44)
+#define LTTNG_UST_TRACEPOINT_FIELD_LIST                _UST_CMD(0x45)
 
 /* Session FD commands */
 #define LTTNG_UST_METADATA                     \
@@ -190,6 +208,7 @@ struct lttng_ust_calibrate {
 
 /* Tracepoint list commands */
 #define LTTNG_UST_TRACEPOINT_LIST_GET          _UST_CMD(0x90)
+#define LTTNG_UST_TRACEPOINT_FIELD_LIST_GET    _UST_CMD(0x91)
 
 #define LTTNG_UST_ROOT_HANDLE  0
 
index 65f502360372638749d6ed77fcaa2d55d91b4344..9c015821b53a8f651f0e032098cd96e9fcea768b 100644 (file)
@@ -271,6 +271,16 @@ struct lttng_ust_tracepoint_list {
        struct cds_list_head head;
 };
 
+struct tp_field_list_entry {
+       struct lttng_ust_field_iter field;
+       struct cds_list_head head;
+};
+
+struct lttng_ust_field_list {
+       struct tp_field_list_entry *iter;
+       struct cds_list_head head;
+};
+
 struct ust_pending_probe;
 
 /*
@@ -444,6 +454,10 @@ int ltt_probes_get_event_list(struct lttng_ust_tracepoint_list *list);
 void ltt_probes_prune_event_list(struct lttng_ust_tracepoint_list *list);
 struct lttng_ust_tracepoint_iter *
        lttng_ust_tracepoint_list_get_iter_next(struct lttng_ust_tracepoint_list *list);
+int ltt_probes_get_field_list(struct lttng_ust_field_list *list);
+void ltt_probes_prune_field_list(struct lttng_ust_field_list *list);
+struct lttng_ust_field_iter *
+       lttng_ust_field_list_get_iter_next(struct lttng_ust_field_list *list);
 
 int ltt_wildcard_enable(struct session_wildcard *wildcard);
 int ltt_wildcard_disable(struct session_wildcard *wildcard);
index 02df21b2f61c847e3ba082866577daa4c40c79bc..3d6b1414b97c6baf2a0615592288cb9e67bb0225 100644 (file)
@@ -219,6 +219,89 @@ struct lttng_ust_tracepoint_iter *
        return &entry->tp;
 }
 
+void ltt_probes_prune_field_list(struct lttng_ust_field_list *list)
+{
+       struct tp_field_list_entry *list_entry, *tmp;
+
+       cds_list_for_each_entry_safe(list_entry, tmp, &list->head, head) {
+               cds_list_del(&list_entry->head);
+               free(list_entry);
+       }
+}
+
+/*
+ * called with UST lock held.
+ */
+int ltt_probes_get_field_list(struct lttng_ust_field_list *list)
+{
+       struct lttng_probe_desc *probe_desc;
+       int i;
+
+       CDS_INIT_LIST_HEAD(&list->head);
+       cds_list_for_each_entry(probe_desc, &probe_list, head) {
+               for (i = 0; i < probe_desc->nr_events; i++) {
+                       const struct lttng_event_desc *event_desc =
+                               probe_desc->event_desc[i];
+                       int j;
+
+                       for (j = 0; j < event_desc->nr_fields; j++) {
+                               const struct lttng_event_field *event_field =
+                                       &event_desc->fields[j];
+                               struct tp_field_list_entry *list_entry;
+
+                               list_entry = zmalloc(sizeof(*list_entry));
+                               if (!list_entry)
+                                       goto err_nomem;
+                               cds_list_add(&list_entry->head, &list->head);
+                               strncpy(list_entry->field.event_name,
+                                       event_desc->name,
+                                       LTTNG_UST_SYM_NAME_LEN);
+                               list_entry->field.event_name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
+                               strncpy(list_entry->field.field_name,
+                                       event_field->name,
+                                       LTTNG_UST_SYM_NAME_LEN);
+                               list_entry->field.field_name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
+                               if (!event_desc->loglevel) {
+                                       list_entry->field.loglevel = TRACE_DEFAULT;
+                               } else {
+                                       list_entry->field.loglevel = *(*event_desc->loglevel);
+                               }
+                       }
+               }
+       }
+       if (cds_list_empty(&list->head))
+               list->iter = NULL;
+       else
+               list->iter =
+                       cds_list_first_entry(&list->head,
+                               struct tp_field_list_entry, head);
+       return 0;
+
+err_nomem:
+       ltt_probes_prune_field_list(list);
+       return -ENOMEM;
+}
+
+/*
+ * Return current iteration position, advance internal iterator to next.
+ * Return NULL if end of list.
+ */
+struct lttng_ust_field_iter *
+       lttng_ust_field_list_get_iter_next(struct lttng_ust_field_list *list)
+{
+       struct tp_field_list_entry *entry;
+
+       if (!list->iter)
+               return NULL;
+       entry = list->iter;
+       if (entry->head.next == &list->head)
+               list->iter = NULL;
+       else
+               list->iter = cds_list_entry(entry->head.next,
+                               struct tp_field_list_entry, head);
+       return &entry->field;
+}
+
 /*
  * marshall all probes/all events and create those that fit the
  * wildcard. Add them to the events list as created.
index 435763d7e4e6f5f2ffd6754c15be1439f65f41f8..c16a617ceb98710b28466e6dc72080d463d173cc 100644 (file)
@@ -52,6 +52,8 @@ static int lttng_ust_abi_close_in_progress;
 
 static
 int lttng_abi_tracepoint_list(void);
+static
+int lttng_abi_tracepoint_field_list(void);
 
 /*
  * Object descriptor table. Should be protected from concurrent access
@@ -220,6 +222,7 @@ static const struct lttng_ust_objd_ops lttng_event_ops;
 static const struct lttng_ust_objd_ops lttng_wildcard_ops;
 static const struct lttng_ust_objd_ops lib_ring_buffer_objd_ops;
 static const struct lttng_ust_objd_ops lttng_tracepoint_list_ops;
+static const struct lttng_ust_objd_ops lttng_tracepoint_field_list_ops;
 
 enum channel_type {
        PER_CPU_CHANNEL,
@@ -303,6 +306,8 @@ long lttng_abi_add_context(int objd,
  *             Returns the LTTng kernel tracer version
  *     LTTNG_UST_TRACEPOINT_LIST
  *             Returns a file descriptor listing available tracepoints
+ *     LTTNG_UST_TRACEPOINT_FIELD_LIST
+ *             Returns a file descriptor listing available tracepoint fields
  *     LTTNG_UST_WAIT_QUIESCENT
  *             Returns after all previously running probes have completed
  *
@@ -320,6 +325,8 @@ long lttng_cmd(int objd, unsigned int cmd, unsigned long arg,
                                (struct lttng_ust_tracer_version *) arg);
        case LTTNG_UST_TRACEPOINT_LIST:
                return lttng_abi_tracepoint_list();
+       case LTTNG_UST_TRACEPOINT_FIELD_LIST:
+               return lttng_abi_tracepoint_field_list();
        case LTTNG_UST_WAIT_QUIESCENT:
                synchronize_trace();
                return 0;
@@ -602,6 +609,89 @@ static const struct lttng_ust_objd_ops lttng_tracepoint_list_ops = {
        .cmd = lttng_tracepoint_list_cmd,
 };
 
+static
+long lttng_tracepoint_field_list_cmd(int objd, unsigned int cmd,
+       unsigned long arg, union ust_args *uargs)
+{
+       struct lttng_ust_field_list *list = objd_private(objd);
+       struct lttng_ust_field_iter *tp =
+               (struct lttng_ust_field_iter *) arg;
+       struct lttng_ust_field_iter *iter;
+
+       switch (cmd) {
+       case LTTNG_UST_TRACEPOINT_FIELD_LIST_GET:
+       {
+       retry:
+               iter = lttng_ust_field_list_get_iter_next(list);
+               if (!iter)
+                       return -ENOENT;
+               if (!strcmp(iter->event_name, "lttng_ust:metadata"))
+                       goto retry;
+               memcpy(tp, iter, sizeof(*tp));
+               return 0;
+       }
+       default:
+               return -EINVAL;
+       }
+}
+
+static
+int lttng_abi_tracepoint_field_list(void)
+{
+       int list_objd, ret;
+       struct lttng_ust_field_list *list;
+
+       list_objd = objd_alloc(NULL, &lttng_tracepoint_field_list_ops);
+       if (list_objd < 0) {
+               ret = list_objd;
+               goto objd_error;
+       }
+       list = zmalloc(sizeof(*list));
+       if (!list) {
+               ret = -ENOMEM;
+               goto alloc_error;
+       }
+       objd_set_private(list_objd, list);
+
+       /* populate list by walking on all registered probes. */
+       ret = ltt_probes_get_field_list(list);
+       if (ret) {
+               goto list_error;
+       }
+       return list_objd;
+
+list_error:
+       free(list);
+alloc_error:
+       {
+               int err;
+
+               err = lttng_ust_objd_unref(list_objd);
+               assert(!err);
+       }
+objd_error:
+       return ret;
+}
+
+static
+int lttng_release_tracepoint_field_list(int objd)
+{
+       struct lttng_ust_field_list *list = objd_private(objd);
+
+       if (list) {
+               ltt_probes_prune_field_list(list);
+               free(list);
+               return 0;
+       } else {
+               return -EINVAL;
+       }
+}
+
+static const struct lttng_ust_objd_ops lttng_tracepoint_field_list_ops = {
+       .release = lttng_release_tracepoint_field_list,
+       .cmd = lttng_tracepoint_field_list_cmd,
+};
+
 struct stream_priv_data {
        struct lttng_ust_lib_ring_buffer *buf;
        struct ltt_channel *ltt_chan;
This page took 0.028975 seconds and 4 git commands to generate.