static ssize_t compress_iov_to_buffer(struct trace_record *target, const struct iovec *iov, int iovcnt) { if (NULL == iov) { errno = EFAULT; return -1; } if (iovcnt < 1) { return 0; } char *src_buf = iov[0].iov_base; size_t input_len = iov[0].iov_len; size_t compressed_length = 0; struct snappy_env env; int rc = snappy_init_env(&env); if (rc < 0) { goto finish; } if (iovcnt > 1) { /* TODO: Snappy should be able to accept an input IOV directly. Since this support is currently broken we use a workaround instead. */ input_len = total_iovec_len(iov, iovcnt); src_buf = malloc(input_len); if ((NULL == src_buf) || (copy_iov_to_buffer(src_buf, iov, iovcnt) != (ssize_t) input_len)) { rc = -errno; goto finish; } } if (input_len > 0) { /* Don't bother compressing trailing padding chars. Those will be re-inserted by the reader. */ input_len -= trace_r_count_chr_occurrences(src_buf + 1, input_len - 1, TRACE_UNUSED_SPACE_FILL_VALUE); rc = snappy_compress(&env, src_buf, input_len, (char *)target, &compressed_length); } finish: snappy_free_env(&env); if (src_buf != iov[0].iov_base) { free(src_buf); } if (0 != rc) { errno = -rc; ERR("Buffer compression failed with err", errno, strerror(errno)); return (ssize_t) -1; } TRACE_ASSERT(((ssize_t) compressed_length > 0) || (0 == input_len)); return (ssize_t) compressed_length; }
ssize_t internal_buf_write_compressed(struct trace_internal_buf *buf, const struct iovec *iov, int iovcnt) { const size_t max_size = snappy_max_compressed_length(total_iovec_len(iov, iovcnt)); const size_t max_recs = internal_buf_bytes_to_recs(max_size); const unsigned start_idx = internal_buf_alloc_space(buf, max_recs); if (INTERNAL_BUF_INVALID_INDEX == start_idx) { return -1; } const ssize_t compressed_len = compress_iov_to_buffer(buf->records + start_idx, iov, iovcnt); if (compressed_len < 0) { compactify_buffer(buf, start_idx, 0); return -1; } compactify_buffer(buf, start_idx, internal_buf_bytes_to_recs(compressed_len)); fill_compression_remainder_with_pattern(buf, compressed_len); return compressed_len; }
static int trace_dumper_write(struct trace_dumper_configuration_s *conf, struct trace_record_file *record_file, const struct iovec *iov, int iovcnt) { int expected_bytes = total_iovec_len(iov, iovcnt); int rc = 0; if (conf->record_file.fd >= 0) { rc = writev(record_file->fd, iov, iovcnt); if (rc != expected_bytes) { return -1; } record_file->records_written += expected_bytes / sizeof(struct trace_record); } if (conf->online) { int parser_rc = dump_iovector_to_parser(conf, &conf->parser, iov, iovcnt); if (parser_rc != 0) { return -1; } } return expected_bytes; }