Mercurial > dovecot > core-2.2
changeset 13534:0860ac364dec
Added rawlog i/ostreams.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Wed, 21 Sep 2011 15:57:57 +0300 |
parents | e0bee6c56a05 |
children | 87662d9ceff8 |
files | src/lib/Makefile.am src/lib/iostream-rawlog-private.h src/lib/iostream-rawlog.c src/lib/iostream-rawlog.h src/lib/istream-rawlog.c src/lib/istream-rawlog.h src/lib/ostream-rawlog.c src/lib/ostream-rawlog.h |
diffstat | 8 files changed, 332 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib/Makefile.am Wed Sep 21 15:54:06 2011 +0300 +++ b/src/lib/Makefile.am Wed Sep 21 15:57:57 2011 +0300 @@ -48,6 +48,7 @@ imem.c \ ipwd.c \ iostream.c \ + iostream-rawlog.c \ istream.c \ istream-base64-encoder.c \ istream-concat.c \ @@ -56,6 +57,7 @@ istream-file.c \ istream-limit.c \ istream-mmap.c \ + istream-rawlog.c \ istream-seekable.c \ istream-tee.c \ ioloop.c \ @@ -88,6 +90,7 @@ ostream.c \ ostream-file.c \ ostream-buffer.c \ + ostream-rawlog.c \ primes.c \ printf-format-fix.c \ process-title.c \ @@ -162,11 +165,14 @@ imem.h \ ipwd.h \ iostream-private.h \ + iostream-rawlog.h \ + iostream-rawlog-private.h \ istream.h \ istream-base64-encoder.h \ istream-concat.h \ istream-crlf.h \ istream-private.h \ + istream-rawlog.h \ istream-seekable.h \ istream-tee.h \ ioloop.h \ @@ -189,6 +195,7 @@ nfs-workarounds.h \ ostream.h \ ostream-private.h \ + ostream-rawlog.h \ primes.h \ printf-format-fix.h \ process-title.h \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib/iostream-rawlog-private.h Wed Sep 21 15:57:57 2011 +0300 @@ -0,0 +1,18 @@ +#ifndef IOSTREAM_RAWLOG_PRIVATE_H +#define IOSTREAM_RAWLOG_PRIVATE_H + +struct rawlog_iostream { + struct iostream_private *iostream; + + char *rawlog_path; + int rawlog_fd; + + bool autoclose_fd; + bool write_timestamp; +}; + +void iostream_rawlog_write(struct rawlog_iostream *rstream, + const unsigned char *data, size_t size); +void iostream_rawlog_close(struct rawlog_iostream *rstream); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib/iostream-rawlog.c Wed Sep 21 15:57:57 2011 +0300 @@ -0,0 +1,118 @@ +/* Copyright (c) 2011 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "hostpid.h" +#include "ioloop.h" +#include "write-full.h" +#include "istream.h" +#include "ostream.h" +#include "istream-rawlog.h" +#include "ostream-rawlog.h" +#include "iostream-private.h" +#include "iostream-rawlog-private.h" +#include "iostream-rawlog.h" + +#include <unistd.h> +#include <fcntl.h> + +static void +rawlog_write(struct rawlog_iostream *rstream, const void *data, size_t size) +{ + if (rstream->rawlog_fd == -1) + return; + + if (write_full(rstream->rawlog_fd, data, size) < 0) { + i_error("rawlog_istream.write(%s) failed: %m", + rstream->rawlog_path); + iostream_rawlog_close(rstream); + } +} + +static void rawlog_write_timestamp(struct rawlog_iostream *rstream) +{ + char buf[MAX_INT_STRLEN + 6 + 2]; + + i_snprintf(buf, sizeof(buf), "%lu.%06u ", + (unsigned long)ioloop_timeval.tv_sec, + (unsigned int)ioloop_timeval.tv_usec); + rawlog_write(rstream, buf, strlen(buf)); +} + +void iostream_rawlog_write(struct rawlog_iostream *rstream, + const unsigned char *data, size_t size) +{ + size_t i, start; + + i_assert(size > 0); + + io_loop_time_refresh(); + if (rstream->write_timestamp) + rawlog_write_timestamp(rstream); + + for (start = 0, i = 1; i < size; i++) { + if (data[i-1] == '\n') { + rawlog_write(rstream, data + start, i - start); + rawlog_write_timestamp(rstream); + start = i; + } + } + if (start != size) + rawlog_write(rstream, data + start, size - start); + rstream->write_timestamp = data[size-1] == '\n'; +} + +void iostream_rawlog_close(struct rawlog_iostream *rstream) +{ + if (rstream->autoclose_fd && rstream->rawlog_fd != -1) { + if (close(rstream->rawlog_fd) < 0) { + i_error("rawlog_istream.close(%s) failed: %m", + rstream->rawlog_path); + } + } + rstream->rawlog_fd = -1; + i_free_and_null(rstream->rawlog_path); +} + +int iostream_rawlog_create(const char *dir, struct istream **input, + struct ostream **output) +{ + static unsigned int counter = 0; + const char *in_path, *out_path; + struct istream *old_input; + struct ostream *old_output; + struct tm *tm; + char timestamp[50]; + int in_fd, out_fd; + + tm = localtime(&ioloop_time); + if (strftime(timestamp, sizeof(timestamp), "%Y%m%d-%H%M%S", tm) <= 0) + i_fatal("strftime() failed"); + + counter++; + in_path = t_strdup_printf("%s/%s.%s.%u.in", + dir, timestamp, my_pid, counter); + out_path = t_strdup_printf("%s/%s.%s.%u.out", + dir, timestamp, my_pid, counter); + + in_fd = open(in_path, O_CREAT | O_APPEND | O_WRONLY, 0600); + if (in_fd == -1) { + i_error("creat(%s) failed: %m", in_path); + return -1; + } + + out_fd = open(out_path, O_CREAT | O_APPEND | O_WRONLY, 0600); + if (out_fd == -1) { + i_error("creat(%s) failed: %m", out_path); + (void)close(in_fd); + (void)unlink(in_path); + return -1; + } + + old_input = *input; + old_output = *output; + *input = i_stream_create_rawlog(old_input, in_path, in_fd, TRUE); + *output = o_stream_create_rawlog(old_output, out_path, out_fd, TRUE); + i_stream_unref(&old_input); + o_stream_unref(&old_output); + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib/iostream-rawlog.h Wed Sep 21 15:57:57 2011 +0300 @@ -0,0 +1,7 @@ +#ifndef IOSTREAM_RAWLOG_H +#define IOSTREAM_RAWLOG_H + +int iostream_rawlog_create(const char *dir, struct istream **input, + struct ostream **output); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib/istream-rawlog.c Wed Sep 21 15:57:57 2011 +0300 @@ -0,0 +1,104 @@ +/* Copyright (c) 2011 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "iostream-rawlog-private.h" +#include "istream-private.h" +#include "istream-rawlog.h" + +struct rawlog_istream { + struct istream_private istream; + struct rawlog_iostream riostream; +}; + +static void i_stream_rawlog_close(struct iostream_private *stream) +{ + struct rawlog_istream *rstream = (struct rawlog_istream *)stream; + + iostream_rawlog_close(&rstream->riostream); +} + +static void i_stream_rawlog_destroy(struct iostream_private *stream) +{ + struct rawlog_istream *rstream = (struct rawlog_istream *)stream; + uoff_t v_offset; + + v_offset = rstream->istream.parent_start_offset + + rstream->istream.istream.v_offset; + if (rstream->istream.parent->seekable || + v_offset > rstream->istream.parent->v_offset) { + /* get to same position in parent stream */ + i_stream_seek(rstream->istream.parent, v_offset); + } + i_stream_unref(&rstream->istream.parent); +} + +static ssize_t i_stream_rawlog_read(struct istream_private *stream) +{ + struct rawlog_istream *rstream = (struct rawlog_istream *)stream; + ssize_t ret; + size_t pos; + + i_stream_seek(stream->parent, rstream->istream.parent_start_offset + + stream->istream.v_offset); + + stream->pos -= stream->skip; + stream->skip = 0; + + stream->buffer = i_stream_get_data(stream->parent, &pos); + if (pos > stream->pos) + ret = 0; + else do { + if ((ret = i_stream_read(stream->parent)) == -2) + return -2; + + stream->istream.stream_errno = stream->parent->stream_errno; + stream->istream.eof = stream->parent->eof; + stream->buffer = i_stream_get_data(stream->parent, &pos); + } while (pos <= stream->pos && ret > 0); + + if (pos <= stream->pos) + ret = ret == 0 ? 0 : -1; + else { + ret = (ssize_t)(pos - stream->pos); + iostream_rawlog_write(&rstream->riostream, + stream->buffer + stream->pos, ret); + } + stream->pos = pos; + i_assert(ret != -1 || stream->istream.eof || + stream->istream.stream_errno != 0); + return ret; +} + +static const struct stat * +i_stream_rawlog_stat(struct istream_private *stream, bool exact) +{ + return i_stream_stat(stream->parent, exact); +} + +struct istream * +i_stream_create_rawlog(struct istream *input, const char *rawlog_path, + int rawlog_fd, bool autoclose_fd) +{ + struct rawlog_istream *rstream; + + i_assert(rawlog_path != NULL); + i_assert(rawlog_fd != -1); + + rstream = i_new(struct rawlog_istream, 1); + rstream->istream.max_buffer_size = input->real_stream->max_buffer_size; + rstream->riostream.rawlog_path = i_strdup(rawlog_path); + rstream->riostream.rawlog_fd = rawlog_fd; + rstream->riostream.autoclose_fd = autoclose_fd; + rstream->riostream.write_timestamp = TRUE; + + rstream->istream.read = i_stream_rawlog_read; + rstream->istream.stat = i_stream_rawlog_stat; + rstream->istream.iostream.close = i_stream_rawlog_close; + rstream->istream.iostream.destroy = i_stream_rawlog_destroy; + + rstream->istream.istream.readable_fd = input->readable_fd; + rstream->istream.istream.blocking = input->blocking; + rstream->istream.istream.seekable = input->seekable; + return i_stream_create(&rstream->istream, input, + i_stream_get_fd(input)); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib/istream-rawlog.h Wed Sep 21 15:57:57 2011 +0300 @@ -0,0 +1,8 @@ +#ifndef ISTREAM_RAWLOG_H +#define ISTREAM_RAWLOG_H + +struct istream * +i_stream_create_rawlog(struct istream *input, const char *rawlog_path, + int rawlog_fd, bool autoclose_fd); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib/ostream-rawlog.c Wed Sep 21 15:57:57 2011 +0300 @@ -0,0 +1,62 @@ +/* Copyright (c) 2011 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "iostream-rawlog-private.h" +#include "ostream-private.h" +#include "ostream-rawlog.h" + +struct rawlog_ostream { + struct ostream_private ostream; + struct rawlog_iostream riostream; +}; + +static void o_stream_rawlog_close(struct iostream_private *stream) +{ + struct rawlog_ostream *rstream = (struct rawlog_ostream *)stream; + + o_stream_flush(rstream->ostream.parent); + iostream_rawlog_close(&rstream->riostream); +} + +static ssize_t +o_stream_rawlog_sendv(struct ostream_private *stream, + const struct const_iovec *iov, unsigned int iov_count) +{ + struct rawlog_ostream *rstream = (struct rawlog_ostream *)stream; + unsigned int i; + ssize_t ret; + + for (i = 0; i < iov_count; i++) { + iostream_rawlog_write(&rstream->riostream, + iov[i].iov_base, iov[i].iov_len); + } + + if ((ret = o_stream_sendv(stream->parent, iov, iov_count)) < 0) { + o_stream_copy_error_from_parent(stream); + return -1; + } + + stream->ostream.offset += ret; + return ret; +} + +struct ostream * +o_stream_create_rawlog(struct ostream *output, const char *rawlog_path, + int rawlog_fd, bool autoclose_fd) +{ + struct rawlog_ostream *rstream; + + i_assert(rawlog_path != NULL); + i_assert(rawlog_fd != -1); + + rstream = i_new(struct rawlog_ostream, 1); + rstream->ostream.sendv = o_stream_rawlog_sendv; + rstream->ostream.iostream.close = o_stream_rawlog_close; + + rstream->riostream.rawlog_path = i_strdup(rawlog_path); + rstream->riostream.rawlog_fd = rawlog_fd; + rstream->riostream.autoclose_fd = autoclose_fd; + rstream->riostream.write_timestamp = TRUE; + + return o_stream_create(&rstream->ostream, output); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib/ostream-rawlog.h Wed Sep 21 15:57:57 2011 +0300 @@ -0,0 +1,8 @@ +#ifndef OSTREAM_RAWLOG_H +#define OSTREAM_RAWLOG_H + +struct ostream * +o_stream_create_rawlog(struct ostream *output, const char *rawlog_path, + int rawlog_fd, bool autoclose_fd); + +#endif