Network streaming support
[lttng-tools.git] / src / bin / lttng-sessiond / consumer.c
CommitLineData
00e2e675
DG
1/*
2 * Copyright (C) 2012 - David Goulet <dgoulet@efficios.com>
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, version 2 only, as
6 * published by the Free Software Foundation.
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., 51
15 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16 */
17
18#define _GNU_SOURCE
19#include <assert.h>
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23#include <sys/stat.h>
24#include <sys/types.h>
25#include <unistd.h>
26
27#include <common/common.h>
28#include <common/defaults.h>
29#include <common/uri.h>
30
31#include "consumer.h"
32
33/*
34 * Allocate and assign data to a consumer_output object.
35 *
36 * Return pointer to structure.
37 */
38struct consumer_output *consumer_create_output(enum consumer_dst_type type)
39{
40 struct consumer_output *output = NULL;
41
42 output = zmalloc(sizeof(struct consumer_output));
43 if (output == NULL) {
44 PERROR("zmalloc consumer_output");
45 goto error;
46 }
47
48 /* By default, consumer output is enabled */
49 output->enabled = 1;
50 output->type = type;
51 output->net_seq_index = -1;
52 /*
53 * Important to keep it to a negative value on creation since it was zeroed
54 * during allocation and the file descriptor 0 is a valid one.
55 */
56 output->sock = -1;
57
58error:
59 return output;
60}
61
62/*
63 * Delete the consumer_output object from the list and free the ptr.
64 */
65void consumer_destroy_output(struct consumer_output *obj)
66{
67 if (obj == NULL) {
68 return;
69 }
70
71 if (obj->sock >= 0) {
72 (void) close(obj->sock);
73 }
74 free(obj);
75}
76
77/*
78 * Copy consumer output and returned the newly allocated copy.
79 */
80struct consumer_output *consumer_copy_output(struct consumer_output *obj)
81{
82 struct consumer_output *output;
83
84 assert(obj);
85
86 output = consumer_create_output(obj->type);
87 if (output == NULL) {
88 goto error;
89 }
90
91 memcpy(output, obj, sizeof(struct consumer_output));
92
93error:
94 return output;
95}
96
97/*
98 * Set network URI to the consumer output object.
99 *
100 * Return 0 on success. Negative value on error.
101 */
102int consumer_set_network_uri(struct consumer_output *obj,
103 struct lttng_uri *uri)
104{
105 int ret;
106 char tmp_path[PATH_MAX];
107 char hostname[HOST_NAME_MAX];
108 struct lttng_uri *dst_uri = NULL;
109
110 /* Code flow error safety net. */
111 assert(obj);
112 assert(uri);
113
114 switch (uri->stype) {
115 case LTTNG_STREAM_CONTROL:
116 dst_uri = &obj->dst.net.control;
117 obj->dst.net.control_isset = 1;
118 if (uri->port == 0) {
119 /* Assign default port. */
120 uri->port = DEFAULT_NETWORK_CONTROL_PORT;
121 }
122 break;
123 case LTTNG_STREAM_DATA:
124 dst_uri = &obj->dst.net.data;
125 obj->dst.net.data_isset = 1;
126 if (uri->port == 0) {
127 /* Assign default port. */
128 uri->port = DEFAULT_NETWORK_DATA_PORT;
129 }
130 break;
131 default:
132 ERR("Set network uri type unknown %d", uri->stype);
133 goto error;
134 }
135
136 ret = uri_compare(dst_uri, uri);
137 if (!ret) {
138 /* Same URI, don't touch it and return success. */
139 DBG3("URI network compare are the same");
140 goto end;
141 }
142
143 /* URIs were not equal, replacing it. */
144 memset(dst_uri, 0, sizeof(struct lttng_uri));
145 memcpy(dst_uri, uri, sizeof(struct lttng_uri));
146 obj->type = CONSUMER_DST_NET;
147
148 /* Handle subdir and add hostname in front. */
149 if (dst_uri->stype == LTTNG_STREAM_CONTROL) {
150 /* Get hostname to append it in the pathname */
151 ret = gethostname(hostname, sizeof(hostname));
152 if (ret < 0) {
153 PERROR("gethostname. Fallback on default localhost");
154 strncpy(hostname, "localhost", sizeof(hostname));
155 }
156 hostname[sizeof(hostname) - 1] = '\0';
157
158 /* Setup consumer subdir if none present in the control URI */
159 if (strlen(dst_uri->subdir) == 0) {
160 ret = snprintf(tmp_path, sizeof(tmp_path), "%s/%s",
161 hostname, obj->subdir);
162 } else {
163 ret = snprintf(tmp_path, sizeof(tmp_path), "%s/%s",
164 hostname, dst_uri->subdir);
165 }
166 if (ret < 0) {
167 PERROR("snprintf set consumer uri subdir");
168 goto error;
169 }
170
171 strncpy(obj->subdir, tmp_path, sizeof(obj->subdir));
172 DBG3("Consumer set network uri subdir path %s", tmp_path);
173 }
174
175end:
176 return 0;
177
178error:
179 return -1;
180}
181
182/*
183 * Send file descriptor to consumer via sock.
184 */
185int consumer_send_fds(int sock, int *fds, size_t nb_fd)
186{
187 int ret;
188
189 assert(fds);
190 assert(nb_fd > 0);
191
192 ret = lttcomm_send_fds_unix_sock(sock, fds, nb_fd);
193 if (ret < 0) {
194 PERROR("send consumer fds");
195 goto error;
196 }
197
198error:
199 return ret;
200}
201
202/*
203 * Consumer send channel communication message structure to consumer.
204 */
205int consumer_send_channel(int sock, struct lttcomm_consumer_msg *msg)
206{
207 int ret;
208
209 assert(msg);
210 assert(sock >= 0);
211
212 ret = lttcomm_send_unix_sock(sock, msg,
213 sizeof(struct lttcomm_consumer_msg));
214 if (ret < 0) {
215 PERROR("send consumer channel");
216 goto error;
217 }
218
219error:
220 return ret;
221}
222
223/*
224 * Init channel communication message structure.
225 */
226void consumer_init_channel_comm_msg(struct lttcomm_consumer_msg *msg,
227 enum lttng_consumer_command cmd,
228 int channel_key,
229 uint64_t max_sb_size,
230 uint64_t mmap_len,
231 const char *name)
232{
233 assert(msg);
234
235 /* TODO: Args validation */
236
237 /* Zeroed structure */
238 memset(msg, 0, sizeof(struct lttcomm_consumer_msg));
239
240 /* Send channel */
241 msg->cmd_type = cmd;
242 msg->u.channel.channel_key = channel_key;
243 msg->u.channel.max_sb_size = max_sb_size;
244 msg->u.channel.mmap_len = mmap_len;
245}
246
247/*
248 * Init stream communication message structure.
249 */
250void consumer_init_stream_comm_msg(struct lttcomm_consumer_msg *msg,
251 enum lttng_consumer_command cmd,
252 int channel_key,
253 int stream_key,
254 uint32_t state,
255 enum lttng_event_output output,
256 uint64_t mmap_len,
257 uid_t uid,
258 gid_t gid,
259 int net_index,
260 unsigned int metadata_flag,
261 const char *name,
262 const char *pathname)
263{
264 assert(msg);
265
266 memset(msg, 0, sizeof(struct lttcomm_consumer_msg));
267
268 /* TODO: Args validation */
269
270 msg->cmd_type = cmd;
271 msg->u.stream.channel_key = channel_key;
272 msg->u.stream.stream_key = stream_key;
273 msg->u.stream.state = state;
274 msg->u.stream.output = output;
275 msg->u.stream.mmap_len = mmap_len;
276 msg->u.stream.uid = uid;
277 msg->u.stream.gid = gid;
278 msg->u.stream.net_index = net_index;
279 msg->u.stream.metadata_flag = metadata_flag;
280 strncpy(msg->u.stream.name, name, sizeof(msg->u.stream.name));
281 msg->u.stream.name[sizeof(msg->u.stream.name) - 1] = '\0';
282 strncpy(msg->u.stream.path_name, pathname,
283 sizeof(msg->u.stream.path_name));
284 msg->u.stream.path_name[sizeof(msg->u.stream.path_name) - 1] = '\0';
285}
286
287/*
288 * Send stream communication structure to the consumer.
289 */
290int consumer_send_stream(int sock, struct consumer_output *dst,
291 struct lttcomm_consumer_msg *msg, int *fds, size_t nb_fd)
292{
293 int ret;
294
295 assert(msg);
296 assert(dst);
297
298 switch (dst->type) {
299 case CONSUMER_DST_NET:
300 /* Consumer should send the stream on the network. */
301 msg->u.stream.net_index = dst->net_seq_index;
302 break;
303 case CONSUMER_DST_LOCAL:
304 /* Add stream file name to stream path */
305 strncat(msg->u.stream.path_name, "/", sizeof(msg->u.stream.path_name));
306 strncat(msg->u.stream.path_name, msg->u.stream.name,
307 sizeof(msg->u.stream.path_name));
308 msg->u.stream.path_name[sizeof(msg->u.stream.path_name) - 1] = '\0';
309 /* Indicate that the stream is NOT network */
310 msg->u.stream.net_index = -1;
311 break;
312 default:
313 ERR("Consumer unknown output type (%d)", dst->type);
314 ret = -1;
315 goto error;
316 }
317
318 /* Send on socket */
319 ret = lttcomm_send_unix_sock(sock, msg,
320 sizeof(struct lttcomm_consumer_msg));
321 if (ret < 0) {
322 PERROR("send consumer stream");
323 goto error;
324 }
325
326 ret = consumer_send_fds(sock, fds, nb_fd);
327 if (ret < 0) {
328 goto error;
329 }
330
331error:
332 return ret;
333}
This page took 0.053684 seconds and 4 git commands to generate.