Change the UST event hash table match function
[lttng-tools.git] / src / bin / lttng-sessiond / filter.c
1 /*
2 * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
3 * Copyright (C) 2012 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License, version 2 only,
7 * as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18
19 #define _GNU_SOURCE
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <unistd.h>
24 #include <urcu/list.h>
25
26 #include <common/error.h>
27 #include <common/sessiond-comm/sessiond-comm.h>
28
29 #include "filter.h"
30 #include "kernel.h"
31 #include "ust-app.h"
32 #include "trace-ust.h"
33
34 /*
35 * Add UST context to event.
36 */
37 static int add_ufilter_to_event(struct ltt_ust_session *usess, int domain,
38 struct ltt_ust_channel *uchan, struct ltt_ust_event *uevent,
39 struct lttng_filter_bytecode *bytecode)
40 {
41 int ret;
42
43 if (uevent->filter) {
44 ret = -EEXIST;
45 goto error;
46 }
47 /* Same layout. */
48 uevent->filter = (struct lttng_ust_filter_bytecode *) bytecode;
49 uevent->filter->seqnum = usess->filter_seq_num;
50
51 switch (domain) {
52 case LTTNG_DOMAIN_UST:
53 ret = ust_app_set_filter_event_glb(usess, uchan, uevent,
54 bytecode);
55 if (ret < 0) {
56 goto error;
57 }
58 usess->filter_seq_num++;
59 break;
60 default:
61 ret = -ENOSYS;
62 goto error;
63 }
64
65 DBG("Filter UST added to event %s",uevent->attr.name);
66
67 return 0;
68
69 error:
70 free(bytecode);
71 return ret;
72 }
73
74 /*
75 * Add UST context to tracer.
76 */
77 int filter_ust_set(struct ltt_ust_session *usess, int domain,
78 struct lttng_filter_bytecode *bytecode, struct lttng_event *event,
79 char *channel_name)
80 {
81 int ret = LTTNG_OK, have_event = 0;
82 struct lttng_ht_iter iter;
83 struct lttng_ht *chan_ht;
84 struct ltt_ust_channel *uchan = NULL;
85 struct ltt_ust_event *uevent = NULL;
86
87 /*
88 * Define which channel's hashtable to use from the domain or quit if
89 * unknown domain.
90 */
91 switch (domain) {
92 case LTTNG_DOMAIN_UST:
93 chan_ht = usess->domain_global.channels;
94 break;
95 #if 0
96 case LTTNG_DOMAIN_UST_EXEC_NAME:
97 case LTTNG_DOMAIN_UST_PID:
98 case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN:
99 #endif
100 default:
101 ret = LTTNG_ERR_UND;
102 goto error;
103 }
104
105 /* Do we have a valid event. */
106 if (event && event->name[0] != '\0') {
107 have_event = 1;
108 }
109
110 /* Get UST channel if defined */
111 if (strlen(channel_name) != 0) {
112 uchan = trace_ust_find_channel_by_name(chan_ht, channel_name);
113 if (uchan == NULL) {
114 ret = LTTNG_ERR_UST_CHAN_NOT_FOUND;
115 goto error;
116 }
117 }
118
119 /* If UST channel specified and event name, get UST event ref */
120 if (uchan && have_event) {
121 uevent = trace_ust_find_event(uchan->events, event->name, bytecode,
122 event->loglevel);
123 if (uevent == NULL) {
124 ret = LTTNG_ERR_UST_EVENT_NOT_FOUND;
125 goto error;
126 }
127 }
128
129 /* At this point, we have 4 possibilities */
130
131 if (uchan && uevent) { /* Add filter to event in channel */
132 ret = add_ufilter_to_event(usess, domain, uchan, uevent,
133 bytecode);
134 } else if (uchan && !have_event) { /* Add filter to channel */
135 ERR("Cannot add filter to channel");
136 ret = LTTNG_ERR_FATAL; /* not supported. */
137 goto error;
138 } else if (!uchan && have_event) { /* Add filter to event */
139 /* Add context to event without having the channel name */
140 cds_lfht_for_each_entry(chan_ht->ht, &iter.iter, uchan, node.node) {
141 uevent = trace_ust_find_event(uchan->events, event->name, bytecode,
142 event->loglevel);
143 if (uevent != NULL) {
144 ret = add_ufilter_to_event(usess, domain, uchan, uevent, bytecode);
145 /*
146 * LTTng UST does not allowed the same event to be registered
147 * multiple time in different or the same channel. So, if we
148 * found our event, we stop.
149 */
150 goto end;
151 }
152 }
153 ret = LTTNG_ERR_UST_EVENT_NOT_FOUND;
154 goto error;
155 } else if (!uchan && !have_event) { /* Add filter all events, all channels */
156 ERR("Cannot add filter to channel");
157 ret = LTTNG_ERR_FATAL; /* not supported. */
158 goto error;
159 }
160
161 end:
162 /* Must handle both local internal error and UST code. */
163 switch (ret) {
164 case -EEXIST:
165 case -LTTNG_UST_ERR_EXIST:
166 ret = LTTNG_ERR_FILTER_EXIST;
167 break;
168 case -ENOMEM:
169 ret = LTTNG_ERR_FATAL;
170 break;
171 case -EINVAL:
172 case -LTTNG_UST_ERR_INVAL:
173 ret = LTTNG_ERR_FILTER_INVAL;
174 break;
175 case -ENOSYS:
176 case -LTTNG_UST_ERR_NOSYS:
177 ret = LTTNG_ERR_UNKNOWN_DOMAIN;
178 break;
179 default:
180 ret = LTTNG_OK;
181 break;
182 }
183
184 error:
185 return ret;
186 }
This page took 0.032922 seconds and 4 git commands to generate.