X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=formats%2Flttng-live%2Flttng-live-comm.c;h=3970ac22ee6ed43fa33dae4664061cc478811836;hb=49a4acefd0905cd95253f91d3781c758999847c3;hp=7076f9c5edb723972f69ddeadfd66e2ecdabb1cb;hpb=af701dc48bc54cee796ee2e525a700689f9e8e73;p=babeltrace.git diff --git a/formats/lttng-live/lttng-live-comm.c b/formats/lttng-live/lttng-live-comm.c index 7076f9c5..3970ac22 100644 --- a/formats/lttng-live/lttng-live-comm.c +++ b/formats/lttng-live/lttng-live-comm.c @@ -33,6 +33,7 @@ #include #include #include +#include #include @@ -54,6 +55,8 @@ #include "lttng-live.h" #include "lttng-viewer-abi.h" +#define ACTIVE_POLL_DELAY 100 /* ms */ + /* * Memory allocation zeroed */ @@ -72,6 +75,38 @@ static int get_new_metadata(struct lttng_live_ctx *ctx, struct lttng_live_viewer_stream *viewer_stream, char **metadata_buf); +static +ssize_t lttng_live_recv(int fd, void *buf, size_t len) +{ + ssize_t ret; + size_t copied = 0, to_copy = len; + + do { + ret = recv(fd, buf + copied, to_copy, 0); + if (ret > 0) { + assert(ret <= to_copy); + copied += ret; + to_copy -= ret; + } + } while ((ret > 0 && to_copy > 0) + || (ret < 0 && errno == EINTR)); + if (ret > 0) + ret = copied; + /* ret = 0 means orderly shutdown, ret < 0 is error. */ + return ret; +} + +static +ssize_t lttng_live_send(int fd, const void *buf, size_t len) +{ + ssize_t ret; + + do { + ret = send(fd, buf, len, MSG_NOSIGNAL); + } while (ret < 0 && errno == EINTR); + return ret; +} + int lttng_live_connect_viewer(struct lttng_live_ctx *ctx) { struct hostent *host; @@ -124,9 +159,7 @@ int lttng_live_establish_connection(struct lttng_live_ctx *ctx) connect.minor = htobe32(LTTNG_LIVE_MINOR); connect.type = htobe32(LTTNG_VIEWER_CLIENT_COMMAND); - do { - ret_len = send(ctx->control_sock, &cmd, sizeof(cmd), 0); - } while (ret_len < 0 && errno == EINTR); + ret_len = lttng_live_send(ctx->control_sock, &cmd, sizeof(cmd)); if (ret_len < 0) { perror("[error] Error sending cmd"); ret = ret_len; @@ -134,9 +167,7 @@ int lttng_live_establish_connection(struct lttng_live_ctx *ctx) } assert(ret_len == sizeof(cmd)); - do { - ret_len = send(ctx->control_sock, &connect, sizeof(connect), 0); - } while (ret_len < 0 && errno == EINTR); + ret_len = lttng_live_send(ctx->control_sock, &connect, sizeof(connect)); if (ret_len < 0) { perror("[error] Error sending version"); ret = ret_len; @@ -144,9 +175,7 @@ int lttng_live_establish_connection(struct lttng_live_ctx *ctx) } assert(ret_len == sizeof(connect)); - do { - ret_len = recv(ctx->control_sock, &connect, sizeof(connect), 0); - } while (ret_len < 0 && errno == EINTR); + ret_len = lttng_live_recv(ctx->control_sock, &connect, sizeof(connect)); if (ret_len == 0) { fprintf(stderr, "[error] Remote side has closed connection\n"); ret = -1; @@ -251,9 +280,7 @@ int lttng_live_list_sessions(struct lttng_live_ctx *ctx, const char *path) cmd.data_size = 0; cmd.cmd_version = 0; - do { - ret_len = send(ctx->control_sock, &cmd, sizeof(cmd), 0); - } while (ret_len < 0 && errno == EINTR); + ret_len = lttng_live_send(ctx->control_sock, &cmd, sizeof(cmd)); if (ret_len < 0) { perror("[error] Error sending cmd"); ret = ret_len; @@ -261,9 +288,7 @@ int lttng_live_list_sessions(struct lttng_live_ctx *ctx, const char *path) } assert(ret_len == sizeof(cmd)); - do { - ret_len = recv(ctx->control_sock, &list, sizeof(list), 0); - } while (ret_len < 0 && errno == EINTR); + ret_len = lttng_live_recv(ctx->control_sock, &list, sizeof(list)); if (ret_len == 0) { fprintf(stderr, "[error] Remote side has closed connection\n"); ret = -1; @@ -278,9 +303,7 @@ int lttng_live_list_sessions(struct lttng_live_ctx *ctx, const char *path) sessions_count = be32toh(list.sessions_count); for (i = 0; i < sessions_count; i++) { - do { - ret_len = recv(ctx->control_sock, &lsession, sizeof(lsession), 0); - } while (ret_len < 0 && errno == EINTR); + ret_len = lttng_live_recv(ctx->control_sock, &lsession, sizeof(lsession)); if (ret_len == 0) { fprintf(stderr, "[error] Remote side has closed connection\n"); ret = -1; @@ -386,9 +409,7 @@ int lttng_live_attach_session(struct lttng_live_ctx *ctx, uint64_t id) // rq.seek = htobe32(LTTNG_VIEWER_SEEK_BEGINNING); rq.seek = htobe32(LTTNG_VIEWER_SEEK_LAST); - do { - ret_len = send(ctx->control_sock, &cmd, sizeof(cmd), 0); - } while (ret_len < 0 && errno == EINTR); + ret_len = lttng_live_send(ctx->control_sock, &cmd, sizeof(cmd)); if (ret_len < 0) { perror("[error] Error sending cmd"); ret = ret_len; @@ -396,9 +417,7 @@ int lttng_live_attach_session(struct lttng_live_ctx *ctx, uint64_t id) } assert(ret_len == sizeof(cmd)); - do { - ret_len = send(ctx->control_sock, &rq, sizeof(rq), 0); - } while (ret_len < 0 && errno == EINTR); + ret_len = lttng_live_send(ctx->control_sock, &rq, sizeof(rq)); if (ret_len < 0) { perror("[error] Error sending attach request"); ret = ret_len; @@ -406,9 +425,7 @@ int lttng_live_attach_session(struct lttng_live_ctx *ctx, uint64_t id) } assert(ret_len == sizeof(rq)); - do { - ret_len = recv(ctx->control_sock, &rp, sizeof(rp), 0); - } while (ret_len < 0 && errno == EINTR); + ret_len = lttng_live_recv(ctx->control_sock, &rp, sizeof(rp)); if (ret_len == 0) { fprintf(stderr, "[error] Remote side has closed connection\n"); ret = -1; @@ -465,9 +482,7 @@ int lttng_live_attach_session(struct lttng_live_ctx *ctx, uint64_t id) ctx->session->streams = g_new0(struct lttng_live_viewer_stream, ctx->session->stream_count); for (i = 0; i < be32toh(rp.streams_count); i++) { - do { - ret_len = recv(ctx->control_sock, &stream, sizeof(stream), 0); - } while (ret_len < 0 && errno == EINTR); + ret_len = lttng_live_recv(ctx->control_sock, &stream, sizeof(stream)); if (ret_len == 0) { fprintf(stderr, "[error] Remote side has closed connection\n"); ret = -1; @@ -546,6 +561,45 @@ end: return ret; } +static +int append_metadata(struct lttng_live_ctx *ctx, + struct lttng_live_viewer_stream *viewer_stream) +{ + int ret; + struct lttng_live_viewer_stream *metadata; + char *metadata_buf = NULL; + + printf_verbose("get_next_index: new metadata needed\n"); + ret = get_new_metadata(ctx, viewer_stream, &metadata_buf); + if (ret < 0) { + free(metadata_buf); + goto error; + } + + metadata = viewer_stream->ctf_trace->metadata_stream; + metadata->ctf_trace->metadata_fp = + babeltrace_fmemopen(metadata_buf, + metadata->metadata_len, "rb"); + if (!metadata->ctf_trace->metadata_fp) { + perror("Metadata fmemopen"); + free(metadata_buf); + ret = -1; + goto error; + } + ret = ctf_append_trace_metadata( + viewer_stream->ctf_trace->handle->td, + metadata->ctf_trace->metadata_fp); + /* We accept empty metadata packets */ + if (ret != 0 && ret != -ENOENT) { + fprintf(stderr, "[error] Appending metadata\n"); + goto error; + } + ret = 0; + +error: + return ret; +} + static int get_data_packet(struct lttng_live_ctx *ctx, struct ctf_stream_pos *pos, @@ -558,6 +612,7 @@ int get_data_packet(struct lttng_live_ctx *ctx, ssize_t ret_len; int ret; +retry: cmd.cmd = htobe32(LTTNG_VIEWER_GET_PACKET); cmd.data_size = sizeof(rq); cmd.cmd_version = 0; @@ -568,9 +623,7 @@ int get_data_packet(struct lttng_live_ctx *ctx, rq.offset = offset; rq.len = htobe32(len); - do { - ret_len = send(ctx->control_sock, &cmd, sizeof(cmd), 0); - } while (ret_len < 0 && errno == EINTR); + ret_len = lttng_live_send(ctx->control_sock, &cmd, sizeof(cmd)); if (ret_len < 0) { perror("[error] Error sending cmd"); ret = ret_len; @@ -578,9 +631,7 @@ int get_data_packet(struct lttng_live_ctx *ctx, } assert(ret_len == sizeof(cmd)); - do { - ret_len = send(ctx->control_sock, &rq, sizeof(rq), 0); - } while (ret_len < 0 && errno == EINTR); + ret_len = lttng_live_send(ctx->control_sock, &rq, sizeof(rq)); if (ret_len < 0) { perror("[error] Error sending get_data_packet request"); ret = ret_len; @@ -588,9 +639,7 @@ int get_data_packet(struct lttng_live_ctx *ctx, } assert(ret_len == sizeof(rq)); - do { - ret_len = recv(ctx->control_sock, &rp, sizeof(rp), 0); - } while (ret_len < 0 && errno == EINTR); + ret_len = lttng_live_recv(ctx->control_sock, &rp, sizeof(rp)); if (ret_len == 0) { fprintf(stderr, "[error] Remote side has closed connection\n"); ret = -1; @@ -624,15 +673,21 @@ int get_data_packet(struct lttng_live_ctx *ctx, case LTTNG_VIEWER_GET_PACKET_ERR: if (rp.flags & LTTNG_VIEWER_FLAG_NEW_METADATA) { printf_verbose("get_data_packet: new metadata needed\n"); - ret = 0; - goto end; + ret = append_metadata(ctx, stream); + if (ret) + goto error; } if (rp.flags & LTTNG_VIEWER_FLAG_NEW_STREAM) { + printf_verbose("get_data_packet: new streams needed\n"); ret = ask_new_streams(ctx); if (ret < 0) goto error; - g_hash_table_foreach(ctx->session->ctf_traces, add_traces, - ctx->bt_ctx); + g_hash_table_foreach(ctx->session->ctf_traces, + add_traces, ctx->bt_ctx); + } + if (rp.flags & (LTTNG_VIEWER_FLAG_NEW_METADATA + | LTTNG_VIEWER_FLAG_NEW_STREAM)) { + goto retry; } fprintf(stderr, "[error] get_data_packet: error\n"); ret = -1; @@ -681,11 +736,8 @@ int get_data_packet(struct lttng_live_ctx *ctx, stream->mmap_size); } - do { - ret_len = recv(ctx->control_sock, - mmap_align_addr(pos->base_mma), len, - MSG_WAITALL); - } while (ret_len < 0 && errno == EINTR); + ret_len = lttng_live_recv(ctx->control_sock, + mmap_align_addr(pos->base_mma), len); if (ret_len == 0) { fprintf(stderr, "[error] Remote side has closed connection\n"); ret = -1; @@ -697,7 +749,7 @@ int get_data_packet(struct lttng_live_ctx *ctx, goto error; } assert(ret_len == len); - + ret = 0; end: error: return ret; @@ -720,9 +772,7 @@ int get_one_metadata_packet(struct lttng_live_ctx *ctx, cmd.data_size = sizeof(rq); cmd.cmd_version = 0; - do { - ret_len = send(ctx->control_sock, &cmd, sizeof(cmd), 0); - } while (ret_len < 0 && errno == EINTR); + ret_len = lttng_live_send(ctx->control_sock, &cmd, sizeof(cmd)); if (ret_len < 0) { perror("[error] Error sending cmd"); ret = ret_len; @@ -730,9 +780,7 @@ int get_one_metadata_packet(struct lttng_live_ctx *ctx, } assert(ret_len == sizeof(cmd)); - do { - ret_len = send(ctx->control_sock, &rq, sizeof(rq), 0); - } while (ret_len < 0 && errno == EINTR); + ret_len = lttng_live_send(ctx->control_sock, &rq, sizeof(rq)); if (ret_len < 0) { perror("[error] Error sending get_metadata request"); ret = ret_len; @@ -740,9 +788,7 @@ int get_one_metadata_packet(struct lttng_live_ctx *ctx, } assert(ret_len == sizeof(rq)); - do { - ret_len = recv(ctx->control_sock, &rp, sizeof(rp), 0); - } while (ret_len < 0 && errno == EINTR); + ret_len = lttng_live_recv(ctx->control_sock, &rp, sizeof(rp)); if (ret_len == 0) { fprintf(stderr, "[error] Remote side has closed connection\n"); ret = -1; @@ -786,9 +832,7 @@ int get_one_metadata_packet(struct lttng_live_ctx *ctx, ret = -1; goto error; } - do { - ret_len = recv(ctx->control_sock, data, len, MSG_WAITALL); - } while (ret_len < 0 && errno == EINTR); + ret_len = lttng_live_recv(ctx->control_sock, data, len); if (ret_len == 0) { fprintf(stderr, "[error] Remote side has closed connection\n"); ret = -1; @@ -834,9 +878,14 @@ int get_new_metadata(struct lttng_live_ctx *ctx, { int ret = 0; struct lttng_live_viewer_stream *metadata_stream; - size_t size; + size_t size, len_read = 0;; metadata_stream = viewer_stream->ctf_trace->metadata_stream; + if (!metadata_stream) { + fprintf(stderr, "[error] No metadata stream\n"); + ret = -1; + goto error; + } metadata_stream->metadata_len = 0; ret = open_metadata_fp_write(metadata_stream, metadata_buf, &size); if (ret < 0) { @@ -850,9 +899,16 @@ int get_new_metadata(struct lttng_live_ctx *ctx, * negative value on error. */ ret = get_one_metadata_packet(ctx, metadata_stream); - } while (ret > 0); + if (ret > 0) { + len_read += ret; + } + if (!len_read) { + (void) poll(NULL, 0, ACTIVE_POLL_DELAY); + } + } while (ret > 0 || !len_read); - fclose(metadata_stream->metadata_fp_write); + if (fclose(metadata_stream->metadata_fp_write)) + perror("fclose"); metadata_stream->metadata_fp_write = NULL; error: @@ -883,9 +939,7 @@ int get_next_index(struct lttng_live_ctx *ctx, rq.stream_id = htobe64(viewer_stream->id); retry: - do { - ret_len = send(ctx->control_sock, &cmd, sizeof(cmd), 0); - } while (ret_len < 0 && errno == EINTR); + ret_len = lttng_live_send(ctx->control_sock, &cmd, sizeof(cmd)); if (ret_len < 0) { perror("[error] Error sending cmd"); ret = ret_len; @@ -893,9 +947,7 @@ retry: } assert(ret_len == sizeof(cmd)); - do { - ret_len = send(ctx->control_sock, &rq, sizeof(rq), 0); - } while (ret_len < 0 && errno == EINTR); + ret_len = lttng_live_send(ctx->control_sock, &rq, sizeof(rq)); if (ret_len < 0) { perror("[error] Error sending get_next_index request"); ret = ret_len; @@ -903,9 +955,7 @@ retry: } assert(ret_len == sizeof(rq)); - do { - ret_len = recv(ctx->control_sock, &rp, sizeof(rp), 0); - } while (ret_len < 0 && errno == EINTR); + ret_len = lttng_live_recv(ctx->control_sock, &rp, sizeof(rp)); if (ret_len == 0) { fprintf(stderr, "[error] Remote side has closed connection\n"); ret = -1; @@ -937,35 +987,21 @@ retry: index->events_discarded = be64toh(rp.events_discarded); if (rp.flags & LTTNG_VIEWER_FLAG_NEW_METADATA) { - struct lttng_live_viewer_stream *metadata; - char *metadata_buf = NULL; - - printf_verbose("get_next_index: new metadata needed\n"); - ret = get_new_metadata(ctx, viewer_stream, &metadata_buf); - if (ret < 0) { - goto error; - } - metadata = viewer_stream->ctf_trace->metadata_stream; - metadata->ctf_trace->metadata_fp = - babeltrace_fmemopen(metadata_buf, - metadata->metadata_len, "rb"); - if (!metadata->ctf_trace->metadata_fp) { - perror("Metadata fmemopen"); - ret = -1; + ret = append_metadata(ctx, viewer_stream); + if (ret) goto error; - } } if (rp.flags & LTTNG_VIEWER_FLAG_NEW_STREAM) { ret = ask_new_streams(ctx); if (ret < 0) goto error; - g_hash_table_foreach(ctx->session->ctf_traces, add_traces, - ctx->bt_ctx); + g_hash_table_foreach(ctx->session->ctf_traces, + add_traces, ctx->bt_ctx); } break; case LTTNG_VIEWER_INDEX_RETRY: printf_verbose("get_next_index: retry\n"); - sleep(1); + (void) poll(NULL, 0, ACTIVE_POLL_DELAY); goto retry; case LTTNG_VIEWER_INDEX_HUP: printf_verbose("get_next_index: stream hung up\n"); @@ -1134,9 +1170,7 @@ int lttng_live_create_viewer_session(struct lttng_live_ctx *ctx) cmd.data_size = 0; cmd.cmd_version = 0; - do { - ret_len = send(ctx->control_sock, &cmd, sizeof(cmd), 0); - } while (ret_len < 0 && errno == EINTR); + ret_len = lttng_live_send(ctx->control_sock, &cmd, sizeof(cmd)); if (ret_len < 0) { perror("[error] Error sending cmd"); ret = ret_len; @@ -1144,9 +1178,7 @@ int lttng_live_create_viewer_session(struct lttng_live_ctx *ctx) } assert(ret_len == sizeof(cmd)); - do { - ret_len = recv(ctx->control_sock, &resp, sizeof(resp), 0); - } while (ret_len < 0 && errno == EINTR); + ret_len = lttng_live_recv(ctx->control_sock, &resp, sizeof(resp)); if (ret_len == 0) { fprintf(stderr, "[error] Remote side has closed connection\n"); ret = -1; @@ -1298,9 +1330,7 @@ int lttng_live_get_new_streams(struct lttng_live_ctx *ctx, uint64_t id) memset(&rq, 0, sizeof(rq)); rq.session_id = htobe64(id); - do { - ret_len = send(ctx->control_sock, &cmd, sizeof(cmd), 0); - } while (ret_len < 0 && errno == EINTR); + ret_len = lttng_live_send(ctx->control_sock, &cmd, sizeof(cmd)); if (ret_len < 0) { perror("[error] Error sending cmd"); ret = ret_len; @@ -1308,9 +1338,7 @@ int lttng_live_get_new_streams(struct lttng_live_ctx *ctx, uint64_t id) } assert(ret_len == sizeof(cmd)); - do { - ret_len = send(ctx->control_sock, &rq, sizeof(rq), 0); - } while (ret_len < 0 && errno == EINTR); + ret_len = lttng_live_send(ctx->control_sock, &rq, sizeof(rq)); if (ret_len < 0) { perror("[error] Error sending get_new_streams request"); ret = ret_len; @@ -1318,9 +1346,7 @@ int lttng_live_get_new_streams(struct lttng_live_ctx *ctx, uint64_t id) } assert(ret_len == sizeof(rq)); - do { - ret_len = recv(ctx->control_sock, &rp, sizeof(rp), 0); - } while (ret_len < 0 && errno == EINTR); + ret_len = lttng_live_recv(ctx->control_sock, &rp, sizeof(rp)); if (ret_len == 0) { fprintf(stderr, "[error] Remote side has closed connection\n"); ret = -1; @@ -1369,9 +1395,7 @@ int lttng_live_get_new_streams(struct lttng_live_ctx *ctx, uint64_t id) ctx->session->streams = g_new0(struct lttng_live_viewer_stream, ctx->session->stream_count); for (i = 0; i < stream_count; i++) { - do { - ret_len = recv(ctx->control_sock, &stream, sizeof(stream), 0); - } while (ret_len < 0 && errno == EINTR); + ret_len = lttng_live_recv(ctx->control_sock, &stream, sizeof(stream)); if (ret_len == 0) { fprintf(stderr, "[error] Remote side has closed connection\n"); ret = -1; @@ -1443,8 +1467,9 @@ void lttng_live_read(struct lttng_live_ctx *ctx) sout = container_of(td_write, struct ctf_text_stream_pos, trace_descriptor); - if (!sout->parent.event_cb) + if (!sout->parent.event_cb) { goto end_free; + } ret = lttng_live_create_viewer_session(ctx); if (ret < 0) { @@ -1471,11 +1496,16 @@ void lttng_live_read(struct lttng_live_ctx *ctx) int flags; while (!ctx->session->stream_count) { - if (ctx->session_ids->len == 0) + if (ctx->session_ids->len == 0) { goto end_free; + } ret = ask_new_streams(ctx); - if (ret < 0) + if (ret < 0) { goto end_free; + } + if (!ctx->session->stream_count) { + (void) poll(NULL, 0, ACTIVE_POLL_DELAY); + } } g_hash_table_foreach(ctx->session->ctf_traces, add_traces,