Commit | Line | Data |
---|---|---|
97ee3a89 DG |
1 | /* |
2 | * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca> | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify it | |
5 | * under the terms of the GNU General Public License as published by the Free | |
6 | * Software Foundation; only version 2 of the License. | |
7 | * | |
8 | * This program is distributed in the hope that it will be useful, but WITHOUT | |
9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
11 | * more details. | |
12 | * | |
13 | * You should have received a copy of the GNU General Public License along with | |
14 | * this program; if not, write to the Free Software Foundation, Inc., 59 Temple | |
15 | * Place - Suite 330, Boston, MA 02111-1307, USA. | |
16 | */ | |
17 | ||
18 | #define _GNU_SOURCE | |
19 | #include <stdio.h> | |
20 | #include <stdlib.h> | |
21 | #include <string.h> | |
22 | #include <unistd.h> | |
23 | ||
24 | #include <lttngerr.h> | |
25 | #include <lttng-share.h> | |
26 | ||
27 | #include "trace-ust.h" | |
28 | ||
29 | /* | |
30 | * Find the channel name for the given ust session. | |
31 | */ | |
32 | struct ltt_ust_channel *trace_ust_get_channel_by_name( | |
33 | char *name, struct ltt_ust_session *session) | |
34 | { | |
35 | struct ltt_ust_channel *chan; | |
36 | ||
37 | if (session == NULL) { | |
38 | ERR("Undefine session"); | |
39 | goto error; | |
40 | } | |
41 | ||
42 | cds_list_for_each_entry(chan, &session->channels.head, list) { | |
43 | if (strcmp(name, chan->name) == 0) { | |
44 | DBG("Found UST channel by name %s", name); | |
45 | return chan; | |
46 | } | |
47 | } | |
48 | ||
49 | error: | |
50 | return NULL; | |
51 | } | |
52 | ||
53 | /* | |
54 | * Find the event name for the given channel. | |
55 | */ | |
56 | struct ltt_ust_event *trace_ust_get_event_by_name( | |
57 | char *name, struct ltt_ust_channel *channel) | |
58 | { | |
59 | struct ltt_ust_event *ev; | |
60 | ||
61 | if (channel == NULL) { | |
62 | ERR("Undefine channel"); | |
63 | goto error; | |
64 | } | |
65 | ||
66 | cds_list_for_each_entry(ev, &channel->events.head, list) { | |
67 | if (strcmp(name, ev->event->name) == 0) { | |
68 | DBG("Found UST event by name %s for channel %s", name, | |
69 | channel->name); | |
70 | return ev; | |
71 | } | |
72 | } | |
73 | ||
74 | error: | |
75 | return NULL; | |
76 | } | |
77 | ||
78 | /* | |
79 | * Allocate and initialize a ust session data structure. | |
80 | * | |
81 | * Return pointer to structure or NULL. | |
82 | */ | |
83 | struct ltt_ust_session *trace_ust_create_session(void) | |
84 | { | |
85 | struct ltt_ust_session *lus; | |
86 | ||
87 | /* Allocate a new ltt ust session */ | |
88 | lus = malloc(sizeof(struct ltt_ust_session)); | |
89 | if (lus == NULL) { | |
90 | perror("create ust session malloc"); | |
91 | goto error; | |
92 | } | |
93 | ||
94 | /* Init data structure */ | |
95 | lus->handle = -1; | |
96 | lus->enabled = 1; | |
97 | lus->uconsumer_fds_sent = 0; | |
98 | lus->path = NULL; | |
99 | lus->metadata = NULL; | |
100 | lus->channels.count = 0; | |
101 | CDS_INIT_LIST_HEAD(&lus->channels.head); | |
102 | ||
103 | return lus; | |
104 | ||
105 | error: | |
106 | return NULL; | |
107 | } | |
108 | ||
109 | /* | |
110 | * Allocate and initialize a ust channel data structure. | |
111 | * | |
112 | * Return pointer to structure or NULL. | |
113 | */ | |
114 | struct ltt_ust_channel *trace_ust_create_channel(char *name, char *path, | |
115 | struct lttng_ust_channel *chan) | |
116 | { | |
117 | int ret; | |
118 | struct ltt_ust_channel *luc; | |
119 | ||
120 | luc = malloc(sizeof(struct ltt_ust_channel)); | |
121 | if (luc == NULL) { | |
122 | perror("ltt_ust_channel malloc"); | |
123 | goto error; | |
124 | } | |
125 | ||
126 | luc->attr = malloc(sizeof(struct lttng_ust_channel)); | |
127 | if (luc->attr == NULL) { | |
128 | perror("lttng_ust_channel malloc"); | |
129 | goto error; | |
130 | } | |
131 | memcpy(luc->attr, chan, sizeof(struct lttng_ust_channel)); | |
132 | ||
133 | luc->handle = -1; | |
134 | luc->enabled = 1; | |
135 | luc->ctx = NULL; | |
136 | luc->events.count = 0; | |
137 | CDS_INIT_LIST_HEAD(&luc->events.head); | |
138 | ||
139 | /* Copy channel name */ | |
140 | strncpy(luc->name, name, LTTNG_UST_SYM_NAME_LEN); | |
141 | luc->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0'; | |
142 | ||
143 | /* Set trace output path */ | |
144 | ret = asprintf(&luc->trace_path, "%s", path); | |
145 | if (ret < 0) { | |
146 | perror("asprintf ust create channel"); | |
147 | goto error; | |
148 | } | |
149 | ||
150 | return luc; | |
151 | ||
152 | error: | |
153 | return NULL; | |
154 | } | |
155 | ||
156 | /* | |
157 | * Allocate and initialize a ust event. Set name and event type. | |
158 | * | |
159 | * Return pointer to structure or NULL. | |
160 | */ | |
161 | struct ltt_ust_event *trace_ust_create_event(struct lttng_event *ev) | |
162 | { | |
163 | struct ltt_ust_event *lue; | |
164 | struct lttng_ust_event *event; | |
165 | ||
166 | lue = malloc(sizeof(struct ltt_ust_event)); | |
167 | event = malloc(sizeof(struct lttng_ust_event)); | |
168 | if (lue == NULL || event == NULL) { | |
169 | perror("ust event malloc"); | |
170 | goto error; | |
171 | } | |
172 | ||
173 | switch (ev->type) { | |
174 | case LTTNG_EVENT_PROBE: | |
175 | event->instrumentation = LTTNG_UST_PROBE; | |
176 | break; | |
177 | case LTTNG_EVENT_FUNCTION: | |
178 | event->instrumentation = LTTNG_UST_FUNCTION; | |
179 | break; | |
180 | case LTTNG_EVENT_FUNCTION_ENTRY: | |
181 | event->instrumentation = LTTNG_UST_FUNCTION; | |
182 | break; | |
183 | case LTTNG_EVENT_TRACEPOINT: | |
184 | event->instrumentation = LTTNG_UST_TRACEPOINT; | |
185 | break; | |
186 | default: | |
187 | ERR("Unknown ust instrumentation type (%d)", ev->type); | |
188 | goto error; | |
189 | } | |
190 | ||
191 | /* Copy event name */ | |
192 | strncpy(event->name, ev->name, LTTNG_UST_SYM_NAME_LEN); | |
193 | event->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0'; | |
194 | ||
195 | /* Setting up a ust event */ | |
196 | lue->handle = -1; | |
197 | lue->event = event; | |
198 | lue->enabled = 1; | |
199 | lue->ctx = NULL; | |
200 | ||
201 | return lue; | |
202 | ||
203 | error: | |
204 | return NULL; | |
205 | } | |
206 | ||
207 | /* | |
208 | * Allocate and initialize a ust metadata. | |
209 | * | |
210 | * Return pointer to structure or NULL. | |
211 | */ | |
212 | struct ltt_ust_metadata *trace_ust_create_metadata(char *path) | |
213 | { | |
214 | int ret; | |
215 | struct ltt_ust_metadata *lum; | |
216 | struct lttng_ust_channel *attr; | |
217 | ||
218 | lum = malloc(sizeof(struct ltt_ust_metadata)); | |
219 | attr = malloc(sizeof(struct lttng_ust_channel)); | |
220 | if (lum == NULL || attr == NULL) { | |
221 | perror("ust metadata malloc"); | |
222 | goto error; | |
223 | } | |
224 | ||
225 | /* Set default attributes */ | |
226 | attr->overwrite = DEFAULT_CHANNEL_OVERWRITE; | |
227 | attr->subbuf_size = DEFAULT_METADATA_SUBBUF_SIZE; | |
228 | attr->num_subbuf = DEFAULT_METADATA_SUBBUF_NUM; | |
229 | attr->switch_timer_interval = DEFAULT_CHANNEL_SWITCH_TIMER; | |
230 | attr->read_timer_interval = DEFAULT_CHANNEL_READ_TIMER; | |
231 | attr->output = DEFAULT_UST_CHANNEL_OUTPUT; | |
232 | ||
233 | lum->attr = attr; | |
234 | lum->handle = -1; | |
235 | /* Set metadata trace path */ | |
236 | ret = asprintf(&lum->trace_path, "%s/metadata", path); | |
237 | if (ret < 0) { | |
238 | perror("asprintf ust metadata"); | |
239 | goto error; | |
240 | } | |
241 | ||
242 | return lum; | |
243 | ||
244 | error: | |
245 | return NULL; | |
246 | } | |
247 | ||
248 | /* | |
249 | * Cleanup ust event structure. | |
250 | */ | |
251 | void trace_ust_destroy_event(struct ltt_ust_event *event) | |
252 | { | |
253 | DBG("[trace] Destroy ust event %s", event->event->name); | |
254 | ||
255 | /* Free attributes */ | |
256 | free(event->event); | |
257 | free(event->ctx); | |
258 | ||
259 | /* Remove from event list */ | |
260 | cds_list_del(&event->list); | |
261 | free(event); | |
262 | } | |
263 | ||
264 | /* | |
265 | * Cleanup ust channel structure. | |
266 | */ | |
267 | void trace_ust_destroy_channel(struct ltt_ust_channel *channel) | |
268 | { | |
269 | struct ltt_ust_event *event, *etmp; | |
270 | ||
271 | DBG("[trace] Destroy ust channel %d", channel->handle); | |
272 | ||
273 | free(channel->trace_path); | |
274 | /* Free attributes structure */ | |
275 | free(channel->attr); | |
276 | free(channel->ctx); | |
277 | ||
278 | /* For each event in the channel list */ | |
279 | cds_list_for_each_entry_safe(event, etmp, &channel->events.head, list) { | |
280 | trace_ust_destroy_event(event); | |
281 | } | |
282 | ||
283 | /* Remove from channel list */ | |
284 | cds_list_del(&channel->list); | |
285 | free(channel); | |
286 | } | |
287 | ||
288 | /* | |
289 | * Cleanup ust metadata structure. | |
290 | */ | |
291 | void trace_ust_destroy_metadata(struct ltt_ust_metadata *metadata) | |
292 | { | |
293 | DBG("[trace] Destroy ust metadata %d", metadata->handle); | |
294 | ||
295 | /* Free attributes */ | |
296 | free(metadata->attr); | |
297 | free(metadata->trace_path); | |
298 | ||
299 | free(metadata); | |
300 | } | |
301 | ||
302 | /* | |
303 | * Cleanup ust session structure | |
304 | */ | |
305 | void trace_ust_destroy_session(struct ltt_ust_session *session) | |
306 | { | |
307 | struct ltt_ust_channel *channel, *ctmp; | |
308 | ||
309 | DBG("[trace] Destroy ust session %d", session->handle); | |
310 | ||
311 | /* Extra safety */ | |
312 | if (session == NULL) { | |
313 | return; | |
314 | } | |
315 | ||
316 | if (session->metadata != NULL) { | |
317 | trace_ust_destroy_metadata(session->metadata); | |
318 | } | |
319 | ||
320 | cds_list_for_each_entry_safe(channel, ctmp, &session->channels.head, list) { | |
321 | trace_ust_destroy_channel(channel); | |
322 | } | |
323 | ||
324 | free(session->path); | |
325 | free(session); | |
326 | } |