Implement filter bytecode support in lttng-session, and parse filter string
[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
50 switch (domain) {
51 case LTTNG_DOMAIN_UST:
52 ret = ust_app_set_filter_event_glb(usess, uchan, uevent,
53 bytecode);
54 if (ret < 0) {
55 goto error;
56 }
57 break;
58 default:
59 ret = -ENOSYS;
60 goto error;
61 }
62
63 DBG("Filter UST added to event %s",uevent->attr.name);
64
65 return 0;
66
67 error:
68 free(bytecode);
69 return ret;
70 }
71
72 /*
73 * Add UST context to tracer.
74 */
75 int filter_ust_set(struct ltt_ust_session *usess, int domain,
76 struct lttng_filter_bytecode *bytecode, char *event_name,
77 char *channel_name)
78 {
79 int ret = LTTCOMM_OK, have_event = 0;
80 struct lttng_ht_iter iter;
81 struct lttng_ht *chan_ht;
82 struct ltt_ust_channel *uchan = NULL;
83 struct ltt_ust_event *uevent = NULL;
84
85 /*
86 * Define which channel's hashtable to use from the domain or quit if
87 * unknown domain.
88 */
89 switch (domain) {
90 case LTTNG_DOMAIN_UST:
91 chan_ht = usess->domain_global.channels;
92 break;
93 #if 0
94 case LTTNG_DOMAIN_UST_EXEC_NAME:
95 case LTTNG_DOMAIN_UST_PID:
96 case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN:
97 #endif
98 default:
99 ret = LTTCOMM_UND;
100 goto error;
101 }
102
103 /* Do we have an event name */
104 if (strlen(event_name) != 0) {
105 have_event = 1;
106 }
107
108 /* Get UST channel if defined */
109 if (strlen(channel_name) != 0) {
110 uchan = trace_ust_find_channel_by_name(chan_ht, channel_name);
111 if (uchan == NULL) {
112 ret = LTTCOMM_UST_CHAN_NOT_FOUND;
113 goto error;
114 }
115 }
116
117 /* If UST channel specified and event name, get UST event ref */
118 if (uchan && have_event) {
119 uevent = trace_ust_find_event_by_name(uchan->events, event_name);
120 if (uevent == NULL) {
121 ret = LTTCOMM_UST_EVENT_NOT_FOUND;
122 goto error;
123 }
124 }
125
126 /* At this point, we have 4 possibilities */
127
128 if (uchan && uevent) { /* Add filter to event in channel */
129 ret = add_ufilter_to_event(usess, domain, uchan, uevent,
130 bytecode);
131 } else if (uchan && !have_event) { /* Add filter to channel */
132 ERR("Cannot add filter to channel");
133 ret = LTTCOMM_FATAL; /* not supported. */
134 goto error;
135 } else if (!uchan && have_event) { /* Add filter to event */
136 /* Add context to event without having the channel name */
137 cds_lfht_for_each_entry(chan_ht->ht, &iter.iter, uchan, node.node) {
138 uevent = trace_ust_find_event_by_name(uchan->events, event_name);
139 if (uevent != NULL) {
140 ret = add_ufilter_to_event(usess, domain, uchan, uevent, bytecode);
141 /*
142 * LTTng UST does not allowed the same event to be registered
143 * multiple time in different or the same channel. So, if we
144 * found our event, we stop.
145 */
146 goto end;
147 }
148 }
149 ret = LTTCOMM_UST_EVENT_NOT_FOUND;
150 goto error;
151 } else if (!uchan && !have_event) { /* Add filter all events, all channels */
152 ERR("Cannot add filter to channel");
153 ret = LTTCOMM_FATAL; /* not supported. */
154 goto error;
155 }
156
157 end:
158 switch (ret) {
159 case -EEXIST:
160 ret = LTTCOMM_FILTER_EXIST;
161 break;
162 case -ENOMEM:
163 ret = LTTCOMM_FATAL;
164 break;
165 case -EINVAL:
166 ret = LTTCOMM_FILTER_INVAL;
167 break;
168 case -ENOSYS:
169 ret = LTTCOMM_UNKNOWN_DOMAIN;
170 break;
171 default:
172 ret = LTTCOMM_OK;
173 break;
174 }
175
176 error:
177 return ret;
178 }
This page took 0.044907 seconds and 4 git commands to generate.