Implement loglevels as event and wildcard attributes
[lttng-ust.git] / liblttng-ust / ltt-probes.c
1 /*
2 * ltt-probes.c
3 *
4 * Copyright 2010 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
5 *
6 * Holds LTTng probes registry.
7 *
8 * Dual LGPL v2.1/GPL v2 license.
9 */
10
11 #include <string.h>
12 #include <errno.h>
13 #include <urcu/list.h>
14 #include <urcu/hlist.h>
15 #include <lttng/ust-events.h>
16 #include <assert.h>
17 #include <helper.h>
18 #include <ctype.h>
19
20 #include "tracepoint-internal.h"
21 #include "ltt-tracer-core.h"
22 #include "jhash.h"
23 #include "error.h"
24
25 /*
26 * probe list is protected by ust_lock()/ust_unlock().
27 */
28 static CDS_LIST_HEAD(probe_list);
29
30 static
31 const struct lttng_probe_desc *find_provider(const char *provider)
32 {
33 struct lttng_probe_desc *iter;
34
35 cds_list_for_each_entry(iter, &probe_list, head) {
36 if (!strcmp(iter->provider, provider))
37 return iter;
38 }
39 return NULL;
40 }
41
42 static
43 const struct lttng_event_desc *find_event(const char *name)
44 {
45 struct lttng_probe_desc *probe_desc;
46 int i;
47
48 cds_list_for_each_entry(probe_desc, &probe_list, head) {
49 for (i = 0; i < probe_desc->nr_events; i++) {
50 if (!strncmp(probe_desc->event_desc[i]->name, name,
51 LTTNG_UST_SYM_NAME_LEN - 1))
52 return probe_desc->event_desc[i];
53 }
54 }
55 return NULL;
56 }
57
58 int ltt_probe_register(struct lttng_probe_desc *desc)
59 {
60 struct lttng_probe_desc *iter;
61 int ret = 0;
62 int i;
63
64 ust_lock();
65 if (find_provider(desc->provider)) {
66 ret = -EEXIST;
67 goto end;
68 }
69 /*
70 * TODO: This is O(N^2). Turn into a hash table when probe registration
71 * overhead becomes an issue.
72 */
73 for (i = 0; i < desc->nr_events; i++) {
74 if (find_event(desc->event_desc[i]->name)) {
75 ret = -EEXIST;
76 goto end;
77 }
78 }
79
80 /*
81 * We sort the providers by struct lttng_probe_desc pointer
82 * address.
83 */
84 cds_list_for_each_entry_reverse(iter, &probe_list, head) {
85 BUG_ON(iter == desc); /* Should never be in the list twice */
86 if (iter < desc) {
87 /* We belong to the location right after iter. */
88 cds_list_add(&desc->head, &iter->head);
89 goto desc_added;
90 }
91 }
92 /* We should be added at the head of the list */
93 cds_list_add(&desc->head, &probe_list);
94 desc_added:
95 DBG("just registered probe %s containing %u events",
96 desc->provider, desc->nr_events);
97 /*
98 * fix the events awaiting probe load.
99 */
100 for (i = 0; i < desc->nr_events; i++) {
101 ret = pending_probe_fix_events(desc->event_desc[i]);
102 assert(!ret);
103 }
104 end:
105 ust_unlock();
106 return ret;
107 }
108
109 void ltt_probe_unregister(struct lttng_probe_desc *desc)
110 {
111 ust_lock();
112 cds_list_del(&desc->head);
113 DBG("just unregistered probe %s", desc->provider);
114 ust_unlock();
115 }
116
117 /*
118 * called with UST lock held.
119 */
120 const struct lttng_event_desc *ltt_event_get(const char *name)
121 {
122 const struct lttng_event_desc *event;
123
124 event = find_event(name);
125 if (!event)
126 return NULL;
127 return event;
128 }
129
130 void ltt_event_put(const struct lttng_event_desc *event)
131 {
132 }
133
134 void ltt_probes_prune_event_list(struct lttng_ust_tracepoint_list *list)
135 {
136 struct tp_list_entry *list_entry, *tmp;
137
138 cds_list_for_each_entry_safe(list_entry, tmp, &list->head, head) {
139 cds_list_del(&list_entry->head);
140 free(list_entry);
141 }
142 }
143
144 /*
145 * called with UST lock held.
146 */
147 int ltt_probes_get_event_list(struct lttng_ust_tracepoint_list *list)
148 {
149 struct lttng_probe_desc *probe_desc;
150 int i;
151
152 CDS_INIT_LIST_HEAD(&list->head);
153 cds_list_for_each_entry(probe_desc, &probe_list, head) {
154 for (i = 0; i < probe_desc->nr_events; i++) {
155 struct tp_list_entry *list_entry;
156
157 list_entry = zmalloc(sizeof(*list_entry));
158 if (!list_entry)
159 goto err_nomem;
160 cds_list_add(&list_entry->head, &list->head);
161 strncpy(list_entry->tp.name,
162 probe_desc->event_desc[i]->name,
163 LTTNG_UST_SYM_NAME_LEN);
164 list_entry->tp.name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
165 if (!probe_desc->event_desc[i]->loglevel) {
166 list_entry->tp.loglevel = TRACE_DEFAULT;
167 } else {
168 list_entry->tp.loglevel = *(*probe_desc->event_desc[i]->loglevel);
169 }
170 }
171 }
172 if (cds_list_empty(&list->head))
173 list->iter = NULL;
174 else
175 list->iter =
176 cds_list_first_entry(&list->head, struct tp_list_entry, head);
177 return 0;
178
179 err_nomem:
180 ltt_probes_prune_event_list(list);
181 return -ENOMEM;
182 }
183
184 /*
185 * Return current iteration position, advance internal iterator to next.
186 * Return NULL if end of list.
187 */
188 struct lttng_ust_tracepoint_iter *
189 lttng_ust_tracepoint_list_get_iter_next(struct lttng_ust_tracepoint_list *list)
190 {
191 struct tp_list_entry *entry;
192
193 if (!list->iter)
194 return NULL;
195 entry = list->iter;
196 if (entry->head.next == &list->head)
197 list->iter = NULL;
198 else
199 list->iter = cds_list_entry(entry->head.next,
200 struct tp_list_entry, head);
201 return &entry->tp;
202 }
203
204 /*
205 * marshall all probes/all events and create those that fit the
206 * wildcard. Add them to the events list as created.
207 */
208 void ltt_probes_create_wildcard_events(struct wildcard_entry *entry,
209 struct session_wildcard *wildcard)
210 {
211 struct lttng_probe_desc *probe_desc;
212 struct lttng_ust_event event_param;
213 int i;
214
215 cds_list_for_each_entry(probe_desc, &probe_list, head) {
216 for (i = 0; i < probe_desc->nr_events; i++) {
217 const struct lttng_event_desc *event_desc;
218 int match = 0;
219
220 event_desc = probe_desc->event_desc[i];
221 /* compare excluding final '*' */
222 assert(strlen(entry->name) > 0);
223 if (strcmp(event_desc->name, "lttng_ust:metadata")
224 && (strlen(entry->name) == 1
225 || !strncmp(event_desc->name, entry->name,
226 strlen(entry->name) - 1))) {
227 if (ltt_loglevel_match(event_desc,
228 entry->loglevel_type,
229 entry->loglevel)) {
230 match = 1;
231 }
232 }
233 if (match) {
234 struct ltt_event *ev;
235 int ret;
236
237 memcpy(&event_param, &wildcard->event_param,
238 sizeof(event_param));
239 memcpy(event_param.name,
240 event_desc->name,
241 sizeof(event_param.name));
242 /* create event */
243 ret = ltt_event_create(wildcard->chan,
244 &event_param, NULL,
245 &ev);
246 if (ret) {
247 DBG("Error creating event");
248 continue;
249 }
250 cds_list_add(&ev->wildcard_list,
251 &wildcard->events);
252 }
253 }
254 }
255 }
256
This page took 0.033584 seconds and 4 git commands to generate.