vod_status_t write_buffer_queue_flush(write_buffer_queue_t* queue) { buffer_header_t* cur_buffer; vod_status_t rc; while (!is_list_empty(&queue->buffers)) { cur_buffer = (buffer_header_t*)queue->buffers.next; remove_entry_list(&cur_buffer->link); if (cur_buffer->cur_pos <= cur_buffer->start_pos) { continue; } rc = queue->write_callback(queue->write_context, cur_buffer->start_pos, cur_buffer->cur_pos - cur_buffer->start_pos); if (rc != VOD_OK) { vod_log_debug1(VOD_LOG_DEBUG_LEVEL, queue->request_context->log, 0, "write_buffer_queue_flush: write_callback failed %i", rc); return rc; } // no reason to reuse the buffer here } return VOD_OK; }
vod_status_t write_buffer_queue_send(write_buffer_queue_t* queue, off_t max_offset) { buffer_header_t* cur_buffer; vod_status_t rc; while (!is_list_empty(&queue->buffers)) { cur_buffer = (buffer_header_t*)queue->buffers.next; if (cur_buffer->cur_pos <= cur_buffer->start_pos) { break; } if (cur_buffer->end_offset > max_offset) { break; } remove_entry_list(&cur_buffer->link); if (cur_buffer == queue->cur_write_buffer) { queue->cur_write_buffer = NULL; } rc = queue->write_callback(queue->write_context, cur_buffer->start_pos, cur_buffer->cur_pos - cur_buffer->start_pos); if (rc != VOD_OK) { vod_log_debug1(VOD_LOG_DEBUG_LEVEL, queue->request_context->log, 0, "write_buffer_queue_send: write_callback failed %i", rc); return rc; } if (!queue->reuse_buffers) { cur_buffer->start_pos = NULL; } cur_buffer->cur_pos = cur_buffer->start_pos; insert_tail_list(&queue->buffers, &cur_buffer->link); } return VOD_OK; }
int print_lines(FILE* source, int inotify_fd, buffer_t* cur_buffer, long cur_buffer_offset, long skip_count) { z_stream strm; u_char inotify_buffer[INOTIFY_BUF_LEN]; u_char out[CHUNK_SIZE_COMP]; u_char in[CHUNK_SIZE_READ]; u_char* end_pos; u_char* cur_pos; int read_file = 0; ssize_t bytes_read; buffer_t* old_buffer; int rc; strm.avail_in = 0; strm.next_in = Z_NULL; for (;;) { // initialize inflate strm.zalloc = Z_NULL; strm.zfree = Z_NULL; strm.opaque = Z_NULL; rc = inflateInit2(&strm, 31); if (rc != Z_OK) { printf("inflateInit2 failed %d", rc); return 1; } do { // get an input buffer while (strm.avail_in == 0) { if (read_file) { // already processed all buffers in memory, read from file strm.avail_in = fread(in, 1, CHUNK_SIZE_READ, source); if (strm.avail_in < 0) { printf("fread failed %d", errno); return 1; } if (strm.avail_in == 0) { // nothing to read, wait until new data is available bytes_read = read(inotify_fd, inotify_buffer, INOTIFY_BUF_LEN); if (bytes_read <= 0) { printf("read inotify failed %d", errno); return 1; } } strm.next_in = in; continue; } if (cur_buffer_offset >= cur_buffer->size) { // finished handling current buffer, move to the next one if (cur_buffer->node.next == &buffer_queue) { if (!forever) { return 0; } read_file = 1; continue; } old_buffer = cur_buffer; cur_buffer = (buffer_t*)cur_buffer->node.next; cur_buffer_offset = 0; remove_entry_list(&old_buffer->node); free(old_buffer->data); free(old_buffer); } strm.next_in = cur_buffer->data + cur_buffer_offset; strm.avail_in = cur_buffer->size - cur_buffer_offset; cur_buffer_offset = cur_buffer->size; } do { // inflate as much as possible strm.avail_out = CHUNK_SIZE_COMP; strm.next_out = out; rc = inflate(&strm, Z_NO_FLUSH); switch (rc) { case Z_NEED_DICT: case Z_DATA_ERROR: case Z_MEM_ERROR: (void)inflateEnd(&strm); return 1; } // skip lines end_pos = out + CHUNK_SIZE_COMP - strm.avail_out; for (cur_pos = out; skip_count && cur_pos < end_pos; cur_pos++) { if (*cur_pos == '\n') { skip_count--; } } // write the remainder fwrite(cur_pos, end_pos - cur_pos, 1, stdout); } while (strm.avail_out == 0); // done when inflate says so } while (rc != Z_STREAM_END); (void)inflateEnd(&strm); } }