dovecot-2.2: lib: Added o_stream_create_failure_at() to inject E...

dovecot at dovecot.org dovecot at dovecot.org
Tue Jun 16 13:43:20 UTC 2015


details:   http://hg.dovecot.org/dovecot-2.2/rev/1c7288c054b1
changeset: 18866:1c7288c054b1
user:      Timo Sirainen <tss at iki.fi>
date:      Tue Jun 16 16:22:18 2015 +0300
description:
lib: Added o_stream_create_failure_at() to inject EIO at given offset in ostream

diffstat:

 src/lib/Makefile.am               |    3 +
 src/lib/ostream-failure-at.c      |  108 ++++++++++++++++++++++++++++++++++++++
 src/lib/ostream-failure-at.h      |   10 +++
 src/lib/test-lib.c                |    1 +
 src/lib/test-lib.h                |    1 +
 src/lib/test-ostream-failure-at.c |   52 ++++++++++++++++++
 6 files changed, 175 insertions(+), 0 deletions(-)

diffs (231 lines):

diff -r 99827acc1888 -r 1c7288c054b1 src/lib/Makefile.am
--- a/src/lib/Makefile.am	Tue Jun 16 16:21:56 2015 +0300
+++ b/src/lib/Makefile.am	Tue Jun 16 16:22:18 2015 +0300
@@ -109,6 +109,7 @@
 	numpack.c \
 	ostream.c \
 	ostream-buffer.c \
+	ostream-failure-at.c \
 	ostream-file.c \
 	ostream-hash.c \
 	ostream-rawlog.c \
@@ -237,6 +238,7 @@
 	nfs-workarounds.h \
 	numpack.h \
 	ostream.h \
+	ostream-failure-at.h \
 	ostream-hash.h \
 	ostream-private.h \
 	ostream-rawlog.h \
@@ -318,6 +320,7 @@
 	test-mempool-alloconly.c \
 	test-net.c \
 	test-numpack.c \
+	test-ostream-failure-at.c \
 	test-ostream-file.c \
 	test-primes.c \
 	test-printf-format-fix.c \
diff -r 99827acc1888 -r 1c7288c054b1 src/lib/ostream-failure-at.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/ostream-failure-at.c	Tue Jun 16 16:22:18 2015 +0300
@@ -0,0 +1,108 @@
+/* Copyright (c) 2015 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "buffer.h"
+#include "ostream-private.h"
+#include "ostream-failure-at.h"
+
+struct failure_at_ostream {
+	struct ostream_private ostream;
+	char *error_string;
+	uoff_t failure_offset;
+	bool failed;
+};
+
+static void o_stream_failure_at_destroy(struct iostream_private *stream)
+{
+	struct failure_at_ostream *fstream =
+		(struct failure_at_ostream *)stream;
+
+	i_free(fstream->error_string);
+}
+
+static ssize_t
+o_stream_failure_at_sendv(struct ostream_private *stream,
+			  const struct const_iovec *iov, unsigned int iov_count)
+{
+	struct failure_at_ostream *fstream =
+		(struct failure_at_ostream *)stream;
+	unsigned int i;
+	struct const_iovec *iov_dup;
+	unsigned int iov_dup_count;
+	uoff_t bytes_until_failure;
+	ssize_t ret;
+
+	if (fstream->failure_offset <= stream->ostream.offset) {
+		io_stream_set_error(&stream->iostream, "%s",
+				    fstream->error_string);
+		stream->ostream.stream_errno = errno = EIO;
+		fstream->failed = TRUE;
+		return -1;
+	}
+	bytes_until_failure = fstream->failure_offset - stream->ostream.offset;
+
+	iov_dup = i_new(struct const_iovec, iov_count);
+	iov_dup_count = iov_count;
+	for (i = 0; i < iov_count; i++) {
+		iov_dup[i] = iov[i];
+		if (iov_dup[i].iov_len >= bytes_until_failure) {
+			iov_dup[i].iov_len = bytes_until_failure;
+			iov_dup_count = i+1;
+			break;
+		}
+	}
+	ret = o_stream_sendv(stream->parent, iov_dup, iov_dup_count);
+	i_free(iov_dup);
+
+	if (ret < 0) {
+		o_stream_copy_error_from_parent(stream);
+		return -1;
+	}
+	stream->ostream.offset += ret;
+	return ret;
+}
+
+static int
+o_stream_failure_at_flush(struct ostream_private *stream)
+{
+	struct failure_at_ostream *fstream =
+		(struct failure_at_ostream *)stream;
+
+	if (fstream->failed) {
+		io_stream_set_error(&stream->iostream, "%s",
+				    fstream->error_string);
+		stream->ostream.stream_errno = errno = EIO;
+		return -1;
+	}
+	return o_stream_flush(stream->parent);
+}
+
+struct ostream *
+o_stream_create_failure_at(struct ostream *output, uoff_t failure_offset,
+			   const char *error_string)
+{
+	struct failure_at_ostream *fstream;
+
+	fstream = i_new(struct failure_at_ostream, 1);
+	fstream->ostream.sendv = o_stream_failure_at_sendv;
+	fstream->ostream.flush = o_stream_failure_at_flush;
+	fstream->ostream.iostream.destroy = o_stream_failure_at_destroy;
+	fstream->failure_offset = failure_offset;
+	fstream->error_string = i_strdup(error_string);
+	return o_stream_create(&fstream->ostream, output,
+			       o_stream_get_fd(output));
+}
+
+struct ostream *
+o_stream_create_failure_at_flush(struct ostream *output, const char *error_string)
+{
+	struct failure_at_ostream *fstream;
+
+	fstream = i_new(struct failure_at_ostream, 1);
+	fstream->ostream.flush = o_stream_failure_at_flush;
+	fstream->ostream.iostream.destroy = o_stream_failure_at_destroy;
+	fstream->error_string = i_strdup(error_string);
+	fstream->failed = TRUE;
+	return o_stream_create(&fstream->ostream, output,
+			       o_stream_get_fd(output));
+}
diff -r 99827acc1888 -r 1c7288c054b1 src/lib/ostream-failure-at.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/ostream-failure-at.h	Tue Jun 16 16:22:18 2015 +0300
@@ -0,0 +1,10 @@
+#ifndef OSTREAM_FAILURE_AT_H
+#define OSTREAM_FAILURE_AT_H
+
+struct ostream *
+o_stream_create_failure_at(struct ostream *output, uoff_t failure_offset,
+			   const char *error_string);
+struct ostream *
+o_stream_create_failure_at_flush(struct ostream *output, const char *error_string);
+
+#endif
diff -r 99827acc1888 -r 1c7288c054b1 src/lib/test-lib.c
--- a/src/lib/test-lib.c	Tue Jun 16 16:21:56 2015 +0300
+++ b/src/lib/test-lib.c	Tue Jun 16 16:22:18 2015 +0300
@@ -36,6 +36,7 @@
 		test_mempool_alloconly,
 		test_net,
 		test_numpack,
+		test_ostream_failure_at,
 		test_ostream_file,
 		test_primes,
 		test_printf_format_fix,
diff -r 99827acc1888 -r 1c7288c054b1 src/lib/test-lib.h
--- a/src/lib/test-lib.h	Tue Jun 16 16:21:56 2015 +0300
+++ b/src/lib/test-lib.h	Tue Jun 16 16:22:18 2015 +0300
@@ -38,6 +38,7 @@
 enum fatal_test_state fatal_mempool(int);
 void test_net(void);
 void test_numpack(void);
+void test_ostream_failure_at(void);
 void test_ostream_file(void);
 void test_primes(void);
 void test_printf_format_fix(void);
diff -r 99827acc1888 -r 1c7288c054b1 src/lib/test-ostream-failure-at.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/test-ostream-failure-at.c	Tue Jun 16 16:22:18 2015 +0300
@@ -0,0 +1,52 @@
+/* Copyright (c) 2015 Dovecot authors, see the included COPYING file */
+
+#include "test-lib.h"
+#include "buffer.h"
+#include "ostream.h"
+#include "ostream-failure-at.h"
+
+#define TEST_DATA_LENGTH 128
+#define TEST_ERRMSG "test-ostream-failure-at error triggered"
+
+void test_ostream_failure_at(void)
+{
+	unsigned char test_data[TEST_DATA_LENGTH];
+	struct ostream *output, *buf_output;
+	buffer_t *buf = buffer_create_dynamic(pool_datastack_create(), 256);
+	unsigned int i;
+
+	test_begin("ostream failure at");
+	for (i = 0; i < sizeof(test_data); i++)
+		test_data[i] = i;
+	for (i = 0; i < TEST_DATA_LENGTH; i++) {
+		buf_output = o_stream_create_buffer(buf);
+		output = o_stream_create_failure_at(buf_output, i, TEST_ERRMSG);
+		if (i > 0)
+			test_assert(o_stream_send(output, test_data, sizeof(test_data)) == i);
+		test_assert_idx(o_stream_send(output, test_data, sizeof(test_data)) == -1 &&
+				output->offset == i &&
+				output->stream_errno == EIO &&
+				strcmp(o_stream_get_error(output), TEST_ERRMSG) == 0, i);
+		o_stream_destroy(&output);
+		o_stream_destroy(&buf_output);
+	}
+	/* shouldn't fail */
+	buf_output = o_stream_create_buffer(buf);
+	output = o_stream_create_failure_at(buf_output, TEST_DATA_LENGTH, TEST_ERRMSG);
+	test_assert(o_stream_send(output, test_data, sizeof(test_data)) == TEST_DATA_LENGTH);
+	test_assert(o_stream_flush(output) > 0 &&
+		    output->offset == TEST_DATA_LENGTH &&
+		    output->stream_errno == 0);
+	o_stream_destroy(&output);
+	o_stream_destroy(&buf_output);
+
+	/* fail at flush */
+	buf_output = o_stream_create_buffer(buf);
+	output = o_stream_create_failure_at_flush(buf_output, TEST_ERRMSG);
+	test_assert(o_stream_send(output, test_data, sizeof(test_data)) == TEST_DATA_LENGTH);
+	test_assert(o_stream_flush(output) < 0 && output->stream_errno == EIO &&
+		    strcmp(o_stream_get_error(output), TEST_ERRMSG) == 0);
+	o_stream_destroy(&output);
+	o_stream_destroy(&buf_output);
+	test_end();
+}


More information about the dovecot-cvs mailing list