annotate src/lib/istream-try.c @ 22664:fea53c2725c0

director: Fix director_max_parallel_moves/kicks type Should be uint, not time.
author Timo Sirainen <timo.sirainen@dovecot.fi>
date Thu, 09 Nov 2017 12:24:16 +0200
parents 708b4dda62dc
children cb108f786fb4
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
22607
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
1 /* Copyright (c) 2013-2017 Dovecot authors, see the included COPYING file */
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
2
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
3 #include "lib.h"
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
4 #include "istream-private.h"
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
5 #include "istream-try.h"
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
6
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
7 struct try_istream {
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
8 struct istream_private istream;
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
9
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
10 unsigned int try_input_count;
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
11 struct istream **try_input;
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
12 unsigned int try_idx;
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
13
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
14 struct istream *final_input;
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
15 };
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
16
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
17 static void i_stream_unref_try_inputs(struct try_istream *tstream)
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
18 {
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
19 for (unsigned int i = 0; i < tstream->try_input_count; i++) {
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
20 if (tstream->try_input[i] != NULL)
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
21 i_stream_unref(&tstream->try_input[i]);
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
22 }
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
23 tstream->try_input_count = 0;
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
24 i_free(tstream->try_input);
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
25 }
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
26
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
27 static void i_stream_try_close(struct iostream_private *stream,
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
28 bool close_parent)
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
29 {
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
30 struct try_istream *tstream = (struct try_istream *)stream;
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
31
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
32 if (close_parent) {
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
33 if (tstream->istream.parent != NULL)
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
34 i_stream_close(tstream->istream.parent);
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
35 for (unsigned int i = 0; i < tstream->try_input_count; i++) {
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
36 if (tstream->try_input[i] != NULL)
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
37 i_stream_close(tstream->try_input[i]);
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
38 }
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
39 }
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
40 i_stream_unref_try_inputs(tstream);
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
41 }
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
42
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
43 static bool i_stream_try_is_buffer_full(struct istream *try_input)
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
44 {
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
45 /* See if one of the parent istreams have their buffer full.
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
46 This is mainly intended to check with istream-tee whether its
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
47 parent is full. That means that the try_input has already seen
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
48 a full buffer of input, but it hasn't decided to return anything
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
49 yet. But it also hasn't failed, so we'll assume that the input is
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
50 correct for it and it simply needs a lot more input before it can
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
51 return anything (e.g. istream-bzlib). */
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
52 while (try_input->real_stream->parent != NULL) {
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
53 try_input = try_input->real_stream->parent;
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
54 if (try_input->real_stream->pos == try_input->real_stream->buffer_size &&
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
55 try_input->real_stream->buffer_size > 0)
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
56 return TRUE;
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
57 }
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
58 return FALSE;
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
59 }
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
60
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
61 static int i_stream_try_detect(struct try_istream *tstream)
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
62 {
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
63 int ret;
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
64
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
65 for (; tstream->try_idx < tstream->try_input_count; tstream->try_idx++) {
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
66 struct istream *try_input =
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
67 tstream->try_input[tstream->try_idx];
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
68
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
69 ret = i_stream_read(try_input);
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
70 if (ret == 0 && i_stream_try_is_buffer_full(try_input))
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
71 ret = 1;
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
72 if (ret > 0) {
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
73 i_stream_init_parent(&tstream->istream, try_input);
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
74 i_stream_unref_try_inputs(tstream);
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
75 return 1;
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
76 }
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
77 if (ret == 0)
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
78 return 0;
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
79 if (try_input->stream_errno != EINVAL) {
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
80 tstream->istream.istream.stream_errno =
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
81 try_input->stream_errno;
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
82 io_stream_set_error(&tstream->istream.iostream,
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
83 "Unexpected error while detecting stream format: %s",
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
84 i_stream_get_error(try_input));
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
85 return -1;
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
86 }
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
87 }
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
88
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
89 /* All streams failed with EINVAL. */
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
90 io_stream_set_error(&tstream->istream.iostream,
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
91 "Failed to detect stream format");
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
92 tstream->istream.istream.stream_errno = EINVAL;
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
93 return -1;
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
94 }
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
95
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
96 static ssize_t
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
97 i_stream_try_read(struct istream_private *stream)
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
98 {
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
99 struct try_istream *tstream = (struct try_istream *)stream;
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
100 int ret;
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
101
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
102 if (stream->parent == NULL) {
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
103 if ((ret = i_stream_try_detect(tstream)) <= 0)
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
104 return ret;
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
105 }
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
106
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
107 i_stream_seek(stream->parent, stream->parent_start_offset +
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
108 stream->istream.v_offset);
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
109 return i_stream_read_copy_from_parent(&stream->istream);
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
110 }
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
111
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
112 struct istream *istream_try_create(struct istream *const input[])
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
113 {
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
114 struct try_istream *tstream;
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
115 unsigned int count;
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
116 size_t max_buffer_size = I_STREAM_MIN_SIZE;
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
117 bool blocking = TRUE, seekable = TRUE;
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
118
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
119 for (count = 0; input[count] != NULL; count++) {
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
120 max_buffer_size = I_MAX(max_buffer_size,
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
121 i_stream_get_max_buffer_size(input[count]));
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
122 if (!input[count]->blocking)
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
123 blocking = FALSE;
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
124 if (!input[count]->seekable)
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
125 seekable = FALSE;
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
126 i_stream_ref(input[count]);
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
127 }
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
128 i_assert(count != 0);
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
129
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
130 tstream = i_new(struct try_istream, 1);
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
131 tstream->try_input_count = count;
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
132 tstream->try_input = p_memdup(default_pool, input,
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
133 sizeof(*input) * count);
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
134
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
135 tstream->istream.iostream.close = i_stream_try_close;
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
136
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
137 tstream->istream.max_buffer_size = max_buffer_size;
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
138 tstream->istream.read = i_stream_try_read;
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
139
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
140 tstream->istream.istream.readable_fd = FALSE;
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
141 tstream->istream.istream.blocking = blocking;
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
142 tstream->istream.istream.seekable = seekable;
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
143 return i_stream_create(&tstream->istream, NULL, -1);
708b4dda62dc lib: Add istream-try
Timo Sirainen <timo.sirainen@dovecot.fi>
parents:
diff changeset
144 }