Commit | Line | Data |
---|---|---|
1b368955 JD |
1 | /* |
2 | * Copyright (c) - 2013 Julien Desfossez <jdesfossez@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 as published by as | |
6 | * published by the Free 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., 51 | |
15 | * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
16 | */ | |
17 | ||
18 | #define _GNU_SOURCE | |
19 | #include <assert.h> | |
20 | #include <errno.h> | |
21 | #include <stdio.h> | |
22 | #include <stdlib.h> | |
23 | #include <string.h> | |
24 | #include <unistd.h> | |
25 | #include <time.h> | |
26 | #include <sys/types.h> | |
27 | #include <inttypes.h> | |
28 | #include <stdlib.h> | |
29 | #include <sys/socket.h> | |
30 | #include <netinet/in.h> | |
31 | #include <netdb.h> | |
32 | #include <fcntl.h> | |
33 | #include <sys/mman.h> | |
34 | #include <sys/stat.h> | |
35 | ||
36 | #include <tap/tap.h> | |
37 | #include <lttng/lttng.h> | |
38 | ||
39 | #include <urcu/list.h> | |
40 | #include <bin/lttng-sessiond/session.h> | |
41 | #include <common/common.h> | |
42 | ||
2f8f53af | 43 | #include <bin/lttng-relayd/lttng-viewer-abi.h> |
50adc264 | 44 | #include <common/index/ctf-index.h> |
1b368955 | 45 | |
f263b7fd JD |
46 | #include <common/compat/endian.h> |
47 | ||
1b368955 JD |
48 | #define SESSION1 "test1" |
49 | #define RELAYD_URL "net://localhost" | |
50 | #define LIVE_TIMER 2000000 | |
51 | ||
52 | /* Number of TAP tests in this file */ | |
25b50f8f | 53 | #define NUM_TESTS 8 |
1b368955 JD |
54 | #define mmap_size 524288 |
55 | ||
56 | int ust_consumerd32_fd; | |
57 | int ust_consumerd64_fd; | |
58 | ||
59 | static int control_sock; | |
60 | struct live_session *session; | |
61 | ||
62 | static int first_packet_offset; | |
63 | static int first_packet_len; | |
b185faf7 | 64 | static int first_packet_stream_id = -1; |
1b368955 JD |
65 | |
66 | struct viewer_stream { | |
67 | uint64_t id; | |
68 | uint64_t ctf_trace_id; | |
69 | void *mmap_base; | |
70 | int fd; | |
71 | int metadata_flag; | |
72 | int first_read; | |
73 | char path[PATH_MAX]; | |
74 | }; | |
75 | ||
76 | struct live_session { | |
77 | struct viewer_stream *streams; | |
78 | uint64_t live_timer_interval; | |
79 | uint64_t stream_count; | |
80 | }; | |
81 | ||
10236918 MD |
82 | static |
83 | ssize_t lttng_live_recv(int fd, void *buf, size_t len) | |
84 | { | |
85 | ssize_t ret; | |
86 | size_t copied = 0, to_copy = len; | |
87 | ||
88 | do { | |
89 | ret = recv(fd, buf + copied, to_copy, 0); | |
90 | if (ret > 0) { | |
91 | assert(ret <= to_copy); | |
92 | copied += ret; | |
93 | to_copy -= ret; | |
94 | } | |
95 | } while ((ret > 0 && to_copy > 0) | |
96 | || (ret < 0 && errno == EINTR)); | |
97 | if (ret > 0) | |
98 | ret = copied; | |
99 | /* ret = 0 means orderly shutdown, ret < 0 is error. */ | |
100 | return ret; | |
101 | } | |
102 | ||
103 | static | |
104 | ssize_t lttng_live_send(int fd, const void *buf, size_t len) | |
105 | { | |
106 | ssize_t ret; | |
107 | ||
108 | do { | |
109 | ret = send(fd, buf, len, MSG_NOSIGNAL); | |
110 | } while (ret < 0 && errno == EINTR); | |
111 | return ret; | |
112 | } | |
113 | ||
1b368955 JD |
114 | static |
115 | int connect_viewer(char *hostname) | |
116 | { | |
117 | struct hostent *host; | |
118 | struct sockaddr_in server_addr; | |
119 | int ret; | |
120 | ||
121 | host = gethostbyname(hostname); | |
122 | if (!host) { | |
123 | ret = -1; | |
124 | goto end; | |
125 | } | |
126 | ||
127 | if ((control_sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { | |
6f04ed72 | 128 | PERROR("Socket"); |
1b368955 JD |
129 | ret = -1; |
130 | goto end; | |
131 | } | |
132 | ||
133 | server_addr.sin_family = AF_INET; | |
134 | server_addr.sin_port = htons(5344); | |
135 | server_addr.sin_addr = *((struct in_addr *) host->h_addr); | |
136 | bzero(&(server_addr.sin_zero), 8); | |
137 | ||
138 | if (connect(control_sock, (struct sockaddr *) &server_addr, | |
139 | sizeof(struct sockaddr)) == -1) { | |
6f04ed72 | 140 | PERROR("Connect"); |
1b368955 JD |
141 | ret = -1; |
142 | goto end; | |
143 | } | |
144 | ||
145 | server_addr.sin_family = AF_INET; | |
146 | server_addr.sin_port = htons(5345); | |
147 | server_addr.sin_addr = *((struct in_addr *) host->h_addr); | |
148 | bzero(&(server_addr.sin_zero), 8); | |
149 | ||
150 | ret = 0; | |
151 | ||
152 | end: | |
153 | return ret; | |
154 | } | |
155 | ||
156 | int establish_connection(void) | |
157 | { | |
158 | struct lttng_viewer_cmd cmd; | |
159 | struct lttng_viewer_connect connect; | |
10236918 | 160 | ssize_t ret_len; |
1b368955 | 161 | |
c4e361a4 | 162 | cmd.cmd = htobe32(LTTNG_VIEWER_CONNECT); |
1b368955 JD |
163 | cmd.data_size = sizeof(connect); |
164 | cmd.cmd_version = 0; | |
165 | ||
dcf5c25e | 166 | memset(&connect, 0, sizeof(connect)); |
1b368955 JD |
167 | connect.major = htobe32(VERSION_MAJOR); |
168 | connect.minor = htobe32(VERSION_MINOR); | |
c4e361a4 | 169 | connect.type = htobe32(LTTNG_VIEWER_CLIENT_COMMAND); |
1b368955 | 170 | |
10236918 MD |
171 | ret_len = lttng_live_send(control_sock, &cmd, sizeof(cmd)); |
172 | if (ret_len < 0) { | |
b185faf7 | 173 | diag("Error sending cmd"); |
1b368955 JD |
174 | goto error; |
175 | } | |
10236918 MD |
176 | ret_len = lttng_live_send(control_sock, &connect, sizeof(connect)); |
177 | if (ret_len < 0) { | |
b185faf7 | 178 | diag("Error sending version"); |
1b368955 JD |
179 | goto error; |
180 | } | |
181 | ||
10236918 MD |
182 | ret_len = lttng_live_recv(control_sock, &connect, sizeof(connect)); |
183 | if (ret_len == 0) { | |
b185faf7 | 184 | diag("[error] Remote side has closed connection"); |
10236918 MD |
185 | goto error; |
186 | } | |
187 | if (ret_len < 0) { | |
b185faf7 | 188 | diag("Error receiving version"); |
1b368955 JD |
189 | goto error; |
190 | } | |
10236918 | 191 | return 0; |
1b368955 JD |
192 | |
193 | error: | |
10236918 | 194 | return -1; |
1b368955 JD |
195 | } |
196 | ||
197 | /* | |
198 | * Returns the number of sessions, should be 1 during the unit test. | |
199 | */ | |
b185faf7 | 200 | int list_sessions(uint64_t *session_id) |
1b368955 JD |
201 | { |
202 | struct lttng_viewer_cmd cmd; | |
203 | struct lttng_viewer_list_sessions list; | |
204 | struct lttng_viewer_session lsession; | |
10236918 MD |
205 | int i; |
206 | ssize_t ret_len; | |
1b368955 JD |
207 | int first_session = 0; |
208 | ||
c4e361a4 | 209 | cmd.cmd = htobe32(LTTNG_VIEWER_LIST_SESSIONS); |
1b368955 JD |
210 | cmd.data_size = 0; |
211 | cmd.cmd_version = 0; | |
212 | ||
10236918 MD |
213 | ret_len = lttng_live_send(control_sock, &cmd, sizeof(cmd)); |
214 | if (ret_len < 0) { | |
b185faf7 | 215 | diag("Error sending cmd"); |
1b368955 JD |
216 | goto error; |
217 | } | |
218 | ||
10236918 MD |
219 | ret_len = lttng_live_recv(control_sock, &list, sizeof(list)); |
220 | if (ret_len == 0) { | |
b185faf7 | 221 | diag("[error] Remote side has closed connection"); |
10236918 MD |
222 | goto error; |
223 | } | |
224 | if (ret_len < 0) { | |
b185faf7 | 225 | diag("Error receiving session list"); |
1b368955 JD |
226 | goto error; |
227 | } | |
228 | ||
229 | for (i = 0; i < be32toh(list.sessions_count); i++) { | |
10236918 MD |
230 | ret_len = lttng_live_recv(control_sock, &lsession, sizeof(lsession)); |
231 | if (ret_len < 0) { | |
b185faf7 | 232 | diag("Error receiving session"); |
1b368955 JD |
233 | goto error; |
234 | } | |
235 | if (lsession.streams > 0 && first_session <= 0) { | |
236 | first_session = be64toh(lsession.id); | |
237 | *session_id = first_session; | |
238 | } | |
239 | } | |
240 | ||
10236918 | 241 | return be32toh(list.sessions_count); |
1b368955 JD |
242 | |
243 | error: | |
10236918 | 244 | return -1; |
1b368955 JD |
245 | } |
246 | ||
10236918 | 247 | int create_viewer_session(void) |
25b50f8f JD |
248 | { |
249 | struct lttng_viewer_cmd cmd; | |
250 | struct lttng_viewer_create_session_response resp; | |
25b50f8f JD |
251 | ssize_t ret_len; |
252 | ||
253 | cmd.cmd = htobe32(LTTNG_VIEWER_CREATE_SESSION); | |
254 | cmd.data_size = 0; | |
255 | cmd.cmd_version = 0; | |
256 | ||
10236918 | 257 | ret_len = lttng_live_send(control_sock, &cmd, sizeof(cmd)); |
25b50f8f | 258 | if (ret_len < 0) { |
b185faf7 | 259 | diag("[error] Error sending cmd"); |
25b50f8f JD |
260 | goto error; |
261 | } | |
262 | assert(ret_len == sizeof(cmd)); | |
263 | ||
10236918 MD |
264 | ret_len = lttng_live_recv(control_sock, &resp, sizeof(resp)); |
265 | if (ret_len == 0) { | |
b185faf7 | 266 | diag("[error] Remote side has closed connection"); |
10236918 MD |
267 | goto error; |
268 | } | |
25b50f8f | 269 | if (ret_len < 0) { |
b185faf7 | 270 | diag("[error] Error receiving create session reply"); |
25b50f8f JD |
271 | goto error; |
272 | } | |
273 | assert(ret_len == sizeof(resp)); | |
274 | ||
275 | if (be32toh(resp.status) != LTTNG_VIEWER_CREATE_SESSION_OK) { | |
b185faf7 | 276 | diag("[error] Error creating viewer session"); |
25b50f8f JD |
277 | goto error; |
278 | } | |
10236918 | 279 | return 0; |
25b50f8f JD |
280 | |
281 | error: | |
10236918 | 282 | return -1; |
25b50f8f JD |
283 | } |
284 | ||
b185faf7 | 285 | int attach_session(uint64_t id) |
1b368955 JD |
286 | { |
287 | struct lttng_viewer_cmd cmd; | |
288 | struct lttng_viewer_attach_session_request rq; | |
289 | struct lttng_viewer_attach_session_response rp; | |
290 | struct lttng_viewer_stream stream; | |
10236918 MD |
291 | int i; |
292 | ssize_t ret_len; | |
1b368955 JD |
293 | |
294 | session = zmalloc(sizeof(struct live_session)); | |
295 | if (!session) { | |
1b368955 JD |
296 | goto error; |
297 | } | |
298 | ||
c4e361a4 | 299 | cmd.cmd = htobe32(LTTNG_VIEWER_ATTACH_SESSION); |
1b368955 JD |
300 | cmd.data_size = sizeof(rq); |
301 | cmd.cmd_version = 0; | |
302 | ||
dcf5c25e | 303 | memset(&rq, 0, sizeof(rq)); |
1b368955 | 304 | rq.session_id = htobe64(id); |
c4e361a4 | 305 | rq.seek = htobe32(LTTNG_VIEWER_SEEK_BEGINNING); |
1b368955 | 306 | |
10236918 MD |
307 | ret_len = lttng_live_send(control_sock, &cmd, sizeof(cmd)); |
308 | if (ret_len < 0) { | |
b185faf7 | 309 | diag("Error sending cmd LTTNG_VIEWER_ATTACH_SESSION"); |
1b368955 JD |
310 | goto error; |
311 | } | |
10236918 MD |
312 | ret_len = lttng_live_send(control_sock, &rq, sizeof(rq)); |
313 | if (ret_len < 0) { | |
b185faf7 | 314 | diag("Error sending attach request"); |
1b368955 JD |
315 | goto error; |
316 | } | |
317 | ||
10236918 MD |
318 | ret_len = lttng_live_recv(control_sock, &rp, sizeof(rp)); |
319 | if (ret_len == 0) { | |
b185faf7 | 320 | diag("[error] Remote side has closed connection"); |
10236918 MD |
321 | goto error; |
322 | } | |
323 | if (ret_len < 0) { | |
b185faf7 | 324 | diag("Error receiving attach response"); |
1b368955 JD |
325 | goto error; |
326 | } | |
c4e361a4 | 327 | if (be32toh(rp.status) != LTTNG_VIEWER_ATTACH_OK) { |
10236918 | 328 | goto error; |
1b368955 JD |
329 | } |
330 | ||
331 | session->stream_count = be32toh(rp.streams_count); | |
b185faf7 JG |
332 | if (session->stream_count == 0) { |
333 | diag("Got session stream count == 0"); | |
334 | goto error; | |
335 | } | |
1b368955 JD |
336 | session->streams = zmalloc(session->stream_count * |
337 | sizeof(struct viewer_stream)); | |
338 | if (!session->streams) { | |
1b368955 JD |
339 | goto error; |
340 | } | |
341 | ||
342 | for (i = 0; i < be32toh(rp.streams_count); i++) { | |
10236918 MD |
343 | ret_len = lttng_live_recv(control_sock, &stream, sizeof(stream)); |
344 | if (ret_len == 0) { | |
b185faf7 | 345 | diag("[error] Remote side has closed connection"); |
10236918 MD |
346 | goto error; |
347 | } | |
348 | if (ret_len < 0) { | |
b185faf7 | 349 | diag("Error receiving stream"); |
1b368955 JD |
350 | goto error; |
351 | } | |
352 | session->streams[i].id = be64toh(stream.id); | |
353 | ||
354 | session->streams[i].ctf_trace_id = be64toh(stream.ctf_trace_id); | |
355 | session->streams[i].first_read = 1; | |
b185faf7 JG |
356 | session->streams[i].mmap_base = mmap(NULL, mmap_size, |
357 | PROT_READ | PROT_WRITE, | |
1b368955 JD |
358 | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); |
359 | if (session->streams[i].mmap_base == MAP_FAILED) { | |
b185faf7 | 360 | diag("mmap error"); |
1b368955 JD |
361 | goto error; |
362 | } | |
363 | ||
364 | if (be32toh(stream.metadata_flag)) { | |
365 | session->streams[i].metadata_flag = 1; | |
366 | } | |
367 | } | |
10236918 | 368 | return session->stream_count; |
1b368955 | 369 | |
1b368955 | 370 | error: |
10236918 | 371 | return -1; |
1b368955 JD |
372 | } |
373 | ||
374 | int get_metadata(void) | |
375 | { | |
376 | struct lttng_viewer_cmd cmd; | |
377 | struct lttng_viewer_get_metadata rq; | |
378 | struct lttng_viewer_metadata_packet rp; | |
10236918 | 379 | ssize_t ret_len; |
1b368955 JD |
380 | int ret; |
381 | uint64_t i; | |
382 | char *data = NULL; | |
383 | uint64_t len = 0; | |
384 | int metadata_stream_id = -1; | |
385 | ||
c4e361a4 | 386 | cmd.cmd = htobe32(LTTNG_VIEWER_GET_METADATA); |
1b368955 JD |
387 | cmd.data_size = sizeof(rq); |
388 | cmd.cmd_version = 0; | |
389 | ||
390 | for (i = 0; i < session->stream_count; i++) { | |
391 | if (session->streams[i].metadata_flag) { | |
392 | metadata_stream_id = i; | |
393 | break; | |
394 | } | |
395 | } | |
396 | ||
397 | if (metadata_stream_id < 0) { | |
b185faf7 | 398 | diag("No metadata stream found"); |
1b368955 JD |
399 | goto error; |
400 | } | |
401 | ||
402 | rq.stream_id = htobe64(session->streams[metadata_stream_id].id); | |
403 | ||
10236918 MD |
404 | ret_len = lttng_live_send(control_sock, &cmd, sizeof(cmd)); |
405 | if (ret_len < 0) { | |
b185faf7 | 406 | diag("Error sending cmd"); |
1b368955 JD |
407 | goto error; |
408 | } | |
10236918 MD |
409 | ret_len = lttng_live_send(control_sock, &rq, sizeof(rq)); |
410 | if (ret_len < 0) { | |
b185faf7 | 411 | diag("Error sending get_metadata request"); |
1b368955 JD |
412 | goto error; |
413 | } | |
10236918 MD |
414 | ret_len = lttng_live_recv(control_sock, &rp, sizeof(rp)); |
415 | if (ret_len == 0) { | |
b185faf7 | 416 | diag("[error] Remote side has closed connection"); |
10236918 MD |
417 | goto error; |
418 | } | |
419 | if (ret_len < 0) { | |
b185faf7 | 420 | diag("Error receiving metadata response"); |
1b368955 JD |
421 | goto error; |
422 | } | |
423 | switch (be32toh(rp.status)) { | |
b185faf7 JG |
424 | case LTTNG_VIEWER_METADATA_OK: |
425 | break; | |
426 | case LTTNG_VIEWER_NO_NEW_METADATA: | |
427 | diag("Got LTTNG_VIEWER_NO_NEW_METADATA:"); | |
428 | ret = 0; | |
429 | goto end; | |
430 | case LTTNG_VIEWER_METADATA_ERR: | |
431 | diag("Got LTTNG_VIEWER_METADATA_ERR:"); | |
432 | goto error; | |
433 | default: | |
434 | diag("Got unknown status during LTTNG_VIEWER_GET_METADATA"); | |
435 | goto error; | |
1b368955 JD |
436 | } |
437 | ||
438 | len = be64toh(rp.len); | |
439 | if (len <= 0) { | |
10236918 | 440 | goto error; |
1b368955 JD |
441 | } |
442 | ||
443 | data = zmalloc(len); | |
444 | if (!data) { | |
6f04ed72 | 445 | PERROR("relay data zmalloc"); |
1b368955 JD |
446 | goto error; |
447 | } | |
10236918 MD |
448 | ret_len = lttng_live_recv(control_sock, data, len); |
449 | if (ret_len == 0) { | |
b185faf7 | 450 | diag("[error] Remote side has closed connection"); |
10236918 MD |
451 | goto error_free_data; |
452 | } | |
453 | if (ret_len < 0) { | |
b185faf7 | 454 | diag("Error receiving trace packet"); |
10236918 | 455 | goto error_free_data; |
1b368955 JD |
456 | } |
457 | free(data); | |
10236918 | 458 | ret = len; |
1b368955 | 459 | end: |
1b368955 | 460 | return ret; |
10236918 MD |
461 | |
462 | error_free_data: | |
463 | free(data); | |
464 | error: | |
465 | return -1; | |
1b368955 JD |
466 | } |
467 | ||
468 | int get_next_index(void) | |
469 | { | |
470 | struct lttng_viewer_cmd cmd; | |
471 | struct lttng_viewer_get_next_index rq; | |
472 | struct lttng_viewer_index rp; | |
10236918 | 473 | ssize_t ret_len; |
1b368955 JD |
474 | int id; |
475 | ||
c4e361a4 | 476 | cmd.cmd = htobe32(LTTNG_VIEWER_GET_NEXT_INDEX); |
1b368955 JD |
477 | cmd.data_size = sizeof(rq); |
478 | cmd.cmd_version = 0; | |
479 | ||
480 | for (id = 0; id < session->stream_count; id++) { | |
481 | if (session->streams[id].metadata_flag) { | |
482 | continue; | |
483 | } | |
10236918 | 484 | memset(&rq, 0, sizeof(rq)); |
1b368955 JD |
485 | rq.stream_id = htobe64(session->streams[id].id); |
486 | ||
487 | retry: | |
10236918 MD |
488 | ret_len = lttng_live_send(control_sock, &cmd, sizeof(cmd)); |
489 | if (ret_len < 0) { | |
b185faf7 | 490 | diag("Error sending cmd"); |
1b368955 JD |
491 | goto error; |
492 | } | |
10236918 MD |
493 | ret_len = lttng_live_send(control_sock, &rq, sizeof(rq)); |
494 | if (ret_len < 0) { | |
b185faf7 | 495 | diag("Error sending get_next_index request"); |
1b368955 JD |
496 | goto error; |
497 | } | |
10236918 MD |
498 | ret_len = lttng_live_recv(control_sock, &rp, sizeof(rp)); |
499 | if (ret_len == 0) { | |
b185faf7 | 500 | diag("[error] Remote side has closed connection"); |
10236918 MD |
501 | goto error; |
502 | } | |
503 | if (ret_len < 0) { | |
b185faf7 | 504 | diag("Error receiving index response"); |
1b368955 JD |
505 | goto error; |
506 | } | |
507 | ||
508 | rp.flags = be32toh(rp.flags); | |
509 | ||
510 | switch (be32toh(rp.status)) { | |
b185faf7 JG |
511 | case LTTNG_VIEWER_INDEX_INACTIVE: |
512 | /* Skip this stream. */ | |
513 | diag("Got LTTNG_VIEWER_INDEX_INACTIVE"); | |
514 | continue; | |
515 | case LTTNG_VIEWER_INDEX_OK: | |
516 | break; | |
517 | case LTTNG_VIEWER_INDEX_RETRY: | |
518 | sleep(1); | |
519 | goto retry; | |
520 | case LTTNG_VIEWER_INDEX_HUP: | |
521 | diag("Got LTTNG_VIEWER_INDEX_HUP"); | |
522 | session->streams[id].id = -1ULL; | |
523 | session->streams[id].fd = -1; | |
524 | goto error; | |
525 | case LTTNG_VIEWER_INDEX_ERR: | |
526 | diag("Got LTTNG_VIEWER_INDEX_ERR"); | |
527 | goto error; | |
528 | default: | |
529 | diag("Unknown reply status during LTTNG_VIEWER_GET_NEXT_INDEX (%d)", be32toh(rp.status)); | |
530 | goto error; | |
1b368955 | 531 | } |
b185faf7 JG |
532 | if (first_packet_stream_id < 0) { |
533 | /* | |
534 | * Initialize the first packet stream id. That is, | |
535 | * the first active stream encoutered. | |
536 | */ | |
1b368955 JD |
537 | first_packet_offset = be64toh(rp.offset); |
538 | first_packet_len = be64toh(rp.packet_size) / CHAR_BIT; | |
539 | first_packet_stream_id = id; | |
b185faf7 JG |
540 | diag("Got first packet index with offset %d and len %d", |
541 | first_packet_offset, first_packet_len); | |
1b368955 JD |
542 | } |
543 | } | |
10236918 | 544 | return 0; |
1b368955 JD |
545 | |
546 | error: | |
10236918 | 547 | return -1; |
1b368955 JD |
548 | } |
549 | ||
550 | static | |
551 | int get_data_packet(int id, uint64_t offset, | |
552 | uint64_t len) | |
553 | { | |
554 | struct lttng_viewer_cmd cmd; | |
555 | struct lttng_viewer_get_packet rq; | |
556 | struct lttng_viewer_trace_packet rp; | |
10236918 | 557 | ssize_t ret_len; |
1b368955 | 558 | |
c4e361a4 | 559 | cmd.cmd = htobe32(LTTNG_VIEWER_GET_PACKET); |
1b368955 JD |
560 | cmd.data_size = sizeof(rq); |
561 | cmd.cmd_version = 0; | |
562 | ||
10236918 | 563 | memset(&rq, 0, sizeof(rq)); |
1b368955 JD |
564 | rq.stream_id = htobe64(session->streams[id].id); |
565 | /* Already in big endian. */ | |
566 | rq.offset = offset; | |
567 | rq.len = htobe32(len); | |
568 | ||
10236918 MD |
569 | ret_len = lttng_live_send(control_sock, &cmd, sizeof(cmd)); |
570 | if (ret_len < 0) { | |
b185faf7 | 571 | diag("Error sending cmd"); |
1b368955 JD |
572 | goto error; |
573 | } | |
10236918 MD |
574 | ret_len = lttng_live_send(control_sock, &rq, sizeof(rq)); |
575 | if (ret_len < 0) { | |
b185faf7 | 576 | diag("Error sending get_data_packet request"); |
1b368955 JD |
577 | goto error; |
578 | } | |
10236918 MD |
579 | ret_len = lttng_live_recv(control_sock, &rp, sizeof(rp)); |
580 | if (ret_len == 0) { | |
b185faf7 | 581 | diag("[error] Remote side has closed connection"); |
10236918 MD |
582 | goto error; |
583 | } | |
584 | if (ret_len < 0) { | |
b185faf7 | 585 | diag("Error receiving data response"); |
1b368955 JD |
586 | goto error; |
587 | } | |
588 | rp.flags = be32toh(rp.flags); | |
589 | ||
590 | switch (be32toh(rp.status)) { | |
c4e361a4 | 591 | case LTTNG_VIEWER_GET_PACKET_OK: |
10236918 | 592 | len = be32toh(rp.len); |
b185faf7 JG |
593 | if (len == 0) { |
594 | diag("Got LTTNG_VIEWER_GET_PACKET_OK, but len == 0"); | |
595 | goto error; | |
596 | } | |
1b368955 | 597 | break; |
c4e361a4 | 598 | case LTTNG_VIEWER_GET_PACKET_RETRY: |
b185faf7 | 599 | diag("Got LTTNG_VIEWER_GET_PACKET_RETRY:"); |
10236918 | 600 | goto error; |
c4e361a4 | 601 | case LTTNG_VIEWER_GET_PACKET_ERR: |
1b368955 | 602 | if (rp.flags & LTTNG_VIEWER_FLAG_NEW_METADATA) { |
b185faf7 | 603 | diag("Got LTTNG_VIEWER_GET_PACKET_ERR with NEW_METADATA flag"); |
1b368955 JD |
604 | goto end; |
605 | } | |
b185faf7 | 606 | diag("Got LTTNG_VIEWER_GET_PACKET_ERR:"); |
10236918 | 607 | goto error; |
1b368955 | 608 | default: |
b185faf7 | 609 | diag("Got unknown status code during LTTNG_VIEWER_GET_PACKET"); |
10236918 | 610 | goto error; |
1b368955 JD |
611 | } |
612 | ||
613 | if (len > mmap_size) { | |
b185faf7 | 614 | diag("mmap_size not big enough"); |
1b368955 JD |
615 | goto error; |
616 | } | |
617 | ||
10236918 MD |
618 | ret_len = lttng_live_recv(control_sock, session->streams[id].mmap_base, len); |
619 | if (ret_len == 0) { | |
b185faf7 | 620 | diag("[error] Remote side has closed connection"); |
10236918 MD |
621 | goto error; |
622 | } | |
623 | if (ret_len < 0) { | |
b185faf7 | 624 | diag("Error receiving trace packet"); |
1b368955 JD |
625 | goto error; |
626 | } | |
1b368955 | 627 | end: |
10236918 | 628 | return 0; |
1b368955 | 629 | error: |
10236918 | 630 | return -1; |
1b368955 JD |
631 | } |
632 | ||
633 | int main(int argc, char **argv) | |
634 | { | |
635 | int ret; | |
b185faf7 | 636 | uint64_t session_id; |
1b368955 JD |
637 | |
638 | plan_tests(NUM_TESTS); | |
639 | ||
640 | diag("Live unit tests"); | |
641 | ||
642 | ret = connect_viewer("localhost"); | |
643 | ok(ret == 0, "Connect viewer to relayd"); | |
644 | ||
645 | ret = establish_connection(); | |
646 | ok(ret == 0, "Established connection and version check with %d.%d", | |
647 | VERSION_MAJOR, VERSION_MINOR); | |
648 | ||
649 | ret = list_sessions(&session_id); | |
650 | ok(ret > 0, "List sessions : %d session(s)", ret); | |
651 | ||
25b50f8f JD |
652 | ret = create_viewer_session(); |
653 | ok(ret == 0, "Create viewer session"); | |
654 | ||
1b368955 | 655 | ret = attach_session(session_id); |
b185faf7 | 656 | ok(ret > 0, "Attach to session, %d stream(s) received", ret); |
1b368955 JD |
657 | |
658 | ret = get_metadata(); | |
659 | ok(ret > 0, "Get metadata, received %d bytes", ret); | |
660 | ||
661 | ret = get_next_index(); | |
662 | ok(ret == 0, "Get one index per stream"); | |
663 | ||
664 | ret = get_data_packet(first_packet_stream_id, first_packet_offset, | |
665 | first_packet_len); | |
10236918 | 666 | ok(ret == 0, |
1b368955 JD |
667 | "Get one data packet for stream %d, offset %d, len %d", |
668 | first_packet_stream_id, first_packet_offset, | |
669 | first_packet_len); | |
670 | ||
671 | return exit_status(); | |
672 | } |