dovecot-2.2: iostream-rawlog: Added possibility to save input/ou...

dovecot at dovecot.org dovecot at dovecot.org
Wed Aug 29 16:19:12 EEST 2012


details:   http://hg.dovecot.org/dovecot-2.2/rev/8ce6d41d2d41
changeset: 14967:8ce6d41d2d41
user:      Timo Sirainen <tss at iki.fi>
date:      Wed Aug 29 16:18:56 2012 +0300
description:
iostream-rawlog: Added possibility to save input/output to the same file.

diffstat:

 src/lib/iostream-rawlog-private.h |   15 +++-
 src/lib/iostream-rawlog.c         |  161 ++++++++++++++++++++++++++++++-------
 src/lib/iostream-rawlog.h         |    9 ++
 src/lib/istream-rawlog.c          |    5 +-
 src/lib/istream-rawlog.h          |    2 +-
 src/lib/ostream-rawlog.c          |    5 +-
 src/lib/ostream-rawlog.h          |    2 +-
 7 files changed, 156 insertions(+), 43 deletions(-)

diffs (truncated from 357 to 300 lines):

diff -r fff00bb85ae4 -r 8ce6d41d2d41 src/lib/iostream-rawlog-private.h
--- a/src/lib/iostream-rawlog-private.h	Wed Aug 29 16:12:08 2012 +0300
+++ b/src/lib/iostream-rawlog-private.h	Wed Aug 29 16:18:56 2012 +0300
@@ -1,16 +1,27 @@
 #ifndef IOSTREAM_RAWLOG_PRIVATE_H
 #define IOSTREAM_RAWLOG_PRIVATE_H
 
+#define IOSTREAM_RAWLOG_MAX_PREFIX_LEN 3
+
+enum iostream_rawlog_flags {
+	IOSTREAM_RAWLOG_FLAG_AUTOCLOSE	= 0x01,
+	IOSTREAM_RAWLOG_FLAG_BUFFERED	= 0x02
+};
+
 struct rawlog_iostream {
 	struct iostream_private *iostream;
+	enum iostream_rawlog_flags flags;
 
 	char *rawlog_path;
 	int rawlog_fd;
+	buffer_t *buffer;
 
-	bool autoclose_fd;
-	bool write_timestamp;
+	bool input;
+	bool line_continued;
 };
 
+void iostream_rawlog_init(struct rawlog_iostream *rstream,
+			  enum iostream_rawlog_flags flags, bool input);
 void iostream_rawlog_write(struct rawlog_iostream *rstream,
 			   const unsigned char *data, size_t size);
 void iostream_rawlog_close(struct rawlog_iostream *rstream);
diff -r fff00bb85ae4 -r 8ce6d41d2d41 src/lib/iostream-rawlog.c
--- a/src/lib/iostream-rawlog.c	Wed Aug 29 16:12:08 2012 +0300
+++ b/src/lib/iostream-rawlog.c	Wed Aug 29 16:18:56 2012 +0300
@@ -3,19 +3,23 @@
 #include "lib.h"
 #include "hostpid.h"
 #include "ioloop.h"
+#include "buffer.h"
+#include "str.h"
 #include "write-full.h"
 #include "time-util.h"
 #include "istream.h"
 #include "ostream.h"
+#include "iostream-private.h"
+#include "iostream-rawlog-private.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>
 
+#define RAWLOG_MAX_LINE_LEN 8192
+
 static void
 rawlog_write(struct rawlog_iostream *rstream, const void *data, size_t size)
 {
@@ -29,43 +33,98 @@
 	}
 }
 
-static void rawlog_write_timestamp(struct rawlog_iostream *rstream)
+static void
+rawlog_write_timestamp(struct rawlog_iostream *rstream, bool line_ends)
 {
-	char buf[MAX_INT_STRLEN + 6 + 2];
+	unsigned char data[MAX_INT_STRLEN + 6 + 1 + 3];
+	buffer_t buf;
 
-	if (i_snprintf(buf, sizeof(buf), "%lu.%06u ",
-		       (unsigned long)ioloop_timeval.tv_sec,
-		       (unsigned int)ioloop_timeval.tv_usec) < 0)
-		i_unreached();
-	rawlog_write(rstream, buf, strlen(buf));
+	buffer_create_data(&buf, data, sizeof(data));
+	str_printfa(&buf, "%lu.%06u ",
+		    (unsigned long)ioloop_timeval.tv_sec,
+		    (unsigned int)ioloop_timeval.tv_usec);
+	if ((rstream->flags & IOSTREAM_RAWLOG_FLAG_BUFFERED) != 0) {
+		str_append_c(&buf, rstream->input ? 'I' : 'O');
+		str_append_c(&buf, line_ends ? ':' : '>');
+		str_append_c(&buf, ' ');
+	}
+	rawlog_write(rstream, buf.data, buf.used);
+}
+
+void iostream_rawlog_init(struct rawlog_iostream *rstream,
+			  enum iostream_rawlog_flags flags, bool input)
+{
+	rstream->flags = flags;
+	rstream->input = input;
+	if ((rstream->flags & IOSTREAM_RAWLOG_FLAG_BUFFERED) != 0)
+		rstream->buffer = buffer_create_dynamic(default_pool, 1024);
+}
+
+static void
+iostream_rawlog_write_unbuffered(struct rawlog_iostream *rstream,
+				 const unsigned char *data, size_t size)
+{
+	size_t i, start;
+
+	if (!rstream->line_continued)
+		rawlog_write_timestamp(rstream, TRUE);
+
+	for (start = 0, i = 1; i < size; i++) {
+		if (data[i-1] == '\n') {
+			rawlog_write(rstream, data + start, i - start);
+			rawlog_write_timestamp(rstream, TRUE);
+			start = i;
+		}
+	}
+	if (start != size)
+		rawlog_write(rstream, data + start, size - start);
+	rstream->line_continued = data[size-1] != '\n';
 }
 
 void iostream_rawlog_write(struct rawlog_iostream *rstream,
 			   const unsigned char *data, size_t size)
 {
-	size_t i, start;
+	const unsigned char *p;
+	size_t pos;
+	bool line_ends;
 
 	i_assert(size > 0);
 
 	io_loop_time_refresh();
-	if (rstream->write_timestamp)
-		rawlog_write_timestamp(rstream);
+	if ((rstream->flags & IOSTREAM_RAWLOG_FLAG_BUFFERED) == 0) {
+		iostream_rawlog_write_unbuffered(rstream, data, size);
+		return;
+	}
 
-	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;
+	do {
+		p = memchr(data, '\n', size);
+		if (p != NULL) {
+			line_ends = TRUE;
+			pos = p-data + 1;
+		} else if (rstream->buffer->used + size < RAWLOG_MAX_LINE_LEN) {
+			buffer_append(rstream->buffer, data, size);
+			return;
+		} else {
+			line_ends = FALSE;
+			pos = size;
 		}
-	}
-	if (start != size)
-		rawlog_write(rstream, data + start, size - start);
-	rstream->write_timestamp = data[size-1] == '\n';
+
+		rawlog_write_timestamp(rstream, line_ends);
+		if (rstream->buffer->used > 0) {
+			rawlog_write(rstream, rstream->buffer->data,
+				     rstream->buffer->used);
+		}
+		rawlog_write(rstream, data, pos);
+
+		data += pos;
+		size -= pos;
+	} while (size > 0);
 }
 
 void iostream_rawlog_close(struct rawlog_iostream *rstream)
 {
-	if (rstream->autoclose_fd && rstream->rawlog_fd != -1) {
+	if ((rstream->flags & IOSTREAM_RAWLOG_FLAG_AUTOCLOSE) != 0 &&
+	    rstream->rawlog_fd != -1) {
 		if (close(rstream->rawlog_fd) < 0) {
 			i_error("rawlog_istream.close(%s) failed: %m",
 				rstream->rawlog_path);
@@ -73,31 +132,39 @@
 	}
 	rstream->rawlog_fd = -1;
 	i_free_and_null(rstream->rawlog_path);
+	if (rstream->buffer != NULL)
+		buffer_free(&rstream->buffer);
 }
 
 int iostream_rawlog_create(const char *dir, struct istream **input,
 			   struct ostream **output)
 {
 	static unsigned int counter = 0;
-	const char *timestamp, *in_path, *out_path;
+	const char *timestamp, *prefix;
+
+	timestamp = t_strflocaltime("%Y%m%d-%H%M%S", ioloop_time);
+
+	counter++;
+	prefix = t_strdup_printf("%s/%s.%s.%u", dir, timestamp, my_pid, counter);
+	return iostream_rawlog_create_prefix(prefix, input, output);
+}
+
+int iostream_rawlog_create_prefix(const char *prefix, struct istream **input,
+				  struct ostream **output)
+{
+	const char *in_path, *out_path;
 	struct istream *old_input;
 	struct ostream *old_output;
 	int in_fd, out_fd;
 
-	timestamp = t_strflocaltime("%Y%m%d-%H%M%S", ioloop_time);
-
-	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_path = t_strdup_printf("%s.in", prefix);
 	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_path = t_strdup_printf("%s.out", prefix);
 	out_fd = open(out_path, O_CREAT | O_APPEND | O_WRONLY, 0600);
 	if (out_fd == -1) {
 		i_error("creat(%s) failed: %m", out_path);
@@ -108,9 +175,37 @@
 
 	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);
+	*input = i_stream_create_rawlog(old_input, in_path, in_fd,
+					IOSTREAM_RAWLOG_FLAG_AUTOCLOSE);
+	*output = o_stream_create_rawlog(old_output, out_path, out_fd,
+					 IOSTREAM_RAWLOG_FLAG_AUTOCLOSE);
 	i_stream_unref(&old_input);
 	o_stream_unref(&old_output);
 	return 0;
 }
+
+int iostream_rawlog_create_path(const char *path, struct istream **input,
+				struct ostream **output)
+{
+	struct istream *old_input;
+	struct ostream *old_output;
+	int fd;
+
+	fd = open(path, O_CREAT | O_APPEND | O_WRONLY, 0600);
+	if (fd == -1) {
+		i_error("creat(%s) failed: %m", path);
+		return -1;
+	}
+
+	old_input = *input;
+	old_output = *output;
+	*input = i_stream_create_rawlog(old_input, path, fd,
+					IOSTREAM_RAWLOG_FLAG_AUTOCLOSE |
+					IOSTREAM_RAWLOG_FLAG_BUFFERED);
+	*output = o_stream_create_rawlog(old_output, path, fd,
+					 IOSTREAM_RAWLOG_FLAG_AUTOCLOSE |
+					 IOSTREAM_RAWLOG_FLAG_BUFFERED);
+	i_stream_unref(&old_input);
+	o_stream_unref(&old_output);
+	return 0;
+}
diff -r fff00bb85ae4 -r 8ce6d41d2d41 src/lib/iostream-rawlog.h
--- a/src/lib/iostream-rawlog.h	Wed Aug 29 16:12:08 2012 +0300
+++ b/src/lib/iostream-rawlog.h	Wed Aug 29 16:18:56 2012 +0300
@@ -1,8 +1,17 @@
 #ifndef IOSTREAM_RAWLOG_H
 #define IOSTREAM_RAWLOG_H
 
+/* Create rawlog *.in and *.out files to the given directory. */
 int ATTR_NOWARN_UNUSED_RESULT
 iostream_rawlog_create(const char *dir, struct istream **input,
 		       struct ostream **output);
+/* Create rawlog prefix.in and prefix.out files. */
+int ATTR_NOWARN_UNUSED_RESULT
+iostream_rawlog_create_prefix(const char *prefix, struct istream **input,
+			      struct ostream **output);
+/* Create rawlog path, writing both input and output to the same file. */
+int ATTR_NOWARN_UNUSED_RESULT
+iostream_rawlog_create_path(const char *path, struct istream **input,
+			    struct ostream **output);
 
 #endif
diff -r fff00bb85ae4 -r 8ce6d41d2d41 src/lib/istream-rawlog.c
--- a/src/lib/istream-rawlog.c	Wed Aug 29 16:12:08 2012 +0300
+++ b/src/lib/istream-rawlog.c	Wed Aug 29 16:18:56 2012 +0300
@@ -71,7 +71,7 @@
 
 struct istream *
 i_stream_create_rawlog(struct istream *input, const char *rawlog_path,
-		       int rawlog_fd, bool autoclose_fd)
+		       int rawlog_fd, enum iostream_rawlog_flags flags)


More information about the dovecot-cvs mailing list