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